]>
git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.akb/src/main/java/org/argeo/slc/akb/utils/AkbJcrUtils.java
b7d0ba7df6ebf49729538e32e165ab70837c8045
1 package org
.argeo
.slc
.akb
.utils
;
3 import java
.util
.ArrayList
;
6 import java
.util
.TreeMap
;
9 import javax
.jcr
.NodeIterator
;
10 import javax
.jcr
.Property
;
11 import javax
.jcr
.PropertyIterator
;
12 import javax
.jcr
.Repository
;
13 import javax
.jcr
.RepositoryException
;
14 import javax
.jcr
.Session
;
15 import javax
.jcr
.Value
;
16 import javax
.jcr
.query
.Row
;
17 import javax
.jcr
.query
.RowIterator
;
19 import org
.argeo
.jcr
.JcrUtils
;
20 import org
.argeo
.jcr
.PropertyDiff
;
21 import org
.argeo
.slc
.akb
.AkbException
;
22 import org
.argeo
.slc
.akb
.AkbNames
;
23 import org
.argeo
.slc
.akb
.AkbTypes
;
25 /** Some static utils methods that might be factorized in a near future */
26 public class AkbJcrUtils
{
28 // /////////////////////////
31 * Returns the list of environment templates that are visible for the
34 public static List
<Node
> getDefinedTemplate(Session session
) {
36 if (session
.nodeExists(AkbNames
.AKB_TEMPLATES_BASE_PATH
)) {
37 NodeIterator ni
= session
.getNode(
38 AkbNames
.AKB_TEMPLATES_BASE_PATH
).getNodes();
39 List
<Node
> templates
= new ArrayList
<Node
>();
40 while (ni
.hasNext()) {
41 Node currN
= ni
.nextNode();
42 if (currN
.isNodeType(AkbTypes
.AKB_ENV_TEMPLATE
))
48 } catch (RepositoryException re
) {
49 throw new AkbException("Unable to list templates", re
);
54 * Returns a template given it's name
56 public static Node
getTemplateByName(Session session
, String name
) {
60 if (session
.nodeExists(AkbNames
.AKB_TEMPLATES_BASE_PATH
)) {
61 NodeIterator ni
= session
.getNode(
62 AkbNames
.AKB_TEMPLATES_BASE_PATH
).getNodes();
63 while (ni
.hasNext()) {
64 Node currN
= ni
.nextNode();
65 if (name
.equals(AkbJcrUtils
.get(currN
, Property
.JCR_TITLE
)))
70 } catch (RepositoryException re
) {
71 throw new AkbException("Unable to list templates", re
);
76 * Return the type of alias that must be used given current item type
78 public static String
getAliasTypeForNode(Node itemTemplate
) {
80 if (itemTemplate
.isNodeType(AkbTypes
.AKB_JDBC_QUERY
))
81 return AkbTypes
.AKB_JDBC_CONNECTOR
;
82 else if (itemTemplate
.isNodeType(AkbTypes
.AKB_SSH_COMMAND
)
83 || itemTemplate
.isNodeType(AkbTypes
.AKB_SSH_FILE
))
84 return AkbTypes
.AKB_SSH_CONNECTOR
;
86 throw new AkbException("No connector type define for node "
88 } catch (RepositoryException re
) {
89 throw new AkbException("Unable to login", re
);
94 * Return current template depending on the passed node
96 public static Node
getCurrentTemplate(Node akbNode
) {
98 if (akbNode
.getDepth() == 0)
99 // no base path for root node
101 Node parNode
= akbNode
.getParent();
103 while (parNode
!= null)
104 if (akbNode
.isNodeType(AkbTypes
.AKB_ENV_TEMPLATE
))
106 else if (parNode
.getDepth() == 0)
107 // we found not fitting node
111 parNode
= parNode
.getParent();
114 } catch (RepositoryException re
) {
115 throw new AkbException("Unable to find template for node "
121 * Return the current env base path
123 public static String
getCurrentEnvBasePath(Node akbNode
) {
125 if (akbNode
.getDepth() == 0)
126 // no base path for root node
129 Node parNode
= akbNode
.getParent();
131 while (parNode
!= null)
132 if (akbNode
.isNodeType(AkbTypes
.AKB_ENV
)
133 || akbNode
.isNodeType(AkbTypes
.AKB_ENV_TEMPLATE
))
134 return akbNode
.getPath();
135 else if (parNode
.getDepth() == 0)
136 // we found not fitting node
140 parNode
= parNode
.getParent();
143 } catch (RepositoryException re
) {
144 throw new AkbException("Unable to login", re
);
148 // //////////////////////////////////
149 // METHODS THAT CAN BE FACTORIZED
151 * Call {@link Repository#login()} without exceptions (useful in super
152 * constructors and dependency injection).
154 public static Session
login(Repository repository
) {
156 return repository
.login();
157 } catch (RepositoryException re
) {
158 throw new AkbException("Unable to login", re
);
163 * Convert a {@link rowIterator} to a list of {@link Node} given a selector
164 * name. It relies on the <code>Row.getNode(String selectorName)</code>
167 public static List
<Node
> rowIteratorToList(RowIterator rowIterator
,
168 String selectorName
) throws RepositoryException
{
169 List
<Node
> nodes
= new ArrayList
<Node
>();
170 while (rowIterator
.hasNext()) {
171 Row row
= rowIterator
.nextRow();
172 if (row
.getNode(selectorName
) != null)
173 nodes
.add(row
.getNode(selectorName
));
179 * Check if a string is null or an empty string (a string with only spaces
180 * is considered as empty
182 public static boolean isEmptyString(String stringToTest
) {
183 return stringToTest
== null || "".equals(stringToTest
.trim());
187 * Check if a string is null or an empty string (a string with only spaces
188 * is considered as empty
190 public static boolean checkNotEmptyString(String string
) {
191 return string
!= null && !"".equals(string
.trim());
195 * Wraps the versionMananger.isCheckedOut(path) method to adapt it to the
196 * current check in / check out policy.
198 * TODO : add management of check out by others.
200 public static boolean isNodeCheckedOut(Node node
) {
202 return node
.getSession().getWorkspace().getVersionManager()
203 .isCheckedOut(node
.getPath());
204 } catch (RepositoryException re
) {
205 throw new AkbException("Unable to get check out status for node",
211 * For the time being, same as isNodeCheckedOut(Node node).
213 * TODO : add management of check out by others.
215 public static boolean isNodeCheckedOutByMe(Node node
) {
216 return isNodeCheckedOut(node
);
220 * Wraps the versionMananger.checkedOut(path) method to adapt it to the
221 * current check in / check out policy.
223 * TODO : add management of check out by others.
225 public static void checkout(Node node
) {
227 node
.getSession().getWorkspace().getVersionManager()
228 .checkout(node
.getPath());
229 } catch (RepositoryException re
) {
230 throw new AkbException("Unable to check out Node", re
);
235 * Wraps the versionMananger.checkedIn(path) method to adapt it to the
236 * current check in / check out policy.
238 * It also checked if the current entity has to be moved or not. TODO : add
239 * management of check out by others.
241 public static void saveAndCheckin(Node node
) {
243 JcrUtils
.updateLastModified(node
);
244 node
.getSession().save();
245 node
.getSession().getWorkspace().getVersionManager()
246 .checkin(node
.getPath());
247 } catch (RepositoryException re
) {
248 throw new AkbException("Unable to save and chek in node", re
);
253 * Wraps the versionMananger.checkedIn(path) method to adapt it to the
254 * current check in / check out policy.
256 * TODO : add management of check out by others. TODO : manage usecase where
257 * a node that has never been checked in (draft node) is canceled and thus
260 public static void cancelAndCheckin(Node node
) {
262 String path
= node
.getPath();
263 Session session
= node
.getSession();
264 JcrUtils
.discardUnderlyingSessionQuietly(node
);
265 // if the node has never been saved, it does not exist anymore.
266 if (session
.nodeExists(path
))
267 session
.getWorkspace().getVersionManager().checkin(path
);
268 } catch (RepositoryException re
) {
269 throw new AkbException("Unable to save and chek in node", re
);
274 * Concisely get the string value of a property. It returns an empty String
275 * rather than null if this node doesn't have this property or if the
276 * corresponding property is an empty string.
278 public static String
get(Node node
, String propertyName
) {
280 if (!node
.hasProperty(propertyName
))
283 return node
.getProperty(propertyName
).getString();
284 } catch (RepositoryException e
) {
285 throw new AkbException("Cannot get property " + propertyName
291 * Concisely get the value of a property or null if this node doesn't have
294 public static Boolean
getBooleanValue(Node node
, String propertyName
) {
296 if (!node
.hasProperty(propertyName
))
299 return node
.getProperty(propertyName
).getBoolean();
300 } catch (RepositoryException e
) {
301 throw new AkbException("Cannot get boolean property "
302 + propertyName
+ " of " + node
, e
);
307 * Concisely get the identifier of a node in Ui listener for instance
309 public static String
getIdentifierQuietly(Node node
) {
311 return node
.getIdentifier();
312 } catch (RepositoryException e
) {
313 throw new AkbException("Cannot get identifier for node " + node
, e
);
317 public static Map
<String
, PropertyDiff
> diffProperties(Node reference
,
319 Map
<String
, PropertyDiff
> diffs
= new TreeMap
<String
, PropertyDiff
>();
320 diffPropertiesLevel(diffs
, null, reference
, observed
);
325 * Compare the properties of two nodes. Extends
326 * <code>JcrUtils.diffPropertiesLevel</code> to also track differences in
327 * multiple value properties and sub graph. No property is skipped (among
328 * other all technical jcr:... properties) to be able to track jcr:title and
329 * description properties, among other. Filtering must be applied afterwards
330 * to only keep relevant properties.
332 static void diffPropertiesLevel(Map
<String
, PropertyDiff
> diffs
,
333 String baseRelPath
, Node reference
, Node observed
) {
335 // check removed and modified
336 PropertyIterator pit
= reference
.getProperties();
337 while (pit
.hasNext()) {
338 Property p
= pit
.nextProperty();
339 String name
= p
.getName();
340 // if (name.startsWith("jcr:"))
343 if (!observed
.hasProperty(name
)) {
344 String relPath
= propertyRelPath(baseRelPath
, name
);
345 PropertyDiff pDiff
= new PropertyDiff(PropertyDiff
.REMOVED
,
346 relPath
, p
.getValue(), null);
347 diffs
.put(relPath
, pDiff
);
349 if (p
.isMultiple()) {
352 Value
[] refValues
= p
.getValues();
353 Value
[] newValues
= observed
.getProperty(name
)
355 String relPath
= propertyRelPath(baseRelPath
, name
);
356 refValues
: for (Value refValue
: refValues
) {
357 for (Value newValue
: newValues
) {
358 if (refValue
.equals(newValue
))
361 PropertyDiff pDiff
= new PropertyDiff(
362 PropertyDiff
.REMOVED
, relPath
, refValue
,
364 diffs
.put(relPath
+ "_" + i
++, pDiff
);
367 newValues
: for (Value newValue
: newValues
) {
368 for (Value refValue
: refValues
) {
369 if (refValue
.equals(newValue
))
372 PropertyDiff pDiff
= new PropertyDiff(
373 PropertyDiff
.ADDED
, relPath
, null, newValue
);
374 diffs
.put(relPath
+ "_" + i
++, pDiff
);
378 Value referenceValue
= p
.getValue();
379 Value newValue
= observed
.getProperty(name
).getValue();
380 if (!referenceValue
.equals(newValue
)) {
381 String relPath
= propertyRelPath(baseRelPath
, name
);
382 PropertyDiff pDiff
= new PropertyDiff(
383 PropertyDiff
.MODIFIED
, relPath
,
384 referenceValue
, newValue
);
385 diffs
.put(relPath
, pDiff
);
391 pit
= observed
.getProperties();
393 while (pit
.hasNext()) {
394 Property p
= pit
.nextProperty();
395 String name
= p
.getName();
396 // if (name.startsWith("jcr:"))
398 if (!reference
.hasProperty(name
)) {
399 String relPath
= propertyRelPath(baseRelPath
, name
);
400 if (p
.isMultiple()) {
401 Value
[] newValues
= observed
.getProperty(name
)
404 for (Value newValue
: newValues
) {
405 PropertyDiff pDiff
= new PropertyDiff(
406 PropertyDiff
.ADDED
, relPath
, null, newValue
);
407 diffs
.put(relPath
+ "_" + i
++, pDiff
);
410 PropertyDiff pDiff
= new PropertyDiff(
411 PropertyDiff
.ADDED
, relPath
, null, p
.getValue());
412 diffs
.put(relPath
, pDiff
);
416 } catch (RepositoryException e
) {
417 throw new AkbException("Cannot diff " + reference
+ " and "
422 /** Builds a property relPath to be used in the diff. */
423 private static String
propertyRelPath(String baseRelPath
,
424 String propertyName
) {
425 if (baseRelPath
== null)
428 return baseRelPath
+ '/' + propertyName
;
431 /** prevent instantiation by others */
432 private AkbJcrUtils() {