public static FeatureReader wrap(FeatureReader reader, final Query remainingParameters) throws DataStoreException { final Integer start = remainingParameters.getStartIndex(); final Integer max = remainingParameters.getMaxFeatures(); final Filter filter = remainingParameters.getFilter(); final GenericName[] properties = remainingParameters.getPropertyNames(); final SortBy[] sorts = remainingParameters.getSortBy(); final double[] resampling = remainingParameters.getResolution(); final CoordinateReferenceSystem crs = remainingParameters.getCoordinateSystemReproject(); final Hints hints = remainingParameters.getHints(); // we should take care of wrapping the reader in a correct order to avoid // unnecessary calculations. fast and reducing number wrapper should be placed first. // but we must not take misunderstanding assumptions neither. // exemple : filter is slow than startIndex and MaxFeature but must be placed before // otherwise the result will be illogic. // wrap sort by --------------------------------------------------------- // This can be really expensive, and force the us to read the full iterator. // that may cause out of memory errors. if (sorts != null && sorts.length != 0) { reader = GenericSortByFeatureIterator.wrap(reader, sorts); } // wrap filter ---------------------------------------------------------- // we must keep the filter first since it impacts the start index and max feature if (filter != null && filter != Filter.INCLUDE) { if (filter == Filter.EXCLUDE) { // filter that exclude everything, use optimzed reader reader = GenericEmptyFeatureIterator.createReader(reader.getFeatureType()); // close original reader reader.close(); } else { reader = GenericFilterFeatureIterator.wrap(reader, filter); } } // wrap start index ----------------------------------------------------- if (start != null && start > 0) { reader = GenericStartIndexFeatureIterator.wrap(reader, start); } // wrap max ------------------------------------------------------------- if (max != null) { if (max == 0) { // use an optimized reader reader = GenericEmptyFeatureIterator.createReader(reader.getFeatureType()); // close original reader reader.close(); } else { reader = GenericMaxFeatureIterator.wrap(reader, max); } } // wrap properties, remove primary keys if necessary -------------------- final Boolean hide = (Boolean) hints.get(HintsPending.FEATURE_HIDE_ID_PROPERTY); final FeatureType original = reader.getFeatureType(); FeatureType mask = original; if (properties != null) { final List<GenericName> names = new ArrayList<GenericName>(); loop: for (GenericName n : properties) { for (GenericName dn : names) { if (NamesExt.match(n, dn)) continue loop; } names.add(n); } try { mask = FeatureTypeUtilities.createSubType(mask, names.toArray(new GenericName[0])); } catch (MismatchedFeatureException ex) { throw new DataStoreException(ex); } } if (hide != null && hide) { try { // remove primary key properties mask = FeatureTypeUtilities.excludePrimaryKeyFields(mask); } catch (MismatchedFeatureException ex) { throw new DataStoreException(ex); } } if (mask != original) { reader = GenericRetypeFeatureIterator.wrap(reader, mask, hints); } // wrap resampling ------------------------------------------------------ if (resampling != null) { reader = GenericTransformFeatureIterator.wrap( reader, new GeometryScaleTransformer(resampling[0], resampling[1]), hints); } // wrap reprojection ---------------------------------------------------- if (crs != null) { try { reader = GenericReprojectFeatureIterator.wrap(reader, crs, hints); } catch (FactoryException ex) { throw new DataStoreException(ex); } catch (MismatchedFeatureException ex) { throw new DataStoreException(ex); } } return reader; }