You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by st...@apache.org on 2004/12/15 19:43:46 UTC

svn commit: r112006 - in incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core: nodetype xml

Author: stefan
Date: Wed Dec 15 10:43:44 2004
New Revision: 112006

URL: http://svn.apache.org/viewcvs?view=rev&rev=112006
Log:
comparing node type definitions (analyzing type of change)
some reformatting (removing tab characters
Modified:
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/ChildItemDef.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/ChildNodeDef.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeDefDiff.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SysViewImportHandler.java

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/ChildItemDef.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/ChildItemDef.java?view=diff&rev=112006&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/ChildItemDef.java&r1=112005&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/ChildItemDef.java&r2=112006
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/ChildItemDef.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/ChildItemDef.java	Wed Dec 15 10:43:44 2004
@@ -62,10 +62,16 @@
     }
 
     public void setDeclaringNodeType(QName declaringNodeType) {
+        if (declaringNodeType == null) {
+            throw new IllegalArgumentException("declaringNodeType can not be null");
+        }
         this.declaringNodeType = declaringNodeType;
     }
 
     public void setName(QName name) {
+        if (name == null) {
+            throw new IllegalArgumentException("name can not be null");
+        }
         this.name = name;
     }
 

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/ChildNodeDef.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/ChildNodeDef.java?view=diff&rev=112006&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/ChildNodeDef.java&r1=112005&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/ChildNodeDef.java&r2=112006
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/ChildNodeDef.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/ChildNodeDef.java	Wed Dec 15 10:43:44 2004
@@ -59,6 +59,9 @@
      * @param requiredPrimaryTypes
      */
     public void setRequiredPrimaryTypes(QName[] requiredPrimaryTypes) {
+        if (requiredPrimaryTypes == null) {
+            throw new IllegalArgumentException("requiredPrimaryTypes can not be null");
+        }
         this.requiredPrimaryTypes = requiredPrimaryTypes;
     }
 

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeDefDiff.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeDefDiff.java?view=diff&rev=112006&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeDefDiff.java&r1=112005&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeDefDiff.java&r2=112006
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeDefDiff.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeDefDiff.java	Wed Dec 15 10:43:44 2004
@@ -15,73 +15,526 @@
  */
 package org.apache.jackrabbit.core.nodetype;
 
+import javax.jcr.PropertyType;
+import java.util.*;
+
 /**
  * A <code>NodeTypeDefDiff</code> represents the result of the comparison of
  * two node type definitions.
+ * <p/>
+ * The result of the comparison can be categorized as one of the following types:
+ * <p/>
+ * <b><code>NONE</code></b> inidcates that there is no modification at all.
+ * <p/>
+ * A <b><code>TRIVIAL</code></b> modification has no impact on the consistency
+ * of existing content and does not affect existing/assigned definition id's.
+ * The following modifications are considered <code>TRIVIAL</code>:
+ * <ul>
+ * <li>changing node type <code>orderableChildNodes</code> flag
+ * <li>adding non-<code>mandatory</code> property/child node
+ * <li>changing property/child node <code>primaryItem</code> flag
+ * <li>changing property/child node <code>protected</code> flag
+ * <li>changing property/child node <code>onParentVersion</code> value
+ * <li>changing property/child node <code>mandatory</code> flag to <code>false</code>
+ * <li>changing property/child node <code>autoCreate</code> flag
+ * <li>changing child node <code>defaultPrimaryType</code>
+ * <li>changing child node <code>sameNameSibs</code> flag to <code>true</code>
+ * <li>weaken property <code>valueConstraints</code> (e.g. by removing completely
+ * or by adding to existing or by making a single constraint less restrictive)
+ * <li>changing property <code>defaultValues</code>
+ * </ul>
+ * <p/>
+ * A <b><code>MINOR</code></b> modification has no impact on the consistency
+ * of existing content but <i>does</i> affect existing/assigned definition id's.
+ * The following modifications are considered <code>MINOR</code>:
+ * <ul>
+ * <li>changing specific property/child node <code>name</code> to <code>*</code>
+ * <li>weaken child node <code>requiredPrimaryTypes</code> (e.g. by removing)
+ * <li>changing specific property <code>requiredType</code> to <code>undefined</code>
+ * <li>changing property <code>multiple</code> flag to <code>true</code>
+ * </ul>
+ * <p/>
+ * A <b><code>MAJOR</code></b> modification <i>affects</i> the consistency of
+ * existing content and <i>does</i> change existing/assigned definition id's.
+ * All modifications that are neither <b><code>TRIVIAL</code></b> nor
+ * <b><code>MINOR</code></b> are considered <b><code>MAJOR</code></b>.
+ *
+ * @see #getType()
  */
 public class NodeTypeDefDiff {
 
-    // type constants
-    public static final int TRIVIAL = 0;
-    public static final int MINOR = 0;
-    public static final int MAJOR = 0;
+    /**
+     * no modification
+     */
+    public static final int NONE = 0;
+    /**
+     * trivial modification: does neither affect consistency of existing content
+     * nor does it change existing/assigned definition id's
+     */
+    public static final int TRIVIAL = 1;
+    /**
+     * minor modification: does not affect consistency of existing content but
+     * <i>does</i> change existing/assigned definition id's
+     */
+    public static final int MINOR = 2;
+    /**
+     * major modification: <i>does</i> affect consistency of existing content
+     * and <i>does</i> change existing/assigned definition id's
+     */
+    public static final int MAJOR = 3;
 
     private final NodeTypeDef oldDef;
     private final NodeTypeDef newDef;
     private int type;
-/*
-    private QName name;
-    private QName[] supertypes;
-    private boolean mixin;
-    private boolean orderableChildNodes;
-    private PropDef[] propDefs;
-    private ChildNodeDef[] nodeDefs;
-*/
+
+    private List propDefDiffs = new ArrayList();
+    private List childNodeDefDiffs = new ArrayList();
+
     /**
      * Constructor
      */
     private NodeTypeDefDiff(NodeTypeDef oldDef, NodeTypeDef newDef) {
-	this.oldDef = oldDef;
-	this.newDef = newDef;
-	init();
+        this.oldDef = oldDef;
+        this.newDef = newDef;
+        init();
     }
 
     /**
      *
      */
     private void init() {
-	// @todo build diff and set type
+        if (oldDef.equals(newDef)) {
+            // definitions are identical
+            type = NONE;
+        } else {
+            // definitions are not identical, determine type of modification
+
+            // assume TRIVIAL change by default
+            type = TRIVIAL;
+
+            // check supertypes (MAJOR modification)
+            if (supertypesChanged()) {
+                type = MAJOR;
+            }
+
+            // check mixin flag (MAJOR modification)
+            if (oldDef.isMixin() != newDef.isMixin()) {
+                type = MAJOR;
+            }
+
+            // no need to check orderableChildNodes flag (TRIVIAL modification)
+
+            // check property definitions
+            int tmpType = buildPropDefDiffs();
+            if (tmpType > type) {
+                type = tmpType;
+            }
+
+            // check child node definitions
+            tmpType = buildChildNodeDefDiffs();
+            if (tmpType > type) {
+                type = tmpType;
+            }
+        }
     }
 
     /**
-     *
      * @param oldDef
      * @param newDef
      * @return
      */
     public static NodeTypeDefDiff create(NodeTypeDef oldDef, NodeTypeDef newDef) {
-	if (oldDef == null || newDef == null) {
-	    throw new IllegalArgumentException("arguments can not be null");
-	}
-	if (!oldDef.getName().equals(newDef.getName())) {
-	    throw new IllegalArgumentException("node type names must match");
-	}
-	return new NodeTypeDefDiff(oldDef, newDef);
+        if (oldDef == null || newDef == null) {
+            throw new IllegalArgumentException("arguments can not be null");
+        }
+        if (!oldDef.getName().equals(newDef.getName())) {
+            throw new IllegalArgumentException("at least node type names must be matching");
+        }
+        return new NodeTypeDefDiff(oldDef, newDef);
     }
 
     /**
-     *
      * @return
-     */ 
+     */
+    public boolean isModified() {
+        return type != NONE;
+    }
+
+    /**
+     * @return
+     */
     public boolean isTrivial() {
-	return type == TRIVIAL;
+        return type == TRIVIAL;
     }
 
     /**
-     *
      * @return
      */
+    public boolean isMinor() {
+        return type == MINOR;
+    }
+
+    /**
+     * @return
+     */
+    public boolean isMajor() {
+        return type == MAJOR;
+    }
+
+    /**
+     * Returns the type of modification as expressed by the following constants:
+     * <ul>
+     * <li><b><code>NONE</code></b>: no modification at all
+     * <li><b><code>TRIVIAL</code></b>: does neither affect consistency of
+     * existing content nor does it change existing/assigned definition id's
+     * <li><b><code>MINOR</code></b>: does not affect consistency of existing
+     * content but <i>does</i> change existing/assigned definition id's
+     * <li><b><code>MAJOR</code></b>: <i>does</i> affect consistency of existing
+     * content and <i>does</i> change existing/assigned definition id's
+     * </ul>
+     *
+     * @return the type of modification
+     */
     public int getType() {
-	return type;
+        return type;
+    }
+
+    /**
+     * @return
+     */
+    public boolean supertypesChanged() {
+        return !Arrays.equals(oldDef.getSupertypes(), newDef.getSupertypes());
+    }
+
+    /**
+     * @return
+     */
+    public boolean propertyDefsChanged() {
+        return !Arrays.equals(oldDef.getPropertyDefs(), newDef.getPropertyDefs());
+    }
+
+    /**
+     * @return
+     */
+    public boolean childNodeDefsChanged() {
+        return !Arrays.equals(oldDef.getChildNodeDefs(), newDef.getChildNodeDefs());
+    }
+
+    /**
+     *
+     * @return
+     */
+    private int buildPropDefDiffs() {
+        /**
+         * propDefId determinants: declaringNodeType, name, requiredType, multiple
+         * todo: try also to match entries with modified id's
+         */
+
+        int maxType = NONE;
+        PropDef[] pda1 = oldDef.getPropertyDefs();
+        HashMap defs1 = new HashMap();
+        for (int i = 0; i < pda1.length; i++) {
+            defs1.put(new PropDefId(pda1[i]), pda1[i]);
+        }
+
+        PropDef[] pda2 = newDef.getPropertyDefs();
+        HashMap defs2 = new HashMap();
+        for (int i = 0; i < pda2.length; i++) {
+            defs2.put(new PropDefId(pda2[i]), pda2[i]);
+        }
+
+        /**
+         * walk through defs1 and process all entries found in
+         * both defs1 & defs2 and those found only in defs1
+         */
+        Iterator iter = defs1.keySet().iterator();
+        while (iter.hasNext()) {
+            PropDefId id = (PropDefId) iter.next();
+            PropDef def1 = (PropDef) defs1.get(id);
+            PropDef def2 = (PropDef) defs2.get(id);
+            PropDefDiff diff = new PropDefDiff(def1, def2);
+            if (diff.getType() > maxType) {
+                maxType = diff.getType();
+            }
+            propDefDiffs.add(diff);
+            defs2.remove(id);
+        }
+
+        /**
+         * defs2 by now only contains entries found in defs2 only;
+         * walk through defs2 and process all remaining entries
+         */
+        iter = defs2.keySet().iterator();
+        while (iter.hasNext()) {
+            PropDefId id = (PropDefId) iter.next();
+            PropDef def = (PropDef) defs2.get(id);
+            PropDefDiff diff = new PropDefDiff(null, def);
+            if (diff.getType() > maxType) {
+                maxType = diff.getType();
+            }
+            propDefDiffs.add(diff);
+        }
+
+        return maxType;
+    }
+
+    /**
+     *
+     * @return
+     */
+    private int buildChildNodeDefDiffs() {
+        /**
+         * nodeDefId determinants: declaringNodeType, name, requiredPrimaryTypes
+         * todo: try also to match entries with modified id's
+         */
+
+        int maxType = NONE;
+        ChildNodeDef[] cnda1 = oldDef.getChildNodeDefs();
+        HashMap defs1 = new HashMap();
+        for (int i = 0; i < cnda1.length; i++) {
+            defs1.put(new NodeDefId(cnda1[i]), cnda1[i]);
+        }
+
+        ChildNodeDef[] cnda2 = newDef.getChildNodeDefs();
+        HashMap defs2 = new HashMap();
+        for (int i = 0; i < cnda1.length; i++) {
+            defs2.put(new NodeDefId(cnda2[i]), cnda2[i]);
+        }
+
+        /**
+         * walk through defs1 and process all entries found in
+         * both defs1 & defs2 and those found only in defs1
+         */
+        Iterator iter = defs1.keySet().iterator();
+        while (iter.hasNext()) {
+            NodeDefId id = (NodeDefId) iter.next();
+            ChildNodeDef def1 = (ChildNodeDef) defs1.get(id);
+            ChildNodeDef def2 = (ChildNodeDef) defs2.get(id);
+            ChildNodeDefDiff diff = new ChildNodeDefDiff(def1, def2);
+            if (diff.getType() > maxType) {
+                maxType = diff.getType();
+            }
+            childNodeDefDiffs.add(diff);
+            defs2.remove(id);
+        }
+
+        /**
+         * defs2 by now only contains entries found in defs2 only;
+         * walk through defs2 and process all remaining entries
+         */
+        iter = defs2.keySet().iterator();
+        while (iter.hasNext()) {
+            NodeDefId id = (NodeDefId) iter.next();
+            ChildNodeDef def = (ChildNodeDef) defs2.get(id);
+            ChildNodeDefDiff diff = new ChildNodeDefDiff(null, def);
+            if (diff.getType() > maxType) {
+                maxType = diff.getType();
+            }
+            childNodeDefDiffs.add(diff);
+        }
+
+        return maxType;
+    }
+
+    //--------------------------------------------------------< inner classes >
+    abstract class ChildItemDefDiff {
+        protected final ChildItemDef oldDef;
+        protected final ChildItemDef newDef;
+        protected int type;
+
+        ChildItemDefDiff(ChildItemDef oldDef, ChildItemDef newDef) {
+            this.oldDef = oldDef;
+            this.newDef = newDef;
+            init();
+        }
+
+        protected void init() {
+            // determine type of modification
+            if (isAdded()) {
+                if (!newDef.isMandatory()) {
+                    // adding a non-mandatory child item is a TRIVIAL change
+                    type = TRIVIAL;
+                } else {
+                    // adding a mandatory child item is a MAJOR change
+                    type = MAJOR;
+                }
+            } else if (isRemoved()) {
+                // removing a child item is a MAJOR change
+                type = MAJOR;
+            } else {
+                /**
+                 * neither added nor removed => has to be either identical
+                 * or modified
+                 */
+                if (oldDef.equals(newDef)) {
+                    // identical
+                    type = NONE;
+                } else {
+                    // modified
+                    if (oldDef.isMandatory() != newDef.isMandatory()
+                            && newDef.isMandatory()) {
+                        // making a child item mandatory is a MAJOR change
+                        type = MAJOR;
+                    } else {
+                        if (!oldDef.definesResidual()
+                                && newDef.definesResidual()) {
+                            // just making a child item residual is a MINOR change
+                            type = MINOR;
+                        } else {
+                            if (!oldDef.getName().equals(newDef.getName())) {
+                                // changing the name of a child item is a MAJOR change
+                                type = MAJOR;
+                            } else {
+                                // all other changes are TRIVIAL
+                                type = TRIVIAL;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        public int getType() {
+            return type;
+        }
+
+        public boolean isAdded() {
+            return oldDef == null && newDef != null;
+        }
+
+        public boolean isRemoved() {
+            return oldDef != null && newDef == null;
+        }
+
+        public boolean isModified() {
+            return oldDef != null && newDef != null
+                    && !oldDef.equals(newDef);
+        }
+    }
+
+    public class PropDefDiff extends ChildItemDefDiff {
+
+        PropDefDiff(PropDef oldDef, PropDef newDef) {
+            super(oldDef, newDef);
+        }
+
+        public PropDef getOldDef() {
+            return (PropDef) oldDef;
+        }
+
+        public PropDef getNewDef() {
+            return (PropDef) newDef;
+        }
+
+        protected void init() {
+            super.init();
+            /**
+             * only need to do comparison if base class implementation
+             * detected a non-MAJOR modification (i.e. TRIVIAL or MINOR);
+             * no need to check for additions or removals as this is already
+             * handled in base class implementation.
+             */
+            if (isModified() && type != NONE && type != MAJOR) {
+                /**
+                 * check if valueConstraints were made more restrictive
+                 * (constraints are ORed)
+                 */
+                ValueConstraint[] vca1 = getOldDef().getValueConstraints();
+                HashSet set1 = new HashSet();
+                for (int i = 0; i < vca1.length; i++) {
+                    set1.add(vca1[i].getDefinition());
+                }
+                ValueConstraint[] vca2 = getNewDef().getValueConstraints();
+                HashSet set2 = new HashSet();
+                for (int i = 0; i < vca2.length; i++) {
+                    set2.add(vca2[i].getDefinition());
+                }
+
+                if (set1.isEmpty() && !set2.isEmpty()) {
+                    // added constraint where there was no constraint (MAJOR change)
+                    type = MAJOR;
+                } else if (!set2.containsAll(set1) && !set2.isEmpty()) {
+                    // removed existing constraint (MAJOR change)
+                    type = MAJOR;
+                }
+
+                // no need to check defaultValues (TRIVIAL change)
+
+                if (type == TRIVIAL) {
+                    int t1 = getOldDef().getRequiredType();
+                    int t2 = getNewDef().getRequiredType();
+                    if (t1 != t2) {
+                        if (t2 == PropertyType.UNDEFINED) {
+                            // changed getRequiredType to UNDEFINED (MINOR change)
+                            type = MINOR;
+                        } else {
+                            // changed getRequiredType to specific type (MAJOR change)
+                            type = MAJOR;
+                        }
+                    }
+                    boolean b1 = getOldDef().isMultiple();
+                    boolean b2 = getNewDef().isMultiple();
+                    if (b1 != b1) {
+                        if (b2) {
+                            // changed multiple flag to true (MINOR change)
+                            type = MINOR;
+                        } else {
+                            // changed multiple flag to false (MAJOR change)
+                            type = MAJOR;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    public class ChildNodeDefDiff extends ChildItemDefDiff {
+
+        ChildNodeDefDiff(ChildNodeDef oldDef, ChildNodeDef newDef) {
+            super(oldDef, newDef);
+        }
+
+        public ChildNodeDef getOldDef() {
+            return (ChildNodeDef) oldDef;
+        }
+
+        public ChildNodeDef getNewDef() {
+            return (ChildNodeDef) newDef;
+        }
+
+        protected void init() {
+            super.init();
+            /**
+             * only need to do comparison if base class implementation
+             * detected a non-MAJOR modification (i.e. TRIVIAL or MINOR);
+             * no need to check for additions or removals as this is already
+             * handled in base class implementation.
+             */
+            if (isModified() && type != NONE && type != MAJOR) {
+
+                boolean b1 = getOldDef().allowSameNameSibs();
+                boolean b2 = getNewDef().allowSameNameSibs();
+                if (b1 != b1 && !b2) {
+                    // changed sameNameSibs flag to false (MAJOR change)
+                    type = MAJOR;
+                }
+
+                // no need to check defaultPrimaryType (TRIVIAL change)
+
+                if (type == TRIVIAL) {
+                    List l1 = Arrays.asList(getOldDef().getRequiredPrimaryTypes());
+                    List l2 = Arrays.asList(getNewDef().getRequiredPrimaryTypes());
+                    if (!l1.equals(l2)) {
+                        if (l1.containsAll(l2)) {
+                            // removed requiredPrimaryType (MINOR change)
+                            type = MINOR;
+                        } else {
+                            // added requiredPrimaryType (MAJOR change)
+                            type = MAJOR;
+                        }
+                    }
+                }
+            }
+        }
     }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java?view=diff&rev=112006&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java&r1=112005&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java&r2=112006
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java	Wed Dec 15 10:43:44 2004
@@ -523,6 +523,15 @@
         PropDef[] pda = ntd.getPropertyDefs();
         for (int i = 0; i < pda.length; i++) {
             PropDef pd = pda[i];
+            /**
+             * sanity check:
+             * make sure declaring node type matches name of node type definition
+             */
+            if (!name.equals(pd.getDeclaringNodeType())) {
+                String msg = "[" + name + "#" + pd.getName() + "] invalid declaring node type specified";
+                log.error(msg);
+                throw new InvalidNodeTypeDefException(msg);
+            }
             // check primary item flag
             if (pd.isPrimaryItem()) {
                 if (pd.definesResidual()) {
@@ -632,6 +641,15 @@
         ChildNodeDef[] cnda = ntd.getChildNodeDefs();
         for (int i = 0; i < cnda.length; i++) {
             ChildNodeDef cnd = cnda[i];
+            /**
+             * sanity check:
+             * make sure declaring node type matches name of node type definition
+             */
+            if (!name.equals(cnd.getDeclaringNodeType())) {
+                String msg = "[" + name + "#" + cnd.getName() + "] invalid declaring node type specified";
+                log.error(msg);
+                throw new InvalidNodeTypeDefException(msg);
+            }
             // check primary item flag
             if (cnd.isPrimaryItem()) {
                 if (cnd.definesResidual()) {

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SysViewImportHandler.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SysViewImportHandler.java?view=diff&rev=112006&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SysViewImportHandler.java&r1=112005&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SysViewImportHandler.java&r2=112006
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SysViewImportHandler.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SysViewImportHandler.java	Wed Dec 15 10:43:44 2004
@@ -16,11 +16,11 @@
 package org.apache.jackrabbit.core.xml;
 
 import org.apache.jackrabbit.core.*;
-import org.apache.jackrabbit.core.version.VersionManager;
 import org.apache.jackrabbit.core.nodetype.NodeTypeImpl;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
 import org.apache.jackrabbit.core.util.Base64;
 import org.apache.jackrabbit.core.util.ValueHelper;
+import org.apache.jackrabbit.core.version.VersionManager;
 import org.apache.log4j.Logger;
 import org.xml.sax.Attributes;
 import org.xml.sax.ContentHandler;
@@ -28,9 +28,9 @@
 import org.xml.sax.helpers.DefaultHandler;
 
 import javax.jcr.*;
+import javax.jcr.nodetype.ConstraintViolationException;
 import javax.jcr.nodetype.NodeDef;
 import javax.jcr.nodetype.PropertyDef;
-import javax.jcr.nodetype.ConstraintViolationException;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.util.*;
@@ -51,10 +51,14 @@
      */
     private Stack stateStack = new Stack();
 
-    /** list of all reference properties that need to be adjusted */
+    /**
+     * list of all reference properties that need to be adjusted
+     */
     private LinkedList references = new LinkedList();
 
-    /** list of all mix:referenceable */
+    /**
+     * list of all mix:referenceable
+     */
     private HashMap referees = new HashMap();
 
     /**
@@ -66,10 +70,10 @@
     private StringBuffer currentPropValue;
 
     SysViewImportHandler(NodeImpl importTargetNode, SessionImpl session) {
-	ImportState state = new ImportState();
-	state.node = importTargetNode;
-	this.session = session;
-	stateStack.push(state);
+        ImportState state = new ImportState();
+        state.node = importTargetNode;
+        this.session = session;
+        stateStack.push(state);
     }
 
     //-------------------------------------------------------< ContentHandler >
@@ -77,279 +81,279 @@
      * @see ContentHandler#startElement(String, String, String, Attributes)
      */
     public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
-	try {
-	    String elemName;
-	    String nsURI;
-	    if (namespaceURI != null && !"".equals(namespaceURI)) {
-		nsURI = namespaceURI;
-		elemName = localName;
-	    } else {
-		try {
-		    nsURI = QName.fromJCRName(qName, session.getNamespaceResolver()).getNamespaceURI();
-		    elemName = QName.fromJCRName(qName, session.getNamespaceResolver()).getLocalName();
-		} catch (BaseException e) {
-		    // should never happen...
-		    String msg = "internal error: failed to parse/resolve element name " + qName;
-		    log.error(msg, e);
-		    throw new SAXException(msg, e);
-		}
-	    }
-	    // check namespace
-	    if (!NamespaceRegistryImpl.NS_SV_URI.equals(nsURI)) {
-		throw new SAXException(new InvalidSerializedDataException("invalid namespace for element in system view xml document: " + nsURI));
-	    }
-	    // check element name
-	    if (SysViewSAXEventGenerator.NODE_ELEMENT.equals(elemName)) {
-		// sv:node element
-
-		// node name (value of sv:name attribute)
-		String name = atts.getValue(SysViewSAXEventGenerator.NS_SV_URI, SysViewSAXEventGenerator.NAME_ATTRIBUTE);
-		if (name == null) {
-		    // try qualified name
-		    name = atts.getValue(SysViewSAXEventGenerator.NS_SV_PREFIX + ":" + SysViewSAXEventGenerator.NAME_ATTRIBUTE);
-		}
-		if (name == null) {
-		    throw new SAXException(new InvalidSerializedDataException("missing mandatory sv:name attributeof element sv:node"));
-		}
-
-		ImportState current = (ImportState) stateStack.peek();
-		if (current.node == null) {
-		    // need to create current node first
-		    createNode(current);
-		}
-
-		// push new ImportState instance onto the stack
-		ImportState state = new ImportState();
-		state.parent = current.node;
-		try {
-		    state.nodeName = QName.fromJCRName(name, session.getNamespaceResolver());
-		} catch (IllegalNameException ine) {
-		    throw new SAXException(new InvalidSerializedDataException("illegal node name: " + name, ine));
-		} catch (UnknownPrefixException upe) {
-		    throw new SAXException(new InvalidSerializedDataException("illegal node name: " + name, upe));
-		}
-		stateStack.push(state);
-	    } else if (SysViewSAXEventGenerator.PROPERTY_ELEMENT.equals(elemName)) {
-		// sv:property element
-
-		// reset temp fields
-		currentPropValues = new ArrayList();
-
-		// property name (value of sv:name attribute)
-		String name = atts.getValue(SysViewSAXEventGenerator.NS_SV_URI, SysViewSAXEventGenerator.NAME_ATTRIBUTE);
-		if (name == null) {
-		    // try qualified name
-		    name = atts.getValue(SysViewSAXEventGenerator.NS_SV_PREFIX + ":" + SysViewSAXEventGenerator.NAME_ATTRIBUTE);
-		}
-		if (name == null) {
-		    throw new SAXException(new InvalidSerializedDataException("missing mandatory sv:name attributeof element sv:property"));
-		}
-		try {
-		    currentPropName = QName.fromJCRName(name, session.getNamespaceResolver());
-		} catch (IllegalNameException ine) {
-		    throw new SAXException(new InvalidSerializedDataException("illegal property name: " + name, ine));
-		} catch (UnknownPrefixException upe) {
-		    throw new SAXException(new InvalidSerializedDataException("illegal property name: " + name, upe));
-		}
-		// property type (sv:type attribute)
-		String type = atts.getValue(SysViewSAXEventGenerator.NS_SV_URI, SysViewSAXEventGenerator.TYPE_ATTRIBUTE);
-		if (type == null) {
-		    // try qualified name
-		    type = atts.getValue(SysViewSAXEventGenerator.NS_SV_PREFIX + ":" + SysViewSAXEventGenerator.TYPE_ATTRIBUTE);
-		}
-		if (type == null) {
-		    throw new SAXException(new InvalidSerializedDataException("missing mandatory sv:type attributeof element sv:property"));
-		}
-		currentPropType = PropertyType.valueFromName(type);
-	    } else if (SysViewSAXEventGenerator.VALUE_ELEMENT.equals(elemName)) {
-		// sv:value element
-
-		// reset temp fields
-		currentPropValue = new StringBuffer();
-	    } else {
-		throw new SAXException(new InvalidSerializedDataException("unexpected element found in system view xml document: " + elemName));
-	    }
-	} catch (RepositoryException re) {
-	    throw new SAXException(re);
-	}
+        try {
+            String elemName;
+            String nsURI;
+            if (namespaceURI != null && !"".equals(namespaceURI)) {
+                nsURI = namespaceURI;
+                elemName = localName;
+            } else {
+                try {
+                    nsURI = QName.fromJCRName(qName, session.getNamespaceResolver()).getNamespaceURI();
+                    elemName = QName.fromJCRName(qName, session.getNamespaceResolver()).getLocalName();
+                } catch (BaseException e) {
+                    // should never happen...
+                    String msg = "internal error: failed to parse/resolve element name " + qName;
+                    log.error(msg, e);
+                    throw new SAXException(msg, e);
+                }
+            }
+            // check namespace
+            if (!NamespaceRegistryImpl.NS_SV_URI.equals(nsURI)) {
+                throw new SAXException(new InvalidSerializedDataException("invalid namespace for element in system view xml document: " + nsURI));
+            }
+            // check element name
+            if (SysViewSAXEventGenerator.NODE_ELEMENT.equals(elemName)) {
+                // sv:node element
+
+                // node name (value of sv:name attribute)
+                String name = atts.getValue(SysViewSAXEventGenerator.NS_SV_URI, SysViewSAXEventGenerator.NAME_ATTRIBUTE);
+                if (name == null) {
+                    // try qualified name
+                    name = atts.getValue(SysViewSAXEventGenerator.NS_SV_PREFIX + ":" + SysViewSAXEventGenerator.NAME_ATTRIBUTE);
+                }
+                if (name == null) {
+                    throw new SAXException(new InvalidSerializedDataException("missing mandatory sv:name attributeof element sv:node"));
+                }
+
+                ImportState current = (ImportState) stateStack.peek();
+                if (current.node == null) {
+                    // need to create current node first
+                    createNode(current);
+                }
+
+                // push new ImportState instance onto the stack
+                ImportState state = new ImportState();
+                state.parent = current.node;
+                try {
+                    state.nodeName = QName.fromJCRName(name, session.getNamespaceResolver());
+                } catch (IllegalNameException ine) {
+                    throw new SAXException(new InvalidSerializedDataException("illegal node name: " + name, ine));
+                } catch (UnknownPrefixException upe) {
+                    throw new SAXException(new InvalidSerializedDataException("illegal node name: " + name, upe));
+                }
+                stateStack.push(state);
+            } else if (SysViewSAXEventGenerator.PROPERTY_ELEMENT.equals(elemName)) {
+                // sv:property element
+
+                // reset temp fields
+                currentPropValues = new ArrayList();
+
+                // property name (value of sv:name attribute)
+                String name = atts.getValue(SysViewSAXEventGenerator.NS_SV_URI, SysViewSAXEventGenerator.NAME_ATTRIBUTE);
+                if (name == null) {
+                    // try qualified name
+                    name = atts.getValue(SysViewSAXEventGenerator.NS_SV_PREFIX + ":" + SysViewSAXEventGenerator.NAME_ATTRIBUTE);
+                }
+                if (name == null) {
+                    throw new SAXException(new InvalidSerializedDataException("missing mandatory sv:name attributeof element sv:property"));
+                }
+                try {
+                    currentPropName = QName.fromJCRName(name, session.getNamespaceResolver());
+                } catch (IllegalNameException ine) {
+                    throw new SAXException(new InvalidSerializedDataException("illegal property name: " + name, ine));
+                } catch (UnknownPrefixException upe) {
+                    throw new SAXException(new InvalidSerializedDataException("illegal property name: " + name, upe));
+                }
+                // property type (sv:type attribute)
+                String type = atts.getValue(SysViewSAXEventGenerator.NS_SV_URI, SysViewSAXEventGenerator.TYPE_ATTRIBUTE);
+                if (type == null) {
+                    // try qualified name
+                    type = atts.getValue(SysViewSAXEventGenerator.NS_SV_PREFIX + ":" + SysViewSAXEventGenerator.TYPE_ATTRIBUTE);
+                }
+                if (type == null) {
+                    throw new SAXException(new InvalidSerializedDataException("missing mandatory sv:type attributeof element sv:property"));
+                }
+                currentPropType = PropertyType.valueFromName(type);
+            } else if (SysViewSAXEventGenerator.VALUE_ELEMENT.equals(elemName)) {
+                // sv:value element
+
+                // reset temp fields
+                currentPropValue = new StringBuffer();
+            } else {
+                throw new SAXException(new InvalidSerializedDataException("unexpected element found in system view xml document: " + elemName));
+            }
+        } catch (RepositoryException re) {
+            throw new SAXException(re);
+        }
     }
 
     /**
      * @see ContentHandler#characters(char[], int, int)
      */
     public void characters(char[] ch, int start, int length) throws SAXException {
-	if (currentPropValue != null) {
-	    // property value (character data of sv:value element)
-	    currentPropValue.append(ch, start, length);
-	}
+        if (currentPropValue != null) {
+            // property value (character data of sv:value element)
+            currentPropValue.append(ch, start, length);
+        }
     }
 
     /**
      * @see ContentHandler#endElement(String, String, String)
      */
     public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
-	try {
-	    String elemName;
-	    if (localName != null && !"".equals(localName)) {
-		elemName = localName;
-	    } else {
-		try {
-		    elemName = QName.fromJCRName(qName, session.getNamespaceResolver()).getLocalName();
-		} catch (BaseException e) {
-		    // should never happen...
-		    String msg = "internal error: failed to parse/resolve element name " + qName;
-		    log.error(msg, e);
-		    throw new SAXException(msg, e);
-		}
-	    }
-	    // check element name
-	    ImportState current = (ImportState) stateStack.peek();
-	    if (SysViewSAXEventGenerator.NODE_ELEMENT.equals(elemName)) {
-		// sv:node element
-		if (current.node == null) {
-		    // need to create current node first
-		    createNode(current);
-		}
-		// pop current state from stack
-		stateStack.pop();
-	    } else if (SysViewSAXEventGenerator.PROPERTY_ELEMENT.equals(elemName)) {
-		// sv:property element
-
-		// check if all system properties (jcr:primaryType, jcr:uuid etc.)
-		// have been collected and create node as necessary
-		if (currentPropName.equals(ItemImpl.PROPNAME_PRIMARYTYPE)) {
-		    try {
-			current.primaryType = QName.fromJCRName((String) currentPropValues.get(0), session.getNamespaceResolver());
-		    } catch (IllegalNameException ine) {
-			throw new SAXException(new InvalidSerializedDataException("illegal node type name: " + currentPropValues.get(0), ine));
-		    } catch (UnknownPrefixException upe) {
-			throw new SAXException(new InvalidSerializedDataException("illegal node type name: " + currentPropValues.get(0), upe));
-		    }
-		} else if (currentPropName.equals(ItemImpl.PROPNAME_MIXINTYPES)) {
-		    if (current.mixinTypes == null) {
-			current.mixinTypes = new ArrayList(currentPropValues.size());
-		    }
-		    for (int i = 0; i < currentPropValues.size(); i++) {
-			try {
-			    QName mixin = QName.fromJCRName((String) currentPropValues.get(i), session.getNamespaceResolver());
-			    current.mixinTypes.add(mixin);
-			} catch (IllegalNameException ine) {
-			    throw new SAXException(new InvalidSerializedDataException("illegal mixin type name: " + currentPropValues.get(i), ine));
-			} catch (UnknownPrefixException upe) {
-			    throw new SAXException(new InvalidSerializedDataException("illegal mixin type name: " + currentPropValues.get(i), upe));
-			}
-		    }
-		} else if (currentPropName.equals(ItemImpl.PROPNAME_UUID)) {
-		    current.uuid = (String) currentPropValues.get(0);
-		    // jcr:uuid is the last system property; we can assume that all
-		    // required system properties have been collected by now
-		    if (current.node == null) {
-			// now that we're collected all required system properties
-			// we're ready to create the node
-			createNode(current);
-		    }
-		} else if (currentPropName.equals(VersionManager.PROPNAME_BASE_VERSION)) {
-                    // ignore so far
-		} else if (currentPropName.equals(VersionManager.PROPNAME_VERSION_HISTORY)) {
-                    // ignore so far
-		} else if (currentPropName.equals(VersionManager.PROPNAME_PREDECESSORS)) {
-                    // ignore so far
-		} else if (currentPropName.equals(VersionManager.PROPNAME_IS_CHECKED_OUT)) {
-                    // ignore so far
-		} else {
-		    // non-system property encountered; we can assume that all
-		    // required system properties have been collected by now
-		    if (current.node == null) {
-			// now that we're collected all required system properties
-			// we're ready to create the node
-			createNode(current);
-		    }
-
-		    // convert values to native type and set property
-		    Value[] vals = new Value[currentPropValues.size()];
-		    for (int i = 0; i < currentPropValues.size(); i++) {
-			String value = (String) currentPropValues.get(i);
-			if (currentPropType == PropertyType.BINARY) {
-			    // base64 encoded binary value
-			    ByteArrayOutputStream baos = new ByteArrayOutputStream();
-			    try {
-				Base64.decode(value, baos);
-				baos.close();
-			    } catch (IOException ioe) {
-				throw new SAXException("failed to decode binary value", ioe);
-			    }
-			    vals[i] = new BinaryValue(baos.toByteArray());
-			} else {
-			    vals[i] = ValueHelper.convert(value, currentPropType);
-			}
-		    }
-		    if (current.node.hasProperty(currentPropName)) {
-			PropertyDef def = current.node.getProperty(currentPropName).getDefinition();
-			if (def.isProtected()) {
-			    // ignore protected property
-			    // reset temp fields and get outta here
-			    currentPropValues = null;
-			    return;
-			}
-		    }
-		    // multi- or single-valued property?
-		    if (vals.length == 1) {
-			// could be single- or multi-valued (n == 1)
-			try {
-			    // try setting single-value
-			    current.node.setProperty(currentPropName, vals[0]);
-			} catch (ValueFormatException vfe) {
+        try {
+            String elemName;
+            if (localName != null && !"".equals(localName)) {
+                elemName = localName;
+            } else {
+                try {
+                    elemName = QName.fromJCRName(qName, session.getNamespaceResolver()).getLocalName();
+                } catch (BaseException e) {
+                    // should never happen...
+                    String msg = "internal error: failed to parse/resolve element name " + qName;
+                    log.error(msg, e);
+                    throw new SAXException(msg, e);
+                }
+            }
+            // check element name
+            ImportState current = (ImportState) stateStack.peek();
+            if (SysViewSAXEventGenerator.NODE_ELEMENT.equals(elemName)) {
+                // sv:node element
+                if (current.node == null) {
+                    // need to create current node first
+                    createNode(current);
+                }
+                // pop current state from stack
+                stateStack.pop();
+            } else if (SysViewSAXEventGenerator.PROPERTY_ELEMENT.equals(elemName)) {
+                // sv:property element
+
+                // check if all system properties (jcr:primaryType, jcr:uuid etc.)
+                // have been collected and create node as necessary
+                if (currentPropName.equals(ItemImpl.PROPNAME_PRIMARYTYPE)) {
+                    try {
+                        current.primaryType = QName.fromJCRName((String) currentPropValues.get(0), session.getNamespaceResolver());
+                    } catch (IllegalNameException ine) {
+                        throw new SAXException(new InvalidSerializedDataException("illegal node type name: " + currentPropValues.get(0), ine));
+                    } catch (UnknownPrefixException upe) {
+                        throw new SAXException(new InvalidSerializedDataException("illegal node type name: " + currentPropValues.get(0), upe));
+                    }
+                } else if (currentPropName.equals(ItemImpl.PROPNAME_MIXINTYPES)) {
+                    if (current.mixinTypes == null) {
+                        current.mixinTypes = new ArrayList(currentPropValues.size());
+                    }
+                    for (int i = 0; i < currentPropValues.size(); i++) {
+                        try {
+                            QName mixin = QName.fromJCRName((String) currentPropValues.get(i), session.getNamespaceResolver());
+                            current.mixinTypes.add(mixin);
+                        } catch (IllegalNameException ine) {
+                            throw new SAXException(new InvalidSerializedDataException("illegal mixin type name: " + currentPropValues.get(i), ine));
+                        } catch (UnknownPrefixException upe) {
+                            throw new SAXException(new InvalidSerializedDataException("illegal mixin type name: " + currentPropValues.get(i), upe));
+                        }
+                    }
+                } else if (currentPropName.equals(ItemImpl.PROPNAME_UUID)) {
+                    current.uuid = (String) currentPropValues.get(0);
+                    // jcr:uuid is the last system property; we can assume that all
+                    // required system properties have been collected by now
+                    if (current.node == null) {
+                        // now that we're collected all required system properties
+                        // we're ready to create the node
+                        createNode(current);
+                    }
+                } else if (currentPropName.equals(VersionManager.PROPNAME_BASE_VERSION)) {
+// ignore so far
+                } else if (currentPropName.equals(VersionManager.PROPNAME_VERSION_HISTORY)) {
+// ignore so far
+                } else if (currentPropName.equals(VersionManager.PROPNAME_PREDECESSORS)) {
+// ignore so far
+                } else if (currentPropName.equals(VersionManager.PROPNAME_IS_CHECKED_OUT)) {
+// ignore so far
+                } else {
+                    // non-system property encountered; we can assume that all
+                    // required system properties have been collected by now
+                    if (current.node == null) {
+                        // now that we're collected all required system properties
+                        // we're ready to create the node
+                        createNode(current);
+                    }
+
+                    // convert values to native type and set property
+                    Value[] vals = new Value[currentPropValues.size()];
+                    for (int i = 0; i < currentPropValues.size(); i++) {
+                        String value = (String) currentPropValues.get(i);
+                        if (currentPropType == PropertyType.BINARY) {
+                            // base64 encoded binary value
+                            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                            try {
+                                Base64.decode(value, baos);
+                                baos.close();
+                            } catch (IOException ioe) {
+                                throw new SAXException("failed to decode binary value", ioe);
+                            }
+                            vals[i] = new BinaryValue(baos.toByteArray());
+                        } else {
+                            vals[i] = ValueHelper.convert(value, currentPropType);
+                        }
+                    }
+                    if (current.node.hasProperty(currentPropName)) {
+                        PropertyDef def = current.node.getProperty(currentPropName).getDefinition();
+                        if (def.isProtected()) {
+                            // ignore protected property
+                            // reset temp fields and get outta here
+                            currentPropValues = null;
+                            return;
+                        }
+                    }
+                    // multi- or single-valued property?
+                    if (vals.length == 1) {
+                        // could be single- or multi-valued (n == 1)
+                        try {
+                            // try setting single-value
+                            current.node.setProperty(currentPropName, vals[0]);
+                        } catch (ValueFormatException vfe) {
+// try setting value array
+                            current.node.setProperty(currentPropName, vals);
+                        } catch (ConstraintViolationException vfe) {
                             // try setting value array
                             current.node.setProperty(currentPropName, vals);
-			} catch (ConstraintViolationException vfe) {
-			    // try setting value array
-			    current.node.setProperty(currentPropName, vals);
-			}
-		    } else {
-			// can only be multi-valued (n == 0 || n > 1)
-			current.node.setProperty(currentPropName, vals);
-		    }
-                    // check if reference for later resolution
-                    if (currentPropType==PropertyType.REFERENCE) {
+                        }
+                    } else {
+                        // can only be multi-valued (n == 0 || n > 1)
+                        current.node.setProperty(currentPropName, vals);
+                    }
+// check if reference for later resolution
+                    if (currentPropType == PropertyType.REFERENCE) {
                         references.add(current.node.getProperty(currentPropName));
                     }
-		}
+                }
 
-		// reset temp fields
-		currentPropValues = null;
-	    } else if (SysViewSAXEventGenerator.VALUE_ELEMENT.equals(elemName)) {
-		// sv:value element
-		currentPropValues.add(currentPropValue.toString());
-		// reset temp fields
-		currentPropValue = null;
-	    } else {
-		throw new SAXException(new InvalidSerializedDataException("invalid element in system view xml document: " + elemName));
-	    }
-	} catch (RepositoryException re) {
-	    throw new SAXException(re);
-	}
+                // reset temp fields
+                currentPropValues = null;
+            } else if (SysViewSAXEventGenerator.VALUE_ELEMENT.equals(elemName)) {
+                // sv:value element
+                currentPropValues.add(currentPropValue.toString());
+                // reset temp fields
+                currentPropValue = null;
+            } else {
+                throw new SAXException(new InvalidSerializedDataException("invalid element in system view xml document: " + elemName));
+            }
+        } catch (RepositoryException re) {
+            throw new SAXException(re);
+        }
     }
 
     private void createNode(ImportState state) throws RepositoryException {
-	if (state.primaryType == null) {
-	    throw new InvalidSerializedDataException("missing mandatory jcr:primaryType property");
-	}
-	if (state.uuid != null) {
-	    // @todo what are the semantics of the uuid with respect to import?
-	    // move existing node with given uuid to current position?
-	    // create with new uuid? what about reference values refering to given uuid?
-	}
-	if (state.parent.hasNode(state.nodeName)) {
+        if (state.primaryType == null) {
+            throw new InvalidSerializedDataException("missing mandatory jcr:primaryType property");
+        }
+        if (state.uuid != null) {
+            // @todo what are the semantics of the uuid with respect to import?
+            // move existing node with given uuid to current position?
+            // create with new uuid? what about reference values refering to given uuid?
+        }
+        if (state.parent.hasNode(state.nodeName)) {
             state.node = state.parent.getNode(state.nodeName);
-	    NodeDef def = state.node.getDefinition();
-	    if (def.isProtected()) {
-                // @todo how to handle protected/auto-created child node?
+            NodeDef def = state.node.getDefinition();
+            if (def.isProtected()) {
+// @todo how to handle protected/auto-created child node?
 
             } else if (def.isAutoCreate()) {
-		// @todo how to handle protected/auto-created child node?
+                // @todo how to handle protected/auto-created child node?
 
-	    }
-	} else {
+            }
+        } else {
             state.node = (NodeImpl) state.parent.addNode(state.nodeName, state.primaryType);
             if (state.mixinTypes != null) {
                 for (int i = 0; i < state.mixinTypes.size(); i++) {
@@ -375,12 +379,12 @@
                 if (prop.getDefinition().isMultiple()) {
                     Value[] values = prop.getValues();
                     Value[] newVals = new Value[values.length];
-                    for (int i=0; i<values.length; i++) {
+                    for (int i = 0; i < values.length; i++) {
                         Value val = values[i];
-                        if (val.getType()==PropertyType.REFERENCE) {
+                        if (val.getType() == PropertyType.REFERENCE) {
                             String original = val.getString();
                             String adjusted = (String) referees.get(original);
-                            if (adjusted==null) {
+                            if (adjusted == null) {
                                 log.error("Reference " + original + " of property can not be adjusted! " + prop.getPath());
                                 newVals[i] = val;
                             } else {
@@ -393,10 +397,10 @@
                     prop.setValue(newVals);
                 } else {
                     Value val = prop.getValue();
-                    if (val.getType()==PropertyType.REFERENCE) {
+                    if (val.getType() == PropertyType.REFERENCE) {
                         String original = val.getString();
                         String adjusted = (String) referees.get(original);
-                        if (adjusted==null) {
+                        if (adjusted == null) {
                             log.error("Reference " + original + " of property can not be adjusted! " + prop.getPath());
                         } else {
                             prop.setValue(session.getNodeByUUID(adjusted));
@@ -412,12 +416,12 @@
 
     //--------------------------------------------------------< inner classes >
     class ImportState {
-	QName primaryType = null;
-	ArrayList mixinTypes = null;
-	String uuid = null;
-
-	QName nodeName = null;
-	NodeImpl parent = null;
-	NodeImpl node = null;
+        QName primaryType = null;
+        ArrayList mixinTypes = null;
+        String uuid = null;
+
+        QName nodeName = null;
+        NodeImpl parent = null;
+        NodeImpl node = null;
     }
 }