[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:
Robert von Burg 2014-02-25 21:21:42 +01:00
parent 9f3cbf06f1
commit b8981cc592
7 changed files with 57 additions and 18 deletions

View File

@ -50,9 +50,9 @@ public interface ElementMap<T extends StrolchElement> {
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);

View File

@ -130,7 +130,7 @@ public abstract class CachedElementMap<T extends StrolchElement> 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<T extends StrolchElement> 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<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
* {@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<T extends StrolchElement> implements Elem
}
@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("Elements may not be null!", elements); //$NON-NLS-1$
if (elements.isEmpty())
return;
return Collections.emptyList();
// sort elements by type
Map<String, List<T>> map = sortElementsToType(elements);
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
for (String type : map.keySet()) {
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());
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
getDao(tx).updateAll(elements);
return replacedElements;
}
@Override

View File

@ -74,8 +74,9 @@ public abstract class TransactionalElementMap<T extends StrolchElement> 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<T extends StrolchElement> implemen
}
@Override
public void updateAll(StrolchTransaction tx, List<T> elements) {
public List<T> updateAll(StrolchTransaction tx, List<T> elements) {
getDao(tx).updateAll(elements);
return elements;
}
}

View File

@ -56,7 +56,6 @@ public abstract class AbstractTransaction implements StrolchTransaction {
private ObserverHandler observerHandler;
private boolean suppressUpdates;
private TransactionResult txResult;
private boolean open;
private Set<StrolchRootElement> 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();

View File

@ -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();

View File

@ -17,7 +17,9 @@ package li.strolch.persistence.api;
public enum TransactionState {
OPEN, //
COMMITTING, //
ROLLING_BACK, //
COMMITTED, //
ROLLED_BACK, //
ROLLED_BACK,
FAILED;
}

View File

@ -74,4 +74,6 @@ public abstract class Command implements Restrictable {
}
public abstract void doCommand();
public abstract void undo();
}