+public class TransactionChainProxy implements DOMStoreTransactionChain {
+
+ private static final Logger LOG = LoggerFactory.getLogger(TransactionChainProxy.class);
+
+ private interface State {
+ boolean isReady();
+
+ SimpleEntry<Object, List<Future<ActorSelection>>> getReadyFutures();
+
+ void setReadyFutures(Object txIdentifier, List<Future<ActorSelection>> readyFutures);
+ }
+
+ private static class Allocated implements State {
+ private volatile SimpleEntry<Object, List<Future<ActorSelection>>> readyFutures;
+
+ @Override
+ public boolean isReady() {
+ return readyFutures != null;
+ }
+
+ @Override
+ public SimpleEntry<Object, List<Future<ActorSelection>>> getReadyFutures() {
+ return readyFutures != null ? readyFutures : EMPTY_READY_FUTURES;
+ }
+
+ @Override
+ public void setReadyFutures(Object txIdentifier, List<Future<ActorSelection>> readyFutures) {
+ this.readyFutures = new SimpleEntry<>(txIdentifier, readyFutures);
+ }
+ }
+
+ private static abstract class AbstractDefaultState implements State {
+ @Override
+ public SimpleEntry<Object, List<Future<ActorSelection>>> getReadyFutures() {
+ return EMPTY_READY_FUTURES;
+ }
+
+ @Override
+ public void setReadyFutures(Object txIdentifier, List<Future<ActorSelection>> readyFutures) {
+ throw new IllegalStateException("No transaction is allocated");
+ }
+ }
+
+ private static final State IDLE_STATE = new AbstractDefaultState() {
+ @Override
+ public boolean isReady() {
+ return true;
+ }
+ };
+
+ private static final State CLOSED_STATE = new AbstractDefaultState() {
+ @Override
+ public boolean isReady() {
+ throw new TransactionChainClosedException("Transaction chain has been closed");
+ }
+ };
+
+ private static final SimpleEntry<Object, List<Future<ActorSelection>>> EMPTY_READY_FUTURES =
+ new SimpleEntry<Object, List<Future<ActorSelection>>>("",
+ Collections.<Future<ActorSelection>>emptyList());
+
+ private static final AtomicReferenceFieldUpdater<TransactionChainProxy, State> STATE_UPDATER =
+ AtomicReferenceFieldUpdater.newUpdater(TransactionChainProxy.class, State.class, "state");
+