/*
* 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.geogit;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Logger;
import org.geogit.api.CommitOp;
import org.geogit.api.CommitStateResolver;
import org.geogit.api.GeoGIT;
import org.geogit.api.NothingToCommitException;
import org.geogit.api.RevCommit;
import org.geogit.repository.StagingArea;
import org.geogit.repository.WorkingTree;
import org.geotools.data.Transaction;
import org.geotools.feature.FeatureCollection;
import org.geotools.util.NullProgressListener;
import org.geotools.util.logging.Logging;
import org.opengis.feature.type.Name;
import org.opengis.filter.Filter;
import org.opengis.filter.identity.FeatureId;
import org.opengis.util.ProgressListener;
@SuppressWarnings("rawtypes")
public class VersioningTransactionState implements Transaction.State {
public static final VersioningTransactionState VOID = new VersioningTransactionState(
null) {
@Override
public List<FeatureId> stageInsert(final Name typeName,
FeatureCollection affectedFeatures) throws Exception {
return Collections.emptyList();
}
@Override
public void stageUpdate(final Name typeName,
final FeatureCollection affectedFeatures) throws Exception {
}
@Override
public void stageDelete(Name typeName, Filter filter,
FeatureCollection affectedFeatures) throws Exception {
}
@Override
public void stageRename(final Name typeName, final String oldFid,
final String newFid) {
}
};
static {
// only set resolver if not overriden by application
CommitStateResolver current = GeoGIT.getCommitStateResolver();
if (GeoGIT.DEFAULT_COMMIT_RESOLVER.equals(current)) {
GeoGIT.setCommitStateResolver(new GeoToolsCommitStateResolver());
}
}
private static final ProgressListener NULL_PROGRESS_LISTENER = new NullProgressListener();
private static final Logger LOGGER = Logging
.getLogger(VersioningTransactionState.class);
private Transaction transaction;
private GeoGIT geoGit;
private String id;
private Set<Name> changedTypes;
public VersioningTransactionState(final GeoGIT geoGit) {
this.geoGit = geoGit;
this.id = UUID.randomUUID().toString();
this.changedTypes = Collections.synchronizedSet(new HashSet<Name>());
}
@Override
public void setTransaction(final Transaction transaction) {
if (transaction != null) {
// configure
this.transaction = transaction;
} else {
this.transaction = null;
// TODO: is there some cleanup to do here?
}
}
@Override
public void addAuthorization(String AuthID) throws IOException {
// TODO Auto-generated method stub
}
@Override
public void commit() throws IOException {
LOGGER.info("Committing changeset " + id);
try {
GeoToolsCommitStateResolver.CURRENT_TRANSACTION.set(transaction);
// final Ref branch =
// geoGit.checkout().setName(transactionID).call();
// commit to the branch
RevCommit commit = null;
// checkout master
// final Ref master = geoGit.checkout().setName("master").call();
// merge branch to master
// MergeResult mergeResult = geoGit.merge().include(branch).call();
// TODO: check mergeResult is success?
// geoGit.branchDelete().setName(transactionID).call();
try {
// geoGit.add().call();
CommitOp commitOp = geoGit.commit();
commit = commitOp.call();
LOGGER.info("New commit: " + commit);
} catch (NothingToCommitException emptyCommit) {
LOGGER.warning("GeoGit threw NothingToCommitException, this may be due to the transaction having not changed the repository contents");
} catch (IOException e) {
throw e;
} catch (Exception e) {
throw new IOException(e);
}
} finally {
GeoToolsCommitStateResolver.CURRENT_TRANSACTION.remove();
}
}
@Override
public void rollback() throws IOException {
geoGit.getRepository().getIndex().reset();
}
/**
* @param transactionID
* @param typeName
* @param affectedFeatures
* @return the list of feature ids of the inserted features, in the order
* they were added
* @throws Exception
*/
public List<FeatureId> stageInsert(final Name typeName,
FeatureCollection affectedFeatures) throws Exception {
return stageInsert(typeName, affectedFeatures, false);
}
public List<FeatureId> stageInsert(final Name typeName,
FeatureCollection affectedFeatures,
final boolean forceUseProvidedFIDs) throws Exception {
changedTypes.add(typeName);
WorkingTree workingTree = geoGit.getRepository().getWorkingTree();
List<FeatureId> inserted = workingTree.insert(affectedFeatures,
forceUseProvidedFIDs, NULL_PROGRESS_LISTENER);
geoGit.add().call();
return inserted;
}
public void stageUpdate(final Name typeName,
final FeatureCollection newValues) throws Exception {
changedTypes.add(typeName);
WorkingTree workingTree = geoGit.getRepository().getWorkingTree();
workingTree.update(newValues, NULL_PROGRESS_LISTENER);
geoGit.add().call();
}
public void stageDelete(final Name typeName, final Filter filter,
final FeatureCollection affectedFeatures) throws Exception {
changedTypes.add(typeName);
WorkingTree workingTree = geoGit.getRepository().getWorkingTree();
workingTree.delete(typeName, filter, affectedFeatures);
geoGit.add().call();
}
public void stageRename(final Name typeName, final String oldFid,
final String newFid) {
StagingArea index = geoGit.getRepository().getIndex();
final String namespaceURI = typeName.getNamespaceURI();
final String localPart = typeName.getLocalPart();
List<String> from = Arrays.asList(namespaceURI, localPart, oldFid);
List<String> to = Arrays.asList(namespaceURI, localPart, newFid);
index.renamed(from, to);
}
private List<String> path(final Name typeName) {
List<String> path = new ArrayList<String>(2);
if (typeName.getNamespaceURI() != null) {
path.add(typeName.getNamespaceURI());
}
path.add(typeName.getLocalPart());
return path;
}
}