public SimpleFeatureCollection sort(org.opengis.filter.sort.SortBy sort) { Query query = new DefaultQuery(); ((DefaultQuery) query).setSortBy(new org.opengis.filter.sort.SortBy[] {sort}); query = DataUtilities.mixQueries(this.query, query, null); return new ContentFeatureCollection(featureSource, query); }
public FeatureCollection<SimpleFeatureType, SimpleFeature> getLog( String fromVersion, String toVersion, Filter filter, String[] userIds, int maxRows) throws IOException { if (filter == null) filter = Filter.INCLUDE; RevisionInfo r1 = new RevisionInfo(fromVersion); RevisionInfo r2 = new RevisionInfo(toVersion); boolean swapped = false; if (r1.revision > r2.revision) { // swap them RevisionInfo tmpr = r1; r1 = r2; r2 = tmpr; String tmps = toVersion; toVersion = fromVersion; fromVersion = tmps; swapped = true; } // We implement this exactly as described. Happily, it seems Postgis does not have // sql lentgh limitations. Yet, if would be a lot better if we could encode this // as a single sql query with subqueries... (but not all filters are encodable...) ModifiedFeatureIds mfids = store.getModifiedFeatureFIDs( schema.getTypeName(), fromVersion, toVersion, filter, userIds, getTransaction()); Set ids = new HashSet(mfids.getCreated()); ids.addAll(mfids.getDeleted()); ids.addAll(mfids.getModified()); // grab the eventually modified revisions from mfids r1 = mfids.fromRevision; r2 = mfids.toRevision; // no changes? if (ids.isEmpty()) return new EmptyFeatureCollection(schema); // Create a filter that sounds like: // (revision > r1 and revision <= r2) or (expired > r1 and expired <= r2) and fid in // (fidlist) FilterFactory ff = CommonFactoryFinder.getFilterFactory(null); Filter fidFilter = store.buildFidFilter(ids); Filter transformedFidFilter = store.transformFidFilter(schema.getTypeName(), fidFilter); Filter revGrR1 = ff.greater(ff.property("revision"), ff.literal(r1.revision)); Filter revLeR2 = ff.lessOrEqual(ff.property("revision"), ff.literal(r2.revision)); Filter expGrR1 = ff.greater(ff.property("expired"), ff.literal(r1.revision)); Filter expLeR2 = ff.lessOrEqual(ff.property("expired"), ff.literal(r2.revision)); Filter versionFilter = ff.and(transformedFidFilter, ff.or(ff.and(revGrR1, revLeR2), ff.and(expGrR1, expLeR2))); // We just want the revision and expired, build a query against the real feature type DefaultQuery q = new DefaultQuery(schema.getTypeName(), versionFilter, new String[] {"revision", "expired"}); FeatureReader<SimpleFeatureType, SimpleFeature> fr = null; SortedSet revisions = new TreeSet(); try { fr = store.wrapped.getFeatureReader(q, getTransaction()); while (fr.hasNext()) { SimpleFeature f = fr.next(); Long revision = (Long) f.getAttribute(0); if (revision.longValue() > r1.revision) revisions.add(revision); Long expired = (Long) f.getAttribute(1); if (expired.longValue() != Long.MAX_VALUE && expired.longValue() > r1.revision) revisions.add(expired); } } catch (Exception e) { throw new DataSourceException("Error reading modified revisions from datastore", e); } finally { if (fr != null) fr.close(); } // now, we have a list of revisions between a min and a max // let's try to build a fid filter with revisions from the biggest to the smallest Set revisionIdSet = new HashSet(); for (Iterator it = revisions.iterator(); it.hasNext(); ) { Long rev = (Long) it.next(); revisionIdSet.add( ff.featureId(VersionedPostgisDataStore.TBL_CHANGESETS + "." + rev.toString())); } if (revisionIdSet.isEmpty()) return new EmptyFeatureCollection(schema); Filter revisionFilter = ff.id(revisionIdSet); // return the changelog // TODO: sort on revision descending. Unfortunately, to do so we have to fix fid mappers, // so that auto-increment can return revision among the attributes, and at the same // time simply allow not include fid attributes in the insert queries (or provide a // "default" // value for them). FeatureSource<SimpleFeatureType, SimpleFeature> changesets = (FeatureSource<SimpleFeatureType, SimpleFeature>) store.getFeatureSource(VersionedPostgisDataStore.TBL_CHANGESETS); DefaultQuery sq = new DefaultQuery(); sq.setFilter(revisionFilter); final SortOrder order = swapped ? SortOrder.ASCENDING : SortOrder.DESCENDING; sq.setSortBy(new SortBy[] {ff.sort("revision", order)}); if (maxRows > 0) sq.setMaxFeatures(maxRows); return changesets.getFeatures(sq); }