]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrResultListener.java
Refactor JCR utils and home usage
[gpl/argeo-slc.git] / runtime / org.argeo.slc.support.jcr / src / main / java / org / argeo / slc / jcr / execution / JcrResultListener.java
1 /*
2 * Copyright (C) 2007-2012 Mathieu Baudier
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 package org.argeo.slc.jcr.execution;
17
18 import java.util.Collections;
19 import java.util.GregorianCalendar;
20 import java.util.HashMap;
21 import java.util.Map;
22
23 import javax.jcr.Node;
24 import javax.jcr.NodeIterator;
25 import javax.jcr.Property;
26 import javax.jcr.PropertyIterator;
27 import javax.jcr.RepositoryException;
28 import javax.jcr.Session;
29 import javax.jcr.query.Query;
30 import javax.jcr.query.QueryManager;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.argeo.jcr.JcrUtils;
35 import org.argeo.slc.SlcException;
36 import org.argeo.slc.core.attachment.Attachment;
37 import org.argeo.slc.core.structure.SimpleSElement;
38 import org.argeo.slc.core.structure.tree.TreeSPath;
39 import org.argeo.slc.core.test.SimpleResultPart;
40 import org.argeo.slc.core.test.tree.PartSubList;
41 import org.argeo.slc.core.test.tree.TreeTestResult;
42 import org.argeo.slc.core.test.tree.TreeTestResultListener;
43 import org.argeo.slc.jcr.SlcJcrUtils;
44 import org.argeo.slc.jcr.SlcNames;
45 import org.argeo.slc.jcr.SlcTypes;
46 import org.argeo.slc.test.TestResultPart;
47 import org.argeo.slc.test.TestStatus;
48
49 /**
50 * Persists results in JCR by listening to {@link TreeTestResult}. This is to
51 * facilitate transition from legacy approaches and should not be used in new
52 * implementations.
53 */
54 public class JcrResultListener implements TreeTestResultListener, SlcNames {
55 private final static Log log = LogFactory.getLog(JcrResultListener.class);
56
57 private Session session;
58
59 /** Caches the mapping between SLC uuids and internal JCR identifiers */
60 private Map<String, String> uuidToIdentifier = Collections
61 .synchronizedMap(new HashMap<String, String>());
62
63 public void resultPartAdded(TreeTestResult testResult,
64 TestResultPart testResultPart) {
65 try {
66 String uuid = testResult.getUuid();
67 Node resultNode = getResultNode(uuid);
68 if (resultNode == null) {
69 resultNode = createResultNode(testResult);
70 // session.save();
71 }
72 String partParentPath;
73 TreeSPath currentPath = testResult.getCurrentPath();
74 if (currentPath != null) {
75 String subPath = currentPath.getAsUniqueString();
76 partParentPath = resultNode.getPath() + subPath;
77 } else {
78 partParentPath = resultNode.getPath();
79 // TODO create some depth?
80 }
81
82 Node partParentNode;
83 if (session.itemExists(partParentPath)) {
84 partParentNode = session.getNode(partParentPath);
85 } else {
86 partParentNode = JcrUtils.mkdirs(session, partParentPath);
87 // session.save();
88 }
89 // create part node
90 SimpleSElement element = null;
91 if (testResult.getElements().containsKey(currentPath)) {
92 element = (SimpleSElement) testResult.getElements().get(
93 currentPath);
94 }
95
96 String elementLabel = element != null && element.getLabel() != null
97 && !element.getLabel().trim().equals("") ? element
98 .getLabel() : null;
99 String partNodeName = elementLabel != null ? JcrUtils
100 .replaceInvalidChars(elementLabel, '_') : Long
101 .toString(System.currentTimeMillis());
102
103 Node resultPartNode = partParentNode.addNode(partNodeName,
104 SlcTypes.SLC_CHECK);
105 resultPartNode.setProperty(SLC_SUCCESS,
106 testResultPart.getStatus() == TestStatus.PASSED);
107 if (elementLabel != null)
108 resultPartNode.setProperty(Property.JCR_TITLE, elementLabel);
109 if (testResultPart.getMessage() != null)
110 resultPartNode.setProperty(SLC_MESSAGE,
111 testResultPart.getMessage());
112 if (testResultPart.getExceptionMessage() != null)
113 resultPartNode.setProperty(SLC_ERROR_MESSAGE,
114 testResultPart.getExceptionMessage());
115 // JcrUtils.debug(resultPartNode);
116
117 JcrUtils.updateLastModified(resultNode);
118
119 if (element != null) {
120 element = (SimpleSElement) testResult.getElements().get(
121 currentPath);
122 if (log.isTraceEnabled())
123 log.trace(" Path= " + currentPath + ", part="
124 + testResultPart.getMessage());
125 for (Map.Entry<String, String> tag : element.getTags()
126 .entrySet()) {
127 String tagNodeName = JcrUtils.replaceInvalidChars(
128 tag.getKey(), '_');
129 // log.debug("key=" + tag.getKey() + ", tagNodeName="
130 // + tagNodeName);
131 Node tagNode = resultPartNode.addNode(tagNodeName,
132 SlcTypes.SLC_PROPERTY);
133 tagNode.setProperty(SLC_NAME, tag.getKey());
134 tagNode.setProperty(SLC_VALUE, tag.getValue());
135 }
136 }
137
138 session.save();
139 } catch (RepositoryException e) {
140 JcrUtils.discardQuietly(session);
141 log.error("Cannot add result part " + testResultPart + " to "
142 + testResult, e);
143 // throw new SlcException("Cannot add result part " + testResultPart
144 // + " to " + testResult, e);
145 }
146
147 }
148
149 /** @return null if does not exist */
150 protected Node getResultNode(String uuid) throws RepositoryException {
151 Node resultNode;
152 if (uuidToIdentifier.containsKey(uuid)) {
153 return session.getNodeByIdentifier(uuidToIdentifier.get(uuid));
154 } else {
155 Query q = session
156 .getWorkspace()
157 .getQueryManager()
158 .createQuery(
159 "select * from [slc:result] where [slc:uuid]='"
160 + uuid + "'", Query.JCR_SQL2);
161 resultNode = JcrUtils.querySingleNode(q);
162 if (resultNode != null)
163 uuidToIdentifier.put(uuid, resultNode.getIdentifier());
164 }
165 return resultNode;
166 }
167
168 protected Node createResultNode(TreeTestResult testResult)
169 throws RepositoryException {
170 String uuid = testResult.getUuid();
171 String path = SlcJcrUtils.createResultPath(session, uuid);
172 Node resultNode = JcrUtils.mkdirs(session, path, SlcTypes.SLC_TEST_RESULT);
173 resultNode.setProperty(SLC_UUID, uuid);
174 for (Map.Entry<String, String> entry : testResult.getAttributes()
175 .entrySet()) {
176 resultNode.setProperty(entry.getKey(), entry.getValue());
177 }
178
179 uuidToIdentifier.put(uuid, resultNode.getIdentifier());
180 return resultNode;
181 }
182
183 public void close(TreeTestResult testResult) {
184 try {
185 String uuid = testResult.getUuid();
186 Node resultNode = getResultNode(uuid);
187 if (resultNode == null)
188 resultNode = createResultNode(testResult);
189 JcrUtils.updateLastModified(resultNode);
190 GregorianCalendar closeDate = new GregorianCalendar();
191 closeDate.setTime(testResult.getCloseDate());
192 resultNode.setProperty(SLC_COMPLETED, closeDate);
193
194 uuidToIdentifier.remove(uuid);
195 session.save();
196
197 if (log.isDebugEnabled())
198 log.debug("Closed test result " + uuid);
199 } catch (RepositoryException e) {
200 JcrUtils.discardQuietly(session);
201 log.error("Cannot close result " + testResult, e);
202 // throw new SlcException("Cannot close result " + testResult, e);
203 }
204
205 }
206
207 public void addAttachment(TreeTestResult testResult, Attachment attachment) {
208
209 }
210
211 public void setSession(Session session) {
212 this.session = session;
213 }
214
215 /**
216 * Creates and populates a {@link TreeTestResult} from the related result
217 * node. Meant to simplify migration of legacy applications. This is no
218 * stable API.
219 */
220 public static TreeTestResult nodeToTreeTestResult(Node resultNode) {
221 try {
222 String resultPath = resultNode.getPath();
223 TreeTestResult ttr = new TreeTestResult();
224 // base properties
225 ttr.setUuid(resultNode.getProperty(SLC_UUID).getString());
226 if (resultNode.hasProperty(SLC_COMPLETED))
227 ttr.setCloseDate(resultNode.getProperty(SLC_COMPLETED)
228 .getDate().getTime());
229 // attributes
230 for (PropertyIterator pit = resultNode.getProperties(); pit
231 .hasNext();) {
232 Property p = pit.nextProperty();
233 if (p.getName().indexOf(':') < 0) {
234 ttr.getAttributes().put(p.getName(), p.getString());
235 }
236 }
237
238 QueryManager qm = resultNode.getSession().getWorkspace()
239 .getQueryManager();
240 String statement = "SELECT * FROM [" + SlcTypes.SLC_CHECK
241 + "] WHERE ISDESCENDANTNODE(['" + resultPath + "'])";
242 NodeIterator nit = qm.createQuery(statement, Query.JCR_SQL2)
243 .execute().getNodes();
244 while (nit.hasNext()) {
245 Node checkNode = nit.nextNode();
246 String relPath = checkNode.getPath().substring(
247 resultPath.length());
248 TreeSPath tsp = new TreeSPath(relPath);
249
250 // result part
251 SimpleResultPart srp = new SimpleResultPart();
252 if (checkNode.getProperty(SLC_SUCCESS).getBoolean())
253 srp.setStatus(TestStatus.PASSED);
254 else if (checkNode.hasProperty(SLC_ERROR_MESSAGE))
255 srp.setStatus(TestStatus.ERROR);
256 else
257 srp.setStatus(TestStatus.FAILED);
258 if (checkNode.hasProperty(SLC_MESSAGE))
259 srp.setMessage(checkNode.getProperty(SLC_MESSAGE)
260 .getString());
261 if (!ttr.getResultParts().containsKey(tsp))
262 ttr.getResultParts().put(tsp, new PartSubList());
263 ttr.getResultParts().get(tsp).getParts().add(srp);
264
265 // element
266 SimpleSElement elem = new SimpleSElement();
267 if (checkNode.hasProperty(Property.JCR_TITLE))
268 elem.setLabel(checkNode.getProperty(Property.JCR_TITLE)
269 .getString());
270 else
271 elem.setLabel("");// some legacy code expect it to be set
272 for (NodeIterator tagIt = checkNode.getNodes(); tagIt.hasNext();) {
273 Node tagNode = tagIt.nextNode();
274 elem.getTags().put(
275 tagNode.getProperty(SLC_NAME).getString(),
276 tagNode.getProperty(SLC_VALUE).getString());
277 }
278 ttr.getElements().put(tsp, elem);
279 }
280 return ttr;
281 } catch (RepositoryException e) {
282 throw new SlcException("Cannot generate tree test result from "
283 + resultNode, e);
284 }
285 }
286 }