[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
This commit is contained in:
parent
9f3cbf06f1
commit
b8981cc592
|
@ -50,9 +50,9 @@ public interface ElementMap<T extends StrolchElement> {
|
||||||
|
|
||||||
public void addAll(StrolchTransaction tx, List<T> elements);
|
public void addAll(StrolchTransaction tx, List<T> elements);
|
||||||
|
|
||||||
public void update(StrolchTransaction tx, T element);
|
public T update(StrolchTransaction tx, T element);
|
||||||
|
|
||||||
public void updateAll(StrolchTransaction tx, List<T> elements);
|
public List<T> updateAll(StrolchTransaction tx, List<T> elements);
|
||||||
|
|
||||||
public void remove(StrolchTransaction tx, T element);
|
public void remove(StrolchTransaction tx, T element);
|
||||||
|
|
||||||
|
|
|
@ -130,7 +130,7 @@ public abstract class CachedElementMap<T extends StrolchElement> implements Elem
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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("Transaction may not be null!", tx); //$NON-NLS-1$
|
||||||
DBC.PRE.assertNotNull("Element may not be null!", element); //$NON-NLS-1$
|
DBC.PRE.assertNotNull("Element may not be null!", element); //$NON-NLS-1$
|
||||||
|
|
||||||
|
@ -141,14 +141,17 @@ public abstract class CachedElementMap<T extends StrolchElement> implements Elem
|
||||||
throw new StrolchPersistenceException(msg);
|
throw new StrolchPersistenceException(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T replacedElement;
|
||||||
synchronized (byType) {
|
synchronized (byType) {
|
||||||
if (byType.remove(element.getId()) == null) {
|
if (byType.remove(element.getId()) == null) {
|
||||||
msg = MessageFormat.format(msg, element.getLocator());
|
msg = MessageFormat.format(msg, element.getLocator());
|
||||||
throw new StrolchPersistenceException(msg);
|
throw new StrolchPersistenceException(msg);
|
||||||
}
|
}
|
||||||
byType.put(element.getId(), element);
|
replacedElement = byType.put(element.getId(), element);
|
||||||
getDao(tx).update(element);
|
getDao(tx).update(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return replacedElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -184,8 +187,8 @@ public abstract class CachedElementMap<T extends StrolchElement> implements Elem
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special method used when starting the container to cache the values. Not to be used anywhere else but from the
|
* 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
|
* {@link CachedRealm} and of course through the {@link #add(StrolchTransaction, StrolchElement)}-call to not
|
||||||
* to not duplicate code
|
* duplicate code
|
||||||
*
|
*
|
||||||
* @param element
|
* @param element
|
||||||
* @param tx
|
* @param tx
|
||||||
|
@ -275,18 +278,20 @@ public abstract class CachedElementMap<T extends StrolchElement> implements Elem
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateAll(StrolchTransaction tx, List<T> elements) {
|
public List<T> updateAll(StrolchTransaction tx, List<T> elements) {
|
||||||
DBC.PRE.assertNotNull("Transaction may not be null!", tx); //$NON-NLS-1$
|
DBC.PRE.assertNotNull("Transaction may not be null!", tx); //$NON-NLS-1$
|
||||||
DBC.PRE.assertNotNull("Elements may not be null!", elements); //$NON-NLS-1$
|
DBC.PRE.assertNotNull("Elements may not be null!", elements); //$NON-NLS-1$
|
||||||
|
|
||||||
if (elements.isEmpty())
|
if (elements.isEmpty())
|
||||||
return;
|
return Collections.emptyList();
|
||||||
|
|
||||||
// sort elements by type
|
// sort elements by type
|
||||||
Map<String, List<T>> map = sortElementsToType(elements);
|
Map<String, List<T>> map = sortElementsToType(elements);
|
||||||
|
|
||||||
String msg = "The element {0} can not be updated as it does not exist!"; //$NON-NLS-1$
|
String msg = "The element {0} can not be updated as it does not exist!"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
List<T> replacedElements = new ArrayList<>(elements.size());
|
||||||
|
|
||||||
// update elements
|
// update elements
|
||||||
for (String type : map.keySet()) {
|
for (String type : map.keySet()) {
|
||||||
List<T> list = map.get(type);
|
List<T> list = map.get(type);
|
||||||
|
@ -304,7 +309,7 @@ public abstract class CachedElementMap<T extends StrolchElement> implements Elem
|
||||||
msg = MessageFormat.format(msg, element.getLocator());
|
msg = MessageFormat.format(msg, element.getLocator());
|
||||||
throw new StrolchPersistenceException(msg);
|
throw new StrolchPersistenceException(msg);
|
||||||
}
|
}
|
||||||
byType.put(element.getId(), element);
|
replacedElements.add(byType.put(element.getId(), element));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -312,6 +317,8 @@ public abstract class CachedElementMap<T extends StrolchElement> implements Elem
|
||||||
|
|
||||||
// last is to perform DB changes
|
// last is to perform DB changes
|
||||||
getDao(tx).updateAll(elements);
|
getDao(tx).updateAll(elements);
|
||||||
|
|
||||||
|
return replacedElements;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -74,8 +74,9 @@ public abstract class TransactionalElementMap<T extends StrolchElement> implemen
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(StrolchTransaction tx, T element) {
|
public T update(StrolchTransaction tx, T element) {
|
||||||
getDao(tx).update(element);
|
getDao(tx).update(element);
|
||||||
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -94,7 +95,8 @@ public abstract class TransactionalElementMap<T extends StrolchElement> implemen
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateAll(StrolchTransaction tx, List<T> elements) {
|
public List<T> updateAll(StrolchTransaction tx, List<T> elements) {
|
||||||
getDao(tx).updateAll(elements);
|
getDao(tx).updateAll(elements);
|
||||||
|
return elements;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,6 @@ public abstract class AbstractTransaction implements StrolchTransaction {
|
||||||
private ObserverHandler observerHandler;
|
private ObserverHandler observerHandler;
|
||||||
private boolean suppressUpdates;
|
private boolean suppressUpdates;
|
||||||
private TransactionResult txResult;
|
private TransactionResult txResult;
|
||||||
private boolean open;
|
|
||||||
|
|
||||||
private Set<StrolchRootElement> lockedElements;
|
private Set<StrolchRootElement> lockedElements;
|
||||||
|
|
||||||
|
@ -65,12 +64,32 @@ public abstract class AbstractTransaction implements StrolchTransaction {
|
||||||
this.lockedElements = new HashSet<>();
|
this.lockedElements = new HashSet<>();
|
||||||
this.closeStrategy = TransactionCloseStrategy.COMMIT;
|
this.closeStrategy = TransactionCloseStrategy.COMMIT;
|
||||||
this.txResult = new TransactionResult(getRealmName(), System.nanoTime(), new Date());
|
this.txResult = new TransactionResult(getRealmName(), System.nanoTime(), new Date());
|
||||||
this.open = true;
|
this.txResult.setState(TransactionState.OPEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isOpen() {
|
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
|
@Override
|
||||||
|
@ -209,9 +228,11 @@ public abstract class AbstractTransaction implements StrolchTransaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
this.txResult.setState(TransactionState.COMMITTING);
|
||||||
commit(this.txResult);
|
commit(this.txResult);
|
||||||
handleCommit(start);
|
handleCommit(start);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
this.txResult.setState(TransactionState.ROLLING_BACK);
|
||||||
handleFailure(start, e);
|
handleFailure(start, e);
|
||||||
} finally {
|
} finally {
|
||||||
unlockElements();
|
unlockElements();
|
||||||
|
@ -239,7 +260,6 @@ public abstract class AbstractTransaction implements StrolchTransaction {
|
||||||
protected abstract void rollback(TransactionResult txResult) throws Exception;
|
protected abstract void rollback(TransactionResult txResult) throws Exception;
|
||||||
|
|
||||||
private void handleCommit(long start) {
|
private void handleCommit(long start) {
|
||||||
this.open = false;
|
|
||||||
|
|
||||||
long end = System.nanoTime();
|
long end = System.nanoTime();
|
||||||
long txDuration = end - txResult.getStartNanos();
|
long txDuration = end - txResult.getStartNanos();
|
||||||
|
@ -272,7 +292,6 @@ public abstract class AbstractTransaction implements StrolchTransaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleRollback(long start) {
|
private void handleRollback(long start) {
|
||||||
this.open = false;
|
|
||||||
|
|
||||||
long end = System.nanoTime();
|
long end = System.nanoTime();
|
||||||
long txDuration = end - this.txResult.getStartNanos();
|
long txDuration = end - this.txResult.getStartNanos();
|
||||||
|
@ -284,7 +303,6 @@ public abstract class AbstractTransaction implements StrolchTransaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void handleFailure(long closeStartNanos, Exception e) {
|
protected void handleFailure(long closeStartNanos, Exception e) {
|
||||||
this.open = false;
|
|
||||||
|
|
||||||
long end = System.nanoTime();
|
long end = System.nanoTime();
|
||||||
long txDuration = end - this.txResult.getStartNanos();
|
long txDuration = end - this.txResult.getStartNanos();
|
||||||
|
|
|
@ -45,6 +45,14 @@ public interface StrolchTransaction extends AutoCloseable {
|
||||||
|
|
||||||
public boolean isOpen();
|
public boolean isOpen();
|
||||||
|
|
||||||
|
public boolean isRollingBack();
|
||||||
|
|
||||||
|
public boolean isCommitting();
|
||||||
|
|
||||||
|
public boolean isCommitted();
|
||||||
|
|
||||||
|
public boolean isRolledBack();
|
||||||
|
|
||||||
public ResourceMap getResourceMap();
|
public ResourceMap getResourceMap();
|
||||||
|
|
||||||
public OrderMap getOrderMap();
|
public OrderMap getOrderMap();
|
||||||
|
|
|
@ -17,7 +17,9 @@ package li.strolch.persistence.api;
|
||||||
|
|
||||||
public enum TransactionState {
|
public enum TransactionState {
|
||||||
OPEN, //
|
OPEN, //
|
||||||
|
COMMITTING, //
|
||||||
|
ROLLING_BACK, //
|
||||||
COMMITTED, //
|
COMMITTED, //
|
||||||
ROLLED_BACK, //
|
ROLLED_BACK,
|
||||||
FAILED;
|
FAILED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,4 +74,6 @@ public abstract class Command implements Restrictable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void doCommand();
|
public abstract void doCommand();
|
||||||
|
|
||||||
|
public abstract void undo();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue