registry, T path);
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/StructureElement.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/StructureElement.java
new file mode 100644
index 000000000..8e9d15bff
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/StructureElement.java
@@ -0,0 +1,10 @@
+package org.argeo.slc.core.structure;
+
+/**
+ * Atomic element holding metadata such as description about the element which
+ * registered.
+ */
+public interface StructureElement {
+ /** Label of this element. */
+ public String getLabel();
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/StructureElementProvider.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/StructureElementProvider.java
new file mode 100644
index 000000000..b9aa14452
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/StructureElementProvider.java
@@ -0,0 +1,5 @@
+package org.argeo.slc.core.structure;
+
+public interface StructureElementProvider {
+ public StructureElement createStructureElement();
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/StructurePath.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/StructurePath.java
new file mode 100644
index 000000000..452dc9514
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/StructurePath.java
@@ -0,0 +1,16 @@
+package org.argeo.slc.core.structure;
+
+/**
+ * Path allowing to uniquely identify a StructureElement
within a
+ * registry.
+ *
+ * @see StructureElement
+ * @see StructurePath
+ */
+public interface StructurePath {
+ /**
+ * Unique representation as a string. Most implementation will also provide
+ * a mean to interpret this string.
+ */
+ public String getAsUniqueString();
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/StructureRegistry.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/StructureRegistry.java
new file mode 100644
index 000000000..71f80cb77
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/StructureRegistry.java
@@ -0,0 +1,57 @@
+package org.argeo.slc.core.structure;
+
+import java.util.List;
+
+import org.argeo.slc.core.deploy.DeployedSystem;
+
+/** Registry where the whole structure is stored. */
+public interface StructureRegistry {
+ /** Read mode: the structure is only read. */
+ public static String READ = "READ";
+ /** All mode: everything is executed regardless of the active paths. */
+ public static String ALL = "ALL";
+ /** Active mode: only the active paths are executed. */
+ public static String ACTIVE = "STATUS_ACTIVE";
+
+ /** Adds an element to the registry. */
+ public void register(P path, StructureElement element);
+
+ /** Lists all registered elements. */
+ public List listElements();
+
+ /** Lists all registered elements. */
+ public List listPaths();
+
+ /** Gets a element based on its path. */
+ public T getElement(P path);
+
+ /**
+ * Set the interpreter mode: read, all or active.
+ *
+ * @see #READ
+ * @see #ALL
+ * @see #STATUS_ACTIVE
+ */
+ public void setMode(String mode);
+
+ /**
+ * Gets the current interpreter mode.
+ *
+ * @see #READ
+ * @see #ALL
+ * @see #STATUS_ACTIVE
+ */
+ public String getMode();
+
+ /**
+ * Gets the list of active paths, which will be run if executed in
+ * STATUS_ACTIVE
mode.
+ */
+ public List getActivePaths();
+
+ /**
+ * Sets the list of active path, which will be run if executed in
+ * STATUS_ACTIVE
mode.
+ */
+ public void setActivePaths(List
activePaths);
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/package.html b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/package.html
new file mode 100644
index 000000000..d9bab8a55
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/package.html
@@ -0,0 +1,6 @@
+
+
+
+SLC Structure framework allowing to uniquely reference actions.
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/tree/TreeSPath.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/tree/TreeSPath.java
new file mode 100644
index 000000000..a31239f83
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/tree/TreeSPath.java
@@ -0,0 +1,205 @@
+package org.argeo.slc.core.structure.tree;
+
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import org.argeo.slc.core.SlcException;
+import org.argeo.slc.core.structure.StructurePath;
+import org.argeo.slc.core.structure.StructureRegistry;
+
+/**
+ * Path for tree based StructureRegistry
implementations.
+ */
+public class TreeSPath implements StructurePath, Comparable {
+ /** Default character to use a separator: /. */
+ private static Character DEFAULT_SEPARATOR = '/';
+
+ private Character separator = DEFAULT_SEPARATOR;
+
+ private String asUniqueString;
+
+ /** For ORM */
+ private Long tid;
+
+ public TreeSPath() {
+
+ }
+
+ public TreeSPath(String asUniqueString) {
+ this.asUniqueString = checkAndFormatPath(asUniqueString);
+ }
+
+ public String getAsUniqueString() {
+ return asUniqueString;
+ }
+
+ /**
+ * Sets all the required data from a string. ATTENTION: the path is
+ * not checked for performance reason. This method should be used only by
+ * ORM/OXM frameworks. Use constructor to create immutable tree structure
+ * paths.
+ */
+ public void setAsUniqueString(String str) {
+ this.asUniqueString = str;
+ }
+
+ /** The separator actually used by this path. */
+ public Character getSeparator() {
+ return separator;
+ }
+
+ /** Gets the parent path. */
+ public TreeSPath getParent() {
+ int lastSep = getAsUniqueString().lastIndexOf(separator);
+ if (lastSep < 1) {
+ return null;
+ }
+ String parentUniqueString = getAsUniqueString().substring(0, lastSep);
+ return new TreeSPath(parentUniqueString);
+ }
+
+ /** Gets the name part of the path. */
+ public String getName() {
+ int lastSep = getAsUniqueString().lastIndexOf(separator);
+ return getAsUniqueString().substring(lastSep+1);
+ }
+
+ /** Create a path without parent. */
+ public static TreeSPath createRootPath(String name) {
+ if (name.indexOf(DEFAULT_SEPARATOR) >= 0) {
+ throw new SlcException("Name cannot contain " + DEFAULT_SEPARATOR);
+ }
+ return new TreeSPath('/' + name);
+ }
+
+ /** Create a child . */
+ public TreeSPath createChild(String name) {
+ if (name.indexOf(separator) > -1) {
+ throw new SlcException("Tree path name '" + name
+ + "' contains separator character " + separator);
+ }
+ return new TreeSPath(getAsUniqueString() + '/' + name);
+ }
+
+ /**
+ * Parses a string to a path.
+ *
+ * @deprecated use constructor instead
+ */
+ public static TreeSPath parseToCreatePath(String path) {
+ return parseToCreatePath(path, DEFAULT_SEPARATOR);
+ }
+
+ protected String checkAndFormatPath(String str) {
+ if (str.length() < 2) {
+ throw new SlcException("Path " + str + " is not short");
+ }
+ if (str.charAt(0) != separator) {
+ throw new SlcException("Path " + str + " have to start with "
+ + separator);
+ }
+
+ StringBuffer buf = new StringBuffer(str.length() + 5);
+ StringTokenizer st = new StringTokenizer(str, separator.toString());
+ while (st.hasMoreTokens()) {
+ buf.append(separator).append(st.nextToken());
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Parses a string to a path.
+ *
+ * @deprecated use constructor instead
+ */
+ public static TreeSPath parseToCreatePath(String path, Character separator) {
+ return new TreeSPath(path);
+ }
+
+ /** Lists the children from a registry. */
+ public List listChildren(StructureRegistry registry) {
+ return listChildrenPaths(registry, this);
+ }
+
+ /** Lists the children from a given path from a registry. */
+ public static List listChildrenPaths(
+ StructureRegistry registry, TreeSPath path) {
+ List paths = new Vector();
+ List allPaths = registry.listPaths();
+ for (TreeSPath pathT : allPaths) {
+ if (pathT.getParent() != null && pathT.getParent().equals(path)) {
+ paths.add(pathT);
+ }
+ }
+ return paths;
+ }
+
+ /** Gets the root tree path of this path. */
+ public TreeSPath getRoot() {
+ TreeSPath root = this;
+ while (root.getParent() != null) {
+ root = root.getParent();
+ }
+ return root;
+ }
+
+ /** Depth of this path. */
+ public Integer getDepth() {
+ return depthImpl(this);
+ }
+
+ protected int depthImpl(TreeSPath path) {
+ if (path.getParent() == null) {
+ return 1;
+ } else {
+ return depthImpl(path.getParent()) + 1;
+ }
+ }
+
+ public List getHierarchyAsList() {
+ List lst = new Vector();
+ addParentToList(lst, this);
+ lst.add(this);
+ return lst;
+ }
+
+ protected void addParentToList(List lst, TreeSPath current) {
+ TreeSPath parent = current.getParent();
+ if (parent != null) {
+ addParentToList(lst, parent);
+ lst.add(parent);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return getAsUniqueString();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof StructurePath) {
+ StructurePath path = (StructurePath) obj;
+ return getAsUniqueString().equals(path.getAsUniqueString());
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return getAsUniqueString().hashCode();
+ }
+
+ public int compareTo(StructurePath o) {
+ return getAsUniqueString().compareTo(o.getAsUniqueString());
+ }
+
+ public Long getTid() {
+ return tid;
+ }
+
+ void setTid(Long tid) {
+ this.tid = tid;
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/tree/TreeSRegistry.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/tree/TreeSRegistry.java
new file mode 100644
index 000000000..10125678c
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/tree/TreeSRegistry.java
@@ -0,0 +1,95 @@
+package org.argeo.slc.core.structure.tree;
+
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.Vector;
+
+import org.argeo.slc.core.UnsupportedException;
+import org.argeo.slc.core.structure.SimpleSElement;
+import org.argeo.slc.core.structure.StructureElement;
+import org.argeo.slc.core.structure.StructureRegistry;
+
+/** Tree based implementation of a structure registry. */
+public class TreeSRegistry implements StructureRegistry {
+ public final static String STATUS_ACTIVE = "STATUS_ACTIVE";
+
+ /** For ORM */
+ private Long tid;
+ private String status;
+ private Map elements = new TreeMap();
+
+ private String mode = StructureRegistry.ALL;
+
+ private List activePaths;
+
+ public T getElement(TreeSPath path) {
+ return (T)elements.get(path);
+ }
+
+ public List listElements() {
+ return new Vector(elements.values());
+ }
+
+ public List listPaths() {
+ return new Vector(elements.keySet());
+ }
+
+ public void register(TreeSPath path, StructureElement element) {
+ final SimpleSElement simpleSElement;
+ if (element instanceof SimpleSElement) {
+ simpleSElement = (SimpleSElement) element;
+ } else {
+ simpleSElement = new SimpleSElement(element.getLabel());
+ }
+
+ if (path == null)
+ throw new UnsupportedException("Path cannot be null.");
+
+ elements.put(path, simpleSElement);
+
+ }
+
+ public String getMode() {
+ return mode;
+ }
+
+ public void setMode(String mode) {
+ this.mode = mode;
+ }
+
+ public List getActivePaths() {
+ return activePaths;
+ }
+
+ public void setActivePaths(List activePaths) {
+ this.activePaths = activePaths;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ /** Gets the elements. */
+ public Map getElements() {
+ return elements;
+ }
+
+ /** Sets the elements (for ORM). */
+ public void setElements(Map elements) {
+ this.elements = elements;
+ }
+
+ Long getTid() {
+ return tid;
+ }
+
+ void setTid(Long tid) {
+ this.tid = tid;
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/tree/TreeSRelated.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/tree/TreeSRelated.java
new file mode 100644
index 000000000..f939fbc12
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/tree/TreeSRelated.java
@@ -0,0 +1,11 @@
+package org.argeo.slc.core.structure.tree;
+
+import org.argeo.slc.core.structure.StructureAware;
+import org.argeo.slc.core.structure.StructureElement;
+import org.argeo.slc.core.structure.StructureRegistry;
+
+public interface TreeSRelated extends StructureAware{
+ public TreeSPath getBasePath();
+ public StructureRegistry getRegistry();
+ public StructureElement getStructureElement(String key);
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/tree/TreeSRelatedHelper.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/tree/TreeSRelatedHelper.java
new file mode 100644
index 000000000..acc829c36
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/tree/TreeSRelatedHelper.java
@@ -0,0 +1,32 @@
+package org.argeo.slc.core.structure.tree;
+
+import org.argeo.slc.core.structure.SimpleSElement;
+import org.argeo.slc.core.structure.StructureElement;
+import org.argeo.slc.core.structure.StructureRegistry;
+
+/**
+ * Provides default implementations of some methods of TreeSRelated
.
+ */
+public abstract class TreeSRelatedHelper implements TreeSRelated {
+ private TreeSPath basePath;
+ private StructureRegistry registry;
+
+ public TreeSPath getBasePath() {
+ return basePath;
+ }
+
+ public StructureRegistry getRegistry() {
+ return registry;
+ }
+
+ public void notifyCurrentPath(StructureRegistry registry,
+ TreeSPath path) {
+ basePath = path;
+ this.registry = registry;
+ }
+
+ public StructureElement getStructureElement(String key) {
+ return new SimpleSElement(key);
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/tree/package.html b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/tree/package.html
new file mode 100644
index 000000000..a2a51e4d9
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/structure/tree/package.html
@@ -0,0 +1,6 @@
+
+
+
+Tree-based implementation of the SLC structure framework.
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/BasicTestData.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/BasicTestData.java
new file mode 100644
index 000000000..a8ee46cbf
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/BasicTestData.java
@@ -0,0 +1,24 @@
+package org.argeo.slc.core.test;
+
+
+public class BasicTestData implements TestData {
+ private Object expected;
+ private Object reached;
+
+ public Object getExpected() {
+ return expected;
+ }
+
+ public void setExpected(Object expected) {
+ this.expected = expected;
+ }
+
+ public Object getReached() {
+ return reached;
+ }
+
+ public void setReached(Object reached) {
+ this.reached = reached;
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/BasicTestDefinition.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/BasicTestDefinition.java
new file mode 100644
index 000000000..1178b41ec
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/BasicTestDefinition.java
@@ -0,0 +1,36 @@
+package org.argeo.slc.core.test;
+
+import org.argeo.slc.core.structure.tree.TreeSRelatedHelper;
+import org.argeo.slc.core.test.context.ContextAware;
+import org.argeo.slc.core.test.context.ContextUtils;
+
+/** Understands basic test data and context aware test data. */
+public class BasicTestDefinition extends TreeSRelatedHelper implements
+ TestDefinition {
+
+ public void execute(TestRun testRun) {
+ if (testRun. getTestData() instanceof BasicTestData) {
+ BasicTestData testData = testRun.getTestData();
+ TestResult result = testRun.getTestResult();
+
+ try {
+ if (testData.getExpected().equals(testData.getReached())) {
+ result.addResultPart(new SimpleResultPart(
+ TestStatus.PASSED, "Reached and expected equals"));
+ } else {
+ result.addResultPart(new SimpleResultPart(
+ TestStatus.FAILED, "Expected "
+ + testData.getExpected() + " but reched "
+ + testData.getReached()));
+ }
+ } catch (Exception e) {
+ result.addResultPart(new SimpleResultPart(TestStatus.ERROR,
+ "Could not compare", e));
+ }
+ } else if (testRun. getTestData() instanceof ContextAware) {
+ TestData testData = testRun.getTestData();
+ ContextUtils.compareReachedExpected((ContextAware) testData,
+ testRun.getTestResult(), this);
+ }
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/ExecutableTestRun.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/ExecutableTestRun.java
new file mode 100644
index 000000000..34216799f
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/ExecutableTestRun.java
@@ -0,0 +1,9 @@
+package org.argeo.slc.core.test;
+
+/** A test run that can be executed */
+public interface ExecutableTestRun extends TestRun {
+
+ /** Executes this test run. */
+ public void execute();
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/IncompatibleTestDataException.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/IncompatibleTestDataException.java
new file mode 100644
index 000000000..db4184d05
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/IncompatibleTestDataException.java
@@ -0,0 +1,18 @@
+package org.argeo.slc.core.test;
+
+import org.argeo.slc.core.SlcException;
+
+/**
+ * Exception to throw when a test definition cannot interpret the provided test
+ * data.
+ */
+public class IncompatibleTestDataException extends SlcException {
+ static final long serialVersionUID = 1l;
+
+ public IncompatibleTestDataException(TestData testData,
+ TestDefinition testDefinition) {
+ super("TestData " + testData.getClass()
+ + " is not compatible with TestDefinition "
+ + testDefinition.getClass());
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/NumericTRId.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/NumericTRId.java
new file mode 100644
index 000000000..0b1674ae9
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/NumericTRId.java
@@ -0,0 +1,71 @@
+package org.argeo.slc.core.test;
+
+import org.argeo.slc.core.deploy.DeployedSystemId;
+
+/**
+ * Basic implementation of test run id based on a long value and a reference to
+ * a deployed system id.
+ *
+ * @deprecated
+ */
+public class NumericTRId implements TestResultId {
+ /** For ORM */
+ private Long tid;
+
+ private Long value;
+ private DeployedSystemId deployedSystemId;
+
+ /** For ORM */
+ public NumericTRId() {
+
+ }
+
+ public NumericTRId(Long value) {
+ this.value = value;
+ }
+
+ /**
+ * Initializes the long value with the current time (based on
+ * java.lang.System.currentTimeMillis()
).
+ */
+ public void init() {
+ if (getValue() == null) {
+ setValue(System.currentTimeMillis());
+ }
+ }
+
+ public Long getValue() {
+ return value;
+ }
+
+ public void setValue(Long value) {
+ this.value = value;
+ }
+
+ public DeployedSystemId getDeployedSystemId() {
+ return deployedSystemId;
+ }
+
+ public void setDeployedSystemId(DeployedSystemId deployedSystemId) {
+ this.deployedSystemId = deployedSystemId;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return value.toString().equals(obj.toString());
+ }
+
+ @Override
+ public String toString() {
+ return value.toString();
+ }
+
+ Long getTid() {
+ return tid;
+ }
+
+ void setTid(Long tid) {
+ this.tid = tid;
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/SimpleResultPart.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/SimpleResultPart.java
new file mode 100644
index 000000000..e114e1f6d
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/SimpleResultPart.java
@@ -0,0 +1,128 @@
+package org.argeo.slc.core.test;
+
+/**
+ *
+ * Basic implementation of a result part, implementing the standard three status
+ * approach for test results.
+ *
+ *
+ * @see TestStatus
+ */
+public class SimpleResultPart implements TestResultPart, TestStatus,
+ TestRunAware {
+
+ /** @deprecated */
+ private Long tid;
+
+ private String testRunUuid;
+
+ /** The status. Default to ERROR since it should always be explicitely set. */
+ private Integer status = ERROR;
+ private String message;
+ private String exceptionMessage;
+
+ public SimpleResultPart() {
+ }
+
+ public SimpleResultPart(Integer status, String message) {
+ this(status, message, null);
+ }
+
+ public SimpleResultPart(Integer status, String message, Exception exception) {
+ this.status = status;
+ this.message = message;
+ setException(exception);
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public void setStatus(Integer status) {
+ this.status = status;
+ }
+
+ public Integer getStatus() {
+ return status;
+ }
+
+ public String getExceptionMessage() {
+ return exceptionMessage;
+ }
+
+ public void setException(Exception exception) {
+ if (exception == null)
+ return;
+
+ StringBuffer buf = new StringBuffer("");
+ buf.append(exception.toString());
+ buf.append('\n');
+ for (StackTraceElement elem : exception.getStackTrace()) {
+ buf.append('\t').append(elem.toString()).append('\n');
+ }
+
+ if (exception.getCause() != null)
+ addRootCause(buf, exception.getCause());
+
+ this.exceptionMessage = buf.toString();
+ }
+
+ protected void addRootCause(StringBuffer buf, Throwable cause) {
+ if (cause == null)
+ return;
+
+ buf.append("Caused by: " + cause.getMessage());
+ for (StackTraceElement elem : cause.getStackTrace()) {
+ buf.append('\t').append(elem.toString()).append('\n');
+ }
+
+ if (cause.getCause() != null) {
+ addRootCause(buf, cause.getCause());
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer buf = new StringBuffer("");
+ buf.append(SlcTestUtils.statusToString(status));
+ if (status == PASSED || status == FAILED) {
+ buf.append(' ');
+ } else if (status == ERROR) {
+ buf.append(" ");
+ }
+ buf.append(message);
+ return buf.toString();
+ }
+
+ /** @deprecated */
+ Long getTid() {
+ return tid;
+ }
+
+ /** @deprecated */
+ void setTid(Long tid) {
+ this.tid = tid;
+ }
+
+ public String getTestRunUuid() {
+ return testRunUuid;
+ }
+
+ /** For ORM */
+ public void setTestRunUuid(String testRunUuid) {
+ this.testRunUuid = testRunUuid;
+ }
+
+ public void notifyTestRun(TestRun testRun) {
+ testRunUuid = testRun.getUuid();
+ }
+
+ public void setExceptionMessage(String exceptionMessage) {
+ this.exceptionMessage = exceptionMessage;
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/SimpleTestResult.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/SimpleTestResult.java
new file mode 100644
index 000000000..c1d783a77
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/SimpleTestResult.java
@@ -0,0 +1,74 @@
+package org.argeo.slc.core.test;
+
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+import java.util.Vector;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.argeo.slc.core.SlcException;
+
+/**
+ * Basic implementation of a test result containing only a list of result parts.
+ */
+public class SimpleTestResult implements TestResult {
+ private static Log log = LogFactory.getLog(SimpleTestResult.class);
+
+ private String uuid;
+ private String currentTestRunUuid;
+
+ private Boolean throwError = true;
+
+ private Date closeDate;
+ private List parts = new Vector();
+
+ public void addResultPart(TestResultPart part) {
+ if (throwError && part.getStatus() == ERROR) {
+ throw new SlcException(
+ "There was an error in the underlying test: "
+ + part.getExceptionMessage());
+ }
+ parts.add(part);
+ if (log.isDebugEnabled())
+ log.debug(part);
+ }
+
+ public void close() {
+ parts.clear();
+ closeDate = new Date();
+ }
+
+ public List getParts() {
+ return parts;
+ }
+
+ public Date getCloseDate() {
+ return closeDate;
+ }
+
+ public void setThrowError(Boolean throwError) {
+ this.throwError = throwError;
+ }
+
+ public void notifyTestRun(TestRun testRun) {
+ currentTestRunUuid = testRun.getUuid();
+ }
+
+ public String getUuid() {
+ if (uuid == null) {
+ uuid = UUID.randomUUID().toString();
+ }
+ return uuid;
+ }
+
+ public void setUuid(String uuid) {
+ this.uuid = uuid;
+ }
+
+ public String getCurrentTestRunUuid() {
+ return currentTestRunUuid;
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/SimpleTestRun.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/SimpleTestRun.java
new file mode 100644
index 000000000..e2ab043cf
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/SimpleTestRun.java
@@ -0,0 +1,96 @@
+package org.argeo.slc.core.test;
+
+import java.util.UUID;
+
+import org.argeo.slc.core.deploy.DeployedSystem;
+import org.argeo.slc.core.process.SlcExecution;
+import org.argeo.slc.core.process.SlcExecutionStep;
+
+/**
+ * A basic bean implementation of a WritableTestRun
, holding
+ * references to the various parts of a test run.
+ */
+public class SimpleTestRun implements WritableTestRun, ExecutableTestRun {
+ private String uuid;
+
+ private String slcExecutionUuid;
+ private String slcExecutionStepUuid;
+
+ private DeployedSystem deployedSystem;
+ private TestData testData;
+ private TestDefinition testDefinition;
+ private TestResult testResult;
+
+ /** Executes the underlying test definition. */
+ public void execute() {
+ uuid = UUID.randomUUID().toString();
+ if (testResult != null)
+ testResult.notifyTestRun(this);
+ testDefinition.execute(this);
+ }
+
+ public T getDeployedSystem() {
+ return (T) deployedSystem;
+ }
+
+ public void setDeployedSystem(DeployedSystem deployedSystem) {
+ this.deployedSystem = deployedSystem;
+ }
+
+ public T getTestData() {
+ return (T) testData;
+ }
+
+ public void setTestData(TestData testData) {
+ this.testData = testData;
+ }
+
+ public T getTestDefinition() {
+ return (T) testDefinition;
+ }
+
+ public void setTestDefinition(TestDefinition testDefinition) {
+ this.testDefinition = testDefinition;
+ }
+
+ public T getTestResult() {
+ return (T) testResult;
+ }
+
+ public void setTestResult(TestResult testResult) {
+ this.testResult = testResult;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public void setUuid(String uuid) {
+ this.uuid = uuid;
+ }
+
+ public String getSlcExecutionUuid() {
+ return slcExecutionUuid;
+ }
+
+ public void setSlcExecutionUuid(String slcExecutionUuid) {
+ this.slcExecutionUuid = slcExecutionUuid;
+ }
+
+ public String getSlcExecutionStepUuid() {
+ return slcExecutionStepUuid;
+ }
+
+ public void setSlcExecutionStepUuid(String slcExecutionStepUuid) {
+ this.slcExecutionStepUuid = slcExecutionStepUuid;
+ }
+
+ public void notifySlcExecution(SlcExecution slcExecution) {
+ slcExecutionUuid = slcExecution.getUuid();
+ SlcExecutionStep step = slcExecution.currentStep();
+ if (step != null) {
+ slcExecutionStepUuid = step.getUuid();
+ }
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/SlcTestUtils.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/SlcTestUtils.java
new file mode 100644
index 000000000..c7d7840cd
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/SlcTestUtils.java
@@ -0,0 +1,40 @@
+package org.argeo.slc.core.test;
+
+import org.argeo.slc.core.SlcException;
+
+public abstract class SlcTestUtils {
+ public static String statusToString(Integer status){
+ if(status.equals(TestStatus.PASSED)){
+ return TestStatus.STATUSSTR_PASSED;
+ }
+ else if(status.equals(TestStatus.FAILED)){
+ return TestStatus.STATUSSTR_FAILED;
+ }
+ else if(status.equals(TestStatus.ERROR)){
+ return TestStatus.STATUSSTR_ERROR;
+ }
+ else{
+ throw new SlcException("Unrecognized status "+status);
+ }
+ }
+
+ public static Integer stringToStatus(String statusStr){
+ if(statusStr.equals(TestStatus.STATUSSTR_PASSED)){
+ return TestStatus.PASSED;
+ }
+ else if(statusStr.equals(TestStatus.STATUSSTR_FAILED)){
+ return TestStatus.FAILED;
+ }
+ else if(statusStr.equals(TestStatus.STATUSSTR_ERROR)){
+ return TestStatus.ERROR;
+ }
+ else{
+ throw new SlcException("Unrecognized status string "+statusStr);
+ }
+ }
+
+ private SlcTestUtils(){
+
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestData.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestData.java
new file mode 100644
index 000000000..4105e0925
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestData.java
@@ -0,0 +1,9 @@
+package org.argeo.slc.core.test;
+
+/**
+ * Any data required by a test in order to run: configuration, expected,
+ * reached, etc.
+ */
+public interface TestData {
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestDataProvider.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestDataProvider.java
new file mode 100644
index 000000000..e0e02c3a6
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestDataProvider.java
@@ -0,0 +1,5 @@
+package org.argeo.slc.core.test;
+
+public interface TestDataProvider {
+ public T getTestData(Class clss, String key);
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestDataUtils.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestDataUtils.java
new file mode 100644
index 000000000..66cae87c3
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestDataUtils.java
@@ -0,0 +1,45 @@
+package org.argeo.slc.core.test;
+
+import org.argeo.slc.core.UnsupportedException;
+
+/** Utilities for dealing with test datas. */
+public class TestDataUtils {
+ /** Extracts the test data from the given provider. */
+ public static T getFromProvider(Object obj,
+ Class clss, String key) {
+ if (obj instanceof TestDataProvider) {
+ TestDataProvider testDataProvider = (TestDataProvider) obj;
+ return testDataProvider.getTestData(clss, key);
+ } else {
+ throw new UnsupportedException("test data provider", obj);
+ }
+ }
+
+ /**
+ * Extracts the test data from the given provider using null
+ * as key.
+ */
+ public static T getFromProvider(Object obj,
+ Class clss) {
+ return getFromProvider(obj, clss, null);
+ }
+
+ /**
+ * Returns it self after making the proper checks. Used for test data being
+ * their own data providers.
+ */
+ public static T getItSelf(Class clss,
+ TestData testDataObject) {
+ if (clss.isAssignableFrom(testDataObject.getClass())) {
+ return (T) testDataObject;
+ } else {
+ throw new UnsupportedException("test data", testDataObject);
+ }
+
+ }
+
+ /** Makes sure this is an utility class. */
+ private TestDataUtils() {
+
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestDefinition.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestDefinition.java
new file mode 100644
index 000000000..7c75d6a73
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestDefinition.java
@@ -0,0 +1,10 @@
+package org.argeo.slc.core.test;
+
+/**
+ * The programmatic definition of a test, which will be associated with
+ * transient objects within a test run.
+ */
+public interface TestDefinition extends TestStatus {
+ /** Performs the test. */
+ public void execute(TestRun testRun);
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestReport.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestReport.java
new file mode 100644
index 000000000..8256e8644
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestReport.java
@@ -0,0 +1,10 @@
+package org.argeo.slc.core.test;
+
+/**
+ * A report that can be generated based on a given test result. This
+ * interface may change in the future.
+ */
+public interface TestReport {
+ /** Performs the actions necessary to generate a report. */
+ public void generateTestReport(TestResult result);
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestResult.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestResult.java
new file mode 100644
index 000000000..5aa1c6193
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestResult.java
@@ -0,0 +1,23 @@
+package org.argeo.slc.core.test;
+
+import java.util.Date;
+
+/** The result of a test */
+public interface TestResult extends TestStatus, TestRunAware {
+ public String getUuid();
+
+ /** Adds a part of the result. */
+ public void addResultPart(TestResultPart part);
+
+ /**
+ * Marks that the collection of test results is completed and free the
+ * related resources (also closing listeners).
+ */
+ public void close();
+
+ /**
+ * The date when this test result was closed. Can be null, which means the
+ * result is not closed.
+ */
+ public Date getCloseDate();
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestResultId.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestResultId.java
new file mode 100644
index 000000000..46af52799
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestResultId.java
@@ -0,0 +1,14 @@
+package org.argeo.slc.core.test;
+
+import org.argeo.slc.core.deploy.DeployedSystemId;
+
+/**
+ * The unique id referencing a test result.
+ *
+ * @deprecated
+ */
+public interface TestResultId {
+ /** Gets the id of the related deployed system. */
+ public DeployedSystemId getDeployedSystemId();
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestResultListener.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestResultListener.java
new file mode 100644
index 000000000..c42d783d0
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestResultListener.java
@@ -0,0 +1,11 @@
+package org.argeo.slc.core.test;
+
+/** Listener to the operations on a test result. */
+public interface TestResultListener {
+ /** Notified when a part was added to a test result. */
+ public void resultPartAdded(T testResult,
+ TestResultPart testResultPart);
+
+ /** Stops listening and release the related resources. */
+ public void close(T testResult);
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestResultPart.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestResultPart.java
new file mode 100644
index 000000000..fc5749b86
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestResultPart.java
@@ -0,0 +1,18 @@
+package org.argeo.slc.core.test;
+
+
+/**
+ * Part of a test result.
+ *
+ * @see TestResult
+ */
+public interface TestResultPart {
+ /** The status, as defined in {@link TestStatus}. */
+ public Integer getStatus();
+
+ /** The related message. */
+ public String getMessage();
+
+ /** The underlying Exception
. Can be null. */
+ public String getExceptionMessage();
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestRun.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestRun.java
new file mode 100644
index 000000000..5a4ac50b6
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestRun.java
@@ -0,0 +1,22 @@
+package org.argeo.slc.core.test;
+
+import org.argeo.slc.core.deploy.DeployedSystem;
+import org.argeo.slc.core.process.SlcExecutionAware;
+
+/** The actual run of a test */
+public interface TestRun extends SlcExecutionAware{
+ /** Gets UUID */
+ public String getUuid();
+
+ /** Gets the related test definition. */
+ public T getTestDefinition();
+
+ /** Gets the related test data */
+ public T getTestData();
+
+ /** Gets the related deployed system. */
+ public T getDeployedSystem();
+
+ /** Gets the related result where to record results. */
+ public T getTestResult();
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestRunAware.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestRunAware.java
new file mode 100644
index 000000000..6cca1440e
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestRunAware.java
@@ -0,0 +1,7 @@
+package org.argeo.slc.core.test;
+
+public interface TestRunAware {
+ /** Notifies the current test run. */
+ public void notifyTestRun(TestRun testRun);
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestRunDescriptor.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestRunDescriptor.java
new file mode 100644
index 000000000..d48ea2db9
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestRunDescriptor.java
@@ -0,0 +1,82 @@
+package org.argeo.slc.core.test;
+
+import org.argeo.slc.core.deploy.DeployedSystem;
+import org.argeo.slc.core.process.SlcExecution;
+
+public class TestRunDescriptor {
+ private String testRunUuid;
+ private String slcExecutionUuid;
+ private String slcExecutionStepUuid;
+ private String testResultUuid;
+ private String deployedSytemId;
+
+ public TestRunDescriptor() {
+
+ }
+
+ public TestRunDescriptor(TestRun testRun) {
+ testRunUuid = testRun.getUuid();
+
+ if (testRun.getTestResult() != null)
+ testResultUuid = testRun. getTestResult().getUuid();
+
+ if (testRun.getDeployedSystem() != null)
+ deployedSytemId = testRun. getDeployedSystem()
+ .getDeployedSystemId();
+
+ if (testRun instanceof SimpleTestRun) {
+ slcExecutionUuid = ((SimpleTestRun) testRun).getSlcExecutionUuid();
+ slcExecutionStepUuid = ((SimpleTestRun) testRun)
+ .getSlcExecutionStepUuid();
+ }
+ }
+
+ public String getTestRunUuid() {
+ return testRunUuid;
+ }
+
+ public void setTestRunUuid(String testRunUuid) {
+ this.testRunUuid = testRunUuid;
+ }
+
+ public String getSlcExecutionUuid() {
+ return slcExecutionUuid;
+ }
+
+ public void setSlcExecutionUuid(String slcExecutionUuid) {
+ this.slcExecutionUuid = slcExecutionUuid;
+ }
+
+ public String getSlcExecutionStepUuid() {
+ return slcExecutionStepUuid;
+ }
+
+ public void setSlcExecutionStepUuid(String slcExecutionStepUuid) {
+ this.slcExecutionStepUuid = slcExecutionStepUuid;
+ }
+
+ public String getTestResultUuid() {
+ return testResultUuid;
+ }
+
+ public void setTestResultUuid(String testResultUuid) {
+ this.testResultUuid = testResultUuid;
+ }
+
+ public String getDeployedSytemId() {
+ return deployedSytemId;
+ }
+
+ public void setDeployedSytemId(String deploymentId) {
+ this.deployedSytemId = deploymentId;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof TestRunDescriptor) {
+ return getTestRunUuid().equals(
+ ((TestRunDescriptor) obj).getTestRunUuid());
+ }
+ return false;
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestStatus.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestStatus.java
new file mode 100644
index 000000000..d6954be8f
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/TestStatus.java
@@ -0,0 +1,29 @@
+package org.argeo.slc.core.test;
+
+/**
+ * Simple statuses.
+ *
+ *
+ * - {@link #PASSED}: the test succeeded
+ * - {@link #FAILED}: the test could run, but did not reach the expected
+ * result
+ * - {@link #ERROR}: an error during the test run prevented to get a
+ * significant information on the tested system.
+ *
+ *
+ */
+public interface TestStatus {
+ /** The flag for a passed test: 0 */
+ public final static Integer PASSED = 0;
+ /** The flag for a failed test: 1 */
+ public final static Integer FAILED = 1;
+ /**
+ * The flag for a test which could not properly run because of an error
+ * (there is no feedback on the behavior of the tested component): 2
+ */
+ public final static Integer ERROR = 2;
+ public final static String STATUSSTR_PASSED = "PASSED";
+ public final static String STATUSSTR_FAILED = "FAILED";
+ public final static String STATUSSTR_ERROR = "ERROR";
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/WritableTestRun.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/WritableTestRun.java
new file mode 100644
index 000000000..8cfe2b72c
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/WritableTestRun.java
@@ -0,0 +1,14 @@
+package org.argeo.slc.core.test;
+
+import org.argeo.slc.core.deploy.DeployedSystem;
+
+/** Test run whose various components can be externally set. */
+public interface WritableTestRun extends ExecutableTestRun {
+ public void setDeployedSystem(DeployedSystem deployedSystem);
+
+ public void setTestData(TestData testData);
+
+ public void setTestDefinition(TestDefinition testDefinition);
+
+ public void setTestResult(TestResult testResult);
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/context/ContextAware.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/context/ContextAware.java
new file mode 100644
index 000000000..5e411831e
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/context/ContextAware.java
@@ -0,0 +1,18 @@
+package org.argeo.slc.core.test.context;
+
+import java.util.Map;
+
+public interface ContextAware {
+ public final static String DEFAULT_SKIP_FLAG = "!";
+ public final static String DEFAULT_ANY_FLAG = "*";
+
+ public Map getValues();
+
+ public void setValues(Map values);
+
+ public Map getExpectedValues();
+
+ public String getContextSkipFlag();
+
+ public String getContextAnyFlag();
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/context/ContextUtils.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/context/ContextUtils.java
new file mode 100644
index 000000000..3826a8710
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/context/ContextUtils.java
@@ -0,0 +1,165 @@
+package org.argeo.slc.core.test.context;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.argeo.slc.core.structure.StructureAware;
+import org.argeo.slc.core.structure.StructureElement;
+import org.argeo.slc.core.structure.StructureRegistry;
+import org.argeo.slc.core.structure.tree.TreeSPath;
+import org.argeo.slc.core.structure.tree.TreeSRelated;
+import org.argeo.slc.core.test.SimpleResultPart;
+import org.argeo.slc.core.test.TestResult;
+import org.argeo.slc.core.test.TestStatus;
+
+public class ContextUtils {
+ private final static Log log = LogFactory.getLog(ContextUtils.class);
+
+ public static void compareReachedExpected(ContextAware contextAware,
+ TestResult testResult, TreeSRelated treeSRelated) {
+ for (String key : contextAware.getExpectedValues().keySet()) {
+
+ // Compare expected values with reached ones
+ Object expectedValue = contextAware.getExpectedValues().get(key);
+
+ if (expectedValue.toString().equals(
+ contextAware.getContextSkipFlag())) {
+ if (log.isDebugEnabled())
+ log.debug("Skipped check for key '" + key + "'");
+ continue;
+ }
+
+ // Register in structure
+ registerInStructure(testResult, treeSRelated, key);
+
+ if (contextAware.getValues().containsKey(key)) {
+ Object reachedValue = contextAware.getValues().get(key);
+
+ if (expectedValue.equals(contextAware.getContextAnyFlag())) {
+ testResult.addResultPart(new SimpleResultPart(
+ TestStatus.PASSED, "Expected any value for key '"
+ + key + "'"));
+ } else if (expectedValue.equals(reachedValue)) {
+ testResult.addResultPart(new SimpleResultPart(
+ TestStatus.PASSED, "Values matched for key '" + key
+ + "'"));
+ } else {
+ testResult.addResultPart(new SimpleResultPart(
+ TestStatus.FAILED, "Mismatch for key '" + key
+ + "': expected '" + expectedValue
+ + "' but reached '" + reachedValue + "'"));
+ }
+ } else {
+ testResult.addResultPart(new SimpleResultPart(
+ TestStatus.FAILED, "No value reached for key '" + key
+ + "'"));
+ }
+ resetStructure(testResult, treeSRelated);
+ }
+ }
+
+ private static void registerInStructure(TestResult testResult,
+ TreeSRelated treeSRelated, String key) {
+ if (treeSRelated != null) {
+ if (treeSRelated.getBasePath() != null) {
+ TreeSPath path = treeSRelated.getBasePath().createChild(key);
+ StructureRegistry registry = treeSRelated
+ .getRegistry();
+ final StructureElement element = treeSRelated
+ .getStructureElement(key);
+ registry.register(path, element);
+ if (testResult instanceof StructureAware)
+ ((StructureAware) testResult).notifyCurrentPath(
+ registry, path);
+
+ if (log.isDebugEnabled())
+ log.debug("Checking key " + key + " for path " + path);
+ }
+ }
+ }
+
+ private static void resetStructure(TestResult testResult,
+ TreeSRelated treeSRelated) {
+ if (treeSRelated != null) {
+ if (treeSRelated.getBasePath() != null) {
+ if (testResult instanceof StructureAware) {
+ ((StructureAware) testResult).notifyCurrentPath(
+ treeSRelated.getRegistry(), treeSRelated
+ .getBasePath());
+ }
+ }
+ }
+ }
+
+ /**
+ * Makes sure that all children and sub-children of parent share the same
+ * maps for values and expected values.
+ */
+ public static void synchronize(ParentContextAware parent) {
+ Map expectedValuesCommon = new TreeMap(
+ parent.getExpectedValues());
+ synchronize(parent, expectedValuesCommon);
+ if (log.isDebugEnabled())
+ log.debug("Synchonized context " + parent);
+
+ }
+
+ private static void synchronize(ParentContextAware parent,
+ Map expectedValuesCommon) {
+ for (ContextAware child : parent.getChildContexts()) {
+ // Values
+ putNotContained(parent.getValues(), child.getValues());
+ child.setValues(parent.getValues());
+
+ // Expected Values
+ // Expected values reference is not overridden: each child has its
+ // own expected values map.
+ overrideContained(expectedValuesCommon, child.getExpectedValues());
+
+ // Creates a new Map in order not to disturb other context using the
+ // same keys
+ Map expectedValuesCommonChild = new TreeMap(
+ expectedValuesCommon);
+ putNotContained(expectedValuesCommonChild, child
+ .getExpectedValues());
+
+ if (child instanceof ParentContextAware) {
+ // Recursive sync
+ synchronize((ParentContextAware) child,
+ expectedValuesCommonChild);
+ }
+ }
+
+ }
+
+ /**
+ * Put into common map the values from child map which are not already
+ * defined in common map.
+ */
+ public static void putNotContained(Map commonMap,
+ Map childMap) {
+ for (String key : childMap.keySet()) {
+ if (!commonMap.containsKey(key)) {
+ commonMap.put(key, childMap.get(key));
+ }
+ }
+ }
+
+ /** Overrides child map values with the values already set in common map */
+ public static void overrideContained(Map commonMap,
+ Map childMap) {
+ for (String key : childMap.keySet()) {
+ if (commonMap.containsKey(key)) {
+ childMap.put(key, commonMap.get(key));
+ }
+ }
+ }
+
+ /** Makes sure this cannot be instantiated. */
+ private ContextUtils() {
+
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/context/DefaultContextTestData.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/context/DefaultContextTestData.java
new file mode 100644
index 000000000..a39a91539
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/context/DefaultContextTestData.java
@@ -0,0 +1,14 @@
+package org.argeo.slc.core.test.context;
+
+import org.argeo.slc.core.test.TestData;
+import org.argeo.slc.core.test.TestDataProvider;
+import org.argeo.slc.core.test.TestDataUtils;
+
+public class DefaultContextTestData extends SimpleContextAware implements
+ TestData, TestDataProvider {
+
+ public T getTestData(Class clss, String key) {
+ return TestDataUtils.getItSelf(clss, this);
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/context/ParentContextAware.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/context/ParentContextAware.java
new file mode 100644
index 000000000..a8fc8b2be
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/context/ParentContextAware.java
@@ -0,0 +1,8 @@
+package org.argeo.slc.core.test.context;
+
+import java.util.Collection;
+
+public interface ParentContextAware extends ContextAware {
+ public Collection getChildContexts();
+ public void addChildContext(ContextAware contextAware);
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/context/SimpleContextAware.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/context/SimpleContextAware.java
new file mode 100644
index 000000000..c4fb5ab40
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/context/SimpleContextAware.java
@@ -0,0 +1,69 @@
+package org.argeo.slc.core.test.context;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.springframework.beans.factory.InitializingBean;
+
+import org.argeo.slc.core.SlcException;
+
+public class SimpleContextAware implements ContextAware, InitializingBean {
+ private ParentContextAware parentContext;
+
+ private Map values = new TreeMap();
+ private Map expectedValues = new TreeMap();
+
+ private String contextSkipFlag = DEFAULT_SKIP_FLAG;
+ private String contextAnyFlag = DEFAULT_ANY_FLAG;
+
+ public Map getValues() {
+ return values;
+ }
+
+ public void setValues(Map values) {
+ this.values = values;
+ }
+
+ public Map getExpectedValues() {
+ return expectedValues;
+ }
+
+ public void setExpectedValues(Map expectedValues) {
+ this.expectedValues = expectedValues;
+ }
+
+ /** Used to add this context as a child by setting a property. */
+ public void setParentContext(ParentContextAware parentContextAware) {
+ if (parentContext != null)
+ throw new SlcException("Parent context already set");
+ this.parentContext = parentContextAware;
+ this.parentContext.addChildContext(this);
+ }
+
+ protected ParentContextAware getParentContext() {
+ return parentContext;
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ if (parentContext != null) {
+ ContextUtils.synchronize(parentContext);
+ }
+ }
+
+ public String getContextSkipFlag() {
+ return contextSkipFlag;
+ }
+
+ public void setContextSkipFlag(String contextSkipFlag) {
+ this.contextSkipFlag = contextSkipFlag;
+ }
+
+ public String getContextAnyFlag() {
+ return contextAnyFlag;
+ }
+
+ public void setContextAnyFlag(String contextAnyFlag) {
+ this.contextAnyFlag = contextAnyFlag;
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/context/SimpleParentContextAware.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/context/SimpleParentContextAware.java
new file mode 100644
index 000000000..2dfa12346
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/context/SimpleParentContextAware.java
@@ -0,0 +1,33 @@
+package org.argeo.slc.core.test.context;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Vector;
+
+import org.springframework.beans.factory.InitializingBean;
+
+public class SimpleParentContextAware extends SimpleContextAware implements
+ ParentContextAware, InitializingBean {
+ private List children = new Vector();
+
+ public Collection getChildContexts() {
+ return children;
+ }
+
+ public void addChildContext(ContextAware contextAware) {
+ children.add(contextAware);
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ if (getParentContext() != null) {
+ // If has a parent, sync it.
+ super.afterPropertiesSet();
+ } else {
+ if(children.size()>0){
+ // No need to synchronize if no children
+ ContextUtils.synchronize(this);
+ }
+ }
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/context/package.html b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/context/package.html
new file mode 100644
index 000000000..cd08d63f3
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/context/package.html
@@ -0,0 +1,6 @@
+
+
+
+Context variables to be passed between parts of tests.
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/package.html b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/package.html
new file mode 100644
index 000000000..c70d2d151
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/package.html
@@ -0,0 +1,6 @@
+
+
+
+SLC Test: test of software systems.
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/CompositeTreeTestDefinition.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/CompositeTreeTestDefinition.java
new file mode 100644
index 000000000..f26c08580
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/CompositeTreeTestDefinition.java
@@ -0,0 +1,90 @@
+package org.argeo.slc.core.test.tree;
+
+import java.util.List;
+import java.util.Vector;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.argeo.slc.core.structure.SimpleSElement;
+import org.argeo.slc.core.structure.StructureAware;
+import org.argeo.slc.core.structure.StructureElement;
+import org.argeo.slc.core.structure.StructureElementProvider;
+import org.argeo.slc.core.structure.StructurePath;
+import org.argeo.slc.core.structure.StructureRegistry;
+import org.argeo.slc.core.structure.tree.TreeSPath;
+import org.argeo.slc.core.test.TestDefinition;
+import org.argeo.slc.core.test.TestResult;
+import org.argeo.slc.core.test.TestRun;
+
+/**
+ * Collection of test definitions propagating tree structure information to its
+ * children.
+ */
+public class CompositeTreeTestDefinition implements TestDefinition,
+ StructureAware {
+ private Log log = LogFactory.getLog(CompositeTreeTestDefinition.class);
+
+ private List tasks = null;
+ private List taskPaths = null;
+ private TreeSPath path;
+ private StructureRegistry registry;
+
+ public void execute(TestRun testRun) {
+ log.info("Execute sequence of test definitions...");
+
+ int i = 0;
+ for (TestDefinition task : tasks) {
+ TestResult result = testRun.getTestResult();
+ if (result instanceof StructureAware) {
+ ((StructureAware) result).notifyCurrentPath(registry, taskPaths
+ .get(i));
+ }
+
+ task.execute(testRun);
+
+ // Reset current path in case it has been changed
+ if (result instanceof StructureAware) {
+ ((StructureAware) result).notifyCurrentPath(registry, path);
+ }
+ i++;
+ }
+ }
+
+ /** Sets the list of children test definitions */
+ public void setTasks(List tasks) {
+ this.tasks = tasks;
+ if (tasks != null) {
+ taskPaths = new Vector();
+ }
+ }
+
+ public void notifyCurrentPath(StructureRegistry registry,
+ TreeSPath path) {
+ this.path = path;
+ this.registry = registry;
+
+ // clear task paths
+ taskPaths.clear();
+
+ Integer count = 0;
+ for (TestDefinition task : tasks) {
+ final StructureElement element;
+ if (task instanceof StructureElementProvider) {
+ element = ((StructureElementProvider) task)
+ .createStructureElement();
+ } else {
+ element = new SimpleSElement("[no desc]");
+ }
+ TreeSPath taskPath = this.path.createChild(count.toString());
+ registry.register(taskPath, element);
+ taskPaths.add(taskPath);
+ if (task instanceof StructureAware) {
+ ((StructureAware) task).notifyCurrentPath(registry,
+ taskPath);
+ }
+ count++;
+ }
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/PartSubList.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/PartSubList.java
new file mode 100644
index 000000000..128da6abb
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/PartSubList.java
@@ -0,0 +1,50 @@
+package org.argeo.slc.core.test.tree;
+
+import java.util.List;
+import java.util.Vector;
+
+import org.argeo.slc.core.test.TestResultPart;
+import org.argeo.slc.core.test.TestStatus;
+
+/**
+ * List of TestResultPart
. It can be used to build complex
+ * TestResult
affording the possibility to a
+ * TestDefinition
to add a list of result part under the same
+ * StructurePath
.
+ *
+ * @see TreeTestResult
+ */
+public class PartSubList {
+
+ /** For ORM */
+ private Long tid;
+
+ private List parts = new Vector();
+
+ /** Gets the result parts. */
+ public List getParts() {
+ return parts;
+ }
+
+ /** Sets the result parts. */
+ public void setParts(List parts) {
+ this.parts = parts;
+ }
+
+ Long getTid() {
+ return tid;
+ }
+
+ void setTid(Long tid) {
+ this.tid = tid;
+ }
+
+ public Boolean getIsPassed() {
+ for (TestResultPart part : parts) {
+ if (part.getStatus() != TestStatus.PASSED) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/TreeTestResult.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/TreeTestResult.java
new file mode 100644
index 000000000..328d5981a
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/TreeTestResult.java
@@ -0,0 +1,183 @@
+package org.argeo.slc.core.test.tree;
+
+import java.util.Date;
+import java.util.List;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.Vector;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.argeo.slc.core.SlcException;
+import org.argeo.slc.core.structure.StructureAware;
+import org.argeo.slc.core.structure.StructureElement;
+import org.argeo.slc.core.structure.StructureRegistry;
+import org.argeo.slc.core.structure.tree.TreeSPath;
+import org.argeo.slc.core.test.TestResult;
+import org.argeo.slc.core.test.TestResultListener;
+import org.argeo.slc.core.test.TestResultPart;
+import org.argeo.slc.core.test.TestRun;
+import org.argeo.slc.core.test.TestRunAware;
+
+/**
+ * Complex implementation of a test result compatible with a tree based
+ * structure.
+ */
+public class TreeTestResult implements TestResult, StructureAware,Comparable {
+ private Log log = LogFactory.getLog(TreeTestResult.class);
+
+ private List> listeners = new Vector>();
+
+ private TreeSPath currentPath;
+ private TestRun currentTestRun;
+
+ private Date closeDate;
+
+ private boolean isClosed = false;
+
+ private String uuid;
+
+ private SortedMap resultParts = new TreeMap();
+ private SortedMap elements = new TreeMap();
+
+ /** Sets the list of listeners. */
+ public void setListeners(List> listeners) {
+ this.listeners = listeners;
+ }
+
+ public void addResultPart(TestResultPart part) {
+ if (currentPath == null) {
+ throw new SlcException("No current path set.");
+ }
+ PartSubList subList = resultParts.get(currentPath);
+ if (subList == null) {
+ subList = new PartSubList();
+ resultParts.put(currentPath, subList);
+ }
+ if (part instanceof TestRunAware && currentTestRun != null) {
+ ((TestRunAware) part).notifyTestRun(currentTestRun);
+ }
+ subList.getParts().add(part);
+
+ // notify listeners
+ synchronized (listeners) {
+ for (TestResultListener listener : listeners) {
+ listener.resultPartAdded(this, part);
+ }
+ }
+ }
+
+ public void notifyCurrentPath(StructureRegistry registry,
+ TreeSPath path) {
+ if (registry != null) {
+ for (TreeSPath p : path.getHierarchyAsList()) {
+ if (!elements.containsKey(p)) {
+ StructureElement elem = registry.getElement(p);
+ if (elem != null) {
+ elements.put(p, elem);
+ }
+ } else {
+ if (log.isTraceEnabled())
+ log.trace("An element is already registered for path "
+ + p + " and was not updated");
+ }
+
+ }
+ }
+
+ currentPath = (TreeSPath) path;
+ }
+
+ /** Gets the current path. */
+ public TreeSPath getCurrentPath() {
+ return currentPath;
+ }
+
+ /** Gets all the results structured as a map of PartSubLists. */
+ public SortedMap getResultParts() {
+ return resultParts;
+ }
+
+ /** Used by ORM systems. */
+ void setResultParts(SortedMap resultParts) {
+ this.resultParts = resultParts;
+ }
+
+ public void close() {
+ if (isClosed) {
+ throw new SlcException("Test Result #" + getUuid()
+ + " alredy closed.");
+ }
+ closeDate = new Date();
+
+ synchronized (listeners) {
+ for (TestResultListener listener : listeners) {
+ listener.close(this);
+ }
+ listeners.clear();
+ }
+ isClosed = true;
+
+ log.info("Test Result #" + getUuid() + " closed.");
+ }
+
+ public Date getCloseDate() {
+ return closeDate;
+ }
+
+ /** Sets the close date (for ORM) */
+ public void setCloseDate(Date closeDate) {
+ this.closeDate = closeDate;
+ }
+
+ public void notifyTestRun(TestRun testRun) {
+ currentTestRun = testRun;
+ }
+
+ public SortedMap getElements() {
+ return elements;
+ }
+
+ public void setElements(SortedMap pathNames) {
+ this.elements = pathNames;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public void setUuid(String uuid) {
+ this.uuid = uuid;
+ }
+
+ public SortedMap getRelatedElements(
+ TreeSPath path) {
+ SortedMap relatedElements = new TreeMap();
+ List hierarchy = path.getHierarchyAsList();
+ for (TreeSPath currPath : elements.keySet()) {
+ if (hierarchy.contains(currPath)) {
+ relatedElements.put(currPath, elements.get(currPath));
+ }
+ }
+ return relatedElements;
+ }
+
+ public TestRun getCurrentTestRun() {
+ return currentTestRun;
+ }
+
+ public int compareTo(TreeTestResult ttr2) {
+ TreeTestResult ttr1 = this;
+ if (ttr1.getCloseDate() != null && ttr2.getCloseDate() != null) {
+ return -ttr1.getCloseDate().compareTo(ttr2.getCloseDate());
+ } else if (ttr1.getCloseDate() != null && ttr2.getCloseDate() == null) {
+ return 1;
+ } else if (ttr1.getCloseDate() == null && ttr2.getCloseDate() != null) {
+ return -1;
+ } else {
+ return ttr1.getUuid().compareTo(ttr2.getUuid());
+ }
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/TreeTestResultCollection.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/TreeTestResultCollection.java
new file mode 100644
index 000000000..1c454687c
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/TreeTestResultCollection.java
@@ -0,0 +1,45 @@
+package org.argeo.slc.core.test.tree;
+
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+public class TreeTestResultCollection implements
+ Comparable {
+ private String id;
+ private SortedSet results = new TreeSet();
+
+ public TreeTestResultCollection() {
+ }
+
+ public TreeTestResultCollection(String id) {
+ this.id = id;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public SortedSet getResults() {
+ return results;
+ }
+
+ public void setResults(SortedSet results) {
+ this.results = results;
+ }
+
+ public int compareTo(TreeTestResultCollection o) {
+ return getId().compareTo(o.getId());
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof TreeTestResultCollection) {
+ return getId().equals(((TreeTestResultCollection) o).getId());
+ }
+ return false;
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/TreeTestResultLogger.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/TreeTestResultLogger.java
new file mode 100644
index 000000000..2246e18b0
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/TreeTestResultLogger.java
@@ -0,0 +1,39 @@
+package org.argeo.slc.core.test.tree;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.argeo.slc.core.test.TestResultListener;
+import org.argeo.slc.core.test.TestResultPart;
+import org.argeo.slc.core.test.TestStatus;
+
+/**
+ * Listener logging tree-based test results to the underlying logging system.
+ *
+ * @see TreeTestResult
+ *
+ */
+public class TreeTestResultLogger implements TestResultListener {
+
+ private static Log log = LogFactory.getLog(TreeTestResultLogger.class);
+
+ public void resultPartAdded(TreeTestResult testResult,
+ TestResultPart testResultPart) {
+ String msg = testResultPart + " - " + testResult.getUuid() + ":"
+ + testResult.getCurrentPath();
+ if (testResultPart.getStatus().equals(TestStatus.PASSED)) {
+ log.info(msg);
+ } else if (testResultPart.getStatus().equals(TestStatus.FAILED)) {
+ log.warn(msg);
+ } else if (testResultPart.getStatus().equals(TestStatus.ERROR)) {
+ log.error(msg + "\n" + testResultPart.getExceptionMessage());
+ } else {
+ log.error("Unknow test status: " + msg);
+ }
+ }
+
+ public void close(TreeTestResult testResult) {
+ log.info("Test result " + testResult.getUuid() + " closed.");
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/WebServiceTreeTestResultNotifier.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/WebServiceTreeTestResultNotifier.java
new file mode 100644
index 000000000..6cfd4da61
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/WebServiceTreeTestResultNotifier.java
@@ -0,0 +1,110 @@
+package org.argeo.slc.core.test.tree;
+
+import org.springframework.ws.client.WebServiceIOException;
+import org.springframework.ws.client.core.WebServiceTemplate;
+import org.springframework.ws.soap.client.SoapFaultClientException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.argeo.slc.core.test.TestResultListener;
+import org.argeo.slc.core.test.TestResultPart;
+import org.argeo.slc.msg.test.tree.CloseTreeTestResultRequest;
+import org.argeo.slc.msg.test.tree.CreateTreeTestResultRequest;
+import org.argeo.slc.msg.test.tree.ResultPartRequest;
+import org.argeo.slc.ws.client.WebServiceUtils;
+
+public class WebServiceTreeTestResultNotifier implements
+ TestResultListener {
+ private WebServiceTemplate template;
+ private Boolean onlyOnClose = false;
+
+ private Log log = LogFactory.getLog(getClass());
+
+ private Boolean cannotConnect = false;
+
+ public void resultPartAdded(TreeTestResult testResult,
+ TestResultPart testResultPart) {
+ if (onlyOnClose)
+ return;
+
+ if (cannotConnect)
+ return;
+
+ try {
+ if (testResult.getResultParts().size() == 1
+ && testResult.getResultParts().values().iterator().next()
+ .getParts().size() == 1) {
+ CreateTreeTestResultRequest req = new CreateTreeTestResultRequest(
+ testResult);
+
+ if (log.isDebugEnabled())
+ log.debug("Send create result request for result "
+ + testResult.getUuid());
+
+ WebServiceUtils.marshalSendAndReceive(template, req);
+ } else {
+ ResultPartRequest req = new ResultPartRequest(testResult);
+
+ if (log.isDebugEnabled())
+ log.debug("Send result parts for result "
+ + testResult.getUuid());
+
+ WebServiceUtils.marshalSendAndReceive(template, req);
+ }
+ } catch (SoapFaultClientException e) {
+ WebServiceUtils.manageSoapException(e);
+
+ } catch (WebServiceIOException e) {
+ manageIoException(e);
+ }
+ }
+
+ public void close(TreeTestResult testResult) {
+ if (cannotConnect)
+ return;
+
+ try {
+ if (onlyOnClose) {
+ CreateTreeTestResultRequest req = new CreateTreeTestResultRequest(
+ testResult);
+
+ if (log.isDebugEnabled())
+ log.debug("Send create result request for result "
+ + testResult.getUuid());
+
+ WebServiceUtils.marshalSendAndReceive(template, req);
+ } else {
+ CloseTreeTestResultRequest req = new CloseTreeTestResultRequest(
+ testResult);
+
+ if (log.isDebugEnabled())
+ log.debug("Send close result request for result "
+ + testResult.getUuid());
+
+ WebServiceUtils.marshalSendAndReceive(template, req);
+
+ }
+ } catch (SoapFaultClientException e) {
+ WebServiceUtils.manageSoapException(e);
+ } catch (WebServiceIOException e) {
+ manageIoException(e);
+ }
+ }
+
+ public void setTemplate(WebServiceTemplate template) {
+ this.template = template;
+ }
+
+ public void setOnlyOnClose(Boolean onlyOnClose) {
+ this.onlyOnClose = onlyOnClose;
+ }
+
+ protected void manageIoException(WebServiceIOException e) {
+ if (!cannotConnect) {
+ log.error("Cannot connect to " + template.getDefaultUri()
+ + ". Won't try again.", e);
+ cannotConnect = true;
+ }
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/XsltReportGenerator.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/XsltReportGenerator.java
new file mode 100644
index 000000000..059c209f1
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/XsltReportGenerator.java
@@ -0,0 +1,156 @@
+package org.argeo.slc.core.test.tree;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.Templates;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.springframework.core.io.Resource;
+import org.springframework.oxm.Marshaller;
+import org.springframework.xml.transform.StringResult;
+import org.w3c.dom.Document;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.argeo.slc.core.SlcException;
+import org.argeo.slc.core.test.TestResultListener;
+import org.argeo.slc.core.test.TestResultPart;
+
+public class XsltReportGenerator implements TestResultListener {
+ private Log log = LogFactory.getLog(getClass());
+
+ private DocumentBuilder documentBuilder = null;
+
+ private Resource xsltStyleSheet;
+
+ private Templates templates;
+
+ private Marshaller marshaller;
+
+ private String outputDir;
+ private String outputFileExtension = "html";
+
+ private Boolean logXml = false;
+
+ public void init() {
+ if (templates != null)
+ return;
+
+ if (xsltStyleSheet == null)
+ throw new SlcException("XSLT style sheet not specified.");
+
+ InputStream in = null;
+ try {
+ TransformerFactory transformerFactory = TransformerFactory
+ .newInstance();
+ in = xsltStyleSheet.getInputStream();
+ StreamSource xsltSource = new StreamSource(in);
+ templates = transformerFactory.newTemplates(xsltSource);
+ } catch (Exception e) {
+ throw new SlcException("Could not initialize templates", e);
+ } finally {
+ IOUtils.closeQuietly(in);
+ }
+ }
+
+ public void resultPartAdded(TreeTestResult testResult,
+ TestResultPart testResultPart) {
+
+ }
+
+ public void close(TreeTestResult testResult) {
+ if (templates == null)
+ throw new SlcException("XSLT template not initialized");
+
+ File file = getFile(testResult);
+ OutputStream out = null;
+
+ try {
+ Transformer transformer = templates.newTransformer();
+
+ if (documentBuilder == null)
+ documentBuilder = DocumentBuilderFactory.newInstance()
+ .newDocumentBuilder();
+
+ Document document = documentBuilder.newDocument();
+ DOMResult marshallResult = new DOMResult(document);
+ marshaller.marshal(testResult, marshallResult);
+
+ if (logXml) {
+ Transformer identityTransformer = TransformerFactory
+ .newInstance().newTransformer();
+ StringResult xmlResult = new StringResult();
+ identityTransformer.transform(new DOMSource(marshallResult
+ .getNode()), xmlResult);
+ log.info("Marshalled XML:\n" + xmlResult);
+ }
+
+ DOMSource transfoSource = new DOMSource(marshallResult.getNode());
+
+ if (outputDir != null) {
+ File dir = new File(outputDir);
+ dir.mkdirs();
+ out = new FileOutputStream(file);
+ StreamResult outputResult = new StreamResult(out);
+ transformer.transform(transfoSource, outputResult);
+ } else {
+ // print on console if no output dir
+ StringResult result = new StringResult();
+ transformer.transform(transfoSource, result);
+ log.info("Generated report:\n" + result);
+ }
+ } catch (Exception e) {
+ throw new SlcException(
+ "Could not transform test result to " + file, e);
+ } finally {
+ IOUtils.closeQuietly(out);
+ }
+ }
+
+ public Resource getXsltStyleSheet() {
+ return xsltStyleSheet;
+ }
+
+ public void setXsltStyleSheet(Resource xsltStyleSheet) {
+ this.xsltStyleSheet = xsltStyleSheet;
+ }
+
+ public void setTemplates(Templates templates) {
+ this.templates = templates;
+ }
+
+ public void setMarshaller(Marshaller marshaller) {
+ this.marshaller = marshaller;
+ }
+
+ public void setOutputDir(String outputDir) {
+ this.outputDir = outputDir;
+ }
+
+ public void setOutputFileExtension(String outputFileExtension) {
+ this.outputFileExtension = outputFileExtension;
+ }
+
+ protected File getFile(TreeTestResult result) {
+ Long time = System.currentTimeMillis();
+ return new File(outputDir + File.separator + time + "-"
+ + result.getUuid() + "." + outputFileExtension);
+ }
+
+ public void setLogXml(Boolean logXml) {
+ this.logXml = logXml;
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/htmlreport/FullHtmlTreeReport.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/htmlreport/FullHtmlTreeReport.java
new file mode 100644
index 000000000..a77eb34f0
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/htmlreport/FullHtmlTreeReport.java
@@ -0,0 +1,168 @@
+package org.argeo.slc.core.test.tree.htmlreport;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.SimpleDateFormat;
+import java.util.Comparator;
+import java.util.List;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.argeo.slc.core.SlcException;
+import org.argeo.slc.core.structure.StructureAware;
+import org.argeo.slc.core.structure.StructurePath;
+import org.argeo.slc.core.structure.StructureRegistry;
+import org.argeo.slc.core.structure.tree.TreeSPath;
+import org.argeo.slc.core.test.TestReport;
+import org.argeo.slc.core.test.TestResult;
+import org.argeo.slc.core.test.tree.TreeTestResult;
+import org.argeo.slc.dao.structure.tree.TreeSRegistryDao;
+import org.argeo.slc.dao.test.TestResultDao;
+
+/**
+ * Basic implementation of TestReport generating static HTML pages. If a
+ * TestResultDao
is passed, all the data is dumped, otherwise
+ * only the passed TestResult
.
+ */
+public class FullHtmlTreeReport implements TestReport, StructureAware {
+ private static final Log log = LogFactory.getLog(FullHtmlTreeReport.class);
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
+
+ private TestResultDao testResultDao;
+ private TreeSRegistryDao treeSRegistryDao;
+ private File reportDir;
+
+ private StructureRegistry localRegistry;
+
+ public void generateTestReport(TestResult testResult) {
+
+ if (testResultDao == null) {
+ if (testResult == null)
+ throw new SlcException(
+ "Cannot generate report without DAO or result instance.");
+
+ TreeTestResult result = (TreeTestResult) testResult;
+ ResultPage page = new ResultPage(this, result);
+ page.generate(getRegistry(result));
+ } else {
+ if (reportDir.exists()) {
+ // clean
+ for (File file : reportDir.listFiles()) {
+ file.delete();
+ }
+ }
+ reportDir.mkdirs();
+
+ resourceToFile("index.html");
+
+ ResultsList index = new ResultsList(this);
+ List list = testResultDao.listTestResults();
+ SortedSet sortedSet = new TreeSet(
+ new Comparator() {
+
+ public int compare(TestResult o1, TestResult o2) {
+ if (o1.getCloseDate() == null
+ || o2.getCloseDate() == null)
+ return 0;
+ // inverse date order (last first)
+ return o2.getCloseDate().compareTo(
+ o1.getCloseDate());
+ }
+
+ });
+ sortedSet.addAll(list);
+ for (TestResult testRes : sortedSet) {
+ TreeTestResult result = (TreeTestResult) testRes;
+
+ index.addTestResult(result);
+ ResultPage page = new ResultPage(this, result);
+ page.generate(getRegistry(result));
+ }
+ index.close();
+ }
+ log.info("Generated HTML test result report to "+reportDir);
+ }
+
+ /**
+ * Generates a result file location based on the report dir and the id of
+ * the test result.
+ */
+ protected File getResultFile(TreeTestResult result) {
+ return new File(reportDir.getPath() + File.separator + "slc-result-"
+ + result.getUuid() + ".html");
+ }
+
+ /** Sets the DAO to use to extract all data. */
+ public void setTestResultDao(TestResultDao testResultDao) {
+ this.testResultDao = testResultDao;
+ }
+
+ /** Sets the tree structure registry DAO. */
+ public void setTreeSRegistryDao(TreeSRegistryDao treeSRegistryDao) {
+ this.treeSRegistryDao = treeSRegistryDao;
+ }
+
+ /** Sets the directory where to generate all the data. */
+ public void setReportDir(File reportDir) {
+ this.reportDir = reportDir;
+ }
+
+ private StructureRegistry getRegistry(TreeTestResult result) {
+ StructureRegistry registry = null;
+ if (treeSRegistryDao != null) {
+ TreeSPath path = result.getResultParts().firstKey();
+ registry = treeSRegistryDao.getActiveTreeSRegistry();
+ }
+ if (registry == null) {
+ registry = localRegistry;
+ }
+ if (registry == null) {
+ throw new SlcException("No structure registry available");
+ }
+ return registry;
+ }
+
+ public void notifyCurrentPath(StructureRegistry registry, StructurePath path) {
+ this.localRegistry = registry;
+ }
+
+ File getReportDir() {
+ return reportDir;
+ }
+
+ void addStyles(StringBuffer buf) {
+ try {
+ buf.append("\n");
+ } catch (IOException e) {
+ throw new SlcException("Cannot load styles", e);
+ }
+ }
+
+ private void resourceToFile(String resourceName) {
+ try {
+ File file = new File(getReportDir() + File.separator + resourceName);
+ InputStream in = FullHtmlTreeReport.class
+ .getResourceAsStream(resourceName);
+ FileOutputStream out = new FileOutputStream(file);
+ IOUtils.copy(in, out);
+ IOUtils.closeQuietly(in);
+ IOUtils.closeQuietly(out);
+ } catch (Exception e) {
+ throw new SlcException("Cannot load resource", e);
+ }
+
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/htmlreport/ResultPage.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/htmlreport/ResultPage.java
new file mode 100644
index 000000000..69bba492e
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/htmlreport/ResultPage.java
@@ -0,0 +1,211 @@
+package org.argeo.slc.core.test.tree.htmlreport;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Date;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.argeo.slc.core.structure.StructureElement;
+import org.argeo.slc.core.structure.StructureRegistry;
+import org.argeo.slc.core.structure.tree.TreeSPath;
+import org.argeo.slc.core.test.SimpleResultPart;
+import org.argeo.slc.core.test.TestResultPart;
+import org.argeo.slc.core.test.TestStatus;
+import org.argeo.slc.core.test.tree.PartSubList;
+import org.argeo.slc.core.test.tree.TreeTestResult;
+
+class ResultPage {
+ private final static Log log = LogFactory.getLog(ResultPage.class);
+
+ private final FullHtmlTreeReport report;
+ private final TreeTestResult result;
+
+ ResultPage(FullHtmlTreeReport report, TreeTestResult result) {
+ this.report = report;
+ this.result = result;
+ }
+
+ /**
+ * Generates a result page for one test result
+ *
+ * @param file
+ * file to which generate the HTML
+ * @param result
+ * the result to dump
+ */
+ protected void generate(StructureRegistry registry) {
+ StringBuffer buf = new StringBuffer("");
+ buf.append("\n");
+ buf.append("");
+ buf.append("Result #").append(result.getUuid());
+ buf.append("\n");
+ report.addStyles(buf);
+ buf.append("\n");
+
+ buf.append("\n");
+
+ // Header
+ buf.append("\n");
+ buf.append("Result #").append(result.getUuid()).append("
\n");
+ Date closeDate = result.getCloseDate();
+ if (closeDate == null) {
+ buf.append("[Not closed]");
+ } else {
+ buf.append(report.sdf.format(closeDate));
+ }
+
+ // TOC
+ generateToc(buf, registry);
+
+ generatePartsList(buf, registry);
+
+ buf.append("");
+ buf.append("");
+
+ try {
+ FileUtils.writeStringToFile(report.getResultFile(result), buf
+ .toString());
+ } catch (IOException e) {
+ log.error("Could not save result page.", e);
+ }
+ }
+
+ private void generateToc(StringBuffer buf,
+ StructureRegistry registry) {
+ buf.append("Overview
\n");
+ SortedMap toc = new TreeMap();
+ for (TreeSPath path : result.getResultParts().keySet()) {
+ PartSubList subList = (PartSubList) result.getResultParts().get(
+ path);
+ boolean isFailed = false;
+ for (TestResultPart part : subList.getParts()) {
+ if (!part.getStatus().equals(TestStatus.PASSED)) {
+ isFailed = true;
+ break;
+ }
+ }
+ fillToc(toc, path, isFailed);
+ }
+
+ buf.append("\n");
+ buf.append("
\n");
+ }
+
+ private void generatePartsList(StringBuffer buf,
+ StructureRegistry registry) {
+ for (TreeSPath path : result.getResultParts().keySet()) {
+ buf.append("\n");
+ buf.append("");
+ buf.append("
");
+ describedPath(path, registry, buf);
+ buf.append("
");
+
+ PartSubList subList = (PartSubList) result.getResultParts().get(
+ path);
+ buf.append("\n");
+ int displayedIndex = 1;// for display only
+ for (TestResultPart part : subList.getParts()) {
+ SimpleResultPart sPart = (SimpleResultPart) part;
+ buf.append("Related Test Run Id:").append(
+ sPart.getTestRunUuid()).append("
\n");
+ String clss = "";
+ if (sPart.getStatus().equals(TestStatus.PASSED)) {
+ clss = "passed";
+ } else {
+ clss = "failed";
+ }
+ buf.append("");
+ buf.append("").append(displayedIndex)
+ .append(" | ");
+ buf.append("");
+
+ buf.append(sPart.getMessage());
+ if (sPart.getStatus().equals(TestStatus.ERROR)) {
+ buf
+ .append(" An unexpected error prevented the test to run properly.");
+ buf.append(sPart.getExceptionMessage());
+ buf.append(" ");
+ }
+ buf.append(" | ");
+ buf.append("
\n");
+
+ displayedIndex++;
+ }
+ buf.append("
\n");
+ buf.append("top\n");
+ buf.append("
\n");
+ }
+ }
+
+ private void fillToc(SortedMap toc, TreeSPath path,
+ boolean isFailed) {
+ if (isFailed) {
+ toc.put(path, TestStatus.FAILED);
+ } else {
+ if (!toc.containsKey(path)) {
+ toc.put(path, TestStatus.PASSED);
+ }
+ }
+
+ if (path.getParent() != null) {
+ fillToc(toc, path.getParent(), isFailed);
+ }
+ }
+
+ private String anchor(TreeSPath path) {
+ return path.getAsUniqueString().replace(path.getSeparator(), '_');
+ }
+
+ private void describedPath(TreeSPath path,
+ StructureRegistry registry, StringBuffer buf) {
+ // StringBuffer buf = new StringBuffer("");
+ if (path.getParent() != null) {
+ describedPath(path.getParent(), registry, buf);
+ }
+ String description = path.getName();
+ if (registry != null) {
+ StructureElement element = registry.getElement(path);
+ if (element != null) {
+ description = element.getLabel();
+ }
+ }
+ buf.append('/').append(description);
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/htmlreport/ResultsList.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/htmlreport/ResultsList.java
new file mode 100644
index 000000000..09895d454
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/htmlreport/ResultsList.java
@@ -0,0 +1,63 @@
+package org.argeo.slc.core.test.tree.htmlreport;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Date;
+
+import org.argeo.slc.core.test.tree.TreeTestResult;
+
+class ResultsList {
+ private final FullHtmlTreeReport report;
+ private final StringBuffer buf = new StringBuffer("");
+
+ ResultsList(FullHtmlTreeReport report) {
+ this.report = report;
+
+ buf.append("");
+ buf.append("");
+ buf.append("Results\n");
+ report.addStyles(buf);
+ buf.append("\n");
+ buf.append("\n");
+
+ buf.append("Results
\n");
+ buf.append("\n");
+ buf.append("Date | Result Id |
\n");
+ }
+
+ void addTestResult(TreeTestResult result) {
+ buf.append("\n");
+ // Date
+ buf.append("");
+ Date closeDate = result.getCloseDate();
+ if (closeDate == null) {
+ buf.append("[Not closed]");
+ } else {
+ buf.append(report.sdf.format(closeDate));
+ }
+ buf.append(" | \n");
+ // Id and link
+ buf.append("#");
+ buf.append(result.getUuid()).append(" | \n");
+
+ buf.append("
\n");
+ }
+
+ void close() {
+ buf.append("
\n");
+
+ try {
+ FileWriter writer = new FileWriter(report.getReportDir().getPath()
+ + File.separator + "slc-resultsList.html");
+ writer.write(buf.toString());
+ writer.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/htmlreport/package.html b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/htmlreport/package.html
new file mode 100644
index 000000000..b10bc3d6f
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/htmlreport/package.html
@@ -0,0 +1,6 @@
+
+
+
+Static HTML report for tree based test results.
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/package.html b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/package.html
new file mode 100644
index 000000000..8ad12037e
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/core/test/tree/package.html
@@ -0,0 +1,6 @@
+
+
+
+Extension of SLC Test integrating tree-based structure.
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/process/SlcExecutionDao.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/process/SlcExecutionDao.java
new file mode 100644
index 000000000..181a9febe
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/process/SlcExecutionDao.java
@@ -0,0 +1,12 @@
+package org.argeo.slc.dao.process;
+
+import java.util.List;
+
+import org.argeo.slc.core.process.SlcExecution;
+
+public interface SlcExecutionDao {
+ public void create(SlcExecution slcExecution);
+ public void update(SlcExecution slcExecution);
+ public SlcExecution getSlcExecution(String uuid);
+ public List listSlcExecutions();
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/structure/SimpleSElementDao.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/structure/SimpleSElementDao.java
new file mode 100644
index 000000000..bed950ff3
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/structure/SimpleSElementDao.java
@@ -0,0 +1,5 @@
+package org.argeo.slc.dao.structure;
+
+public interface SimpleSElementDao {
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/structure/package.html b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/structure/package.html
new file mode 100644
index 000000000..f8b5ae763
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/structure/package.html
@@ -0,0 +1,6 @@
+
+
+
+DAOs for the core structure objects.
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/structure/tree/TreeSPathDao.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/structure/tree/TreeSPathDao.java
new file mode 100644
index 000000000..0ebca0d8c
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/structure/tree/TreeSPathDao.java
@@ -0,0 +1,11 @@
+package org.argeo.slc.dao.structure.tree;
+
+import org.argeo.slc.core.structure.tree.TreeSPath;
+
+public interface TreeSPathDao {
+ public void create(TreeSPath path);
+
+ public TreeSPath getTreeSPath(String pathString);
+
+ public TreeSPath getOrCreate(TreeSPath pathTransient);
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/structure/tree/TreeSRegistryDao.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/structure/tree/TreeSRegistryDao.java
new file mode 100644
index 000000000..f271f8cbe
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/structure/tree/TreeSRegistryDao.java
@@ -0,0 +1,25 @@
+package org.argeo.slc.dao.structure.tree;
+
+import org.argeo.slc.core.structure.StructureRegistry;
+import org.argeo.slc.core.structure.tree.TreeSPath;
+import org.argeo.slc.core.structure.tree.TreeSRegistry;
+
+/**
+ * DAO for tree-base structure registry.
+ *
+ * @see TreeSRegistry
+ */
+public interface TreeSRegistryDao {
+ /** Gets the TreeSRegistry which has the same root path as the provided path. */
+ public TreeSRegistry getActiveTreeSRegistry();
+
+ /** Creates a new registry. */
+ public void create(TreeSRegistry registry);
+
+ /** Updates an existing registry. */
+ public void update(TreeSRegistry registry);
+
+ /** Sync with local registry */
+ public void syncPath(TreeSRegistry registry,
+ StructureRegistry localRegistry, TreeSPath path);
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/structure/tree/package.html b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/structure/tree/package.html
new file mode 100644
index 000000000..b8cd81210
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/structure/tree/package.html
@@ -0,0 +1,6 @@
+
+
+
+DAOs for the tree-based structure objects.
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/test/TestResultDao.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/test/TestResultDao.java
new file mode 100644
index 000000000..01cdffd25
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/test/TestResultDao.java
@@ -0,0 +1,28 @@
+package org.argeo.slc.dao.test;
+
+import java.util.Date;
+import java.util.List;
+
+import org.argeo.slc.core.test.TestResult;
+
+/**
+ * The dao for TestResult
.
+ *
+ * @see TestResult
+ */
+public interface TestResultDao {
+ /** Gets a test result based on its id. */
+ public T getTestResult(String uuid);
+
+ /** Persists a new test result. */
+ public void create(TestResult testResult);
+
+ /** Updates an already persisted test result. */
+ public void update(TestResult testResult);
+
+ /** Lists all test results. */
+ public List listTestResults();
+
+
+ public void close(String id, Date closeDate);
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/test/TestRunDescriptorDao.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/test/TestRunDescriptorDao.java
new file mode 100644
index 000000000..7397458b5
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/test/TestRunDescriptorDao.java
@@ -0,0 +1,8 @@
+package org.argeo.slc.dao.test;
+
+import org.argeo.slc.core.test.TestRunDescriptor;
+
+public interface TestRunDescriptorDao {
+ public TestRunDescriptor getTestRunDescriptor(String id);
+ public void saveOrUpdate(TestRunDescriptor testRunDescriptor);
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/test/package.html b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/test/package.html
new file mode 100644
index 000000000..38ae2b5bf
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/test/package.html
@@ -0,0 +1,6 @@
+
+
+
+Data Access Objects for SLC Test.
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/test/tree/TreeTestResultCollectionDao.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/test/tree/TreeTestResultCollectionDao.java
new file mode 100644
index 000000000..02bc13488
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/test/tree/TreeTestResultCollectionDao.java
@@ -0,0 +1,15 @@
+package org.argeo.slc.dao.test.tree;
+
+import java.util.SortedSet;
+
+import org.argeo.slc.core.test.tree.TreeTestResultCollection;
+
+public interface TreeTestResultCollectionDao {
+ public void create(TreeTestResultCollection ttrCollection);
+
+ public void update(TreeTestResultCollection ttrCollection);
+
+ public TreeTestResultCollection getTestResultCollection(String id);
+
+ public SortedSet listCollections();
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/test/tree/TreeTestResultDao.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/test/tree/TreeTestResultDao.java
new file mode 100644
index 000000000..c66d36921
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/test/tree/TreeTestResultDao.java
@@ -0,0 +1,12 @@
+package org.argeo.slc.dao.test.tree;
+
+import java.util.List;
+
+import org.argeo.slc.core.structure.tree.TreeSPath;
+import org.argeo.slc.core.test.tree.TreeTestResult;
+import org.argeo.slc.dao.test.TestResultDao;
+
+public interface TreeTestResultDao extends TestResultDao {
+ /** Lists results containing this path */
+ public List listResults(TreeSPath path);
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/test/tree/TreeTestResultPersister.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/test/tree/TreeTestResultPersister.java
new file mode 100644
index 000000000..73766ead6
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/dao/test/tree/TreeTestResultPersister.java
@@ -0,0 +1,55 @@
+package org.argeo.slc.dao.test.tree;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.argeo.slc.core.test.TestResultListener;
+import org.argeo.slc.core.test.TestResultPart;
+import org.argeo.slc.core.test.tree.TreeTestResult;
+
+/**
+ * Listener persisting tree-based results.
+ *
+ * @see TreeTestResult
+ */
+public class TreeTestResultPersister implements
+ TestResultListener {
+ private static Log log = LogFactory.getLog(TreeTestResultPersister.class);
+
+ private TreeTestResultDao testResultDao;
+
+ public void resultPartAdded(TreeTestResult testResult,
+ TestResultPart testResultPart) {
+ try {
+ TreeTestResult persistedResult = testResultDao
+ .getTestResult(testResult.getUuid());
+
+ if (persistedResult == null) {
+ testResultDao.create(testResult);
+ } else {
+ testResultDao.update(testResult);
+ }
+ } catch (Exception e) {
+ log.error("Could not persist result part " + testResultPart
+ + " for result " + testResult.getUuid());
+ }
+ }
+
+ public void close(TreeTestResult testResult) {
+ TreeTestResult persistedResult = (TreeTestResult) testResultDao
+ .getTestResult(testResult.getUuid());
+
+ if (persistedResult != null) {
+ persistedResult.setCloseDate(testResult.getCloseDate());
+ testResultDao.update(persistedResult);
+ }
+ if (log.isDebugEnabled())
+ log.debug("Closed result persister for result "
+ + testResult.getUuid());
+ }
+
+ /** Sets the DAO to use in order to persist the results. */
+ public void setTestResultDao(TreeTestResultDao testResultDao) {
+ this.testResultDao = testResultDao;
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/DataInterpreter.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/DataInterpreter.java
new file mode 100644
index 000000000..7a57b0552
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/DataInterpreter.java
@@ -0,0 +1,20 @@
+package org.argeo.slc.diff;
+
+/**
+ * Converts data into a format better adapted for comparison. It is typically
+ * used to convert String
into typed format such as
+ * BigDecimal
+ */
+public interface DataInterpreter {
+ /**
+ * Converts data
+ *
+ * @param key
+ * any object used to differentiate the type of data (e.g.
+ * column, path)
+ * @param value
+ * the data to convert
+ * @return the converted object
+ */
+ public Object convert(Object key, Object value);
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/Diff.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/Diff.java
new file mode 100644
index 000000000..0b28996e9
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/Diff.java
@@ -0,0 +1,9 @@
+package org.argeo.slc.diff;
+
+import org.springframework.core.io.Resource;
+
+/** A comparator providing structured information about the differences found. */
+public interface Diff {
+ /** Performs the comparison. */
+ public DiffResult compare(Resource expected, Resource reached);
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/DiffIssue.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/DiffIssue.java
new file mode 100644
index 000000000..5517b3a66
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/DiffIssue.java
@@ -0,0 +1,22 @@
+package org.argeo.slc.diff;
+
+/** The root class for issues which happened during a diff. */
+public abstract class DiffIssue implements Comparable {
+ /** The position of this issue. */
+ protected final DiffPosition position;
+
+ /** Constructor */
+ public DiffIssue(DiffPosition position) {
+ super();
+ this.position = position;
+ }
+
+ public int compareTo(DiffIssue o) {
+ return position.compareTo(o.position);
+ }
+
+ /** The position of this issue within the test file */
+ public DiffPosition getPosition() {
+ return position;
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/DiffKey.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/DiffKey.java
new file mode 100644
index 000000000..9d34f720a
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/DiffKey.java
@@ -0,0 +1,9 @@
+package org.argeo.slc.diff;
+
+/**
+ * Object able to uniquely identify an atomic diff part. Used to identify
+ * missings and left-overs.
+ */
+public interface DiffKey {
+ public String toString();
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/DiffMissing.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/DiffMissing.java
new file mode 100644
index 000000000..da4476660
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/DiffMissing.java
@@ -0,0 +1,31 @@
+package org.argeo.slc.diff;
+
+/**
+ * A value missing in one of the file. If its position is related to expected,
+ * this means it is a left over in the reached, if its position is related to
+ * the reached it means that it is missing from the reached. If the value is
+ * null it means that the entire line is missing.
+ */
+public class DiffMissing extends DiffIssue {
+ private final DiffKey key;
+
+ public DiffMissing(DiffPosition position, DiffKey key) {
+ super(position);
+ this.key = key;
+ }
+
+ public Object getKey() {
+ return key;
+ }
+
+ @Override
+ public String toString() {
+ if (position.relatedFile == RelatedFile.EXPECTED) {
+ return position + ": left over " + key;
+ } else if (position.relatedFile == RelatedFile.REACHED) {
+ return position + ": missing " + key;
+ }
+ return super.toString();
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/DiffMissingXml.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/DiffMissingXml.java
new file mode 100644
index 000000000..ca3fd21a2
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/DiffMissingXml.java
@@ -0,0 +1,43 @@
+package org.argeo.slc.diff;
+
+/**
+ * DiffMissing
using the XPath of the position as
+ * DiffKey
+ */
+public class DiffMissingXml extends DiffMissing {
+
+ public DiffMissingXml(XPathDiffPosition position) {
+ super(position, new DiffKeyXml(position.getXPath()));
+ }
+
+ /** Implementation of DiffKey
based on an XPath string. */
+ protected static class DiffKeyXml implements DiffKey {
+ private final String xPath;
+
+ public DiffKeyXml(String xPath) {
+ this.xPath = xPath;
+ }
+
+ public String getXPath() {
+ return xPath;
+ }
+
+ @Override
+ public String toString() {
+ return xPath;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof DiffKeyXml))
+ return false;
+ return xPath.equals(((DiffKeyXml) obj).xPath);
+ }
+
+ @Override
+ public int hashCode() {
+ return xPath.hashCode();
+ }
+
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/DiffNotMatched.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/DiffNotMatched.java
new file mode 100644
index 000000000..04f7acff1
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/DiffNotMatched.java
@@ -0,0 +1,27 @@
+package org.argeo.slc.diff;
+
+/** Diff issue where reached and expected values are different. */
+public class DiffNotMatched extends DiffIssue {
+ private final Object expected;
+ private final Object reached;
+
+ public DiffNotMatched(DiffPosition position, Object expected, Object reached) {
+ super(position);
+ this.expected = expected;
+ this.reached = reached;
+ }
+
+ public Object getExpected() {
+ return expected;
+ }
+
+ public Object getReached() {
+ return reached;
+ }
+
+ @Override
+ public String toString() {
+ return position + ": not matched " + expected + " <> " + reached;
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/DiffPosition.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/DiffPosition.java
new file mode 100644
index 000000000..302c0afa9
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/DiffPosition.java
@@ -0,0 +1,16 @@
+package org.argeo.slc.diff;
+
+/** The position of a diff issue within the test resource. */
+public abstract class DiffPosition implements Comparable {
+ protected RelatedFile relatedFile;
+
+ public DiffPosition(RelatedFile relatedFile) {
+ super();
+ this.relatedFile = relatedFile;
+ }
+
+ public RelatedFile getRelatedFile() {
+ return relatedFile;
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/DiffResult.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/DiffResult.java
new file mode 100644
index 000000000..0e29fdd05
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/DiffResult.java
@@ -0,0 +1,12 @@
+package org.argeo.slc.diff;
+
+import java.util.List;
+
+/**
+ * The result of a diff. Can be subclassed to provided more structured
+ * information.
+ */
+public interface DiffResult {
+ /** The list of issues, a zero size meaning that the diff succeeded. */
+ public List getIssues();
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/LineTokenizer.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/LineTokenizer.java
new file mode 100644
index 000000000..fed4c37b5
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/LineTokenizer.java
@@ -0,0 +1,96 @@
+package org.argeo.slc.diff;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Parses a string as a vector of strings according to a separator, dealing
+ * properly with missing values. This is intended to be used instead of the
+ * standard StringTokenizer, which does not deal well with empty values.
+ * Contrary to the StringTokenizer the provided String is parsed in the
+ * constructor and the values stored as a property. This should therefore not be
+ * used to parse long strings. No reference to the argument passed in
+ * constructor is kept.
+ */
+public class LineTokenizer {
+ private final List tokens;
+
+ /** Complete constructor. */
+ public LineTokenizer(String stringToParse, Character separator,
+ String noValueString) {
+ this.tokens = parse(stringToParse, separator, noValueString);
+ }
+
+ /**
+ * Parse the string as a vector of strings. Can be overridden in order to
+ * provide another implementation.
+ */
+ protected List parse(final String stringToParse,
+ final char separator, final String noValueString) {
+ // Init
+ final int NULL = -1;
+ List res = new ArrayList();
+ final char[] array = stringToParse.toCharArray();
+ int lastSeparatorIndex = NULL;
+
+ // Loop on chars
+ for (int currIndex = 0; currIndex < array.length; currIndex++) {
+ char c = array[currIndex];
+ if (c == separator) {
+ if (currIndex == 0) {
+ // first char is a separator
+ res.add(new String(noValueString));
+ lastSeparatorIndex = 0;
+ } else if (lastSeparatorIndex == NULL) {
+ // first separator found
+ res.add(new String(array, 0, currIndex));
+ lastSeparatorIndex = currIndex;
+ } else if (lastSeparatorIndex != NULL
+ && (lastSeparatorIndex == (currIndex - 1))) {
+ // consecutive separators
+ res.add(new String(noValueString));
+ lastSeparatorIndex = currIndex;
+ } else {
+ // simple case
+ res.add(new String(array, lastSeparatorIndex + 1, currIndex
+ - lastSeparatorIndex - 1));
+ lastSeparatorIndex = currIndex;
+ }
+ }
+ }
+
+ // Finalize
+ if (lastSeparatorIndex == NULL) {
+ // no separator found
+ res.add(new String(stringToParse));
+ } else if (lastSeparatorIndex == (array.length - 1)) {
+ // last char is a separator
+ res.add(new String(noValueString));
+ } else {
+ // last token
+ res.add(new String(array, lastSeparatorIndex + 1, array.length
+ - lastSeparatorIndex - 1));
+ }
+ return res;
+ }
+
+ /** The tokens. */
+ public List getTokens() {
+ return tokens;
+ }
+
+ /** Parse */
+ public static List tokenize(String stringToParse,
+ Character separator, String noValueString) {
+ LineTokenizer lt = new LineTokenizer(stringToParse, separator,
+ noValueString);
+ return lt.getTokens();
+ }
+
+ /** Parse, using the empty string as no value string. */
+ public static List tokenize(String stringToParse,
+ Character separator) {
+ return tokenize(stringToParse, separator, "");
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/RelatedFile.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/RelatedFile.java
new file mode 100644
index 000000000..757968355
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/RelatedFile.java
@@ -0,0 +1,9 @@
+package org.argeo.slc.diff;
+
+/** Enumeration of the types of resource tested. */
+public enum RelatedFile {
+ /** The expected resource */
+ EXPECTED,
+ /** The reached resource */
+ REACHED
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/SimpleDiffResult.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/SimpleDiffResult.java
new file mode 100644
index 000000000..6eefb7f28
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/SimpleDiffResult.java
@@ -0,0 +1,14 @@
+package org.argeo.slc.diff;
+
+import java.util.List;
+import java.util.Vector;
+
+/** A basic implementation of DiffResult
. */
+public class SimpleDiffResult implements DiffResult {
+ private List issues = new Vector();
+
+ public List getIssues() {
+ return issues;
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/TableDiffPosition.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/TableDiffPosition.java
new file mode 100644
index 000000000..d8a3d785d
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/TableDiffPosition.java
@@ -0,0 +1,66 @@
+package org.argeo.slc.diff;
+
+import org.argeo.slc.core.UnsupportedException;
+
+/**
+ * A diff position within a table structure such a CSV file or an SQL result
+ * set.
+ */
+public class TableDiffPosition extends DiffPosition {
+ private Integer line;
+ /** Can be null */
+ private Integer column;
+ /** Can be null */
+ private String columnName;
+
+ public TableDiffPosition(RelatedFile relatedFile, Integer line,
+ Integer column, String columnName) {
+ super(relatedFile);
+ this.line = line;
+ this.column = column;
+ this.columnName = columnName;
+ }
+
+ public Integer getLine() {
+ return line;
+ }
+
+ public Integer getColumn() {
+ return column;
+ }
+
+ public String getColumnName() {
+ return columnName;
+ }
+
+ public int compareTo(DiffPosition dp) {
+ if (!(dp instanceof TableDiffPosition))
+ throw new UnsupportedException("position", dp);
+
+ TableDiffPosition o = (TableDiffPosition) dp;
+ if (relatedFile.equals(o.relatedFile)) {
+ if (line == o.line) {
+ return column.compareTo(o.column);
+ } else {
+ return line.compareTo(o.line);
+ }
+ } else {
+ return relatedFile.compareTo(o.relatedFile);
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer buf = new StringBuffer("");
+ buf.append(relatedFile).append('[').append(line);
+ if (column != null) {
+ buf.append(',').append(column);
+ if (columnName != null) {
+ buf.append('-').append(columnName);
+ }
+ }
+ buf.append(']');
+ return buf.toString();
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/Tolerance.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/Tolerance.java
new file mode 100644
index 000000000..b44a7123a
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/Tolerance.java
@@ -0,0 +1,18 @@
+package org.argeo.slc.diff;
+
+/** Compares objects, eventually using tolerance mechanisms. */
+public interface Tolerance {
+ /**
+ * Compares objects
+ *
+ * @param key
+ * any object used to differentiate the type of data (e.g.
+ * column, path)
+ * @param expected
+ * the expected value
+ * @param reached
+ * the reached value
+ * @return the converted object
+ */
+ public Boolean compare(Object key, Object expected, Object reached);
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/XPathDiffPosition.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/XPathDiffPosition.java
new file mode 100644
index 000000000..0d2234240
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/XPathDiffPosition.java
@@ -0,0 +1,35 @@
+package org.argeo.slc.diff;
+
+import org.argeo.slc.core.UnsupportedException;
+
+/** A diff position within an Xml file. NOT YET IMPLEMENTED. */
+public class XPathDiffPosition extends DiffPosition {
+
+ private String xPath;
+
+ public XPathDiffPosition(RelatedFile relatedFile, String path) {
+ super(relatedFile);
+ xPath = path;
+ }
+
+ public int compareTo(DiffPosition dp) {
+ if (!(dp instanceof XPathDiffPosition))
+ throw new UnsupportedException("position", dp);
+
+ XPathDiffPosition o = (XPathDiffPosition) dp;
+ if (relatedFile.equals(o.relatedFile)) {
+ return xPath.compareTo(o.xPath);
+ } else {
+ return relatedFile.compareTo(o.relatedFile);
+ }
+ }
+
+ public String getXPath() {
+ return xPath;
+ }
+
+ @Override
+ public String toString() {
+ return xPath;
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/package.html b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/package.html
new file mode 100644
index 000000000..a58e68575
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/diff/package.html
@@ -0,0 +1,6 @@
+
+
+
+Abstraction of diff comparison with structured results.
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/hibernate/process/SlcExecutionDaoHibernate.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/hibernate/process/SlcExecutionDaoHibernate.java
new file mode 100644
index 000000000..9518d93fc
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/hibernate/process/SlcExecutionDaoHibernate.java
@@ -0,0 +1,31 @@
+package org.argeo.slc.hibernate.process;
+
+import java.util.List;
+
+import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
+
+import org.argeo.slc.core.process.SlcExecution;
+import org.argeo.slc.dao.process.SlcExecutionDao;
+
+public class SlcExecutionDaoHibernate extends HibernateDaoSupport implements
+ SlcExecutionDao {
+
+ public void create(SlcExecution slcExecution) {
+ getHibernateTemplate().save(slcExecution);
+ }
+
+ public void update(SlcExecution slcExecution) {
+ getHibernateTemplate().update(slcExecution);
+ }
+
+ public SlcExecution getSlcExecution(String uuid) {
+ return (SlcExecution) getHibernateTemplate().get(SlcExecution.class,
+ uuid);
+ }
+
+ public List listSlcExecutions() {
+ return (List) getHibernateTemplate().loadAll(
+ SlcExecution.class);
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/hibernate/structure/tree/TreeSPathDaoHibernate.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/hibernate/structure/tree/TreeSPathDaoHibernate.java
new file mode 100644
index 000000000..1e120632c
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/hibernate/structure/tree/TreeSPathDaoHibernate.java
@@ -0,0 +1,62 @@
+package org.argeo.slc.hibernate.structure.tree;
+
+import java.util.List;
+
+import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.argeo.slc.core.structure.tree.TreeSPath;
+import org.argeo.slc.dao.structure.tree.TreeSPathDao;
+
+/**
+ * The Hibernate implementation for tree-based result of the test result dao.
+ *
+ * @see TreeTestResult
+ */
+public class TreeSPathDaoHibernate extends HibernateDaoSupport implements
+ TreeSPathDao {
+
+ private static Log log = LogFactory.getLog(TreeSPathDaoHibernate.class);
+
+ public void create(TreeSPath path) {
+ createImpl(path);
+ }
+
+ private void createImpl(TreeSPath path) {
+ if (path.getParent() != null) {
+ TreeSPath parent = getTreeSPath(path.getParent()
+ .getAsUniqueString());
+ if (parent == null) {
+ createImpl(path.getParent());
+ }
+ }
+ getHibernateTemplate().save(path);
+ if (log.isTraceEnabled())
+ log.trace("Saved TreeSPath " + path.getAsUniqueString());
+ }
+
+ public TreeSPath getTreeSPath(String pathString) {
+ List> list = getHibernateTemplate().find(
+ "from TreeSPath where asUniqueString=?", pathString);
+ if (list.size() == 0) {
+ return null;
+ } else {
+ return (TreeSPath) list.get(0);
+ }
+ }
+
+ public TreeSPath getOrCreate(TreeSPath pathTransient) {
+ TreeSPath path = getTreeSPath(pathTransient.getAsUniqueString());
+ if (path != null) {
+ return path;
+ } else {
+ create(pathTransient);
+ // TODO: optimize
+ return getTreeSPath(pathTransient.getAsUniqueString());
+ }
+
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/hibernate/structure/tree/TreeSRegistryDaoHibernate.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/hibernate/structure/tree/TreeSRegistryDaoHibernate.java
new file mode 100644
index 000000000..fab18a19d
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/hibernate/structure/tree/TreeSRegistryDaoHibernate.java
@@ -0,0 +1,133 @@
+package org.argeo.slc.hibernate.structure.tree;
+
+import java.util.List;
+
+import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.argeo.slc.core.structure.SimpleSElement;
+import org.argeo.slc.core.structure.StructureElement;
+import org.argeo.slc.core.structure.StructureRegistry;
+import org.argeo.slc.core.structure.tree.TreeSPath;
+import org.argeo.slc.core.structure.tree.TreeSRegistry;
+import org.argeo.slc.dao.structure.tree.TreeSPathDao;
+import org.argeo.slc.dao.structure.tree.TreeSRegistryDao;
+import org.hibernate.Session;
+
+/**
+ * The Hibernate implementation for tree-based structure registry.
+ *
+ * @see TreeSRegistry
+ */
+public class TreeSRegistryDaoHibernate extends HibernateDaoSupport implements
+ TreeSRegistryDao {
+
+ private TreeSPathDao treeSPathDao;
+
+ private static Log log = LogFactory.getLog(TreeSRegistryDaoHibernate.class);
+
+ public void create(TreeSRegistry registry) {
+ getHibernateTemplate().save(registry);
+ }
+
+ public void update(TreeSRegistry registryArg) {
+ Session session = getSession();
+ session.beginTransaction();
+ TreeSRegistry registry = (TreeSRegistry)session.merge(registryArg);
+ session.update(registry);
+ session.getTransaction().commit();
+ }
+
+ public TreeSRegistry getActiveTreeSRegistry() {
+ List> list = getHibernateTemplate().find(
+ "from TreeSRegistry where status=?",
+ TreeSRegistry.STATUS_ACTIVE);
+ if (list.size() == 0) {
+ return null;
+ } else {
+ return (TreeSRegistry) list.get(0);
+ }
+ }
+
+ public void syncPath(TreeSRegistry registryArg,
+ StructureRegistry localRegistry, TreeSPath pathArg) {
+ Session session = getSession();
+ session.beginTransaction();
+ TreeSRegistry registry = (TreeSRegistry)session.merge(registryArg);
+ TreeSPath path = (TreeSPath)session.merge(pathArg);
+ if (log.isTraceEnabled())
+ log.trace("Session#" + session.hashCode() + " " + session);
+ syncPathImpl(registry, localRegistry, path, session);
+ session.update(registry);
+ session.getTransaction().commit();
+ }
+
+ private void syncPathImpl(TreeSRegistry registry,
+ StructureRegistry localRegistry, TreeSPath path,
+ Session session) {
+ if (path.getParent() != null) {
+ TreeSPath parent = treeSPathDao.getOrCreate(path.getParent());
+ syncPathImpl(registry, localRegistry, parent, session);
+ }
+
+ if (log.isTraceEnabled())
+ log.trace("Synchronize path " + path);
+
+ if (registry.getElement(path) == null) {
+ final StructureElement element = getElement(registry,
+ localRegistry, path, session);
+ StructureElement elementPersisted = (StructureElement) session
+ .merge(element);
+ registry.register(path, elementPersisted);
+ // update(registry);
+
+ if (log.isTraceEnabled())
+ log.trace("No element in persisted structure for " + path
+ + ", merged to " + elementPersisted);
+ } else {
+ if (localRegistry != null) {
+ StructureElement element = getElement(registry, localRegistry,
+ path, session);
+
+ if (element != null) {
+ StructureElement elementPersisted = (StructureElement) session
+ .merge(element);
+ registry.register(path, elementPersisted);
+ // update(registry);
+ if (log.isTraceEnabled())
+ log
+ .trace("Update existing element in persisted structure for "
+ + path
+ + ", merged to "
+ + elementPersisted);
+ }
+ }
+ }
+
+ }
+
+ public void setTreeSPathDao(TreeSPathDao treeSPathDao) {
+ this.treeSPathDao = treeSPathDao;
+ }
+
+ protected StructureElement getElement(TreeSRegistry registry,
+ StructureRegistry localRegistry, TreeSPath path,
+ Session session) {
+ StructureElement element;
+ if (localRegistry != null) {
+ element = localRegistry.getElement(path);
+ if (session.getSessionFactory()
+ .getClassMetadata(element.getClass()) == null) {
+ if (log.isTraceEnabled())
+ log.trace("Replace non-hibernate element " + element
+ + " by a simple element.");
+ element = new SimpleSElement(element.getLabel());
+ }
+ } else {
+ element = new SimpleSElement(path.getName());
+ }
+ return element;
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/hibernate/structure/tree/package.html b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/hibernate/structure/tree/package.html
new file mode 100644
index 000000000..9b5cfa237
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/hibernate/structure/tree/package.html
@@ -0,0 +1,6 @@
+
+
+
+Hibernate based DAO implementations for tree-based structure objects.
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/hibernate/test/TestRunDescriptorDaoHibernate.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/hibernate/test/TestRunDescriptorDaoHibernate.java
new file mode 100644
index 000000000..49162d529
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/hibernate/test/TestRunDescriptorDaoHibernate.java
@@ -0,0 +1,20 @@
+package org.argeo.slc.hibernate.test;
+
+import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
+
+import org.argeo.slc.core.test.TestRunDescriptor;
+import org.argeo.slc.dao.test.TestRunDescriptorDao;
+
+public class TestRunDescriptorDaoHibernate extends HibernateDaoSupport
+ implements TestRunDescriptorDao {
+
+ public TestRunDescriptor getTestRunDescriptor(String id) {
+ return (TestRunDescriptor) getHibernateTemplate().get(
+ TestRunDescriptor.class, id);
+ }
+
+ public void saveOrUpdate(TestRunDescriptor testRunDescriptor) {
+ getHibernateTemplate().saveOrUpdate(testRunDescriptor);
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/hibernate/test/tree/TestResultDaoHibernate.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/hibernate/test/tree/TestResultDaoHibernate.java
new file mode 100644
index 000000000..681a707f1
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/hibernate/test/tree/TestResultDaoHibernate.java
@@ -0,0 +1,68 @@
+package org.argeo.slc.hibernate.test.tree;
+
+import java.util.Date;
+import java.util.List;
+
+import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
+
+import org.argeo.slc.core.SlcException;
+import org.argeo.slc.core.structure.tree.TreeSPath;
+import org.argeo.slc.core.test.NumericTRId;
+import org.argeo.slc.core.test.TestResult;
+import org.argeo.slc.core.test.TestResultId;
+import org.argeo.slc.core.test.tree.TreeTestResult;
+import org.argeo.slc.dao.test.tree.TreeTestResultDao;
+
+/**
+ * The Hibernate implementation for tree-based result of the test result dao.
+ *
+ * @see TreeTestResult
+ */
+public class TestResultDaoHibernate extends HibernateDaoSupport implements
+ TreeTestResultDao {
+
+ public void create(TestResult testResult) {
+ getHibernateTemplate().save(testResult);
+ }
+
+ public void update(TestResult testResult) {
+ getHibernateTemplate().saveOrUpdate(testResult);
+ }
+
+ public TreeTestResult getTestResult(String uuid) {
+ List> list = getHibernateTemplate().find(
+ "from TreeTestResult where uuid=?", uuid);
+ if (list.size() == 0) {
+ return null;
+ } else {
+ return (TreeTestResult) list.get(0);
+ }
+
+ }
+
+ public List listTestResults() {
+ return (List) getHibernateTemplate().find(
+ "from TreeTestResult");
+ }
+
+ public List listResults(TreeSPath path) {
+ List list = getHibernateTemplate().find(
+ "from TreeTestResult res where ? in indices(res.resultParts)",
+ path.getAsUniqueString());
+ return list;
+ }
+
+ public void close(String id, Date closeDate) {
+// TreeTestResult ttr = (TreeTestResult) getHibernateTemplate().load(
+// TreeTestResult.class, id);
+ TreeTestResult ttr = getTestResult(id);
+ if (ttr != null) {
+ ttr.setCloseDate(closeDate);
+ getHibernateTemplate().update(ttr);
+ } else {
+ throw new SlcException("Result with id " + id
+ + " could not be closed because it was not found.");
+ }
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/hibernate/test/tree/TreeTestResultCollectionDaoHibernate.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/hibernate/test/tree/TreeTestResultCollectionDaoHibernate.java
new file mode 100644
index 000000000..b08072058
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/hibernate/test/tree/TreeTestResultCollectionDaoHibernate.java
@@ -0,0 +1,32 @@
+package org.argeo.slc.hibernate.test.tree;
+
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
+
+import org.argeo.slc.core.test.tree.TreeTestResultCollection;
+import org.argeo.slc.dao.test.tree.TreeTestResultCollectionDao;
+
+public class TreeTestResultCollectionDaoHibernate extends HibernateDaoSupport
+ implements TreeTestResultCollectionDao {
+
+ public void create(TreeTestResultCollection ttrCollection) {
+ getHibernateTemplate().save(ttrCollection);
+ }
+
+ public TreeTestResultCollection getTestResultCollection(String id) {
+ return (TreeTestResultCollection) getHibernateTemplate().get(
+ TreeTestResultCollection.class, id);
+ }
+
+ public void update(TreeTestResultCollection ttrCollection) {
+ getHibernateTemplate().update(ttrCollection);
+ }
+
+ public SortedSet listCollections() {
+ return new TreeSet(getHibernateTemplate()
+ .find("from TreeTestResultCollection"));
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/hibernate/test/tree/package.html b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/hibernate/test/tree/package.html
new file mode 100644
index 000000000..6042b0789
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/hibernate/test/tree/package.html
@@ -0,0 +1,6 @@
+
+
+
+Hibernate based DAO implementations for tree-based SLC Test.
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/maven/MavenFile.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/maven/MavenFile.java
new file mode 100644
index 000000000..31c6385a6
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/maven/MavenFile.java
@@ -0,0 +1,63 @@
+package org.argeo.slc.maven;
+
+import org.argeo.slc.core.build.Distribution;
+import org.argeo.slc.core.deploy.DeploymentData;
+
+public class MavenFile implements Distribution, DeploymentData {
+ private String groupId;
+ private String artifactId;
+ private String version;
+ private String type;
+ private String classifier;
+
+ private String distributionId;
+
+ public String getDistributionId() {
+ return distributionId;
+ }
+
+ public void setDistributionId(String distributionId) {
+ this.distributionId = distributionId;
+ }
+
+ public String getGroupId() {
+ return groupId;
+ }
+
+ public void setGroupId(String groupId) {
+ this.groupId = groupId;
+ }
+
+ public String getArtifactId() {
+ return artifactId;
+ }
+
+ public void setArtifactId(String artifactId) {
+ this.artifactId = artifactId;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getClassifier() {
+ return classifier;
+ }
+
+ public void setClassifier(String classifier) {
+ this.classifier = classifier;
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/maven/MavenManager.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/maven/MavenManager.java
new file mode 100644
index 000000000..3a07e227a
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/maven/MavenManager.java
@@ -0,0 +1,105 @@
+package org.argeo.slc.maven;
+
+import java.io.File;
+import java.util.List;
+import java.util.Vector;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.embedder.MavenEmbedder;
+import org.apache.maven.embedder.MavenEmbedderException;
+
+import org.argeo.slc.core.SlcException;
+
+public class MavenManager {
+ private final Log log = LogFactory.getLog(getClass());
+
+ private String repositoryId;
+ private String repositoryUrl;
+ private String localRepositoryPath;
+
+ private ArtifactRepository localRepository;
+ private List remoteRepositories;
+
+ private MavenEmbedder mavenEmbedder;
+
+ public void init() {
+ try {
+ mavenEmbedder = new MavenEmbedder();
+ mavenEmbedder.setOffline(true);
+ mavenEmbedder.setClassLoader(Thread.currentThread()
+ .getContextClassLoader());
+ mavenEmbedder.start();
+
+ mavenEmbedder.setLocalRepositoryDirectory(new File(
+ localRepositoryPath));
+
+ localRepository = mavenEmbedder.getLocalRepository();
+
+ // localRepository = mavenEmbedder.createLocalRepository(new File(
+ // localRepositoryPath));
+
+ ArtifactRepository repository = mavenEmbedder.createRepository(
+ repositoryUrl, repositoryId);
+
+ remoteRepositories = new Vector();
+ remoteRepositories.add(repository);
+ } catch (Exception e) {
+ throw new SlcException("Cannot initialize Maven manager", e);
+ }
+ }
+
+ private Artifact resolve(MavenFile mavenDistribution) {
+ try {
+ Artifact artifact;
+ if (mavenDistribution.getClassifier() == null) {
+ artifact = mavenEmbedder.createArtifact(mavenDistribution
+ .getGroupId(), mavenDistribution.getArtifactId(),
+ mavenDistribution.getVersion(),
+ Artifact.SCOPE_PROVIDED, mavenDistribution.getType());
+ } else {
+ artifact = mavenEmbedder.createArtifactWithClassifier(
+ mavenDistribution.getGroupId(), mavenDistribution
+ .getArtifactId(), mavenDistribution
+ .getVersion(), mavenDistribution.getType(),
+ mavenDistribution.getClassifier());
+ }
+
+ mavenEmbedder
+ .resolve(artifact, remoteRepositories, localRepository);
+
+ return artifact;
+ } catch (Exception e) {
+ throw new SlcException("Cannot resolve artifact.", e);
+ }
+ }
+
+ public File getPackageLocation(MavenFile mavenDistribution) {
+ return resolve(mavenDistribution).getFile();
+ }
+
+ public void destroy() {
+ try {
+ if (mavenEmbedder != null) {
+ mavenEmbedder.stop();
+ }
+ } catch (MavenEmbedderException e) {
+ log.error("Cannot destroy Maven manager", e);
+ }
+ }
+
+ public void setRepositoryId(String repositoryId) {
+ this.repositoryId = repositoryId;
+ }
+
+ public void setRepositoryUrl(String repositoryUrl) {
+ this.repositoryUrl = repositoryUrl;
+ }
+
+ public void setLocalRepositoryPath(String localRepositoryPath) {
+ this.localRepositoryPath = localRepositoryPath;
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/msg/process/SlcExecutionRequest.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/msg/process/SlcExecutionRequest.java
new file mode 100644
index 000000000..84d582681
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/msg/process/SlcExecutionRequest.java
@@ -0,0 +1,16 @@
+package org.argeo.slc.msg.process;
+
+import org.argeo.slc.core.process.SlcExecution;
+
+public class SlcExecutionRequest {
+ private SlcExecution slcExecution;
+
+ public SlcExecution getSlcExecution() {
+ return slcExecution;
+ }
+
+ public void setSlcExecution(SlcExecution slcExecution) {
+ this.slcExecution = slcExecution;
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/msg/process/SlcExecutionStatusRequest.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/msg/process/SlcExecutionStatusRequest.java
new file mode 100644
index 000000000..78afc830f
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/msg/process/SlcExecutionStatusRequest.java
@@ -0,0 +1,30 @@
+package org.argeo.slc.msg.process;
+
+public class SlcExecutionStatusRequest {
+ private String slcExecutionUuid;
+ private String newStatus;
+
+ public SlcExecutionStatusRequest() {
+ }
+
+ public SlcExecutionStatusRequest(String slcExecutionUuid, String newStatus) {
+ this.slcExecutionUuid = slcExecutionUuid;
+ this.newStatus = newStatus;
+ }
+
+ public String getSlcExecutionUuid() {
+ return slcExecutionUuid;
+ }
+
+ public void setSlcExecutionUuid(String slcExecutionUuid) {
+ this.slcExecutionUuid = slcExecutionUuid;
+ }
+
+ public String getNewStatus() {
+ return newStatus;
+ }
+
+ public void setNewStatus(String newStatus) {
+ this.newStatus = newStatus;
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/msg/process/SlcExecutionStepsRequest.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/msg/process/SlcExecutionStepsRequest.java
new file mode 100644
index 000000000..237f05f87
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/msg/process/SlcExecutionStepsRequest.java
@@ -0,0 +1,31 @@
+package org.argeo.slc.msg.process;
+
+import java.util.List;
+import java.util.Vector;
+
+import org.argeo.slc.core.process.SlcExecutionStep;
+
+public class SlcExecutionStepsRequest {
+ private String slcExecutionUuid;
+ private List steps = new Vector();
+
+ public String getSlcExecutionUuid() {
+ return slcExecutionUuid;
+ }
+
+ public void setSlcExecutionUuid(String slcExecutionUuid) {
+ this.slcExecutionUuid = slcExecutionUuid;
+ }
+
+ public List getSteps() {
+ return steps;
+ }
+
+ public void setSteps(List step) {
+ this.steps = step;
+ }
+
+ public void addStep(SlcExecutionStep step) {
+ steps.add(step);
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/msg/test/tree/CloseTreeTestResultRequest.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/msg/test/tree/CloseTreeTestResultRequest.java
new file mode 100644
index 000000000..c0b74e36e
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/msg/test/tree/CloseTreeTestResultRequest.java
@@ -0,0 +1,41 @@
+package org.argeo.slc.msg.test.tree;
+
+import java.util.Date;
+
+import org.argeo.slc.core.test.tree.TreeTestResult;
+
+public class CloseTreeTestResultRequest {
+ private String resultUuid;
+ private Date closeDate;
+
+ public CloseTreeTestResultRequest() {
+
+ }
+
+ public CloseTreeTestResultRequest(String resultUuid, Date closeDate) {
+ this.resultUuid = resultUuid;
+ this.closeDate = closeDate;
+ }
+
+ public CloseTreeTestResultRequest(TreeTestResult ttr) {
+ this.resultUuid = ttr.getUuid();
+ this.closeDate = ttr.getCloseDate();
+ }
+
+ public String getResultUuid() {
+ return resultUuid;
+ }
+
+ public void setResultUuid(String id) {
+ this.resultUuid = id;
+ }
+
+ public Date getCloseDate() {
+ return closeDate;
+ }
+
+ public void setCloseDate(Date closeDate) {
+ this.closeDate = closeDate;
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/msg/test/tree/CreateTreeTestResultRequest.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/msg/test/tree/CreateTreeTestResultRequest.java
new file mode 100644
index 000000000..0a7af822b
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/msg/test/tree/CreateTreeTestResultRequest.java
@@ -0,0 +1,23 @@
+package org.argeo.slc.msg.test.tree;
+
+import org.argeo.slc.core.test.tree.TreeTestResult;
+
+public class CreateTreeTestResultRequest {
+ private TreeTestResult treeTestResult;
+
+ public CreateTreeTestResultRequest() {
+
+ }
+
+ public CreateTreeTestResultRequest(TreeTestResult treeTestResult) {
+ this.treeTestResult = treeTestResult;
+ }
+
+ public TreeTestResult getTreeTestResult() {
+ return treeTestResult;
+ }
+
+ public void setTreeTestResult(TreeTestResult treeTestResult) {
+ this.treeTestResult = treeTestResult;
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/msg/test/tree/ResultPartRequest.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/msg/test/tree/ResultPartRequest.java
new file mode 100644
index 000000000..ac0908711
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/msg/test/tree/ResultPartRequest.java
@@ -0,0 +1,93 @@
+package org.argeo.slc.msg.test.tree;
+
+import java.util.Map;
+
+import org.argeo.slc.core.SlcException;
+import org.argeo.slc.core.process.SlcExecution;
+import org.argeo.slc.core.structure.StructureElement;
+import org.argeo.slc.core.structure.tree.TreeSPath;
+import org.argeo.slc.core.test.SimpleResultPart;
+import org.argeo.slc.core.test.TestRunDescriptor;
+import org.argeo.slc.core.test.tree.PartSubList;
+import org.argeo.slc.core.test.tree.TreeTestResult;
+
+public class ResultPartRequest {
+ private String resultUuid;
+ private SimpleResultPart resultPart;
+ private TreeSPath path;
+ private Map relatedElements;
+ private TestRunDescriptor testRunDescriptor;
+
+ public ResultPartRequest() {
+
+ }
+
+ public ResultPartRequest(TreeTestResult ttr, TreeSPath path,
+ SimpleResultPart resultPart) {
+ resultUuid = ttr.getUuid();
+ this.resultPart = resultPart;
+ this.path = path;
+ relatedElements = ttr.getRelatedElements(path);
+ if (ttr.getCurrentTestRun() != null)
+ testRunDescriptor = new TestRunDescriptor(ttr.getCurrentTestRun());
+ }
+
+ public ResultPartRequest(TreeTestResult ttr) {
+ resultUuid = ttr.getUuid();
+ this.path = ttr.getCurrentPath();
+
+ PartSubList lst = ttr.getResultParts().get(path);
+ if (lst.getParts().size() < 1) {
+ throw new SlcException("Cannot find part for path " + path
+ + " in result " + resultUuid);
+ }
+
+ this.resultPart = (SimpleResultPart) lst.getParts().get(
+ lst.getParts().size() - 1);
+ relatedElements = ttr.getRelatedElements(path);
+ if (ttr.getCurrentTestRun() != null)
+ testRunDescriptor = new TestRunDescriptor(ttr.getCurrentTestRun());
+ }
+
+ public String getResultUuid() {
+ return resultUuid;
+ }
+
+ public void setResultUuid(String resultUuid) {
+ this.resultUuid = resultUuid;
+ }
+
+ public SimpleResultPart getResultPart() {
+ return resultPart;
+ }
+
+ public void setResultPart(SimpleResultPart resultPart) {
+ this.resultPart = resultPart;
+ }
+
+ public TreeSPath getPath() {
+ return path;
+ }
+
+ public void setPath(TreeSPath path) {
+ this.path = path;
+ }
+
+ public TestRunDescriptor getTestRunDescriptor() {
+ return testRunDescriptor;
+ }
+
+ public void setTestRunDescriptor(TestRunDescriptor testRunDescriptor) {
+ this.testRunDescriptor = testRunDescriptor;
+ }
+
+ public Map getRelatedElements() {
+ return relatedElements;
+ }
+
+ public void setRelatedElements(
+ Map relatedElements) {
+ this.relatedElements = relatedElements;
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/spring/SpringUtils.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/spring/SpringUtils.java
new file mode 100644
index 000000000..fc9b65686
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/spring/SpringUtils.java
@@ -0,0 +1,21 @@
+package org.argeo.slc.spring;
+
+import java.util.Map;
+
+import org.springframework.beans.factory.ListableBeanFactory;
+
+public class SpringUtils {
+ public static T loadSingleFromContext(ListableBeanFactory context,
+ Class clss) {
+ Map beans = context.getBeansOfType(clss);
+ if (beans.size() == 1) {
+ return beans.values().iterator().next();
+ } else {
+ return null;
+ }
+ }
+
+ private SpringUtils() {
+
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/support/deploy/ApacheHttpdServer.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/support/deploy/ApacheHttpdServer.java
new file mode 100644
index 000000000..6d77cdd51
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/support/deploy/ApacheHttpdServer.java
@@ -0,0 +1,47 @@
+package org.argeo.slc.support.deploy;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+
+import org.argeo.slc.core.SlcException;
+import org.argeo.slc.core.build.Distribution;
+import org.springframework.core.io.Resource;
+
+public class ApacheHttpdServer implements WebServer {
+ private Resource baseUrlRes;
+ private File baseLocation;
+
+ public URL getBaseUrl() {
+ try {
+ return baseUrlRes.getURL();
+ } catch (IOException e) {
+ throw new SlcException("Cannot get url from "+baseUrlRes,e);
+ }
+ }
+
+ public void setBaseUrlRes(Resource baseUrlRes){
+ this.baseUrlRes = baseUrlRes;
+ }
+
+
+
+ public File getBaseLocation() {
+ return baseLocation;
+ }
+
+ public void setBaseLocation(File baseLocation) {
+ this.baseLocation = baseLocation;
+ }
+
+ public String getDeployedSystemId() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public Distribution getDistribution() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/support/deploy/BasicDeployEnvironment.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/support/deploy/BasicDeployEnvironment.java
new file mode 100644
index 000000000..60dfea024
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/support/deploy/BasicDeployEnvironment.java
@@ -0,0 +1,75 @@
+package org.argeo.slc.support.deploy;
+
+import java.io.File;
+import java.net.URL;
+import java.util.Map;
+import java.util.Properties;
+import java.util.UUID;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.ant.AntRegistryUtil;
+import org.argeo.slc.core.SlcException;
+import org.argeo.slc.core.deploy.DeployEnvironment;
+import org.argeo.slc.maven.MavenFile;
+import org.argeo.slc.maven.MavenManager;
+
+public class BasicDeployEnvironment implements DeployEnvironment {
+ private static final Log log = LogFactory
+ .getLog(BasicDeployEnvironment.class);
+ private MavenManager mavenManager;
+
+ public void unpackTo(Object packg, File targetLocation,
+ Map filter) {
+ File packageLocation;
+ String type = null;
+ String removeRootDir = "enabled";
+ if (packg instanceof MavenFile) {
+ packageLocation = mavenManager
+ .getPackageLocation((MavenFile) packg);
+ type = ((MavenFile) packg).getType();
+ } else if (packg instanceof File) {
+ packageLocation = (File) packg;
+ // TODO: type based on extension
+ } else {
+ throw new SlcException("Unrecognized package type "
+ + packg.getClass());
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("Unpack " + packageLocation + " of type " + type + " to "
+ + targetLocation);
+ }
+
+ try {
+ File tempDir = new File("/tmp/"+UUID.randomUUID().toString());
+ tempDir.mkdirs();
+ targetLocation.mkdirs();
+ Properties props = new Properties();
+ props.setProperty("dest", targetLocation.getAbsolutePath());
+ props.setProperty("src", packageLocation.getAbsolutePath());
+ props.setProperty("tempDir", tempDir.getAbsolutePath());
+ props.setProperty("removeRootDir", removeRootDir);
+
+ URL antUrl = getClass().getClassLoader().getResource(
+ "org/argeo/slc/support/deploy/ant/build.xml");
+
+ if (type == null || type.equals("zip")) {
+ AntRegistryUtil.runAll(antUrl, "deployZip", props);
+ } else if (type.equals("tar.gz")) {
+ AntRegistryUtil.runAll(antUrl, "deployTarGz", props);
+ } else {
+ throw new SlcException("Unknow package type " + type);
+ }
+ } catch (SlcException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new SlcException("Cannot unpack package " + packg + " to "
+ + targetLocation, e);
+ }
+ }
+
+ public void setMavenManager(MavenManager mavenManager) {
+ this.mavenManager = mavenManager;
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/support/deploy/HttpdApplicationDeployment.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/support/deploy/HttpdApplicationDeployment.java
new file mode 100644
index 000000000..79eb0bd4f
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/support/deploy/HttpdApplicationDeployment.java
@@ -0,0 +1,79 @@
+package org.argeo.slc.support.deploy;
+
+import java.io.File;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.core.SlcException;
+import org.argeo.slc.core.build.Distribution;
+import org.argeo.slc.core.deploy.DeployEnvironment;
+import org.argeo.slc.core.deploy.DeployedSystem;
+import org.argeo.slc.core.deploy.DeploymentData;
+import org.argeo.slc.core.deploy.ExecutableDeployment;
+import org.argeo.slc.core.deploy.TargetData;
+
+public class HttpdApplicationDeployment implements ExecutableDeployment {
+ private static final Log log = LogFactory
+ .getLog(HttpdApplicationDeployment.class);
+
+ private HttpdApplicationTargetData targetData;
+ private DeploymentData deploymentData;
+ private SimpleHttpdApplication deployedSystem;
+ private Distribution distribution;
+
+ private DeployEnvironment deployEnvironment;
+
+ public void execute() {
+ try {
+ deployEnvironment.unpackTo(getDistribution(), targetData
+ .getTargetRootLocation(), null);
+
+ // FIXME: make it generic
+ String deployDataPath = targetData.getTargetRootLocation()
+ .getCanonicalPath();
+
+ deployEnvironment.unpackTo(getDeploymentData(), new File(
+ deployDataPath), null);
+ deployedSystem = new SimpleHttpdApplication();
+ deployedSystem.setTargetData(targetData);
+
+ } catch (Exception e) {
+ throw new SlcException("Cannot deploy " + deploymentData + " to "
+ + targetData, e);
+ }
+
+ }
+
+ public void setTargetData(TargetData targetData) {
+ this.targetData = (HttpdApplicationTargetData) targetData;
+ }
+
+ public void setDeploymentData(DeploymentData deploymentData) {
+ this.deploymentData = deploymentData;
+ }
+
+ public DeployedSystem getDeployedSystem() {
+ return deployedSystem;
+ }
+
+ public DeploymentData getDeploymentData() {
+ return deploymentData;
+ }
+
+ public TargetData getTargetData() {
+ return targetData;
+ }
+
+ public Distribution getDistribution() {
+ return distribution;
+ }
+
+ public void setDistribution(Distribution distribution) {
+ this.distribution = distribution;
+ }
+
+ public void setDeployEnvironment(DeployEnvironment deployEnvironment) {
+ this.deployEnvironment = deployEnvironment;
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/support/deploy/HttpdApplicationTargetData.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/support/deploy/HttpdApplicationTargetData.java
new file mode 100644
index 000000000..7097289ec
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/support/deploy/HttpdApplicationTargetData.java
@@ -0,0 +1,44 @@
+package org.argeo.slc.support.deploy;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.argeo.slc.core.SlcException;
+import org.argeo.slc.core.deploy.TargetData;
+
+public class HttpdApplicationTargetData implements TargetData {
+ private ApacheHttpdServer webServer;
+ private String relativePath;
+
+ public ApacheHttpdServer getWebServer() {
+ return webServer;
+ }
+
+ public void setWebServer(ApacheHttpdServer webServer) {
+ this.webServer = webServer;
+ }
+
+ public String getRelativePath() {
+ return relativePath;
+ }
+
+ public void setRelativePath(String relativePath) {
+ this.relativePath = relativePath;
+ }
+
+ public URL getTargetBaseUrl() {
+ try {
+ URL wsUrl = getWebServer().getBaseUrl();
+ return new URL(wsUrl, wsUrl.getFile() + '/' + relativePath);
+ } catch (MalformedURLException e) {
+ throw new SlcException("Cannot get base url for " + relativePath, e);
+ }
+ }
+
+ public File getTargetRootLocation() {
+ return new File(getWebServer().getBaseLocation().getPath()
+ + File.separator + getRelativePath());
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/support/deploy/SimpleHttpdApplication.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/support/deploy/SimpleHttpdApplication.java
new file mode 100644
index 000000000..bb98c383f
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/support/deploy/SimpleHttpdApplication.java
@@ -0,0 +1,41 @@
+package org.argeo.slc.support.deploy;
+
+import java.io.File;
+import java.net.URL;
+
+import org.argeo.slc.core.build.Distribution;
+
+public class SimpleHttpdApplication implements WebApplication {
+ private HttpdApplicationTargetData targetData;
+ private Distribution distribution;
+
+ public void setDistribution(Distribution distribution) {
+ this.distribution = distribution;
+ }
+
+ public URL getBaseUrl() {
+ return targetData.getTargetBaseUrl();
+ }
+
+ public File getRootLocation() {
+ return targetData.getTargetRootLocation();
+ }
+
+ public String getDeployedSystemId() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public HttpdApplicationTargetData getTargetData() {
+ return targetData;
+ }
+
+ public void setTargetData(HttpdApplicationTargetData targetData) {
+ this.targetData = targetData;
+ }
+
+ public Distribution getDistribution() {
+ return distribution;
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/support/deploy/WebApplication.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/support/deploy/WebApplication.java
new file mode 100644
index 000000000..da0b1129e
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/support/deploy/WebApplication.java
@@ -0,0 +1,11 @@
+package org.argeo.slc.support.deploy;
+
+import java.io.File;
+import java.net.URL;
+
+import org.argeo.slc.core.deploy.DeployedSystem;
+
+public interface WebApplication extends DeployedSystem{
+ public URL getBaseUrl();
+ public File getRootLocation();
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/support/deploy/WebServer.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/support/deploy/WebServer.java
new file mode 100644
index 000000000..fc747bc94
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/support/deploy/WebServer.java
@@ -0,0 +1,9 @@
+package org.argeo.slc.support.deploy;
+
+import java.net.URL;
+
+import org.argeo.slc.core.deploy.DeployedSystem;
+
+public interface WebServer extends DeployedSystem {
+ public URL getBaseUrl();
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/unit/AbstractSpringTestCase.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/unit/AbstractSpringTestCase.java
new file mode 100644
index 000000000..4ad916d57
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/unit/AbstractSpringTestCase.java
@@ -0,0 +1,64 @@
+package org.argeo.slc.unit;
+
+import junit.framework.TestCase;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.argeo.slc.core.SlcException;
+import org.argeo.slc.spring.SpringUtils;
+
+/** Helper for tests using a Spring application co,text. */
+public abstract class AbstractSpringTestCase extends TestCase {
+ protected final Log log = LogFactory.getLog(getClass());
+ private ApplicationContext context;
+
+ /**
+ * Gets (and create if necessary) the application context to use. Default
+ * implementation uses a class path xml application context and calls
+ * {@link #getApplicationContextLocation()}.
+ */
+ protected ApplicationContext getContext() {
+ if (context == null) {
+ context = new ClassPathXmlApplicationContext(
+ getApplicationContextLocation());
+ }
+ return context;
+ }
+
+ /** Returns a bean from the underlying context */
+ protected T getBean(String beanId) {
+ return (T) getContext().getBean(beanId);
+ }
+
+ protected T getBean(Class extends T> clss) {
+ T bean = SpringUtils.loadSingleFromContext(getContext(), clss);
+ if (bean == null) {
+ throw new SlcException("Cannot retrieve a unique bean of type "
+ + clss);
+ } else {
+ return bean;
+ }
+ }
+
+ /**
+ * Th location of the application to load. The default implementation
+ * returns applicationContext.xml found in the same package as the
+ * test.
+ */
+ protected String getApplicationContextLocation() {
+ return inPackage("applicationContext.xml");
+ }
+
+ /**
+ * Prefixes the package of the class after converting the '.' to '/' in
+ * order to have a resource path.
+ */
+ protected String inPackage(String suffix) {
+ String prefix = getClass().getPackage().getName().replace('.', '/');
+ return prefix + '/' + suffix;
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/unit/DbModel.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/unit/DbModel.java
new file mode 100644
index 000000000..504dffedd
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/unit/DbModel.java
@@ -0,0 +1,47 @@
+package org.argeo.slc.unit;
+
+import java.sql.Connection;
+import java.util.List;
+import java.util.Properties;
+
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.tool.hbm2ddl.SchemaExport;
+
+/**
+ * Creates a relational data model from Hibernate mapping files. The benefit of
+ * this class is to be able to use Hibernate to have test data which are
+ * independent from the type of database used.
+ */
+public class DbModel {
+ private String dialect;
+ private List mappings;
+
+ /** Sets the Hibernate dialect to use. */
+ public void setDialect(String dialect) {
+ this.dialect = dialect;
+ }
+
+ /** Sets the list of mappings to consider. */
+ public void setMappings(List mappings) {
+ this.mappings = mappings;
+ }
+
+ /**
+ * Creates an Hibernate schema export tool, in order to create the
+ * underlying datamodel.
+ */
+ public SchemaExport createSchemaExport(Connection connection) {
+ Configuration configuration = new Configuration();
+ Properties properties = new Properties();
+ properties.setProperty(Environment.DIALECT, dialect);
+ properties.setProperty(Environment.HBM2DDL_AUTO, "create");
+ configuration.setProperties(properties);
+
+ for (String mapping : mappings) {
+ configuration.addResource(mapping.trim());
+ }
+
+ return new SchemaExport(configuration, connection);
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/unit/IndependentDbTestCase.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/unit/IndependentDbTestCase.java
new file mode 100644
index 000000000..bd6b2f993
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/unit/IndependentDbTestCase.java
@@ -0,0 +1,169 @@
+package org.argeo.slc.unit;
+
+import java.io.InputStream;
+import java.sql.SQLException;
+
+import javax.sql.DataSource;
+
+import org.dbunit.DataSourceDatabaseTester;
+import org.dbunit.DatabaseUnitException;
+import org.dbunit.IDatabaseTester;
+import org.dbunit.database.IDatabaseConnection;
+import org.dbunit.dataset.IDataSet;
+import org.dbunit.dataset.ReplacementDataSet;
+import org.dbunit.dataset.xml.FlatXmlDataSet;
+import org.dbunit.operation.DatabaseOperation;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+
+import org.apache.commons.io.IOUtils;
+
+import org.hibernate.tool.hbm2ddl.SchemaExport;
+
+import org.argeo.slc.core.SlcException;
+
+/**
+ * Helper to make db vendor independent tests using DbUnit data sets. Based on
+ * {@link DbModel}.
+ */
+public abstract class IndependentDbTestCase extends AbstractSpringTestCase {
+ private IDatabaseTester databaseTester;
+
+ /** Creates the DDL of the data model and loads the data. */
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ databaseTester = new DataSourceDatabaseTester(getDataSource());
+ databaseTester.setSetUpOperation(new DatabaseOperation() {
+
+ @Override
+ public void execute(IDatabaseConnection connection, IDataSet dataSet)
+ throws DatabaseUnitException, SQLException {
+ DbModel dbModel = getDbModel();
+ SchemaExport schemaExport = dbModel
+ .createSchemaExport(connection.getConnection());
+ schemaExport.create(true, true);
+
+ DatabaseOperation.INSERT.execute(connection, dataSet);
+ }
+
+ });
+ databaseTester.setDataSet(createDataSet());
+ databaseTester.onSetup();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ if (databaseTester != null) {
+ databaseTester.onTearDown();
+ }
+ super.tearDown();
+ }
+
+ /**
+ * The data source to use. The default implementation returns a bean named
+ * {@link #getDataSourceBeanName}
+ */
+ protected DataSource getDataSource() {
+ return (DataSource) getContext().getBean(getDataSourceBeanName());
+ }
+
+ /**
+ * The name of the data source bean to use. The default implementation
+ * returns dataSource.
+ */
+ protected String getDataSourceBeanName() {
+ return "slcDefault.dataSource.inMemoryTestHSQL";
+ }
+
+ /**
+ * Creates the data set to use. The default implementation creates a
+ * FlatXmlDataSet
load from the resource defined in
+ * {@link #getDataSetResource()}
+ */
+ protected IDataSet createDataSet() {
+ InputStream in = null;
+ try {
+ in = getDataSetResource().getInputStream();
+ String[] replaceStrings = getReplacementStrings();
+ IDataSet dataSet;
+ if (replaceStrings.length == 0) {
+ dataSet = new FlatXmlDataSet(in);
+ } else {
+ dataSet = new ReplacementDataSet(new FlatXmlDataSet(in));
+ for (String str : replaceStrings) {
+ replace((ReplacementDataSet) dataSet, str);
+ }
+ }
+ return dataSet;
+ } catch (Exception e) {
+ throw new SlcException("Cannot create data set", e);
+ } finally {
+ IOUtils.closeQuietly(in);
+ }
+ }
+
+ /**
+ * To be overridden. Return an empty array by default.
+ *
+ * @return the array of strings to replace in the dataset
+ */
+ protected String[] getReplacementStrings() {
+ return new String[0];
+ }
+
+ /**
+ * Set the object replacing the given string. To be overridden. Does nothing
+ * by default.
+ */
+ protected void replace(ReplacementDataSet dataSet, String str)
+ throws Exception {
+
+ }
+
+ /**
+ * Replace the given string by the content of the resource with the same
+ * name in the same package, as a byte array.
+ */
+ protected void replaceByRessource(ReplacementDataSet dataSet, String str)
+ throws Exception {
+ Resource zipResource = new ClassPathResource(inPackage(str));
+
+ dataSet.addReplacementObject(str, IOUtils.toByteArray(zipResource
+ .getInputStream()));
+ }
+
+ /**
+ * The resource of the data set to load. The default implementation loads a
+ * ClassPathResource
located at
+ * {@link #getDataSetResourceLocation()}.
+ */
+ protected Resource getDataSetResource() {
+ return new ClassPathResource(getDataSetResourceLocation());
+ }
+
+ /**
+ * The location of the data set to load. The default implementation loads
+ * dataSet.xml found in the same package as the test.
+ */
+ protected String getDataSetResourceLocation() {
+ return inPackage("dataSet.xml");
+ }
+
+ /**
+ * The DB model to us to create the DDL of the testes database. The default
+ * implementation loads a bean named after {@link #getDbModelBeanName()}.
+ */
+ protected DbModel getDbModel() {
+ return (DbModel) getContext().getBean(getDbModelBeanName());
+ }
+
+ /**
+ * The name of the bean to load. The default implementation returns
+ * dbModel.
+ */
+ protected String getDbModelBeanName() {
+ return "dbModel";
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/unit/UnitUtils.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/unit/UnitUtils.java
new file mode 100644
index 000000000..e88deed01
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/unit/UnitUtils.java
@@ -0,0 +1,42 @@
+package org.argeo.slc.unit;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertNotNull;
+
+public abstract class UnitUtils {
+ public static void assertDateSec(Date expected, Date reached) {
+ if (expected == null) {
+ assertNull(reached);
+ return;
+ } else {
+ assertNotNull(reached);
+ }
+
+ Calendar expectedCal = new GregorianCalendar();
+ expectedCal.setTime(expected);
+ Calendar reachedCal = new GregorianCalendar();
+ reachedCal.setTime(reached);
+ assertEquals(expectedCal.get(Calendar.YEAR), reachedCal
+ .get(Calendar.YEAR));
+ assertEquals(expectedCal.get(Calendar.MONTH), reachedCal
+ .get(Calendar.MONTH));
+ assertEquals(expectedCal.get(Calendar.DATE), reachedCal
+ .get(Calendar.DATE));
+ assertEquals(expectedCal.get(Calendar.HOUR_OF_DAY), reachedCal
+ .get(Calendar.HOUR_OF_DAY));
+ assertEquals(expectedCal.get(Calendar.MINUTE), reachedCal
+ .get(Calendar.MINUTE));
+ assertEquals(expectedCal.get(Calendar.SECOND), reachedCal
+ .get(Calendar.SECOND));
+ }
+
+ private UnitUtils() {
+
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/unit/UnitXmlUtils.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/unit/UnitXmlUtils.java
new file mode 100644
index 000000000..af6f92320
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/unit/UnitXmlUtils.java
@@ -0,0 +1,39 @@
+package org.argeo.slc.unit;
+
+import java.io.IOException;
+
+import javax.xml.transform.Source;
+
+import junit.framework.TestCase;
+
+import org.springframework.xml.validation.XmlValidator;
+import org.springframework.xml.xsd.XsdSchema;
+import org.xml.sax.SAXParseException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public abstract class UnitXmlUtils {
+ private final static Log log = LogFactory.getLog(UnitXmlUtils.class);
+
+ public static void assertXsdSchemaValidation(XsdSchema schema, Source source)
+ throws IOException {
+ XmlValidator validator = schema.createValidator();
+ assertXmlValidation(validator, source);
+ }
+
+ public static void assertXmlValidation(XmlValidator validator, Source source)
+ throws IOException {
+ SAXParseException[] exceptions = validator.validate(source);
+ if (exceptions.length != 0) {
+ for (SAXParseException ex : exceptions) {
+ log.error(ex.getMessage());
+ }
+ TestCase.fail("Could not validate");
+ }
+ }
+
+ private UnitXmlUtils() {
+
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/unit/package.html b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/unit/package.html
new file mode 100644
index 000000000..907430d09
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/unit/package.html
@@ -0,0 +1,6 @@
+
+
+
+Helpers for unit tests.
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/unit/test/tree/UnitTestTreeUtil.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/unit/test/tree/UnitTestTreeUtil.java
new file mode 100644
index 000000000..1862055fa
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/unit/test/tree/UnitTestTreeUtil.java
@@ -0,0 +1,148 @@
+package org.argeo.slc.unit.test.tree;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.fail;
+import static org.argeo.slc.unit.UnitUtils.assertDateSec;
+
+import org.argeo.slc.core.structure.SimpleSElement;
+import org.argeo.slc.core.structure.tree.TreeSPath;
+import org.argeo.slc.core.test.SimpleResultPart;
+import org.argeo.slc.core.test.TestResultPart;
+import org.argeo.slc.core.test.tree.PartSubList;
+import org.argeo.slc.core.test.tree.TreeTestResult;
+
+/** Utilities for unit tests. */
+public class UnitTestTreeUtil {
+ private final static Log log = LogFactory.getLog(UnitTestTreeUtil.class);
+
+ public static void assertTreeTestResult(TreeTestResult expected,
+ TreeTestResult reached) {
+ assertEquals(expected.getUuid(), reached.getUuid());
+ assertDateSec(expected.getCloseDate(), reached.getCloseDate());
+
+ assertEquals(expected.getResultParts().size(), reached.getResultParts()
+ .size());
+ for (TreeSPath path : expected.getResultParts().keySet()) {
+ PartSubList lstExpected = expected.getResultParts().get(path);
+ PartSubList lstReached = expected.getResultParts().get(path);
+ if (lstReached == null) {
+ fail("No result for path " + path);
+ return;
+ }
+ assertPartSubList(lstExpected, lstReached);
+ }
+
+ assertEquals(expected.getElements().size(), reached.getElements()
+ .size());
+ for (TreeSPath path : expected.getElements().keySet()) {
+ // String nameExpected = expected.getElements().get(path);
+ // String nameReached = expected.getElements().get(path);
+ SimpleSElement elemExpected = (SimpleSElement) expected
+ .getElements().get(path);
+ SimpleSElement elemReached = (SimpleSElement) expected
+ .getElements().get(path);
+ assertNotNull(elemReached);
+ assertElements(elemExpected, elemReached);
+ }
+
+ }
+
+ public static void assertElements(SimpleSElement expected,
+ SimpleSElement reached) {
+ assertEquals(expected.getLabel(), reached.getLabel());
+ assertEquals(expected.getTags().size(), reached.getTags().size());
+ for (String tagName : expected.getTags().keySet()) {
+ String expectedTagValue = expected.getTags().get(tagName);
+ String reachedTagValue = reached.getTags().get(tagName);
+ assertNotNull(reachedTagValue);
+ assertEquals(expectedTagValue, reachedTagValue);
+ }
+ }
+
+ public static void assertPartSubList(PartSubList lstExpected,
+ PartSubList lstReached) {
+ assertEquals(lstExpected.getParts().size(), lstReached.getParts()
+ .size());
+ for (int i = 0; i < lstExpected.getParts().size(); i++) {
+ assertPart(lstExpected.getParts().get(i), lstReached.getParts()
+ .get(i));
+ }
+ }
+
+ /** Asserts one part of a tree test result */
+ public static void assertPart(TreeTestResult testResult, String pathStr,
+ int index, Integer status, String message) {
+ TreeSPath path = new TreeSPath(pathStr);
+ PartSubList list = testResult.getResultParts().get(path);
+ if (list == null) {
+ fail("No result for path " + path);
+ return;
+ }
+ if (index >= list.getParts().size()) {
+ fail("Not enough parts.");
+ }
+ SimpleResultPart part = (SimpleResultPart) list.getParts().get(index);
+ assertPart(part, status, message, null, part.getTestRunUuid(), true);
+ }
+
+ public static void assertPart(TestResultPart expected,
+ TestResultPart reached) {
+ String expectedTestRunUuid = null;
+ if (expected instanceof SimpleResultPart) {
+ expectedTestRunUuid = ((SimpleResultPart) expected)
+ .getTestRunUuid();
+ }
+
+ assertPart(reached, expected.getStatus(), expected.getMessage(),
+ expected.getExceptionMessage(), expectedTestRunUuid, false);
+ }
+
+ /** Assert one part of a tree test result. */
+ private static void assertPart(TestResultPart part, Integer status,
+ String message, String exceptionDescription,
+ String expectedTestRunUuid, boolean skipExceptionMessage) {
+ assertEquals(status, part.getStatus());
+
+ if (log.isTraceEnabled()) {
+ log.trace("Expected message:" + message);
+ log.trace("Reached message:" + part.getMessage());
+ }
+ assertEquals(message, part.getMessage());
+ if (!skipExceptionMessage) {
+ if (exceptionDescription == null) {
+ assertNull(part.getExceptionMessage());
+ } else {
+ if (log.isTraceEnabled()) {
+ log.trace("Expected exception message:"
+ + exceptionDescription);
+ log.trace("Reached exception message:"
+ + part.getExceptionMessage());
+ }
+
+ assertEquals(exceptionDescription, part.getExceptionMessage());
+ }
+ }
+
+ if (expectedTestRunUuid != null) {
+ SimpleResultPart reachedPart = (SimpleResultPart) part;
+ assertNotNull(reachedPart.getTestRunUuid());
+ assertEquals(expectedTestRunUuid, reachedPart.getTestRunUuid());
+ } else {
+ if (part instanceof SimpleResultPart) {
+ assertNull(((SimpleResultPart) part).getTestRunUuid());
+ }
+
+ }
+
+ }
+
+ /** Makes sure this is a singleton */
+ private UnitTestTreeUtil() {
+
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/ws/client/ValidatingClientInterceptor.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/ws/client/ValidatingClientInterceptor.java
new file mode 100644
index 000000000..cd3add67c
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/ws/client/ValidatingClientInterceptor.java
@@ -0,0 +1,88 @@
+package org.argeo.slc.ws.client;
+
+import java.io.IOException;
+
+import javax.xml.transform.Source;
+
+import org.springframework.ws.client.WebServiceClientException;
+import org.springframework.ws.client.WebServiceIOException;
+import org.springframework.ws.client.support.interceptor.ClientInterceptor;
+import org.springframework.ws.context.MessageContext;
+import org.springframework.xml.validation.XmlValidator;
+import org.xml.sax.SAXParseException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class ValidatingClientInterceptor implements ClientInterceptor {
+ private final static Log log = LogFactory
+ .getLog(ValidatingClientInterceptor.class);
+
+ private Boolean validateRequest = true;
+ private Boolean validateResponse = false;
+ private XmlValidator validator = null;
+
+ public boolean handleFault(MessageContext messageContext)
+ throws WebServiceClientException {
+ return true;
+ }
+
+ public boolean handleRequest(MessageContext messageContext)
+ throws WebServiceClientException {
+ if (validateRequest) {
+ if (messageContext.getRequest() == null)
+ return true;
+
+ Source source = messageContext.getRequest().getPayloadSource();
+ try {
+ return validate(source);
+ } catch (IOException e) {
+ throw new WebServiceIOException("Cannot validate request", e);
+ }
+ } else {
+ return true;
+ }
+ }
+
+ public boolean handleResponse(MessageContext messageContext)
+ throws WebServiceClientException {
+ if (validateResponse) {
+ if (messageContext.getResponse() == null)
+ return true;
+
+ Source source = messageContext.getResponse().getPayloadSource();
+ try {
+ return validate(source);
+ } catch (IOException e) {
+ throw new WebServiceIOException("Cannot validate response", e);
+ }
+ } else {
+ return true;
+ }
+ }
+
+ protected boolean validate(Source source) throws IOException {
+ SAXParseException[] exceptions = validator.validate(source);
+ if (exceptions.length != 0) {
+ for (SAXParseException ex : exceptions) {
+ log.error(ex.getMessage());
+ }
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ public void setValidateRequest(Boolean validateRequest) {
+ this.validateRequest = validateRequest;
+ }
+
+ public void setValidateResponse(Boolean validateResponse) {
+ this.validateResponse = validateResponse;
+ }
+
+ public void setValidator(XmlValidator validator) {
+ this.validator = validator;
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/ws/client/WebServiceUtils.java b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/ws/client/WebServiceUtils.java
new file mode 100644
index 000000000..d37a27efe
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/java/org/argeo/slc/ws/client/WebServiceUtils.java
@@ -0,0 +1,78 @@
+package org.argeo.slc.ws.client;
+
+import java.util.Iterator;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.dom.DOMSource;
+
+import org.springframework.ws.client.core.WebServiceTemplate;
+import org.springframework.ws.soap.SoapFaultDetail;
+import org.springframework.ws.soap.SoapFaultDetailElement;
+import org.springframework.ws.soap.client.SoapFaultClientException;
+import org.springframework.xml.transform.StringResult;
+import org.w3c.dom.Node;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public abstract class WebServiceUtils {
+ private final static Log log = LogFactory.getLog(WebServiceUtils.class);
+
+ public static Object marshalSendAndReceiveSafe(WebServiceTemplate template,
+ Object req) {
+ try {
+ Object resp = marshalSendAndReceive(template, req);
+ return resp;
+ } catch (Exception e) {
+ log.error("Cannot send web servicerequest: "+e.getMessage());
+ if(log.isDebugEnabled()){
+ log.debug("Webservice exception details: ",e);
+ }
+ return null;
+ }
+ }
+
+ public static Object marshalSendAndReceive(
+ WebServiceTemplate template, Object req) {
+ if (log.isTraceEnabled()) {
+ try {
+ StringResult result = new StringResult();
+ template.getMarshaller().marshal(req, result);
+ log.trace("About to send " + result);
+ } catch (Exception e) {
+ log.error("Cannot marshall " + req + " for logging", e);
+ }
+ }
+ Object resp = template.marshalSendAndReceive(req);
+ return resp;
+ }
+
+ public static void manageSoapException(SoapFaultClientException e) {
+ log
+ .error("WS root cause: "
+ + e.getSoapFault().getFaultStringOrReason());
+ StringBuffer stack = new StringBuffer("");
+ SoapFaultDetail detail = e.getSoapFault().getFaultDetail();
+ if (detail != null) {
+ Iterator it = (Iterator) detail
+ .getDetailEntries();
+ while (it.hasNext()) {
+ SoapFaultDetailElement elem = it.next();
+ if (elem.getName().getLocalPart().equals("StackElement")) {
+ Source source = elem.getSource();
+ if (source instanceof DOMSource) {
+ Node node = ((DOMSource) source).getNode();
+ stack.append(node.getTextContent()).append('\n');
+ }
+ }
+ }
+
+ if (stack.length() > 0 && log.isTraceEnabled())
+ log.error("WS root cause stack: " + stack);
+ }
+ }
+
+ private WebServiceUtils() {
+
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/main/resources/META-INF/services/org.apache.tools.ant.ProjectHelper b/org.argeo.slc.hibernate/src/main/resources/META-INF/services/org.apache.tools.ant.ProjectHelper
new file mode 100644
index 000000000..1c222d5e1
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/META-INF/services/org.apache.tools.ant.ProjectHelper
@@ -0,0 +1 @@
+org.argeo.slc.ant.SlcProjectHelper
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/ant/taskdefs.properties b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/ant/taskdefs.properties
new file mode 100644
index 000000000..85e0743c8
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/ant/taskdefs.properties
@@ -0,0 +1,5 @@
+# Tasks
+slc.test=org.argeo.slc.ant.test.SlcTestTask
+slc.deploy=org.argeo.slc.ant.deploy.SlcDeployTask
+slc.closeResult=org.argeo.slc.ant.test.SlcCloseTestResultTask
+slc.report=org.argeo.slc.ant.test.SlcReportTask
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/ant/typedefs.properties b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/ant/typedefs.properties
new file mode 100644
index 000000000..0cb3b2c46
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/ant/typedefs.properties
@@ -0,0 +1,2 @@
+# Types
+slc.context=org.argeo.slc.ant.test.ParentContextType
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/castor/mapping.xml b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/castor/mapping.xml
new file mode 100644
index 000000000..92c2c71d0
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/castor/mapping.xml
@@ -0,0 +1,41 @@
+
+
+
+ Mapping of generic types
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/castor/msg/mapping.xml b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/castor/msg/mapping.xml
new file mode 100644
index 000000000..f695f9573
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/castor/msg/mapping.xml
@@ -0,0 +1,82 @@
+
+
+
+ Message objects XML mapping
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/castor/process/mapping.xml b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/castor/process/mapping.xml
new file mode 100644
index 000000000..1b5b2ec95
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/castor/process/mapping.xml
@@ -0,0 +1,51 @@
+
+
+
+
+
+ Process objects XML mapping
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/castor/spring/applicationContext.xml b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/castor/spring/applicationContext.xml
new file mode 100644
index 000000000..068d773fb
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/castor/spring/applicationContext.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+ classpath:org/argeo/slc/castor/msg/mapping.xml
+
+
+ classpath:org/argeo/slc/castor/process/mapping.xml
+
+
+ classpath:org/argeo/slc/castor/structure/mapping.xml
+
+
+ classpath:org/argeo/slc/castor/test/mapping.xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/castor/structure/mapping.xml b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/castor/structure/mapping.xml
new file mode 100644
index 000000000..3e20025b3
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/castor/structure/mapping.xml
@@ -0,0 +1,35 @@
+
+
+
+ Structure related objects XML mapping
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/castor/test/mapping.xml b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/castor/test/mapping.xml
new file mode 100644
index 000000000..adfea8a9d
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/castor/test/mapping.xml
@@ -0,0 +1,82 @@
+
+
+
+ Test objects XML mapping
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/core/test/spring/applicationContext.xml b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/core/test/spring/applicationContext.xml
new file mode 100644
index 000000000..3e1cd53eb
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/core/test/spring/applicationContext.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/core/test/tree/basicReport.xslt b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/core/test/tree/basicReport.xslt
new file mode 100644
index 000000000..947cef0f9
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/core/test/tree/basicReport.xslt
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+ Result
+
+
+
+ Result
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/core/test/tree/htmlreport/index.html b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/core/test/tree/htmlreport/index.html
new file mode 100644
index 000000000..32beed3b5
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/core/test/tree/htmlreport/index.html
@@ -0,0 +1,16 @@
+
+
+
+SLC test results
+
+
+
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/core/test/tree/htmlreport/style.css b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/core/test/tree/htmlreport/style.css
new file mode 100644
index 000000000..134c6b55d
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/core/test/tree/htmlreport/style.css
@@ -0,0 +1,64 @@
+body {
+ font-family: sans-serif;
+ font-size: 12px;
+ color: black;
+ background-color: white;
+}
+
+h1 {
+ font-family: sans-serif;
+ font-size: 16px;
+ font-weight: bold;
+ color: #000000;
+ padding: 0px 0px 5px 0px;
+ margin: 0px;
+}
+
+h2 {
+ font-family: sans-serif;
+ font-size: 14px;
+ font-weight: bold;
+ color: #000000;
+ padding: 5px 0px 5px 0px;
+ margin: 0px;
+ margin-top: 5px;
+}
+
+table,form {
+ margin: 0px;
+}
+
+th {
+ font-size: 12px;
+ padding: 2px 20px 2px 2px;
+ vertical-align: top;
+ text-align: left;
+}
+
+td {
+ font-size: 12px;
+ padding: 1px;
+ vertical-align: top;
+ text-align: left;
+}
+
+.passed {
+ color: green;
+}
+
+.failed {
+ color: red;
+}
+
+a {
+ text-decoration: none;
+}
+
+a.nav {
+ color: #0066CC;
+ text-decoration: none;
+}
+
+a:hover {
+ text-decoration: underline;
+}
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/process/SlcExecution.hbm.xml b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/process/SlcExecution.hbm.xml
new file mode 100644
index 000000000..bde8cc54d
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/process/SlcExecution.hbm.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/process/SlcExecutionStep.hbm.xml b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/process/SlcExecutionStep.hbm.xml
new file mode 100644
index 000000000..ce22c71a4
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/process/SlcExecutionStep.hbm.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/spring/applicationContext.xml b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/spring/applicationContext.xml
new file mode 100644
index 000000000..19f1d73c8
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/spring/applicationContext.xml
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org/argeo/slc/hibernate/structure/SimpleSElement.hbm.xml
+
+
+ org/argeo/slc/hibernate/structure/tree/TreeSPath.hbm.xml
+
+
+ org/argeo/slc/hibernate/structure/tree/TreeSRegistry.hbm.xml
+
+
+ org/argeo/slc/hibernate/test/NumericTRId.hbm.xml
+
+
+ org/argeo/slc/hibernate/test/SimpleResultPart.hbm.xml
+
+
+ org/argeo/slc/hibernate/test/tree/TreeTestResult.hbm.xml
+
+
+ org/argeo/slc/hibernate/test/tree/TreeTestResultCollection.hbm.xml
+
+
+ org/argeo/slc/hibernate/test/tree/PartSubList.hbm.xml
+
+
+ org/argeo/slc/hibernate/test/TestRunDescriptor.hbm.xml
+
+
+ org/argeo/slc/hibernate/process/SlcExecution.hbm.xml
+
+
+ org/argeo/slc/hibernate/process/SlcExecutionStep.hbm.xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/structure/SimpleSElement.hbm.xml b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/structure/SimpleSElement.hbm.xml
new file mode 100644
index 000000000..0bc9e6aea
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/structure/SimpleSElement.hbm.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/structure/tree/TreeSPath.hbm.xml b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/structure/tree/TreeSPath.hbm.xml
new file mode 100644
index 000000000..0e282505f
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/structure/tree/TreeSPath.hbm.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/structure/tree/TreeSRegistry.hbm.xml b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/structure/tree/TreeSRegistry.hbm.xml
new file mode 100644
index 000000000..2182a2304
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/structure/tree/TreeSRegistry.hbm.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/test/NumericTRId.hbm.xml b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/test/NumericTRId.hbm.xml
new file mode 100644
index 000000000..ca9c5d972
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/test/NumericTRId.hbm.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/test/SimpleResultPart.hbm.xml b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/test/SimpleResultPart.hbm.xml
new file mode 100644
index 000000000..42f32dfb8
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/test/SimpleResultPart.hbm.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/test/TestResultId.hbm.xml b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/test/TestResultId.hbm.xml
new file mode 100644
index 000000000..dee13a618
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/test/TestResultId.hbm.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/test/TestRunDescriptor.hbm.xml b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/test/TestRunDescriptor.hbm.xml
new file mode 100644
index 000000000..a00332cc2
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/test/TestRunDescriptor.hbm.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/test/tree/PartSubList.hbm.xml b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/test/tree/PartSubList.hbm.xml
new file mode 100644
index 000000000..f86de7312
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/test/tree/PartSubList.hbm.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/test/tree/TreeTestResult.hbm.xml b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/test/tree/TreeTestResult.hbm.xml
new file mode 100644
index 000000000..37db79a6d
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/test/tree/TreeTestResult.hbm.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/test/tree/TreeTestResultCollection.hbm.xml b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/test/tree/TreeTestResultCollection.hbm.xml
new file mode 100644
index 000000000..19fce6656
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/hibernate/test/tree/TreeTestResultCollection.hbm.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/support/deploy/ant/build.xml b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/support/deploy/ant/build.xml
new file mode 100644
index 000000000..693f5ecb9
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/support/deploy/ant/build.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/ws/client/spring/applicationContext.xml b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/ws/client/spring/applicationContext.xml
new file mode 100644
index 000000000..9bb2ff7f4
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/ws/client/spring/applicationContext.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/xml/slc.xsd b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/xml/slc.xsd
new file mode 100644
index 000000000..b457f18f0
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/xml/slc.xsd
@@ -0,0 +1,235 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/xml/spring/applicationContext.xml b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/xml/spring/applicationContext.xml
new file mode 100644
index 000000000..13bd1dd03
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/main/resources/org/argeo/slc/xml/spring/applicationContext.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
diff --git a/org.argeo.slc.hibernate/src/site/apt/index.apt b/org.argeo.slc.hibernate/src/site/apt/index.apt
new file mode 100644
index 000000000..f414460db
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/site/apt/index.apt
@@ -0,0 +1 @@
+Argeo SLC Site
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/ant/SlcAntTest.java b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/ant/SlcAntTest.java
new file mode 100644
index 000000000..c19cdd4a2
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/ant/SlcAntTest.java
@@ -0,0 +1,24 @@
+package org.argeo.slc.ant;
+
+import java.net.URL;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.argeo.slc.unit.AbstractSpringTestCase;
+
+public class SlcAntTest extends AbstractSpringTestCase {
+ private Log log = LogFactory.getLog(getClass());
+
+ public void testSimpleRun() {
+ // AntRegistryUtil.runAll(getClass().getResource(
+ // "/org/argeo/slc/ant/build.xml"), "test", null);
+
+ URL url = getClass().getResource("/org/argeo/slc/ant/build.xml");
+ log.info("Run Ant file from URL: " + url);
+ AntRunner antRunner = new AntRunner(getContext(), url, "test");
+
+ antRunner.run();
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/core/process/SlcExecutionCastorTest.java b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/core/process/SlcExecutionCastorTest.java
new file mode 100644
index 000000000..55fba622f
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/core/process/SlcExecutionCastorTest.java
@@ -0,0 +1,114 @@
+package org.argeo.slc.core.process;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.text.SimpleDateFormat;
+import java.util.UUID;
+
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.msg.process.SlcExecutionRequest;
+import org.argeo.slc.msg.process.SlcExecutionStepsRequest;
+import org.argeo.slc.unit.AbstractSpringTestCase;
+import org.argeo.slc.unit.UnitXmlUtils;
+
+import org.springframework.oxm.Marshaller;
+import org.springframework.oxm.Unmarshaller;
+import org.springframework.xml.transform.StringResult;
+import org.springframework.xml.transform.StringSource;
+import org.springframework.xml.validation.XmlValidator;
+import org.springframework.xml.xsd.XsdSchema;
+
+public class SlcExecutionCastorTest extends AbstractSpringTestCase {
+ private Log log = LogFactory.getLog(getClass());
+
+ private Marshaller marshaller;
+ private Unmarshaller unmarshaller;
+
+ @Override
+ public void setUp() {
+ marshaller = getBean(Marshaller.class);
+ unmarshaller = getBean(Unmarshaller.class);
+ }
+
+ public void testMarshalling() throws Exception {
+ SlcExecution slcExec = SlcExecutionTestUtils.createSimpleSlcExecution();
+
+ SlcExecutionRequest msgSave = new SlcExecutionRequest();
+ msgSave.setSlcExecution(slcExec);
+
+ String msgSaveXml = marshallAndLog(marshaller, msgSave);
+
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
+ SlcExecutionStep step0 = new SlcExecutionStep();
+ step0.setUuid(UUID.randomUUID().toString());
+ step0.setBegin(sdf.parse("2008-04-17 18:21"));
+ step0.setType("LOG");
+ step0.addLog("A log message\nand another line");
+
+ SlcExecutionStep step1 = new SlcExecutionStep();
+ step1.setUuid(UUID.randomUUID().toString());
+ step1.setBegin(sdf.parse("2008-04-17 18:25"));
+ step1.setType("LOG");
+ step1.addLog("A nother log message");
+
+ SlcExecutionStepsRequest msgNotif = new SlcExecutionStepsRequest();
+ msgNotif.addStep(step0);
+ msgNotif.addStep(step1);
+ msgNotif.setSlcExecutionUuid(slcExec.getUuid());
+
+ String msgNotifXml = marshallAndLog(marshaller, msgNotif);
+
+ SlcExecutionRequest msgSaveUnm = unmarshall(unmarshaller, msgSaveXml);
+ assertNotNull(msgSaveUnm);
+ SlcExecutionTestUtils.assertSlcExecution(slcExec, msgSaveUnm
+ .getSlcExecution());
+
+ SlcExecutionStepsRequest msgNotifUnm = unmarshall(unmarshaller,
+ msgNotifXml);
+ assertNotNull(msgNotifUnm);
+ assertEquals(slcExec.getUuid(), msgNotifUnm.getSlcExecutionUuid());
+ assertEquals(2, msgNotifUnm.getSteps().size());
+ SlcExecutionTestUtils.assertSlcExecutionStep(step0, msgNotifUnm
+ .getSteps().get(0));
+ SlcExecutionTestUtils.assertSlcExecutionStep(step1, msgNotifUnm
+ .getSteps().get(1));
+
+ SlcExecution slcExecUnm = msgSaveUnm.getSlcExecution();
+ slcExecUnm.getSteps().addAll(msgNotifUnm.getSteps());
+
+ SlcExecutionRequest msgUpdate = new SlcExecutionRequest();
+ msgUpdate.setSlcExecution(slcExecUnm);
+ String msgUpdateXml = marshallAndLog(marshaller, msgUpdate);
+
+ SlcExecutionRequest msgUpdateUnm = unmarshall(unmarshaller,
+ msgUpdateXml);
+ assertNotNull(msgUpdateUnm);
+ }
+
+ private String marshallAndLog(Marshaller marshaller, Object obj)
+ throws IOException {
+ StringResult xml = new StringResult();
+ marshaller.marshal(obj, xml);
+ log.info("Marshalled object: " + xml);
+
+ UnitXmlUtils.assertXmlValidation(getBean(XmlValidator.class),
+ new StringSource(xml.toString()));
+
+ return xml.toString();
+ }
+
+ private T unmarshall(Unmarshaller unmarshaller, String xml)
+ throws IOException {
+ StringReader reader = new StringReader(xml);
+ Object obj = unmarshaller.unmarshal(new StreamSource(reader));
+ IOUtils.closeQuietly(reader);
+ return (T) obj;
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/core/process/SlcExecutionTestUtils.java b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/core/process/SlcExecutionTestUtils.java
new file mode 100644
index 000000000..c3c880366
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/core/process/SlcExecutionTestUtils.java
@@ -0,0 +1,51 @@
+package org.argeo.slc.core.process;
+
+import java.util.UUID;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static org.argeo.slc.unit.UnitUtils.assertDateSec;
+
+public abstract class SlcExecutionTestUtils {
+
+ public static SlcExecution createSimpleSlcExecution() {
+ SlcExecution slcExec = new SlcExecution();
+ slcExec.setUuid(UUID.randomUUID().toString());
+ slcExec.setHost("localhost");
+ slcExec.setUser("user");
+ slcExec.setType("slcAnt");
+ slcExec.setStatus("STARTED");
+ slcExec.getAttributes().put("ant.file", "/test");
+ return slcExec;
+ }
+
+ public static void assertSlcExecution(SlcExecution expected,
+ SlcExecution reached) {
+ assertNotNull(reached);
+ assertEquals(expected.getHost(), reached.getHost());
+ assertEquals(expected.getUser(), reached.getUser());
+ assertEquals(expected.getType(), reached.getType());
+ assertEquals(expected.getStatus(), reached.getStatus());
+ assertEquals(expected.getAttributes().size(), reached.getAttributes()
+ .size());
+ for (String key : expected.getAttributes().keySet()) {
+ String expectedValue = expected.getAttributes().get(key);
+ String reachedValue = reached.getAttributes().get(key);
+ assertNotNull(reachedValue);
+ assertEquals(expectedValue, reachedValue);
+ }
+ }
+
+ public static void assertSlcExecutionStep(SlcExecutionStep expected,
+ SlcExecutionStep reached) {
+ assertNotNull(reached);
+ assertEquals(expected.getUuid(), reached.getUuid());
+ assertEquals(expected.getType(), reached.getType());
+ assertEquals(expected.logAsString(), reached.logAsString());
+ assertDateSec(expected.getBegin(), reached.getBegin());
+ }
+
+ private SlcExecutionTestUtils() {
+
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/core/structure/tree/TreeSPathTest.java b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/core/structure/tree/TreeSPathTest.java
new file mode 100644
index 000000000..fab683111
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/core/structure/tree/TreeSPathTest.java
@@ -0,0 +1,57 @@
+package org.argeo.slc.core.structure.tree;
+
+import junit.framework.TestCase;
+
+public class TreeSPathTest extends TestCase {
+
+ public void testNew() {
+ TreeSPath path = new TreeSPath("/test");
+ assertEquals("test", path.getName());
+ assertNull(path.getParent());
+
+ path = new TreeSPath("/root/subdir");
+ assertEquals("subdir", path.getName());
+ assertEquals(new TreeSPath("/root"), path.getParent());
+ }
+
+ public void testEquals() {
+ TreeSPath path1 = new TreeSPath("/test");
+ TreeSPath path2 = new TreeSPath("/test");
+ assertEquals(path1, path2);
+
+ path1 = new TreeSPath("/test/subdir/anotherdir");
+ path2 = new TreeSPath("/test/subdir/anotherdir");
+ assertEquals(path1, path2);
+
+ path1 = new TreeSPath("/test/subdir/anotherd");
+ path2 = new TreeSPath("/test/subdir/anotherdir");
+ assertNotSame(path1, path2);
+
+ path1 = new TreeSPath("/test/subdir");
+ path2 = new TreeSPath("/test/subdir/anotherdir");
+ assertNotSame(path1, path2);
+
+ path1 = new TreeSPath("/test/subd/anotherdir");
+ path2 = new TreeSPath("/test/subdir/anotherdir");
+ assertNotSame(path1, path2);
+ }
+
+ public void testCheckFormat(){
+ try{
+ new TreeSPath("hello");
+ fail("Bad format should be rejected");
+ }catch(Exception e){
+ // exception expected
+ }
+
+ try{
+ new TreeSPath("/");
+ fail("Bad format should be rejected");
+ }catch(Exception e){
+ // exception expected
+ }
+
+ assertEquals(new TreeSPath("/test"), new TreeSPath("/test/"));
+ assertEquals(new TreeSPath("/test/dir"), new TreeSPath("//test///dir////"));
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/core/test/context/ContextTest.java b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/core/test/context/ContextTest.java
new file mode 100644
index 000000000..6d53ef7e3
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/core/test/context/ContextTest.java
@@ -0,0 +1,30 @@
+package org.argeo.slc.core.test.context;
+
+import java.util.List;
+
+import org.argeo.slc.core.test.SimpleTestResult;
+import org.argeo.slc.core.test.TestResultPart;
+import org.argeo.slc.core.test.TestStatus;
+import org.argeo.slc.unit.AbstractSpringTestCase;
+
+public class ContextTest extends AbstractSpringTestCase {
+
+ public void testComplexContext() {
+ SimpleTestResult testResult = new SimpleTestResult();
+ ContextUtils.compareReachedExpected(
+ (ContextAware) getBean("context.c1"), testResult, null);
+ ContextUtils.compareReachedExpected(
+ (ContextAware) getBean("context.c2"), testResult, null);
+ ContextUtils.compareReachedExpected(
+ (ContextAware) getBean("context.c3"), testResult, null);
+
+ List parts = testResult.getParts();
+ assertEquals(6, parts.size());
+ assertEquals(TestStatus.PASSED, parts.get(0).getStatus());
+ assertEquals(TestStatus.PASSED, parts.get(1).getStatus());
+ assertEquals(TestStatus.PASSED, parts.get(2).getStatus());
+ assertEquals(TestStatus.FAILED, parts.get(3).getStatus());
+ assertEquals(TestStatus.PASSED, parts.get(4).getStatus());
+ assertEquals(TestStatus.PASSED, parts.get(5).getStatus());
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/core/test/tree/TreeTestResultCastorTest.java b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/core/test/tree/TreeTestResultCastorTest.java
new file mode 100644
index 000000000..b35ea1774
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/core/test/tree/TreeTestResultCastorTest.java
@@ -0,0 +1,100 @@
+package org.argeo.slc.core.test.tree;
+
+import org.springframework.oxm.Marshaller;
+import org.springframework.oxm.Unmarshaller;
+import org.springframework.xml.transform.StringResult;
+import org.springframework.xml.transform.StringSource;
+import org.springframework.xml.validation.XmlValidator;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import static org.argeo.slc.core.test.tree.TreeTestResultTestUtils.createCompleteTreeTestResult;
+import static org.argeo.slc.core.test.tree.TreeTestResultTestUtils.createSimpleResultPartRequest;
+import static org.argeo.slc.unit.UnitUtils.assertDateSec;
+
+import org.argeo.slc.core.structure.tree.TreeSPath;
+import org.argeo.slc.core.test.SimpleResultPart;
+import org.argeo.slc.msg.test.tree.CloseTreeTestResultRequest;
+import org.argeo.slc.msg.test.tree.CreateTreeTestResultRequest;
+import org.argeo.slc.msg.test.tree.ResultPartRequest;
+import org.argeo.slc.unit.AbstractSpringTestCase;
+import org.argeo.slc.unit.UnitXmlUtils;
+import org.argeo.slc.unit.test.tree.UnitTestTreeUtil;
+
+public class TreeTestResultCastorTest extends AbstractSpringTestCase {
+ private Log log = LogFactory.getLog(getClass());
+
+ private Marshaller marshaller;
+ private Unmarshaller unmarshaller;
+
+ @Override
+ public void setUp() {
+ marshaller = getBean(Marshaller.class);
+ unmarshaller = getBean(Unmarshaller.class);
+ }
+
+ public void testMarshUnmarsh() throws Exception {
+ TreeTestResult ttr = createCompleteTreeTestResult();
+
+ StringResult xml = marshallAndValidate(ttr);
+
+ TreeTestResult ttrUnm = (TreeTestResult) unmarshaller
+ .unmarshal(new StringSource(xml.toString()));
+
+ UnitTestTreeUtil.assertTreeTestResult(ttr, ttrUnm);
+ }
+
+ public void testCreateTreeTestResultRequest() throws Exception {
+ CreateTreeTestResultRequest req = new CreateTreeTestResultRequest();
+ req.setTreeTestResult(createCompleteTreeTestResult());
+
+ StringResult xml = marshallAndValidate(req);
+
+ CreateTreeTestResultRequest reqUnm = (CreateTreeTestResultRequest) unmarshaller
+ .unmarshal(new StringSource(xml.toString()));
+
+ UnitTestTreeUtil.assertTreeTestResult(req.getTreeTestResult(), reqUnm
+ .getTreeTestResult());
+ }
+
+ public void testResultPartRequest() throws Exception {
+ TreeTestResult ttr = createCompleteTreeTestResult();
+ ResultPartRequest req = createSimpleResultPartRequest(ttr);
+
+ StringResult xml = marshallAndValidate(req);
+
+ ResultPartRequest reqUnm = (ResultPartRequest) unmarshaller
+ .unmarshal(new StringSource(xml.toString()));
+
+ UnitTestTreeUtil
+ .assertPart(req.getResultPart(), reqUnm.getResultPart());
+ }
+
+ public void testCloseTreeTestResultRequest() throws Exception {
+ TreeTestResult ttr = createCompleteTreeTestResult();
+ ttr.close();
+
+ CloseTreeTestResultRequest req = new CloseTreeTestResultRequest(ttr
+ .getUuid(), ttr.getCloseDate());
+
+ StringResult xml = marshallAndValidate(req);
+
+ CloseTreeTestResultRequest reqUnm = (CloseTreeTestResultRequest) unmarshaller
+ .unmarshal(new StringSource(xml.toString()));
+
+ assertEquals(ttr.getUuid(), reqUnm.getResultUuid());
+ assertDateSec(ttr.getCloseDate(), ttr.getCloseDate());
+ }
+
+ private StringResult marshallAndValidate(Object obj) throws Exception {
+ StringResult xml = new StringResult();
+ marshaller.marshal(obj, xml);
+
+ log.info("Marshalled ResultPart Request: " + xml);
+
+ UnitXmlUtils.assertXmlValidation(getBean(XmlValidator.class),
+ new StringSource(xml.toString()));
+ return xml;
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/core/test/tree/TreeTestResultTestUtils.java b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/core/test/tree/TreeTestResultTestUtils.java
new file mode 100644
index 000000000..bc7dcbdd2
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/core/test/tree/TreeTestResultTestUtils.java
@@ -0,0 +1,106 @@
+package org.argeo.slc.core.test.tree;
+
+import java.util.Date;
+import java.util.UUID;
+
+import org.argeo.slc.core.build.Distribution;
+import org.argeo.slc.core.deploy.DeployedSystem;
+import org.argeo.slc.core.process.SlcExecution;
+import org.argeo.slc.core.process.SlcExecutionStep;
+import org.argeo.slc.core.process.SlcExecutionTestUtils;
+import org.argeo.slc.core.structure.SimpleSElement;
+import org.argeo.slc.core.structure.tree.TreeSPath;
+import org.argeo.slc.core.structure.tree.TreeSRegistry;
+import org.argeo.slc.core.test.SimpleResultPart;
+import org.argeo.slc.core.test.SimpleTestRun;
+import org.argeo.slc.core.test.TestStatus;
+import org.argeo.slc.msg.test.tree.ResultPartRequest;
+
+public abstract class TreeTestResultTestUtils {
+
+ public static TreeTestResult createSimpleTreeTestResult() {
+ TreeTestResult treeTestResult = new TreeTestResult();
+ treeTestResult.setUuid(UUID.randomUUID().toString());
+ return treeTestResult;
+ }
+
+ public static TreeTestResult createCompleteTreeTestResult() {
+ SlcExecution slcExecution = SlcExecutionTestUtils
+ .createSimpleSlcExecution();
+ SlcExecutionStep step = new SlcExecutionStep("LOG", "JUnit step");
+ slcExecution.getSteps().add(step);
+
+ SimpleTestRun testRun = new SimpleTestRun();
+ testRun.setUuid(UUID.randomUUID().toString());
+
+ String pathStr = "/test";
+ TreeSPath path = new TreeSPath(pathStr);
+
+ TreeSRegistry registry = new TreeSRegistry();
+ SimpleSElement elem = new SimpleSElement("Unit Test");
+ elem.getTags().put("myTag", "myTagValue");
+ registry.register(path, elem);
+
+ TreeTestResult ttr = createSimpleTreeTestResult();
+ ttr.notifyCurrentPath(registry, path);
+ ttr.notifyTestRun(testRun);
+ testRun.setTestResult(ttr);
+ testRun.setDeployedSystem(new DeployedSystem() {
+ private String uuid = UUID.randomUUID().toString();
+
+ public String getDeployedSystemId() {
+ return uuid;
+ }
+
+ public Distribution getDistribution() {
+ return null;
+ }
+ });
+ testRun.notifySlcExecution(slcExecution);
+
+ ttr.addResultPart(createSimpleResultPartPassed());
+ ttr.addResultPart(createSimpleResultPartFailed());
+ ttr.addResultPart(createSimpleResultPartError());
+ return ttr;
+ }
+
+ public static SimpleResultPart createSimpleResultPartPassed() {
+ SimpleResultPart partPassed = new SimpleResultPart();
+ String msgPassed = "message\nnew line";
+ partPassed.setStatus(TestStatus.PASSED);
+ partPassed.setMessage(msgPassed);
+ return partPassed;
+ }
+
+ public static SimpleResultPart createSimpleResultPartFailed() {
+ SimpleResultPart partFailed = new SimpleResultPart();
+ String msgFailed = "too bad";
+ partFailed.setStatus(TestStatus.FAILED);
+ partFailed.setMessage(msgFailed);
+ return partFailed;
+ }
+
+ public static SimpleResultPart createSimpleResultPartError() {
+ SimpleResultPart partFailed = new SimpleResultPart();
+ String msgFailed = "crashed\nanother line";
+ partFailed.setStatus(TestStatus.ERROR);
+ partFailed.setMessage(msgFailed);
+ partFailed.setException(new Exception("Test Exception"));
+ return partFailed;
+ }
+
+ public static ResultPartRequest createSimpleResultPartRequest(TreeTestResult ttr) {
+ TreeSPath path = ttr.getCurrentPath();
+ PartSubList lst = ttr.getResultParts().get(path);
+ SimpleResultPart part = (SimpleResultPart) lst.getParts().get(2);
+
+ ResultPartRequest req = new ResultPartRequest(ttr, path, part);
+ req.setPath(ttr.getCurrentPath());
+
+ return req;
+ }
+
+ private TreeTestResultTestUtils() {
+
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/diff/LineTokenizerTest.java b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/diff/LineTokenizerTest.java
new file mode 100644
index 000000000..58ed61a92
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/diff/LineTokenizerTest.java
@@ -0,0 +1,53 @@
+package org.argeo.slc.diff;
+
+import java.util.List;
+
+import junit.framework.TestCase;
+
+public class LineTokenizerTest extends TestCase {
+ public void testSimple() throws Exception {
+ testAndAssert("a,b,c", new String[] { "a", "b", "c" });
+ testAndAssert("hello,bonjour,hallo,priviet", new String[] { "hello",
+ "bonjour", "hallo", "priviet" });
+ }
+
+ public void testTricky() throws Exception {
+ testAndAssert("alone", new String[] { "alone" });
+ testAndAssert("", new String[] { "" });
+
+ testAndAssert(",hello,bonjour,hallo,priviet", new String[] { "",
+ "hello", "bonjour", "hallo", "priviet" });
+ testAndAssert("hello,bonjour,,hallo,priviet", new String[] { "hello",
+ "bonjour", "", "hallo", "priviet" });
+ testAndAssert("hello,bonjour,hallo,priviet,", new String[] { "hello",
+ "bonjour", "hallo", "priviet", "" });
+ testAndAssert(",hello,,bonjour,hallo,,,,priviet,", new String[] { "",
+ "hello", "", "bonjour", "hallo", "", "", "", "priviet", "" });
+
+ testAndAssert(",,,", new String[] { "", "", "", "" });
+ }
+
+ public void testComplex() throws Exception {
+ testAndAssert("a#b#c", '#', "", new String[] { "a", "b", "c" });
+ testAndAssert("hello!bonjour!hallo!priviet", '!', "", new String[] {
+ "hello", "bonjour", "hallo", "priviet" });
+
+ testAndAssert("hello,,bonjour,,hallo,priviet", ',', "",
+ new String[] { "hello", "", "bonjour", "",
+ "hallo", "priviet" });
+ }
+
+ private void testAndAssert(String str, String[] expected) {
+ testAndAssert(str, ',', "", expected);
+ }
+
+ private void testAndAssert(String str, Character sep, String noValueStr,
+ String[] expected) {
+ List res = LineTokenizer.tokenize(str, sep, noValueStr);
+ assertEquals("Size", expected.length, res.size());
+ for (int i = 0; i < res.size(); i++) {
+ String token = res.get(i);
+ assertEquals("Value@" + i, expected[i], token);
+ }
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/hibernate/process/SlcExecutionHibernateTest.java b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/hibernate/process/SlcExecutionHibernateTest.java
new file mode 100644
index 000000000..f821dbd9b
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/hibernate/process/SlcExecutionHibernateTest.java
@@ -0,0 +1,74 @@
+package org.argeo.slc.hibernate.process;
+
+import java.util.List;
+
+import org.argeo.slc.core.process.SlcExecution;
+import org.argeo.slc.core.process.SlcExecutionStep;
+import org.argeo.slc.core.process.SlcExecutionTestUtils;
+import org.argeo.slc.dao.process.SlcExecutionDao;
+import org.argeo.slc.unit.AbstractSpringTestCase;
+
+public class SlcExecutionHibernateTest extends AbstractSpringTestCase {
+
+ public void testSave() {
+ SlcExecutionDao dao = getBean(SlcExecutionDao.class);
+
+ SlcExecution slcExec = SlcExecutionTestUtils.createSimpleSlcExecution();
+ slcExec.getSteps().add(new SlcExecutionStep("LOG", "A log line"));
+ slcExec.getSteps().add(new SlcExecutionStep("LOG", "Two log\nlines"));
+
+ dao.create(slcExec);
+
+ SlcExecution slcExecPersisted = dao.getSlcExecution(slcExec.getUuid());
+ SlcExecutionTestUtils.assertSlcExecution(slcExec, slcExecPersisted);
+ assertEquals(2, slcExecPersisted.getSteps().size());
+ SlcExecutionTestUtils.assertSlcExecutionStep(slcExec.getSteps().get(0),
+ slcExecPersisted.getSteps().get(0));
+ SlcExecutionTestUtils.assertSlcExecutionStep(slcExec.getSteps().get(1),
+ slcExecPersisted.getSteps().get(1));
+ }
+
+ public void testModify() {
+ SlcExecutionDao dao = getBean(SlcExecutionDao.class);
+
+ // slcExecution Creation
+ SlcExecution slcExec = SlcExecutionTestUtils.createSimpleSlcExecution();
+ slcExec.getSteps().add(new SlcExecutionStep("LOG", "A log line"));
+ slcExec.getSteps().add(new SlcExecutionStep("LOG", "Two log\nlines"));
+
+ dao.create(slcExec);
+
+ // slcExecution retrieval and update
+ SlcExecution slcExecRetrieved = dao.getSlcExecution(slcExec.getUuid());
+
+ List logLineListStep0 = slcExecRetrieved.getSteps().get(0)
+ .getLogLines();
+ for (String logLine : logLineListStep0)
+ logLine = logLine + "appended Log text";
+
+ slcExecRetrieved.getSteps().get(0).setLogLines(logLineListStep0);
+ slcExecRetrieved.getSteps().add(
+ new SlcExecutionStep("LOG", "Three \n log \n lines"));
+
+ dao.update(slcExecRetrieved);
+
+ // updated slcExecution retrieval and comparison
+ SlcExecution slcExecUpdated = dao.getSlcExecution(slcExec.getUuid());
+
+ SlcExecutionTestUtils.assertSlcExecution(slcExecRetrieved,
+ slcExecUpdated);
+ assertEquals(3, slcExecUpdated.getSteps().size());
+ SlcExecutionTestUtils.assertSlcExecutionStep(slcExecUpdated.getSteps()
+ .get(0), slcExecRetrieved.getSteps().get(0));
+ SlcExecutionTestUtils.assertSlcExecutionStep(slcExecUpdated.getSteps()
+ .get(1), slcExecRetrieved.getSteps().get(1));
+ SlcExecutionTestUtils.assertSlcExecutionStep(slcExecUpdated.getSteps()
+ .get(2), slcExecRetrieved.getSteps().get(2));
+ }
+
+ @Override
+ protected String getApplicationContextLocation() {
+ return "org/argeo/slc/hibernate/applicationContext.xml";
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/hibernate/structure/tree/TreeSPathDaoHibernateTest.java b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/hibernate/structure/tree/TreeSPathDaoHibernateTest.java
new file mode 100644
index 000000000..3cb906b24
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/hibernate/structure/tree/TreeSPathDaoHibernateTest.java
@@ -0,0 +1,29 @@
+package org.argeo.slc.hibernate.structure.tree;
+
+import org.argeo.slc.core.structure.tree.TreeSPath;
+import org.argeo.slc.dao.structure.tree.TreeSPathDao;
+import org.argeo.slc.unit.AbstractSpringTestCase;
+
+public class TreeSPathDaoHibernateTest extends AbstractSpringTestCase {
+
+ public void testCreate() {
+ TreeSPathDao treeSPathDao = getBean(TreeSPathDao.class);
+
+ String pathParentStr = "/root/testParent";
+ String pathStr = pathParentStr + "/test";
+ TreeSPath path = TreeSPath.parseToCreatePath(pathStr);
+ treeSPathDao.create(path);
+
+ TreeSPath pathChild = treeSPathDao.getTreeSPath(pathStr);
+ assertEquals(path, pathChild);
+
+ TreeSPath pathParent = treeSPathDao.getTreeSPath(pathParentStr);
+ assertEquals(path.getParent(), pathParent);
+ }
+
+ @Override
+ protected String getApplicationContextLocation() {
+ return "org/argeo/slc/hibernate/applicationContext.xml";
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/hibernate/structure/tree/TreeSRegistryDaoHibernateTest.java b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/hibernate/structure/tree/TreeSRegistryDaoHibernateTest.java
new file mode 100644
index 000000000..c9d0a99cd
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/hibernate/structure/tree/TreeSRegistryDaoHibernateTest.java
@@ -0,0 +1,41 @@
+package org.argeo.slc.hibernate.structure.tree;
+
+import org.argeo.slc.core.structure.SimpleSElement;
+import org.argeo.slc.core.structure.tree.TreeSPath;
+import org.argeo.slc.core.structure.tree.TreeSRegistry;
+import org.argeo.slc.dao.structure.tree.TreeSPathDao;
+import org.argeo.slc.dao.structure.tree.TreeSRegistryDao;
+import org.argeo.slc.unit.AbstractSpringTestCase;
+
+public class TreeSRegistryDaoHibernateTest extends AbstractSpringTestCase {
+
+ public void testCreate() {
+ TreeSRegistryDao treeSRegistryDao = getBean(TreeSRegistryDao.class);
+
+ TreeSPathDao treeSPathDao = (TreeSPathDao) getContext().getBean(
+ "treeSPathDao");
+
+ TreeSPath root = TreeSPath.parseToCreatePath("/root");
+ TreeSPath path = root.createChild("test");
+
+ treeSPathDao.create(root);
+ treeSPathDao.create(path);
+
+ TreeSRegistry registry = new TreeSRegistry();
+ registry.setStatus(TreeSRegistry.STATUS_ACTIVE);
+ String desc = "desc";
+ registry.register(path, new SimpleSElement(desc));
+
+ treeSRegistryDao.create(registry);
+
+ TreeSRegistry registry2 = treeSRegistryDao.getActiveTreeSRegistry();
+ SimpleSElement element = registry2.getElements().get(path);
+ assertEquals(desc, element.getLabel());
+ }
+
+ @Override
+ protected String getApplicationContextLocation() {
+ return "org/argeo/slc/hibernate/applicationContext.xml";
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/hibernate/test/tree/CastorTestResultDaoHibernateTest.java b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/hibernate/test/tree/CastorTestResultDaoHibernateTest.java
new file mode 100644
index 000000000..4b5d6bd1f
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/hibernate/test/tree/CastorTestResultDaoHibernateTest.java
@@ -0,0 +1,44 @@
+package org.argeo.slc.hibernate.test.tree;
+
+import org.springframework.oxm.Marshaller;
+import org.springframework.oxm.Unmarshaller;
+import org.springframework.xml.transform.StringResult;
+import org.springframework.xml.transform.StringSource;
+
+import org.argeo.slc.core.structure.tree.TreeSPath;
+import org.argeo.slc.core.test.tree.TreeTestResult;
+import org.argeo.slc.core.test.tree.TreeTestResultTestUtils;
+import org.argeo.slc.dao.test.tree.TreeTestResultDao;
+import org.argeo.slc.unit.AbstractSpringTestCase;
+import org.argeo.slc.unit.test.tree.UnitTestTreeUtil;
+
+public class CastorTestResultDaoHibernateTest extends AbstractSpringTestCase {
+
+ public void testUnmarshallAndCreate() throws Exception {
+ TreeTestResult ttr = TreeTestResultTestUtils
+ .createCompleteTreeTestResult();
+
+ StringResult result = new StringResult();
+ getBean(Marshaller.class).marshal(ttr, result);
+
+ StringSource source = new StringSource(result.toString());
+ TreeTestResult ttrUnm = (TreeTestResult) getBean(Unmarshaller.class)
+ .unmarshal(source);
+
+ for (TreeSPath path : ttrUnm.getResultParts().keySet()) {
+ log.debug("Path: " + path.getClass() + ": " + path);
+ }
+
+ TreeTestResultDao ttrDao = getBean(TreeTestResultDao.class);
+ ttrDao.create(ttrUnm);
+ TreeTestResult ttrPersist = ttrDao.getTestResult(ttr.getUuid());
+
+ UnitTestTreeUtil.assertTreeTestResult(ttr, ttrPersist);
+ }
+
+ @Override
+ protected String getApplicationContextLocation() {
+ return "org/argeo/slc/hibernate/withCastor.xml";
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/hibernate/test/tree/TreeTestResultCollectionDaoHibernateTest.java b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/hibernate/test/tree/TreeTestResultCollectionDaoHibernateTest.java
new file mode 100644
index 000000000..786ff527b
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/hibernate/test/tree/TreeTestResultCollectionDaoHibernateTest.java
@@ -0,0 +1,52 @@
+package org.argeo.slc.hibernate.test.tree;
+
+import org.argeo.slc.core.test.tree.TreeTestResult;
+import org.argeo.slc.core.test.tree.TreeTestResultCollection;
+import org.argeo.slc.core.test.tree.TreeTestResultTestUtils;
+import org.argeo.slc.dao.test.tree.TreeTestResultCollectionDao;
+import org.argeo.slc.dao.test.tree.TreeTestResultDao;
+import org.argeo.slc.unit.AbstractSpringTestCase;
+import org.argeo.slc.unit.test.tree.UnitTestTreeUtil;
+
+public class TreeTestResultCollectionDaoHibernateTest extends
+ AbstractSpringTestCase {
+
+ public void testScenario() {
+ TreeTestResultDao ttrDao = getBean(TreeTestResultDao.class);
+ TreeTestResultCollectionDao ttrcDao = getBean(TreeTestResultCollectionDao.class);
+
+ String ttrcName = "testCollection";
+
+ TreeTestResult ttr1 = TreeTestResultTestUtils
+ .createCompleteTreeTestResult();
+ ttrDao.create(ttr1);
+
+ TreeTestResultCollection ttrc = new TreeTestResultCollection(ttrcName);
+ ttrcDao.create(ttrc);
+
+ ttrc.getResults().add(ttr1);
+ ttrcDao.update(ttrc);
+
+ TreeTestResult ttr2 = TreeTestResultTestUtils
+ .createCompleteTreeTestResult();
+ ttrDao.create(ttr2);
+
+ ttrc.getResults().add(ttr2);
+ ttrcDao.update(ttrc);
+
+ ttrc.getResults().remove(ttr1);
+ ttrcDao.update(ttrc);
+
+ TreeTestResultCollection ttrcPersist = ttrcDao
+ .getTestResultCollection(ttrcName);
+ assertEquals(1, ttrcPersist.getResults().size());
+ UnitTestTreeUtil.assertTreeTestResult(ttr2, ttrcPersist.getResults()
+ .iterator().next());
+ }
+
+ @Override
+ protected String getApplicationContextLocation() {
+ return "org/argeo/slc/hibernate/applicationContext.xml";
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/hibernate/test/tree/TreeTestResultDaoHibernateTest.java b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/hibernate/test/tree/TreeTestResultDaoHibernateTest.java
new file mode 100644
index 000000000..c1808da13
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/hibernate/test/tree/TreeTestResultDaoHibernateTest.java
@@ -0,0 +1,119 @@
+package org.argeo.slc.hibernate.test.tree;
+
+import static org.argeo.slc.core.test.tree.TreeTestResultTestUtils.createCompleteTreeTestResult;
+import static org.argeo.slc.core.test.tree.TreeTestResultTestUtils.createSimpleTreeTestResult;
+
+import java.util.Date;
+
+import org.argeo.slc.core.structure.SimpleSElement;
+import org.argeo.slc.core.structure.tree.TreeSPath;
+import org.argeo.slc.core.structure.tree.TreeSRegistry;
+import org.argeo.slc.core.test.SimpleResultPart;
+import org.argeo.slc.core.test.TestStatus;
+import org.argeo.slc.core.test.tree.TreeTestResult;
+import org.argeo.slc.core.test.tree.TreeTestResultTestUtils;
+import org.argeo.slc.dao.test.tree.TreeTestResultDao;
+import org.argeo.slc.unit.AbstractSpringTestCase;
+import org.argeo.slc.unit.test.tree.UnitTestTreeUtil;
+
+public class TreeTestResultDaoHibernateTest extends AbstractSpringTestCase {
+ private TreeTestResultDao testResultDao = null;
+
+ @Override
+ public void setUp() {
+ testResultDao = (TreeTestResultDao) getContext().getBean(
+ "testResultDao");
+ }
+
+ public void testCreate() {
+
+ TreeTestResult ttr = createCompleteTreeTestResult();
+ testResultDao.create(ttr);
+
+ TreeTestResult ttrPersisted = (TreeTestResult) testResultDao
+ .getTestResult(ttr.getUuid());
+
+ UnitTestTreeUtil.assertTreeTestResult(ttr, ttrPersisted);
+ }
+
+ public void testUpdate() {
+ TreeTestResult ttr = createCompleteTreeTestResult();
+ testResultDao.create(ttr);
+
+ TreeTestResult ttrUpdated = (TreeTestResult) testResultDao
+ .getTestResult(ttr.getUuid());
+
+ // Modifying ttrUpdated
+
+ /**
+ * this closeDate update commented because the assertTreeTestResult will
+ * find a unexpected discrepancy in the date.
+ * ttrUpdated.setCloseDate(new Date());
+ */
+
+ String pathStr = "/test";
+ TreeSPath path = TreeSPath.parseToCreatePath(pathStr);
+
+ TreeSRegistry registry = new TreeSRegistry();
+ SimpleSElement elem = new SimpleSElement("Unit Test");
+ elem.getTags().put("myTag", "myTagValue");
+ registry.register(path, elem);
+
+ ttrUpdated.notifyCurrentPath(registry, path);
+
+ ttrUpdated.addResultPart(TreeTestResultTestUtils
+ .createSimpleResultPartPassed());
+ ttrUpdated.addResultPart(TreeTestResultTestUtils
+ .createSimpleResultPartFailed());
+ ttrUpdated.addResultPart(TreeTestResultTestUtils
+ .createSimpleResultPartError());
+
+ testResultDao.update(ttrUpdated);
+
+ // comparison of ttrUpdated and ttrRetrieved
+ TreeTestResult ttrRetrieved = (TreeTestResult) testResultDao
+ .getTestResult(ttr.getUuid());
+
+ UnitTestTreeUtil.assertTreeTestResult(ttrRetrieved, ttrUpdated);
+ }
+
+ public void testMultipleUpdateScenario() throws Exception{
+ TreeSRegistry registry = new TreeSRegistry();
+
+ TreeSPath path = new TreeSPath("/root/test");
+ SimpleSElement elem = new SimpleSElement("Unit Test");
+ elem.getTags().put("myTag", "myTagValue");
+ registry.register(path, elem);
+
+ TreeTestResult ttr = createSimpleTreeTestResult();
+ ttr.notifyCurrentPath(registry, path);
+ ttr.addResultPart(new SimpleResultPart(TestStatus.PASSED,"First test"));
+
+ testResultDao.create(ttr);
+
+ path = new TreeSPath("/root/test2/subtest");
+ elem = new SimpleSElement("Sub Test");
+ elem.getTags().put("myTag", "myTagValue");
+ registry.register(path, elem);
+
+ ttr.notifyCurrentPath(registry, path);
+ ttr.addResultPart(new SimpleResultPart(TestStatus.PASSED,"Second test"));
+
+ testResultDao.update(ttr);
+
+ ttr.notifyCurrentPath(registry, path);
+ ttr.addResultPart(new SimpleResultPart(TestStatus.PASSED,"Third test with same path"));
+
+ testResultDao.update(ttr);
+
+ ttr.close();
+
+ testResultDao.close(ttr.getUuid(), ttr.getCloseDate());
+ }
+
+ @Override
+ protected String getApplicationContextLocation() {
+ return "org/argeo/slc/hibernate/applicationContext.xml";
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/ws/SlcAntWsIntegrationTest.java b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/ws/SlcAntWsIntegrationTest.java
new file mode 100644
index 000000000..7b3d662f7
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/ws/SlcAntWsIntegrationTest.java
@@ -0,0 +1,25 @@
+package org.argeo.slc.ws;
+
+import java.net.URL;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.argeo.slc.ant.AntRunner;
+import org.argeo.slc.unit.AbstractSpringTestCase;
+
+public class SlcAntWsIntegrationTest extends AbstractSpringTestCase {
+ private Log log = LogFactory.getLog(getClass());
+
+ public void testSimpleRun() {
+ // AntRegistryUtil.runAll(getClass().getResource(
+ // "/org/argeo/slc/ant/build.xml"), "test", null);
+
+ URL url = getClass().getResource("/org/argeo/slc/ant/build.xml");
+ log.info("Run Ant file from URL: " + url);
+ AntRunner antRunner = new AntRunner(getContext(), url, "test");
+
+ antRunner.run();
+ }
+
+}
diff --git a/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/ws/SlcExecutionWsIntegrationTest.java b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/ws/SlcExecutionWsIntegrationTest.java
new file mode 100644
index 000000000..2aa29e2ab
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/ws/SlcExecutionWsIntegrationTest.java
@@ -0,0 +1,29 @@
+package org.argeo.slc.ws;
+
+import org.springframework.ws.client.core.WebServiceTemplate;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.argeo.slc.core.process.SlcExecution;
+import org.argeo.slc.core.process.SlcExecutionTestUtils;
+import org.argeo.slc.msg.process.SlcExecutionRequest;
+import org.argeo.slc.unit.AbstractSpringTestCase;
+
+public class SlcExecutionWsIntegrationTest extends AbstractSpringTestCase {
+ private Log log = LogFactory.getLog(getClass());
+
+ public void testSendSlcExecutionrequest() {
+ WebServiceTemplate template = getBean(WebServiceTemplate.class);
+ SlcExecution slcExec = SlcExecutionTestUtils.createSimpleSlcExecution();
+
+ SlcExecutionRequest req = new SlcExecutionRequest();
+ req.setSlcExecution(slcExec);
+
+ log.info("Send SlcExecutionRequest for SlcExecution "
+ + slcExec.getUuid());
+
+ Object resp = template.marshalSendAndReceive(req);
+ log.info("Resp: " + resp);
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/ws/TreeTestResultWsIntegrationTest.java b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/ws/TreeTestResultWsIntegrationTest.java
new file mode 100644
index 000000000..6e6ffa176
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/java/org/argeo/slc/ws/TreeTestResultWsIntegrationTest.java
@@ -0,0 +1,70 @@
+package org.argeo.slc.ws;
+
+import org.springframework.ws.client.core.WebServiceTemplate;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import static org.argeo.slc.core.test.tree.TreeTestResultTestUtils.createCompleteTreeTestResult;
+import static org.argeo.slc.core.test.tree.TreeTestResultTestUtils.createSimpleResultPartRequest;
+
+import org.argeo.slc.core.test.tree.TreeTestResult;
+import org.argeo.slc.msg.test.tree.CloseTreeTestResultRequest;
+import org.argeo.slc.msg.test.tree.CreateTreeTestResultRequest;
+import org.argeo.slc.msg.test.tree.ResultPartRequest;
+import org.argeo.slc.unit.AbstractSpringTestCase;
+
+public class TreeTestResultWsIntegrationTest extends AbstractSpringTestCase {
+ private Log log = LogFactory.getLog(getClass());
+
+ public void testCreateTreeTestResultRequest() {
+ WebServiceTemplate template = getBean(WebServiceTemplate.class);
+ CreateTreeTestResultRequest req = new CreateTreeTestResultRequest(
+ createCompleteTreeTestResult());
+ req.getTreeTestResult().close();// in order to avoid unclosed in test db
+
+ log.info("Send CreateTreeTestResultRequest for result "
+ + req.getTreeTestResult().getUuid());
+
+ Object resp = template.marshalSendAndReceive(req);
+ log.info("Resp: " + resp);
+ }
+
+ public void testResultPartRequest() {
+ WebServiceTemplate template = getBean(WebServiceTemplate.class);
+ TreeTestResult ttr = createCompleteTreeTestResult();
+ ttr.close();// in order to avoid unclosed in test db
+ CreateTreeTestResultRequest reqCreate = new CreateTreeTestResultRequest(
+ ttr);
+ log.info("Send CreateTreeTestResultRequest for result "
+ + reqCreate.getTreeTestResult().getUuid());
+ template.marshalSendAndReceive(reqCreate);
+
+ ResultPartRequest req = createSimpleResultPartRequest(ttr);
+
+ log.info("Send ResultPartRequest for result " + req.getResultUuid());
+ Object resp = template.marshalSendAndReceive(req);
+ log.info("Resp: " + resp);
+ }
+
+ public void testCloseTreeTestResultRequest() {
+ WebServiceTemplate template = getBean(WebServiceTemplate.class);
+
+ TreeTestResult ttr = createCompleteTreeTestResult();
+ CreateTreeTestResultRequest reqCreate = new CreateTreeTestResultRequest(
+ ttr);
+ log.info("Send CreateTreeTestResultRequest for result "
+ + reqCreate.getTreeTestResult().getUuid());
+ template.marshalSendAndReceive(reqCreate);
+
+ ttr.close();
+ CloseTreeTestResultRequest req = new CloseTreeTestResultRequest(ttr
+ .getUuid(), ttr.getCloseDate());
+
+ log.info("Send CloseTreeTestResultRequest for result "
+ + req.getResultUuid());
+
+ Object resp = template.marshalSendAndReceive(req);
+ log.info("Resp: " + resp);
+ }
+}
diff --git a/org.argeo.slc.hibernate/src/test/resources/log4j.properties b/org.argeo.slc.hibernate/src/test/resources/log4j.properties
new file mode 100644
index 000000000..605a28c48
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/resources/log4j.properties
@@ -0,0 +1,27 @@
+# Set root logger level to DEBUG and its only appender to A1.
+log4j.rootLogger=INFO, console
+
+## Levels
+# Slc
+log4j.logger.org.argeo=DEBUG
+
+# Castor
+log4j.logger.org.exolab.castor=WARN
+
+# Spring
+log4j.logger.org.springframework=INFO
+# Hibernate
+log4j.logger.org.hibernate=WARN
+#log4j.logger.org.hibernate.SQL=TRACE
+#log4j.logger.org.hibernate.tool.hbm2ddl=TRACE
+#log4j.logger.org.hibernate.type=TRACE
+
+
+## Appenders
+# A1 is set to be a ConsoleAppender.
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+
+# A1 uses PatternLayout.
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c%n
+
diff --git a/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/ant/applicationContext.xml b/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/ant/applicationContext.xml
new file mode 100644
index 000000000..6ff9b8522
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/ant/applicationContext.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/ant/build.xml b/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/ant/build.xml
new file mode 100644
index 000000000..f2ea5c52c
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/ant/build.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/ant/nonDepContext.xml b/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/ant/nonDepContext.xml
new file mode 100644
index 000000000..56da88a8b
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/ant/nonDepContext.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+ toto
+
+
+ toto
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/castor/applicationContext.xml b/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/castor/applicationContext.xml
new file mode 100644
index 000000000..7a89af927
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/castor/applicationContext.xml
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/core/process/applicationContext.xml b/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/core/process/applicationContext.xml
new file mode 100644
index 000000000..899daf548
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/core/process/applicationContext.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/core/test/context/applicationContext.xml b/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/core/test/context/applicationContext.xml
new file mode 100644
index 000000000..e45899c11
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/core/test/context/applicationContext.xml
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/core/test/tree/applicationContext.xml b/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/core/test/tree/applicationContext.xml
new file mode 100644
index 000000000..9601c3301
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/core/test/tree/applicationContext.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/hibernate/applicationContext.xml b/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/hibernate/applicationContext.xml
new file mode 100644
index 000000000..31158cf49
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/hibernate/applicationContext.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/hibernate/withCastor.xml b/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/hibernate/withCastor.xml
new file mode 100644
index 000000000..ae7f97114
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/hibernate/withCastor.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/ws/applicationContext.xml b/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/ws/applicationContext.xml
new file mode 100644
index 000000000..a94d128b3
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/ws/applicationContext.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
diff --git a/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/ws/execution.xml b/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/ws/execution.xml
new file mode 100644
index 000000000..bdb071b0c
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/ws/execution.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/ws/result.xml b/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/ws/result.xml
new file mode 100644
index 000000000..ce5442d5e
--- /dev/null
+++ b/org.argeo.slc.hibernate/src/test/resources/org/argeo/slc/ws/result.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
--
2.39.2