X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=server%2Fruntime%2Forg.argeo.server.jcr%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fjcr%2FJcrUtils.java;h=554e9f34c6e8ff2118699a16cd172760238a9ab4;hb=2f1a4e0b8313d3872f7cbc73cea9f0d56cfe4fe6;hp=707639526422f709d425b5dff7cc2fb5247aa45c;hpb=02693451a9af0a877ab97c59681fb2f32976155a;p=lgpl%2Fargeo-commons.git diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java index 707639526..554e9f34c 100644 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java +++ b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java @@ -21,7 +21,11 @@ import java.text.ParseException; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; +import java.util.Iterator; +import java.util.List; +import java.util.Map; import java.util.StringTokenizer; +import java.util.TreeMap; import javax.jcr.NamespaceRegistry; import javax.jcr.Node; @@ -31,6 +35,7 @@ import javax.jcr.PropertyIterator; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.Value; +import javax.jcr.nodetype.NodeType; import javax.jcr.query.Query; import javax.jcr.query.QueryResult; @@ -197,7 +202,7 @@ public class JcrUtils { else currentNode = currentNode.addNode(part); if (versioning) - currentNode.addMixin(ArgeoJcrConstants.MIX_VERSIONABLE); + currentNode.addMixin(NodeType.MIX_VERSIONABLE); if (log.isTraceEnabled()) log.debug("Added folder " + part + " as " + current); } else { @@ -258,7 +263,7 @@ public class JcrUtils { // First output the node path log.debug(node.getPath()); // Skip the virtual (and large!) jcr:system subtree - if (node.getName().equals(ArgeoJcrConstants.JCR_SYSTEM)) { + if (node.getName().equals("jcr:system")) { return; } @@ -333,25 +338,152 @@ public class JcrUtils { /** * Check whether all first-level properties (except jcr:* properties) are - * equal. + * equal. Skip jcr:* properties */ - public static Boolean allPropertiesEquals(Node node1, Node node2) { + public static Boolean allPropertiesEquals(Node reference, Node observed, + Boolean onlyCommonProperties) { try { - PropertyIterator pit = node1.getProperties(); - while (pit.hasNext()) { - Property prop1 = pit.nextProperty(); - String propName = prop1.getName(); - if (!node2.hasProperty(propName)) - return false; + PropertyIterator pit = reference.getProperties(); + props: while (pit.hasNext()) { + Property propReference = pit.nextProperty(); + String propName = propReference.getName(); + if (propName.startsWith("jcr:")) + continue props; + + if (!observed.hasProperty(propName)) + if (onlyCommonProperties) + continue props; + else + return false; // TODO: deal with multiple property values? - if (!node2.getProperty(propName).getValue() - .equals(prop1.getValue())) + if (!observed.getProperty(propName).getValue() + .equals(propReference.getValue())) return false; } return true; } catch (RepositoryException e) { throw new ArgeoException("Cannot check all properties equals of " - + node1 + " and " + node2, e); + + reference + " and " + observed, e); + } + } + + public static Map diffProperties(Node reference, + Node observed) { + Map diffs = new TreeMap(); + diffPropertiesLevel(diffs, null, reference, observed); + return diffs; + } + + /** + * Compare the properties of two nodes. Recursivity to child nodes is not + * yet supported. Skip jcr:* properties. + */ + static void diffPropertiesLevel(Map diffs, + String baseRelPath, Node reference, Node observed) { + try { + // check removed and modified + PropertyIterator pit = reference.getProperties(); + props: while (pit.hasNext()) { + Property p = pit.nextProperty(); + String name = p.getName(); + if (name.startsWith("jcr:")) + continue props; + + if (!observed.hasProperty(name)) { + String relPath = propertyRelPath(baseRelPath, name); + PropertyDiff pDiff = new PropertyDiff(PropertyDiff.REMOVED, + relPath, p.getValue(), null); + diffs.put(relPath, pDiff); + } else { + if (p.isMultiple()) + continue props; + Value referenceValue = p.getValue(); + Value newValue = observed.getProperty(name).getValue(); + if (!referenceValue.equals(newValue)) { + String relPath = propertyRelPath(baseRelPath, name); + PropertyDiff pDiff = new PropertyDiff( + PropertyDiff.MODIFIED, relPath, referenceValue, + newValue); + diffs.put(relPath, pDiff); + } + } + } + // check added + pit = observed.getProperties(); + props: while (pit.hasNext()) { + Property p = pit.nextProperty(); + String name = p.getName(); + if (name.startsWith("jcr:")) + continue props; + if (!reference.hasProperty(name)) { + String relPath = propertyRelPath(baseRelPath, name); + PropertyDiff pDiff = new PropertyDiff(PropertyDiff.ADDED, + relPath, null, p.getValue()); + diffs.put(relPath, pDiff); + } + } + } catch (RepositoryException e) { + throw new ArgeoException("Cannot diff " + reference + " and " + + observed, e); } } + + /** + * Compare only a restricted list of properties of two nodes. No + * recursivity. + * + */ + public static Map diffProperties(Node reference, + Node observed, List properties) { + Map diffs = new TreeMap(); + try { + Iterator pit = properties.iterator(); + + props: while (pit.hasNext()) { + String name = pit.next(); + if (!reference.hasProperty(name)) { + if (!observed.hasProperty(name)) + continue props; + Value val = observed.getProperty(name).getValue(); + try { + // empty String but not null + if ("".equals(val.getString())) + continue props; + } catch (Exception e) { + // not parseable as String, silent + } + PropertyDiff pDiff = new PropertyDiff(PropertyDiff.ADDED, + name, null, val); + diffs.put(name, pDiff); + } else if (!observed.hasProperty(name)) { + PropertyDiff pDiff = new PropertyDiff(PropertyDiff.REMOVED, + name, reference.getProperty(name).getValue(), null); + diffs.put(name, pDiff); + } else { + Value referenceValue = reference.getProperty(name) + .getValue(); + Value newValue = observed.getProperty(name).getValue(); + if (!referenceValue.equals(newValue)) { + PropertyDiff pDiff = new PropertyDiff( + PropertyDiff.MODIFIED, name, referenceValue, + newValue); + diffs.put(name, pDiff); + } + } + } + } catch (RepositoryException e) { + throw new ArgeoException("Cannot diff " + reference + " and " + + observed, e); + } + return diffs; + } + + /** Builds a property relPath to be used in the diff. */ + private static String propertyRelPath(String baseRelPath, + String propertyName) { + if (baseRelPath == null) + return propertyName; + else + return baseRelPath + '/' + propertyName; + } }