[Major] Implemented opt-in versioning
Now all root elements have a version, and if the realm has versioning enabled, then actions through the ElementMap lead to new versions being created. There are also methods to revert/undo changes to an object. Some tests are still failing, this will be fixed later
This commit is contained in:
parent
219eb26182
commit
9dc09515e9
|
@ -23,33 +23,106 @@ import li.strolch.model.StrolchRootElement;
|
||||||
import li.strolch.model.parameter.Parameter;
|
import li.strolch.model.parameter.Parameter;
|
||||||
import li.strolch.model.parameter.StringListParameter;
|
import li.strolch.model.parameter.StringListParameter;
|
||||||
import li.strolch.model.parameter.StringParameter;
|
import li.strolch.model.parameter.StringParameter;
|
||||||
|
import li.strolch.persistence.api.StrolchDao;
|
||||||
|
import li.strolch.persistence.api.StrolchPersistenceException;
|
||||||
import li.strolch.persistence.api.StrolchTransaction;
|
import li.strolch.persistence.api.StrolchTransaction;
|
||||||
import li.strolch.runtime.StrolchConstants;
|
import li.strolch.runtime.StrolchConstants;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <p>
|
||||||
|
* The {@link ElementMap} is the entry point to the Strolch model. Any access to Strolch objects is done using the
|
||||||
|
* {@link ElementMap}. A concrete {@link ElementMap} instance uses the given {@link StrolchTransaction} to access the a
|
||||||
|
* {@link StrolchDao} and perform the relevant operation.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* <b>Note:</b>
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
|
*
|
||||||
|
* @param <T>
|
||||||
|
* the object instance being managed
|
||||||
*/
|
*/
|
||||||
public interface ElementMap<T extends StrolchRootElement> {
|
public interface ElementMap<T extends StrolchRootElement> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the underlying persistence layer has elements with the given type
|
||||||
|
*
|
||||||
|
* @param tx
|
||||||
|
* the open {@link StrolchTransaction}
|
||||||
|
* @param type
|
||||||
|
* the type of element to check for
|
||||||
|
*
|
||||||
|
* @return true if the underlying persistence layer has elements with the given type
|
||||||
|
*/
|
||||||
public boolean hasType(StrolchTransaction tx, String type);
|
public boolean hasType(StrolchTransaction tx, String type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the underlying persistence layer has an element with the given type and ID
|
||||||
|
*
|
||||||
|
* @param tx
|
||||||
|
* the open {@link StrolchTransaction}
|
||||||
|
* @param type
|
||||||
|
* the type of element to check for
|
||||||
|
* @param id
|
||||||
|
* the ID of the element to check for
|
||||||
|
*
|
||||||
|
* @return true if the underlying persistence layer has an element with the given type and ID
|
||||||
|
*/
|
||||||
public boolean hasElement(StrolchTransaction tx, String type, String id);
|
public boolean hasElement(StrolchTransaction tx, String type, String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of elements regardless of type in the underlying persistence layer
|
||||||
|
*
|
||||||
|
* @param tx
|
||||||
|
* the open {@link StrolchTransaction}
|
||||||
|
*
|
||||||
|
* @return the number of elements regardless of type in the underlying persistence layer
|
||||||
|
*/
|
||||||
public long querySize(StrolchTransaction tx);
|
public long querySize(StrolchTransaction tx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of elements of the given type in the underlying persistence layer
|
||||||
|
*
|
||||||
|
* @param tx
|
||||||
|
* the open {@link StrolchTransaction}
|
||||||
|
* @param type
|
||||||
|
* the type of element for which the number of elements is to be queried
|
||||||
|
*
|
||||||
|
* @return the number of elements of the given type in the underlying persistence layer
|
||||||
|
*/
|
||||||
public long querySize(StrolchTransaction tx, String type);
|
public long querySize(StrolchTransaction tx, String type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the element with the type "Template" and the id = type
|
* Returns a copy of the element with the type "Template" and the id = type
|
||||||
*
|
*
|
||||||
* @param tx
|
* @param tx
|
||||||
* the open {@link StrolchTransaction}
|
* the open {@link StrolchTransaction}
|
||||||
* @param type
|
* @param type
|
||||||
* The template id to return
|
* The template id to return
|
||||||
|
*
|
||||||
* @return the template, or null if it does not exist
|
* @return the template, or null if it does not exist
|
||||||
*/
|
*/
|
||||||
public T getTemplate(StrolchTransaction tx, String type);
|
public T getTemplate(StrolchTransaction tx, String type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a copy of the element with the type "Template" and the id = type
|
||||||
|
*
|
||||||
|
* @param tx
|
||||||
|
* the open {@link StrolchTransaction}
|
||||||
|
* @param type
|
||||||
|
* The template id to return
|
||||||
|
* @param assertExists
|
||||||
|
* if true, and element does not exist, then a {@link StrolchException} is thrown
|
||||||
|
*
|
||||||
|
* @return the template, or null if it does not exist
|
||||||
|
*
|
||||||
|
* @throws StrolchException
|
||||||
|
* if the template does not exist
|
||||||
|
*/
|
||||||
|
public T getTemplate(StrolchTransaction tx, String type, boolean assertExists) throws StrolchException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the element with the given type and id, or null if it does not exist
|
* Retrieves the element with the given type and id, or null if it does not exist
|
||||||
*
|
*
|
||||||
|
@ -64,6 +137,63 @@ public interface ElementMap<T extends StrolchRootElement> {
|
||||||
*/
|
*/
|
||||||
public T getBy(StrolchTransaction tx, String type, String id);
|
public T getBy(StrolchTransaction tx, String type, String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the element with the given type and id, or null if it does not exist
|
||||||
|
*
|
||||||
|
* @param tx
|
||||||
|
* the open transaction
|
||||||
|
* @param type
|
||||||
|
* the type of the element to retrieve
|
||||||
|
* @param id
|
||||||
|
* the id of the element to retrieve
|
||||||
|
* @param assertExists
|
||||||
|
* if true, and element does not exist, then a {@link StrolchException} is thrown
|
||||||
|
*
|
||||||
|
* @return the element with the type and id, or null if it does not exist
|
||||||
|
*
|
||||||
|
* @throws StrolchException
|
||||||
|
* if the element does not exist
|
||||||
|
*/
|
||||||
|
public T getBy(StrolchTransaction tx, String type, String id, boolean assertExists) throws StrolchException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the specific version of the element with the given type and id, or null if it does not exist
|
||||||
|
*
|
||||||
|
* @param tx
|
||||||
|
* the open transaction
|
||||||
|
* @param type
|
||||||
|
* the type of the element to retrieve
|
||||||
|
* @param id
|
||||||
|
* the id of the element to retrieve
|
||||||
|
* @param version
|
||||||
|
* the version to get
|
||||||
|
*
|
||||||
|
* @return the element with the type and id, or null if it does not exist
|
||||||
|
*/
|
||||||
|
public T getBy(StrolchTransaction tx, String type, String id, int version);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the specific version of the element with the given type and id, or null if it does not exist
|
||||||
|
*
|
||||||
|
* @param tx
|
||||||
|
* the open transaction
|
||||||
|
* @param type
|
||||||
|
* the type of the element to retrieve
|
||||||
|
* @param id
|
||||||
|
* the id of the element to retrieve
|
||||||
|
* @param version
|
||||||
|
* the version to get
|
||||||
|
* @param assertExists
|
||||||
|
* if true, and element does not exist, then a {@link StrolchException} is thrown
|
||||||
|
*
|
||||||
|
* @return the element with the type and id, or null if it does not exist
|
||||||
|
*
|
||||||
|
* @throws StrolchException
|
||||||
|
* if the element does not exist
|
||||||
|
*/
|
||||||
|
public T getBy(StrolchTransaction tx, String type, String id, int version, boolean assertExists)
|
||||||
|
throws StrolchException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the element which is referenced by the given {@link StringParameter}. A reference {@link Parameter} must
|
* Returns the element which is referenced by the given {@link StringParameter}. A reference {@link Parameter} must
|
||||||
* have its interpretation set to the element type being referenced e.g. s
|
* have its interpretation set to the element type being referenced e.g. s
|
||||||
|
@ -105,29 +235,264 @@ public interface ElementMap<T extends StrolchRootElement> {
|
||||||
*/
|
*/
|
||||||
public List<T> getBy(StrolchTransaction tx, StringListParameter refP, boolean assertExists) throws StrolchException;
|
public List<T> getBy(StrolchTransaction tx, StringListParameter refP, boolean assertExists) throws StrolchException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries and returns all the versions of the element with the given type and ID
|
||||||
|
*
|
||||||
|
* @param tx
|
||||||
|
* the {@link StrolchTransaction} instance
|
||||||
|
* @param type
|
||||||
|
* the type of the element to be queried
|
||||||
|
* @param id
|
||||||
|
* the id of the element to be queried
|
||||||
|
*
|
||||||
|
* @return all the versions of the element with the given type and ID
|
||||||
|
*/
|
||||||
|
public List<T> getVersionsFor(StrolchTransaction tx, String type, String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all elements in the underlying persistence layer regardless of type
|
||||||
|
*
|
||||||
|
* @param tx
|
||||||
|
* the {@link StrolchTransaction} instance
|
||||||
|
*
|
||||||
|
* @return all elements in the underlying persistence layer regardless of type
|
||||||
|
*/
|
||||||
public List<T> getAllElements(StrolchTransaction tx);
|
public List<T> getAllElements(StrolchTransaction tx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all elements in the underlying persistence layer of the given type
|
||||||
|
*
|
||||||
|
* @param tx
|
||||||
|
* the {@link StrolchTransaction} instance
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* the type of the elements to retrieve
|
||||||
|
*
|
||||||
|
* @return all elements in the underlying persistence layer of the given type
|
||||||
|
*/
|
||||||
public List<T> getElementsBy(StrolchTransaction tx, String type);
|
public List<T> getElementsBy(StrolchTransaction tx, String type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the types known in the underlying persistence layer
|
||||||
|
*
|
||||||
|
* @param tx
|
||||||
|
* the {@link StrolchTransaction} instance
|
||||||
|
*
|
||||||
|
* @return all the types known in the underlying persistence layer
|
||||||
|
*/
|
||||||
public Set<String> getTypes(StrolchTransaction tx);
|
public Set<String> getTypes(StrolchTransaction tx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all keys/IDs of all elements in the underlying persistence layer, regardless of type
|
||||||
|
*
|
||||||
|
* @param tx
|
||||||
|
* the {@link StrolchTransaction} instance
|
||||||
|
*
|
||||||
|
* @return all keys/IDs of all elements in the underlying persistence layer, regardless of type
|
||||||
|
*/
|
||||||
public Set<String> getAllKeys(StrolchTransaction tx);
|
public Set<String> getAllKeys(StrolchTransaction tx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all keys/IDs of all elements in the underlying persistence layer, of the given type
|
||||||
|
*
|
||||||
|
* @param tx
|
||||||
|
* the {@link StrolchTransaction} instance
|
||||||
|
* @param type
|
||||||
|
* the type of the element to retrieve the keys for
|
||||||
|
*
|
||||||
|
* @return all keys/IDs of all elements in the underlying persistence layer, of the given type
|
||||||
|
*/
|
||||||
public Set<String> getKeysBy(StrolchTransaction tx, String type);
|
public Set<String> getKeysBy(StrolchTransaction tx, String type);
|
||||||
|
|
||||||
public void add(StrolchTransaction tx, T element);
|
/**
|
||||||
|
* Adds the given element to the underlying persistence layer. The element may not already exist
|
||||||
|
*
|
||||||
|
* @param tx
|
||||||
|
* the {@link StrolchTransaction} instance
|
||||||
|
* @param element
|
||||||
|
* the element to add
|
||||||
|
*
|
||||||
|
* @throws StrolchPersistenceException
|
||||||
|
* if an element already exists with the same ID
|
||||||
|
*/
|
||||||
|
public void add(StrolchTransaction tx, T element) throws StrolchPersistenceException;
|
||||||
|
|
||||||
public void addAll(StrolchTransaction tx, List<T> elements);
|
/**
|
||||||
|
* Adds the given elements to the underlying persistence layer. None of the elements may already exist
|
||||||
|
*
|
||||||
|
* @param tx
|
||||||
|
* the {@link StrolchTransaction} instance
|
||||||
|
* @param elements
|
||||||
|
* the elements to add
|
||||||
|
*
|
||||||
|
* @throws StrolchPersistenceException
|
||||||
|
* if an element already exists with the same ID
|
||||||
|
*/
|
||||||
|
public void addAll(StrolchTransaction tx, List<T> elements) throws StrolchPersistenceException;
|
||||||
|
|
||||||
public T update(StrolchTransaction tx, T element);
|
/**
|
||||||
|
* Updates the existing element
|
||||||
|
*
|
||||||
|
* @param tx
|
||||||
|
* the {@link StrolchTransaction} instance
|
||||||
|
* @param element
|
||||||
|
* the element to update
|
||||||
|
*
|
||||||
|
* @return the replaced element
|
||||||
|
*
|
||||||
|
* @throws StrolchPersistenceException
|
||||||
|
* if the element does not exist
|
||||||
|
*/
|
||||||
|
public void update(StrolchTransaction tx, T element) throws StrolchPersistenceException;
|
||||||
|
|
||||||
public List<T> updateAll(StrolchTransaction tx, List<T> elements);
|
/**
|
||||||
|
* Updates all the existing elements
|
||||||
|
*
|
||||||
|
* @param tx
|
||||||
|
* the {@link StrolchTransaction} instance
|
||||||
|
* @param elements
|
||||||
|
* the elements to update
|
||||||
|
*
|
||||||
|
* @return the replaced elements
|
||||||
|
*
|
||||||
|
* @throws StrolchPersistenceException
|
||||||
|
* if any of the elements don't yet exist
|
||||||
|
*/
|
||||||
|
public void updateAll(StrolchTransaction tx, List<T> elements) throws StrolchPersistenceException;
|
||||||
|
|
||||||
public void remove(StrolchTransaction tx, T element);
|
/**
|
||||||
|
* Removes the given element
|
||||||
|
*
|
||||||
|
* @param tx
|
||||||
|
* the {@link StrolchTransaction} instance
|
||||||
|
* @param element
|
||||||
|
* the element to be removed
|
||||||
|
*
|
||||||
|
* @throws StrolchPersistenceException
|
||||||
|
* if the element does not exist
|
||||||
|
*/
|
||||||
|
public void remove(StrolchTransaction tx, T element) throws StrolchPersistenceException;
|
||||||
|
|
||||||
public void removeAll(StrolchTransaction tx, List<T> elements);
|
/**
|
||||||
|
* Removes the given elements
|
||||||
|
*
|
||||||
|
* @param tx
|
||||||
|
* the {@link StrolchTransaction} instance
|
||||||
|
* @param elements
|
||||||
|
* the elements to be removed
|
||||||
|
*
|
||||||
|
* @throws StrolchPersistenceException
|
||||||
|
* if any of the elements don't yet exist
|
||||||
|
*/
|
||||||
|
public void removeAll(StrolchTransaction tx, List<T> elements) throws StrolchPersistenceException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Removes all elements regardless of the type
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* <b>Note:</b> This method ignores versioning. Do NOT call this method unless you want to clear the model!
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param tx
|
||||||
|
* the {@link StrolchTransaction} instance
|
||||||
|
*
|
||||||
|
* @return the number of elements removed
|
||||||
|
*/
|
||||||
public long removeAll(StrolchTransaction tx);
|
public long removeAll(StrolchTransaction tx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Removes all elements of the given type
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* <b>Note:</b> This method ignores versioning. Do NOT call this method unless you want to clear the model!
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param tx
|
||||||
|
* the {@link StrolchTransaction} instance
|
||||||
|
* @param type
|
||||||
|
* the type of elements to remove
|
||||||
|
*
|
||||||
|
* @return the number of elements removed
|
||||||
|
*/
|
||||||
public long removeAllBy(StrolchTransaction tx, String type);
|
public long removeAllBy(StrolchTransaction tx, String type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Undoes the given version by reverting to the previous version of the element given. If the element given is the
|
||||||
|
* first version, then the element is removed. If the previous version exists, then it is reverted to it. If the
|
||||||
|
* given element does not exist, nor it's previous version, then a {@link StrolchPersistenceException} is thrown
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* <b>Note:</b> This method should only be used in the same transaction where the element was created to undo a
|
||||||
|
* change in the same transaction. If there is a requirement to revert to a previous version, then the
|
||||||
|
* {@link #revertToVersion(StrolchTransaction, StrolchRootElement)} method.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param tx
|
||||||
|
* the {@link StrolchTransaction} instance
|
||||||
|
* @param element
|
||||||
|
* the element which is to be reverted to a previous version
|
||||||
|
*
|
||||||
|
* @throws StrolchException
|
||||||
|
* if the version does not exist, if this version is not the latest version, if the previous version is
|
||||||
|
* missing or other problems arise
|
||||||
|
*/
|
||||||
|
public void undoVersion(StrolchTransaction tx, T element) throws StrolchException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Reverts to the given version of the specified element. This method will retrieve the given version of the
|
||||||
|
* specified element, then set a new version on that element which is an increment of the current latest version and
|
||||||
|
* store this new version. The new element is then returned for convenience.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* <b>Note:</b> This is the method which should be called when a change should be reverted. This method gurantees
|
||||||
|
* that the history is not changed and that a new version is saved but with the version of the element specified.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param tx
|
||||||
|
* the {@link StrolchTransaction} instance
|
||||||
|
* @param element
|
||||||
|
* the version of the element to revert to
|
||||||
|
*
|
||||||
|
* @return the new version of the element
|
||||||
|
*
|
||||||
|
* @throws StrolchException
|
||||||
|
* if the version does not exist
|
||||||
|
*/
|
||||||
|
public T revertToVersion(StrolchTransaction tx, T element) throws StrolchException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Reverts to the given version of the specified element. This method will retrieve the given version of the
|
||||||
|
* specified element, then set a new version on that element which is an increment of the current latest version and
|
||||||
|
* store this new version. The new element is then returned for convenience.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* <b>Note:</b> This is the method which should be called when a change should be reverted. This method gurantees
|
||||||
|
* that the history is not changed and that a new version is saved but with the version of the element specified.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param tx
|
||||||
|
* the {@link StrolchTransaction} instance
|
||||||
|
* @param type
|
||||||
|
* the type of the element to revert to
|
||||||
|
* @param id
|
||||||
|
* the id of the element to revert to
|
||||||
|
* @param version
|
||||||
|
* the version of the specified element to revert to
|
||||||
|
*
|
||||||
|
* @return the new version of the element
|
||||||
|
*
|
||||||
|
* @throws StrolchException
|
||||||
|
* if the version does not exist
|
||||||
|
*/
|
||||||
|
public T revertToVersion(StrolchTransaction tx, String type, String id, int version) throws StrolchException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,5 +45,7 @@ public interface StrolchRealm {
|
||||||
|
|
||||||
public boolean isUpdateObservers();
|
public boolean isUpdateObservers();
|
||||||
|
|
||||||
|
public boolean isVersioningEnabled();
|
||||||
|
|
||||||
public ObserverHandler getObserverHandler();
|
public ObserverHandler getObserverHandler();
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,7 +137,15 @@ public class AuditingElementMapFacade<T extends StrolchRootElement> implements E
|
||||||
@Override
|
@Override
|
||||||
public T getTemplate(StrolchTransaction tx, String type) {
|
public T getTemplate(StrolchTransaction tx, String type) {
|
||||||
T template = this.elementMap.getTemplate(tx, type);
|
T template = this.elementMap.getTemplate(tx, type);
|
||||||
if (this.observeAccessReads)
|
if (this.observeAccessReads && template != null)
|
||||||
|
this.read.add(template);
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T getTemplate(StrolchTransaction tx, String type, boolean assertExists) throws StrolchException {
|
||||||
|
T template = this.elementMap.getTemplate(tx, type, assertExists);
|
||||||
|
if (this.observeAccessReads && template != null)
|
||||||
this.read.add(template);
|
this.read.add(template);
|
||||||
return template;
|
return template;
|
||||||
}
|
}
|
||||||
|
@ -145,7 +153,32 @@ public class AuditingElementMapFacade<T extends StrolchRootElement> implements E
|
||||||
@Override
|
@Override
|
||||||
public T getBy(StrolchTransaction tx, String type, String id) {
|
public T getBy(StrolchTransaction tx, String type, String id) {
|
||||||
T element = this.elementMap.getBy(tx, type, id);
|
T element = this.elementMap.getBy(tx, type, id);
|
||||||
if (this.observeAccessReads)
|
if (this.observeAccessReads && element != null)
|
||||||
|
this.read.add(element);
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T getBy(StrolchTransaction tx, String type, String id, boolean assertExists) throws StrolchException {
|
||||||
|
T element = this.elementMap.getBy(tx, type, id, assertExists);
|
||||||
|
if (this.observeAccessReads && element != null)
|
||||||
|
this.read.add(element);
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T getBy(StrolchTransaction tx, String type, String id, int version) {
|
||||||
|
T element = this.elementMap.getBy(tx, type, id, version);
|
||||||
|
if (this.observeAccessReads && element != null)
|
||||||
|
this.read.add(element);
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T getBy(StrolchTransaction tx, String type, String id, int version, boolean assertExists)
|
||||||
|
throws StrolchException {
|
||||||
|
T element = this.elementMap.getBy(tx, type, id, version, assertExists);
|
||||||
|
if (this.observeAccessReads && element != null)
|
||||||
this.read.add(element);
|
this.read.add(element);
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
@ -153,23 +186,32 @@ public class AuditingElementMapFacade<T extends StrolchRootElement> implements E
|
||||||
@Override
|
@Override
|
||||||
public T getBy(StrolchTransaction tx, StringParameter refP, boolean assertExists) throws StrolchException {
|
public T getBy(StrolchTransaction tx, StringParameter refP, boolean assertExists) throws StrolchException {
|
||||||
T element = this.elementMap.getBy(tx, refP, assertExists);
|
T element = this.elementMap.getBy(tx, refP, assertExists);
|
||||||
if (this.observeAccessReads)
|
if (this.observeAccessReads && element != null)
|
||||||
this.read.add(element);
|
this.read.add(element);
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<T> getBy(StrolchTransaction tx, StringListParameter refP, boolean assertExists) throws StrolchException {
|
public List<T> getBy(StrolchTransaction tx, StringListParameter refP, boolean assertExists)
|
||||||
|
throws StrolchException {
|
||||||
List<T> elements = this.elementMap.getBy(tx, refP, assertExists);
|
List<T> elements = this.elementMap.getBy(tx, refP, assertExists);
|
||||||
if (this.observeAccessReads)
|
if (this.observeAccessReads && !elements.isEmpty())
|
||||||
this.read.addAll(elements);
|
this.read.addAll(elements);
|
||||||
return elements;
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<T> getVersionsFor(StrolchTransaction tx, String type, String id) {
|
||||||
|
List<T> versions = this.elementMap.getVersionsFor(tx, type, id);
|
||||||
|
if (this.observeAccessReads && !versions.isEmpty())
|
||||||
|
this.read.add(versions.get(versions.size() - 1));
|
||||||
|
return versions;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<T> getAllElements(StrolchTransaction tx) {
|
public List<T> getAllElements(StrolchTransaction tx) {
|
||||||
List<T> elements = this.elementMap.getAllElements(tx);
|
List<T> elements = this.elementMap.getAllElements(tx);
|
||||||
if (this.observeAccessReads)
|
if (this.observeAccessReads && !elements.isEmpty())
|
||||||
this.read.addAll(elements);
|
this.read.addAll(elements);
|
||||||
return elements;
|
return elements;
|
||||||
}
|
}
|
||||||
|
@ -177,7 +219,7 @@ public class AuditingElementMapFacade<T extends StrolchRootElement> implements E
|
||||||
@Override
|
@Override
|
||||||
public List<T> getElementsBy(StrolchTransaction tx, String type) {
|
public List<T> getElementsBy(StrolchTransaction tx, String type) {
|
||||||
List<T> elements = this.elementMap.getElementsBy(tx, type);
|
List<T> elements = this.elementMap.getElementsBy(tx, type);
|
||||||
if (this.observeAccessReads)
|
if (this.observeAccessReads && !elements.isEmpty())
|
||||||
this.read.addAll(elements);
|
this.read.addAll(elements);
|
||||||
return elements;
|
return elements;
|
||||||
}
|
}
|
||||||
|
@ -210,18 +252,15 @@ public class AuditingElementMapFacade<T extends StrolchRootElement> implements E
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T update(StrolchTransaction tx, T element) {
|
public void update(StrolchTransaction tx, T element) {
|
||||||
T replaced = this.elementMap.update(tx, element);
|
this.elementMap.update(tx, element);
|
||||||
this.updated.add(element);
|
this.updated.add(element);
|
||||||
return replaced;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<T> updateAll(StrolchTransaction tx, List<T> elements) {
|
public void updateAll(StrolchTransaction tx, List<T> elements) {
|
||||||
List<T> replaced = this.elementMap.updateAll(tx, elements);
|
this.elementMap.updateAll(tx, elements);
|
||||||
this.updated.addAll(elements);
|
this.updated.addAll(elements);
|
||||||
return replaced;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -255,4 +294,27 @@ public class AuditingElementMapFacade<T extends StrolchRootElement> implements E
|
||||||
|
|
||||||
return removed;
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T revertToVersion(StrolchTransaction tx, String type, String id, int version) throws StrolchException {
|
||||||
|
T element = this.elementMap.revertToVersion(tx, type, id, version);
|
||||||
|
this.updated.add(element);
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T revertToVersion(StrolchTransaction tx, T element) throws StrolchException {
|
||||||
|
T revertedElement = this.elementMap.revertToVersion(tx, element);
|
||||||
|
this.updated.add(revertedElement);
|
||||||
|
return revertedElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void undoVersion(StrolchTransaction tx, T element) throws StrolchException {
|
||||||
|
this.elementMap.undoVersion(tx, element);
|
||||||
|
if (element.getVersion().isFirstVersion())
|
||||||
|
this.deleted.add(element);
|
||||||
|
else
|
||||||
|
this.updated.add(element);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import static li.strolch.model.StrolchModelConstants.INTERPRETATION_ACTIVITY_REF
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import li.strolch.agent.api.ActivityMap;
|
import li.strolch.agent.api.ActivityMap;
|
||||||
|
import li.strolch.agent.api.StrolchRealm;
|
||||||
import li.strolch.model.activity.Activity;
|
import li.strolch.model.activity.Activity;
|
||||||
import li.strolch.model.parameter.Parameter;
|
import li.strolch.model.parameter.Parameter;
|
||||||
import li.strolch.model.query.ActivityQuery;
|
import li.strolch.model.query.ActivityQuery;
|
||||||
|
@ -31,9 +32,10 @@ public class CachedActivityMap extends CachedElementMap<Activity> implements Act
|
||||||
|
|
||||||
private ActivityDao cachedDao;
|
private ActivityDao cachedDao;
|
||||||
|
|
||||||
public CachedActivityMap() {
|
public CachedActivityMap(StrolchRealm realm) {
|
||||||
super();
|
super(realm);
|
||||||
this.cachedDao = new InMemoryActivityDao();
|
// the cached DAO should not have versioning enabled
|
||||||
|
this.cachedDao = new InMemoryActivityDao(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -16,23 +16,27 @@
|
||||||
package li.strolch.agent.impl;
|
package li.strolch.agent.impl;
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import li.strolch.agent.api.ElementMap;
|
import li.strolch.agent.api.ElementMap;
|
||||||
|
import li.strolch.agent.api.StrolchRealm;
|
||||||
import li.strolch.exception.StrolchException;
|
import li.strolch.exception.StrolchException;
|
||||||
import li.strolch.model.StrolchRootElement;
|
import li.strolch.model.StrolchRootElement;
|
||||||
|
import li.strolch.model.Version;
|
||||||
import li.strolch.model.parameter.Parameter;
|
import li.strolch.model.parameter.Parameter;
|
||||||
import li.strolch.model.parameter.StringListParameter;
|
import li.strolch.model.parameter.StringListParameter;
|
||||||
import li.strolch.model.parameter.StringParameter;
|
import li.strolch.model.parameter.StringParameter;
|
||||||
import li.strolch.persistence.api.StrolchDao;
|
import li.strolch.persistence.api.StrolchDao;
|
||||||
|
import li.strolch.persistence.api.StrolchPersistenceException;
|
||||||
import li.strolch.persistence.api.StrolchTransaction;
|
import li.strolch.persistence.api.StrolchTransaction;
|
||||||
import li.strolch.runtime.StrolchConstants;
|
import li.strolch.runtime.StrolchConstants;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
*/
|
*/
|
||||||
|
@ -40,6 +44,16 @@ public abstract class CachedElementMap<T extends StrolchRootElement> implements
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(CachedElementMap.class);
|
private static final Logger logger = LoggerFactory.getLogger(CachedElementMap.class);
|
||||||
|
|
||||||
|
private StrolchRealm realm;
|
||||||
|
|
||||||
|
public CachedElementMap(StrolchRealm realm) {
|
||||||
|
this.realm = realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected StrolchRealm getRealm() {
|
||||||
|
return this.realm;
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract StrolchDao<T> getCachedDao();
|
protected abstract StrolchDao<T> getCachedDao();
|
||||||
|
|
||||||
protected abstract StrolchDao<T> getDbDao(StrolchTransaction tx);
|
protected abstract StrolchDao<T> getDbDao(StrolchTransaction tx);
|
||||||
|
@ -66,62 +80,110 @@ public abstract class CachedElementMap<T extends StrolchRootElement> implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized T getTemplate(StrolchTransaction tx, String type) {
|
public synchronized T getTemplate(StrolchTransaction tx, String type) {
|
||||||
return getBy(tx, StrolchConstants.TEMPLATE, type);
|
return getTemplate(tx, type, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T getTemplate(StrolchTransaction tx, String type, boolean assertExists) {
|
||||||
|
T t = getCachedDao().queryBy(StrolchConstants.TEMPLATE, type);
|
||||||
|
if (assertExists && t == null) {
|
||||||
|
String msg = "The template for type {0} does not exist!"; //$NON-NLS-1$
|
||||||
|
throw new StrolchException(MessageFormat.format(msg, type));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
T clone = (T) t.getClone();
|
||||||
|
clone.setVersion(t.getVersion());
|
||||||
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized T getBy(StrolchTransaction tx, String type, String id) {
|
public synchronized T getBy(StrolchTransaction tx, String type, String id) {
|
||||||
return getCachedDao().queryBy(type, id);
|
return getBy(tx, type, id, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void assertIsRefParam(Parameter<?> refP);
|
@Override
|
||||||
|
public T getBy(StrolchTransaction tx, String type, String id, boolean assertExists) throws StrolchException {
|
||||||
|
T t = getCachedDao().queryBy(type, id);
|
||||||
|
if (assertExists && t == null) {
|
||||||
|
String msg = "The element for type {0} and id {1} does not exist!"; //$NON-NLS-1$
|
||||||
|
throw new StrolchException(MessageFormat.format(msg, type, id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
T clone = (T) t.getClone();
|
||||||
|
clone.setVersion(t.getVersion());
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T getBy(StrolchTransaction tx, String type, String id, int version) {
|
||||||
|
return getBy(tx, type, id, version, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T getBy(StrolchTransaction tx, String type, String id, int version, boolean assertExists)
|
||||||
|
throws StrolchException {
|
||||||
|
T t = getDbDao(tx).queryBy(type, id, version);
|
||||||
|
if (assertExists && t == null) {
|
||||||
|
String msg = "The element for type {0} and id {1} and version {2} does not exist!"; //$NON-NLS-1$
|
||||||
|
msg = MessageFormat.format(msg, type, id, version);
|
||||||
|
throw new StrolchException(msg);
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T getBy(StrolchTransaction tx, StringParameter refP, boolean assertExists) throws StrolchException {
|
public T getBy(StrolchTransaction tx, StringParameter refP, boolean assertExists) throws StrolchException {
|
||||||
assertIsRefParam(refP);
|
assertIsRefParam(refP);
|
||||||
String type = refP.getUom();
|
String type = refP.getUom();
|
||||||
String id = refP.getValue();
|
String id = refP.getValue();
|
||||||
T element = getBy(tx, type, id);
|
return getBy(tx, type, id, assertExists);
|
||||||
if (assertExists && element == null) {
|
|
||||||
String msg = "The element for refP {0} with id {1} does not exist!"; //$NON-NLS-1$
|
|
||||||
msg = MessageFormat.format(msg, refP.getLocator(), id);
|
|
||||||
throw new StrolchException(msg);
|
|
||||||
}
|
|
||||||
return element;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<T> getBy(StrolchTransaction tx, StringListParameter refP, boolean assertExists) throws StrolchException {
|
public List<T> getBy(StrolchTransaction tx, StringListParameter refP, boolean assertExists)
|
||||||
|
throws StrolchException {
|
||||||
assertIsRefParam(refP);
|
assertIsRefParam(refP);
|
||||||
|
|
||||||
List<T> elements = new ArrayList<>();
|
|
||||||
String type = refP.getUom();
|
String type = refP.getUom();
|
||||||
List<String> ids = refP.getValue();
|
List<String> ids = refP.getValue();
|
||||||
|
|
||||||
for (String id : ids) {
|
return ids.stream().map(id -> getBy(tx, type, id, assertExists)).filter(Objects::nonNull)
|
||||||
T element = getBy(tx, type, id);
|
.collect(Collectors.toList());
|
||||||
if (element != null) {
|
|
||||||
elements.add(element);
|
|
||||||
} else if (assertExists) {
|
|
||||||
if (assertExists && element == null) {
|
|
||||||
String msg = "The element for refP {0} with id {1} does not exist!"; //$NON-NLS-1$
|
|
||||||
msg = MessageFormat.format(msg, refP.getLocator(), id);
|
|
||||||
throw new StrolchException(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return elements;
|
@Override
|
||||||
|
public List<T> getVersionsFor(StrolchTransaction tx, String type, String id) {
|
||||||
|
return getDbDao(tx).queryVersionsFor(type, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized List<T> getAllElements(StrolchTransaction tx) {
|
public synchronized List<T> getAllElements(StrolchTransaction tx) {
|
||||||
return getCachedDao().queryAll();
|
List<T> all = getCachedDao().queryAll();
|
||||||
|
return all.stream().map(t -> {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
T clone = (T) t.getClone();
|
||||||
|
clone.setVersion(t.getVersion());
|
||||||
|
return clone;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized List<T> getElementsBy(StrolchTransaction tx, String type) {
|
public synchronized List<T> getElementsBy(StrolchTransaction tx, String type) {
|
||||||
return getCachedDao().queryAll(type);
|
List<T> all = getCachedDao().queryAll(type);
|
||||||
|
return all.stream().map(t -> {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
T clone = (T) t.getClone();
|
||||||
|
clone.setVersion(t.getVersion());
|
||||||
|
return clone;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -139,14 +201,6 @@ public abstract class CachedElementMap<T extends StrolchRootElement> implements
|
||||||
return getCachedDao().queryKeySet(type);
|
return getCachedDao().queryKeySet(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void add(StrolchTransaction tx, T element) {
|
|
||||||
// first perform cached change
|
|
||||||
getCachedDao().save(element);
|
|
||||||
// last is to perform DB changes
|
|
||||||
getDbDao(tx).save(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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}
|
* {@link CachedRealm}
|
||||||
|
@ -158,27 +212,28 @@ public abstract class CachedElementMap<T extends StrolchRootElement> implements
|
||||||
getCachedDao().save(element);
|
getCachedDao().save(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO for update we should return the updated elements, or remove the return value
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized T update(StrolchTransaction tx, T element) {
|
public synchronized void add(StrolchTransaction tx, T element) {
|
||||||
|
if (realm.isVersioningEnabled())
|
||||||
|
Version.updateVersionFor(element, tx.getCertificate().getUsername(), false);
|
||||||
|
else
|
||||||
|
Version.setInitialVersionFor(element, tx.getCertificate().getUsername());
|
||||||
|
|
||||||
// first perform cached change
|
// first perform cached change
|
||||||
getCachedDao().update(element);
|
getCachedDao().save(element);
|
||||||
// last is to perform DB changes
|
// last is to perform DB changes
|
||||||
getDbDao(tx).update(element);
|
getDbDao(tx).save(element);
|
||||||
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void remove(StrolchTransaction tx, T element) {
|
|
||||||
// first perform cached change
|
|
||||||
getCachedDao().remove(element);
|
|
||||||
getDbDao(tx).remove(element);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void addAll(StrolchTransaction tx, List<T> elements) {
|
public synchronized void addAll(StrolchTransaction tx, List<T> elements) {
|
||||||
|
for (T element : elements) {
|
||||||
|
if (realm.isVersioningEnabled())
|
||||||
|
Version.updateVersionFor(element, tx.getCertificate().getUsername(), false);
|
||||||
|
else
|
||||||
|
Version.setInitialVersionFor(element, tx.getCertificate().getUsername());
|
||||||
|
}
|
||||||
|
|
||||||
// first perform cached change
|
// first perform cached change
|
||||||
getCachedDao().saveAll(elements);
|
getCachedDao().saveAll(elements);
|
||||||
// last is to perform DB changes
|
// last is to perform DB changes
|
||||||
|
@ -186,22 +241,80 @@ public abstract class CachedElementMap<T extends StrolchRootElement> implements
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized List<T> updateAll(StrolchTransaction tx, List<T> elements) {
|
public synchronized void update(StrolchTransaction tx, T element) {
|
||||||
|
if (realm.isVersioningEnabled())
|
||||||
|
Version.updateVersionFor(element, tx.getCertificate().getUsername(), false);
|
||||||
|
else
|
||||||
|
Version.setInitialVersionFor(element, tx.getCertificate().getUsername());
|
||||||
|
|
||||||
|
// first perform cached change
|
||||||
|
getCachedDao().update(element);
|
||||||
|
// last is to perform DB changes
|
||||||
|
getDbDao(tx).update(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void updateAll(StrolchTransaction tx, List<T> elements) {
|
||||||
|
for (T t : elements) {
|
||||||
|
if (realm.isVersioningEnabled())
|
||||||
|
Version.updateVersionFor(t, tx.getCertificate().getUsername(), false);
|
||||||
|
else
|
||||||
|
Version.setInitialVersionFor(t, tx.getCertificate().getUsername());
|
||||||
|
}
|
||||||
|
|
||||||
|
// first perform cached change
|
||||||
|
getCachedDao().updateAll(elements);
|
||||||
|
// last is to perform DB changes
|
||||||
|
getDbDao(tx).updateAll(elements);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void remove(StrolchTransaction tx, T element) {
|
||||||
|
if (realm.isVersioningEnabled())
|
||||||
|
Version.updateVersionFor(element, tx.getCertificate().getUsername(), true);
|
||||||
|
else
|
||||||
|
Version.setInitialVersionFor(element, tx.getCertificate().getUsername());
|
||||||
|
|
||||||
|
if (this.realm.isVersioningEnabled()) {
|
||||||
|
|
||||||
|
// first perform cached change
|
||||||
|
getCachedDao().update(element);
|
||||||
|
// last is to perform DB changes
|
||||||
|
getDbDao(tx).update(element);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// first perform cached change
|
||||||
|
getCachedDao().remove(element);
|
||||||
|
// last is to perform DB changes
|
||||||
|
getDbDao(tx).remove(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void removeAll(StrolchTransaction tx, List<T> elements) {
|
||||||
|
for (T t : elements) {
|
||||||
|
if (realm.isVersioningEnabled())
|
||||||
|
Version.updateVersionFor(t, tx.getCertificate().getUsername(), true);
|
||||||
|
else
|
||||||
|
Version.setInitialVersionFor(t, tx.getCertificate().getUsername());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.realm.isVersioningEnabled()) {
|
||||||
|
|
||||||
// first perform cached change
|
// first perform cached change
|
||||||
getCachedDao().updateAll(elements);
|
getCachedDao().updateAll(elements);
|
||||||
// last is to perform DB changes
|
// last is to perform DB changes
|
||||||
getDbDao(tx).updateAll(elements);
|
getDbDao(tx).updateAll(elements);
|
||||||
|
|
||||||
return elements;
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void removeAll(StrolchTransaction tx, List<T> elements) {
|
|
||||||
// first perform cached change
|
// first perform cached change
|
||||||
getCachedDao().removeAll(elements);
|
getCachedDao().removeAll(elements);
|
||||||
// last is to perform DB changes
|
// last is to perform DB changes
|
||||||
getDbDao(tx).removeAll(elements);
|
getDbDao(tx).removeAll(elements);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized long removeAll(StrolchTransaction tx) {
|
public synchronized long removeAll(StrolchTransaction tx) {
|
||||||
|
@ -232,4 +345,63 @@ public abstract class CachedElementMap<T extends StrolchRootElement> implements
|
||||||
|
|
||||||
return removed;
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T revertToVersion(StrolchTransaction tx, T element) throws StrolchException {
|
||||||
|
return revertToVersion(tx, element.getType(), element.getId(), element.getVersion().getVersion());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T revertToVersion(StrolchTransaction tx, String type, String id, int version) throws StrolchException {
|
||||||
|
if (!this.realm.isVersioningEnabled()) {
|
||||||
|
throw new StrolchPersistenceException("Can not und a version if versioning is not enabled!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the current and specified version
|
||||||
|
T current = getBy(tx, type, id, true);
|
||||||
|
T versionT = getBy(tx, type, id, version, true);
|
||||||
|
|
||||||
|
// create the new version
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
T clone = (T) versionT.getClone();
|
||||||
|
clone.setVersion(current.getVersion().next(tx.getCertificate().getUsername(), false));
|
||||||
|
|
||||||
|
// save the new version
|
||||||
|
getCachedDao().update(clone);
|
||||||
|
getDbDao(tx).update(clone);
|
||||||
|
|
||||||
|
// and return new version
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void undoVersion(StrolchTransaction tx, T element) throws StrolchException {
|
||||||
|
if (!this.realm.isVersioningEnabled()) {
|
||||||
|
throw new StrolchPersistenceException("Can not und a version if versioning is not enabled!");
|
||||||
|
}
|
||||||
|
|
||||||
|
String type = element.getType();
|
||||||
|
String id = element.getId();
|
||||||
|
|
||||||
|
Version elementVersion = element.getVersion();
|
||||||
|
|
||||||
|
// make sure the given element is the latest version
|
||||||
|
T current = getBy(tx, type, id, true);
|
||||||
|
if (!current.getVersion().equals(elementVersion)) {
|
||||||
|
String msg = "Can not undo the version {0} as it is not the latest!"; //$NON-NLS-1$
|
||||||
|
msg = MessageFormat.format(msg, elementVersion);
|
||||||
|
throw new StrolchException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elementVersion.isFirstVersion()) {
|
||||||
|
getCachedDao().remove(element);
|
||||||
|
getDbDao(tx).remove(element);
|
||||||
|
} else {
|
||||||
|
T previous = getBy(tx, type, id, elementVersion.getPreviousVersion(), false);
|
||||||
|
getCachedDao().update(previous);
|
||||||
|
getDbDao(tx).removeVersion(current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void assertIsRefParam(Parameter<?> refP);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import static li.strolch.model.StrolchModelConstants.INTERPRETATION_ORDER_REF;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import li.strolch.agent.api.OrderMap;
|
import li.strolch.agent.api.OrderMap;
|
||||||
|
import li.strolch.agent.api.StrolchRealm;
|
||||||
import li.strolch.model.Order;
|
import li.strolch.model.Order;
|
||||||
import li.strolch.model.parameter.Parameter;
|
import li.strolch.model.parameter.Parameter;
|
||||||
import li.strolch.model.query.OrderQuery;
|
import li.strolch.model.query.OrderQuery;
|
||||||
|
@ -31,9 +32,10 @@ public class CachedOrderMap extends CachedElementMap<Order> implements OrderMap
|
||||||
|
|
||||||
private OrderDao cachedDao;
|
private OrderDao cachedDao;
|
||||||
|
|
||||||
public CachedOrderMap() {
|
public CachedOrderMap(StrolchRealm realm) {
|
||||||
super();
|
super(realm);
|
||||||
this.cachedDao = new InMemoryOrderDao();
|
// the cached DAO should not have versioning enabled
|
||||||
|
this.cachedDao = new InMemoryOrderDao(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -95,17 +95,14 @@ public class CachedRealm extends InternalStrolchRealm {
|
||||||
super.initialize(container, configuration);
|
super.initialize(container, configuration);
|
||||||
|
|
||||||
this.persistenceHandler = container.getComponent(PersistenceHandler.class);
|
this.persistenceHandler = container.getComponent(PersistenceHandler.class);
|
||||||
this.resourceMap = new CachedResourceMap();
|
this.resourceMap = new CachedResourceMap(this);
|
||||||
this.orderMap = new CachedOrderMap();
|
this.orderMap = new CachedOrderMap(this);
|
||||||
this.activityMap = new CachedActivityMap();
|
this.activityMap = new CachedActivityMap(this);
|
||||||
|
|
||||||
if (isAuditTrailEnabled()) {
|
if (isAuditTrailEnabled())
|
||||||
this.auditTrail = new CachedAuditTrail();
|
this.auditTrail = new CachedAuditTrail();
|
||||||
logger.info("Enabling AuditTrail for realm " + getRealm()); //$NON-NLS-1$
|
else
|
||||||
} else {
|
|
||||||
this.auditTrail = new NoStrategyAuditTrail();
|
this.auditTrail = new NoStrategyAuditTrail();
|
||||||
logger.info("AuditTrail is disabled for realm " + getRealm()); //$NON-NLS-1$
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -20,6 +20,7 @@ import static li.strolch.model.StrolchModelConstants.INTERPRETATION_RESOURCE_REF
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import li.strolch.agent.api.ResourceMap;
|
import li.strolch.agent.api.ResourceMap;
|
||||||
|
import li.strolch.agent.api.StrolchRealm;
|
||||||
import li.strolch.model.Resource;
|
import li.strolch.model.Resource;
|
||||||
import li.strolch.model.parameter.Parameter;
|
import li.strolch.model.parameter.Parameter;
|
||||||
import li.strolch.model.query.ResourceQuery;
|
import li.strolch.model.query.ResourceQuery;
|
||||||
|
@ -31,9 +32,10 @@ public class CachedResourceMap extends CachedElementMap<Resource> implements Res
|
||||||
|
|
||||||
private ResourceDao cachedDao;
|
private ResourceDao cachedDao;
|
||||||
|
|
||||||
public CachedResourceMap() {
|
public CachedResourceMap(StrolchRealm realm) {
|
||||||
super();
|
super(realm);
|
||||||
this.cachedDao = new InMemoryResourceDao();
|
// the cached DAO should not have versioning enabled
|
||||||
|
this.cachedDao = new InMemoryResourceDao(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -39,6 +39,7 @@ public class DefaultRealmHandler extends StrolchComponent implements RealmHandle
|
||||||
public static final String PROP_ENABLE_AUDIT_TRAIL = "enableAuditTrail"; //$NON-NLS-1$
|
public static final String PROP_ENABLE_AUDIT_TRAIL = "enableAuditTrail"; //$NON-NLS-1$
|
||||||
public static final String PROP_ENABLE_AUDIT_TRAIL_FOR_READ = "enableAuditTrailForRead"; //$NON-NLS-1$
|
public static final String PROP_ENABLE_AUDIT_TRAIL_FOR_READ = "enableAuditTrailForRead"; //$NON-NLS-1$
|
||||||
public static final String PROP_ENABLE_OBSERVER_UPDATES = "enableObserverUpdates"; //$NON-NLS-1$
|
public static final String PROP_ENABLE_OBSERVER_UPDATES = "enableObserverUpdates"; //$NON-NLS-1$
|
||||||
|
public static final String PROP_ENABLE_VERSIONING = "enableVersioning"; //$NON-NLS-1$
|
||||||
public static final String PREFIX_DATA_STORE_MODE = "dataStoreMode"; //$NON-NLS-1$
|
public static final String PREFIX_DATA_STORE_MODE = "dataStoreMode"; //$NON-NLS-1$
|
||||||
public static final String PREFIX_DATA_STORE_FILE = "dataStoreFile"; //$NON-NLS-1$
|
public static final String PREFIX_DATA_STORE_FILE = "dataStoreFile"; //$NON-NLS-1$
|
||||||
public static final String PROP_REALMS = "realms"; //$NON-NLS-1$
|
public static final String PROP_REALMS = "realms"; //$NON-NLS-1$
|
||||||
|
@ -76,9 +77,11 @@ public class DefaultRealmHandler extends StrolchComponent implements RealmHandle
|
||||||
this.realms = new HashMap<>();
|
this.realms = new HashMap<>();
|
||||||
String[] realms = configuration.getStringArray(PROP_REALMS, StrolchConstants.DEFAULT_REALM);
|
String[] realms = configuration.getStringArray(PROP_REALMS, StrolchConstants.DEFAULT_REALM);
|
||||||
for (String realmName : realms) {
|
for (String realmName : realms) {
|
||||||
|
|
||||||
String dataStoreModeKey = StrolchConstants.makeRealmKey(realmName, PREFIX_DATA_STORE_MODE);
|
String dataStoreModeKey = StrolchConstants.makeRealmKey(realmName, PREFIX_DATA_STORE_MODE);
|
||||||
String realmMode = configuration.getString(dataStoreModeKey, null);
|
String realmMode = configuration.getString(dataStoreModeKey, null);
|
||||||
DataStoreMode dataStoreMode = DataStoreMode.parseDataStoreMode(realmMode);
|
DataStoreMode dataStoreMode = DataStoreMode.parseDataStoreMode(realmMode);
|
||||||
|
|
||||||
InternalStrolchRealm realm = dataStoreMode.createRealm(realmName);
|
InternalStrolchRealm realm = dataStoreMode.createRealm(realmName);
|
||||||
this.realms.put(realmName, realm);
|
this.realms.put(realmName, realm);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,6 @@ import li.strolch.persistence.api.StrolchTransaction;
|
||||||
import li.strolch.persistence.inmemory.InMemoryPersistence;
|
import li.strolch.persistence.inmemory.InMemoryPersistence;
|
||||||
import li.strolch.privilege.model.Certificate;
|
import li.strolch.privilege.model.Certificate;
|
||||||
import li.strolch.privilege.model.PrivilegeContext;
|
import li.strolch.privilege.model.PrivilegeContext;
|
||||||
import li.strolch.runtime.StrolchConstants;
|
|
||||||
import li.strolch.runtime.configuration.ComponentConfiguration;
|
import li.strolch.runtime.configuration.ComponentConfiguration;
|
||||||
import li.strolch.utils.dbc.DBC;
|
import li.strolch.utils.dbc.DBC;
|
||||||
|
|
||||||
|
@ -86,18 +85,15 @@ public class EmptyRealm extends InternalStrolchRealm {
|
||||||
@Override
|
@Override
|
||||||
public void initialize(ComponentContainer container, ComponentConfiguration configuration) {
|
public void initialize(ComponentContainer container, ComponentConfiguration configuration) {
|
||||||
super.initialize(container, configuration);
|
super.initialize(container, configuration);
|
||||||
this.persistenceHandler = new InMemoryPersistence(container.getPrivilegeHandler());
|
this.persistenceHandler = new InMemoryPersistence(container.getPrivilegeHandler(), isVersioningEnabled());
|
||||||
this.resourceMap = new TransactionalResourceMap();
|
this.resourceMap = new TransactionalResourceMap(this);
|
||||||
this.orderMap = new TransactionalOrderMap();
|
this.orderMap = new TransactionalOrderMap(this);
|
||||||
|
this.activityMap = new TransactionalActivityMap(this);
|
||||||
|
|
||||||
String enableAuditKey = StrolchConstants.makeRealmKey(getRealm(), DefaultRealmHandler.PROP_ENABLE_AUDIT_TRAIL);
|
if (isAuditTrailEnabled())
|
||||||
if (configuration.getBoolean(enableAuditKey, Boolean.FALSE)) {
|
|
||||||
this.auditTrail = new TransactionalAuditTrail();
|
this.auditTrail = new TransactionalAuditTrail();
|
||||||
logger.info("Enabling AuditTrail for realm " + getRealm()); //$NON-NLS-1$
|
else
|
||||||
} else {
|
|
||||||
this.auditTrail = new NoStrategyAuditTrail();
|
this.auditTrail = new NoStrategyAuditTrail();
|
||||||
logger.info("AuditTrail is disabled for realm " + getRealm()); //$NON-NLS-1$
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -15,9 +15,17 @@
|
||||||
*/
|
*/
|
||||||
package li.strolch.agent.impl;
|
package li.strolch.agent.impl;
|
||||||
|
|
||||||
|
import static li.strolch.agent.impl.DefaultRealmHandler.PROP_ENABLE_AUDIT_TRAIL;
|
||||||
|
import static li.strolch.agent.impl.DefaultRealmHandler.PROP_ENABLE_AUDIT_TRAIL_FOR_READ;
|
||||||
|
import static li.strolch.agent.impl.DefaultRealmHandler.PROP_ENABLE_OBSERVER_UPDATES;
|
||||||
|
import static li.strolch.agent.impl.DefaultRealmHandler.PROP_ENABLE_VERSIONING;
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import li.strolch.agent.api.ActivityMap;
|
import li.strolch.agent.api.ActivityMap;
|
||||||
import li.strolch.agent.api.AuditTrail;
|
import li.strolch.agent.api.AuditTrail;
|
||||||
import li.strolch.agent.api.ComponentContainer;
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
|
@ -32,9 +40,6 @@ import li.strolch.runtime.StrolchConstants;
|
||||||
import li.strolch.runtime.configuration.ComponentConfiguration;
|
import li.strolch.runtime.configuration.ComponentConfiguration;
|
||||||
import li.strolch.utils.dbc.DBC;
|
import li.strolch.utils.dbc.DBC;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
*/
|
*/
|
||||||
|
@ -47,6 +52,7 @@ public abstract class InternalStrolchRealm implements StrolchRealm {
|
||||||
private LockHandler lockHandler;
|
private LockHandler lockHandler;
|
||||||
private boolean auditTrailEnabled;
|
private boolean auditTrailEnabled;
|
||||||
private boolean auditTrailEnabledForRead;
|
private boolean auditTrailEnabledForRead;
|
||||||
|
private boolean versioningEnabled;
|
||||||
private boolean updateObservers;
|
private boolean updateObservers;
|
||||||
private ObserverHandler observerHandler;
|
private ObserverHandler observerHandler;
|
||||||
|
|
||||||
|
@ -78,26 +84,51 @@ public abstract class InternalStrolchRealm implements StrolchRealm {
|
||||||
|
|
||||||
public void initialize(ComponentContainer container, ComponentConfiguration configuration) {
|
public void initialize(ComponentContainer container, ComponentConfiguration configuration) {
|
||||||
|
|
||||||
String propTryLockTimeUnit = StrolchConstants.makeRealmKey(this.realm, PROP_TRY_LOCK_TIME_UNIT);
|
logger.info("Initializing Realm " + getRealm() + "...");
|
||||||
String propTryLockTime = StrolchConstants.makeRealmKey(this.realm, PROP_TRY_LOCK_TIME);
|
|
||||||
|
|
||||||
String enableAuditKey = StrolchConstants.makeRealmKey(getRealm(), DefaultRealmHandler.PROP_ENABLE_AUDIT_TRAIL);
|
// audits
|
||||||
|
String enableAuditKey = StrolchConstants.makeRealmKey(getRealm(), PROP_ENABLE_AUDIT_TRAIL);
|
||||||
this.auditTrailEnabled = configuration.getBoolean(enableAuditKey, Boolean.FALSE);
|
this.auditTrailEnabled = configuration.getBoolean(enableAuditKey, Boolean.FALSE);
|
||||||
|
|
||||||
String enableAuditForReadKey = StrolchConstants.makeRealmKey(getRealm(),
|
// audits for read
|
||||||
DefaultRealmHandler.PROP_ENABLE_AUDIT_TRAIL_FOR_READ);
|
String enableAuditForReadKey = StrolchConstants.makeRealmKey(getRealm(), PROP_ENABLE_AUDIT_TRAIL_FOR_READ);
|
||||||
this.auditTrailEnabledForRead = configuration.getBoolean(enableAuditForReadKey, Boolean.FALSE);
|
this.auditTrailEnabledForRead = configuration.getBoolean(enableAuditForReadKey, Boolean.FALSE);
|
||||||
|
|
||||||
String updateObserversKey = StrolchConstants.makeRealmKey(getRealm(),
|
// observer updates
|
||||||
DefaultRealmHandler.PROP_ENABLE_OBSERVER_UPDATES);
|
String updateObserversKey = StrolchConstants.makeRealmKey(getRealm(), PROP_ENABLE_OBSERVER_UPDATES);
|
||||||
this.updateObservers = configuration.getBoolean(updateObserversKey, Boolean.FALSE);
|
this.updateObservers = configuration.getBoolean(updateObserversKey, Boolean.FALSE);
|
||||||
if (this.updateObservers)
|
if (this.updateObservers)
|
||||||
this.observerHandler = new DefaultObserverHandler();
|
this.observerHandler = new DefaultObserverHandler();
|
||||||
|
|
||||||
|
// lock timeout
|
||||||
|
String propTryLockTimeUnit = StrolchConstants.makeRealmKey(this.realm, PROP_TRY_LOCK_TIME_UNIT);
|
||||||
|
String propTryLockTime = StrolchConstants.makeRealmKey(this.realm, PROP_TRY_LOCK_TIME);
|
||||||
TimeUnit timeUnit = TimeUnit.valueOf(configuration.getString(propTryLockTimeUnit, TimeUnit.SECONDS.name()));
|
TimeUnit timeUnit = TimeUnit.valueOf(configuration.getString(propTryLockTimeUnit, TimeUnit.SECONDS.name()));
|
||||||
long time = configuration.getLong(propTryLockTime, 10);
|
long time = configuration.getLong(propTryLockTime, 10);
|
||||||
logger.info(MessageFormat.format("Using a locking try timeout of {0}s", timeUnit.toSeconds(time))); //$NON-NLS-1$
|
|
||||||
this.lockHandler = new DefaultLockHandler(this.realm, timeUnit, time);
|
this.lockHandler = new DefaultLockHandler(this.realm, timeUnit, time);
|
||||||
|
|
||||||
|
// versioning
|
||||||
|
String enableVersioningKey = StrolchConstants.makeRealmKey(getRealm(), PROP_ENABLE_VERSIONING);
|
||||||
|
this.versioningEnabled = configuration.getBoolean(enableVersioningKey, Boolean.FALSE);
|
||||||
|
|
||||||
|
if (this.auditTrailEnabled)
|
||||||
|
logger.info("Enabling AuditTrail for realm " + getRealm()); //$NON-NLS-1$
|
||||||
|
else
|
||||||
|
logger.info("AuditTrail not enabled for realm " + getRealm()); //$NON-NLS-1$
|
||||||
|
if (this.auditTrailEnabledForRead)
|
||||||
|
logger.info("Enabling AuditTrail for read for realm " + getRealm()); //$NON-NLS-1$
|
||||||
|
else
|
||||||
|
logger.info("AuditTrail not enabled for read for realm " + getRealm()); //$NON-NLS-1$
|
||||||
|
if (this.updateObservers)
|
||||||
|
logger.info("Enabling Observer Updates for realm " + getRealm()); //$NON-NLS-1$
|
||||||
|
else
|
||||||
|
logger.info("Observer Updates not enabled for realm " + getRealm()); //$NON-NLS-1$
|
||||||
|
if (this.versioningEnabled)
|
||||||
|
logger.info("Enabling Versioning for realm " + getRealm()); //$NON-NLS-1$
|
||||||
|
else
|
||||||
|
logger.info("Versioning not enabled for realm " + getRealm()); //$NON-NLS-1$
|
||||||
|
|
||||||
|
logger.info(MessageFormat.format("Using a locking try timeout of {0}s", timeUnit.toSeconds(time))); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -115,6 +146,11 @@ public abstract class InternalStrolchRealm implements StrolchRealm {
|
||||||
return this.updateObservers;
|
return this.updateObservers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isVersioningEnabled() {
|
||||||
|
return this.versioningEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ObserverHandler getObserverHandler() {
|
public ObserverHandler getObserverHandler() {
|
||||||
if (!this.updateObservers)
|
if (!this.updateObservers)
|
||||||
|
|
|
@ -20,6 +20,7 @@ import static li.strolch.model.StrolchModelConstants.INTERPRETATION_ACTIVITY_REF
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import li.strolch.agent.api.ActivityMap;
|
import li.strolch.agent.api.ActivityMap;
|
||||||
|
import li.strolch.agent.api.StrolchRealm;
|
||||||
import li.strolch.model.activity.Activity;
|
import li.strolch.model.activity.Activity;
|
||||||
import li.strolch.model.parameter.Parameter;
|
import li.strolch.model.parameter.Parameter;
|
||||||
import li.strolch.model.query.ActivityQuery;
|
import li.strolch.model.query.ActivityQuery;
|
||||||
|
@ -28,6 +29,10 @@ import li.strolch.persistence.api.StrolchTransaction;
|
||||||
|
|
||||||
public class TransactionalActivityMap extends TransactionalElementMap<Activity> implements ActivityMap {
|
public class TransactionalActivityMap extends TransactionalElementMap<Activity> implements ActivityMap {
|
||||||
|
|
||||||
|
public TransactionalActivityMap(StrolchRealm realm) {
|
||||||
|
super(realm);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void assertIsRefParam(Parameter<?> refP) {
|
protected void assertIsRefParam(Parameter<?> refP) {
|
||||||
ElementMapHelpers.assertIsRefParam(INTERPRETATION_ACTIVITY_REF, refP);
|
ElementMapHelpers.assertIsRefParam(INTERPRETATION_ACTIVITY_REF, refP);
|
||||||
|
|
|
@ -16,17 +16,21 @@
|
||||||
package li.strolch.agent.impl;
|
package li.strolch.agent.impl;
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import li.strolch.agent.api.ElementMap;
|
import li.strolch.agent.api.ElementMap;
|
||||||
|
import li.strolch.agent.api.StrolchRealm;
|
||||||
import li.strolch.exception.StrolchException;
|
import li.strolch.exception.StrolchException;
|
||||||
import li.strolch.model.StrolchRootElement;
|
import li.strolch.model.StrolchRootElement;
|
||||||
|
import li.strolch.model.Version;
|
||||||
import li.strolch.model.parameter.Parameter;
|
import li.strolch.model.parameter.Parameter;
|
||||||
import li.strolch.model.parameter.StringListParameter;
|
import li.strolch.model.parameter.StringListParameter;
|
||||||
import li.strolch.model.parameter.StringParameter;
|
import li.strolch.model.parameter.StringParameter;
|
||||||
import li.strolch.persistence.api.StrolchDao;
|
import li.strolch.persistence.api.StrolchDao;
|
||||||
|
import li.strolch.persistence.api.StrolchPersistenceException;
|
||||||
import li.strolch.persistence.api.StrolchTransaction;
|
import li.strolch.persistence.api.StrolchTransaction;
|
||||||
import li.strolch.runtime.StrolchConstants;
|
import li.strolch.runtime.StrolchConstants;
|
||||||
|
|
||||||
|
@ -37,6 +41,16 @@ import li.strolch.runtime.StrolchConstants;
|
||||||
*/
|
*/
|
||||||
public abstract class TransactionalElementMap<T extends StrolchRootElement> implements ElementMap<T> {
|
public abstract class TransactionalElementMap<T extends StrolchRootElement> implements ElementMap<T> {
|
||||||
|
|
||||||
|
private StrolchRealm realm;
|
||||||
|
|
||||||
|
public TransactionalElementMap(StrolchRealm realm) {
|
||||||
|
this.realm = realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected StrolchRealm getRealm() {
|
||||||
|
return this.realm;
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract StrolchDao<T> getDao(StrolchTransaction tx);
|
protected abstract StrolchDao<T> getDao(StrolchTransaction tx);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -61,62 +75,160 @@ public abstract class TransactionalElementMap<T extends StrolchRootElement> impl
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T getTemplate(StrolchTransaction tx, String type) {
|
public T getTemplate(StrolchTransaction tx, String type) {
|
||||||
return getBy(tx, StrolchConstants.TEMPLATE, type);
|
return getTemplate(tx, type, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T getTemplate(StrolchTransaction tx, String type, boolean assertExists) throws StrolchException {
|
||||||
|
T t = getBy(tx, StrolchConstants.TEMPLATE, type);
|
||||||
|
if (assertExists && t == null) {
|
||||||
|
String msg = "The template for type {0} does not exist!"; //$NON-NLS-1$
|
||||||
|
msg = MessageFormat.format(msg, type);
|
||||||
|
throw new StrolchException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
T clone = (T) t.getClone();
|
||||||
|
clone.setVersion(t.getVersion());
|
||||||
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T getBy(StrolchTransaction tx, String type, String id) {
|
public T getBy(StrolchTransaction tx, String type, String id) {
|
||||||
return getDao(tx).queryBy(type, id);
|
return getBy(tx, type, id, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void assertIsRefParam(Parameter<?> refP);
|
@Override
|
||||||
|
public T getBy(StrolchTransaction tx, String type, String id, boolean assertExists) throws StrolchException {
|
||||||
|
T t = getDao(tx).queryBy(type, id);
|
||||||
|
if (assertExists && t == null) {
|
||||||
|
String msg = "The element for type {0} and id {1} does not exist!"; //$NON-NLS-1$
|
||||||
|
msg = MessageFormat.format(msg, type, id);
|
||||||
|
throw new StrolchException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (!this.realm.getMode().isTransient())
|
||||||
|
return t;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
T clone = (T) t.getClone();
|
||||||
|
clone.setVersion(t.getVersion());
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T getBy(StrolchTransaction tx, String type, String id, int version) {
|
||||||
|
return getBy(tx, type, id, version, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T getBy(StrolchTransaction tx, String type, String id, int version, boolean assertExists)
|
||||||
|
throws StrolchException {
|
||||||
|
T t = getDao(tx).queryBy(type, id, version);
|
||||||
|
if (assertExists && t == null) {
|
||||||
|
String msg = "The element for type {0} and id {1} and version {2} does not exist!"; //$NON-NLS-1$
|
||||||
|
msg = MessageFormat.format(msg, type, id, version);
|
||||||
|
throw new StrolchException(msg);
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T getBy(StrolchTransaction tx, StringParameter refP, boolean assertExists) throws StrolchException {
|
public T getBy(StrolchTransaction tx, StringParameter refP, boolean assertExists) throws StrolchException {
|
||||||
assertIsRefParam(refP);
|
assertIsRefParam(refP);
|
||||||
String type = refP.getUom();
|
String type = refP.getUom();
|
||||||
String id = refP.getValue();
|
String id = refP.getValue();
|
||||||
T element = getBy(tx, type, id);
|
T t = getBy(tx, type, id);
|
||||||
if (assertExists && element == null) {
|
if (assertExists && t == null) {
|
||||||
String msg = "The element for refP {0} with id {1} does not exist!"; //$NON-NLS-1$
|
String msg = "The element for refP {0} with id {1} does not exist!"; //$NON-NLS-1$
|
||||||
msg = MessageFormat.format(msg, refP.getLocator(), id);
|
msg = MessageFormat.format(msg, refP.getLocator(), id);
|
||||||
throw new StrolchException(msg);
|
throw new StrolchException(msg);
|
||||||
}
|
}
|
||||||
return element;
|
|
||||||
|
if (t == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (!this.realm.getMode().isTransient())
|
||||||
|
return t;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
T clone = (T) t.getClone();
|
||||||
|
clone.setVersion(t.getVersion());
|
||||||
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<T> getBy(StrolchTransaction tx, StringListParameter refP, boolean assertExists) throws StrolchException {
|
public List<T> getBy(StrolchTransaction tx, StringListParameter refP, boolean assertExists)
|
||||||
|
throws StrolchException {
|
||||||
assertIsRefParam(refP);
|
assertIsRefParam(refP);
|
||||||
|
|
||||||
List<T> elements = new ArrayList<>();
|
|
||||||
String type = refP.getUom();
|
String type = refP.getUom();
|
||||||
List<String> ids = refP.getValue();
|
List<String> ids = refP.getValue();
|
||||||
|
|
||||||
for (String id : ids) {
|
return ids.stream().map(id -> {
|
||||||
T element = getBy(tx, type, id);
|
T t = getBy(tx, type, id);
|
||||||
if (element != null) {
|
if (assertExists && t == null) {
|
||||||
elements.add(element);
|
|
||||||
} else if (assertExists) {
|
|
||||||
if (assertExists && element == null) {
|
|
||||||
String msg = "The element for refP {0} with id {1} does not exist!"; //$NON-NLS-1$
|
String msg = "The element for refP {0} with id {1} does not exist!"; //$NON-NLS-1$
|
||||||
msg = MessageFormat.format(msg, refP.getLocator(), id);
|
msg = MessageFormat.format(msg, refP.getLocator(), id);
|
||||||
throw new StrolchException(msg);
|
throw new StrolchException(msg);
|
||||||
}
|
}
|
||||||
|
return t;
|
||||||
|
}).filter(Objects::nonNull).map(t -> {
|
||||||
|
if (!this.realm.getMode().isTransient()) {
|
||||||
|
return t;
|
||||||
|
} else {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
T clone = (T) t.getClone();
|
||||||
|
clone.setVersion(t.getVersion());
|
||||||
|
return clone;
|
||||||
}
|
}
|
||||||
|
}).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
return elements;
|
@Override
|
||||||
|
public List<T> getVersionsFor(StrolchTransaction tx, String type, String id) {
|
||||||
|
return getDao(tx).queryVersionsFor(type, id).stream().map(t -> {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
T clone = (T) t.getClone();
|
||||||
|
clone.setVersion(t.getVersion());
|
||||||
|
return clone;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<T> getAllElements(StrolchTransaction tx) {
|
public List<T> getAllElements(StrolchTransaction tx) {
|
||||||
return getDao(tx).queryAll();
|
List<T> all = getDao(tx).queryAll();
|
||||||
|
|
||||||
|
if (this.realm.getMode().isTransient())
|
||||||
|
return all;
|
||||||
|
|
||||||
|
return all.stream().map(t -> {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
T clone = (T) t.getClone();
|
||||||
|
clone.setVersion(t.getVersion());
|
||||||
|
return clone;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<T> getElementsBy(StrolchTransaction tx, String type) {
|
public List<T> getElementsBy(StrolchTransaction tx, String type) {
|
||||||
return getDao(tx).queryAll(type);
|
List<T> all = getDao(tx).queryAll(type);
|
||||||
|
|
||||||
|
if (this.realm.getMode().isTransient())
|
||||||
|
return all;
|
||||||
|
|
||||||
|
return all.stream().map(t -> {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
T clone = (T) t.getClone();
|
||||||
|
clone.setVersion(t.getVersion());
|
||||||
|
return clone;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -136,35 +248,74 @@ public abstract class TransactionalElementMap<T extends StrolchRootElement> impl
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void add(StrolchTransaction tx, T element) {
|
public void add(StrolchTransaction tx, T element) {
|
||||||
|
if (realm.isVersioningEnabled())
|
||||||
|
Version.updateVersionFor(element, tx.getCertificate().getUsername(), false);
|
||||||
|
else
|
||||||
|
Version.setInitialVersionFor(element, tx.getCertificate().getUsername());
|
||||||
|
|
||||||
getDao(tx).save(element);
|
getDao(tx).save(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public T update(StrolchTransaction tx, T element) {
|
|
||||||
getDao(tx).update(element);
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void remove(StrolchTransaction tx, T element) {
|
|
||||||
getDao(tx).remove(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addAll(StrolchTransaction tx, List<T> elements) {
|
public void addAll(StrolchTransaction tx, List<T> elements) {
|
||||||
|
for (T element : elements) {
|
||||||
|
if (realm.isVersioningEnabled())
|
||||||
|
Version.updateVersionFor(element, tx.getCertificate().getUsername(), false);
|
||||||
|
else
|
||||||
|
Version.setInitialVersionFor(element, tx.getCertificate().getUsername());
|
||||||
|
}
|
||||||
|
|
||||||
getDao(tx).saveAll(elements);
|
getDao(tx).saveAll(elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<T> updateAll(StrolchTransaction tx, List<T> elements) {
|
public void update(StrolchTransaction tx, T element) {
|
||||||
|
if (realm.isVersioningEnabled())
|
||||||
|
Version.updateVersionFor(element, tx.getCertificate().getUsername(), false);
|
||||||
|
else
|
||||||
|
Version.setInitialVersionFor(element, tx.getCertificate().getUsername());
|
||||||
|
|
||||||
|
getDao(tx).update(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateAll(StrolchTransaction tx, List<T> elements) {
|
||||||
|
for (T element : elements) {
|
||||||
|
if (realm.isVersioningEnabled())
|
||||||
|
Version.updateVersionFor(element, tx.getCertificate().getUsername(), false);
|
||||||
|
else
|
||||||
|
Version.setInitialVersionFor(element, tx.getCertificate().getUsername());
|
||||||
|
}
|
||||||
|
|
||||||
getDao(tx).updateAll(elements);
|
getDao(tx).updateAll(elements);
|
||||||
return elements;
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(StrolchTransaction tx, T element) {
|
||||||
|
if (this.realm.isVersioningEnabled()) {
|
||||||
|
Version.updateVersionFor(element, tx.getCertificate().getUsername(), true);
|
||||||
|
getDao(tx).update(element);
|
||||||
|
} else {
|
||||||
|
Version.setInitialVersionFor(element, tx.getCertificate().getUsername());
|
||||||
|
getDao(tx).remove(element);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeAll(StrolchTransaction tx, List<T> elements) {
|
public void removeAll(StrolchTransaction tx, List<T> elements) {
|
||||||
|
for (T element : elements) {
|
||||||
|
if (realm.isVersioningEnabled())
|
||||||
|
Version.updateVersionFor(element, tx.getCertificate().getUsername(), true);
|
||||||
|
else
|
||||||
|
Version.setInitialVersionFor(element, tx.getCertificate().getUsername());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.realm.isVersioningEnabled()) {
|
||||||
|
getDao(tx).updateAll(elements);
|
||||||
|
} else {
|
||||||
getDao(tx).removeAll(elements);
|
getDao(tx).removeAll(elements);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long removeAll(StrolchTransaction tx) {
|
public long removeAll(StrolchTransaction tx) {
|
||||||
|
@ -175,4 +326,50 @@ public abstract class TransactionalElementMap<T extends StrolchRootElement> impl
|
||||||
public long removeAllBy(StrolchTransaction tx, String type) {
|
public long removeAllBy(StrolchTransaction tx, String type) {
|
||||||
return getDao(tx).removeAllBy(type);
|
return getDao(tx).removeAllBy(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T revertToVersion(StrolchTransaction tx, T element) throws StrolchException {
|
||||||
|
return revertToVersion(tx, element.getType(), element.getId(), element.getVersion().getVersion());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T revertToVersion(StrolchTransaction tx, String type, String id, int version) throws StrolchException {
|
||||||
|
if (!this.realm.isVersioningEnabled()) {
|
||||||
|
throw new StrolchPersistenceException("Can not revert to a version if versioning is not enabled!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the current and specified version
|
||||||
|
T current = getBy(tx, type, id, true);
|
||||||
|
T versionT = getBy(tx, type, id, version, true);
|
||||||
|
|
||||||
|
// create the new version
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
T clone = (T) versionT.getClone();
|
||||||
|
clone.setVersion(current.getVersion().next(tx.getCertificate().getUsername(), false));
|
||||||
|
|
||||||
|
// save the new version
|
||||||
|
getDao(tx).update(clone);
|
||||||
|
|
||||||
|
// and return new version
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void undoVersion(StrolchTransaction tx, T element) throws StrolchException {
|
||||||
|
if (!this.realm.isVersioningEnabled()) {
|
||||||
|
throw new StrolchPersistenceException("Can not undo a version if versioning is not enabled!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure the given element is the latest version
|
||||||
|
T current = getBy(tx, element.getType(), element.getId(), true);
|
||||||
|
if (!current.getVersion().equals(element.getVersion())) {
|
||||||
|
String msg = "Can not undo the version {0} as it is not the latest {1}!"; //$NON-NLS-1$
|
||||||
|
msg = MessageFormat.format(msg, element.getVersion(), current.getVersion());
|
||||||
|
throw new StrolchException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
getDao(tx).removeVersion(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void assertIsRefParam(Parameter<?> refP);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import static li.strolch.model.StrolchModelConstants.INTERPRETATION_ORDER_REF;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import li.strolch.agent.api.OrderMap;
|
import li.strolch.agent.api.OrderMap;
|
||||||
|
import li.strolch.agent.api.StrolchRealm;
|
||||||
import li.strolch.model.Order;
|
import li.strolch.model.Order;
|
||||||
import li.strolch.model.parameter.Parameter;
|
import li.strolch.model.parameter.Parameter;
|
||||||
import li.strolch.model.query.OrderQuery;
|
import li.strolch.model.query.OrderQuery;
|
||||||
|
@ -28,6 +29,10 @@ import li.strolch.persistence.api.StrolchTransaction;
|
||||||
|
|
||||||
public class TransactionalOrderMap extends TransactionalElementMap<Order> implements OrderMap {
|
public class TransactionalOrderMap extends TransactionalElementMap<Order> implements OrderMap {
|
||||||
|
|
||||||
|
public TransactionalOrderMap(StrolchRealm realm) {
|
||||||
|
super(realm);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void assertIsRefParam(Parameter<?> refP) {
|
protected void assertIsRefParam(Parameter<?> refP) {
|
||||||
ElementMapHelpers.assertIsRefParam(INTERPRETATION_ORDER_REF, refP);
|
ElementMapHelpers.assertIsRefParam(INTERPRETATION_ORDER_REF, refP);
|
||||||
|
|
|
@ -85,16 +85,14 @@ public class TransactionalRealm extends InternalStrolchRealm {
|
||||||
@Override
|
@Override
|
||||||
public void initialize(ComponentContainer container, ComponentConfiguration configuration) {
|
public void initialize(ComponentContainer container, ComponentConfiguration configuration) {
|
||||||
super.initialize(container, configuration);
|
super.initialize(container, configuration);
|
||||||
this.resourceMap = new TransactionalResourceMap();
|
this.resourceMap = new TransactionalResourceMap(this);
|
||||||
this.orderMap = new TransactionalOrderMap();
|
this.orderMap = new TransactionalOrderMap(this);
|
||||||
this.activityMap = new TransactionalActivityMap();
|
this.activityMap = new TransactionalActivityMap(this);
|
||||||
|
|
||||||
if (isAuditTrailEnabled()) {
|
if (isAuditTrailEnabled()) {
|
||||||
this.auditTrail = new TransactionalAuditTrail();
|
this.auditTrail = new TransactionalAuditTrail();
|
||||||
logger.info("Enabling AuditTrail for realm " + getRealm()); //$NON-NLS-1$
|
|
||||||
} else {
|
} else {
|
||||||
this.auditTrail = new NoStrategyAuditTrail();
|
this.auditTrail = new NoStrategyAuditTrail();
|
||||||
logger.info("AuditTrail is disabled for realm " + getRealm()); //$NON-NLS-1$
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.persistenceHandler = container.getComponent(PersistenceHandler.class);
|
this.persistenceHandler = container.getComponent(PersistenceHandler.class);
|
||||||
|
@ -122,8 +120,8 @@ public class TransactionalRealm extends InternalStrolchRealm {
|
||||||
|
|
||||||
long duration = System.nanoTime() - start;
|
long duration = System.nanoTime() - start;
|
||||||
String durationS = StringHelper.formatNanoDuration(duration);
|
String durationS = StringHelper.formatNanoDuration(duration);
|
||||||
logger.info(MessageFormat.format(
|
logger.info(
|
||||||
"Initialized Transactional Maps for realm {0} took {1}.", getRealm(), durationS)); //$NON-NLS-1$
|
MessageFormat.format("Initialized Transactional Maps for realm {0} took {1}.", getRealm(), durationS)); //$NON-NLS-1$
|
||||||
logger.info(MessageFormat.format("There are {0} Orders", nrOfOrders)); //$NON-NLS-1$
|
logger.info(MessageFormat.format("There are {0} Orders", nrOfOrders)); //$NON-NLS-1$
|
||||||
logger.info(MessageFormat.format("There are {0} Resources", nrOfResources)); //$NON-NLS-1$
|
logger.info(MessageFormat.format("There are {0} Resources", nrOfResources)); //$NON-NLS-1$
|
||||||
logger.info(MessageFormat.format("There are {0} Activities", nrOfActivities)); //$NON-NLS-1$
|
logger.info(MessageFormat.format("There are {0} Activities", nrOfActivities)); //$NON-NLS-1$
|
||||||
|
|
|
@ -20,6 +20,7 @@ import static li.strolch.model.StrolchModelConstants.INTERPRETATION_RESOURCE_REF
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import li.strolch.agent.api.ResourceMap;
|
import li.strolch.agent.api.ResourceMap;
|
||||||
|
import li.strolch.agent.api.StrolchRealm;
|
||||||
import li.strolch.model.Resource;
|
import li.strolch.model.Resource;
|
||||||
import li.strolch.model.parameter.Parameter;
|
import li.strolch.model.parameter.Parameter;
|
||||||
import li.strolch.model.query.ResourceQuery;
|
import li.strolch.model.query.ResourceQuery;
|
||||||
|
@ -28,6 +29,10 @@ import li.strolch.persistence.api.StrolchTransaction;
|
||||||
|
|
||||||
public class TransactionalResourceMap extends TransactionalElementMap<Resource> implements ResourceMap {
|
public class TransactionalResourceMap extends TransactionalElementMap<Resource> implements ResourceMap {
|
||||||
|
|
||||||
|
public TransactionalResourceMap(StrolchRealm realm) {
|
||||||
|
super(realm);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void assertIsRefParam(Parameter<?> refP) {
|
protected void assertIsRefParam(Parameter<?> refP) {
|
||||||
ElementMapHelpers.assertIsRefParam(INTERPRETATION_RESOURCE_REF, refP);
|
ElementMapHelpers.assertIsRefParam(INTERPRETATION_RESOURCE_REF, refP);
|
||||||
|
|
|
@ -103,18 +103,15 @@ public class TransientRealm extends InternalStrolchRealm {
|
||||||
|
|
||||||
this.modelFile = configuration.getDataFile(key, null, configuration.getRuntimeConfiguration(), true);
|
this.modelFile = configuration.getDataFile(key, null, configuration.getRuntimeConfiguration(), true);
|
||||||
|
|
||||||
this.persistenceHandler = new InMemoryPersistence(container.getPrivilegeHandler());
|
this.persistenceHandler = new InMemoryPersistence(container.getPrivilegeHandler(), isVersioningEnabled());
|
||||||
this.resourceMap = new TransactionalResourceMap();
|
this.resourceMap = new TransactionalResourceMap(this);
|
||||||
this.orderMap = new TransactionalOrderMap();
|
this.orderMap = new TransactionalOrderMap(this);
|
||||||
this.activityMap = new TransactionalActivityMap();
|
this.activityMap = new TransactionalActivityMap(this);
|
||||||
|
|
||||||
if (isAuditTrailEnabled()) {
|
if (isAuditTrailEnabled())
|
||||||
this.auditTrail = new TransactionalAuditTrail();
|
this.auditTrail = new TransactionalAuditTrail();
|
||||||
logger.info("Enabling AuditTrail for realm " + getRealm()); //$NON-NLS-1$
|
else
|
||||||
} else {
|
|
||||||
this.auditTrail = new NoStrategyAuditTrail();
|
this.auditTrail = new NoStrategyAuditTrail();
|
||||||
logger.info("AuditTrail is disabled for realm " + getRealm()); //$NON-NLS-1$
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -49,7 +49,6 @@ import li.strolch.model.Resource;
|
||||||
import li.strolch.model.StrolchElement;
|
import li.strolch.model.StrolchElement;
|
||||||
import li.strolch.model.StrolchRootElement;
|
import li.strolch.model.StrolchRootElement;
|
||||||
import li.strolch.model.Tags;
|
import li.strolch.model.Tags;
|
||||||
import li.strolch.model.Version;
|
|
||||||
import li.strolch.model.activity.Activity;
|
import li.strolch.model.activity.Activity;
|
||||||
import li.strolch.model.audit.AccessType;
|
import li.strolch.model.audit.AccessType;
|
||||||
import li.strolch.model.audit.Audit;
|
import li.strolch.model.audit.Audit;
|
||||||
|
@ -67,7 +66,6 @@ import li.strolch.model.visitor.ElementTypeVisitor;
|
||||||
import li.strolch.privilege.base.PrivilegeException;
|
import li.strolch.privilege.base.PrivilegeException;
|
||||||
import li.strolch.privilege.model.Certificate;
|
import li.strolch.privilege.model.Certificate;
|
||||||
import li.strolch.privilege.model.PrivilegeContext;
|
import li.strolch.privilege.model.PrivilegeContext;
|
||||||
import li.strolch.runtime.StrolchConstants;
|
|
||||||
import li.strolch.runtime.privilege.PrivilegeHandler;
|
import li.strolch.runtime.privilege.PrivilegeHandler;
|
||||||
import li.strolch.service.api.Command;
|
import li.strolch.service.api.Command;
|
||||||
import li.strolch.utils.dbc.DBC;
|
import li.strolch.utils.dbc.DBC;
|
||||||
|
@ -86,7 +84,6 @@ public abstract class AbstractTransaction implements StrolchTransaction {
|
||||||
private boolean suppressUpdates;
|
private boolean suppressUpdates;
|
||||||
private boolean suppressAudits;
|
private boolean suppressAudits;
|
||||||
private boolean suppressDoNothingLogging;
|
private boolean suppressDoNothingLogging;
|
||||||
private boolean versioningEnabled;
|
|
||||||
private TransactionResult txResult;
|
private TransactionResult txResult;
|
||||||
|
|
||||||
private List<Command> commands;
|
private List<Command> commands;
|
||||||
|
@ -147,7 +144,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
|
||||||
return this.realm.getRealm();
|
return this.realm.getRealm();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected StrolchRealm getRealm() {
|
public StrolchRealm getRealm() {
|
||||||
return this.realm;
|
return this.realm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,16 +208,6 @@ public abstract class AbstractTransaction implements StrolchTransaction {
|
||||||
return this.suppressAudits;
|
return this.suppressAudits;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setVersioningEnabled(boolean versioningEnabled) {
|
|
||||||
this.versioningEnabled = versioningEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isVersioningEnabled() {
|
|
||||||
return this.versioningEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSuppressDoNothingLogging() {
|
public boolean isSuppressDoNothingLogging() {
|
||||||
return suppressDoNothingLogging;
|
return suppressDoNothingLogging;
|
||||||
|
@ -231,6 +218,11 @@ public abstract class AbstractTransaction implements StrolchTransaction {
|
||||||
this.suppressDoNothingLogging = quietDoNothing;
|
this.suppressDoNothingLogging = quietDoNothing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isVersioningEnabled() {
|
||||||
|
return this.realm.isVersioningEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends StrolchRootElement> void lock(T element) throws StrolchLockException {
|
public <T extends StrolchRootElement> void lock(T element) throws StrolchLockException {
|
||||||
this.realm.lock(element);
|
this.realm.lock(element);
|
||||||
|
@ -407,22 +399,22 @@ public abstract class AbstractTransaction implements StrolchTransaction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Resource getResourceTemplate(String type) {
|
public Resource getResourceTemplate(String type) {
|
||||||
return getResourceBy(StrolchConstants.TEMPLATE, type);
|
return getResourceMap().getTemplate(this, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Resource getResourceTemplate(String type, boolean assertExists) throws StrolchException {
|
public Resource getResourceTemplate(String type, boolean assertExists) throws StrolchException {
|
||||||
return getResourceBy(StrolchConstants.TEMPLATE, type, assertExists);
|
return getResourceMap().getTemplate(this, type, assertExists);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Order getOrderTemplate(String type) {
|
public Order getOrderTemplate(String type) {
|
||||||
return getOrderBy(StrolchConstants.TEMPLATE, type);
|
return getOrderMap().getTemplate(this, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Order getOrderTemplate(String type, boolean assertExists) throws StrolchException {
|
public Order getOrderTemplate(String type, boolean assertExists) throws StrolchException {
|
||||||
return getOrderBy(StrolchConstants.TEMPLATE, type, assertExists);
|
return getOrderMap().getTemplate(this, type, assertExists);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -432,12 +424,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Order getOrderBy(String type, String id, boolean assertExists) throws StrolchException {
|
public Order getOrderBy(String type, String id, boolean assertExists) throws StrolchException {
|
||||||
Order order = getOrderMap().getBy(this, type, id);
|
return getOrderMap().getBy(this, type, id, assertExists);
|
||||||
if (assertExists && order == null) {
|
|
||||||
String msg = "No Order exists with the id {0} with type {1}";
|
|
||||||
throw new StrolchException(MessageFormat.format(msg, id, type));
|
|
||||||
}
|
|
||||||
return order;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -580,21 +567,25 @@ public abstract class AbstractTransaction implements StrolchTransaction {
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
this.txResult.setState(TransactionState.ROLLING_BACK);
|
this.txResult.setState(TransactionState.ROLLING_BACK);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
undoCommands();
|
undoCommands();
|
||||||
} catch (Exception e2) {
|
} catch (Exception ex) {
|
||||||
|
logger.error("Failed to commit transaction and then undo commands due to " + ex.getMessage(), ex);
|
||||||
try {
|
try {
|
||||||
rollback(this.txResult);
|
rollback(this.txResult);
|
||||||
handleRollback(start);
|
handleRollback(start);
|
||||||
} catch (Exception e1) {
|
} catch (Exception exc) {
|
||||||
logger.error("Failed to roll back after failing to undo commands: " + e1.getMessage(), e1); //$NON-NLS-1$
|
logger.error("Failed to roll back after failing to undo commands: " + exc.getMessage(), exc); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
handleFailure(start, e);
|
handleFailure(start, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
rollback(this.txResult);
|
rollback(this.txResult);
|
||||||
handleRollback(start);
|
handleRollback(start);
|
||||||
} catch (Exception e1) {
|
} catch (Exception ex) {
|
||||||
|
logger.error("Failed to commit transaction and then rollback due to " + ex.getMessage(), ex);
|
||||||
handleFailure(start, e);
|
handleFailure(start, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -843,6 +834,8 @@ public abstract class AbstractTransaction implements StrolchTransaction {
|
||||||
|
|
||||||
List<Audit> audits = new ArrayList<>();
|
List<Audit> audits = new ArrayList<>();
|
||||||
|
|
||||||
|
// this is bad... doesn't account for a created and deleted in same TX...
|
||||||
|
|
||||||
if (this.orderMap != null) {
|
if (this.orderMap != null) {
|
||||||
if (this.realm.isAuditTrailEnabledForRead())
|
if (this.realm.isAuditTrailEnabledForRead())
|
||||||
auditsFor(audits, AccessType.READ, Tags.ORDER, this.orderMap.getRead());
|
auditsFor(audits, AccessType.READ, Tags.ORDER, this.orderMap.getRead());
|
||||||
|
@ -916,15 +909,6 @@ public abstract class AbstractTransaction implements StrolchTransaction {
|
||||||
return audit;
|
return audit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateVersionFor(StrolchRootElement element, boolean deleted) {
|
|
||||||
if (this.versioningEnabled) {
|
|
||||||
int v = element.getVersion() == null ? 0 : element.getVersion().getVersion() + 1;
|
|
||||||
Version version = new Version(element.getLocator(), v, this.certificate.getUsername(), deleted);
|
|
||||||
element.setVersion(version);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls {@link Command#validate()} on all registered command. This is done before we perform any commands and thus
|
* Calls {@link Command#validate()} on all registered command. This is done before we perform any commands and thus
|
||||||
* no rollback needs be done due to invalid input for a command
|
* no rollback needs be done due to invalid input for a command
|
||||||
|
@ -943,8 +927,8 @@ public abstract class AbstractTransaction implements StrolchTransaction {
|
||||||
ListIterator<Command> iter = this.commands.listIterator();
|
ListIterator<Command> iter = this.commands.listIterator();
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
Command command = iter.next();
|
Command command = iter.next();
|
||||||
command.doCommand();
|
|
||||||
this.flushedCommands.add(command);
|
this.flushedCommands.add(command);
|
||||||
|
command.doCommand();
|
||||||
iter.remove();
|
iter.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,41 +21,263 @@ import java.util.Set;
|
||||||
import li.strolch.model.StrolchRootElement;
|
import li.strolch.model.StrolchRootElement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <p>
|
||||||
|
* This data access object is used to access {@link StrolchRootElement} from the underlying persistence layer. Objects
|
||||||
|
* in Strolch are always referenced by a type and an ID. The type is a categorisation/grouping of the objects, while the
|
||||||
|
* ID is a unique identifier of the object. The ID must be unique, even for multiple groups.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* The DAO must support versioning. i.e. if versioning is enabled, then if an object is updated or removed, the existing
|
||||||
|
* version is not modified, but a new version is persisted so that rollbacks can be done
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
|
*
|
||||||
|
* @param <T>
|
||||||
|
* the object instance being queried from the underlying persistence layer
|
||||||
*/
|
*/
|
||||||
public interface StrolchDao<T extends StrolchRootElement> {
|
public interface StrolchDao<T extends StrolchRootElement> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries the set of IDs for all elements, regardless of types from the underlying persistence layer.
|
||||||
|
*
|
||||||
|
* @return the set of IDs for all elements
|
||||||
|
*/
|
||||||
public Set<String> queryKeySet();
|
public Set<String> queryKeySet();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if an element exists with the given type and id in the underlying persistence layer
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* the type of elements
|
||||||
|
* @param id
|
||||||
|
* the id of the element to return
|
||||||
|
*
|
||||||
|
* @return true if an element exists with the given type and id
|
||||||
|
*/
|
||||||
public boolean hasElement(String type, String id);
|
public boolean hasElement(String type, String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of elements in the underlying persistence layer, regardless of type
|
||||||
|
*
|
||||||
|
* @return the number of elements in the underlying persistence layer
|
||||||
|
*/
|
||||||
public long querySize();
|
public long querySize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of elements in the underlying persistence layer for the given type
|
||||||
|
*
|
||||||
|
* @return the number of elements in the underlying persistence layer for the given type
|
||||||
|
*/
|
||||||
public long querySize(String type);
|
public long querySize(String type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries the set of IDs for the elements with the given type
|
||||||
|
*
|
||||||
|
* @return the set of IDs for the elements with the given type
|
||||||
|
*/
|
||||||
public Set<String> queryKeySet(String type);
|
public Set<String> queryKeySet(String type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries the current list of types from the underlying persistence layer
|
||||||
|
*
|
||||||
|
* @return the list of types
|
||||||
|
*/
|
||||||
public Set<String> queryTypes();
|
public Set<String> queryTypes();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries the latest version of the element with the given type and ID
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* the type of the element to be queried
|
||||||
|
* @param id
|
||||||
|
* the id of the element to be queried
|
||||||
|
*
|
||||||
|
* @return the element with the given type and ID, or null if it does not exist
|
||||||
|
*/
|
||||||
public T queryBy(String type, String id);
|
public T queryBy(String type, String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Queries a specific version of the element with the given type and ID.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* <b>Note:</b> If you want to query the latest version, then use the method with out the version parameter
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* the type of the element to be queried
|
||||||
|
* @param id
|
||||||
|
* the id of the element to be queried
|
||||||
|
* @param version
|
||||||
|
* the version of the element to be returned
|
||||||
|
*
|
||||||
|
* @return the element with the given type and ID, or null if it does not exist
|
||||||
|
*/
|
||||||
|
public T queryBy(String type, String id, int version);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries and returns all the versions of the element with the given type and ID
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* the type of the element to be queried
|
||||||
|
* @param id
|
||||||
|
* the id of the element to be queried
|
||||||
|
*
|
||||||
|
* @return all the versions of the element with the given type and ID
|
||||||
|
*/
|
||||||
|
public List<T> queryVersionsFor(String type, String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries and returns all elements regardless of type
|
||||||
|
*
|
||||||
|
* @return all elements regardless of type
|
||||||
|
*/
|
||||||
public List<T> queryAll();
|
public List<T> queryAll();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries and returns all elements of the given type
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* the type of element to return
|
||||||
|
*
|
||||||
|
* @return all elements of the given type
|
||||||
|
*/
|
||||||
public List<T> queryAll(String type);
|
public List<T> queryAll(String type);
|
||||||
|
|
||||||
public void save(T element);
|
/**
|
||||||
|
* Persists the given element. The element must not yet exist
|
||||||
|
*
|
||||||
|
* @param element
|
||||||
|
* the element to be persisted
|
||||||
|
*
|
||||||
|
* @throws StrolchPersistenceException
|
||||||
|
* if the element already exists
|
||||||
|
*/
|
||||||
|
public void save(T element) throws StrolchPersistenceException;
|
||||||
|
|
||||||
public void saveAll(List<T> elements);
|
/**
|
||||||
|
* Persists the given list of elements. None of the elements may already exists
|
||||||
|
*
|
||||||
|
* @param elements
|
||||||
|
* the list of elements to be persisted
|
||||||
|
*
|
||||||
|
* @throws StrolchPersistenceException
|
||||||
|
* if any of the elements already exist
|
||||||
|
*/
|
||||||
|
public void saveAll(List<T> elements) throws StrolchPersistenceException;
|
||||||
|
|
||||||
public void update(T element);
|
/**
|
||||||
|
* Updates the given element. The element must already exist
|
||||||
|
*
|
||||||
|
* @param element
|
||||||
|
* the element to be updated
|
||||||
|
*
|
||||||
|
* @throws StrolchPersistenceException
|
||||||
|
* if the element does not exist
|
||||||
|
*/
|
||||||
|
public void update(T element) throws StrolchPersistenceException;
|
||||||
|
|
||||||
public void updateAll(List<T> elements);
|
/**
|
||||||
|
* Updates the given list of elements. Each element must already exist
|
||||||
|
*
|
||||||
|
* @param elements
|
||||||
|
* the elements to be updated
|
||||||
|
*
|
||||||
|
* @throws StrolchPersistenceException
|
||||||
|
* if any of the elements do not exist
|
||||||
|
*/
|
||||||
|
public void updateAll(List<T> elements) throws StrolchPersistenceException;
|
||||||
|
|
||||||
public void remove(T element);
|
/**
|
||||||
|
* <p>
|
||||||
|
* Removes the given element from the underlying persistence layer
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* <b>Note:</b> This method deletes the given object including its versions! Do not call this method if you want to
|
||||||
|
* use versioning!
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param element
|
||||||
|
* the element to be removed
|
||||||
|
*
|
||||||
|
* @throws StrolchPersistenceException
|
||||||
|
* if the element does not exist
|
||||||
|
*/
|
||||||
|
public void remove(T element) throws StrolchPersistenceException;
|
||||||
|
|
||||||
public void removeAll(List<T> elements);
|
/**
|
||||||
|
* <p>
|
||||||
|
* Removes the given elements from the underlying persistence layer
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* <b>Note:</b> This method deletes the given objects including their versions! Do not call this method if you want
|
||||||
|
* to use versioning!
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param elements
|
||||||
|
* the elements to be removed
|
||||||
|
*
|
||||||
|
* @throws StrolchPersistenceException
|
||||||
|
* if any of the elements do not exist
|
||||||
|
*/
|
||||||
|
public void removeAll(List<T> elements) throws StrolchPersistenceException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Removes all elements regardless of type from the underlying persistence layer
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* <b>Note:</b> This method does not support versioning. This method completely removes all objects regardless of
|
||||||
|
* type and their versions!
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @return the number of elements removed
|
||||||
|
*
|
||||||
|
* @throws StrolchPersistenceException
|
||||||
|
*/
|
||||||
public long removeAll();
|
public long removeAll();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Removes all elements of the given type from the underlying persistence layer
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* <b>Note:</b> This method does not support versioning. This method completely removes all objects of the given
|
||||||
|
* type and their versions!
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* the type of element to remove
|
||||||
|
*
|
||||||
|
* @return the number of elements removed
|
||||||
|
*/
|
||||||
public long removeAllBy(String type);
|
public long removeAllBy(String type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Removes the given version of the given element from the underlying persistence layer. The version must be the
|
||||||
|
* latest version and thus always deletes the newest version. To delete multiple versions call this method multiple
|
||||||
|
* times. To remove it completely, call the {@link #remove(StrolchRootElement)} method.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* <b>Note:</b> This element given must be the current latest version!
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param element
|
||||||
|
* the latest version of the element to be removed
|
||||||
|
*
|
||||||
|
* @throws StrolchPersistenceException
|
||||||
|
* if the element/version does not exist
|
||||||
|
*/
|
||||||
|
public void removeVersion(T element) throws StrolchPersistenceException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -279,19 +279,6 @@ public interface StrolchTransaction extends AutoCloseable {
|
||||||
*/
|
*/
|
||||||
public boolean isSuppressAudits();
|
public boolean isSuppressAudits();
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param versioningEnabled
|
|
||||||
*/
|
|
||||||
public void setVersioningEnabled(boolean versioningEnabled);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if versioning of objects is enabled
|
|
||||||
*
|
|
||||||
* @return true if versioning of objects is enabled
|
|
||||||
*/
|
|
||||||
public boolean isVersioningEnabled();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the given argument is true, then logging of a {@link TransactionCloseStrategy#DO_NOTHING} will be suppressed
|
* If the given argument is true, then logging of a {@link TransactionCloseStrategy#DO_NOTHING} will be suppressed
|
||||||
*
|
*
|
||||||
|
@ -307,6 +294,13 @@ public interface StrolchTransaction extends AutoCloseable {
|
||||||
*/
|
*/
|
||||||
boolean isSuppressDoNothingLogging();
|
boolean isSuppressDoNothingLogging();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if versioning is enabled on the {@link StrolchRealm} for which this transaction has been opened
|
||||||
|
*
|
||||||
|
* @return true if versioning is enabled
|
||||||
|
*/
|
||||||
|
boolean isVersioningEnabled();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locks the given element and registers it on the transaction so the lock is released when the transaction is
|
* Locks the given element and registers it on the transaction so the lock is released when the transaction is
|
||||||
* closed
|
* closed
|
||||||
|
@ -376,21 +370,6 @@ public interface StrolchTransaction extends AutoCloseable {
|
||||||
*/
|
*/
|
||||||
public Audit auditFrom(AccessType accessType, StrolchRootElement element);
|
public Audit auditFrom(AccessType accessType, StrolchRootElement element);
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new version for the given element. If the element has no version yet, then the result will be version
|
|
||||||
* 0, otherwise the version will be an increment to the current version
|
|
||||||
*
|
|
||||||
* @param element
|
|
||||||
* the element for which to create a new version
|
|
||||||
* @param deleted
|
|
||||||
* if true, then the version will be marked as deleted, i.e. this object was removed from the element
|
|
||||||
* maps
|
|
||||||
*
|
|
||||||
* @return the new version, which is either an increment of the existing version on the element, or it will be
|
|
||||||
* version 0
|
|
||||||
*/
|
|
||||||
public void updateVersionFor(StrolchRootElement element, boolean deleted);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* Performs the given {@link OrderQuery} and each returned {@link Order} is passed through the {@link OrderVisitor}
|
* Performs the given {@link OrderQuery} and each returned {@link Order} is passed through the {@link OrderVisitor}
|
||||||
|
|
|
@ -25,6 +25,10 @@ import li.strolch.runtime.query.inmemory.InMemoryQuery;
|
||||||
|
|
||||||
public class InMemoryActivityDao extends InMemoryDao<Activity> implements ActivityDao {
|
public class InMemoryActivityDao extends InMemoryDao<Activity> implements ActivityDao {
|
||||||
|
|
||||||
|
public InMemoryActivityDao(boolean versioningEnabled) {
|
||||||
|
super(versioningEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <U> List<U> doQuery(ActivityQuery<U> activityQuery) {
|
public <U> List<U> doQuery(ActivityQuery<U> activityQuery) {
|
||||||
InMemoryActivityQueryVisitor visitor = new InMemoryActivityQueryVisitor();
|
InMemoryActivityQueryVisitor visitor = new InMemoryActivityQueryVisitor();
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package li.strolch.persistence.inmemory;
|
package li.strolch.persistence.inmemory;
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
|
import java.util.ArrayDeque;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
@ -29,25 +30,32 @@ import li.strolch.persistence.api.StrolchPersistenceException;
|
||||||
|
|
||||||
public class InMemoryDao<T extends StrolchRootElement> implements StrolchDao<T> {
|
public class InMemoryDao<T extends StrolchRootElement> implements StrolchDao<T> {
|
||||||
|
|
||||||
private Map<String, Map<String, T>> elementMap;
|
private Map<String, Map<String, ArrayDeque<T>>> elementMap;
|
||||||
|
private boolean versioningEnabled;
|
||||||
|
|
||||||
public InMemoryDao() {
|
public InMemoryDao(boolean versioningEnabled) {
|
||||||
|
this.versioningEnabled = versioningEnabled;
|
||||||
this.elementMap = new HashMap<>();
|
this.elementMap = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean hasElement(String type, String id) {
|
public synchronized boolean hasElement(String type, String id) {
|
||||||
Map<String, T> byType = this.elementMap.get(type);
|
Map<String, ArrayDeque<T>> byType = this.elementMap.get(type);
|
||||||
if (byType == null)
|
if (byType == null)
|
||||||
return false;
|
return false;
|
||||||
return byType.containsKey(id);
|
|
||||||
|
ArrayDeque<T> list = byType.get(id);
|
||||||
|
if (list == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return !list.getLast().getVersion().isDeleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized long querySize() {
|
public synchronized long querySize() {
|
||||||
long size = 0;
|
long size = 0;
|
||||||
for (String type : this.elementMap.keySet()) {
|
for (String type : this.elementMap.keySet()) {
|
||||||
Map<String, T> byType = this.elementMap.get(type);
|
Map<String, ArrayDeque<T>> byType = this.elementMap.get(type);
|
||||||
size += byType.size();
|
size += byType.size();
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
|
@ -55,7 +63,7 @@ public class InMemoryDao<T extends StrolchRootElement> implements StrolchDao<T>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized long querySize(String type) {
|
public synchronized long querySize(String type) {
|
||||||
Map<String, T> byType = this.elementMap.get(type);
|
Map<String, ArrayDeque<T>> byType = this.elementMap.get(type);
|
||||||
if (byType == null)
|
if (byType == null)
|
||||||
return 0;
|
return 0;
|
||||||
return byType.size();
|
return byType.size();
|
||||||
|
@ -63,21 +71,19 @@ public class InMemoryDao<T extends StrolchRootElement> implements StrolchDao<T>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized Set<String> queryKeySet() {
|
public synchronized Set<String> queryKeySet() {
|
||||||
|
|
||||||
Set<String> keySet = new HashSet<>();
|
Set<String> keySet = new HashSet<>();
|
||||||
for (String type : this.elementMap.keySet()) {
|
for (String type : this.elementMap.keySet()) {
|
||||||
Map<String, T> byType = this.elementMap.get(type);
|
Map<String, ArrayDeque<T>> byType = this.elementMap.get(type);
|
||||||
for (String id : byType.keySet()) {
|
for (String id : byType.keySet()) {
|
||||||
keySet.add(id);
|
keySet.add(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return keySet;
|
return keySet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized Set<String> queryKeySet(String type) {
|
public synchronized Set<String> queryKeySet(String type) {
|
||||||
Map<String, T> byType = this.elementMap.get(type);
|
Map<String, ArrayDeque<T>> byType = this.elementMap.get(type);
|
||||||
if (byType == null)
|
if (byType == null)
|
||||||
return new HashSet<>(0);
|
return new HashSet<>(0);
|
||||||
return new HashSet<>(byType.keySet());
|
return new HashSet<>(byType.keySet());
|
||||||
|
@ -90,19 +96,58 @@ public class InMemoryDao<T extends StrolchRootElement> implements StrolchDao<T>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized T queryBy(String type, String id) {
|
public synchronized T queryBy(String type, String id) {
|
||||||
Map<String, T> byType = this.elementMap.get(type);
|
Map<String, ArrayDeque<T>> byType = this.elementMap.get(type);
|
||||||
if (byType == null)
|
if (byType == null)
|
||||||
return null;
|
return null;
|
||||||
return byType.get(id);
|
ArrayDeque<T> list = byType.get(id);
|
||||||
|
if (list == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
T t = list.getLast();
|
||||||
|
if (t.getVersion() != null && t.getVersion().isDeleted())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized T queryBy(String type, String id, int version) {
|
||||||
|
Map<String, ArrayDeque<T>> byType = this.elementMap.get(type);
|
||||||
|
if (byType == null)
|
||||||
|
return null;
|
||||||
|
ArrayDeque<T> list = byType.get(id);
|
||||||
|
if (list == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
for (T t : list) {
|
||||||
|
if (t.getVersion().getVersion() == version)
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized List<T> queryVersionsFor(String type, String id) {
|
||||||
|
Map<String, ArrayDeque<T>> byType = this.elementMap.get(type);
|
||||||
|
if (byType == null)
|
||||||
|
return null;
|
||||||
|
ArrayDeque<T> list = byType.get(id);
|
||||||
|
if (list == null)
|
||||||
|
return new ArrayList<>();
|
||||||
|
return new ArrayList<>(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized List<T> queryAll() {
|
public synchronized List<T> queryAll() {
|
||||||
List<T> elements = new ArrayList<>();
|
List<T> elements = new ArrayList<>();
|
||||||
for (String type : this.elementMap.keySet()) {
|
for (String type : this.elementMap.keySet()) {
|
||||||
Map<String, T> byType = this.elementMap.get(type);
|
Map<String, ArrayDeque<T>> byType = this.elementMap.get(type);
|
||||||
for (String id : byType.keySet()) {
|
for (String id : byType.keySet()) {
|
||||||
elements.add(byType.get(id));
|
ArrayDeque<T> list = byType.get(id);
|
||||||
|
T last = list.getLast();
|
||||||
|
if (last.getVersion() == null || !last.getVersion().isDeleted())
|
||||||
|
elements.add(last);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,27 +156,43 @@ public class InMemoryDao<T extends StrolchRootElement> implements StrolchDao<T>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized List<T> queryAll(String type) {
|
public synchronized List<T> queryAll(String type) {
|
||||||
Map<String, T> byType = this.elementMap.get(type);
|
Map<String, ArrayDeque<T>> byType = this.elementMap.get(type);
|
||||||
if (byType == null)
|
if (byType == null)
|
||||||
return new ArrayList<>(0);
|
return new ArrayList<>(0);
|
||||||
return new ArrayList<>(byType.values());
|
|
||||||
|
List<T> elements = new ArrayList<>();
|
||||||
|
for (ArrayDeque<T> list : byType.values()) {
|
||||||
|
T last = list.getLast();
|
||||||
|
if (last.getVersion() == null || !last.getVersion().isDeleted())
|
||||||
|
elements.add(last);
|
||||||
|
}
|
||||||
|
|
||||||
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void save(T element) {
|
public synchronized void save(T element) {
|
||||||
Map<String, T> byType = this.elementMap.get(element.getType());
|
Map<String, ArrayDeque<T>> byType = this.elementMap.get(element.getType());
|
||||||
if (byType == null) {
|
if (byType == null) {
|
||||||
byType = new HashMap<>();
|
byType = new HashMap<>();
|
||||||
this.elementMap.put(element.getType(), byType);
|
this.elementMap.put(element.getType(), byType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (byType.containsKey(element.getId())) {
|
ArrayDeque<T> list = byType.get(element.getId());
|
||||||
|
|
||||||
|
// only allow add for existing id, if the existing one is "deleted"
|
||||||
|
if (list != null && !list.getLast().getVersion().isDeleted()) {
|
||||||
String msg = "An element already exists with the id {0}. Elements of the same class must always have a unique id, regardless of their type!"; //$NON-NLS-1$
|
String msg = "An element already exists with the id {0}. Elements of the same class must always have a unique id, regardless of their type!"; //$NON-NLS-1$
|
||||||
msg = MessageFormat.format(msg, element.getId());
|
msg = MessageFormat.format(msg, element.getId());
|
||||||
throw new StrolchPersistenceException(msg);
|
throw new StrolchPersistenceException(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
byType.put(element.getId(), element);
|
if (list == null) {
|
||||||
|
list = new ArrayDeque<>();
|
||||||
|
byType.put(element.getId(), list);
|
||||||
|
}
|
||||||
|
|
||||||
|
list.addLast(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -143,13 +204,24 @@ public class InMemoryDao<T extends StrolchRootElement> implements StrolchDao<T>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void update(T element) {
|
public synchronized void update(T element) {
|
||||||
Map<String, T> byType = this.elementMap.get(element.getType());
|
Map<String, ArrayDeque<T>> byType = this.elementMap.get(element.getType());
|
||||||
if (byType == null) {
|
if (byType == null) {
|
||||||
byType = new HashMap<>();
|
String msg = "The element does not yet exist with the type {0} and id {1}. Use add() for new objects!"; //$NON-NLS-1$
|
||||||
this.elementMap.put(element.getType(), byType);
|
msg = MessageFormat.format(msg, element.getType(), element.getId());
|
||||||
|
throw new StrolchPersistenceException(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
byType.put(element.getId(), element);
|
ArrayDeque<T> list = byType.get(element.getId());
|
||||||
|
if (list == null) {
|
||||||
|
String msg = "The element does not yet exist with the type {0} and id {1}. Use add() for new objects!"; //$NON-NLS-1$
|
||||||
|
msg = MessageFormat.format(msg, element.getType(), element.getId());
|
||||||
|
throw new StrolchPersistenceException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.versioningEnabled)
|
||||||
|
list.clear();
|
||||||
|
|
||||||
|
list.addLast(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -161,7 +233,7 @@ public class InMemoryDao<T extends StrolchRootElement> implements StrolchDao<T>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void remove(T element) {
|
public synchronized void remove(T element) {
|
||||||
Map<String, T> byType = this.elementMap.get(element.getType());
|
Map<String, ArrayDeque<T>> byType = this.elementMap.get(element.getType());
|
||||||
if (byType != null) {
|
if (byType != null) {
|
||||||
byType.remove(element.getId());
|
byType.remove(element.getId());
|
||||||
|
|
||||||
|
@ -184,7 +256,7 @@ public class InMemoryDao<T extends StrolchRootElement> implements StrolchDao<T>
|
||||||
|
|
||||||
Set<String> keySet = new HashSet<>(this.elementMap.keySet());
|
Set<String> keySet = new HashSet<>(this.elementMap.keySet());
|
||||||
for (String type : keySet) {
|
for (String type : keySet) {
|
||||||
Map<String, T> byType = this.elementMap.remove(type);
|
Map<String, ArrayDeque<T>> byType = this.elementMap.remove(type);
|
||||||
removed += byType.size();
|
removed += byType.size();
|
||||||
byType.clear();
|
byType.clear();
|
||||||
}
|
}
|
||||||
|
@ -194,11 +266,42 @@ public class InMemoryDao<T extends StrolchRootElement> implements StrolchDao<T>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized long removeAllBy(String type) {
|
public synchronized long removeAllBy(String type) {
|
||||||
Map<String, T> byType = this.elementMap.remove(type);
|
Map<String, ArrayDeque<T>> byType = this.elementMap.remove(type);
|
||||||
if (byType == null)
|
if (byType == null)
|
||||||
return 0;
|
return 0;
|
||||||
long removed = byType.size();
|
long removed = byType.size();
|
||||||
byType.clear();
|
byType.clear();
|
||||||
return removed;
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void removeVersion(T element) throws StrolchPersistenceException {
|
||||||
|
|
||||||
|
Map<String, ArrayDeque<T>> byType = this.elementMap.get(element.getType());
|
||||||
|
if (byType == null) {
|
||||||
|
String msg = "The element does not yet exist with the type {0}!"; //$NON-NLS-1$
|
||||||
|
msg = MessageFormat.format(msg, element.getType());
|
||||||
|
throw new StrolchPersistenceException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayDeque<T> list = byType.get(element.getId());
|
||||||
|
if (list == null) {
|
||||||
|
String msg = "The element does not yet exist with the type {0} and id {1}!"; //$NON-NLS-1$
|
||||||
|
msg = MessageFormat.format(msg, element.getType(), element.getId());
|
||||||
|
throw new StrolchPersistenceException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
T last = list.getLast();
|
||||||
|
if (!last.getVersion().equals(element.getVersion())) {
|
||||||
|
String msg = "The current version {0} is not the same as the version to remove {1}!"; //$NON-NLS-1$
|
||||||
|
msg = MessageFormat.format(msg, last.getVersion(), element.getVersion());
|
||||||
|
throw new StrolchPersistenceException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
list.removeLast();
|
||||||
|
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
byType.remove(element.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,10 @@ import li.strolch.runtime.query.inmemory.InMemoryQuery;
|
||||||
|
|
||||||
public class InMemoryOrderDao extends InMemoryDao<Order> implements OrderDao {
|
public class InMemoryOrderDao extends InMemoryDao<Order> implements OrderDao {
|
||||||
|
|
||||||
|
public InMemoryOrderDao(boolean versioningEnabled) {
|
||||||
|
super(versioningEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <U> List<U> doQuery(OrderQuery<U> orderQuery) {
|
public <U> List<U> doQuery(OrderQuery<U> orderQuery) {
|
||||||
InMemoryOrderQueryVisitor visitor = new InMemoryOrderQueryVisitor();
|
InMemoryOrderQueryVisitor visitor = new InMemoryOrderQueryVisitor();
|
||||||
|
|
|
@ -30,11 +30,13 @@ import li.strolch.runtime.privilege.PrivilegeHandler;
|
||||||
|
|
||||||
public class InMemoryPersistence implements PersistenceHandler {
|
public class InMemoryPersistence implements PersistenceHandler {
|
||||||
|
|
||||||
|
private boolean versioningEnabled;
|
||||||
private Map<String, DaoCache> daoCache;
|
private Map<String, DaoCache> daoCache;
|
||||||
private PrivilegeHandler privilegeHandler;
|
private PrivilegeHandler privilegeHandler;
|
||||||
|
|
||||||
public InMemoryPersistence(PrivilegeHandler privilegeHandler) {
|
public InMemoryPersistence(PrivilegeHandler privilegeHandler, boolean versioningEnabled) {
|
||||||
this.privilegeHandler = privilegeHandler;
|
this.privilegeHandler = privilegeHandler;
|
||||||
|
this.versioningEnabled = versioningEnabled;
|
||||||
this.daoCache = new HashMap<>();
|
this.daoCache = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +77,8 @@ public class InMemoryPersistence implements PersistenceHandler {
|
||||||
private synchronized DaoCache getDaoCache(StrolchTransaction tx) {
|
private synchronized DaoCache getDaoCache(StrolchTransaction tx) {
|
||||||
DaoCache daoCache = this.daoCache.get(tx.getRealmName());
|
DaoCache daoCache = this.daoCache.get(tx.getRealmName());
|
||||||
if (daoCache == null) {
|
if (daoCache == null) {
|
||||||
daoCache = new DaoCache(new InMemoryOrderDao(), new InMemoryResourceDao(), new InMemoryActivityDao(),
|
daoCache = new DaoCache(new InMemoryOrderDao(this.versioningEnabled),
|
||||||
|
new InMemoryResourceDao(this.versioningEnabled), new InMemoryActivityDao(this.versioningEnabled),
|
||||||
new InMemoryAuditDao());
|
new InMemoryAuditDao());
|
||||||
this.daoCache.put(tx.getRealmName(), daoCache);
|
this.daoCache.put(tx.getRealmName(), daoCache);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,10 @@ import li.strolch.runtime.query.inmemory.InMemoryResourceQueryVisitor;
|
||||||
|
|
||||||
public class InMemoryResourceDao extends InMemoryDao<Resource> implements ResourceDao {
|
public class InMemoryResourceDao extends InMemoryDao<Resource> implements ResourceDao {
|
||||||
|
|
||||||
|
public InMemoryResourceDao(boolean versioningEnabled) {
|
||||||
|
super(versioningEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <U> List<U> doQuery(ResourceQuery<U> resourceQuery) {
|
public <U> List<U> doQuery(ResourceQuery<U> resourceQuery) {
|
||||||
InMemoryResourceQueryVisitor visitor = new InMemoryResourceQueryVisitor();
|
InMemoryResourceQueryVisitor visitor = new InMemoryResourceQueryVisitor();
|
||||||
|
|
|
@ -50,6 +50,7 @@ public class ComponentContainerTest {
|
||||||
public static final String PATH_CACHED_CONTAINER = "src/test/resources/cachedtest";
|
public static final String PATH_CACHED_CONTAINER = "src/test/resources/cachedtest";
|
||||||
public static final String PATH_EMPTY_CONTAINER = "src/test/resources/emptytest";
|
public static final String PATH_EMPTY_CONTAINER = "src/test/resources/emptytest";
|
||||||
public static final String PATH_MINIMAL_CONTAINER = "src/test/resources/minimaltest";
|
public static final String PATH_MINIMAL_CONTAINER = "src/test/resources/minimaltest";
|
||||||
|
public static final String PATH_VERSIONING_CONTAINER = "src/test/resources/versioningtest";
|
||||||
|
|
||||||
public static final String PATH_REALM_RUNTIME = "target/realmtest/";
|
public static final String PATH_REALM_RUNTIME = "target/realmtest/";
|
||||||
public static final String PATH_TRANSIENT_RUNTIME = "target/transienttest/";
|
public static final String PATH_TRANSIENT_RUNTIME = "target/transienttest/";
|
||||||
|
|
|
@ -0,0 +1,319 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package li.strolch.runtime.query.inmemory;
|
||||||
|
|
||||||
|
import static li.strolch.model.query.ParameterSelection.booleanSelection;
|
||||||
|
import static li.strolch.model.query.ParameterSelection.floatListSelection;
|
||||||
|
import static li.strolch.model.query.ParameterSelection.floatSelection;
|
||||||
|
import static li.strolch.model.query.ParameterSelection.integerListSelection;
|
||||||
|
import static li.strolch.model.query.ParameterSelection.longListSelection;
|
||||||
|
import static li.strolch.model.query.ParameterSelection.stringListSelection;
|
||||||
|
import static li.strolch.model.query.ParameterSelection.stringSelection;
|
||||||
|
import static li.strolch.utils.StringMatchMode.ci;
|
||||||
|
import static li.strolch.utils.StringMatchMode.es;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import li.strolch.model.ModelGenerator;
|
||||||
|
import li.strolch.model.Order;
|
||||||
|
import li.strolch.model.ParameterBag;
|
||||||
|
import li.strolch.model.State;
|
||||||
|
import li.strolch.model.Version;
|
||||||
|
import li.strolch.model.parameter.BooleanParameter;
|
||||||
|
import li.strolch.model.parameter.FloatListParameter;
|
||||||
|
import li.strolch.model.parameter.FloatParameter;
|
||||||
|
import li.strolch.model.parameter.IntegerListParameter;
|
||||||
|
import li.strolch.model.parameter.LongListParameter;
|
||||||
|
import li.strolch.model.parameter.StringListParameter;
|
||||||
|
import li.strolch.model.parameter.StringParameter;
|
||||||
|
import li.strolch.model.query.IdSelection;
|
||||||
|
import li.strolch.model.query.NameSelection;
|
||||||
|
import li.strolch.model.query.OrderQuery;
|
||||||
|
import li.strolch.model.query.ParameterSelection;
|
||||||
|
import li.strolch.persistence.inmemory.InMemoryOrderDao;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("nls")
|
||||||
|
public class InMemoryOrderQueryTest {
|
||||||
|
|
||||||
|
protected InMemoryOrderDao daoInstance() {
|
||||||
|
return new InMemoryOrderDao(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldQueryById() {
|
||||||
|
|
||||||
|
List<Order> orders = getOrders();
|
||||||
|
InMemoryOrderDao dao = daoInstance();
|
||||||
|
dao.saveAll(orders);
|
||||||
|
|
||||||
|
OrderQuery<Order> orderQuery = OrderQuery.query("MyType1");
|
||||||
|
orderQuery.with(new IdSelection("@1"));
|
||||||
|
|
||||||
|
List<Order> result = dao.doQuery(orderQuery);
|
||||||
|
assertEquals(1, result.size());
|
||||||
|
assertEquals("@1", result.get(0).getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldQueryByIdOr() {
|
||||||
|
|
||||||
|
List<Order> orders = getOrders();
|
||||||
|
InMemoryOrderDao dao = daoInstance();
|
||||||
|
dao.saveAll(orders);
|
||||||
|
|
||||||
|
OrderQuery<Order> orderQuery = OrderQuery.query("MyType2");
|
||||||
|
orderQuery.or().with(new IdSelection("@3"), new IdSelection("@4"));
|
||||||
|
|
||||||
|
List<Order> result = dao.doQuery(orderQuery);
|
||||||
|
assertEquals(2, result.size());
|
||||||
|
assertEquals("@3", result.get(0).getId());
|
||||||
|
assertEquals("@4", result.get(1).getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldQueryByIdAnd() {
|
||||||
|
|
||||||
|
List<Order> orders = getOrders();
|
||||||
|
InMemoryOrderDao dao = daoInstance();
|
||||||
|
dao.saveAll(orders);
|
||||||
|
|
||||||
|
OrderQuery<Order> orderQuery = OrderQuery.query("MyType2");
|
||||||
|
orderQuery.and().with(new IdSelection("@3"), new NameSelection("Res 3", es()));
|
||||||
|
|
||||||
|
List<Order> result = dao.doQuery(orderQuery);
|
||||||
|
assertEquals(1, result.size());
|
||||||
|
assertEquals("@3", result.get(0).getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotQueryByIdAnd() {
|
||||||
|
|
||||||
|
List<Order> orders = getOrders();
|
||||||
|
InMemoryOrderDao dao = daoInstance();
|
||||||
|
dao.saveAll(orders);
|
||||||
|
|
||||||
|
OrderQuery<Order> orderQuery = OrderQuery.query("MyType1");
|
||||||
|
orderQuery.and().with(new IdSelection("@3"), new NameSelection("@4", es()));
|
||||||
|
|
||||||
|
List<Order> result = dao.doQuery(orderQuery);
|
||||||
|
assertEquals(0, result.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldQueryByParameter() {
|
||||||
|
|
||||||
|
List<Order> orders = getOrders();
|
||||||
|
orders.add(getBallOrder());
|
||||||
|
InMemoryOrderDao dao = daoInstance();
|
||||||
|
dao.saveAll(orders);
|
||||||
|
|
||||||
|
OrderQuery<Order> ballQuery = OrderQuery.query("Ball");
|
||||||
|
ballQuery.and().with(
|
||||||
|
//
|
||||||
|
stringSelection("parameters", "color", "red", es()),
|
||||||
|
booleanSelection("parameters", "forChildren", true), floatSelection("parameters", "diameter", 22.0));
|
||||||
|
|
||||||
|
List<Order> result = dao.doQuery(ballQuery);
|
||||||
|
assertEquals(1, result.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldQueryByListParameter() {
|
||||||
|
|
||||||
|
List<Order> orders = getOrders();
|
||||||
|
orders.add(getBallOrder());
|
||||||
|
InMemoryOrderDao dao = daoInstance();
|
||||||
|
dao.saveAll(orders);
|
||||||
|
|
||||||
|
OrderQuery<Order> ballQuery;
|
||||||
|
List<Order> result;
|
||||||
|
|
||||||
|
// string list
|
||||||
|
{
|
||||||
|
ballQuery = OrderQuery.query("Ball");
|
||||||
|
ballQuery.and().with(stringListSelection("parameters", "stringListValues", Arrays.asList("a", "z")));
|
||||||
|
result = dao.doQuery(ballQuery);
|
||||||
|
assertEquals(0, result.size());
|
||||||
|
|
||||||
|
ballQuery = OrderQuery.query("Ball");
|
||||||
|
ballQuery.and().with(stringListSelection("parameters", "stringListValues", Arrays.asList("a")));
|
||||||
|
result = dao.doQuery(ballQuery);
|
||||||
|
assertEquals(1, result.size());
|
||||||
|
|
||||||
|
ballQuery = OrderQuery.query("Ball");
|
||||||
|
ballQuery.and().with(stringListSelection("parameters", "stringListValues", Arrays.asList("c", "b", "a")));
|
||||||
|
result = dao.doQuery(ballQuery);
|
||||||
|
assertEquals(1, result.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
// integer list
|
||||||
|
{
|
||||||
|
ballQuery = OrderQuery.query("Ball");
|
||||||
|
ballQuery.and().with(integerListSelection("parameters", "intListValues", Arrays.asList(1, 5)));
|
||||||
|
result = dao.doQuery(ballQuery);
|
||||||
|
assertEquals(0, result.size());
|
||||||
|
|
||||||
|
ballQuery = OrderQuery.query("Ball");
|
||||||
|
ballQuery.and().with(integerListSelection("parameters", "intListValues", Arrays.asList(1)));
|
||||||
|
result = dao.doQuery(ballQuery);
|
||||||
|
assertEquals(1, result.size());
|
||||||
|
|
||||||
|
ballQuery = OrderQuery.query("Ball");
|
||||||
|
ballQuery.and().with(integerListSelection("parameters", "intListValues", Arrays.asList(3, 2, 1)));
|
||||||
|
result = dao.doQuery(ballQuery);
|
||||||
|
assertEquals(1, result.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
// float list
|
||||||
|
{
|
||||||
|
ballQuery = OrderQuery.query("Ball");
|
||||||
|
ballQuery.and().with(floatListSelection("parameters", "floatListValues", Arrays.asList(4.0, 8.0)));
|
||||||
|
result = dao.doQuery(ballQuery);
|
||||||
|
assertEquals(0, result.size());
|
||||||
|
|
||||||
|
ballQuery = OrderQuery.query("Ball");
|
||||||
|
ballQuery.and().with(floatListSelection("parameters", "floatListValues", Arrays.asList(4.0)));
|
||||||
|
result = dao.doQuery(ballQuery);
|
||||||
|
assertEquals(1, result.size());
|
||||||
|
|
||||||
|
ballQuery = OrderQuery.query("Ball");
|
||||||
|
ballQuery.and().with(floatListSelection("parameters", "floatListValues", Arrays.asList(6.2, 5.1, 4.0)));
|
||||||
|
result = dao.doQuery(ballQuery);
|
||||||
|
assertEquals(1, result.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
// long list
|
||||||
|
{
|
||||||
|
ballQuery = OrderQuery.query("Ball");
|
||||||
|
ballQuery.and().with(longListSelection("parameters", "longListValues", Arrays.asList(8L, 11L)));
|
||||||
|
result = dao.doQuery(ballQuery);
|
||||||
|
assertEquals(0, result.size());
|
||||||
|
|
||||||
|
ballQuery = OrderQuery.query("Ball");
|
||||||
|
ballQuery.and().with(longListSelection("parameters", "longListValues", Arrays.asList(8L)));
|
||||||
|
result = dao.doQuery(ballQuery);
|
||||||
|
assertEquals(1, result.size());
|
||||||
|
|
||||||
|
ballQuery = OrderQuery.query("Ball");
|
||||||
|
ballQuery.and().with(longListSelection("parameters", "longListValues", Arrays.asList(10L, 9L, 8L)));
|
||||||
|
result = dao.doQuery(ballQuery);
|
||||||
|
assertEquals(1, result.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldQueryByNullParameter1() {
|
||||||
|
List<Order> orders = getOrders();
|
||||||
|
orders.add(getBallOrder());
|
||||||
|
InMemoryOrderDao dao = daoInstance();
|
||||||
|
dao.saveAll(orders);
|
||||||
|
|
||||||
|
OrderQuery<Order> ballQuery = OrderQuery.query("Ball");
|
||||||
|
ballQuery.and().with( //
|
||||||
|
ParameterSelection.nullSelection("parameters", "color"));
|
||||||
|
|
||||||
|
List<Order> result = dao.doQuery(ballQuery);
|
||||||
|
assertEquals(0, result.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldQueryByNullParameter2() {
|
||||||
|
List<Order> orders = getOrders();
|
||||||
|
orders.add(getBallOrder());
|
||||||
|
InMemoryOrderDao dao = daoInstance();
|
||||||
|
dao.saveAll(orders);
|
||||||
|
|
||||||
|
OrderQuery<Order> ballQuery = OrderQuery.query("Ball");
|
||||||
|
ballQuery.and().with( //
|
||||||
|
ParameterSelection.nullSelection("parameters", "weight"));
|
||||||
|
|
||||||
|
List<Order> result = dao.doQuery(ballQuery);
|
||||||
|
assertEquals(1, result.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldQueryByNullParameter3() {
|
||||||
|
List<Order> orders = getOrders();
|
||||||
|
orders.add(getBallOrder());
|
||||||
|
InMemoryOrderDao dao = daoInstance();
|
||||||
|
dao.saveAll(orders);
|
||||||
|
|
||||||
|
OrderQuery<Order> ballQuery = OrderQuery.query("Ball");
|
||||||
|
ballQuery.and().with( //
|
||||||
|
ParameterSelection.nullSelection("parameters", "weight"));
|
||||||
|
|
||||||
|
List<Order> result = dao.doQuery(ballQuery);
|
||||||
|
assertEquals(1, result.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldQueryByName() {
|
||||||
|
|
||||||
|
List<Order> orders = getOrders();
|
||||||
|
orders.add(getBallOrder());
|
||||||
|
InMemoryOrderDao dao = daoInstance();
|
||||||
|
dao.saveAll(orders);
|
||||||
|
|
||||||
|
OrderQuery<Order> ballQuery = OrderQuery.query("Ball");
|
||||||
|
ballQuery.with(new NameSelection("ball ", ci()));
|
||||||
|
|
||||||
|
List<Order> result = dao.doQuery(ballQuery);
|
||||||
|
assertEquals(1, result.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Order getBallOrder() {
|
||||||
|
Order o1 = new Order("childrensBall", "Ball 1", "Ball");
|
||||||
|
o1.setVersion(new Version(o1.getLocator(), 0, "ModelGenerator", false));
|
||||||
|
ParameterBag bag = new ParameterBag("parameters", "Ball Details", "Parameters");
|
||||||
|
bag.addParameter(new StringParameter("color", "Color", "red"));
|
||||||
|
bag.addParameter(new BooleanParameter("forChildren", "Color", true));
|
||||||
|
bag.addParameter(new FloatParameter("diameter", "Color", 22.0));
|
||||||
|
bag.addParameter(
|
||||||
|
new StringListParameter("stringListValues", "List of String Values", Arrays.asList("a", "b", "c")));
|
||||||
|
bag.addParameter(new IntegerListParameter("intListValues", "List of Integer Values", Arrays.asList(1, 2, 3)));
|
||||||
|
bag.addParameter(
|
||||||
|
new FloatListParameter("floatListValues", "List of Float Values", Arrays.asList(4.0, 5.1, 6.2)));
|
||||||
|
bag.addParameter(new LongListParameter("longListValues", "List of Long Values", Arrays.asList(8L, 9L, 10L)));
|
||||||
|
o1.addParameterBag(bag);
|
||||||
|
return o1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Order> getOrders() {
|
||||||
|
Order res1 = ModelGenerator.createOrder("@1", "Res 1", "MyType1", new Date(), State.CREATED);
|
||||||
|
Order res2 = ModelGenerator.createOrder("@2", "Res 2", "MyType1", new Date(), State.CREATED);
|
||||||
|
Order res3 = ModelGenerator.createOrder("@3", "Res 3", "MyType2", new Date(), State.CREATED);
|
||||||
|
Order res4 = ModelGenerator.createOrder("@4", "Res 4", "MyType2", new Date(), State.CREATED);
|
||||||
|
Order res5 = ModelGenerator.createOrder("@5", "Res 5", "MyType3", new Date(), State.CREATED);
|
||||||
|
Order res6 = ModelGenerator.createOrder("@6", "Res 6", "MyType3", new Date(), State.CREATED);
|
||||||
|
List<Order> orders = new ArrayList<>();
|
||||||
|
orders.add(res1);
|
||||||
|
orders.add(res2);
|
||||||
|
orders.add(res3);
|
||||||
|
orders.add(res4);
|
||||||
|
orders.add(res5);
|
||||||
|
orders.add(res6);
|
||||||
|
return orders;
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package li.strolch.persistence.inmemory;
|
package li.strolch.runtime.query.inmemory;
|
||||||
|
|
||||||
import li.strolch.agent.api.ComponentContainer;
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
import li.strolch.agent.api.StrolchComponent;
|
import li.strolch.agent.api.StrolchComponent;
|
||||||
|
@ -24,6 +24,7 @@ import li.strolch.persistence.api.OrderDao;
|
||||||
import li.strolch.persistence.api.PersistenceHandler;
|
import li.strolch.persistence.api.PersistenceHandler;
|
||||||
import li.strolch.persistence.api.ResourceDao;
|
import li.strolch.persistence.api.ResourceDao;
|
||||||
import li.strolch.persistence.api.StrolchTransaction;
|
import li.strolch.persistence.api.StrolchTransaction;
|
||||||
|
import li.strolch.persistence.inmemory.InMemoryPersistence;
|
||||||
import li.strolch.privilege.model.Certificate;
|
import li.strolch.privilege.model.Certificate;
|
||||||
import li.strolch.runtime.configuration.ComponentConfiguration;
|
import li.strolch.runtime.configuration.ComponentConfiguration;
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ public class InMemoryPersistenceHandler extends StrolchComponent implements Pers
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(ComponentConfiguration configuration) throws Exception {
|
public void initialize(ComponentConfiguration configuration) throws Exception {
|
||||||
this.persistence = new InMemoryPersistence(getContainer().getPrivilegeHandler());
|
this.persistence = new InMemoryPersistence(getContainer().getPrivilegeHandler(), false);
|
||||||
super.initialize(configuration);
|
super.initialize(configuration);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,3 @@
|
||||||
/*
|
|
||||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package li.strolch.runtime.query.inmemory;
|
package li.strolch.runtime.query.inmemory;
|
||||||
|
|
||||||
import static li.strolch.model.query.ParameterSelection.booleanSelection;
|
import static li.strolch.model.query.ParameterSelection.booleanSelection;
|
||||||
|
@ -28,14 +13,14 @@ import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import li.strolch.model.ModelGenerator;
|
import li.strolch.model.ModelGenerator;
|
||||||
import li.strolch.model.Order;
|
|
||||||
import li.strolch.model.ParameterBag;
|
import li.strolch.model.ParameterBag;
|
||||||
import li.strolch.model.Resource;
|
import li.strolch.model.Resource;
|
||||||
import li.strolch.model.State;
|
import li.strolch.model.Version;
|
||||||
import li.strolch.model.parameter.BooleanParameter;
|
import li.strolch.model.parameter.BooleanParameter;
|
||||||
import li.strolch.model.parameter.FloatListParameter;
|
import li.strolch.model.parameter.FloatListParameter;
|
||||||
import li.strolch.model.parameter.FloatParameter;
|
import li.strolch.model.parameter.FloatParameter;
|
||||||
|
@ -45,39 +30,21 @@ import li.strolch.model.parameter.StringListParameter;
|
||||||
import li.strolch.model.parameter.StringParameter;
|
import li.strolch.model.parameter.StringParameter;
|
||||||
import li.strolch.model.query.IdSelection;
|
import li.strolch.model.query.IdSelection;
|
||||||
import li.strolch.model.query.NameSelection;
|
import li.strolch.model.query.NameSelection;
|
||||||
import li.strolch.model.query.OrderQuery;
|
|
||||||
import li.strolch.model.query.ParameterSelection;
|
import li.strolch.model.query.ParameterSelection;
|
||||||
import li.strolch.model.query.ResourceQuery;
|
import li.strolch.model.query.ResourceQuery;
|
||||||
import li.strolch.persistence.inmemory.InMemoryOrderDao;
|
|
||||||
import li.strolch.persistence.inmemory.InMemoryResourceDao;
|
import li.strolch.persistence.inmemory.InMemoryResourceDao;
|
||||||
|
|
||||||
import org.junit.Test;
|
public class InMemoryResourceQueryTest {
|
||||||
|
|
||||||
/**
|
protected InMemoryResourceDao daoInstance() {
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
return new InMemoryResourceDao(false);
|
||||||
*/
|
|
||||||
@SuppressWarnings("nls")
|
|
||||||
public class InMemoryQueryTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void shouldQueryOrderById() {
|
|
||||||
|
|
||||||
List<Order> orders = getOrders();
|
|
||||||
InMemoryOrderDao dao = new InMemoryOrderDao();
|
|
||||||
dao.saveAll(orders);
|
|
||||||
|
|
||||||
OrderQuery<Order> orderQuery = OrderQuery.query("MyType1");
|
|
||||||
orderQuery.with(new IdSelection("@1"));
|
|
||||||
List<Order> result = dao.doQuery(orderQuery);
|
|
||||||
assertEquals(1, result.size());
|
|
||||||
assertEquals("@1", result.get(0).getId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldQueryResourceById() {
|
public void shouldQueryById() {
|
||||||
|
|
||||||
List<Resource> resources = getResources();
|
List<Resource> resources = getResources();
|
||||||
InMemoryResourceDao dao = new InMemoryResourceDao();
|
InMemoryResourceDao dao = daoInstance();
|
||||||
dao.saveAll(resources);
|
dao.saveAll(resources);
|
||||||
|
|
||||||
ResourceQuery<Resource> resourceQuery = ResourceQuery.query("MyType1");
|
ResourceQuery<Resource> resourceQuery = ResourceQuery.query("MyType1");
|
||||||
|
@ -89,10 +56,10 @@ public class InMemoryQueryTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldQueryResourceByIdOr() {
|
public void shouldQueryByIdOr() {
|
||||||
|
|
||||||
List<Resource> resources = getResources();
|
List<Resource> resources = getResources();
|
||||||
InMemoryResourceDao dao = new InMemoryResourceDao();
|
InMemoryResourceDao dao = daoInstance();
|
||||||
dao.saveAll(resources);
|
dao.saveAll(resources);
|
||||||
|
|
||||||
ResourceQuery<Resource> resourceQuery = ResourceQuery.query("MyType2");
|
ResourceQuery<Resource> resourceQuery = ResourceQuery.query("MyType2");
|
||||||
|
@ -105,10 +72,10 @@ public class InMemoryQueryTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldQueryResourceByIdAnd() {
|
public void shouldQueryByIdAnd() {
|
||||||
|
|
||||||
List<Resource> resources = getResources();
|
List<Resource> resources = getResources();
|
||||||
InMemoryResourceDao dao = new InMemoryResourceDao();
|
InMemoryResourceDao dao = daoInstance();
|
||||||
dao.saveAll(resources);
|
dao.saveAll(resources);
|
||||||
|
|
||||||
ResourceQuery<Resource> resourceQuery = ResourceQuery.query("MyType2");
|
ResourceQuery<Resource> resourceQuery = ResourceQuery.query("MyType2");
|
||||||
|
@ -120,10 +87,10 @@ public class InMemoryQueryTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldNotQueryResourceByIdAnd() {
|
public void shouldNotQueryByIdAnd() {
|
||||||
|
|
||||||
List<Resource> resources = getResources();
|
List<Resource> resources = getResources();
|
||||||
InMemoryResourceDao dao = new InMemoryResourceDao();
|
InMemoryResourceDao dao = daoInstance();
|
||||||
dao.saveAll(resources);
|
dao.saveAll(resources);
|
||||||
|
|
||||||
ResourceQuery<Resource> resourceQuery = ResourceQuery.query("MyType1");
|
ResourceQuery<Resource> resourceQuery = ResourceQuery.query("MyType1");
|
||||||
|
@ -138,7 +105,7 @@ public class InMemoryQueryTest {
|
||||||
|
|
||||||
List<Resource> resources = getResources();
|
List<Resource> resources = getResources();
|
||||||
resources.add(getBallResource());
|
resources.add(getBallResource());
|
||||||
InMemoryResourceDao dao = new InMemoryResourceDao();
|
InMemoryResourceDao dao = daoInstance();
|
||||||
dao.saveAll(resources);
|
dao.saveAll(resources);
|
||||||
|
|
||||||
ResourceQuery<Resource> ballQuery = ResourceQuery.query("Ball");
|
ResourceQuery<Resource> ballQuery = ResourceQuery.query("Ball");
|
||||||
|
@ -156,7 +123,7 @@ public class InMemoryQueryTest {
|
||||||
|
|
||||||
List<Resource> resources = getResources();
|
List<Resource> resources = getResources();
|
||||||
resources.add(getBallResource());
|
resources.add(getBallResource());
|
||||||
InMemoryResourceDao dao = new InMemoryResourceDao();
|
InMemoryResourceDao dao = daoInstance();
|
||||||
dao.saveAll(resources);
|
dao.saveAll(resources);
|
||||||
|
|
||||||
ResourceQuery<Resource> ballQuery;
|
ResourceQuery<Resource> ballQuery;
|
||||||
|
@ -239,7 +206,7 @@ public class InMemoryQueryTest {
|
||||||
public void shouldQueryByNullParameter1() {
|
public void shouldQueryByNullParameter1() {
|
||||||
List<Resource> resources = getResources();
|
List<Resource> resources = getResources();
|
||||||
resources.add(getBallResource());
|
resources.add(getBallResource());
|
||||||
InMemoryResourceDao dao = new InMemoryResourceDao();
|
InMemoryResourceDao dao = daoInstance();
|
||||||
dao.saveAll(resources);
|
dao.saveAll(resources);
|
||||||
|
|
||||||
ResourceQuery<Resource> ballQuery = ResourceQuery.query("Ball");
|
ResourceQuery<Resource> ballQuery = ResourceQuery.query("Ball");
|
||||||
|
@ -254,7 +221,7 @@ public class InMemoryQueryTest {
|
||||||
public void shouldQueryByNullParameter2() {
|
public void shouldQueryByNullParameter2() {
|
||||||
List<Resource> resources = getResources();
|
List<Resource> resources = getResources();
|
||||||
resources.add(getBallResource());
|
resources.add(getBallResource());
|
||||||
InMemoryResourceDao dao = new InMemoryResourceDao();
|
InMemoryResourceDao dao = daoInstance();
|
||||||
dao.saveAll(resources);
|
dao.saveAll(resources);
|
||||||
|
|
||||||
ResourceQuery<Resource> ballQuery = ResourceQuery.query("Ball");
|
ResourceQuery<Resource> ballQuery = ResourceQuery.query("Ball");
|
||||||
|
@ -269,7 +236,7 @@ public class InMemoryQueryTest {
|
||||||
public void shouldQueryByNullParameter3() {
|
public void shouldQueryByNullParameter3() {
|
||||||
List<Resource> resources = getResources();
|
List<Resource> resources = getResources();
|
||||||
resources.add(getBallResource());
|
resources.add(getBallResource());
|
||||||
InMemoryResourceDao dao = new InMemoryResourceDao();
|
InMemoryResourceDao dao = daoInstance();
|
||||||
dao.saveAll(resources);
|
dao.saveAll(resources);
|
||||||
|
|
||||||
ResourceQuery<Resource> ballQuery = ResourceQuery.query("Ball");
|
ResourceQuery<Resource> ballQuery = ResourceQuery.query("Ball");
|
||||||
|
@ -285,7 +252,7 @@ public class InMemoryQueryTest {
|
||||||
|
|
||||||
List<Resource> resources = getResources();
|
List<Resource> resources = getResources();
|
||||||
resources.add(getBallResource());
|
resources.add(getBallResource());
|
||||||
InMemoryResourceDao dao = new InMemoryResourceDao();
|
InMemoryResourceDao dao = daoInstance();
|
||||||
dao.saveAll(resources);
|
dao.saveAll(resources);
|
||||||
|
|
||||||
ResourceQuery<Resource> ballQuery = ResourceQuery.query("Ball");
|
ResourceQuery<Resource> ballQuery = ResourceQuery.query("Ball");
|
||||||
|
@ -297,14 +264,16 @@ public class InMemoryQueryTest {
|
||||||
|
|
||||||
private Resource getBallResource() {
|
private Resource getBallResource() {
|
||||||
Resource res1 = new Resource("childrensBall", "Ball 1", "Ball");
|
Resource res1 = new Resource("childrensBall", "Ball 1", "Ball");
|
||||||
|
res1.setVersion(new Version(res1.getLocator(), 0, "ModelGenerator", false));
|
||||||
ParameterBag bag = new ParameterBag("parameters", "Ball Details", "Parameters");
|
ParameterBag bag = new ParameterBag("parameters", "Ball Details", "Parameters");
|
||||||
bag.addParameter(new StringParameter("color", "Color", "red"));
|
bag.addParameter(new StringParameter("color", "Color", "red"));
|
||||||
bag.addParameter(new BooleanParameter("forChildren", "Color", true));
|
bag.addParameter(new BooleanParameter("forChildren", "Color", true));
|
||||||
bag.addParameter(new FloatParameter("diameter", "Color", 22.0));
|
bag.addParameter(new FloatParameter("diameter", "Color", 22.0));
|
||||||
bag.addParameter(new StringListParameter("stringListValues", "List of String Values", Arrays.asList("a", "b",
|
bag.addParameter(
|
||||||
"c")));
|
new StringListParameter("stringListValues", "List of String Values", Arrays.asList("a", "b", "c")));
|
||||||
bag.addParameter(new IntegerListParameter("intListValues", "List of Integer Values", Arrays.asList(1, 2, 3)));
|
bag.addParameter(new IntegerListParameter("intListValues", "List of Integer Values", Arrays.asList(1, 2, 3)));
|
||||||
bag.addParameter(new FloatListParameter("floatListValues", "List of Float Values", Arrays.asList(4.0, 5.1, 6.2)));
|
bag.addParameter(
|
||||||
|
new FloatListParameter("floatListValues", "List of Float Values", Arrays.asList(4.0, 5.1, 6.2)));
|
||||||
bag.addParameter(new LongListParameter("longListValues", "List of Long Values", Arrays.asList(8L, 9L, 10L)));
|
bag.addParameter(new LongListParameter("longListValues", "List of Long Values", Arrays.asList(8L, 9L, 10L)));
|
||||||
res1.addParameterBag(bag);
|
res1.addParameterBag(bag);
|
||||||
return res1;
|
return res1;
|
||||||
|
@ -324,23 +293,11 @@ public class InMemoryQueryTest {
|
||||||
resources.add(res4);
|
resources.add(res4);
|
||||||
resources.add(res5);
|
resources.add(res5);
|
||||||
resources.add(res6);
|
resources.add(res6);
|
||||||
return resources;
|
|
||||||
|
for (Resource resource : resources) {
|
||||||
|
resource.setVersion(new Version(resource.getLocator(), 0, "Test", false));
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Order> getOrders() {
|
return resources;
|
||||||
Order res1 = ModelGenerator.createOrder("@1", "Res 1", "MyType1", new Date(), State.CREATED);
|
|
||||||
Order res2 = ModelGenerator.createOrder("@2", "Res 2", "MyType1", new Date(), State.CREATED);
|
|
||||||
Order res3 = ModelGenerator.createOrder("@3", "Res 3", "MyType2", new Date(), State.CREATED);
|
|
||||||
Order res4 = ModelGenerator.createOrder("@4", "Res 4", "MyType2", new Date(), State.CREATED);
|
|
||||||
Order res5 = ModelGenerator.createOrder("@5", "Res 5", "MyType3", new Date(), State.CREATED);
|
|
||||||
Order res6 = ModelGenerator.createOrder("@6", "Res 6", "MyType3", new Date(), State.CREATED);
|
|
||||||
List<Order> orders = new ArrayList<>();
|
|
||||||
orders.add(res1);
|
|
||||||
orders.add(res2);
|
|
||||||
orders.add(res3);
|
|
||||||
orders.add(res4);
|
|
||||||
orders.add(res5);
|
|
||||||
orders.add(res6);
|
|
||||||
return orders;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -44,7 +44,7 @@
|
||||||
<Component>
|
<Component>
|
||||||
<name>PersistenceHandler</name>
|
<name>PersistenceHandler</name>
|
||||||
<api>li.strolch.persistence.api.PersistenceHandler</api>
|
<api>li.strolch.persistence.api.PersistenceHandler</api>
|
||||||
<impl>li.strolch.persistence.inmemory.InMemoryPersistenceHandler</impl>
|
<impl>li.strolch.runtime.query.inmemory.InMemoryPersistenceHandler</impl>
|
||||||
</Component>
|
</Component>
|
||||||
</env>
|
</env>
|
||||||
</StrolchConfiguration>
|
</StrolchConfiguration>
|
|
@ -19,7 +19,7 @@
|
||||||
<Component>
|
<Component>
|
||||||
<name>PersistenceHandler</name>
|
<name>PersistenceHandler</name>
|
||||||
<api>li.strolch.persistence.api.PersistenceHandler</api>
|
<api>li.strolch.persistence.api.PersistenceHandler</api>
|
||||||
<impl>li.strolch.persistence.inmemory.InMemoryPersistenceHandler</impl>
|
<impl>li.strolch.runtime.query.inmemory.InMemoryPersistenceHandler</impl>
|
||||||
</Component>
|
</Component>
|
||||||
<Component>
|
<Component>
|
||||||
<name>RealmHandler</name>
|
<name>RealmHandler</name>
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
<Component>
|
<Component>
|
||||||
<name>PersistenceHandler</name>
|
<name>PersistenceHandler</name>
|
||||||
<api>li.strolch.persistence.api.PersistenceHandler</api>
|
<api>li.strolch.persistence.api.PersistenceHandler</api>
|
||||||
<impl>li.strolch.persistence.inmemory.InMemoryPersistenceHandler</impl>
|
<impl>li.strolch.runtime.query.inmemory.InMemoryPersistenceHandler</impl>
|
||||||
</Component>
|
</Component>
|
||||||
</env>
|
</env>
|
||||||
</StrolchConfiguration>
|
</StrolchConfiguration>
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Privilege>
|
||||||
|
|
||||||
|
<Container>
|
||||||
|
|
||||||
|
<Parameters>
|
||||||
|
<!-- parameters for the container itself -->
|
||||||
|
<Parameter name="autoPersistOnUserChangesData" value="true" />
|
||||||
|
</Parameters>
|
||||||
|
|
||||||
|
<EncryptionHandler class="li.strolch.privilege.handler.DefaultEncryptionHandler">
|
||||||
|
<Parameters>
|
||||||
|
<Parameter name="hashAlgorithm" value="SHA-256" />
|
||||||
|
</Parameters>
|
||||||
|
</EncryptionHandler>
|
||||||
|
|
||||||
|
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler">
|
||||||
|
<Parameters>
|
||||||
|
<Parameter name="usersXmlFile" value="PrivilegeUsers.xml" />
|
||||||
|
<Parameter name="rolesXmlFile" value="PrivilegeRoles.xml" />
|
||||||
|
</Parameters>
|
||||||
|
</PersistenceHandler>
|
||||||
|
|
||||||
|
</Container>
|
||||||
|
|
||||||
|
<Policies>
|
||||||
|
<Policy name="DefaultPrivilege" class="li.strolch.privilege.policy.DefaultPrivilege" />
|
||||||
|
<Policy name="RoleAccessPrivilege" class="li.strolch.privilege.policy.RoleAccessPrivilege" />
|
||||||
|
<Policy name="UserAccessPrivilege" class="li.strolch.privilege.policy.UserAccessPrivilege" />
|
||||||
|
</Policies>
|
||||||
|
|
||||||
|
</Privilege>
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Roles>
|
||||||
|
<Role name="agent">
|
||||||
|
<Privilege name="li.strolch.privilege.handler.SystemUserAction" policy="DefaultPrivilege">
|
||||||
|
<Allow>li.strolch.agent.impl.StartRealms</Allow>
|
||||||
|
</Privilege>
|
||||||
|
</Role>
|
||||||
|
<Role name="AppUser">
|
||||||
|
<Privilege name="li.strolch.service.api.Service" policy="DefaultPrivilege">
|
||||||
|
<AllAllowed>true</AllAllowed>
|
||||||
|
</Privilege>
|
||||||
|
<Privilege name="li.strolch.model.query.StrolchQuery" policy="DefaultPrivilege">
|
||||||
|
<AllAllowed>true</AllAllowed>
|
||||||
|
</Privilege>
|
||||||
|
</Role>
|
||||||
|
</Roles>
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Users>
|
||||||
|
<User userId="1" username="agent">
|
||||||
|
<State>SYSTEM</State>
|
||||||
|
<Roles>
|
||||||
|
<Role>agent</Role>
|
||||||
|
</Roles>
|
||||||
|
</User>
|
||||||
|
<User userId="2" username="test" password="9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08">
|
||||||
|
<Firstname>Application</Firstname>
|
||||||
|
<Lastname>Administrator</Lastname>
|
||||||
|
<State>ENABLED</State>
|
||||||
|
<Locale>en_GB</Locale>
|
||||||
|
<Roles>
|
||||||
|
<Role>AppUser</Role>
|
||||||
|
</Roles>
|
||||||
|
</User>
|
||||||
|
</Users>
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<StrolchConfiguration>
|
||||||
|
<env id="dev">
|
||||||
|
<Runtime>
|
||||||
|
<applicationName>StrolchRuntimeTest</applicationName>
|
||||||
|
<Properties>
|
||||||
|
<verbose>true</verbose>
|
||||||
|
</Properties>
|
||||||
|
</Runtime>
|
||||||
|
<Component>
|
||||||
|
<name>PrivilegeHandler</name>
|
||||||
|
<api>li.strolch.runtime.privilege.PrivilegeHandler</api>
|
||||||
|
<impl>li.strolch.runtime.privilege.DefaultStrolchPrivilegeHandler</impl>
|
||||||
|
<Properties>
|
||||||
|
<privilegeConfigFile>PrivilegeConfig.xml</privilegeConfigFile>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component>
|
||||||
|
<name>RealmHandler</name>
|
||||||
|
<api>li.strolch.agent.api.RealmHandler</api>
|
||||||
|
<impl>li.strolch.agent.impl.DefaultRealmHandler</impl>
|
||||||
|
<depends>PrivilegeHandler</depends>
|
||||||
|
<Properties>
|
||||||
|
<enableVersioning>true</enableVersioning>
|
||||||
|
<dataStoreMode>TRANSIENT</dataStoreMode>
|
||||||
|
<dataStoreFile>StrolchModel.xml</dataStoreFile>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component>
|
||||||
|
<name>ServiceHandler</name>
|
||||||
|
<api>li.strolch.runtime.configuration.model.ServiceHandlerTest</api>
|
||||||
|
<impl>li.strolch.runtime.configuration.model.ServiceHandlerTestImpl</impl>
|
||||||
|
<depends>RealmHandler</depends>
|
||||||
|
<Properties>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component>
|
||||||
|
<name>PostInitializer</name>
|
||||||
|
<api>li.strolch.runtime.configuration.model.PostInitializerTest</api>
|
||||||
|
<impl>li.strolch.runtime.configuration.model.PostInitializerTestImpl</impl>
|
||||||
|
<depends>ServiceHandler</depends>
|
||||||
|
<Properties>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
</env>
|
||||||
|
</StrolchConfiguration>
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||||
|
<StrolchModel>
|
||||||
|
<Order Id="MyTestOrder" Name="Test Name" Type="TestType" Date="2013-11-20T07:42:57.699+01:00" State="CREATED">
|
||||||
|
<ParameterBag Id="@bag01" Name="Test Bag" Type="TestBag">
|
||||||
|
<Parameter Id="@param7" Name="StringList Param" Type="StringList" Value="Hello;World" />
|
||||||
|
<Parameter Id="@param6" Name="Date Param" Type="Date" Value="2012-11-30T18:12:05.628+01:00" />
|
||||||
|
<Parameter Id="@param5" Name="String Param" Type="String" Value="Strolch" />
|
||||||
|
<Parameter Id="@param4" Name="Long Param" Type="Long" Value="4453234566" />
|
||||||
|
<Parameter Id="@param3" Name="Integer Param" Type="Integer" Value="77" />
|
||||||
|
<Parameter Id="@param2" Name="Float Param" Type="Float" Value="44.3" />
|
||||||
|
<Parameter Id="@param1" Name="Boolean Param" Type="Boolean" Value="true" />
|
||||||
|
</ParameterBag>
|
||||||
|
</Order>
|
||||||
|
</StrolchModel>
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||||
|
<StrolchModel>
|
||||||
|
<Resource Id="MyTestResource" Name="Test Name" Type="TestType">
|
||||||
|
<ParameterBag Id="@bag01" Name="Test Bag" Type="TestBag">
|
||||||
|
<Parameter Id="@param7" Name="StringList Param" Type="StringList" Value="Hello;World" />
|
||||||
|
<Parameter Id="@param6" Name="Date Param" Type="Date" Value="2012-11-30T18:12:05.628+01:00" />
|
||||||
|
<Parameter Id="@param5" Name="String Param" Type="String" Value="Strolch" />
|
||||||
|
<Parameter Id="@param4" Name="Long Param" Type="Long" Value="4453234566" />
|
||||||
|
<Parameter Id="@param3" Name="Integer Param" Type="Integer" Value="77" />
|
||||||
|
<Parameter Id="@param2" Name="Float Param" Type="Float" Value="44.3" />
|
||||||
|
<Parameter Id="@param1" Name="Boolean Param" Type="Boolean" Value="true" />
|
||||||
|
</ParameterBag>
|
||||||
|
</Resource>
|
||||||
|
</StrolchModel>
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<StrolchModel>
|
||||||
|
<Resource Id="TestType" Name="TestType Template" Type="Template">
|
||||||
|
<ParameterBag Id="@bag01" Name="Test Bag" Type="TestBag">
|
||||||
|
<Parameter Id="@param7" Name="StringList Param" Type="StringList" Value="Hello;World" />
|
||||||
|
<Parameter Id="@param6" Name="Date Param" Type="Date" Value="2012-11-30T18:12:05.628+01:00" />
|
||||||
|
<Parameter Id="@param5" Name="String Param" Type="String" Value="Strolch" />
|
||||||
|
<Parameter Id="@param4" Name="Long Param" Type="Long" Value="4453234566" />
|
||||||
|
<Parameter Id="@param3" Name="Integer Param" Type="Integer" Value="77" />
|
||||||
|
<Parameter Id="@param2" Name="Float Param" Type="Float" Value="44.3" />
|
||||||
|
<Parameter Id="@param1" Name="Boolean Param" Type="Boolean" Value="true" />
|
||||||
|
</ParameterBag>
|
||||||
|
</Resource>
|
||||||
|
<Order Id="MyTestOrder" Name="MyTestOrder Template" Type="Template">
|
||||||
|
<ParameterBag Id="@bag01" Name="Test Bag" Type="TestBag">
|
||||||
|
<Parameter Id="@param7" Name="StringList Param" Type="StringList" Value="Hello;World" />
|
||||||
|
<Parameter Id="@param6" Name="Date Param" Type="Date" Value="2012-11-30T18:12:05.628+01:00" />
|
||||||
|
<Parameter Id="@param5" Name="String Param" Type="String" Value="Strolch" />
|
||||||
|
<Parameter Id="@param4" Name="Long Param" Type="Long" Value="4453234566" />
|
||||||
|
<Parameter Id="@param3" Name="Integer Param" Type="Integer" Value="77" />
|
||||||
|
<Parameter Id="@param2" Name="Float Param" Type="Float" Value="44.3" />
|
||||||
|
<Parameter Id="@param1" Name="Boolean Param" Type="Boolean" Value="true" />
|
||||||
|
</ParameterBag>
|
||||||
|
</Order>
|
||||||
|
|
||||||
|
<IncludeFile file="Resources.xml" />
|
||||||
|
<IncludeFile file="Orders.xml" />
|
||||||
|
|
||||||
|
</StrolchModel>
|
|
@ -22,6 +22,7 @@ import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import li.strolch.exception.StrolchException;
|
import li.strolch.exception.StrolchException;
|
||||||
|
import li.strolch.utils.dbc.DBC;
|
||||||
import li.strolch.utils.helper.StringHelper;
|
import li.strolch.utils.helper.StringHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -126,6 +127,11 @@ public class Locator {
|
||||||
this.pathElements = Collections.unmodifiableList(fullPath);
|
this.pathElements = Collections.unmodifiableList(fullPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String get(int part) {
|
||||||
|
DBC.PRE.assertTrue("Part outside of locator range: " + part, part < this.pathElements.size());
|
||||||
|
return this.pathElements.get(part);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the immutable list of path elements making up this locator
|
* Returns the immutable list of path elements making up this locator
|
||||||
*
|
*
|
||||||
|
|
|
@ -346,6 +346,33 @@ public class ModelGenerator {
|
||||||
return orders;
|
return orders;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a list of {@link Activity Activities} with the given values and adds a {@link ParameterBag} by calling
|
||||||
|
* {@link #createParameterBag(String, String, String)}
|
||||||
|
*
|
||||||
|
* @param idStart
|
||||||
|
* id range start
|
||||||
|
* @param count
|
||||||
|
* the number of elements to create
|
||||||
|
* @param idPrefix
|
||||||
|
* the prefix to generate IDs for the {@link Activity Activities}
|
||||||
|
* @param name
|
||||||
|
* the name of the {@link Activity}
|
||||||
|
* @param type
|
||||||
|
* the type of the {@link Activity}
|
||||||
|
*
|
||||||
|
* @return the list of newly created {@link Activity Activities}
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static List<Activity> createActivities(int idStart, int count, String idPrefix, String name, String type) {
|
||||||
|
List<Activity> activities = new ArrayList<>();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
String id = StringHelper.normalizeLength(String.valueOf((i + idStart)), 8, true, '0');
|
||||||
|
activities.add(createActivity(idPrefix + id, name + " " + i, type));
|
||||||
|
}
|
||||||
|
return activities;
|
||||||
|
}
|
||||||
|
|
||||||
public static Activity createActivity(String id, String name, String type) {
|
public static Activity createActivity(String id, String name, String type) {
|
||||||
|
|
||||||
Activity rootActivity = new Activity(id, name, type);
|
Activity rootActivity = new Activity(id, name, type);
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package li.strolch.model;
|
package li.strolch.model;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import li.strolch.exception.StrolchPolicyException;
|
import li.strolch.exception.StrolchPolicyException;
|
||||||
|
@ -86,8 +87,11 @@ public class Order extends GroupedParameterizedElement implements StrolchRootEle
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setVersion(Version version) throws IllegalArgumentException, IllegalStateException {
|
public void setVersion(Version version) throws IllegalArgumentException, IllegalStateException {
|
||||||
if (this.version != null)
|
if (version != null && !getLocator().equals(version.getLocator())) {
|
||||||
this.version.validateIsNext(version);
|
String msg = "Illegal version as locator is not same: Element: {0} Version: {1}";
|
||||||
|
throw new IllegalArgumentException(MessageFormat.format(msg, getLocator(), version));
|
||||||
|
}
|
||||||
|
|
||||||
this.version = version;
|
this.version = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package li.strolch.model;
|
package li.strolch.model;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -66,8 +67,11 @@ public class Resource extends GroupedParameterizedElement implements StrolchRoot
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setVersion(Version version) throws IllegalArgumentException, IllegalStateException {
|
public void setVersion(Version version) throws IllegalArgumentException, IllegalStateException {
|
||||||
if (this.version != null)
|
if (version != null && !getLocator().equals(version.getLocator())) {
|
||||||
this.version.validateIsNext(version);
|
String msg = "Illegal version as locator is not same: Element: {0} Version: {1}";
|
||||||
|
throw new IllegalArgumentException(MessageFormat.format(msg, getLocator(), version));
|
||||||
|
}
|
||||||
|
|
||||||
this.version = version;
|
this.version = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,6 +144,7 @@ public class Resource extends GroupedParameterizedElement implements StrolchRoot
|
||||||
@Override
|
@Override
|
||||||
public Resource getClone() {
|
public Resource getClone() {
|
||||||
Resource clone = new Resource();
|
Resource clone = new Resource();
|
||||||
|
|
||||||
super.fillClone(clone);
|
super.fillClone(clone);
|
||||||
|
|
||||||
if (this.timedStateMap != null) {
|
if (this.timedStateMap != null) {
|
||||||
|
|
|
@ -34,23 +34,16 @@ public interface StrolchRootElement extends StrolchElement, PolicyContainer, Par
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* Sets the version of this object.
|
* Sets the version of this object
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* <b>Note:</b> If the version is set, then the new version must have the {@link Version#getVersion()} be an
|
|
||||||
* increment to the current version!
|
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param version
|
* @param version
|
||||||
* the version to set
|
* the version to set
|
||||||
*
|
*
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if the given version's locator is not equal to the current version's locator
|
* if the given version's locator is not equal to the current element's locator
|
||||||
* @throws IllegalStateException
|
|
||||||
* if the given version is not the next version (an increment)
|
|
||||||
*/
|
*/
|
||||||
public void setVersion(Version version) throws IllegalArgumentException, IllegalStateException;
|
public void setVersion(Version version) throws IllegalArgumentException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visitor pattern accept method. Takes a {@link StrolchRootElementVisitor} to visit this element
|
* Visitor pattern accept method. Takes a {@link StrolchRootElementVisitor} to visit this element
|
||||||
|
|
|
@ -20,6 +20,10 @@ import li.strolch.utils.dbc.DBC;
|
||||||
* A version has a flag <code>delete</code> which, if true, designates that this version was removed
|
* A version has a flag <code>delete</code> which, if true, designates that this version was removed
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
|
* <p>
|
||||||
|
* A {@link Version} is immutable
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
*/
|
*/
|
||||||
public class Version {
|
public class Version {
|
||||||
|
@ -34,12 +38,12 @@ public class Version {
|
||||||
* Creates a new version instance with the given values. The creation date is now.
|
* Creates a new version instance with the given values. The creation date is now.
|
||||||
*
|
*
|
||||||
* @param version
|
* @param version
|
||||||
* the integer version which must be > 0 and should be incremented for each new version of an object
|
* the integer version which must be >= 0 and should be incremented for each new version of an object
|
||||||
* @param createdBy
|
* @param createdBy
|
||||||
* the username of the creator of this object
|
* the username of the creator of this object
|
||||||
*/
|
*/
|
||||||
public Version(Locator locator, int version, String createdBy, boolean deleted) {
|
public Version(Locator locator, int version, String createdBy, boolean deleted) {
|
||||||
DBC.PRE.assertTrue("Version must by > 0", version > 0);
|
DBC.PRE.assertTrue("Version must by >= 0", version >= 0);
|
||||||
DBC.PRE.assertNotNull("locator must be set!", locator);
|
DBC.PRE.assertNotNull("locator must be set!", locator);
|
||||||
DBC.PRE.assertNotNull("createdBy must be set!", createdBy);
|
DBC.PRE.assertNotNull("createdBy must be set!", createdBy);
|
||||||
this.locator = locator;
|
this.locator = locator;
|
||||||
|
@ -54,7 +58,7 @@ public class Version {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the integer version, which is > 0
|
* Returns the integer version, which is >= 0
|
||||||
*
|
*
|
||||||
* @return the version
|
* @return the version
|
||||||
*/
|
*/
|
||||||
|
@ -123,7 +127,7 @@ public class Version {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates that the given argument is an increment to this version
|
* Validates that the given argument is a newer version to this version
|
||||||
*
|
*
|
||||||
* @param other
|
* @param other
|
||||||
* the other version to check
|
* the other version to check
|
||||||
|
@ -133,14 +137,14 @@ public class Version {
|
||||||
* @throws IllegalStateException
|
* @throws IllegalStateException
|
||||||
* if the given argument is not the next version
|
* if the given argument is not the next version
|
||||||
*/
|
*/
|
||||||
public void validateIsNext(Version other) throws IllegalArgumentException, IllegalStateException {
|
public void validateIsNewer(Version other) throws IllegalArgumentException, IllegalStateException {
|
||||||
if (!this.locator.equals(other.locator)) {
|
if (!this.locator.equals(other.locator)) {
|
||||||
String msg = "Other version {0} is not for same object: {1}";
|
String msg = "Other version {0} is not for same object: {1}";
|
||||||
throw new IllegalArgumentException(MessageFormat.format(msg, other, this.version));
|
throw new IllegalArgumentException(MessageFormat.format(msg, other, this.version));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (other.version != this.version + 1) {
|
if (this.version >= other.version) {
|
||||||
String msg = "Other version: {0} is not an increment to this version: {1}";
|
String msg = "Other version: {0} is a newer version of this version: {1}";
|
||||||
throw new IllegalArgumentException(MessageFormat.format(msg, other, this.version));
|
throw new IllegalArgumentException(MessageFormat.format(msg, other, this.version));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -161,4 +165,80 @@ public class Version {
|
||||||
builder.append("]");
|
builder.append("]");
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the next version, i.e. this version incremented by 1
|
||||||
|
*
|
||||||
|
* @param username
|
||||||
|
* the username to set
|
||||||
|
* @param deleted
|
||||||
|
* the deleted flag to set
|
||||||
|
*
|
||||||
|
* @return the next version
|
||||||
|
*/
|
||||||
|
public Version next(String username, boolean deleted) {
|
||||||
|
return new Version(this.locator, getNextVersion(), username, deleted);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the initial version = 0 for the given element which is also set to not deleted
|
||||||
|
*
|
||||||
|
* @param element
|
||||||
|
* the element for which to create a new version
|
||||||
|
* @param username
|
||||||
|
* the username of the user who created this version of the object
|
||||||
|
*/
|
||||||
|
public static void setInitialVersionFor(StrolchRootElement element, String username) {
|
||||||
|
Version version = new Version(element.getLocator(), 0, username, false);
|
||||||
|
element.setVersion(version);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a new version on the given element. If the element has no version yet, then the result will be version 0,
|
||||||
|
* otherwise the version will be an increment to the current version
|
||||||
|
*
|
||||||
|
* @param element
|
||||||
|
* the element for which to create a new version
|
||||||
|
* @param username
|
||||||
|
* the username of the user who created this version of the object
|
||||||
|
* @param deleted
|
||||||
|
* if true, then the version will be marked as deleted, i.e. this object was removed from the element
|
||||||
|
* maps
|
||||||
|
*/
|
||||||
|
public static void updateVersionFor(StrolchRootElement element, String username, boolean deleted) {
|
||||||
|
int v = element.getVersion() == null ? 0 : element.getVersion().getVersion() + 1;
|
||||||
|
Version version = new Version(element.getLocator(), v, username, deleted);
|
||||||
|
element.setVersion(version);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + (this.deleted ? 1231 : 1237);
|
||||||
|
result = prime * result + ((this.locator == null) ? 0 : this.locator.hashCode());
|
||||||
|
result = prime * result + this.version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
Version other = (Version) obj;
|
||||||
|
if (this.deleted != other.deleted)
|
||||||
|
return false;
|
||||||
|
if (this.locator == null) {
|
||||||
|
if (other.locator != null)
|
||||||
|
return false;
|
||||||
|
} else if (!this.locator.equals(other.locator))
|
||||||
|
return false;
|
||||||
|
if (this.version != other.version)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package li.strolch.model.activity;
|
package li.strolch.model.activity;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
@ -78,8 +79,12 @@ public class Activity extends GroupedParameterizedElement
|
||||||
public void setVersion(Version version) throws IllegalArgumentException, IllegalStateException {
|
public void setVersion(Version version) throws IllegalArgumentException, IllegalStateException {
|
||||||
if (!this.isRootElement())
|
if (!this.isRootElement())
|
||||||
throw new IllegalStateException("Can't set the version on non root of " + getLocator());
|
throw new IllegalStateException("Can't set the version on non root of " + getLocator());
|
||||||
if (this.version != null)
|
|
||||||
this.version.validateIsNext(version);
|
if (version != null && !getLocator().equals(version.getLocator())) {
|
||||||
|
String msg = "Illegal version as locator is not same: Element: {0} Version: {1}";
|
||||||
|
throw new IllegalArgumentException(MessageFormat.format(msg, getLocator(), version));
|
||||||
|
}
|
||||||
|
|
||||||
this.version = version;
|
this.version = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,6 +265,7 @@ public class Activity extends GroupedParameterizedElement
|
||||||
@Override
|
@Override
|
||||||
public Activity getClone() {
|
public Activity getClone() {
|
||||||
Activity clone = new Activity();
|
Activity clone = new Activity();
|
||||||
|
|
||||||
super.fillClone(clone);
|
super.fillClone(clone);
|
||||||
|
|
||||||
if (this.elements == null)
|
if (this.elements == null)
|
||||||
|
|
|
@ -18,6 +18,7 @@ package li.strolch.model.visitor;
|
||||||
import li.strolch.model.Order;
|
import li.strolch.model.Order;
|
||||||
import li.strolch.model.Resource;
|
import li.strolch.model.Resource;
|
||||||
import li.strolch.model.Tags;
|
import li.strolch.model.Tags;
|
||||||
|
import li.strolch.model.activity.Activity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
|
@ -33,4 +34,9 @@ public class ElementTypeVisitor implements StrolchRootElementVisitor<String> {
|
||||||
public String visitResource(Resource resource) {
|
public String visitResource(Resource resource) {
|
||||||
return Tags.RESOURCE;
|
return Tags.RESOURCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String visitActivity(Activity activity) {
|
||||||
|
return Tags.ACTIVITY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ package li.strolch.model.visitor;
|
||||||
|
|
||||||
import li.strolch.model.Order;
|
import li.strolch.model.Order;
|
||||||
import li.strolch.model.Resource;
|
import li.strolch.model.Resource;
|
||||||
|
import li.strolch.model.activity.Activity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
|
@ -26,4 +27,6 @@ public interface StrolchRootElementVisitor<T> extends StrolchVisitor {
|
||||||
public T visitOrder(Order order);
|
public T visitOrder(Order order);
|
||||||
|
|
||||||
public T visitResource(Resource resource);
|
public T visitResource(Resource resource);
|
||||||
|
|
||||||
|
public T visitActivity(Activity activity);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,10 @@ import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.SQLXML;
|
import java.sql.SQLXML;
|
||||||
|
import java.sql.Timestamp;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
@ -30,6 +32,9 @@ import javax.xml.parsers.SAXParser;
|
||||||
import javax.xml.parsers.SAXParserFactory;
|
import javax.xml.parsers.SAXParserFactory;
|
||||||
import javax.xml.transform.sax.SAXResult;
|
import javax.xml.transform.sax.SAXResult;
|
||||||
|
|
||||||
|
import org.xml.sax.ContentHandler;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
import li.strolch.model.Tags;
|
import li.strolch.model.Tags;
|
||||||
import li.strolch.model.activity.Activity;
|
import li.strolch.model.activity.Activity;
|
||||||
import li.strolch.model.query.ActivityQuery;
|
import li.strolch.model.query.ActivityQuery;
|
||||||
|
@ -39,9 +44,6 @@ import li.strolch.model.xml.XmlModelSaxReader;
|
||||||
import li.strolch.persistence.api.ActivityDao;
|
import li.strolch.persistence.api.ActivityDao;
|
||||||
import li.strolch.persistence.api.StrolchPersistenceException;
|
import li.strolch.persistence.api.StrolchPersistenceException;
|
||||||
|
|
||||||
import org.xml.sax.ContentHandler;
|
|
||||||
import org.xml.sax.SAXException;
|
|
||||||
|
|
||||||
@SuppressWarnings("nls")
|
@SuppressWarnings("nls")
|
||||||
public class PostgreSqlActivityDao extends PostgresqlDao<Activity> implements ActivityDao {
|
public class PostgreSqlActivityDao extends PostgresqlDao<Activity> implements ActivityDao {
|
||||||
|
|
||||||
|
@ -68,22 +70,22 @@ public class PostgreSqlActivityDao extends PostgresqlDao<Activity> implements Ac
|
||||||
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
|
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
|
||||||
parser.parse(binaryStream, new XmlModelSaxReader(listener));
|
parser.parse(binaryStream, new XmlModelSaxReader(listener));
|
||||||
} catch (SQLException | IOException | SAXException | ParserConfigurationException e) {
|
} catch (SQLException | IOException | SAXException | ParserConfigurationException e) {
|
||||||
throw new StrolchPersistenceException(MessageFormat.format(
|
throw new StrolchPersistenceException(
|
||||||
"Failed to extract Activity from sqlxml value for {0} / {1}", id, type), e);
|
MessageFormat.format("Failed to extract Activity from sqlxml value for {0} / {1}", id, type), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listener.getActivities().size() == 0)
|
if (listener.getActivities().size() == 0)
|
||||||
throw new StrolchPersistenceException(MessageFormat.format(
|
throw new StrolchPersistenceException(
|
||||||
"No Activity parsed from sqlxml value for {0} / {1}", id, type));
|
MessageFormat.format("No Activity parsed from sqlxml value for {0} / {1}", id, type));
|
||||||
if (listener.getActivities().size() > 1)
|
if (listener.getActivities().size() > 1)
|
||||||
throw new StrolchPersistenceException(MessageFormat.format(
|
throw new StrolchPersistenceException(
|
||||||
"Multiple Activities parsed from sqlxml value for {0} / {1}", id, type));
|
MessageFormat.format("Multiple Activities parsed from sqlxml value for {0} / {1}", id, type));
|
||||||
|
|
||||||
return listener.getActivities().get(0);
|
return listener.getActivities().get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SQLXML createSqlXml(Activity activity, PreparedStatement preparedStatement) throws SQLException,
|
protected SQLXML createSqlXml(Activity activity, PreparedStatement preparedStatement)
|
||||||
SAXException {
|
throws SQLException, SAXException {
|
||||||
SQLXML sqlxml = tx().getConnection().createSQLXML();
|
SQLXML sqlxml = tx().getConnection().createSQLXML();
|
||||||
SAXResult saxResult = sqlxml.setResult(SAXResult.class);
|
SAXResult saxResult = sqlxml.setResult(SAXResult.class);
|
||||||
ContentHandler contentHandler = saxResult.getHandler();
|
ContentHandler contentHandler = saxResult.getHandler();
|
||||||
|
@ -95,14 +97,29 @@ public class PostgreSqlActivityDao extends PostgresqlDao<Activity> implements Ac
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void internalSave(final Activity activity) {
|
protected void internalSave(final Activity activity) {
|
||||||
String sql = "insert into " + getTableName() + " (id, name, type, asxml) values (?, ?, ?, ?)";
|
|
||||||
|
String sql = "insert into " + getTableName()
|
||||||
|
+ " (id, version, created_by, created_at, deleted, latest, name, type, asxml) values (?, ?, ?, ?, ?, true, ?, ?, ?)";
|
||||||
|
|
||||||
try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) {
|
try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) {
|
||||||
|
|
||||||
|
// id
|
||||||
preparedStatement.setString(1, activity.getId());
|
preparedStatement.setString(1, activity.getId());
|
||||||
preparedStatement.setString(2, activity.getName());
|
|
||||||
preparedStatement.setString(3, activity.getType());
|
// version
|
||||||
|
preparedStatement.setInt(2, activity.getVersion().getVersion());
|
||||||
|
preparedStatement.setString(3, activity.getVersion().getCreatedBy());
|
||||||
|
preparedStatement.setTimestamp(4, new Timestamp(activity.getVersion().getCreatedAt().getTime()),
|
||||||
|
Calendar.getInstance());
|
||||||
|
preparedStatement.setBoolean(5, activity.getVersion().isDeleted());
|
||||||
|
|
||||||
|
// attributes
|
||||||
|
preparedStatement.setString(6, activity.getName());
|
||||||
|
preparedStatement.setString(7, activity.getType());
|
||||||
|
|
||||||
SQLXML sqlxml = createSqlXml(activity, preparedStatement);
|
SQLXML sqlxml = createSqlXml(activity, preparedStatement);
|
||||||
preparedStatement.setSQLXML(4, sqlxml);
|
preparedStatement.setSQLXML(8, sqlxml);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
int modCount = preparedStatement.executeUpdate();
|
int modCount = preparedStatement.executeUpdate();
|
||||||
if (modCount != 1) {
|
if (modCount != 1) {
|
||||||
|
@ -118,19 +135,79 @@ public class PostgreSqlActivityDao extends PostgresqlDao<Activity> implements Ac
|
||||||
throw new StrolchPersistenceException(MessageFormat.format("Failed to insert Activity {0} due to {1}",
|
throw new StrolchPersistenceException(MessageFormat.format("Failed to insert Activity {0} due to {1}",
|
||||||
activity.getLocator(), e.getLocalizedMessage()), e);
|
activity.getLocator(), e.getLocalizedMessage()), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (activity.getVersion().isFirstVersion()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// and set the previous version to not be latest anymore
|
||||||
|
sql = "update " + getTableName() + " SET latest = false WHERE id = ? AND version = ?";
|
||||||
|
try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) {
|
||||||
|
|
||||||
|
// primary key
|
||||||
|
preparedStatement.setString(1, activity.getId());
|
||||||
|
preparedStatement.setInt(2, activity.getVersion().getPreviousVersion());
|
||||||
|
|
||||||
|
int modCount = preparedStatement.executeUpdate();
|
||||||
|
if (modCount != 1) {
|
||||||
|
String msg = "Expected to update 1 previous element with id {0} and version {1} but SQL statement modified {2} elements!";
|
||||||
|
msg = MessageFormat.format(msg, activity.getId(), activity.getVersion().getPreviousVersion(), modCount);
|
||||||
|
throw new StrolchPersistenceException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new StrolchPersistenceException(
|
||||||
|
MessageFormat.format("Failed to update previous version of Activity {0} due to {1}",
|
||||||
|
activity.getVersion(), e.getLocalizedMessage()),
|
||||||
|
e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void internalUpdate(final Activity activity) {
|
protected void internalUpdate(final Activity activity) {
|
||||||
String sql = "update " + getTableName() + " set name = ?, type = ?, asxml = ? where id = ? ";
|
|
||||||
|
// with versioning we save a new object
|
||||||
|
if (tx().getRealm().isVersioningEnabled()) {
|
||||||
|
internalSave(activity);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure is first version when versioning is not enabled
|
||||||
|
if (!activity.getVersion().isFirstVersion()) {
|
||||||
|
throw new StrolchPersistenceException(MessageFormat.format(
|
||||||
|
"Versioning is not enabled, so version must always be 0 to perform an update, but it is {0}",
|
||||||
|
activity.getVersion()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// and also not marked as deleted!
|
||||||
|
if (activity.getVersion().isDeleted()) {
|
||||||
|
throw new StrolchPersistenceException(
|
||||||
|
MessageFormat.format("Versioning is not enabled, so version can not be marked as deleted for {0}",
|
||||||
|
activity.getVersion()));
|
||||||
|
}
|
||||||
|
|
||||||
|
String sql = "update " + getTableName()
|
||||||
|
+ " set created_by = ?, created_at = ?, deleted = ?, latest = true, name = ?, type = ?, asxml = ? where id = ? and version = ?";
|
||||||
|
|
||||||
try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) {
|
try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) {
|
||||||
|
|
||||||
preparedStatement.setString(1, activity.getName());
|
// version
|
||||||
preparedStatement.setString(2, activity.getType());
|
preparedStatement.setString(1, activity.getVersion().getCreatedBy());
|
||||||
preparedStatement.setString(4, activity.getId());
|
preparedStatement.setTimestamp(2, new Timestamp(activity.getVersion().getCreatedAt().getTime()),
|
||||||
|
Calendar.getInstance());
|
||||||
|
preparedStatement.setBoolean(3, activity.getVersion().isDeleted());
|
||||||
|
|
||||||
|
// attributes
|
||||||
|
preparedStatement.setString(4, activity.getName());
|
||||||
|
preparedStatement.setString(5, activity.getType());
|
||||||
|
|
||||||
SQLXML sqlxml = createSqlXml(activity, preparedStatement);
|
SQLXML sqlxml = createSqlXml(activity, preparedStatement);
|
||||||
preparedStatement.setSQLXML(3, sqlxml);
|
preparedStatement.setSQLXML(6, sqlxml);
|
||||||
|
|
||||||
|
// primary key
|
||||||
|
preparedStatement.setString(7, activity.getId());
|
||||||
|
preparedStatement.setInt(8, activity.getVersion().getVersion());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
int modCount = preparedStatement.executeUpdate();
|
int modCount = preparedStatement.executeUpdate();
|
||||||
if (modCount != 1) {
|
if (modCount != 1) {
|
||||||
|
|
|
@ -45,7 +45,7 @@ import li.strolch.persistence.api.OrderDao;
|
||||||
import li.strolch.persistence.api.StrolchPersistenceException;
|
import li.strolch.persistence.api.StrolchPersistenceException;
|
||||||
|
|
||||||
@SuppressWarnings("nls")
|
@SuppressWarnings("nls")
|
||||||
public class PostgreSqlOrderDao extends PostgresqlXmlDao<Order> implements OrderDao {
|
public class PostgreSqlOrderDao extends PostgresqlDao<Order> implements OrderDao {
|
||||||
|
|
||||||
public static final String ORDERS = "orders";
|
public static final String ORDERS = "orders";
|
||||||
|
|
||||||
|
@ -96,17 +96,31 @@ public class PostgreSqlOrderDao extends PostgresqlXmlDao<Order> implements Order
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void internalSave(final Order order) {
|
protected void internalSave(final Order order) {
|
||||||
|
|
||||||
String sql = "insert into " + getTableName()
|
String sql = "insert into " + getTableName()
|
||||||
+ " (id, name, type, state, date, asxml) values (?, ?, ?, ?::order_state, ?, ?)";
|
+ " (id, version, created_by, created_at, deleted, latest, name, type, state, date, asxml) values (?, ?, ?, ?, ?, true, ?, ?, ?::order_state, ?, ?)";
|
||||||
|
|
||||||
try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) {
|
try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) {
|
||||||
|
|
||||||
|
// id
|
||||||
preparedStatement.setString(1, order.getId());
|
preparedStatement.setString(1, order.getId());
|
||||||
preparedStatement.setString(2, order.getName());
|
|
||||||
preparedStatement.setString(3, order.getType());
|
// version
|
||||||
preparedStatement.setString(4, order.getState().name());
|
preparedStatement.setInt(2, order.getVersion().getVersion());
|
||||||
preparedStatement.setTimestamp(5, new Timestamp(order.getDate().getTime()), Calendar.getInstance());
|
preparedStatement.setString(3, order.getVersion().getCreatedBy());
|
||||||
|
preparedStatement.setTimestamp(4, new Timestamp(order.getVersion().getCreatedAt().getTime()),
|
||||||
|
Calendar.getInstance());
|
||||||
|
preparedStatement.setBoolean(5, order.getVersion().isDeleted());
|
||||||
|
|
||||||
|
// attributes
|
||||||
|
preparedStatement.setString(6, order.getName());
|
||||||
|
preparedStatement.setString(7, order.getType());
|
||||||
|
preparedStatement.setString(8, order.getState().name());
|
||||||
|
preparedStatement.setTimestamp(9, new Timestamp(order.getDate().getTime()), Calendar.getInstance());
|
||||||
|
|
||||||
SQLXML sqlxml = createSqlXml(order, preparedStatement);
|
SQLXML sqlxml = createSqlXml(order, preparedStatement);
|
||||||
preparedStatement.setSQLXML(6, sqlxml);
|
preparedStatement.setSQLXML(10, sqlxml);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
int modCount = preparedStatement.executeUpdate();
|
int modCount = preparedStatement.executeUpdate();
|
||||||
if (modCount != 1) {
|
if (modCount != 1) {
|
||||||
|
@ -120,29 +134,87 @@ public class PostgreSqlOrderDao extends PostgresqlXmlDao<Order> implements Order
|
||||||
|
|
||||||
} catch (SQLException | SAXException e) {
|
} catch (SQLException | SAXException e) {
|
||||||
throw new StrolchPersistenceException(MessageFormat.format("Failed to insert Order {0} due to {1}",
|
throw new StrolchPersistenceException(MessageFormat.format("Failed to insert Order {0} due to {1}",
|
||||||
order.getLocator(), e.getLocalizedMessage()), e);
|
order.getVersion(), e.getLocalizedMessage()), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (order.getVersion().isFirstVersion()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// and set the previous version to not be latest anymore
|
||||||
|
sql = "update " + getTableName() + " SET latest = false WHERE id = ? AND version = ?";
|
||||||
|
try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) {
|
||||||
|
|
||||||
|
// primary key
|
||||||
|
preparedStatement.setString(1, order.getId());
|
||||||
|
preparedStatement.setInt(2, order.getVersion().getPreviousVersion());
|
||||||
|
|
||||||
|
int modCount = preparedStatement.executeUpdate();
|
||||||
|
if (modCount != 1) {
|
||||||
|
String msg = "Expected to update 1 previous element with id {0} and version {1} but SQL statement modified {2} elements!";
|
||||||
|
msg = MessageFormat.format(msg, order.getId(), order.getVersion().getPreviousVersion(), modCount);
|
||||||
|
throw new StrolchPersistenceException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new StrolchPersistenceException(
|
||||||
|
MessageFormat.format("Failed to update previous version of Order {0} due to {1}",
|
||||||
|
order.getVersion(), e.getLocalizedMessage()),
|
||||||
|
e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void internalUpdate(final Order order) {
|
protected void internalUpdate(final Order order) {
|
||||||
|
|
||||||
|
// with versioning we save a new object
|
||||||
|
if (tx().getRealm().isVersioningEnabled()) {
|
||||||
|
internalSave(order);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure is first version when versioning is not enabled
|
||||||
|
if (!order.getVersion().isFirstVersion()) {
|
||||||
|
throw new StrolchPersistenceException(MessageFormat.format(
|
||||||
|
"Versioning is not enabled, so version must always be 0 to perform an update, but it is {0}",
|
||||||
|
order.getVersion()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// and also not marked as deleted!
|
||||||
|
if (order.getVersion().isDeleted()) {
|
||||||
|
throw new StrolchPersistenceException(MessageFormat.format(
|
||||||
|
"Versioning is not enabled, so version can not be marked as deleted for {0}", order.getVersion()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// now we update the existing object
|
||||||
String sql = "update " + getTableName()
|
String sql = "update " + getTableName()
|
||||||
+ " set name = ?, type = ?, state = ?::order_state, date = ?, asxml = ? where id = ? ";
|
+ " set created_by = ?, created_at = ?, deleted = ?, latest = true, name = ?, type = ?, state = ?::order_state, date = ?, asxml = ? where id = ? and version = ?";
|
||||||
try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) {
|
try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) {
|
||||||
|
|
||||||
preparedStatement.setString(1, order.getName());
|
// version
|
||||||
preparedStatement.setString(2, order.getType());
|
preparedStatement.setString(1, order.getVersion().getCreatedBy());
|
||||||
preparedStatement.setString(3, order.getState().name());
|
preparedStatement.setTimestamp(2, new Timestamp(order.getVersion().getCreatedAt().getTime()),
|
||||||
preparedStatement.setTimestamp(4, new Timestamp(order.getDate().getTime()), Calendar.getInstance());
|
Calendar.getInstance());
|
||||||
preparedStatement.setString(6, order.getId());
|
preparedStatement.setBoolean(3, order.getVersion().isDeleted());
|
||||||
|
|
||||||
|
// attributes
|
||||||
|
preparedStatement.setString(4, order.getName());
|
||||||
|
preparedStatement.setString(5, order.getType());
|
||||||
|
preparedStatement.setString(6, order.getState().name());
|
||||||
|
preparedStatement.setTimestamp(7, new Timestamp(order.getDate().getTime()), Calendar.getInstance());
|
||||||
|
|
||||||
SQLXML sqlxml = createSqlXml(order, preparedStatement);
|
SQLXML sqlxml = createSqlXml(order, preparedStatement);
|
||||||
preparedStatement.setSQLXML(5, sqlxml);
|
preparedStatement.setSQLXML(8, sqlxml);
|
||||||
|
|
||||||
|
// primary key
|
||||||
|
preparedStatement.setString(9, order.getId());
|
||||||
|
preparedStatement.setInt(10, order.getVersion().getVersion());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
int modCount = preparedStatement.executeUpdate();
|
int modCount = preparedStatement.executeUpdate();
|
||||||
if (modCount != 1) {
|
if (modCount != 1) {
|
||||||
String msg = "Expected to update 1 element with id {0} but SQL statement modified {1} elements!";
|
String msg = "Expected to update 1 element with id {0} and version {1} but SQL statement modified {2} elements!";
|
||||||
msg = MessageFormat.format(msg, order.getId(), modCount);
|
msg = MessageFormat.format(msg, order.getId(), order.getVersion().getVersion(), modCount);
|
||||||
throw new StrolchPersistenceException(msg);
|
throw new StrolchPersistenceException(msg);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -100,7 +100,7 @@ public abstract class PostgreSqlQueryVisitor
|
||||||
return this.sqlAsString;
|
return this.sqlAsString;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sql.append("type = ? AND\n");
|
this.sql.append("type = ? AND latest = true AND\n");
|
||||||
this.sql.append(this.sb.toString());
|
this.sql.append(this.sb.toString());
|
||||||
|
|
||||||
appendOrdering();
|
appendOrdering();
|
||||||
|
|
|
@ -21,8 +21,10 @@ import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.SQLXML;
|
import java.sql.SQLXML;
|
||||||
|
import java.sql.Timestamp;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
@ -30,6 +32,9 @@ import javax.xml.parsers.SAXParser;
|
||||||
import javax.xml.parsers.SAXParserFactory;
|
import javax.xml.parsers.SAXParserFactory;
|
||||||
import javax.xml.transform.sax.SAXResult;
|
import javax.xml.transform.sax.SAXResult;
|
||||||
|
|
||||||
|
import org.xml.sax.ContentHandler;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
import li.strolch.model.Resource;
|
import li.strolch.model.Resource;
|
||||||
import li.strolch.model.Tags;
|
import li.strolch.model.Tags;
|
||||||
import li.strolch.model.query.ResourceQuery;
|
import li.strolch.model.query.ResourceQuery;
|
||||||
|
@ -39,9 +44,6 @@ import li.strolch.model.xml.XmlModelSaxReader;
|
||||||
import li.strolch.persistence.api.ResourceDao;
|
import li.strolch.persistence.api.ResourceDao;
|
||||||
import li.strolch.persistence.api.StrolchPersistenceException;
|
import li.strolch.persistence.api.StrolchPersistenceException;
|
||||||
|
|
||||||
import org.xml.sax.ContentHandler;
|
|
||||||
import org.xml.sax.SAXException;
|
|
||||||
|
|
||||||
@SuppressWarnings("nls")
|
@SuppressWarnings("nls")
|
||||||
public class PostgreSqlResourceDao extends PostgresqlDao<Resource> implements ResourceDao {
|
public class PostgreSqlResourceDao extends PostgresqlDao<Resource> implements ResourceDao {
|
||||||
|
|
||||||
|
@ -68,16 +70,16 @@ public class PostgreSqlResourceDao extends PostgresqlDao<Resource> implements Re
|
||||||
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
|
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
|
||||||
parser.parse(binaryStream, new XmlModelSaxReader(listener));
|
parser.parse(binaryStream, new XmlModelSaxReader(listener));
|
||||||
} catch (SQLException | IOException | SAXException | ParserConfigurationException e) {
|
} catch (SQLException | IOException | SAXException | ParserConfigurationException e) {
|
||||||
throw new StrolchPersistenceException(MessageFormat.format(
|
throw new StrolchPersistenceException(
|
||||||
"Failed to extract Resource from sqlxml value for {0} / {1}", id, type), e);
|
MessageFormat.format("Failed to extract Resource from sqlxml value for {0} / {1}", id, type), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listener.getResources().size() == 0)
|
if (listener.getResources().size() == 0)
|
||||||
throw new StrolchPersistenceException(MessageFormat.format(
|
throw new StrolchPersistenceException(
|
||||||
"No Resource parsed from sqlxml value for {0} / {1}", id, type));
|
MessageFormat.format("No Resource parsed from sqlxml value for {0} / {1}", id, type));
|
||||||
if (listener.getResources().size() > 1)
|
if (listener.getResources().size() > 1)
|
||||||
throw new StrolchPersistenceException(MessageFormat.format(
|
throw new StrolchPersistenceException(
|
||||||
"Multiple Resources parsed from sqlxml value for {0} / {1}", id, type));
|
MessageFormat.format("Multiple Resources parsed from sqlxml value for {0} / {1}", id, type));
|
||||||
|
|
||||||
return listener.getResources().get(0);
|
return listener.getResources().get(0);
|
||||||
}
|
}
|
||||||
|
@ -94,14 +96,26 @@ public class PostgreSqlResourceDao extends PostgresqlDao<Resource> implements Re
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void internalSave(final Resource res) {
|
protected void internalSave(final Resource res) {
|
||||||
String sql = "insert into " + getTableName() + " (id, name, type, asxml) values (?, ?, ?, ?)";
|
String sql = "insert into " + getTableName()
|
||||||
|
+ " (id, version, created_by, created_at, deleted, latest, name, type, asxml) values (?, ?, ?, ?, ?, true, ?, ?, ?)";
|
||||||
try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) {
|
try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) {
|
||||||
|
|
||||||
|
// id
|
||||||
preparedStatement.setString(1, res.getId());
|
preparedStatement.setString(1, res.getId());
|
||||||
preparedStatement.setString(2, res.getName());
|
|
||||||
preparedStatement.setString(3, res.getType());
|
// version
|
||||||
|
preparedStatement.setInt(2, res.getVersion().getVersion());
|
||||||
|
preparedStatement.setString(3, res.getVersion().getCreatedBy());
|
||||||
|
preparedStatement.setTimestamp(4, new Timestamp(res.getVersion().getCreatedAt().getTime()),
|
||||||
|
Calendar.getInstance());
|
||||||
|
preparedStatement.setBoolean(5, res.getVersion().isDeleted());
|
||||||
|
|
||||||
|
// attributes
|
||||||
|
preparedStatement.setString(6, res.getName());
|
||||||
|
preparedStatement.setString(7, res.getType());
|
||||||
|
|
||||||
SQLXML sqlxml = createSqlXml(res, preparedStatement);
|
SQLXML sqlxml = createSqlXml(res, preparedStatement);
|
||||||
preparedStatement.setSQLXML(4, sqlxml);
|
preparedStatement.setSQLXML(8, sqlxml);
|
||||||
try {
|
try {
|
||||||
int modCount = preparedStatement.executeUpdate();
|
int modCount = preparedStatement.executeUpdate();
|
||||||
if (modCount != 1) {
|
if (modCount != 1) {
|
||||||
|
@ -117,24 +131,82 @@ public class PostgreSqlResourceDao extends PostgresqlDao<Resource> implements Re
|
||||||
throw new StrolchPersistenceException(MessageFormat.format("Failed to insert Resource {0} due to {1}",
|
throw new StrolchPersistenceException(MessageFormat.format("Failed to insert Resource {0} due to {1}",
|
||||||
res.getLocator(), e.getLocalizedMessage()), e);
|
res.getLocator(), e.getLocalizedMessage()), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (res.getVersion().isFirstVersion()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// and set the previous version to not be latest anymore
|
||||||
|
sql = "update " + getTableName() + " SET latest = false WHERE id = ? AND version = ?";
|
||||||
|
try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) {
|
||||||
|
|
||||||
|
// primary key
|
||||||
|
preparedStatement.setString(1, res.getId());
|
||||||
|
preparedStatement.setInt(2, res.getVersion().getPreviousVersion());
|
||||||
|
|
||||||
|
int modCount = preparedStatement.executeUpdate();
|
||||||
|
if (modCount != 1) {
|
||||||
|
String msg = "Expected to update 1 previous element with id {0} and version {1} but SQL statement modified {2} elements!";
|
||||||
|
msg = MessageFormat.format(msg, res.getId(), res.getVersion().getPreviousVersion(), modCount);
|
||||||
|
throw new StrolchPersistenceException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new StrolchPersistenceException(MessageFormat.format("Failed to insert Resource {0} due to {1}",
|
||||||
|
res.getLocator(), e.getLocalizedMessage()), e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void internalUpdate(final Resource resource) {
|
protected void internalUpdate(final Resource resource) {
|
||||||
String sql = "update " + getTableName() + " set name = ?, type = ?, asxml = ? where id = ? ";
|
|
||||||
|
// with versioning we save a new object
|
||||||
|
if (tx().getRealm().isVersioningEnabled()) {
|
||||||
|
internalSave(resource);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure is first version when versioning is not enabled
|
||||||
|
if (!resource.getVersion().isFirstVersion()) {
|
||||||
|
throw new StrolchPersistenceException(MessageFormat.format(
|
||||||
|
"Versioning is not enabled, so version must always be 0 to perform an update, but it is {0}",
|
||||||
|
resource.getVersion()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// and also not marked as deleted!
|
||||||
|
if (resource.getVersion().isDeleted()) {
|
||||||
|
throw new StrolchPersistenceException(
|
||||||
|
MessageFormat.format("Versioning is not enabled, so version can not be marked as deleted for {0}",
|
||||||
|
resource.getVersion()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// now we update the existing object
|
||||||
|
String sql = "update " + getTableName()
|
||||||
|
+ " set created_by = ?, created_at = ?, deleted = ?, latest = true, name = ?, type = ?, asxml = ? where id = ? and version = ?";
|
||||||
try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) {
|
try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) {
|
||||||
|
|
||||||
preparedStatement.setString(1, resource.getName());
|
// version
|
||||||
preparedStatement.setString(2, resource.getType());
|
preparedStatement.setString(1, resource.getVersion().getCreatedBy());
|
||||||
preparedStatement.setString(4, resource.getId());
|
preparedStatement.setTimestamp(2, new Timestamp(resource.getVersion().getCreatedAt().getTime()),
|
||||||
|
Calendar.getInstance());
|
||||||
|
preparedStatement.setBoolean(3, resource.getVersion().isDeleted());
|
||||||
|
|
||||||
|
// attributes
|
||||||
|
preparedStatement.setString(4, resource.getName());
|
||||||
|
preparedStatement.setString(5, resource.getType());
|
||||||
|
|
||||||
SQLXML sqlxml = createSqlXml(resource, preparedStatement);
|
SQLXML sqlxml = createSqlXml(resource, preparedStatement);
|
||||||
preparedStatement.setSQLXML(3, sqlxml);
|
preparedStatement.setSQLXML(6, sqlxml);
|
||||||
|
|
||||||
|
// primary key
|
||||||
|
preparedStatement.setString(7, resource.getId());
|
||||||
|
preparedStatement.setInt(8, resource.getVersion().getVersion());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
int modCount = preparedStatement.executeUpdate();
|
int modCount = preparedStatement.executeUpdate();
|
||||||
if (modCount != 1) {
|
if (modCount != 1) {
|
||||||
String msg = "Expected to update 1 element with id {0} but SQL statement modified {1} elements!";
|
String msg = "Expected to update 1 element with id {0} and version {1} but SQL statement modified {2} elements!";
|
||||||
msg = MessageFormat.format(msg, resource.getId(), modCount);
|
msg = MessageFormat.format(msg, resource.getId(), resource.getVersion().getVersion(), modCount);
|
||||||
throw new StrolchPersistenceException(msg);
|
throw new StrolchPersistenceException(msg);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -17,6 +17,9 @@ package li.strolch.persistence.postgresql;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import li.strolch.agent.api.StrolchRealm;
|
import li.strolch.agent.api.StrolchRealm;
|
||||||
import li.strolch.persistence.api.AbstractTransaction;
|
import li.strolch.persistence.api.AbstractTransaction;
|
||||||
import li.strolch.persistence.api.ActivityDao;
|
import li.strolch.persistence.api.ActivityDao;
|
||||||
|
@ -28,9 +31,6 @@ import li.strolch.persistence.api.TransactionResult;
|
||||||
import li.strolch.privilege.model.Certificate;
|
import li.strolch.privilege.model.Certificate;
|
||||||
import li.strolch.runtime.privilege.PrivilegeHandler;
|
import li.strolch.runtime.privilege.PrivilegeHandler;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class PostgreSqlStrolchTransaction extends AbstractTransaction {
|
public class PostgreSqlStrolchTransaction extends AbstractTransaction {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(PostgreSqlStrolchTransaction.class);
|
private static final Logger logger = LoggerFactory.getLogger(PostgreSqlStrolchTransaction.class);
|
||||||
|
@ -56,6 +56,8 @@ public class PostgreSqlStrolchTransaction extends AbstractTransaction {
|
||||||
this.orderDao.commit(txResult);
|
this.orderDao.commit(txResult);
|
||||||
if (this.resourceDao != null)
|
if (this.resourceDao != null)
|
||||||
this.resourceDao.commit(txResult);
|
this.resourceDao.commit(txResult);
|
||||||
|
if (this.activityDao != null)
|
||||||
|
this.activityDao.commit(txResult);
|
||||||
|
|
||||||
// don't commit the connection, this is done in postCommit when we close the connection
|
// don't commit the connection, this is done in postCommit when we close the connection
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ import li.strolch.persistence.api.TransactionResult;
|
||||||
@SuppressWarnings("nls")
|
@SuppressWarnings("nls")
|
||||||
public abstract class PostgresqlDao<T extends StrolchRootElement> implements StrolchDao<T> {
|
public abstract class PostgresqlDao<T extends StrolchRootElement> implements StrolchDao<T> {
|
||||||
|
|
||||||
protected PostgreSqlStrolchTransaction tx;
|
private PostgreSqlStrolchTransaction tx;
|
||||||
protected List<DaoCommand> commands;
|
protected List<DaoCommand> commands;
|
||||||
|
|
||||||
public PostgresqlDao(PostgreSqlStrolchTransaction tx) {
|
public PostgresqlDao(PostgreSqlStrolchTransaction tx) {
|
||||||
|
@ -179,6 +179,18 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T queryBy(String type, String id, int version) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<T> queryVersionsFor(String type, String id) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<T> queryAll() {
|
public List<T> queryAll() {
|
||||||
|
|
||||||
|
@ -225,73 +237,55 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save(final T res) {
|
public void save(final T res) {
|
||||||
this.commands.add(new DaoCommand() {
|
this.commands.add(txResult -> {
|
||||||
@Override
|
|
||||||
public void doComand(TransactionResult txResult) {
|
|
||||||
internalSave(res);
|
internalSave(res);
|
||||||
txResult.incCreated(1);
|
txResult.incCreated(1);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveAll(final List<T> elements) {
|
public void saveAll(final List<T> elements) {
|
||||||
this.commands.add(new DaoCommand() {
|
this.commands.add(txResult -> {
|
||||||
@Override
|
|
||||||
public void doComand(TransactionResult txResult) {
|
|
||||||
for (T element : elements) {
|
for (T element : elements) {
|
||||||
internalSave(element);
|
internalSave(element);
|
||||||
}
|
}
|
||||||
txResult.incCreated(elements.size());
|
txResult.incCreated(elements.size());
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(final T element) {
|
public void update(final T element) {
|
||||||
this.commands.add(new DaoCommand() {
|
this.commands.add(txResult -> {
|
||||||
@Override
|
|
||||||
public void doComand(TransactionResult txResult) {
|
|
||||||
internalUpdate(element);
|
internalUpdate(element);
|
||||||
txResult.incUpdated(1);
|
txResult.incUpdated(1);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateAll(final List<T> elements) {
|
public void updateAll(final List<T> elements) {
|
||||||
this.commands.add(new DaoCommand() {
|
this.commands.add(txResult -> {
|
||||||
@Override
|
|
||||||
public void doComand(TransactionResult txResult) {
|
|
||||||
for (T element : elements) {
|
for (T element : elements) {
|
||||||
internalUpdate(element);
|
internalUpdate(element);
|
||||||
}
|
}
|
||||||
txResult.incUpdated(elements.size());
|
txResult.incUpdated(elements.size());
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void remove(final T element) {
|
public void remove(final T element) {
|
||||||
this.commands.add(new DaoCommand() {
|
this.commands.add(txResult -> {
|
||||||
@Override
|
|
||||||
public void doComand(TransactionResult txResult) {
|
|
||||||
internalRemove(element);
|
internalRemove(element);
|
||||||
txResult.incDeleted(1);
|
txResult.incDeleted(1);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeAll(final List<T> elements) {
|
public void removeAll(final List<T> elements) {
|
||||||
this.commands.add(new DaoCommand() {
|
this.commands.add(txResult -> {
|
||||||
@Override
|
|
||||||
public void doComand(TransactionResult txResult) {
|
|
||||||
for (T element : elements) {
|
for (T element : elements) {
|
||||||
internalRemove(element);
|
internalRemove(element);
|
||||||
}
|
}
|
||||||
txResult.incDeleted(elements.size());
|
txResult.incDeleted(elements.size());
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,12 +294,9 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
|
||||||
|
|
||||||
final long toRemove = querySize();
|
final long toRemove = querySize();
|
||||||
|
|
||||||
this.commands.add(new DaoCommand() {
|
this.commands.add(txResult -> {
|
||||||
@Override
|
|
||||||
public void doComand(TransactionResult txResult) {
|
|
||||||
internalRemoveAll(toRemove);
|
internalRemoveAll(toRemove);
|
||||||
txResult.incDeleted(toRemove);
|
txResult.incDeleted(toRemove);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return toRemove;
|
return toRemove;
|
||||||
|
@ -316,17 +307,20 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
|
||||||
|
|
||||||
final long toRemove = querySize(type);
|
final long toRemove = querySize(type);
|
||||||
|
|
||||||
this.commands.add(new DaoCommand() {
|
this.commands.add(txResult -> {
|
||||||
@Override
|
|
||||||
public void doComand(TransactionResult txResult) {
|
|
||||||
internalRemoveAllBy(toRemove, type);
|
internalRemoveAllBy(toRemove, type);
|
||||||
txResult.incDeleted(toRemove);
|
txResult.incDeleted(toRemove);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return toRemove;
|
return toRemove;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeVersion(T element) throws StrolchPersistenceException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param element
|
* @param element
|
||||||
*/
|
*/
|
||||||
|
@ -366,8 +360,8 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new StrolchPersistenceException(MessageFormat.format("Failed to remove all elements due to {0}",
|
throw new StrolchPersistenceException(
|
||||||
e.getLocalizedMessage()), e);
|
MessageFormat.format("Failed to remove all elements due to {0}", e.getLocalizedMessage()), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,8 +377,8 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new StrolchPersistenceException(MessageFormat.format(
|
throw new StrolchPersistenceException(MessageFormat
|
||||||
"Failed to remove all elements of type {0} due to {1}", type, e.getLocalizedMessage()), e);
|
.format("Failed to remove all elements of type {0} due to {1}", type, e.getLocalizedMessage()), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
package li.strolch.persistence.postgresql;
|
|
||||||
|
|
||||||
import java.sql.SQLXML;
|
|
||||||
|
|
||||||
import li.strolch.model.StrolchRootElement;
|
|
||||||
|
|
||||||
public abstract class PostgresqlXmlDao<T extends StrolchRootElement> extends PostgresqlDao<T> {
|
|
||||||
|
|
||||||
public PostgresqlXmlDao(PostgreSqlStrolchTransaction tx) {
|
|
||||||
super(tx);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract T parseFromXml(String id, String type, SQLXML xml);
|
|
||||||
}
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS resources;
|
||||||
|
DROP TABLE IF EXISTS orders;
|
||||||
|
DROP TABLE IF EXISTS activities;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS audits;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS db_version;
|
||||||
|
|
||||||
|
DROP TYPE IF EXISTS order_state;
|
||||||
|
DROP TYPE IF EXISTS access_type;
|
|
@ -0,0 +1,131 @@
|
||||||
|
|
||||||
|
-- DB_VERSION
|
||||||
|
CREATE TABLE IF NOT EXISTS db_version (
|
||||||
|
id serial primary key not null,
|
||||||
|
app varchar(255) not null,
|
||||||
|
version varchar(255) not null,
|
||||||
|
description varchar(255) not null,
|
||||||
|
created timestamp with time zone not null
|
||||||
|
);
|
||||||
|
|
||||||
|
-- RESOURCES
|
||||||
|
CREATE TABLE IF NOT EXISTS resources (
|
||||||
|
id varchar(255) not null,
|
||||||
|
version integer not null,
|
||||||
|
created_by varchar(255) not null,
|
||||||
|
created_at timestamp with time zone not null,
|
||||||
|
deleted boolean not null,
|
||||||
|
latest boolean not null,
|
||||||
|
name varchar(255) not null,
|
||||||
|
type varchar(255) not null,
|
||||||
|
asxml xml not null,
|
||||||
|
|
||||||
|
PRIMARY KEY (id, version)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ORDERS
|
||||||
|
CREATE TYPE order_state AS ENUM ('CREATED', 'OPEN', 'EXECUTION', 'CLOSED');
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS orders (
|
||||||
|
id varchar(255) not null,
|
||||||
|
version integer not null,
|
||||||
|
created_by varchar(255) not null,
|
||||||
|
created_at timestamp with time zone not null,
|
||||||
|
deleted boolean,
|
||||||
|
latest boolean not null,
|
||||||
|
name varchar(255),
|
||||||
|
type varchar(255),
|
||||||
|
state order_state,
|
||||||
|
date timestamp with time zone,
|
||||||
|
asxml xml not null,
|
||||||
|
|
||||||
|
PRIMARY KEY (id, version)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ACTIVITIES
|
||||||
|
CREATE TABLE IF NOT EXISTS activities (
|
||||||
|
id varchar(255) not null,
|
||||||
|
version integer not null,
|
||||||
|
created_by varchar(255) not null,
|
||||||
|
created_at timestamp with time zone not null,
|
||||||
|
deleted boolean not null,
|
||||||
|
latest boolean not null,
|
||||||
|
name varchar(255) not null,
|
||||||
|
type varchar(255) not null,
|
||||||
|
asxml xml not null,
|
||||||
|
|
||||||
|
PRIMARY KEY (id, version)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- AUDITS
|
||||||
|
CREATE TYPE access_type AS ENUM ('READ', 'CREATE', 'UPDATE', 'DELETE');
|
||||||
|
CREATE TABLE IF NOT EXISTS audits (
|
||||||
|
id bigint PRIMARY KEY,
|
||||||
|
username varchar(255) NOT NULL,
|
||||||
|
firstname varchar(255) NOT NULL,
|
||||||
|
lastname varchar(255) NOT NULL,
|
||||||
|
date timestamp with time zone NOT NULL,
|
||||||
|
|
||||||
|
element_type varchar(255) NOT NULL,
|
||||||
|
element_sub_type varchar(255) NOT NULL,
|
||||||
|
element_accessed varchar(255) NOT NULL,
|
||||||
|
new_version timestamp with time zone,
|
||||||
|
|
||||||
|
action varchar(255) NOT NULL,
|
||||||
|
access_type access_type NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- set version
|
||||||
|
INSERT INTO db_version
|
||||||
|
(version, app, description, created)
|
||||||
|
values(
|
||||||
|
'0.1.0',
|
||||||
|
'strolch',
|
||||||
|
'Initial schema version',
|
||||||
|
CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO db_version
|
||||||
|
(version, app, description, created)
|
||||||
|
values(
|
||||||
|
'0.2.0',
|
||||||
|
'strolch',
|
||||||
|
'Added new table for audits',
|
||||||
|
CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO db_version
|
||||||
|
(version, app, description, created)
|
||||||
|
values(
|
||||||
|
'0.2.1',
|
||||||
|
'strolch',
|
||||||
|
'Added new column app to table table version',
|
||||||
|
CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO db_version
|
||||||
|
(version, app, description, created)
|
||||||
|
values(
|
||||||
|
'0.3.0',
|
||||||
|
'strolch',
|
||||||
|
'Added new column element_sub_type to table audits',
|
||||||
|
CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO db_version
|
||||||
|
(version, app, description, created)
|
||||||
|
values(
|
||||||
|
'0.4.0',
|
||||||
|
'strolch',
|
||||||
|
'Added new table activities',
|
||||||
|
CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO db_version
|
||||||
|
(version, app, description, created)
|
||||||
|
values(
|
||||||
|
'0.5.0',
|
||||||
|
'strolch',
|
||||||
|
'Added versioning to root elements',
|
||||||
|
CURRENT_TIMESTAMP
|
||||||
|
);
|
|
@ -0,0 +1,72 @@
|
||||||
|
|
||||||
|
-- add version columns
|
||||||
|
ALTER TABLE resources ADD COLUMN version integer;
|
||||||
|
ALTER TABLE resources ADD COLUMN created_by varchar(255);
|
||||||
|
ALTER TABLE resources ADD COLUMN created_at timestamp with time zone;
|
||||||
|
ALTER TABLE resources ADD COLUMN deleted boolean;
|
||||||
|
ALTER TABLE resources ADD COLUMN latest boolean;
|
||||||
|
|
||||||
|
ALTER TABLE orders ADD COLUMN version integer;
|
||||||
|
ALTER TABLE orders ADD COLUMN created_by varchar(255);
|
||||||
|
ALTER TABLE orders ADD COLUMN created_at timestamp with time zone;
|
||||||
|
ALTER TABLE orders ADD COLUMN deleted boolean;
|
||||||
|
ALTER TABLE orders ADD COLUMN latest boolean;
|
||||||
|
|
||||||
|
ALTER TABLE activities ADD COLUMN version integer;
|
||||||
|
ALTER TABLE activities ADD COLUMN created_by varchar(255);
|
||||||
|
ALTER TABLE activities ADD COLUMN created_at timestamp with time zone;
|
||||||
|
ALTER TABLE activities ADD COLUMN deleted boolean;
|
||||||
|
ALTER TABLE activities ADD COLUMN latest boolean;
|
||||||
|
|
||||||
|
-- set initial values for new columns
|
||||||
|
UPDATE resources SET version = 0 where version IS NULL;
|
||||||
|
UPDATE resources SET created_by = 'MIGRATION' where version IS NULL;
|
||||||
|
UPDATE resources SET created_at = CURRENT_TIMESTAMP where version IS NULL;
|
||||||
|
UPDATE resources SET deleted = false where version IS NULL;
|
||||||
|
|
||||||
|
UPDATE orders SET version = 0 where version IS NULL;
|
||||||
|
UPDATE orders SET created_by = 'MIGRATION' where version IS NULL;
|
||||||
|
UPDATE orders SET created_at = CURRENT_TIMESTAMP where version IS NULL;
|
||||||
|
UPDATE orders SET deleted = false where version IS NULL;
|
||||||
|
|
||||||
|
UPDATE activities SET version = 0 where version IS NULL;
|
||||||
|
UPDATE activities SET created_by = 'MIGRATION' where version IS NULL;
|
||||||
|
UPDATE activities SET created_at = CURRENT_TIMESTAMP where version IS NULL;
|
||||||
|
UPDATE activities SET deleted = false where version IS NULL;
|
||||||
|
|
||||||
|
-- make columns not null
|
||||||
|
ALTER TABLE resources ALTER COLUMN version SET NOT NULL;
|
||||||
|
ALTER TABLE resources ALTER COLUMN created_by SET NOT NULL;
|
||||||
|
ALTER TABLE resources ALTER COLUMN created_at SET NOT NULL;
|
||||||
|
ALTER TABLE resources ALTER COLUMN latest SET NOT NULL;
|
||||||
|
ALTER TABLE resources ALTER COLUMN deleted SET NOT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE orders ALTER COLUMN version SET NOT NULL;
|
||||||
|
ALTER TABLE orders ALTER COLUMN created_by SET NOT NULL;
|
||||||
|
ALTER TABLE orders ALTER COLUMN created_at SET NOT NULL;
|
||||||
|
ALTER TABLE orders ALTER COLUMN latest SET NOT NULL;
|
||||||
|
ALTER TABLE orders ALTER COLUMN deleted SET NOT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE activities ALTER COLUMN version SET NOT NULL;
|
||||||
|
ALTER TABLE activities ALTER COLUMN created_by SET NOT NULL;
|
||||||
|
ALTER TABLE activities ALTER COLUMN created_at SET NOT NULL;
|
||||||
|
ALTER TABLE activities ALTER COLUMN latest SET NOT NULL;
|
||||||
|
ALTER TABLE activities ALTER COLUMN deleted SET NOT NULL;
|
||||||
|
|
||||||
|
-- change primary key to id, version
|
||||||
|
ALTER TABLE resources DROP CONSTRAINT resources_pkey;
|
||||||
|
ALTER TABLE orders DROP CONSTRAINT orders_pkey;
|
||||||
|
ALTER TABLE activities DROP CONSTRAINT activities_pkey;
|
||||||
|
|
||||||
|
ALTER TABLE resources ADD CONSTRAINT resources_pkey PRIMARY KEY (id, version);
|
||||||
|
ALTER TABLE orders ADD CONSTRAINT orders_pkey PRIMARY KEY (id, version);
|
||||||
|
ALTER TABLE activities ADD CONSTRAINT activities_pkey PRIMARY KEY (id, version);
|
||||||
|
|
||||||
|
INSERT INTO db_version
|
||||||
|
(version, app, description, created)
|
||||||
|
values(
|
||||||
|
'0.5.0',
|
||||||
|
'strolch',
|
||||||
|
'Added versioning to root elements',
|
||||||
|
CURRENT_TIMESTAMP
|
||||||
|
);
|
|
@ -1,2 +1,2 @@
|
||||||
# Property file defining what the currently expected version is supposed to be
|
# Property file defining what the currently expected version is supposed to be
|
||||||
db_version=0.4.0
|
db_version=0.5.0
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
<depends>PrivilegeHandler</depends>
|
<depends>PrivilegeHandler</depends>
|
||||||
<depends>PersistenceHandler</depends>
|
<depends>PersistenceHandler</depends>
|
||||||
<Properties>
|
<Properties>
|
||||||
<dataStoreMode>TRANSACTIONAL</dataStoreMode>
|
<dataStoreMode>CACHED</dataStoreMode>
|
||||||
<enableAuditTrail>true</enableAuditTrail>
|
<enableAuditTrail>true</enableAuditTrail>
|
||||||
<enableObserverUpdates>true</enableObserverUpdates>
|
<enableObserverUpdates>true</enableObserverUpdates>
|
||||||
</Properties>
|
</Properties>
|
||||||
|
|
|
@ -22,6 +22,7 @@ import java.util.Set;
|
||||||
|
|
||||||
import li.strolch.model.StrolchRootElement;
|
import li.strolch.model.StrolchRootElement;
|
||||||
import li.strolch.persistence.api.StrolchDao;
|
import li.strolch.persistence.api.StrolchDao;
|
||||||
|
import li.strolch.persistence.api.StrolchPersistenceException;
|
||||||
import li.strolch.persistence.api.StrolchTransaction;
|
import li.strolch.persistence.api.StrolchTransaction;
|
||||||
import li.strolch.xmlpers.api.PersistenceTransaction;
|
import li.strolch.xmlpers.api.PersistenceTransaction;
|
||||||
import li.strolch.xmlpers.objref.IdOfSubTypeRef;
|
import li.strolch.xmlpers.objref.IdOfSubTypeRef;
|
||||||
|
@ -104,6 +105,18 @@ public abstract class AbstractDao<T extends StrolchRootElement> implements Strol
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T queryBy(String type, String id, int version) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<T> queryVersionsFor(String type, String id) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<T> queryAll() {
|
public List<T> queryAll() {
|
||||||
List<T> objects = new ArrayList<>();
|
List<T> objects = new ArrayList<>();
|
||||||
|
@ -163,4 +176,10 @@ public abstract class AbstractDao<T extends StrolchRootElement> implements Strol
|
||||||
SubTypeRef typeRef = getTypeRef(type);
|
SubTypeRef typeRef = getTypeRef(type);
|
||||||
return this.tx.getObjectDao().removeAllBy(typeRef);
|
return this.tx.getObjectDao().removeAllBy(typeRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeVersion(T element) throws StrolchPersistenceException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
throw new UnsupportedOperationException("not yet implemented!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ import li.strolch.utils.dbc.DBC;
|
||||||
public class RemoveOrderCommand extends Command {
|
public class RemoveOrderCommand extends Command {
|
||||||
|
|
||||||
private Order order;
|
private Order order;
|
||||||
|
private boolean removed;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param tx
|
* @param tx
|
||||||
|
@ -65,14 +66,16 @@ public class RemoveOrderCommand extends Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
orderMap.remove(tx(), this.order);
|
orderMap.remove(tx(), this.order);
|
||||||
|
this.removed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void undo() {
|
public void undo() {
|
||||||
if (this.order != null && tx().isRollingBack()) {
|
if (this.order != null && tx().isRollingBack() && this.removed) {
|
||||||
OrderMap orderMap = tx().getOrderMap();
|
if (tx().isVersioningEnabled())
|
||||||
if (!orderMap.hasElement(tx(), this.order.getType(), this.order.getId()))
|
tx().getOrderMap().undoVersion(tx(), this.order);
|
||||||
orderMap.add(tx(), this.order);
|
else
|
||||||
|
tx().getOrderMap().add(tx(), this.order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ import li.strolch.utils.dbc.DBC;
|
||||||
public class RemoveResourceCommand extends Command {
|
public class RemoveResourceCommand extends Command {
|
||||||
|
|
||||||
private Resource resource;
|
private Resource resource;
|
||||||
|
private boolean removed;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param tx
|
* @param tx
|
||||||
|
@ -65,14 +66,16 @@ public class RemoveResourceCommand extends Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
resourceMap.remove(tx(), this.resource);
|
resourceMap.remove(tx(), this.resource);
|
||||||
|
this.removed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void undo() {
|
public void undo() {
|
||||||
if (this.resource != null && tx().isRollingBack()) {
|
if (this.resource != null && tx().isRollingBack() && this.removed) {
|
||||||
ResourceMap resourceMap = tx().getResourceMap();
|
if (tx().isVersioningEnabled())
|
||||||
if (!resourceMap.hasElement(tx(), this.resource.getType(), this.resource.getId()))
|
tx().getResourceMap().undoVersion(tx(), this.resource);
|
||||||
resourceMap.add(tx(), this.resource);
|
else
|
||||||
|
tx().getResourceMap().add(tx(), this.resource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package li.strolch.command;
|
package li.strolch.command;
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import li.strolch.agent.api.ComponentContainer;
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
|
@ -32,7 +33,8 @@ import li.strolch.utils.dbc.DBC;
|
||||||
public class UpdateOrderCollectionCommand extends Command {
|
public class UpdateOrderCollectionCommand extends Command {
|
||||||
|
|
||||||
private List<Order> orders;
|
private List<Order> orders;
|
||||||
private List<Order> replacedElements;
|
private List<Order> replaced;
|
||||||
|
private boolean updated;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param tx
|
* @param tx
|
||||||
|
@ -62,22 +64,32 @@ public class UpdateOrderCollectionCommand extends Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
OrderMap orderMap = tx().getOrderMap();
|
OrderMap orderMap = tx().getOrderMap();
|
||||||
|
this.replaced = new ArrayList<>();
|
||||||
for (Order order : this.orders) {
|
for (Order order : this.orders) {
|
||||||
if (!orderMap.hasElement(tx(), order.getType(), order.getId())) {
|
Order o = orderMap.getBy(tx(), order.getType(), order.getId());
|
||||||
|
if (o == null) {
|
||||||
String msg = "The Order {0} can not be updated as it does not exist!";
|
String msg = "The Order {0} can not be updated as it does not exist!";
|
||||||
msg = MessageFormat.format(msg, order.getLocator());
|
msg = MessageFormat.format(msg, order.getLocator());
|
||||||
throw new StrolchException(msg);
|
throw new StrolchException(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.replaced.add(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.replacedElements = orderMap.updateAll(tx(), this.orders);
|
orderMap.updateAll(tx(), this.orders);
|
||||||
|
this.updated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void undo() {
|
public void undo() {
|
||||||
if (this.replacedElements != null && tx().isRollingBack()) {
|
if (this.updated && tx().isRollingBack()) {
|
||||||
OrderMap orderMap = tx().getOrderMap();
|
if (tx().isVersioningEnabled()) {
|
||||||
orderMap.updateAll(tx(), this.replacedElements);
|
for (Order order : this.orders) {
|
||||||
|
tx().getOrderMap().undoVersion(tx(), order);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tx().getOrderMap().updateAll(tx(), this.replaced);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,8 @@ import li.strolch.utils.dbc.DBC;
|
||||||
public class UpdateOrderCommand extends Command {
|
public class UpdateOrderCommand extends Command {
|
||||||
|
|
||||||
private Order order;
|
private Order order;
|
||||||
private Order replacedElement;
|
private Order replaced;
|
||||||
|
private boolean updated;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param tx
|
* @param tx
|
||||||
|
@ -59,19 +60,24 @@ public class UpdateOrderCommand extends Command {
|
||||||
tx().lock(this.order);
|
tx().lock(this.order);
|
||||||
|
|
||||||
OrderMap orderMap = tx().getOrderMap();
|
OrderMap orderMap = tx().getOrderMap();
|
||||||
if (!orderMap.hasElement(tx(), this.order.getType(), this.order.getId())) {
|
this.replaced = orderMap.getBy(tx(), this.order.getType(), this.order.getId());
|
||||||
String msg = "The Order {0} can not be updated as it does not exist!";
|
if (this.replaced == null) {
|
||||||
|
String msg = "The Order {0} can not be updated as it does not exist!!";
|
||||||
msg = MessageFormat.format(msg, this.order.getLocator());
|
msg = MessageFormat.format(msg, this.order.getLocator());
|
||||||
throw new StrolchException(msg);
|
throw new StrolchException(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.replacedElement = orderMap.update(tx(), this.order);
|
orderMap.update(tx(), this.order);
|
||||||
|
this.updated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void undo() {
|
public void undo() {
|
||||||
if (this.replacedElement != null && tx().isRollingBack()) {
|
if (this.updated && tx().isRollingBack()) {
|
||||||
tx().getOrderMap().update(tx(), this.replacedElement);
|
if (tx().isVersioningEnabled())
|
||||||
|
tx().getOrderMap().undoVersion(tx(), this.order);
|
||||||
|
else
|
||||||
|
tx().getOrderMap().update(tx(), this.replaced);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package li.strolch.command;
|
package li.strolch.command;
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import li.strolch.agent.api.ComponentContainer;
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
|
@ -32,7 +33,8 @@ import li.strolch.utils.dbc.DBC;
|
||||||
public class UpdateResourceCollectionCommand extends Command {
|
public class UpdateResourceCollectionCommand extends Command {
|
||||||
|
|
||||||
private List<Resource> resources;
|
private List<Resource> resources;
|
||||||
private List<Resource> replacedElements;
|
private List<Resource> replaced;
|
||||||
|
private boolean updated;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param tx
|
* @param tx
|
||||||
|
@ -62,22 +64,32 @@ public class UpdateResourceCollectionCommand extends Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceMap resourceMap = tx().getResourceMap();
|
ResourceMap resourceMap = tx().getResourceMap();
|
||||||
|
this.replaced = new ArrayList<>();
|
||||||
for (Resource resource : this.resources) {
|
for (Resource resource : this.resources) {
|
||||||
if (!resourceMap.hasElement(tx(), resource.getType(), resource.getId())) {
|
Resource r = resourceMap.getBy(tx(), resource.getType(), resource.getId());
|
||||||
|
if (r == null) {
|
||||||
String msg = "The Resource {0} can not be updated as it does not exist!";
|
String msg = "The Resource {0} can not be updated as it does not exist!";
|
||||||
msg = MessageFormat.format(msg, resource.getLocator());
|
msg = MessageFormat.format(msg, resource.getLocator());
|
||||||
throw new StrolchException(msg);
|
throw new StrolchException(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.replaced.add(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.replacedElements = resourceMap.updateAll(tx(), this.resources);
|
resourceMap.updateAll(tx(), this.resources);
|
||||||
|
this.updated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void undo() {
|
public void undo() {
|
||||||
if (this.replacedElements != null && tx().isRollingBack()) {
|
if (this.updated && tx().isRollingBack()) {
|
||||||
ResourceMap resourceMap = tx().getResourceMap();
|
if (tx().isVersioningEnabled()) {
|
||||||
resourceMap.updateAll(tx(), this.replacedElements);
|
for (Resource resource : this.resources) {
|
||||||
|
tx().getResourceMap().undoVersion(tx(), resource);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tx().getResourceMap().updateAll(tx(), this.replaced);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,8 @@ import li.strolch.utils.dbc.DBC;
|
||||||
public class UpdateResourceCommand extends Command {
|
public class UpdateResourceCommand extends Command {
|
||||||
|
|
||||||
private Resource resource;
|
private Resource resource;
|
||||||
private Resource replacedElement;
|
private Resource replaced;
|
||||||
|
private boolean updated;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param tx
|
* @param tx
|
||||||
|
@ -59,19 +60,24 @@ public class UpdateResourceCommand extends Command {
|
||||||
tx().lock(this.resource);
|
tx().lock(this.resource);
|
||||||
|
|
||||||
ResourceMap resourceMap = tx().getResourceMap();
|
ResourceMap resourceMap = tx().getResourceMap();
|
||||||
if (!resourceMap.hasElement(tx(), this.resource.getType(), this.resource.getId())) {
|
this.replaced = resourceMap.getBy(tx(), this.resource.getType(), this.resource.getId());
|
||||||
|
if (this.replaced == null) {
|
||||||
String msg = "The Resource {0} can not be updated as it does not exist!!";
|
String msg = "The Resource {0} can not be updated as it does not exist!!";
|
||||||
msg = MessageFormat.format(msg, this.resource.getLocator());
|
msg = MessageFormat.format(msg, this.resource.getLocator());
|
||||||
throw new StrolchException(msg);
|
throw new StrolchException(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.replacedElement = resourceMap.update(tx(), this.resource);
|
resourceMap.update(tx(), this.resource);
|
||||||
|
this.updated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void undo() {
|
public void undo() {
|
||||||
if (this.replacedElement != null && tx().isRollingBack()) {
|
if (this.updated && tx().isRollingBack()) {
|
||||||
tx().getResourceMap().update(tx(), this.replacedElement);
|
if (tx().isVersioningEnabled())
|
||||||
|
tx().getResourceMap().undoVersion(tx(), this.resource);
|
||||||
|
else
|
||||||
|
tx().getResourceMap().update(tx(), this.replaced);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ package li.strolch.command.parameter;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
|
|
||||||
import li.strolch.agent.api.ComponentContainer;
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
|
import li.strolch.command.visitor.UndoUpdateElementVisitor;
|
||||||
import li.strolch.command.visitor.UpdateElementVisitor;
|
import li.strolch.command.visitor.UpdateElementVisitor;
|
||||||
import li.strolch.model.ParameterizedElement;
|
import li.strolch.model.ParameterizedElement;
|
||||||
import li.strolch.model.StrolchRootElement;
|
import li.strolch.model.StrolchRootElement;
|
||||||
|
@ -34,7 +35,6 @@ public class AddParameterCommand extends Command {
|
||||||
|
|
||||||
private ParameterizedElement element;
|
private ParameterizedElement element;
|
||||||
private Parameter<?> parameter;
|
private Parameter<?> parameter;
|
||||||
private StrolchRootElement replacedElement;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param container
|
* @param container
|
||||||
|
@ -79,7 +79,7 @@ public class AddParameterCommand extends Command {
|
||||||
tx().lock(rootElement);
|
tx().lock(rootElement);
|
||||||
|
|
||||||
this.element.addParameter(this.parameter);
|
this.element.addParameter(this.parameter);
|
||||||
this.replacedElement = new UpdateElementVisitor(tx()).update(rootElement);
|
new UpdateElementVisitor(tx()).update(rootElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -87,11 +87,8 @@ public class AddParameterCommand extends Command {
|
||||||
if (this.parameter != null) {
|
if (this.parameter != null) {
|
||||||
if (this.element.hasParameter(this.parameter.getId())) {
|
if (this.element.hasParameter(this.parameter.getId())) {
|
||||||
this.element.removeParameter(this.parameter.getId());
|
this.element.removeParameter(this.parameter.getId());
|
||||||
|
new UndoUpdateElementVisitor(tx()).undo(this.element.getRootElement());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.replacedElement != null && this.element != this.replacedElement) {
|
|
||||||
new UpdateElementVisitor(tx()).update(this.replacedElement);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ package li.strolch.command.parameter;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
|
|
||||||
import li.strolch.agent.api.ComponentContainer;
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
|
import li.strolch.command.visitor.UndoUpdateElementVisitor;
|
||||||
import li.strolch.command.visitor.UpdateElementVisitor;
|
import li.strolch.command.visitor.UpdateElementVisitor;
|
||||||
import li.strolch.model.ParameterizedElement;
|
import li.strolch.model.ParameterizedElement;
|
||||||
import li.strolch.model.StrolchRootElement;
|
import li.strolch.model.StrolchRootElement;
|
||||||
|
@ -36,7 +37,6 @@ public class RemoveParameterCommand extends Command {
|
||||||
private String parameterId;
|
private String parameterId;
|
||||||
|
|
||||||
private Parameter<?> removedParameter;
|
private Parameter<?> removedParameter;
|
||||||
private StrolchRootElement replacedElement;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param container
|
* @param container
|
||||||
|
@ -81,17 +81,14 @@ public class RemoveParameterCommand extends Command {
|
||||||
tx().lock(rootElement);
|
tx().lock(rootElement);
|
||||||
|
|
||||||
this.removedParameter = this.element.removeParameter(this.parameterId);
|
this.removedParameter = this.element.removeParameter(this.parameterId);
|
||||||
this.replacedElement = new UpdateElementVisitor(tx()).update(rootElement);
|
new UpdateElementVisitor(tx()).update(rootElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void undo() {
|
public void undo() {
|
||||||
if (this.removedParameter != null) {
|
if (this.removedParameter != null) {
|
||||||
this.element.addParameter(this.removedParameter);
|
this.element.addParameter(this.removedParameter);
|
||||||
}
|
new UndoUpdateElementVisitor(tx()).undo(this.removedParameter.getRootElement());
|
||||||
|
|
||||||
if (this.replacedElement != null && this.element != this.replacedElement) {
|
|
||||||
new UpdateElementVisitor(tx()).update(this.replacedElement);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package li.strolch.command.parameter;
|
package li.strolch.command.parameter;
|
||||||
|
|
||||||
import li.strolch.agent.api.ComponentContainer;
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
|
import li.strolch.command.visitor.UndoUpdateElementVisitor;
|
||||||
import li.strolch.command.visitor.UpdateElementVisitor;
|
import li.strolch.command.visitor.UpdateElementVisitor;
|
||||||
import li.strolch.model.StrolchRootElement;
|
import li.strolch.model.StrolchRootElement;
|
||||||
import li.strolch.model.parameter.Parameter;
|
import li.strolch.model.parameter.Parameter;
|
||||||
|
@ -46,7 +47,7 @@ public class SetParameterCommand extends Command {
|
||||||
private Integer oldIndex;
|
private Integer oldIndex;
|
||||||
private String oldValueAsString;
|
private String oldValueAsString;
|
||||||
|
|
||||||
private StrolchRootElement replacedElement;
|
private boolean updated;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param container
|
* @param container
|
||||||
|
@ -151,7 +152,8 @@ public class SetParameterCommand extends Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasChanges()) {
|
if (hasChanges()) {
|
||||||
this.replacedElement = new UpdateElementVisitor(tx()).update(rootElement);
|
new UpdateElementVisitor(tx()).update(rootElement);
|
||||||
|
this.updated = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,8 +187,9 @@ public class SetParameterCommand extends Command {
|
||||||
visitor.setValue(this.parameter, this.oldValueAsString);
|
visitor.setValue(this.parameter, this.oldValueAsString);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasChanges() && this.replacedElement != null && this.replacedElement != this.parameter.getRootElement()) {
|
if (hasChanges() && this.updated) {
|
||||||
new UpdateElementVisitor(tx()).update(this.replacedElement);
|
StrolchRootElement rootElement = this.parameter.getRootElement();
|
||||||
|
new UndoUpdateElementVisitor(tx()).undo(rootElement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package li.strolch.command.visitor;
|
||||||
|
|
||||||
|
import li.strolch.model.Order;
|
||||||
|
import li.strolch.model.Resource;
|
||||||
|
import li.strolch.model.StrolchRootElement;
|
||||||
|
import li.strolch.model.activity.Activity;
|
||||||
|
import li.strolch.model.visitor.StrolchRootElementVisitor;
|
||||||
|
import li.strolch.persistence.api.StrolchTransaction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
|
*/
|
||||||
|
public class UndoUpdateElementVisitor implements StrolchRootElementVisitor<Void> {
|
||||||
|
|
||||||
|
private StrolchTransaction tx;
|
||||||
|
|
||||||
|
public UndoUpdateElementVisitor(StrolchTransaction tx) {
|
||||||
|
this.tx = tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Void undo(StrolchRootElement rootElement) {
|
||||||
|
return rootElement.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visitOrder(Order order) {
|
||||||
|
if (tx.isVersioningEnabled())
|
||||||
|
this.tx.getOrderMap().undoVersion(this.tx, order);
|
||||||
|
else
|
||||||
|
this.tx.getOrderMap().update(this.tx, order);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visitResource(Resource resource) {
|
||||||
|
if (tx.isVersioningEnabled())
|
||||||
|
this.tx.getResourceMap().undoVersion(this.tx, resource);
|
||||||
|
else
|
||||||
|
this.tx.getResourceMap().update(this.tx, resource);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visitActivity(Activity activity) {
|
||||||
|
if (tx.isVersioningEnabled())
|
||||||
|
this.tx.getActivityMap().undoVersion(this.tx, activity);
|
||||||
|
else
|
||||||
|
this.tx.getActivityMap().update(this.tx, activity);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,13 +18,14 @@ package li.strolch.command.visitor;
|
||||||
import li.strolch.model.Order;
|
import li.strolch.model.Order;
|
||||||
import li.strolch.model.Resource;
|
import li.strolch.model.Resource;
|
||||||
import li.strolch.model.StrolchRootElement;
|
import li.strolch.model.StrolchRootElement;
|
||||||
|
import li.strolch.model.activity.Activity;
|
||||||
import li.strolch.model.visitor.StrolchRootElementVisitor;
|
import li.strolch.model.visitor.StrolchRootElementVisitor;
|
||||||
import li.strolch.persistence.api.StrolchTransaction;
|
import li.strolch.persistence.api.StrolchTransaction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
*/
|
*/
|
||||||
public class UpdateElementVisitor implements StrolchRootElementVisitor<StrolchRootElement> {
|
public class UpdateElementVisitor implements StrolchRootElementVisitor<Void> {
|
||||||
|
|
||||||
private StrolchTransaction tx;
|
private StrolchTransaction tx;
|
||||||
|
|
||||||
|
@ -32,17 +33,25 @@ public class UpdateElementVisitor implements StrolchRootElementVisitor<StrolchRo
|
||||||
this.tx = tx;
|
this.tx = tx;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StrolchRootElement update(StrolchRootElement rootElement) {
|
public Void update(StrolchRootElement rootElement) {
|
||||||
return rootElement.accept(this);
|
return rootElement.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StrolchRootElement visitOrder(Order order) {
|
public Void visitOrder(Order order) {
|
||||||
return this.tx.getOrderMap().update(this.tx, order);
|
this.tx.getOrderMap().update(this.tx, order);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StrolchRootElement visitResource(Resource resource) {
|
public Void visitResource(Resource resource) {
|
||||||
return this.tx.getResourceMap().update(this.tx, resource);
|
this.tx.getResourceMap().update(this.tx, resource);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visitActivity(Activity activity) {
|
||||||
|
this.tx.getActivityMap().update(this.tx, activity);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,9 +22,16 @@ import static li.strolch.service.test.AbstractRealmServiceTest.REALM_TRANSIENT;
|
||||||
import static li.strolch.service.test.AbstractRealmServiceTest.RUNTIME_PATH;
|
import static li.strolch.service.test.AbstractRealmServiceTest.RUNTIME_PATH;
|
||||||
import static li.strolch.service.test.AbstractRealmServiceTest.dropSchema;
|
import static li.strolch.service.test.AbstractRealmServiceTest.dropSchema;
|
||||||
import static li.strolch.service.test.AbstractRealmServiceTest.importFromXml;
|
import static li.strolch.service.test.AbstractRealmServiceTest.importFromXml;
|
||||||
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import li.strolch.agent.api.ComponentContainer;
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
import li.strolch.agent.api.StrolchRealm;
|
import li.strolch.agent.api.StrolchRealm;
|
||||||
import li.strolch.persistence.api.StrolchTransaction;
|
import li.strolch.persistence.api.StrolchTransaction;
|
||||||
|
@ -33,12 +40,6 @@ import li.strolch.service.api.Command;
|
||||||
import li.strolch.service.api.ServiceHandler;
|
import li.strolch.service.api.ServiceHandler;
|
||||||
import li.strolch.testbase.runtime.RuntimeMock;
|
import li.strolch.testbase.runtime.RuntimeMock;
|
||||||
|
|
||||||
import org.junit.AfterClass;
|
|
||||||
import org.junit.BeforeClass;
|
|
||||||
import org.junit.Rule;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.rules.ExpectedException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
*/
|
*/
|
||||||
|
@ -48,9 +49,6 @@ public abstract class AbstractRealmCommandTest {
|
||||||
|
|
||||||
protected static Certificate certificate;
|
protected static Certificate certificate;
|
||||||
|
|
||||||
@Rule
|
|
||||||
public ExpectedException expectedException = ExpectedException.none();
|
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void beforeClass() throws Exception {
|
public static void beforeClass() throws Exception {
|
||||||
|
|
||||||
|
@ -80,17 +78,27 @@ public abstract class AbstractRealmCommandTest {
|
||||||
|
|
||||||
protected abstract Command getCommandInstance(ComponentContainer container, StrolchTransaction tx);
|
protected abstract Command getCommandInstance(ComponentContainer container, StrolchTransaction tx);
|
||||||
|
|
||||||
protected void doCommandAsFail(String realmName) {
|
protected abstract void validateAfterCommand(ComponentContainer container, StrolchTransaction tx);
|
||||||
this.expectedException.expect(RuntimeException.class);
|
|
||||||
this.expectedException.expectMessage("Fail on purpose after do command!");
|
|
||||||
|
|
||||||
|
protected abstract void validateAfterCommandFailed(ComponentContainer container, StrolchTransaction tx);
|
||||||
|
|
||||||
|
protected void doCommandAsFail(String realmName) {
|
||||||
StrolchRealm realm = runtimeMock.getContainer().getRealm(realmName);
|
StrolchRealm realm = runtimeMock.getContainer().getRealm(realmName);
|
||||||
|
boolean caught = false;
|
||||||
try (StrolchTransaction tx = realm.openTx(certificate, "test")) {
|
try (StrolchTransaction tx = realm.openTx(certificate, "test")) {
|
||||||
Command command = getCommandInstance(runtimeMock.getContainer(), tx);
|
Command command = getCommandInstance(runtimeMock.getContainer(), tx);
|
||||||
FailCommandFacade commandFacade = new FailCommandFacade(runtimeMock.getContainer(), tx, command);
|
FailCommandFacade commandFacade = new FailCommandFacade(runtimeMock.getContainer(), tx, command);
|
||||||
|
|
||||||
tx.addCommand(commandFacade);
|
tx.addCommand(commandFacade);
|
||||||
tx.commitOnClose();
|
tx.commitOnClose();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
assertThat(e.getMessage(), containsString("Fail on purpose after do command!"));
|
||||||
|
caught = true;
|
||||||
|
}
|
||||||
|
assertTrue(caught);
|
||||||
|
|
||||||
|
try (StrolchTransaction tx = realm.openTx(certificate, "test")) {
|
||||||
|
validateAfterCommandFailed(runtimeMock.getContainer(), tx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,21 +109,28 @@ public abstract class AbstractRealmCommandTest {
|
||||||
tx.addCommand(command);
|
tx.addCommand(command);
|
||||||
tx.commitOnClose();
|
tx.commitOnClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try (StrolchTransaction tx = realm.openTx(certificate, "test")) {
|
||||||
|
validateAfterCommand(runtimeMock.getContainer(), tx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldFailCommandTransient() {
|
public void shouldDoCommandTransient() {
|
||||||
doCommandAsFail(REALM_TRANSIENT);
|
doCommandAsFail(REALM_TRANSIENT);
|
||||||
|
doCommand(REALM_TRANSIENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldFailCommandCached() {
|
public void shouldDoCommandCached() {
|
||||||
doCommandAsFail(REALM_CACHED);
|
doCommandAsFail(REALM_CACHED);
|
||||||
|
doCommand(REALM_CACHED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldFailCommandTransactional() {
|
public void shouldDoCommandTransactional() {
|
||||||
doCommandAsFail(REALM_TRANSACTIONAL);
|
doCommandAsFail(REALM_TRANSACTIONAL);
|
||||||
|
doCommand(REALM_TRANSACTIONAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class FailCommandFacade extends Command {
|
private class FailCommandFacade extends Command {
|
||||||
|
|
|
@ -15,17 +15,20 @@
|
||||||
*/
|
*/
|
||||||
package li.strolch.command;
|
package li.strolch.command;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
|
||||||
import li.strolch.agent.api.ComponentContainer;
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
import li.strolch.model.ModelGenerator;
|
import li.strolch.model.ModelGenerator;
|
||||||
import li.strolch.model.Order;
|
import li.strolch.model.Order;
|
||||||
import li.strolch.persistence.api.StrolchTransaction;
|
import li.strolch.persistence.api.StrolchTransaction;
|
||||||
import li.strolch.service.api.Command;
|
import li.strolch.service.api.Command;
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
*/
|
*/
|
||||||
|
@ -48,4 +51,18 @@ public class AddOrderCollectionCommandTest extends AbstractRealmCommandTest {
|
||||||
command.setOrders(this.orders);
|
command.setOrders(this.orders);
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommand(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
for (Order order : orders) {
|
||||||
|
assertTrue(tx.getOrderMap().hasElement(tx, order.getType(), order.getId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommandFailed(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
for (Order order : orders) {
|
||||||
|
assertFalse(tx.getOrderMap().hasElement(tx, order.getType(), order.getId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,14 +15,17 @@
|
||||||
*/
|
*/
|
||||||
package li.strolch.command;
|
package li.strolch.command;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
|
||||||
import li.strolch.agent.api.ComponentContainer;
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
import li.strolch.model.ModelGenerator;
|
import li.strolch.model.ModelGenerator;
|
||||||
import li.strolch.model.Order;
|
import li.strolch.model.Order;
|
||||||
import li.strolch.persistence.api.StrolchTransaction;
|
import li.strolch.persistence.api.StrolchTransaction;
|
||||||
import li.strolch.service.api.Command;
|
import li.strolch.service.api.Command;
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
*/
|
*/
|
||||||
|
@ -42,4 +45,14 @@ public class AddOrderCommandTest extends AbstractRealmCommandTest {
|
||||||
command.setOrder(this.order);
|
command.setOrder(this.order);
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommand(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
assertTrue(tx.getOrderMap().hasElement(tx, this.order.getType(), this.order.getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommandFailed(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
assertFalse(tx.getOrderMap().hasElement(tx, this.order.getType(), this.order.getId()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,17 +15,20 @@
|
||||||
*/
|
*/
|
||||||
package li.strolch.command;
|
package li.strolch.command;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
|
||||||
import li.strolch.agent.api.ComponentContainer;
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
import li.strolch.model.ModelGenerator;
|
import li.strolch.model.ModelGenerator;
|
||||||
import li.strolch.model.Resource;
|
import li.strolch.model.Resource;
|
||||||
import li.strolch.persistence.api.StrolchTransaction;
|
import li.strolch.persistence.api.StrolchTransaction;
|
||||||
import li.strolch.service.api.Command;
|
import li.strolch.service.api.Command;
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
*/
|
*/
|
||||||
|
@ -48,4 +51,18 @@ public class AddResourceCollectionCommandTest extends AbstractRealmCommandTest {
|
||||||
command.setResources(this.resources);
|
command.setResources(this.resources);
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommand(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
for (Resource resource : resources) {
|
||||||
|
assertTrue(tx.getResourceMap().hasElement(tx, resource.getType(), resource.getId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommandFailed(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
for (Resource resource : resources) {
|
||||||
|
assertFalse(tx.getResourceMap().hasElement(tx, resource.getType(), resource.getId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,14 +15,17 @@
|
||||||
*/
|
*/
|
||||||
package li.strolch.command;
|
package li.strolch.command;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
|
||||||
import li.strolch.agent.api.ComponentContainer;
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
import li.strolch.model.ModelGenerator;
|
import li.strolch.model.ModelGenerator;
|
||||||
import li.strolch.model.Resource;
|
import li.strolch.model.Resource;
|
||||||
import li.strolch.persistence.api.StrolchTransaction;
|
import li.strolch.persistence.api.StrolchTransaction;
|
||||||
import li.strolch.service.api.Command;
|
import li.strolch.service.api.Command;
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
*/
|
*/
|
||||||
|
@ -42,4 +45,14 @@ public class AddResourceCommandTest extends AbstractRealmCommandTest {
|
||||||
command.setResource(this.resource);
|
command.setResource(this.resource);
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommand(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
assertTrue(tx.getResourceMap().hasElement(tx, this.resource.getType(), this.resource.getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommandFailed(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
assertFalse(tx.getResourceMap().hasElement(tx, this.resource.getType(), this.resource.getId()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,14 @@
|
||||||
*/
|
*/
|
||||||
package li.strolch.command;
|
package li.strolch.command;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
|
||||||
import li.strolch.agent.api.ComponentContainer;
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
import li.strolch.model.Locator;
|
import li.strolch.model.Locator;
|
||||||
import li.strolch.model.Order;
|
import li.strolch.model.Order;
|
||||||
|
@ -25,8 +30,6 @@ import li.strolch.model.Tags;
|
||||||
import li.strolch.persistence.api.StrolchTransaction;
|
import li.strolch.persistence.api.StrolchTransaction;
|
||||||
import li.strolch.service.api.Command;
|
import li.strolch.service.api.Command;
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
*/
|
*/
|
||||||
|
@ -54,4 +57,18 @@ public class RemoveOrderCollectionCommandTest extends AbstractRealmCommandTest {
|
||||||
command.setOrders(orders);
|
command.setOrders(orders);
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommand(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
for (Locator locator : locators) {
|
||||||
|
assertFalse(tx.getOrderMap().hasElement(tx, locator.get(1), locator.get(2)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommandFailed(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
for (Locator locator : locators) {
|
||||||
|
assertTrue(tx.getOrderMap().hasElement(tx, locator.get(1), locator.get(2)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,11 @@
|
||||||
*/
|
*/
|
||||||
package li.strolch.command;
|
package li.strolch.command;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
|
||||||
import li.strolch.agent.api.ComponentContainer;
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
import li.strolch.model.Locator;
|
import li.strolch.model.Locator;
|
||||||
import li.strolch.model.Order;
|
import li.strolch.model.Order;
|
||||||
|
@ -22,8 +27,6 @@ import li.strolch.model.Tags;
|
||||||
import li.strolch.persistence.api.StrolchTransaction;
|
import li.strolch.persistence.api.StrolchTransaction;
|
||||||
import li.strolch.service.api.Command;
|
import li.strolch.service.api.Command;
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
*/
|
*/
|
||||||
|
@ -45,4 +48,14 @@ public class RemoveOrderCommandTest extends AbstractRealmCommandTest {
|
||||||
command.setOrder(order);
|
command.setOrder(order);
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommand(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
assertFalse(tx.getOrderMap().hasElement(tx, "TestType", "@3"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommandFailed(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
assertTrue(tx.getOrderMap().hasElement(tx, "TestType", "@3"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,14 @@
|
||||||
*/
|
*/
|
||||||
package li.strolch.command;
|
package li.strolch.command;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
|
||||||
import li.strolch.agent.api.ComponentContainer;
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
import li.strolch.model.Locator;
|
import li.strolch.model.Locator;
|
||||||
import li.strolch.model.Resource;
|
import li.strolch.model.Resource;
|
||||||
|
@ -25,8 +30,6 @@ import li.strolch.model.Tags;
|
||||||
import li.strolch.persistence.api.StrolchTransaction;
|
import li.strolch.persistence.api.StrolchTransaction;
|
||||||
import li.strolch.service.api.Command;
|
import li.strolch.service.api.Command;
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
*/
|
*/
|
||||||
|
@ -54,4 +57,18 @@ public class RemoveResourceCollectionCommandTest extends AbstractRealmCommandTes
|
||||||
command.setResources(resources);
|
command.setResources(resources);
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommand(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
for (Locator locator : locators) {
|
||||||
|
assertFalse(tx.getResourceMap().hasElement(tx, locator.get(1), locator.get(2)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommandFailed(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
for (Locator locator : locators) {
|
||||||
|
assertTrue(tx.getResourceMap().hasElement(tx, locator.get(1), locator.get(2)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,11 @@
|
||||||
*/
|
*/
|
||||||
package li.strolch.command;
|
package li.strolch.command;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
|
||||||
import li.strolch.agent.api.ComponentContainer;
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
import li.strolch.model.Locator;
|
import li.strolch.model.Locator;
|
||||||
import li.strolch.model.Resource;
|
import li.strolch.model.Resource;
|
||||||
|
@ -22,8 +27,6 @@ import li.strolch.model.Tags;
|
||||||
import li.strolch.persistence.api.StrolchTransaction;
|
import li.strolch.persistence.api.StrolchTransaction;
|
||||||
import li.strolch.service.api.Command;
|
import li.strolch.service.api.Command;
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
*/
|
*/
|
||||||
|
@ -45,4 +48,14 @@ public class RemoveResourceCommandTest extends AbstractRealmCommandTest {
|
||||||
command.setResource(resource);
|
command.setResource(resource);
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommand(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
assertFalse(tx.getResourceMap().hasElement(tx, "Enumeration", "sex"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommandFailed(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
assertTrue(tx.getResourceMap().hasElement(tx, "Enumeration", "sex"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,17 +15,19 @@
|
||||||
*/
|
*/
|
||||||
package li.strolch.command;
|
package li.strolch.command;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
|
||||||
import li.strolch.agent.api.ComponentContainer;
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
import li.strolch.model.ModelGenerator;
|
import li.strolch.model.ModelGenerator;
|
||||||
import li.strolch.model.Order;
|
import li.strolch.model.Order;
|
||||||
import li.strolch.persistence.api.StrolchTransaction;
|
import li.strolch.persistence.api.StrolchTransaction;
|
||||||
import li.strolch.service.api.Command;
|
import li.strolch.service.api.Command;
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
*/
|
*/
|
||||||
|
@ -36,6 +38,7 @@ public class UpdateOrderCollectionCommandTest extends AbstractRealmCommandTest {
|
||||||
@Before
|
@Before
|
||||||
public void before() {
|
public void before() {
|
||||||
this.orders = new ArrayList<>();
|
this.orders = new ArrayList<>();
|
||||||
|
// we create elements with the same id as already exists!
|
||||||
this.orders.add(ModelGenerator.createOrder("@1", "Modified Test Order", "TestType"));
|
this.orders.add(ModelGenerator.createOrder("@1", "Modified Test Order", "TestType"));
|
||||||
this.orders.add(ModelGenerator.createOrder("@2", "Modified Test Order", "TestType"));
|
this.orders.add(ModelGenerator.createOrder("@2", "Modified Test Order", "TestType"));
|
||||||
this.orders.add(ModelGenerator.createOrder("@3", "Modified Test Order", "TestType"));
|
this.orders.add(ModelGenerator.createOrder("@3", "Modified Test Order", "TestType"));
|
||||||
|
@ -48,4 +51,20 @@ public class UpdateOrderCollectionCommandTest extends AbstractRealmCommandTest {
|
||||||
command.setOrders(this.orders);
|
command.setOrders(this.orders);
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommand(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
for (Order order : orders) {
|
||||||
|
Order o = tx.getOrderBy(order.getType(), order.getId());
|
||||||
|
assertEquals("Modified Test Order", o.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommandFailed(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
for (Order order : orders) {
|
||||||
|
Order o = tx.getOrderBy(order.getType(), order.getId());
|
||||||
|
assertEquals("Test Name", o.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,4 +42,16 @@ public class UpdateOrderCommandTest extends AbstractRealmCommandTest {
|
||||||
command.setOrder(this.order);
|
command.setOrder(this.order);
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommand(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommandFailed(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,17 +15,19 @@
|
||||||
*/
|
*/
|
||||||
package li.strolch.command;
|
package li.strolch.command;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
|
||||||
import li.strolch.agent.api.ComponentContainer;
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
import li.strolch.model.ModelGenerator;
|
import li.strolch.model.ModelGenerator;
|
||||||
import li.strolch.model.Resource;
|
import li.strolch.model.Resource;
|
||||||
import li.strolch.persistence.api.StrolchTransaction;
|
import li.strolch.persistence.api.StrolchTransaction;
|
||||||
import li.strolch.service.api.Command;
|
import li.strolch.service.api.Command;
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
*/
|
*/
|
||||||
|
@ -48,4 +50,20 @@ public class UpdateResourceCollectionCommandTest extends AbstractRealmCommandTes
|
||||||
command.setResources(this.resources);
|
command.setResources(this.resources);
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommand(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
for (Resource resource : this.resources) {
|
||||||
|
Resource r = tx.getResourceBy(resource.getType(), resource.getId());
|
||||||
|
assertEquals("Modified Enumeration", r.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommandFailed(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
for (Resource resource : this.resources) {
|
||||||
|
Resource r = tx.getResourceBy(resource.getType(), resource.getId());
|
||||||
|
assertEquals(r.getId(), r.getName().toLowerCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,4 +42,16 @@ public class UpdateResourceCommandTest extends AbstractRealmCommandTest {
|
||||||
command.setResource(this.resource);
|
command.setResource(this.resource);
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommand(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommandFailed(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,11 @@
|
||||||
*/
|
*/
|
||||||
package li.strolch.command.parameter;
|
package li.strolch.command.parameter;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
|
||||||
import li.strolch.agent.api.ComponentContainer;
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
import li.strolch.command.AbstractRealmCommandTest;
|
import li.strolch.command.AbstractRealmCommandTest;
|
||||||
import li.strolch.model.Locator;
|
import li.strolch.model.Locator;
|
||||||
|
@ -24,8 +29,6 @@ import li.strolch.model.parameter.Parameter;
|
||||||
import li.strolch.persistence.api.StrolchTransaction;
|
import li.strolch.persistence.api.StrolchTransaction;
|
||||||
import li.strolch.service.api.Command;
|
import li.strolch.service.api.Command;
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
*/
|
*/
|
||||||
|
@ -50,4 +53,16 @@ public class AddParameterCommandTest extends AbstractRealmCommandTest {
|
||||||
command.setParameter(this.parameter);
|
command.setParameter(this.parameter);
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommand(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
ParameterizedElement element = tx.findElement(this.locator);
|
||||||
|
assertTrue(element.hasParameter(this.parameter.getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommandFailed(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
ParameterizedElement element = tx.findElement(this.locator);
|
||||||
|
assertFalse(element.hasParameter(this.parameter.getId()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,11 @@
|
||||||
*/
|
*/
|
||||||
package li.strolch.command.parameter;
|
package li.strolch.command.parameter;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
|
||||||
import li.strolch.agent.api.ComponentContainer;
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
import li.strolch.command.AbstractRealmCommandTest;
|
import li.strolch.command.AbstractRealmCommandTest;
|
||||||
import li.strolch.model.Locator;
|
import li.strolch.model.Locator;
|
||||||
|
@ -22,8 +27,6 @@ import li.strolch.model.ParameterizedElement;
|
||||||
import li.strolch.persistence.api.StrolchTransaction;
|
import li.strolch.persistence.api.StrolchTransaction;
|
||||||
import li.strolch.service.api.Command;
|
import li.strolch.service.api.Command;
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
*/
|
*/
|
||||||
|
@ -48,4 +51,16 @@ public class RemoveParameterCommandTest extends AbstractRealmCommandTest {
|
||||||
command.setParameterId(this.parameterId);
|
command.setParameterId(this.parameterId);
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommand(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
ParameterizedElement element = tx.findElement(this.locator);
|
||||||
|
assertFalse(element.hasParameter(this.parameterId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommandFailed(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
ParameterizedElement element = tx.findElement(this.locator);
|
||||||
|
assertTrue(element.hasParameter(this.parameterId));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package li.strolch.command.parameter;
|
package li.strolch.command.parameter;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
|
||||||
import li.strolch.agent.api.ComponentContainer;
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
import li.strolch.command.AbstractRealmCommandTest;
|
import li.strolch.command.AbstractRealmCommandTest;
|
||||||
import li.strolch.model.Locator;
|
import li.strolch.model.Locator;
|
||||||
|
@ -22,8 +26,6 @@ import li.strolch.model.parameter.Parameter;
|
||||||
import li.strolch.persistence.api.StrolchTransaction;
|
import li.strolch.persistence.api.StrolchTransaction;
|
||||||
import li.strolch.service.api.Command;
|
import li.strolch.service.api.Command;
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
*/
|
*/
|
||||||
|
@ -31,6 +33,7 @@ public class SetParameterCommandTest extends AbstractRealmCommandTest {
|
||||||
|
|
||||||
private Locator locator;
|
private Locator locator;
|
||||||
private String valueAsString;
|
private String valueAsString;
|
||||||
|
private String originalValue;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void before() {
|
public void before() {
|
||||||
|
@ -42,10 +45,23 @@ public class SetParameterCommandTest extends AbstractRealmCommandTest {
|
||||||
protected Command getCommandInstance(ComponentContainer container, StrolchTransaction tx) {
|
protected Command getCommandInstance(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
|
||||||
Parameter<?> parameter = tx.findElement(this.locator);
|
Parameter<?> parameter = tx.findElement(this.locator);
|
||||||
|
this.originalValue = parameter.getValueAsString();
|
||||||
|
|
||||||
SetParameterCommand command = new SetParameterCommand(container, tx);
|
SetParameterCommand command = new SetParameterCommand(container, tx);
|
||||||
command.setValueAsString(this.valueAsString);
|
command.setValueAsString(this.valueAsString);
|
||||||
command.setParameter(parameter);
|
command.setParameter(parameter);
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommand(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
Parameter<?> parameter = tx.findElement(this.locator);
|
||||||
|
assertEquals(this.valueAsString, parameter.getValueAsString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateAfterCommandFailed(ComponentContainer container, StrolchTransaction tx) {
|
||||||
|
Parameter<?> parameter = tx.findElement(this.locator);
|
||||||
|
assertEquals(this.originalValue, parameter.getValueAsString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,15 +15,15 @@
|
||||||
*/
|
*/
|
||||||
package li.strolch.testbase.runtime;
|
package li.strolch.testbase.runtime;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import li.strolch.persistence.api.StrolchTransaction;
|
import li.strolch.persistence.api.StrolchTransaction;
|
||||||
import li.strolch.privilege.model.Certificate;
|
import li.strolch.privilege.model.Certificate;
|
||||||
import li.strolch.runtime.StrolchConstants;
|
import li.strolch.runtime.StrolchConstants;
|
||||||
import li.strolch.runtime.privilege.PrivilegeHandler;
|
import li.strolch.runtime.privilege.PrivilegeHandler;
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public abstract class AbstractModelTest {
|
public abstract class AbstractModelTest {
|
||||||
|
|
||||||
protected static final Logger logger = LoggerFactory.getLogger(AbstractModelTest.class);
|
protected static final Logger logger = LoggerFactory.getLogger(AbstractModelTest.class);
|
||||||
|
@ -97,9 +97,43 @@ public abstract class AbstractModelTest {
|
||||||
testRunner.runBulkOperationTests();
|
testRunner.runBulkOperationTests();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldCreateActivities() {
|
||||||
|
|
||||||
|
ActivityModelTestRunner testRunner = new ActivityModelTestRunner(getRuntimeMock(), this.realmName);
|
||||||
|
testRunner.runCreateActivityTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldQueryActivitySizes() {
|
||||||
|
|
||||||
|
ActivityModelTestRunner testRunner = new ActivityModelTestRunner(getRuntimeMock(), this.realmName);
|
||||||
|
testRunner.runQuerySizeTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldActivityCrud() {
|
||||||
|
|
||||||
|
ActivityModelTestRunner testRunner = new ActivityModelTestRunner(getRuntimeMock(), this.realmName);
|
||||||
|
testRunner.runCrudTests();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldActivityPerformBulkOperations() {
|
||||||
|
|
||||||
|
ActivityModelTestRunner testRunner = new ActivityModelTestRunner(getRuntimeMock(), this.realmName);
|
||||||
|
testRunner.runBulkOperationTests();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldTestAudits() {
|
public void shouldTestAudits() {
|
||||||
AuditModelTestRunner testRunner = new AuditModelTestRunner(getRuntimeMock(), this.realmName);
|
AuditModelTestRunner testRunner = new AuditModelTestRunner(getRuntimeMock(), this.realmName);
|
||||||
testRunner.runTestForAudits();
|
testRunner.runTestForAudits();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldTestVersioning() {
|
||||||
|
VersioningTestRunner testRunner = new VersioningTestRunner(getRuntimeMock());
|
||||||
|
testRunner.runTestsForVersioning();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,276 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2015 Robert von Burg <eitch@eitchnet.ch>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package li.strolch.testbase.runtime;
|
||||||
|
|
||||||
|
import static li.strolch.model.ModelGenerator.BAG_ID;
|
||||||
|
import static li.strolch.model.ModelGenerator.PARAM_STRING_ID;
|
||||||
|
import static li.strolch.model.ModelGenerator.createActivities;
|
||||||
|
import static li.strolch.model.ModelGenerator.createActivity;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import li.strolch.agent.api.ActivityMap;
|
||||||
|
import li.strolch.agent.impl.DataStoreMode;
|
||||||
|
import li.strolch.model.activity.Activity;
|
||||||
|
import li.strolch.model.parameter.Parameter;
|
||||||
|
import li.strolch.persistence.api.StrolchTransaction;
|
||||||
|
import li.strolch.privilege.model.Certificate;
|
||||||
|
import li.strolch.runtime.privilege.PrivilegeHandler;
|
||||||
|
|
||||||
|
@SuppressWarnings("nls")
|
||||||
|
public class ActivityModelTestRunner {
|
||||||
|
|
||||||
|
private static final String ID = "@testActivity";
|
||||||
|
private static final String NAME = "Test Activity";
|
||||||
|
private static final String TYPE = "Produce";
|
||||||
|
|
||||||
|
private RuntimeMock runtimeMock;
|
||||||
|
private String realmName;
|
||||||
|
private Certificate certificate;
|
||||||
|
|
||||||
|
public ActivityModelTestRunner(RuntimeMock runtimeMock, String realmName) {
|
||||||
|
this.runtimeMock = runtimeMock;
|
||||||
|
this.realmName = realmName;
|
||||||
|
|
||||||
|
PrivilegeHandler privilegeHandler = runtimeMock.getContainer().getPrivilegeHandler();
|
||||||
|
this.certificate = privilegeHandler.authenticate("test", "test".getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runCreateActivityTest() {
|
||||||
|
|
||||||
|
// create
|
||||||
|
Activity newActivity = createActivity("MyTestActivity", "Test Name", "TestType"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
|
||||||
|
tx.getActivityMap().add(tx, newActivity);
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runQuerySizeTest() {
|
||||||
|
|
||||||
|
// remove all
|
||||||
|
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
|
||||||
|
tx.getActivityMap().removeAll(tx, tx.getActivityMap().getAllElements(tx));
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// create three activities
|
||||||
|
Activity activity1 = createActivity("myTestActivity1", "Test Name", "QTestType1"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
Activity activity2 = createActivity("myTestActivity2", "Test Name", "QTestType2"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
Activity activity3 = createActivity("myTestActivity3", "Test Name", "QTestType3"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
|
||||||
|
tx.getActivityMap().add(tx, activity1);
|
||||||
|
tx.getActivityMap().add(tx, activity2);
|
||||||
|
tx.getActivityMap().add(tx, activity3);
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// query size
|
||||||
|
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
|
||||||
|
long size = tx.getActivityMap().querySize(tx);
|
||||||
|
assertEquals("Should have three objects", 3, size);
|
||||||
|
|
||||||
|
size = tx.getActivityMap().querySize(tx, "QTestType1");
|
||||||
|
assertEquals("Should have only one object of type 'QTestType1'", 1, size);
|
||||||
|
|
||||||
|
size = tx.getActivityMap().querySize(tx, "QTestType2");
|
||||||
|
assertEquals("Should have only one object of type 'QTestType1'", 1, size);
|
||||||
|
|
||||||
|
size = tx.getActivityMap().querySize(tx, "QTestType3");
|
||||||
|
assertEquals("Should have only one object of type 'QTestType1'", 1, size);
|
||||||
|
|
||||||
|
size = tx.getActivityMap().querySize(tx, "NonExistingType");
|
||||||
|
assertEquals("Should have zero objects of type 'NonExistingType'", 0, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runCrudTests() {
|
||||||
|
|
||||||
|
// create
|
||||||
|
Activity newActivity = createActivity(ID, NAME, TYPE);
|
||||||
|
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
|
||||||
|
tx.getActivityMap().add(tx, newActivity);
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// read
|
||||||
|
Activity readActivity = null;
|
||||||
|
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
|
||||||
|
readActivity = tx.getActivityMap().getBy(tx, TYPE, ID);
|
||||||
|
}
|
||||||
|
assertNotNull("Should read Activity with id " + ID, readActivity);
|
||||||
|
|
||||||
|
// update
|
||||||
|
Parameter<String> sParam = readActivity.getParameter(BAG_ID, PARAM_STRING_ID);
|
||||||
|
String newStringValue = "Giddiya!";
|
||||||
|
sParam.setValue(newStringValue);
|
||||||
|
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
|
||||||
|
tx.getActivityMap().update(tx, readActivity);
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// read updated
|
||||||
|
Activity updatedActivity = null;
|
||||||
|
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
|
||||||
|
updatedActivity = tx.getActivityMap().getBy(tx, TYPE, ID);
|
||||||
|
}
|
||||||
|
assertNotNull("Should read Activity with id " + ID, updatedActivity);
|
||||||
|
if (this.runtimeMock.getRealm(this.realmName).getMode() != DataStoreMode.CACHED)
|
||||||
|
assertFalse("Objects can't be the same reference after re-reading!", readActivity == updatedActivity);
|
||||||
|
Parameter<String> updatedParam = readActivity.getParameter(BAG_ID, PARAM_STRING_ID);
|
||||||
|
assertEquals(newStringValue, updatedParam.getValue());
|
||||||
|
|
||||||
|
// delete
|
||||||
|
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
|
||||||
|
tx.getActivityMap().remove(tx, readActivity);
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// fail to re-read
|
||||||
|
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
|
||||||
|
Activity activity = tx.getActivityMap().getBy(tx, TYPE, ID);
|
||||||
|
assertNull("Should no read Activity with id " + ID, activity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runBulkOperationTests() {
|
||||||
|
|
||||||
|
// create 15 activities
|
||||||
|
List<Activity> activities = new ArrayList<>();
|
||||||
|
activities.addAll(createActivities(activities.size(), 5, "@", "My Activity", "MyType1"));
|
||||||
|
activities.addAll(createActivities(activities.size(), 5, "@", "Other Activity", "MyType2"));
|
||||||
|
activities.addAll(createActivities(activities.size(), 5, "@", "Further Activity", "MyType3"));
|
||||||
|
|
||||||
|
// sort them so we know which activity our objects are
|
||||||
|
Comparator<Activity> comparator = new Comparator<Activity>() {
|
||||||
|
@Override
|
||||||
|
public int compare(Activity o1, Activity o2) {
|
||||||
|
return o1.getId().compareTo(o2.getId());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Collections.sort(activities, comparator);
|
||||||
|
|
||||||
|
// first clear the map, so that we have a clean state
|
||||||
|
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
|
||||||
|
ActivityMap activityMap = tx.getActivityMap();
|
||||||
|
activityMap.removeAll(tx, activityMap.getAllElements(tx));
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// make sure it is empty
|
||||||
|
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
|
||||||
|
ActivityMap activityMap = tx.getActivityMap();
|
||||||
|
assertEquals(0, activityMap.querySize(tx));
|
||||||
|
}
|
||||||
|
|
||||||
|
// now add some activities
|
||||||
|
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
|
||||||
|
tx.getActivityMap().addAll(tx, activities);
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure we have our expected size
|
||||||
|
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
|
||||||
|
ActivityMap activityMap = tx.getActivityMap();
|
||||||
|
assertEquals(activities.size(), activityMap.querySize(tx));
|
||||||
|
assertEquals(5, activityMap.querySize(tx, "MyType3"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// now use the remove all by type
|
||||||
|
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
|
||||||
|
tx.getActivityMap().removeAllBy(tx, "MyType3");
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// again make sure we have our expected size
|
||||||
|
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
|
||||||
|
ActivityMap activityMap = tx.getActivityMap();
|
||||||
|
assertEquals(activities.size() - 5, activityMap.querySize(tx));
|
||||||
|
assertEquals(0, activityMap.querySize(tx, "MyType3"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// now use the remove all
|
||||||
|
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
|
||||||
|
long removed = tx.getActivityMap().removeAll(tx);
|
||||||
|
assertEquals(activities.size() - 5, removed);
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// again make sure we have our expected size
|
||||||
|
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
|
||||||
|
ActivityMap activityMap = tx.getActivityMap();
|
||||||
|
assertEquals(0, activityMap.querySize(tx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the version
|
||||||
|
activities.forEach(t -> t.setVersion(null));
|
||||||
|
|
||||||
|
// now add all again
|
||||||
|
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
|
||||||
|
tx.getActivityMap().addAll(tx, activities);
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<String> expectedTypes = new HashSet<>();
|
||||||
|
expectedTypes.add("MyType1");
|
||||||
|
expectedTypes.add("MyType2");
|
||||||
|
expectedTypes.add("MyType3");
|
||||||
|
|
||||||
|
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
|
||||||
|
List<Activity> allActivities = tx.getActivityMap().getAllElements(tx);
|
||||||
|
Collections.sort(allActivities, comparator);
|
||||||
|
assertEquals(activities, allActivities);
|
||||||
|
}
|
||||||
|
|
||||||
|
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
|
||||||
|
ActivityMap activityMap = tx.getActivityMap();
|
||||||
|
|
||||||
|
Set<String> types = activityMap.getTypes(tx);
|
||||||
|
assertEquals(expectedTypes, types);
|
||||||
|
|
||||||
|
Set<String> keySet = activityMap.getAllKeys(tx);
|
||||||
|
assertEquals(15, keySet.size());
|
||||||
|
|
||||||
|
for (String type : types) {
|
||||||
|
Set<String> idsByType = activityMap.getKeysBy(tx, type);
|
||||||
|
assertEquals(5, idsByType.size());
|
||||||
|
|
||||||
|
List<Activity> activitiesByType = activityMap.getElementsBy(tx, type);
|
||||||
|
assertEquals(5, activitiesByType.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
|
||||||
|
Activity activity = tx.getActivityMap().getBy(tx, "MyType1", "@00000001");
|
||||||
|
assertNotNull(activity);
|
||||||
|
activity = tx.getActivityMap().getBy(tx, "MyType2", "@00000006");
|
||||||
|
assertNotNull(activity);
|
||||||
|
activity = tx.getActivityMap().getBy(tx, "MyType3", "@00000011");
|
||||||
|
assertNotNull(activity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -226,6 +226,9 @@ public class OrderModelTestRunner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove the version
|
||||||
|
orders.forEach(t -> t.setVersion(null));
|
||||||
|
|
||||||
// now add all again
|
// now add all again
|
||||||
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
|
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
|
||||||
tx.getOrderMap().addAll(tx, orders);
|
tx.getOrderMap().addAll(tx, orders);
|
||||||
|
|
|
@ -226,6 +226,8 @@ public class ResourceModelTestRunner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resources.forEach(t -> t.setVersion(null));
|
||||||
|
|
||||||
// now add all again
|
// now add all again
|
||||||
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
|
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
|
||||||
tx.getResourceMap().addAll(tx, resources);
|
tx.getResourceMap().addAll(tx, resources);
|
||||||
|
|
|
@ -0,0 +1,195 @@
|
||||||
|
package li.strolch.testbase.runtime;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
|
import li.strolch.model.ModelGenerator;
|
||||||
|
import li.strolch.model.Resource;
|
||||||
|
import li.strolch.persistence.api.StrolchTransaction;
|
||||||
|
import li.strolch.privilege.model.Certificate;
|
||||||
|
import li.strolch.runtime.privilege.PrivilegeHandler;
|
||||||
|
|
||||||
|
public class VersioningTestRunner {
|
||||||
|
|
||||||
|
private RuntimeMock runtimeMock;
|
||||||
|
private Certificate certificate;
|
||||||
|
|
||||||
|
public VersioningTestRunner(RuntimeMock runtimeMock) {
|
||||||
|
this.runtimeMock = runtimeMock;
|
||||||
|
|
||||||
|
PrivilegeHandler privilegeHandler = runtimeMock.getContainer().getPrivilegeHandler();
|
||||||
|
this.certificate = privilegeHandler.authenticate("test", "test".getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runTestsForVersioning() {
|
||||||
|
|
||||||
|
ComponentContainer container = runtimeMock.getContainer();
|
||||||
|
|
||||||
|
// initialize by adding a resource
|
||||||
|
try (StrolchTransaction tx = container.getRealm(certificate).openTx(certificate, VersioningTestRunner.class)) {
|
||||||
|
Resource res1 = ModelGenerator.createResource("MyTestResource", "Test Name", "TestType");
|
||||||
|
tx.getResourceMap().add(tx, res1);
|
||||||
|
// must be first version
|
||||||
|
assertEquals(0, res1.getVersion().getVersion());
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// first make sure that the we can't change anything without updating the model
|
||||||
|
try (StrolchTransaction tx = container.getRealm(certificate).openTx(certificate, VersioningTestRunner.class)) {
|
||||||
|
Resource res1 = tx.getResourceBy("TestType", "MyTestResource", true);
|
||||||
|
// must be first version
|
||||||
|
assertEquals(0, res1.getVersion().getVersion());
|
||||||
|
res1.setName("Something");
|
||||||
|
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
try (StrolchTransaction tx = container.getRealm(certificate).openTx(certificate, VersioningTestRunner.class)) {
|
||||||
|
Resource res1 = tx.getResourceBy("TestType", "MyTestResource", true);
|
||||||
|
assertEquals("Test Name", res1.getName());
|
||||||
|
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// now do a change
|
||||||
|
try (StrolchTransaction tx = container.getRealm(certificate).openTx(certificate, VersioningTestRunner.class)) {
|
||||||
|
Resource res1 = tx.getResourceBy("TestType", "MyTestResource", true);
|
||||||
|
res1.setName("Something");
|
||||||
|
tx.getResourceMap().update(tx, res1);
|
||||||
|
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
try (StrolchTransaction tx = container.getRealm(certificate).openTx(certificate, VersioningTestRunner.class)) {
|
||||||
|
Resource res1 = tx.getResourceBy("TestType", "MyTestResource", true);
|
||||||
|
assertEquals("Something", res1.getName());
|
||||||
|
// version must be incremented
|
||||||
|
assertEquals(1, res1.getVersion().getVersion());
|
||||||
|
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// now revert the change
|
||||||
|
try (StrolchTransaction tx = container.getRealm(certificate).openTx(certificate, VersioningTestRunner.class)) {
|
||||||
|
Resource revertedVersion = tx.getResourceMap().revertToVersion(tx, "TestType", "MyTestResource", 0);
|
||||||
|
assertEquals("Test Name", revertedVersion.getName());
|
||||||
|
// version must be incremented
|
||||||
|
assertEquals(2, revertedVersion.getVersion().getVersion());
|
||||||
|
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
try (StrolchTransaction tx = container.getRealm(certificate).openTx(certificate, VersioningTestRunner.class)) {
|
||||||
|
Resource res1 = tx.getResourceBy("TestType", "MyTestResource", true);
|
||||||
|
assertEquals("Test Name", res1.getName());
|
||||||
|
// version must be incremented
|
||||||
|
assertEquals(2, res1.getVersion().getVersion());
|
||||||
|
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// undo a version in same TX
|
||||||
|
try (StrolchTransaction tx = container.getRealm(certificate).openTx(certificate, VersioningTestRunner.class)) {
|
||||||
|
Resource res1 = tx.getResourceBy("TestType", "MyTestResource", true);
|
||||||
|
|
||||||
|
// create a new version:
|
||||||
|
res1.setName("Version 3");
|
||||||
|
tx.getResourceMap().update(tx, res1);
|
||||||
|
// version must be incremented
|
||||||
|
assertEquals(3, res1.getVersion().getVersion());
|
||||||
|
|
||||||
|
// now undo
|
||||||
|
tx.getResourceMap().undoVersion(tx, res1);
|
||||||
|
|
||||||
|
// and validate we have again version 2
|
||||||
|
res1 = tx.getResourceBy("TestType", "MyTestResource", true);
|
||||||
|
assertEquals("Test Name", res1.getName());
|
||||||
|
assertEquals(2, res1.getVersion().getVersion());
|
||||||
|
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
try (StrolchTransaction tx = container.getRealm(certificate).openTx(certificate, VersioningTestRunner.class)) {
|
||||||
|
Resource res1 = tx.getResourceBy("TestType", "MyTestResource", true);
|
||||||
|
assertEquals("Test Name", res1.getName());
|
||||||
|
// version must be incremented
|
||||||
|
assertEquals(2, res1.getVersion().getVersion());
|
||||||
|
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// undo all versions
|
||||||
|
try (StrolchTransaction tx = container.getRealm(certificate).openTx(certificate, VersioningTestRunner.class)) {
|
||||||
|
Resource res1;
|
||||||
|
|
||||||
|
// undo three times as we have version 0, 1, 2
|
||||||
|
res1 = tx.getResourceBy("TestType", "MyTestResource", true);
|
||||||
|
assertEquals(2, res1.getVersion().getVersion());
|
||||||
|
tx.getResourceMap().undoVersion(tx, res1);
|
||||||
|
|
||||||
|
res1 = tx.getResourceBy("TestType", "MyTestResource", true);
|
||||||
|
assertEquals(1, res1.getVersion().getVersion());
|
||||||
|
tx.getResourceMap().undoVersion(tx, res1);
|
||||||
|
|
||||||
|
res1 = tx.getResourceBy("TestType", "MyTestResource", true);
|
||||||
|
assertEquals(0, res1.getVersion().getVersion());
|
||||||
|
tx.getResourceMap().undoVersion(tx, res1);
|
||||||
|
|
||||||
|
// and validate all are deleted
|
||||||
|
assertFalse(tx.getResourceMap().hasElement(tx, "TestType", "MyTestResource"));
|
||||||
|
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// do a deletion
|
||||||
|
try (StrolchTransaction tx = container.getRealm(certificate).openTx(certificate, VersioningTestRunner.class)) {
|
||||||
|
Resource res1 = ModelGenerator.createResource("ball", "Red Ball", "Ball");
|
||||||
|
assertNull(res1.getVersion());
|
||||||
|
|
||||||
|
tx.getResourceMap().add(tx, res1);
|
||||||
|
assertEquals(0, res1.getVersion().getVersion());
|
||||||
|
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
try (StrolchTransaction tx = container.getRealm(certificate).openTx(certificate, VersioningTestRunner.class)) {
|
||||||
|
Resource res1 = tx.getResourceBy("Ball", "ball", true);
|
||||||
|
assertEquals("Red Ball", res1.getName());
|
||||||
|
|
||||||
|
tx.getResourceMap().remove(tx, res1);
|
||||||
|
// version must be incremented
|
||||||
|
assertEquals(1, res1.getVersion().getVersion());
|
||||||
|
|
||||||
|
res1 = tx.getResourceBy("Ball", "ball");
|
||||||
|
assertNull(res1);
|
||||||
|
|
||||||
|
assertFalse(tx.getResourceMap().hasElement(tx, "Ball", "ball"));
|
||||||
|
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// restore a version manually
|
||||||
|
try (StrolchTransaction tx = container.getRealm(certificate).openTx(certificate, VersioningTestRunner.class)) {
|
||||||
|
Resource res1 = tx.getResourceBy("Ball", "ball");
|
||||||
|
assertNull(res1);
|
||||||
|
|
||||||
|
List<Resource> versions = tx.getResourceMap().getVersionsFor(tx, "Ball", "ball");
|
||||||
|
assertEquals(2, versions.size());
|
||||||
|
|
||||||
|
res1 = versions.get(versions.size() - 1);
|
||||||
|
assertTrue(res1.getVersion().isDeleted());
|
||||||
|
tx.getResourceMap().add(tx, res1);
|
||||||
|
assertEquals(2, res1.getVersion().getVersion());
|
||||||
|
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
try (StrolchTransaction tx = container.getRealm(certificate).openTx(certificate, VersioningTestRunner.class)) {
|
||||||
|
Resource res1 = tx.getResourceBy("Ball", "ball");
|
||||||
|
assertNotNull(res1);
|
||||||
|
assertEquals(2, res1.getVersion().getVersion());
|
||||||
|
|
||||||
|
tx.commitOnClose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue