/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2002-2008, 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.geotools.arcsde.data.versioning;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.geotools.arcsde.ArcSdeException;
import org.geotools.arcsde.session.Command;
import org.geotools.arcsde.session.ISession;
import org.geotools.arcsde.session.Commands.GetVersionCommand;
import org.geotools.util.logging.Logging;
import com.esri.sde.sdk.client.SeConnection;
import com.esri.sde.sdk.client.SeException;
import com.esri.sde.sdk.client.SeObjectId;
import com.esri.sde.sdk.client.SeState;
import com.esri.sde.sdk.client.SeStreamOp;
import com.esri.sde.sdk.client.SeVersion;
/**
* Handles a versioned table when in transaction mode
*
* @author Gabriel Roldan (TOPP)
* @version $Id$
* @since 2.5.x
* @source $URL:
* http://svn.geotools.org/geotools/trunk/gt/modules/plugin/arcsde/datastore/src/main/java
* /org/geotools/arcsde/data/versioning/TransactionVersionHandler.java $
*/
public class TransactionVersionHandler implements ArcSdeVersionHandler {
private static final Logger LOGGER = Logging.getLogger(TransactionVersionHandler.class
.getName());
private final ISession session;
private final SeVersion version;
/**
* The state used for the transaction, its a sibling of the current state
*/
private SeState transactionState;
public TransactionVersionHandler(final ISession session, final String versionName)
throws IOException {
this.session = session;
LOGGER.finest("Fetching information for version " + versionName);
version = session.issue(new GetVersionCommand(versionName));
}
/**
* Called by ArcSdeFeatureWriter.createStream
*
* @see ArcSdeVersionHandler#
*/
public void setUpStream(final ISession session, final SeStreamOp streamOperation)
throws IOException {
session.issue(new Command<Void>() {
@Override
public Void execute(ISession session, SeConnection connection) throws SeException,
IOException {
LOGGER.finest("setting up stream for transaction on a versioned table");
if (transactionState == null) {
LOGGER.finer("no transaction state created yet, about "
+ "to create a new state for the transaction");
try {
if (LOGGER.isLoggable(Level.FINEST)) {
LOGGER.finest("Refreshing '" + version.getName() + "' version info");
}
version.getInfo();
LOGGER.finest("Getting version state");
final SeState currentState = new SeState(connection, version.getStateId());
final long currentStateId = currentState.getId().longValue();
if (LOGGER.isLoggable(Level.FINER)) {
LOGGER.finer(version.getName() + "version state: " + currentStateId
+ ", open: " + currentState.isOpen() + ", owner: "
+ currentState.getOwner() + ", current user: "
+ connection.getUser());
}
LOGGER.finer("Creating new state for the transaction...");
transactionState = session.createChildState(currentStateId);
LOGGER.finer("New transaction state: " + transactionState.getId()
+ ", parent: " + transactionState.getParentId().longValue());
LOGGER.finer("Locking the transaction state");
transactionState.lock();
LOGGER.finer("Transaction state locked");
} catch (SeException e) {
throw new ArcSdeException(e);
}
}
final SeObjectId differencesId = new SeObjectId(SeState.SE_NULL_STATE_ID);
final SeObjectId currentStateId = transactionState.getId();
streamOperation.setState(currentStateId, differencesId,
SeState.SE_STATE_DIFF_NOCHECK);
return null;
}
});
}
/**
* Not called at all
*
* @see ArcSdeVersionHandler#editOperationWritten(SeStreamOp)
*/
public void editOperationWritten(SeStreamOp editOperation) throws IOException {
// intentionally blank
}
/**
* Not called at all
*
* @see ArcSdeVersionHandler#editOperationFailed(SeStreamOp)
*/
public void editOperationFailed(SeStreamOp editOperation) throws IOException {
// intentionally blank
}
/**
* Called by ArcTransactionState.commit()
*
* @see ArcSdeVersionHandler#commitEditState()
*/
public void commitEditState() throws IOException {
LOGGER.fine("Commiting versioned state");
if (transactionState == null) {
LOGGER.fine("Already commited, ignoring operation");
return;
}
session.issue(new Command<Void>() {
@Override
public Void execute(ISession session, SeConnection connection) throws SeException,
IOException {
SeObjectId transactionStateId = transactionState.getId();
LOGGER.finer("Refreshing version info");
version.getInfo();
LOGGER.finer("Chaning version '" + version.getName()
+ "' state to point to transaction state " + transactionStateId);
version.changeState(transactionStateId);
// SeObjectId parentStateId = transactionState.getId();
// transactionState.trimTree(parentStateId, transactionStateId);
LOGGER.finer("Freeing transaction state lock");
transactionState.freeLock();
transactionState = null;
return null;
}
});
}
/**
* Called by ArcTransactionState.rollback()
*
* @see ArcSdeVersionHandler#rollbackEditState()
*/
public void rollbackEditState() throws IOException {
LOGGER.finer("Rolling back versioned transaction state");
if (transactionState == null) {
LOGGER.finer("Already rolled back, ignoring operation");
return;
}
session.issue(new Command<Void>() {
@Override
public Void execute(ISession session, SeConnection connection) throws SeException,
IOException {
try {
LOGGER.finer("Releasing lock on transaction state "
+ transactionState.getId().longValue());
transactionState.freeLock();
} catch (SeException e) {
// no locked any more, ignore
}
LOGGER.finer("Deleting transaction state " + transactionState.getId().longValue());
transactionState.delete();
transactionState = null;
return null;
}
});
}
}