--- /dev/null
+package org.argeo.slc.core.test.tree;\r
+\r
+import java.util.Date;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.SortedMap;\r
+import java.util.TreeMap;\r
+import java.util.Vector;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.argeo.slc.core.SlcException;\r
+import org.argeo.slc.core.structure.StructureAware;\r
+import org.argeo.slc.core.structure.StructureElement;\r
+import org.argeo.slc.core.structure.StructureRegistry;\r
+import org.argeo.slc.core.structure.tree.TreeSPath;\r
+import org.argeo.slc.core.test.TestResult;\r
+import org.argeo.slc.core.test.TestResultListener;\r
+import org.argeo.slc.core.test.TestResultPart;\r
+import org.argeo.slc.core.test.TestRun;\r
+import org.argeo.slc.core.test.TestRunAware;\r
+\r
+/**\r
+ * Complex implementation of a test result compatible with a tree based\r
+ * structure.\r
+ */\r
+public class TreeTestResult implements TestResult, StructureAware<TreeSPath>,\r
+ Comparable<TreeTestResult> {\r
+ private Log log = LogFactory.getLog(TreeTestResult.class);\r
+\r
+ private List<TestResultListener<TreeTestResult>> listeners = new Vector<TestResultListener<TreeTestResult>>();\r
+\r
+ private TreeSPath currentPath;\r
+ private TestRun currentTestRun;\r
+\r
+ private Date closeDate;\r
+\r
+ private Boolean isClosed = false;\r
+\r
+ private Boolean warnIfAlreadyClosed = true;\r
+\r
+ private String uuid;\r
+\r
+ private SortedMap<TreeSPath, PartSubList> resultParts = new TreeMap<TreeSPath, PartSubList>();\r
+ private SortedMap<TreeSPath, StructureElement> elements = new TreeMap<TreeSPath, StructureElement>();\r
+\r
+ private Map<String, String> attributes = new TreeMap<String, String>();\r
+\r
+ /** Sets the list of listeners. */\r
+ public void setListeners(List<TestResultListener<TreeTestResult>> listeners) {\r
+ this.listeners = listeners;\r
+ }\r
+\r
+ public void addResultPart(TestResultPart part) {\r
+ if (isClosed)\r
+ throw new SlcException("Cannot result parts to a closed result");\r
+\r
+ if (currentPath == null)\r
+ throw new SlcException("No current path set.");\r
+\r
+ PartSubList subList = resultParts.get(currentPath);\r
+ if (subList == null) {\r
+ subList = new PartSubList();\r
+ resultParts.put(currentPath, subList);\r
+ }\r
+ if (part instanceof TestRunAware && currentTestRun != null) {\r
+ ((TestRunAware) part).notifyTestRun(currentTestRun);\r
+ }\r
+ subList.getParts().add(part);\r
+\r
+ // notify listeners\r
+ synchronized (listeners) {\r
+ for (TestResultListener<TreeTestResult> listener : listeners) {\r
+ listener.resultPartAdded(this, part);\r
+ }\r
+ }\r
+ }\r
+\r
+ public void notifyCurrentPath(StructureRegistry<TreeSPath> registry,\r
+ TreeSPath path) {\r
+ if (registry != null) {\r
+ for (TreeSPath p : path.getHierarchyAsList()) {\r
+ if (!elements.containsKey(p)) {\r
+ StructureElement elem = registry.getElement(p);\r
+ if (elem != null) {\r
+ elements.put(p, elem);\r
+ }\r
+ } else {\r
+ if (log.isTraceEnabled())\r
+ log.trace("An element is already registered for path "\r
+ + p + " and was not updated");\r
+ }\r
+\r
+ }\r
+ }\r
+\r
+ currentPath = path;\r
+ }\r
+\r
+ /** Gets the current path. */\r
+ public TreeSPath getCurrentPath() {\r
+ return currentPath;\r
+ }\r
+\r
+ /** Gets all the results structured as a map of <code>PartSubList<code>s. */\r
+ public SortedMap<TreeSPath, PartSubList> getResultParts() {\r
+ return resultParts;\r
+ }\r
+\r
+ /** Used by ORM systems. */\r
+ void setResultParts(SortedMap<TreeSPath, PartSubList> resultParts) {\r
+ this.resultParts = resultParts;\r
+ }\r
+\r
+ public void close() {\r
+ if (resultParts.size() == 0) {\r
+ if (log.isTraceEnabled())\r
+ log.trace("Test Result #" + getUuid()\r
+ + " contains no results, no need to close it.");\r
+ return;\r
+ }\r
+\r
+ if (isClosed) {\r
+ if (warnIfAlreadyClosed)\r
+ log.warn("Test Result #" + getUuid()\r
+ + " already closed. Doing nothing.");\r
+ return;\r
+ }\r
+\r
+ closeDate = new Date();\r
+\r
+ synchronized (listeners) {\r
+ for (TestResultListener<TreeTestResult> listener : listeners) {\r
+ listener.close(this);\r
+ }\r
+ listeners.clear();\r
+ }\r
+ isClosed = true;\r
+\r
+ if (log.isTraceEnabled())\r
+ log.trace("Test Result " + getUuid() + " closed.");\r
+ }\r
+\r
+ public Date getCloseDate() {\r
+ return closeDate;\r
+ }\r
+\r
+ /** Sets the close date (for ORM) */\r
+ public void setCloseDate(Date closeDate) {\r
+ this.closeDate = closeDate;\r
+ }\r
+\r
+ public void notifyTestRun(TestRun testRun) {\r
+ currentTestRun = testRun;\r
+ }\r
+\r
+ public SortedMap<TreeSPath, StructureElement> getElements() {\r
+ return elements;\r
+ }\r
+\r
+ public void setElements(SortedMap<TreeSPath, StructureElement> pathNames) {\r
+ this.elements = pathNames;\r
+ }\r
+\r
+ public String getUuid() {\r
+ return uuid;\r
+ }\r
+\r
+ public void setUuid(String uuid) {\r
+ this.uuid = uuid;\r
+ }\r
+\r
+ public SortedMap<TreeSPath, StructureElement> getRelatedElements(\r
+ TreeSPath path) {\r
+ if (path == null)\r
+ throw new SlcException(\r
+ "Cannot retrieve element for a null path in result #"\r
+ + uuid);\r
+\r
+ SortedMap<TreeSPath, StructureElement> relatedElements = new TreeMap<TreeSPath, StructureElement>();\r
+ List<TreeSPath> hierarchy = path.getHierarchyAsList();\r
+ for (TreeSPath currPath : elements.keySet()) {\r
+ if (hierarchy.contains(currPath)) {\r
+ relatedElements.put(currPath, elements.get(currPath));\r
+ }\r
+ }\r
+ return relatedElements;\r
+ }\r
+\r
+ public TestRun getCurrentTestRun() {\r
+ return currentTestRun;\r
+ }\r
+\r
+ public int compareTo(TreeTestResult ttr2) {\r
+ TreeTestResult ttr1 = this;\r
+ if (ttr1.getCloseDate() != null && ttr2.getCloseDate() != null) {\r
+ return -ttr1.getCloseDate().compareTo(ttr2.getCloseDate());\r
+ } else if (ttr1.getCloseDate() != null && ttr2.getCloseDate() == null) {\r
+ return 1;\r
+ } else if (ttr1.getCloseDate() == null && ttr2.getCloseDate() != null) {\r
+ return -1;\r
+ } else {\r
+ return ttr1.getUuid().compareTo(ttr2.getUuid());\r
+ }\r
+ }\r
+\r
+ public Map<String, String> getAttributes() {\r
+ return attributes;\r
+ }\r
+\r
+ public void setAttributes(Map<String, String> attributes) {\r
+ this.attributes = attributes;\r
+ }\r
+\r
+ public void setWarnIfAlreadyClosed(Boolean warnIfAlreadyClosed) {\r
+ this.warnIfAlreadyClosed = warnIfAlreadyClosed;\r
+ }\r
+\r
+}\r