]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/tree/TreeTestResult.java
Improve logging
[gpl/argeo-slc.git] / runtime / org.argeo.slc.core / src / main / java / org / argeo / slc / core / test / tree / TreeTestResult.java
1 /*
2 * Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org>
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.argeo.slc.core.test.tree;
18
19 import java.io.Serializable;
20 import java.util.ArrayList;
21 import java.util.Date;
22 import java.util.List;
23 import java.util.SortedMap;
24 import java.util.TreeMap;
25 import java.util.UUID;
26 import java.util.Vector;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.argeo.slc.SlcException;
31 import org.argeo.slc.core.attachment.Attachment;
32 import org.argeo.slc.core.attachment.AttachmentsEnabled;
33 import org.argeo.slc.core.attachment.SimpleAttachment;
34 import org.argeo.slc.core.structure.tree.TreeSPath;
35 import org.argeo.slc.structure.StructureAware;
36 import org.argeo.slc.structure.StructureElement;
37 import org.argeo.slc.structure.StructureRegistry;
38 import org.argeo.slc.test.TestResult;
39 import org.argeo.slc.test.TestResultListener;
40 import org.argeo.slc.test.TestResultPart;
41 import org.argeo.slc.test.TestRun;
42 import org.argeo.slc.test.TestRunAware;
43
44 /**
45 * Complex implementation of a test result compatible with a tree based
46 * structure.
47 */
48 public class TreeTestResult implements TestResult, StructureAware<TreeSPath>,
49 Comparable<TreeTestResult>, AttachmentsEnabled, Serializable {
50
51 private static final long serialVersionUID = 1L;
52 private final static Log log = LogFactory.getLog(TreeTestResult.class);
53
54 // Persistence data
55 private String uuid = UUID.randomUUID().toString();
56 private Date closeDate;
57
58 private SortedMap<TreeSPath, PartSubList> resultParts = new TreeMap<TreeSPath, PartSubList>();
59 private SortedMap<TreeSPath, StructureElement> elements = new TreeMap<TreeSPath, StructureElement>();
60 private List<SimpleAttachment> attachments = new ArrayList<SimpleAttachment>();
61
62 // Headers. Used to accelerate request on a specific test result.
63 private SortedMap<String, String> attributes = new TreeMap<String, String>();
64
65 // Runtime Data
66 private TreeSPath currentPath;
67 private transient TestRun currentTestRun;
68 private Boolean warnIfAlreadyClosed = true;
69 private Boolean strictChecks = false;
70 // TODO is it really necessary closeDate == null ?
71 private Boolean isClosed = false;
72
73 private Boolean cache = true;
74
75 private transient List<TestResultListener<TreeTestResult>> listeners = new Vector<TestResultListener<TreeTestResult>>();
76
77 /** Sets the list of listeners. */
78 public void setListeners(List<TestResultListener<TreeTestResult>> listeners) {
79 this.listeners = listeners;
80 }
81
82 public void addResultPart(TestResultPart part) {
83 if (isClosed)
84 notifyIssue(
85 "Trying to add result parts to an already closed result,"
86 + " consider changing the scope of this test result:"
87 + " you are referencing the same stored data with each new call.",
88 null);
89
90 if (currentPath == null)
91 throw new SlcException("No current path set.");
92
93 if (cache) {
94 PartSubList subList = resultParts.get(currentPath);
95 if (subList == null) {
96 subList = new PartSubList();
97 resultParts.put(currentPath, subList);
98 }
99 subList.getParts().add(part);
100 }
101
102 if (part instanceof TestRunAware && currentTestRun != null) {
103 ((TestRunAware) part).notifyTestRun(currentTestRun);
104 }
105
106 // notify listeners
107 synchronized (listeners) {
108 for (TestResultListener<TreeTestResult> listener : listeners) {
109 listener.resultPartAdded(this, part);
110 }
111 }
112 }
113
114 protected void notifyIssue(String msg, Exception e) {
115 if (strictChecks)
116 throw new SlcException(msg, e);
117 else
118 log.error(msg, e);
119 }
120
121 public void notifyCurrentPath(StructureRegistry<TreeSPath> registry,
122 TreeSPath path) {
123 if (!cache)
124 return;
125
126 if (registry != null) {
127 for (TreeSPath p : path.getHierarchyAsList()) {
128 if (!elements.containsKey(p)) {
129 StructureElement elem = registry.getElement(p);
130 if (elem != null) {
131 elements.put(p, elem);
132 }
133 } else {
134 if (log.isTraceEnabled())
135 log.trace("An element is already registered for path "
136 + p + " and was not updated");
137 }
138
139 }
140 }
141
142 currentPath = path;
143 }
144
145 /** Gets the current path. */
146 public TreeSPath getCurrentPath() {
147 return currentPath;
148 }
149
150 /** Gets all the results structured as a map of <code>PartSubList<code>s. */
151 public SortedMap<TreeSPath, PartSubList> getResultParts() {
152 return resultParts;
153 }
154
155 /**
156 * Used by ORM systems. Changed to public in order to enable jcr persistence
157 */
158 public void setResultParts(SortedMap<TreeSPath, PartSubList> resultParts) {
159 this.resultParts = resultParts;
160 }
161
162 public void close() {
163 if (resultParts.size() == 0) {
164 if (log.isTraceEnabled())
165 log.trace("Test Result #" + getUuid()
166 + " contains no results, no need to close it.");
167 return;
168 }
169
170 if (isClosed) {
171 if (warnIfAlreadyClosed)
172 log.warn("Test Result #" + getUuid()
173 + " already closed. Doing nothing.");
174 return;
175 }
176
177 closeDate = new Date();
178
179 synchronized (listeners) {
180 for (TestResultListener<TreeTestResult> listener : listeners) {
181 listener.close(this);
182 }
183 }
184 isClosed = true;
185
186 if (log.isTraceEnabled())
187 log.trace("Test Result " + getUuid() + " closed.");
188 }
189
190 public Date getCloseDate() {
191 return closeDate;
192 }
193
194 /** Sets the close date (for ORM) */
195 public void setCloseDate(Date closeDate) {
196 this.closeDate = closeDate;
197 }
198
199 public void notifyTestRun(TestRun testRun) {
200 currentTestRun = testRun;
201 }
202
203 public SortedMap<TreeSPath, StructureElement> getElements() {
204 return elements;
205 }
206
207 public void setElements(SortedMap<TreeSPath, StructureElement> pathNames) {
208 this.elements = pathNames;
209 }
210
211 public String getUuid() {
212 return uuid;
213 }
214
215 public void setUuid(String uuid) {
216 this.uuid = uuid;
217 }
218
219 public SortedMap<TreeSPath, StructureElement> getRelatedElements(
220 TreeSPath path) {
221 if (path == null)
222 throw new SlcException(
223 "Cannot retrieve element for a null path in result #"
224 + uuid);
225
226 SortedMap<TreeSPath, StructureElement> relatedElements = new TreeMap<TreeSPath, StructureElement>();
227 List<TreeSPath> hierarchy = path.getHierarchyAsList();
228 for (TreeSPath currPath : elements.keySet()) {
229 if (hierarchy.contains(currPath)) {
230 relatedElements.put(currPath, elements.get(currPath));
231 }
232 }
233 return relatedElements;
234 }
235
236 public TestRun getCurrentTestRun() {
237 return currentTestRun;
238 }
239
240 public int compareTo(TreeTestResult ttr2) {
241 TreeTestResult ttr1 = this;
242 if (ttr1.getCloseDate() != null && ttr2.getCloseDate() != null) {
243 if (ttr1.getCloseDate().equals(ttr2.getCloseDate()))
244 return compareUuid(ttr1, ttr2);
245 else
246 return -ttr1.getCloseDate().compareTo(ttr2.getCloseDate());
247 } else if (ttr1.getCloseDate() != null && ttr2.getCloseDate() == null) {
248 return 1;
249 } else if (ttr1.getCloseDate() == null && ttr2.getCloseDate() != null) {
250 return -1;
251 } else {
252 return compareUuid(ttr1, ttr2);
253 }
254 }
255
256 protected int compareUuid(TestResult ttr1, TestResult ttr2) {
257 if (ttr1.getUuid() == null || ttr2.getUuid() == null)
258 throw new SlcException(
259 "Cannot compare tree test result with null uuid");
260 else {
261 if (ttr1.getUuid().equals(ttr2.getUuid()))
262 return 0;
263 return ttr1.getUuid().compareTo(ttr2.getUuid());
264 }
265 }
266
267 public boolean equals(Object obj) {
268 if (obj instanceof TestResult)
269 return compareUuid(this, ((TestResult) obj)) == 0;
270 else
271 return false;
272 }
273
274 public int hashCode() {
275 if (uuid != null)
276 return uuid.hashCode();
277 else
278 return super.hashCode();
279 }
280
281 public SortedMap<String, String> getAttributes() {
282 return attributes;
283 }
284
285 public void setAttributes(SortedMap<String, String> attributes) {
286 this.attributes = attributes;
287 }
288
289 public void setWarnIfAlreadyClosed(Boolean warnIfAlreadyClosed) {
290 this.warnIfAlreadyClosed = warnIfAlreadyClosed;
291 }
292
293 public List<SimpleAttachment> getAttachments() {
294 return attachments;
295 }
296
297 public void setAttachments(List<SimpleAttachment> attachments) {
298 this.attachments = attachments;
299 }
300
301 public void addAttachment(Attachment attachment) {
302 attachments.add((SimpleAttachment) attachment);
303 synchronized (listeners) {
304 for (TestResultListener<TreeTestResult> listener : listeners) {
305 if (listener instanceof TreeTestResultListener)
306 ((TreeTestResultListener) listener).addAttachment(this,
307 attachment);
308 }
309 }
310 }
311
312 public void setStrictChecks(Boolean strictChecks) {
313 this.strictChecks = strictChecks;
314 }
315
316 /**
317 * Whether information should be stored in thsi object or simply forwarded
318 * to teh listeners.
319 */
320 public void setCache(Boolean cache) {
321 this.cache = cache;
322 }
323
324 }