/* * 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.io.IOException; import java.util.HashSet; import java.util.List; import java.util.Set; import org.geogit.api.GeoGIT; import org.geogit.repository.Repository; import org.geoserver.data.versioning.VersioningDataAccess; import org.geotools.data.DataAccess; import org.geotools.data.FeatureLocking; import org.geotools.data.FeatureSource; import org.geotools.data.FeatureStore; import org.geotools.data.Query; import org.geotools.data.ServiceInfo; import org.geotools.feature.DefaultFeatureCollection; import org.geotools.feature.FeatureCollection; import org.opengis.feature.Feature; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.feature.type.FeatureType; import org.opengis.feature.type.Name; import org.opengis.filter.Id; import org.opengis.filter.identity.Identifier; import org.opengis.filter.identity.ResourceId; import org.springframework.util.Assert; import com.google.common.base.Throwables; @SuppressWarnings({ "rawtypes", "unchecked" }) public class DataAccessDecorator<T extends FeatureType, F extends Feature> implements VersioningDataAccess<T, F> { protected DataAccess<T, F> unversioned; protected Repository repository; public DataAccessDecorator(DataAccess unversioned, Repository versioningRepo) { Assert.notNull(unversioned); Assert.notNull(versioningRepo); Assert.isTrue(!(unversioned instanceof DataAccessDecorator)); this.unversioned = unversioned; this.repository = versioningRepo; } public boolean isVersioned(Name name) { boolean isVersioned = repository.getWorkingTree().hasRoot(name); return isVersioned; } /** * @see org.geotools.data.DataAccess#dispose() */ @Override public void dispose() { if (unversioned != null) { unversioned.dispose(); unversioned = null; } } /** * @see org.geotools.data.DataAccess#getFeatureSource(org.opengis.feature.type.Name) */ @Override public FeatureSource<T, F> getFeatureSource(Name typeName) throws IOException { FeatureSource source = unversioned.getFeatureSource(typeName); if (source instanceof FeatureLocking) { return createFeatureLocking((FeatureLocking) source); } else if (source instanceof FeatureStore) { return createFeatureStore((FeatureStore) source); } return createFeatureSource(source); } /** * @see org.geotools.data.DataAccess#getInfo() */ @Override public ServiceInfo getInfo() { return unversioned.getInfo(); } /** * @see org.geotools.data.DataAccess#createSchema(org.opengis.feature.type.FeatureType) */ @Override public void createSchema(T featureType) throws IOException { unversioned.createSchema(featureType); try { repository.getWorkingTree().init(featureType); GeoGIT ggit = new GeoGIT(repository); ggit.add().call(); ggit.commit().call(); } catch (Exception e) { Throwables.propagate(e); } } /** * @see org.geotools.data.DataAccess#updateSchema(org.opengis.feature.type.Name, * org.opengis.feature.type.FeatureType) */ @Override public void updateSchema(Name typeName, T featureType) throws IOException { unversioned.updateSchema(typeName, featureType); } /** * @see org.geotools.data.DataAccess#getNames() */ @Override public List<Name> getNames() throws IOException { return unversioned.getNames(); } /** * @see org.geotools.data.DataAccess#getSchema(org.opengis.feature.type.Name) */ @Override public T getSchema(Name name) throws IOException { return unversioned.getSchema(name); } /** * @precondition {@code typeName != null && versioningFilter != null} * @precondition {@code versioningFilter.getIdentifiers().size() > 0} * @postcondition {@code $return != null} * @param typeName * @param versioningFilter * @param extraQuery * @return * @throws IOException */ public FeatureCollection getFeatures(final Name typeName, final Id versioningFilter, final Query extraQuery) throws IOException { Assert.notNull(typeName); Assert.notNull(versioningFilter); Assert.isTrue(versioningFilter.getIdentifiers().size() > 0); final Set<Identifier> identifiers = versioningFilter.getIdentifiers(); final Set<ResourceId> resourceIds = new HashSet<ResourceId>(); for (Identifier id : identifiers) { if (id instanceof ResourceId) { resourceIds.add((ResourceId) id); } } if (resourceIds.size() == 0) { throw new IllegalArgumentException("At least one " + ResourceId.class.getName() + " should be provided: " + identifiers); } final FeatureType featureType = this.getSchema(typeName); ResourceIdFeatureCollector versionQuery; versionQuery = new ResourceIdFeatureCollector(repository, featureType, resourceIds); DefaultFeatureCollection features = new DefaultFeatureCollection(null, (SimpleFeatureType) featureType); for (Feature f : versionQuery) { features.add((SimpleFeature) f); } return features; } protected FeatureSource<T, F> createFeatureSource(FeatureSource<T, F> source) { return new FeatureSourceDecorator(source, repository); } protected FeatureStore<T, F> createFeatureStore(FeatureStore<T, F> store) { return new FeatureStoreDecorator(store, repository); } protected FeatureLocking<T, F> createFeatureLocking( FeatureLocking<T, F> locking) { return new FeatureLockingDecorator(locking, repository); } }