You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by un...@apache.org on 2014/12/10 14:45:36 UTC

svn commit: r1644408 - in /jackrabbit/branches/2.8/jackrabbit-spi-commons/src: main/java/org/apache/jackrabbit/spi/commons/nodetype/NodeTypeDefDiff.java test/java/org/apache/jackrabbit/spi/commons/nodetype/NodeTypeDefDiffTest.java

Author: unico
Date: Wed Dec 10 13:45:36 2014
New Revision: 1644408

URL: http://svn.apache.org/r1644408
Log:
JCR-3840 take same-name child type definitions into account when reregistering node types

Modified:
    jackrabbit/branches/2.8/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/NodeTypeDefDiff.java
    jackrabbit/branches/2.8/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/nodetype/NodeTypeDefDiffTest.java

Modified: jackrabbit/branches/2.8/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/NodeTypeDefDiff.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.8/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/NodeTypeDefDiff.java?rev=1644408&r1=1644407&r2=1644408&view=diff
==============================================================================
--- jackrabbit/branches/2.8/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/NodeTypeDefDiff.java (original)
+++ jackrabbit/branches/2.8/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/NodeTypeDefDiff.java Wed Dec 10 13:45:36 2014
@@ -27,6 +27,9 @@ import org.apache.jackrabbit.spi.commons
 import javax.jcr.PropertyType;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -280,50 +283,43 @@ public class NodeTypeDefDiff {
      */
     private int buildChildNodeDefDiffs() {
         int maxType = NONE;
-        QNodeDefinition[] cnda1 = oldDef.getChildNodeDefs();
-        Map<QNodeDefinitionId, QNodeDefinition> defs1 = new HashMap<QNodeDefinitionId, QNodeDefinition>();
-        for (QNodeDefinition def1 : cnda1) {
-            defs1.put(new QNodeDefinitionId(def1), def1);
-        }
+        final Map<QNodeDefinitionId, List<QNodeDefinition>> oldDefs = collectChildNodeDefs(oldDef.getChildNodeDefs());
+        final Map<QNodeDefinitionId, List<QNodeDefinition>> newDefs = collectChildNodeDefs(newDef.getChildNodeDefs());
 
-        QNodeDefinition[] cnda2 = newDef.getChildNodeDefs();
-        Map<QNodeDefinitionId, QNodeDefinition> defs2 = new HashMap<QNodeDefinitionId, QNodeDefinition>();
-        for (QNodeDefinition def2 : cnda2) {
-            defs2.put(new QNodeDefinitionId(def2), def2);
+        for (QNodeDefinitionId defId : oldDefs.keySet()) {
+            final ChildNodeDefDiffs childNodeDefDiffs = new ChildNodeDefDiffs(oldDefs.get(defId), newDefs.get(defId));
+            this.childNodeDefDiffs.addAll(childNodeDefDiffs.getChildNodeDefDiffs());
+            newDefs.remove(defId);
         }
 
-        /**
-         * walk through defs1 and process all entries found in
-         * both defs1 & defs2 and those found only in defs1
-         */
-        for (Map.Entry<QNodeDefinitionId, QNodeDefinition> entry1 : defs1.entrySet()) {
-            QNodeDefinitionId id = entry1.getKey();
-            QNodeDefinition def1 = entry1.getValue();
-            QNodeDefinition def2 = defs2.get(id);
-            ChildNodeDefDiff diff = new ChildNodeDefDiff(def1, def2);
-            if (diff.getType() > maxType) {
-                maxType = diff.getType();
-            }
-            childNodeDefDiffs.add(diff);
-            defs2.remove(id);
+        for (QNodeDefinitionId defId : newDefs.keySet()) {
+            final ChildNodeDefDiffs childNodeDefDiffs = new ChildNodeDefDiffs(null, newDefs.get(defId));
+            this.childNodeDefDiffs.addAll(childNodeDefDiffs.getChildNodeDefDiffs());
         }
 
-        /**
-         * defs2 by now only contains entries found in defs2 only;
-         * walk through defs2 and process all remaining entries
-         */
-        for (Map.Entry<QNodeDefinitionId, QNodeDefinition> entry2 : defs2.entrySet()) {
-            QNodeDefinition def2 = entry2.getValue();
-            ChildNodeDefDiff diff = new ChildNodeDefDiff(null, def2);
+        for (ChildNodeDefDiff diff : childNodeDefDiffs) {
             if (diff.getType() > maxType) {
                 maxType = diff.getType();
             }
-            childNodeDefDiffs.add(diff);
         }
 
         return maxType;
     }
 
+    private Map<QNodeDefinitionId, List<QNodeDefinition>> collectChildNodeDefs(final QNodeDefinition[] cnda1) {
+        Map<QNodeDefinitionId, List<QNodeDefinition>> defs1 = new HashMap<QNodeDefinitionId, List<QNodeDefinition>>();
+        for (QNodeDefinition def1 : cnda1) {
+            final QNodeDefinitionId def1Id = new QNodeDefinitionId(def1);
+            List<QNodeDefinition> list = defs1.get(def1Id);
+            if (list == null) {
+                list = new ArrayList<QNodeDefinition>();
+                defs1.put(def1Id, list);
+            }
+            list.add(def1);
+        }
+        return defs1;
+    }
+
     @Override
     public String toString() {
         String result = getClass().getName() + "[\n\tnodeTypeName="
@@ -699,4 +695,67 @@ public class NodeTypeDefDiff {
             return h;
         }
     }
+
+    private class ChildNodeDefDiffs {
+
+        private final List<QNodeDefinition> defs1;
+        private final List<QNodeDefinition> defs2;
+
+        private ChildNodeDefDiffs(final List<QNodeDefinition> defs1, final List<QNodeDefinition> defs2) {
+            this.defs1 = defs1 != null ? defs1 : Collections.<QNodeDefinition>emptyList();
+            this.defs2 = defs2 != null ? defs2 : Collections.<QNodeDefinition>emptyList();
+        }
+
+        private Collection<ChildNodeDefDiff> getChildNodeDefDiffs() {
+            // gather all possible combinations of diffs
+            final List<ChildNodeDefDiff> diffs = new ArrayList<ChildNodeDefDiff>();
+            for (QNodeDefinition def1 : defs1) {
+                for (QNodeDefinition def2 : defs2) {
+                    diffs.add(new ChildNodeDefDiff(def1, def2));
+                }
+            }
+            if (defs2.size() < defs1.size()) {
+                for (QNodeDefinition def1 : defs1) {
+                    diffs.add(new ChildNodeDefDiff(def1, null));
+                }
+            }
+            if (defs1.size() < defs2.size()) {
+                for (QNodeDefinition def2 : defs2) {
+                    diffs.add(new ChildNodeDefDiff(null, def2));
+                }
+            }
+            // sort them according to decreasing compatibility
+            Collections.sort(diffs, new Comparator<ChildNodeDefDiff>() {
+                @Override
+                public int compare(final ChildNodeDefDiff o1, final ChildNodeDefDiff o2) {
+                    return o1.getType() - o2.getType();
+                }
+            });
+            // select the most compatible ones
+            final int size = defs1.size() > defs2.size() ? defs1.size() : defs2.size();
+            final List<ChildNodeDefDiff> results = new ArrayList<ChildNodeDefDiff>();
+            for (ChildNodeDefDiff diff : diffs) {
+                if (!alreadyMatched(results, diff.getNewDef(), diff.getOldDef())) {
+                    results.add(diff);
+                }
+                if (results.size() == size) {
+                    break;
+                }
+            }
+            return results;
+        }
+
+        private boolean alreadyMatched(final List<ChildNodeDefDiff> result, final QNodeDefinition newDef, final QNodeDefinition oldDef) {
+            boolean containsNewDef = false, containsOldDef = false;
+            for (ChildNodeDefDiff d : result) {
+                if (d.getNewDef() != null && d.getNewDef().equals(newDef)) {
+                    containsNewDef = true;
+                }
+                if (d.getOldDef() != null && d.getOldDef().equals(oldDef)) {
+                    containsOldDef = true;
+                }
+            }
+            return containsNewDef || containsOldDef;
+        }
+    }
 }

Modified: jackrabbit/branches/2.8/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/nodetype/NodeTypeDefDiffTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.8/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/nodetype/NodeTypeDefDiffTest.java?rev=1644408&r1=1644407&r2=1644408&view=diff
==============================================================================
--- jackrabbit/branches/2.8/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/nodetype/NodeTypeDefDiffTest.java (original)
+++ jackrabbit/branches/2.8/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/nodetype/NodeTypeDefDiffTest.java Wed Dec 10 13:45:36 2014
@@ -70,7 +70,6 @@ public class NodeTypeDefDiffTest extends
         newDef.setPropertyDefs(new QPropertyDefinition[]{newPropDef.build()});
 
         QNodeDefinitionBuilder newChildDef = new QNodeDefinitionBuilder();
-        newChildDef.setRequiredPrimaryTypes(new Name[]{ NameConstants.NT_BASE, NODE_TYPE1, NameConstants.NT_FOLDER });
         newChildDef.setRequiredPrimaryTypes(new Name[]{ NODE_TYPE1, NameConstants.NT_BASE });
         newChildDef.setName(CHILD_NAME);
         newChildDef.setDeclaringNodeType(oldDef.getName());
@@ -87,4 +86,54 @@ public class NodeTypeDefDiffTest extends
         nodeTypeDefDiff = NodeTypeDefDiff.create(newDef.build(), oldDef.build());
         assertTrue(nodeTypeDefDiff.isMajor());
     }
+
+    public void testChangedSameNameChildNodeDefinition() throws Exception {
+        // old node type definition
+        QNodeTypeDefinitionBuilder oldDef = new QNodeTypeDefinitionBuilder();
+        oldDef.setName(NODE_TYPE1);
+        oldDef.setSupertypes(new Name[] { NameConstants.NT_BASE });
+
+        QNodeDefinitionBuilder oldChildDef1 = new QNodeDefinitionBuilder();
+        oldChildDef1.setRequiredPrimaryTypes(new Name[]{ NameConstants.NT_FOLDER });
+        oldChildDef1.setName(CHILD_NAME);
+        oldChildDef1.setDeclaringNodeType(oldDef.getName());
+
+        QNodeDefinitionBuilder oldChildDef2 = new QNodeDefinitionBuilder();
+        oldChildDef2.setRequiredPrimaryTypes(new Name[]{ NameConstants.NT_FILE });
+        oldChildDef2.setName(CHILD_NAME);
+        oldChildDef2.setDeclaringNodeType(oldDef.getName());
+
+        oldDef.setChildNodeDefs(new QNodeDefinition[] { oldChildDef1.build(), oldChildDef2.build() });
+
+        // new node type definition
+        QNodeTypeDefinitionBuilder newDef = new QNodeTypeDefinitionBuilder();
+        newDef.setName(NODE_TYPE1);
+        newDef.setSupertypes(new Name[] { NameConstants.NT_BASE });
+
+        QNodeDefinitionBuilder newChildDef1 = new QNodeDefinitionBuilder();
+        newChildDef1.setRequiredPrimaryTypes(new Name[]{ NameConstants.NT_FOLDER });
+        newChildDef1.setName(CHILD_NAME);
+        newChildDef1.setDeclaringNodeType(oldDef.getName());
+
+        QNodeDefinitionBuilder newChildDef2 = new QNodeDefinitionBuilder();
+        newChildDef2.setRequiredPrimaryTypes(new Name[]{ NameConstants.NT_FILE });
+        newChildDef2.setName(CHILD_NAME);
+        newChildDef2.setDeclaringNodeType(oldDef.getName());
+
+        QNodeDefinitionBuilder newChildDef3 = new QNodeDefinitionBuilder();
+        newChildDef3.setRequiredPrimaryTypes(new Name[]{ NameConstants.NT_RESOURCE });
+        newChildDef3.setName(CHILD_NAME);
+        newChildDef3.setDeclaringNodeType(oldDef.getName());
+
+        newDef.setChildNodeDefs(new QNodeDefinition[] { newChildDef1.build(), newChildDef2.build(), newChildDef3.build() });
+
+        // from old to new is trivial
+        NodeTypeDefDiff nodeTypeDefDiff = NodeTypeDefDiff.create(oldDef.build(), newDef.build());
+        assertTrue(nodeTypeDefDiff.isTrivial());
+
+        // .. but the reverse is not
+        nodeTypeDefDiff = NodeTypeDefDiff.create(newDef.build(), oldDef.build());
+        assertTrue(nodeTypeDefDiff.isMajor());
+
+    }
 }
\ No newline at end of file