/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2002-2011, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geoserver.data.versioning.decorator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.geogit.api.LogOp;
import org.geogit.api.ObjectId;
import org.geogit.api.Ref;
import org.geogit.api.RevCommit;
import org.geogit.api.RevTree;
import org.geogit.storage.ObjectReader;
import org.geogit.storage.WrappedSerialisingFactory;
import org.geotools.data.Query;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.filter.FilterFactoryImpl;
import org.opengis.feature.Feature;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.Name;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory2;
import org.opengis.filter.identity.Version;
public class VersionedTest extends DecoratedTestCase {
public void testNoHistory() throws Exception {
SimpleFeatureIterator feats = null;
try {
SimpleFeatureSource source = versioned.getFeatureSource(sampleName);
assertNotNull(source);
Query query = new Query(sampleName);
query.setVersion("ALL");
SimpleFeatureCollection collection = source.getFeatures(query);
assertNotNull(collection);
List<SimpleFeature> featList = getOriginalFeatures(sampleName);
assertEquals(featList.size(), collection.size());
feats = collection.features();
assertNotNull(feats);
while (feats.hasNext()) {
SimpleFeature feat = feats.next();
assertNotNull(feat);
LOGGER.info(feat.toString());
assertTrue(containsFeature(feat, featList));
}
LOGGER.info("End testNoHistory");
} finally {
if (feats != null)
feats.close();
}
}
public void testResourceId() throws Exception {
SimpleFeatureIterator feats = null;
List<SimpleFeature> featList = new ArrayList<SimpleFeature>(1);
featList.add(sample1);
try {
SimpleFeatureSource source = versioned.getFeatureSource(sampleName);
assertNotNull(source);
FilterFactory2 ff = new FilterFactoryImpl();
Filter filter = ff.id(ff.resourceId(idS1,
sampleFid1.getFeatureVersion(), null));
Query query = new Query(sampleName, filter);
SimpleFeatureCollection collection = source.getFeatures(query);
assertNotNull(collection);
assertEquals(featList.size(), collection.size());
feats = collection.features();
assertNotNull(feats);
while (feats.hasNext()) {
SimpleFeature feat = feats.next();
assertNotNull(feat);
LOGGER.info(feat.toString());
assertTrue(feat.toString() + " is expected.",
containsFeature(feat, featList));
}
} finally {
if (feats != null)
feats.close();
}
}
public void testResourceIdHistory() throws Exception {
updateSampleFeatures();
SimpleFeatureIterator feats = null;
List<SimpleFeature> featList = new ArrayList<SimpleFeature>(1);
featList.add(sample2);
try {
SimpleFeatureSource source = versioned.getFeatureSource(sampleName);
assertNotNull(source);
FilterFactory2 ff = new FilterFactoryImpl();
Filter filter = ff.id(ff.resourceId(idS2,
sampleFid2.getFeatureVersion(), null));
Query query = new Query(sampleName, filter);
SimpleFeatureCollection collection = source.getFeatures(query);
assertNotNull(collection);
assertEquals(featList.size(), collection.size());
feats = collection.features();
assertNotNull(feats);
while (feats.hasNext()) {
SimpleFeature feat = feats.next();
assertNotNull(feat);
LOGGER.info(feat.toString());
assertTrue(feat.toString() + " is expected.",
containsFeature(feat, featList));
}
} finally {
if (feats != null)
feats.close();
}
}
public void testResourceIdTrivialQuery() throws Exception {
updateSampleFeatures();
SimpleFeatureIterator feats = null;
List<SimpleFeature> featList = new ArrayList<SimpleFeature>(1);
featList.add(sample1);
try {
SimpleFeatureSource source = versioned.getFeatureSource(sampleName);
assertNotNull(source);
FilterFactory2 ff = new FilterFactoryImpl();
Filter filter = ff.id(ff.resourceId(idS1,
sampleFid1.getFeatureVersion(), null));
Query query = new Query(sampleName, filter);
query.setVersion(Version.Action.ALL);
SimpleFeatureCollection collection = source.getFeatures(query);
assertNotNull(collection);
assertEquals(featList.size(), collection.size());
feats = collection.features();
assertNotNull(feats);
while (feats.hasNext()) {
SimpleFeature feat = feats.next();
assertNotNull(feat);
LOGGER.info(feat.toString());
assertTrue(feat.toString() + " is expected.",
containsFeature(feat, featList));
}
} finally {
if (feats != null)
feats.close();
}
}
public void testResourceIdReinforcingQuery() throws Exception {
updateSampleFeatures();
SimpleFeatureIterator feats = null;
List<SimpleFeature> featList = new ArrayList<SimpleFeature>(1);
featList.add(sample1);
try {
SimpleFeatureSource source = versioned.getFeatureSource(sampleName);
assertNotNull(source);
FilterFactory2 ff = new FilterFactoryImpl();
Filter filter = ff.id(ff.resourceId(idS1,
sampleFid1.getFeatureVersion(), null));
Query query = new Query(sampleName, filter);
query.setVersion(Version.Action.FIRST);
SimpleFeatureCollection collection = source.getFeatures(query);
assertNotNull(collection);
assertEquals(featList.size(), collection.size());
feats = collection.features();
assertNotNull(feats);
while (feats.hasNext()) {
SimpleFeature feat = feats.next();
assertNotNull(feat);
LOGGER.info(feat.toString());
assertTrue(feat.toString() + " is expected.",
containsFeature(feat, featList));
}
} finally {
if (feats != null)
feats.close();
}
}
public void testResourceIdContradictoryQuery() throws Exception {
updateSampleFeatures();
SimpleFeatureIterator feats = null;
try {
SimpleFeatureSource source = versioned.getFeatureSource(sampleName);
assertNotNull(source);
FilterFactory2 ff = new FilterFactoryImpl();
Filter filter = ff.id(ff.resourceId(idS1,
sampleFid1.getFeatureVersion(), null));
Query query = new Query(sampleName, filter);
query.setVersion(Version.Action.LAST);
SimpleFeatureCollection collection = source.getFeatures(query);
assertNotNull(collection);
assertEquals(0, collection.size());
} finally {
if (feats != null)
feats.close();
}
}
public void testFullHistory() throws Exception {
updateTestFeatures();
SimpleFeatureIterator feats = null;
try {
SimpleFeatureSource source = versioned.getFeatureSource(testName);
assertNotNull(source);
Query query = new Query(testName);
query.setVersion("ALL");
SimpleFeatureCollection collection = source.getFeatures(query);
assertNotNull(collection);
List<SimpleFeature> featList = getAllFeatures(testName);
LOGGER.info(" " + featList.size());
LOGGER.info(" " + collection.size());
assertEquals(featList.size(), collection.size());
feats = collection.features();
assertNotNull(feats);
while (feats.hasNext()) {
SimpleFeature feat = feats.next();
assertNotNull(feat);
assertTrue(containsFeature(feat, featList));
}
} finally {
if (feats != null)
feats.close();
}
}
public void testBBoxHistory() throws Exception {
updateTestFeatures();
SimpleFeatureIterator feats = null;
try {
List<SimpleFeature> featList = new ArrayList<SimpleFeature>(4);
featList.add(test1);
featList.add(test3);
SimpleFeatureSource source = versioned.getFeatureSource(testName);
assertNotNull(source);
FilterFactory2 ff = new FilterFactoryImpl();
Filter filter = ff.bbox("ln", -1.5, -1.5, 1.5, 1.5, "srid=4326");
Query query = new Query(testName, filter);
query.setVersion("FIRST");
SimpleFeatureCollection collection = source.getFeatures(query);
assertNotNull(collection);
assertEquals(featList.size(), collection.size());
feats = collection.features();
assertNotNull(feats);
while (feats.hasNext()) {
SimpleFeature feat = feats.next();
assertNotNull(feat);
LOGGER.info(feat.toString());
assertTrue(feat.toString() + " is expected.",
containsFeature(feat, featList));
}
} finally {
if (feats != null)
feats.close();
}
}
public void testBBoxFullHistory() throws Exception {
SimpleFeatureIterator feats = null;
try {
updateTestFeatures();
List<SimpleFeature> featList = new ArrayList<SimpleFeature>(4);
featList.add(test1);
featList.add(test3);
featList.add(test1b);
featList.add(test3b);
SimpleFeatureSource source = versioned.getFeatureSource(testName);
assertNotNull(source);
FilterFactory2 ff = new FilterFactoryImpl();
Filter filter = ff.bbox("ln", -1.5, -1.5, 1.5, 1.5, "srid=4326");
Query query = new Query(testName, filter);
query.setVersion("ALL");
SimpleFeatureCollection collection = source.getFeatures(query);
assertNotNull(collection);
assertEquals(featList.size(), collection.size());
feats = collection.features();
assertNotNull(feats);
while (feats.hasNext()) {
SimpleFeature feat = feats.next();
assertNotNull(feat);
LOGGER.info(feat.toString());
assertTrue(feat.toString() + " is expected.",
containsFeature(feat, featList));
}
} finally {
if (feats != null)
feats.close();
}
}
public void testConsistencyNoHistory() throws Exception {
verifyVersionedConsistency();
verifyUnversionedConsistency();
}
public void testConsistencyHistory() throws Exception {
updateTestFeatures();
updateSampleFeatures();
finalTestFeatureUpdate();
verifyVersionedConsistency();
verifyUnversionedConsistency();
}
private void verifyUnversionedConsistency() throws Exception {
SimpleFeatureIterator feats = null;
try {
List<SimpleFeature> decoratedFeatures = new ArrayList<SimpleFeature>();
SimpleFeatureSource source = unversioned.getFeatureSource(testName);
assertNotNull(source);
Query query = new Query(testName);
SimpleFeatureCollection collection = source.getFeatures(query);
assertNotNull(collection);
feats = collection.features();
assertNotNull(feats);
while(feats.hasNext()) {
SimpleFeature feat = feats.next();
assertNotNull(feat);
decoratedFeatures.add(feat);
}
List<SimpleFeature> versionedFeatures = getLatestFeatures(testType);
compareFeatureLists(decoratedFeatures, versionedFeatures);
} finally {
if(feats != null)
feats.close();
}
}
private void verifyVersionedConsistency() throws Exception {
SimpleFeatureIterator feats = null;
try {
List<SimpleFeature> decoratedFeatures = new ArrayList<SimpleFeature>();
SimpleFeatureSource source = versioned.getFeatureSource(testName);
assertNotNull(source);
Query query = new Query(testName);
query.setVersion("ALL");
SimpleFeatureCollection collection = source.getFeatures(query);
assertNotNull(collection);
feats = collection.features();
assertNotNull(feats);
while(feats.hasNext()) {
SimpleFeature feat = feats.next();
assertNotNull(feat);
decoratedFeatures.add(feat);
}
List<SimpleFeature> versionedFeatures = getAllFeatures(testType);
compareFeatureLists(decoratedFeatures, versionedFeatures);
} finally {
if(feats != null)
feats.close();
}
}
private void compareFeatureLists(List<SimpleFeature> left, List<SimpleFeature> right) {
assertEquals(left.size(), right.size());
Iterator<SimpleFeature> it = left.iterator();
while(it.hasNext()) {
SimpleFeature lfeat = it.next();
LOGGER.info(lfeat.toString());
assertTrue(containsFeature(lfeat, right));
}
}
private List<SimpleFeature> getLatestFeatures(SimpleFeatureType featureType) {
Name typeName = featureType.getName();
LogOp logOp = new LogOp(repo);
logOp.addPath(typeName.getNamespaceURI(), typeName.getLocalPart()).setLimit(1);
return getFeaturesFromLog(logOp, featureType);
}
private List<SimpleFeature> getAllFeatures(SimpleFeatureType featureType) {
Name typeName = featureType.getName();
LogOp logOp = new LogOp(repo);
logOp.addPath(typeName.getNamespaceURI(), typeName.getLocalPart());
return getFeaturesFromLog(logOp, featureType);
}
private List<SimpleFeature> getFeaturesFromLog(LogOp logOp, SimpleFeatureType featureType) {
Name typeName = featureType.getName();
try {
Set<Ref> refs = new HashSet<Ref>();
Iterator<RevCommit> featureCommits = logOp.call();
while(featureCommits.hasNext()) {
RevCommit cmt = featureCommits.next();
refs.addAll(getRefsByCommit(cmt, typeName));
}
List<SimpleFeature> feats = new ArrayList<SimpleFeature>();
for(Ref ref : refs) {
SimpleFeature feat = (SimpleFeature)repo.getFeature(featureType, ref.getName(), ref.getObjectId());
feats.add(feat);
}
return feats;
} catch (Exception ex) {
/*
* Need some logging.
*/
return Collections.emptyList();
}
}
private List<Ref> getRefsByCommit(RevCommit commit, Name typeName) {
List<Ref> treeRefs = new ArrayList<Ref>();
if (commit != null) {
ObjectId commitTreeId = commit.getTreeId();
RevTree commitTree = repo.getTree(commitTreeId);
Ref nsRef = commitTree.get(typeName.getNamespaceURI());
RevTree nsTree = repo.getTree(nsRef.getObjectId());
Ref typeRef = nsTree.get(typeName.getLocalPart());
RevTree typeTree = repo.getTree(
typeRef.getObjectId());
Iterator<Ref> it = typeTree.iterator(null);
while (it.hasNext()) {
Ref nextRef = it.next();
treeRefs.add(nextRef);
}
}
return treeRefs;
}
}