List of usage examples for java.util LinkedList addFirst
public void addFirst(E e)
From source file:org.nuxeo.ecm.core.storage.sql.NXQLQueryMaker.java
public Query buildQuery(SQLInfo sqlInfo, Model model, Session session, String query, QueryFilter queryFilter, Object... params) throws StorageException { this.sqlInfo = sqlInfo; database = sqlInfo.database;/*w w w . j a va 2 s . c o m*/ dialect = sqlInfo.dialect; this.model = model; this.session = session; // transform the query according to the transformers defined by the // security policies SQLQuery sqlQuery = SQLQueryParser.parse(query); for (SQLQuery.Transformer transformer : queryFilter.getQueryTransformers()) { sqlQuery = transformer.transform(queryFilter.getPrincipal(), sqlQuery); } /* * Find all relevant types and keys for the criteria. */ QueryAnalyzer info = new QueryAnalyzer(); try { info.visitQuery(sqlQuery); } catch (QueryCannotMatchException e) { // query cannot match return null; } catch (QueryMakerException e) { throw new StorageException(e.getMessage(), e); } /* * Find all the types to take into account (all concrete types being a * subtype of the passed types) based on the FROM list. */ Set<String> types = new HashSet<String>(); for (String typeName : info.fromTypes) { if ("document".equals(typeName)) { typeName = "Document"; } Set<String> subTypes = model.getDocumentSubTypes(typeName); if (subTypes == null) { throw new StorageException("Unknown type: " + typeName); } types.addAll(subTypes); } types.remove(model.ROOT_TYPE); /* * Restrict types based on toplevel ecm:primaryType and ecm:mixinType * predicates. */ types.removeAll(info.typesExcluded); if (!info.typesAnyRequired.isEmpty()) { types.retainAll(info.typesAnyRequired); } if (types.isEmpty()) { // conflicting types requirement, query cannot match return null; } /* * Merge facet filter into mixin clauses and immutable flag. */ FacetFilter facetFilter = queryFilter.getFacetFilter(); if (facetFilter == null) { facetFilter = FacetFilter.ALLOW; } info.mixinsExcluded.addAll(facetFilter.excluded); if (info.mixinsExcluded.remove(FacetNames.IMMUTABLE)) { if (info.immutableClause == Boolean.TRUE) { // conflict on immutable condition, query cannot match return null; } info.immutableClause = Boolean.FALSE; } info.mixinsAllRequired.addAll(facetFilter.required); if (info.mixinsAllRequired.remove(FacetNames.IMMUTABLE)) { if (info.immutableClause == Boolean.FALSE) { // conflict on immutable condition, query cannot match return null; } info.immutableClause = Boolean.TRUE; } /* * Find the relevant tables to join with. */ Set<String> fragmentNames = new HashSet<String>(); for (String prop : info.props) { PropertyInfo propertyInfo = model.getPropertyInfo(prop); if (propertyInfo == null) { throw new StorageException("Unknown field: " + prop); } fragmentNames.add(propertyInfo.fragmentName); } fragmentNames.remove(model.hierTableName); // Do we need to add the versions table too? if (info.needsVersionsTable || info.immutableClause != null) { fragmentNames.add(model.VERSION_TABLE_NAME); } /* * Build the FROM / JOIN criteria for each select. */ DocKind[] docKinds; if (info.proxyClause == Boolean.TRUE) { if (info.immutableClause == Boolean.FALSE) { // proxy but not immutable: query cannot match return null; } docKinds = new DocKind[] { DocKind.PROXY }; } else if (info.proxyClause == Boolean.FALSE || info.immutableClause == Boolean.FALSE) { docKinds = new DocKind[] { DocKind.DIRECT }; } else { docKinds = new DocKind[] { DocKind.DIRECT, DocKind.PROXY }; } Table hier = database.getTable(model.hierTableName); boolean aliasColumns = docKinds.length > 1; Select select = null; String orderBy = null; List<String> statements = new ArrayList<String>(2); List<Serializable> selectParams = new LinkedList<Serializable>(); for (DocKind docKind : docKinds) { // The hierarchy table, which may be an alias table. Table hierTable; // Quoted id in the hierarchy. This is the id returned by the query. String hierId; // Quoted name in the hierarchy. This is the id returned by the query. String hierName; // The hierarchy table of the data. Table dataHierTable; // Quoted id attached to the data that matches. String dataHierId; List<String> joins = new LinkedList<String>(); LinkedList<String> leftJoins = new LinkedList<String>(); List<Serializable> leftJoinsParams = new LinkedList<Serializable>(); LinkedList<String> implicitJoins = new LinkedList<String>(); List<Serializable> implicitJoinsParams = new LinkedList<Serializable>(); List<String> whereClauses = new LinkedList<String>(); List<Serializable> whereParams = new LinkedList<Serializable>(); switch (docKind) { case DIRECT: hierTable = hier; hierId = hierTable.getColumn(model.MAIN_KEY).getFullQuotedName(); hierName = hierTable.getColumn(model.HIER_CHILD_NAME_KEY).getFullQuotedName(); dataHierTable = hierTable; dataHierId = hierId; joins.add(hierTable.getQuotedName()); break; case PROXY: hierTable = new TableAlias(hier, TABLE_HIER_ALIAS); String hierFrom = hier.getQuotedName() + " " + hierTable.getQuotedName(); // TODO use dialect hierId = hierTable.getColumn(model.MAIN_KEY).getFullQuotedName(); hierName = hierTable.getColumn(model.HIER_CHILD_NAME_KEY).getFullQuotedName(); // joined (data) dataHierTable = hier; dataHierId = hier.getColumn(model.MAIN_KEY).getFullQuotedName(); // proxies Table proxies = database.getTable(model.PROXY_TABLE_NAME); String proxiesid = proxies.getColumn(model.MAIN_KEY).getFullQuotedName(); String proxiestargetid = proxies.getColumn(model.PROXY_TARGET_KEY).getFullQuotedName(); // join all that joins.add(hierFrom); joins.add(String.format(JOIN_ON, proxies.getQuotedName(), hierId, proxiesid)); joins.add(String.format(JOIN_ON, dataHierTable.getQuotedName(), dataHierId, proxiestargetid)); break; default: throw new AssertionError(docKind); } // main data joins for (String fragmentName : fragmentNames) { Table table = database.getTable(fragmentName); // the versions table joins on the real hier table boolean useHier = model.VERSION_TABLE_NAME.equals(fragmentName); leftJoins.add(String.format(JOIN_ON, table.getQuotedName(), useHier ? hierId : dataHierId, table.getColumn(model.MAIN_KEY).getFullQuotedName())); } /* * Filter on facets and mixin types, and create the structural WHERE * clauses for the type. */ List<String> typeStrings = new ArrayList<String>(types.size()); NEXT_TYPE: for (String type : types) { Set<String> facets = model.getDocumentTypeFacets(type); for (String facet : info.mixinsExcluded) { if (facets.contains(facet)) { continue NEXT_TYPE; } } for (String facet : info.mixinsAllRequired) { if (!facets.contains(facet)) { continue NEXT_TYPE; } } if (!info.mixinsAnyRequired.isEmpty()) { Set<String> intersection = new HashSet<String>(info.mixinsAnyRequired); intersection.retainAll(facets); if (intersection.isEmpty()) { continue NEXT_TYPE; } } // this type is good typeStrings.add("?"); whereParams.add(type); } if (typeStrings.isEmpty()) { return null; // mixins excluded all types, no match possible } whereClauses.add(String.format("%s IN (%s)", dataHierTable.getColumn(model.MAIN_PRIMARY_TYPE_KEY).getFullQuotedName(), StringUtils.join(typeStrings, ", "))); /* * Add clause for immutable match. */ if (docKind == DocKind.DIRECT && info.immutableClause != null) { String where = String.format("%s IS %s", database.getTable(model.VERSION_TABLE_NAME).getColumn(model.MAIN_KEY).getFullQuotedName(), info.immutableClause.booleanValue() ? "NOT NULL" : "NULL"); whereClauses.add(where); } /* * Parse the WHERE clause from the original query, and deduce from * it actual WHERE clauses and potential JOINs. */ WhereBuilder whereBuilder; try { whereBuilder = new WhereBuilder(database, session, hierTable, hierId, dataHierTable, dataHierId, docKind == DocKind.PROXY, aliasColumns); } catch (QueryMakerException e) { throw new StorageException(e.getMessage(), e); } if (info.wherePredicate != null) { info.wherePredicate.accept(whereBuilder); // JOINs added by fulltext queries leftJoins.addAll(whereBuilder.leftJoins); leftJoinsParams.addAll(whereBuilder.leftJoinsParams); implicitJoins.addAll(whereBuilder.implicitJoins); implicitJoinsParams.addAll(whereBuilder.implicitJoinsParams); // WHERE clause String where = whereBuilder.buf.toString(); if (where.length() != 0) { whereClauses.add(where); whereParams.addAll(whereBuilder.whereParams); } } /* * Security check. */ if (queryFilter.getPrincipals() != null) { Serializable principals = queryFilter.getPrincipals(); Serializable permissions = queryFilter.getPermissions(); if (!dialect.supportsArrays()) { principals = StringUtils.join((String[]) principals, '|'); permissions = StringUtils.join((String[]) permissions, '|'); } if (dialect.supportsReadAcl()) { /* optimized read acl */ whereClauses.add(dialect.getReadAclsCheckSql("r.acl_id")); whereParams.add(principals); joins.add(String.format("%s AS r ON %s = r.id", model.HIER_READ_ACL_TABLE_NAME, hierId)); } else { whereClauses.add(dialect.getSecurityCheckSql(hierId)); whereParams.add(principals); whereParams.add(permissions); } } /* * Columns on which to do ordering. */ String selectWhat = hierId; // always add the name, it will be used for intalio crm selectWhat += ", " + hierName; if (aliasColumns) { // UNION, so we need all orderable columns, aliased int n = 0; for (String key : info.orderKeys) { Column column = whereBuilder.findColumn(key, false, true); String qname = column.getFullQuotedName(); selectWhat += ", " + qname + " AS " + dialect.openQuote() + COL_ORDER_ALIAS_PREFIX + ++n + dialect.closeQuote(); } } /* * Order by. Compute it just once. May use just aliases. */ if (orderBy == null && sqlQuery.orderBy != null) { whereBuilder.buf.setLength(0); sqlQuery.orderBy.accept(whereBuilder); orderBy = whereBuilder.buf.toString(); } /* * Resulting select. */ select = new Select(null); select.setWhat(selectWhat); leftJoins.addFirst(StringUtils.join(joins, " JOIN ")); String from = StringUtils.join(leftJoins, " LEFT JOIN "); if (!implicitJoins.isEmpty()) { implicitJoins.addFirst(from); from = StringUtils.join(implicitJoins, ", "); } select.setFrom(from); select.setWhere(StringUtils.join(whereClauses, " AND ")); selectParams.addAll(leftJoinsParams); selectParams.addAll(implicitJoinsParams); selectParams.addAll(whereParams); statements.add(select.getStatement()); } /* * Create the whole select. */ if (statements.size() > 1) { select = new Select(null); String selectWhat = hier.getColumn(model.MAIN_KEY).getQuotedName(); selectWhat = selectWhat + ", " + hier.getColumn(model.HIER_CHILD_NAME_KEY).getQuotedName(); select.setWhat(selectWhat); // note that Derby has bizarre restrictions on parentheses placement // around UNION, see http://issues.apache.org/jira/browse/DERBY-2374 String from = '(' + StringUtils.join(statements, " UNION ALL ") + ')'; if (dialect.needsAliasForDerivedTable()) { from += " AS " + dialect.openQuote() + UNION_ALIAS + dialect.closeQuote(); } select.setFrom(from); } select.setOrderBy(orderBy); List<Column> whatColumns = Collections.singletonList(hier.getColumn(model.MAIN_KEY)); Query q = new Query(); q.selectInfo = new SQLInfoSelect(select.getStatement(), whatColumns, null, null); q.selectParams = selectParams; return q; }
From source file:com.funambol.foundation.items.dao.PIMCalendarDAO.java
/** * Retrieves the UID list of the calendars considered to be "twins" of a * given calendar./* ww w. ja v a 2 s. c o m*/ * * @param c the Calendar object representing the calendar whose twins * need be found. In the present implementation, only the following * data matter: * <BR>for events <UL><LI>date start<LI>date end<LI>subject</UL> * for tasks <UL><LI>date end<LI>subject</UL> * @throws DAOException * @return a List of UIDs (as String objects) that may be empty but not null */ public List getTwinItems(Calendar c) throws DAOException { if (log.isTraceEnabled()) { log.trace("PIMCalendarDAO getTwinItems begin"); } LinkedList<String> twins = new LinkedList<String>(); Connection con = null; PreparedStatement ps = null; ResultSet rs = null; if (!isTwinSearchAppliableOn(c)) { if (log.isTraceEnabled()) { log.trace("Item with no dtStart, dtEnd, summary: twin search skipped."); } return twins; } try { // Looks up the data source when the first connection is created con = getUserDataSource().getRoutedConnection(userId); con.setReadOnly(true); Date dtStart; Date dtEnd; Date dueTomorrowNoon = null; Date dueYesterdayNoon = null; dtStart = getDateFromString(c.getCalendarContent().isAllDay(), Property.stringFrom(c.getCalendarContent().getDtStart()), "000000"); dtEnd = getDateFromString(c.getCalendarContent().isAllDay(), Property.stringFrom(c.getCalendarContent().getDtEnd()), "235900"); if ((dtEnd != null) && (c.getCalendarContent() instanceof Task)) { java.util.Calendar noon = new GregorianCalendar(TimeZone.getTimeZone("UTC")); noon.setTime(dtEnd); noon.set(java.util.Calendar.HOUR_OF_DAY, 12); noon.set(java.util.Calendar.MINUTE, 0); noon.set(java.util.Calendar.MILLISECOND, 0); noon.add(java.util.Calendar.DATE, +1); dueTomorrowNoon = noon.getTime(); noon.add(java.util.Calendar.DATE, -2); // go back and another -1 dueYesterdayNoon = noon.getTime(); } StringBuffer sqlGetCalendarTwinList = new StringBuffer(SQL_GET_FNBL_PIM_CALENDAR_ID_LIST_BY_USER); String subject = Property.stringFrom(c.getCalendarContent().getSummary(), true); // Empty implies null; if ("null".equals(subject)) { subject = null; } if (subject == null) { sqlGetCalendarTwinList.append(SQL_AND_NO_SUBJECT_IS_SET); } else { sqlGetCalendarTwinList.append(SQL_AND_SUBJECT_EQUALS_QUESTIONMARK); } if (c.getCalendarContent() instanceof Event) { if (dtStart == null) { sqlGetCalendarTwinList.append(SQL_AND_NO_DSTART_IS_SET); } else { sqlGetCalendarTwinList.append(SQL_AND_DSTART_EQUALS_QUESTIONMARK); } } if (dtEnd == null) { // In method updateItems() while storing the Event in the db, if // the End Date is empty it is filled with the Start Date. // Filling the empty EndDate with the StartDate is done only for // Events and not for Tasks. // See "Fix for Siemens S56 end date issue" in method // updateItems(). // So in order to find the twins, if the incoming Event has an // empty EndDate we seek into the db for Events with EndDate // equal to the StartDate value. if (c.getCalendarContent() instanceof Task) { sqlGetCalendarTwinList.append(SQL_AND_NO_DEND_IS_SET); } else { sqlGetCalendarTwinList.append(SQL_AND_DEND_EQUALS_QUESTIONMARK); } } else { if (c.getCalendarContent() instanceof Task) { sqlGetCalendarTwinList.append(SQL_AND_DEND_IN_INTERVAL); } else { sqlGetCalendarTwinList.append(SQL_AND_DEND_EQUALS_QUESTIONMARK); } } if (c.getCalendarContent() instanceof Event) { sqlGetCalendarTwinList.append(SQL_FILTER_BY_TYPE[CALENDAR_EVENT_TYPE]); } else { sqlGetCalendarTwinList.append(SQL_FILTER_BY_TYPE[CALENDAR_TASK_TYPE]); } // // If funambol is not in the debug mode it is not possible to print // the calendar info because it contains sensitive data. // if (Configuration.getConfiguration().isDebugMode()) { if (log.isTraceEnabled()) { StringBuilder sb = new StringBuilder(100); sb.append("Looking for items having: "); if (subject == null || subject.length() == 0) { sb.append("\n> subject: <N/A>"); } else { sb.append("\n> subject: '").append(subject).append('\''); } if (c.getCalendarContent() instanceof Event) { if (dtStart == null) { sb.append("\n> start date: <N/A>"); } else { sb.append("\n> start date: ").append(dtStart); } if (dtEnd == null) { sb.append("\n> end date: <N/A>"); } else { sb.append("\n> end date: ").append(dtEnd); } } else { // It's a task if (dtEnd == null) { sb.append("\n> due date: <N/A>"); } else { sb.append("\n> due date: between ").append(dueYesterdayNoon) .append("\n> and ").append(dueTomorrowNoon) .append(",\n> possibly ").append(dtEnd); } } log.trace(sb.toString()); } } sqlGetCalendarTwinList.append(SQL_ORDER_BY_ID); ps = con.prepareStatement(sqlGetCalendarTwinList.toString()); int k = 1; ps.setString(k++, userId); if (subject != null) { ps.setString(k++, subject.toLowerCase(Locale.ENGLISH)); } if (dtStart != null) { if (c.getCalendarContent() instanceof Event) { ps.setTimestamp(k++, new Timestamp(dtStart.getTime())); } } if (dtEnd != null) { if (c.getCalendarContent() instanceof Task) { ps.setTimestamp(k++, new Timestamp(dueYesterdayNoon.getTime())); ps.setTimestamp(k++, new Timestamp(dueTomorrowNoon.getTime())); } else { ps.setTimestamp(k++, new Timestamp(dtEnd.getTime())); } } else { // In method updateItems() while storing the Event in the db, if // the End Date is empty it is filled with the Start Date. // Filling the empty EndDate with the StartDate is done only for // Events and not for Tasks. // See "Fix for Siemens S56 end date issue" in method // updateItems(). // So in order to find the twins, if the incoming Event has an // empty EndDate we seek into the db for Events with EndDate // equal to the StartDate value. if (c.getCalendarContent() instanceof Event) { ps.setTimestamp(k++, new Timestamp(dtStart.getTime())); } } rs = ps.executeQuery(); long twinId; Timestamp twinDueDate; while (rs.next()) { if (c.getCalendarContent() instanceof Event) { twinId = rs.getLong(1); // dend is not relevant in this case if (log.isTraceEnabled()) { log.trace("Twin event found: " + twinId); } twins.add(Long.toString(twinId)); } else { // it's a Task twinId = rs.getLong(1); twinDueDate = rs.getTimestamp(2); if (log.isTraceEnabled()) { log.trace("Twin task found: " + twinId); } if ((dtEnd != null) && (twinDueDate != null) && twinDueDate.getTime() == dtEnd.getTime()) { twins.addFirst(Long.toString(twinId)); if (log.isTraceEnabled()) { log.trace("Item " + twinId + " is an exact due-date match."); } } else { twins.addLast(Long.toString(twinId)); } } } } catch (Exception e) { throw new DAOException("Error retrieving twin. ", e); } finally { DBTools.close(con, ps, rs); } if (log.isTraceEnabled()) { log.trace("PIMCalendarDAO getTwinItems end"); } return twins; }