From b8981cc592b9e9e7c6bf18545b2abd17abbbd23c Mon Sep 17 00:00:00 2001 From: Robert von Burg Date: Tue, 25 Feb 2014 21:21:42 +0100 Subject: [PATCH] [New] Implemented Command.undo() for all commands This lead to the ElementMaps returning replaced elements when calling update() or updateAll(). Further now the StrolchTransaction has methods to check the state easier than comparing with the TransactionState enum --- .../java/li/strolch/agent/api/ElementMap.java | 4 +-- .../strolch/agent/impl/CachedElementMap.java | 21 ++++++++----- .../agent/impl/TransactionalElementMap.java | 6 ++-- .../persistence/api/AbstractTransaction.java | 30 +++++++++++++++---- .../persistence/api/StrolchTransaction.java | 8 +++++ .../persistence/api/TransactionState.java | 4 ++- .../java/li/strolch/service/api/Command.java | 2 ++ 7 files changed, 57 insertions(+), 18 deletions(-) diff --git a/src/main/java/li/strolch/agent/api/ElementMap.java b/src/main/java/li/strolch/agent/api/ElementMap.java index ba5a078b8..a46a97fb6 100644 --- a/src/main/java/li/strolch/agent/api/ElementMap.java +++ b/src/main/java/li/strolch/agent/api/ElementMap.java @@ -50,9 +50,9 @@ public interface ElementMap { public void addAll(StrolchTransaction tx, List elements); - public void update(StrolchTransaction tx, T element); + public T update(StrolchTransaction tx, T element); - public void updateAll(StrolchTransaction tx, List elements); + public List updateAll(StrolchTransaction tx, List elements); public void remove(StrolchTransaction tx, T element); diff --git a/src/main/java/li/strolch/agent/impl/CachedElementMap.java b/src/main/java/li/strolch/agent/impl/CachedElementMap.java index b4a90778c..ab1e8b875 100644 --- a/src/main/java/li/strolch/agent/impl/CachedElementMap.java +++ b/src/main/java/li/strolch/agent/impl/CachedElementMap.java @@ -130,7 +130,7 @@ public abstract class CachedElementMap implements Elem } @Override - public void update(StrolchTransaction tx, T element) { + public T update(StrolchTransaction tx, T element) { DBC.PRE.assertNotNull("Transaction may not be null!", tx); //$NON-NLS-1$ DBC.PRE.assertNotNull("Element may not be null!", element); //$NON-NLS-1$ @@ -141,14 +141,17 @@ public abstract class CachedElementMap implements Elem throw new StrolchPersistenceException(msg); } + T replacedElement; synchronized (byType) { if (byType.remove(element.getId()) == null) { msg = MessageFormat.format(msg, element.getLocator()); throw new StrolchPersistenceException(msg); } - byType.put(element.getId(), element); + replacedElement = byType.put(element.getId(), element); getDao(tx).update(element); } + + return replacedElement; } @Override @@ -184,8 +187,8 @@ public abstract class CachedElementMap implements Elem /** * Special method used when starting the container to cache the values. Not to be used anywhere else but from the - * {@link CachedRealm} and of course through the {@link #add(StrolchTransaction, StrolchElement)}-call - * to not duplicate code + * {@link CachedRealm} and of course through the {@link #add(StrolchTransaction, StrolchElement)}-call to not + * duplicate code * * @param element * @param tx @@ -275,18 +278,20 @@ public abstract class CachedElementMap implements Elem } @Override - public void updateAll(StrolchTransaction tx, List elements) { + public List updateAll(StrolchTransaction tx, List elements) { DBC.PRE.assertNotNull("Transaction may not be null!", tx); //$NON-NLS-1$ DBC.PRE.assertNotNull("Elements may not be null!", elements); //$NON-NLS-1$ if (elements.isEmpty()) - return; + return Collections.emptyList(); // sort elements by type Map> map = sortElementsToType(elements); String msg = "The element {0} can not be updated as it does not exist!"; //$NON-NLS-1$ + List replacedElements = new ArrayList<>(elements.size()); + // update elements for (String type : map.keySet()) { List list = map.get(type); @@ -304,7 +309,7 @@ public abstract class CachedElementMap implements Elem msg = MessageFormat.format(msg, element.getLocator()); throw new StrolchPersistenceException(msg); } - byType.put(element.getId(), element); + replacedElements.add(byType.put(element.getId(), element)); } } } @@ -312,6 +317,8 @@ public abstract class CachedElementMap implements Elem // last is to perform DB changes getDao(tx).updateAll(elements); + + return replacedElements; } @Override diff --git a/src/main/java/li/strolch/agent/impl/TransactionalElementMap.java b/src/main/java/li/strolch/agent/impl/TransactionalElementMap.java index 8f5dae481..13a412eda 100644 --- a/src/main/java/li/strolch/agent/impl/TransactionalElementMap.java +++ b/src/main/java/li/strolch/agent/impl/TransactionalElementMap.java @@ -74,8 +74,9 @@ public abstract class TransactionalElementMap implemen } @Override - public void update(StrolchTransaction tx, T element) { + public T update(StrolchTransaction tx, T element) { getDao(tx).update(element); + return element; } @Override @@ -94,7 +95,8 @@ public abstract class TransactionalElementMap implemen } @Override - public void updateAll(StrolchTransaction tx, List elements) { + public List updateAll(StrolchTransaction tx, List elements) { getDao(tx).updateAll(elements); + return elements; } } diff --git a/src/main/java/li/strolch/persistence/api/AbstractTransaction.java b/src/main/java/li/strolch/persistence/api/AbstractTransaction.java index 484fa6f51..b2060d8a9 100644 --- a/src/main/java/li/strolch/persistence/api/AbstractTransaction.java +++ b/src/main/java/li/strolch/persistence/api/AbstractTransaction.java @@ -56,7 +56,6 @@ public abstract class AbstractTransaction implements StrolchTransaction { private ObserverHandler observerHandler; private boolean suppressUpdates; private TransactionResult txResult; - private boolean open; private Set lockedElements; @@ -65,12 +64,32 @@ public abstract class AbstractTransaction implements StrolchTransaction { this.lockedElements = new HashSet<>(); this.closeStrategy = TransactionCloseStrategy.COMMIT; this.txResult = new TransactionResult(getRealmName(), System.nanoTime(), new Date()); - this.open = true; + this.txResult.setState(TransactionState.OPEN); } @Override public boolean isOpen() { - return this.open; + return this.txResult.getState() == TransactionState.OPEN; + } + + @Override + public boolean isRollingBack() { + return this.txResult.getState() == TransactionState.ROLLING_BACK; + } + + @Override + public boolean isCommitting() { + return this.txResult.getState() == TransactionState.COMMITTING; + } + + @Override + public boolean isCommitted() { + return this.txResult.getState() == TransactionState.COMMITTED; + } + + @Override + public boolean isRolledBack() { + return this.txResult.getState() == TransactionState.ROLLED_BACK; } @Override @@ -209,9 +228,11 @@ public abstract class AbstractTransaction implements StrolchTransaction { } try { + this.txResult.setState(TransactionState.COMMITTING); commit(this.txResult); handleCommit(start); } catch (Exception e) { + this.txResult.setState(TransactionState.ROLLING_BACK); handleFailure(start, e); } finally { unlockElements(); @@ -239,7 +260,6 @@ public abstract class AbstractTransaction implements StrolchTransaction { protected abstract void rollback(TransactionResult txResult) throws Exception; private void handleCommit(long start) { - this.open = false; long end = System.nanoTime(); long txDuration = end - txResult.getStartNanos(); @@ -272,7 +292,6 @@ public abstract class AbstractTransaction implements StrolchTransaction { } private void handleRollback(long start) { - this.open = false; long end = System.nanoTime(); long txDuration = end - this.txResult.getStartNanos(); @@ -284,7 +303,6 @@ public abstract class AbstractTransaction implements StrolchTransaction { } protected void handleFailure(long closeStartNanos, Exception e) { - this.open = false; long end = System.nanoTime(); long txDuration = end - this.txResult.getStartNanos(); diff --git a/src/main/java/li/strolch/persistence/api/StrolchTransaction.java b/src/main/java/li/strolch/persistence/api/StrolchTransaction.java index 974e2aa3b..74686c2e1 100644 --- a/src/main/java/li/strolch/persistence/api/StrolchTransaction.java +++ b/src/main/java/li/strolch/persistence/api/StrolchTransaction.java @@ -45,6 +45,14 @@ public interface StrolchTransaction extends AutoCloseable { public boolean isOpen(); + public boolean isRollingBack(); + + public boolean isCommitting(); + + public boolean isCommitted(); + + public boolean isRolledBack(); + public ResourceMap getResourceMap(); public OrderMap getOrderMap(); diff --git a/src/main/java/li/strolch/persistence/api/TransactionState.java b/src/main/java/li/strolch/persistence/api/TransactionState.java index 3b922460a..6405bfe4d 100644 --- a/src/main/java/li/strolch/persistence/api/TransactionState.java +++ b/src/main/java/li/strolch/persistence/api/TransactionState.java @@ -17,7 +17,9 @@ package li.strolch.persistence.api; public enum TransactionState { OPEN, // + COMMITTING, // + ROLLING_BACK, // COMMITTED, // - ROLLED_BACK, // + ROLLED_BACK, FAILED; } diff --git a/src/main/java/li/strolch/service/api/Command.java b/src/main/java/li/strolch/service/api/Command.java index 34d1a80da..cdea42493 100644 --- a/src/main/java/li/strolch/service/api/Command.java +++ b/src/main/java/li/strolch/service/api/Command.java @@ -74,4 +74,6 @@ public abstract class Command implements Restrictable { } public abstract void doCommand(); + + public abstract void undo(); }