/** * This method changes the query object so that all propertyName references are resolved to simple * attribute names against the schema of the feature source. * * <p>For example, this method ensures that propertyName's such as "gml:name" are rewritten as * simply "name". */ public static Query resolvePropertyNames(Query query, SimpleFeatureType schema) { Filter resolved = resolvePropertyNames(query.getFilter(), schema); if (resolved == query.getFilter()) { return query; } Query newQuery = new Query(query); newQuery.setFilter(resolved); return newQuery; }
/** * Copy contructor, clones the state of a generic Query into a DefaultQuery * * @param query */ public DefaultQuery(Query query) { this( query.getTypeName(), query.getNamespace(), query.getFilter(), query.getMaxFeatures(), query.getProperties(), query.getHandle()); this.sortBy = query.getSortBy(); this.coordinateSystem = query.getCoordinateSystem(); this.coordinateSystemReproject = query.getCoordinateSystemReproject(); this.version = query.getVersion(); this.hints = query.getHints(); this.startIndex = query.getStartIndex(); this.alias = query.getAlias(); this.joins = query.getJoins(); }
// Jody - Recomend moving to the following // When we are ready for CoordinateSystem support public FeatureReader<SimpleFeatureType, SimpleFeature> getFeatureReader( Query query, Transaction transaction) throws IOException { Filter filter = query.getFilter(); String typeName = query.getTypeName(); String propertyNames[] = query.getPropertyNames(); if (filter == null) { throw new NullPointerException( "getFeatureReader requires Filter: " + "did you mean Filter.INCLUDE?"); } if (typeName == null) { throw new NullPointerException( "getFeatureReader requires typeName: " + "use getTypeNames() for a list of available types"); } if (transaction == null) { throw new NullPointerException( "getFeatureReader requires Transaction: " + "did you mean to use Transaction.AUTO_COMMIT?"); } SimpleFeatureType featureType = getSchema(query.getTypeName()); if (propertyNames != null || query.getCoordinateSystem() != null) { try { featureType = DataUtilities.createSubType(featureType, propertyNames, query.getCoordinateSystem()); } catch (SchemaException e) { LOGGER.log(Level.FINEST, e.getMessage(), e); throw new DataSourceException("Could not create Feature Type for query", e); } } if (filter == Filter.EXCLUDE || filter.equals(Filter.EXCLUDE)) { return new EmptyFeatureReader<SimpleFeatureType, SimpleFeature>(featureType); } // GR: allow subclases to implement as much filtering as they can, // by returning just it's unsupperted filter filter = getUnsupportedFilter(typeName, filter); if (filter == null) { throw new NullPointerException( "getUnsupportedFilter shouldn't return null. Do you mean Filter.INCLUDE?"); } // There are cases where the readers have to lock. Take shapefile for example. Getting a // Reader causes // the file to be locked. However on a commit TransactionStateDiff locks before a writer is // obtained. In order to // prevent deadlocks either the diff has to obtained first or the reader has to be obtained // first. // Because shapefile writes to a buffer first the actual write lock is not flipped until the // transaction has most of the work // done. As a result I suggest getting the diff first then getting the reader. // JE Diff diff = null; if (transaction != Transaction.AUTO_COMMIT) { TransactionStateDiff state = state(transaction); if (state != null) { diff = state.diff(typeName); } } // This calls our subclass "simple" implementation // All other functionality will be built as a reader around // this class // FeatureReader<SimpleFeatureType, SimpleFeature> reader = getFeatureReader(typeName, query); if (diff != null) reader = new DiffFeatureReader<SimpleFeatureType, SimpleFeature>(reader, diff, query.getFilter()); if (!filter.equals(Filter.INCLUDE)) { reader = new FilteringFeatureReader<SimpleFeatureType, SimpleFeature>(reader, filter); } if (!featureType.equals(reader.getFeatureType())) { LOGGER.fine("Recasting feature type to subtype by using a ReTypeFeatureReader"); reader = new ReTypeFeatureReader(reader, featureType, false); } if (query.getMaxFeatures() != Query.DEFAULT_MAX) { reader = new MaxFeatureReader<SimpleFeatureType, SimpleFeature>(reader, query.getMaxFeatures()); } return reader; }
/** * Takes two {@link Query}objects and produce a new one by mixing the restrictions of both of * them. * * <p>The policy to mix the queries components is the following: * * <ul> * <li>typeName: type names MUST match (not checked if some or both queries equals to <code> * Query.ALL</code>) * <li>handle: you must provide one since no sensible choice can be done between the handles of * both queries * <li>maxFeatures: the lower of the two maxFeatures values will be used (most restrictive) * <li>attributeNames: the attributes of both queries will be joined in a single set of * attributes. IMPORTANT: only <b><i>explicitly</i></b> requested attributes will be joint, * so, if the method <code>retrieveAllProperties()</code> of some of the queries returns * <code>true</code> it does not means that all the properties will be joined. You must * create the query with the names of the properties you want to load. * <li>filter: the filtets of both queries are or'ed * <li><b>any other query property is ignored</b> and no guarantees are made of their return * values, so client code shall explicitly care of hints, startIndex, etc., if needed. * </ul> * * @param firstQuery Query against this DataStore * @param secondQuery DOCUMENT ME! * @param handle DOCUMENT ME! * @return Query restricted to the limits of definitionQuery * @throws NullPointerException if some of the queries is null * @throws IllegalArgumentException if the type names of both queries do not match */ public static Query mixQueries(Query firstQuery, Query secondQuery, String handle) { if ((firstQuery == null) && (secondQuery == null)) { // throw new NullPointerException("Cannot combine two null queries"); return Query.ALL; } if (firstQuery == null || firstQuery.equals(Query.ALL)) { return secondQuery; } else if (secondQuery == null || secondQuery.equals(Query.ALL)) { return firstQuery; } if ((firstQuery.getTypeName() != null) && (secondQuery.getTypeName() != null)) { if (!firstQuery.getTypeName().equals(secondQuery.getTypeName())) { String msg = "Type names do not match: " + firstQuery.getTypeName() + " != " + secondQuery.getTypeName(); throw new IllegalArgumentException(msg); } } // mix versions, if possible String version; if (firstQuery.getVersion() != null) { if (secondQuery.getVersion() != null && !secondQuery.getVersion().equals(firstQuery.getVersion())) throw new IllegalArgumentException("First and second query refer different versions"); version = firstQuery.getVersion(); } else { version = secondQuery.getVersion(); } // none of the queries equals Query.ALL, mix them // use the more restrictive max features field int maxFeatures = Math.min(firstQuery.getMaxFeatures(), secondQuery.getMaxFeatures()); // join attributes names String[] propNames = joinAttributes(firstQuery.getPropertyNames(), secondQuery.getPropertyNames()); // join filters Filter filter = firstQuery.getFilter(); Filter filter2 = secondQuery.getFilter(); if ((filter == null) || filter.equals(Filter.INCLUDE)) { filter = filter2; } else if ((filter2 != null) && !filter2.equals(Filter.INCLUDE)) { filter = ff.and(filter, filter2); } Integer start = 0; if (firstQuery.getStartIndex() != null) { start = firstQuery.getStartIndex(); } if (secondQuery.getStartIndex() != null) { start += secondQuery.getStartIndex(); } // collect all hints Hints hints = new Hints(); if (firstQuery.getHints() != null) { hints.putAll(firstQuery.getHints()); } if (secondQuery.getHints() != null) { hints.putAll(secondQuery.getHints()); } // build the mixed query String typeName = firstQuery.getTypeName() != null ? firstQuery.getTypeName() : secondQuery.getTypeName(); Query mixed = new Query(typeName, filter, maxFeatures, propNames, handle); mixed.setVersion(version); mixed.setHints(hints); if (start != 0) { mixed.setStartIndex(start); } return mixed; }