jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ste...@apache.org
Subject svn commit: r158927 - in incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core: ./ nodetype/ state/xml/ xml/
Date Thu, 24 Mar 2005 17:52:38 GMT
Author: stefan
Date: Thu Mar 24 09:52:33 2005
New Revision: 158927

URL: http://svn.apache.org/viewcvs?view=rev&rev=158927
Log:
re-implementing Workspace methods clone, copy, importXML [work in progress...]
plus various minor fixes and cosmetical changes


Modified:
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/InternalValue.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemImpl.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/EffectiveNodeType.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeImpl.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/xml/XMLPersistenceManager.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/DocViewImportHandler.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/ImportHandler.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/Importer.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SessionImporter.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SysViewImportHandler.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java?view=diff&r1=158926&r2=158927
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java Thu Mar 24 09:52:33 2005
@@ -81,10 +81,10 @@
     }
 
     /**
-     * Failsafe translation of internal <code>ItemId</code> to JCR path for use in
-     * error messages etc.
+     * Failsafe translation of internal <code>ItemId</code> to JCR path for use
+     * in error messages etc.
      *
-     * @param id path to convert
+     * @param id id to translate
      * @return JCR path
      */
     public String safeGetJCRPath(ItemId id) {

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/InternalValue.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/InternalValue.java?view=diff&r1=158926&r2=158927
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/InternalValue.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/InternalValue.java Thu Mar 24 09:52:33 2005
@@ -128,7 +128,8 @@
      * @throws ValueFormatException
      * @throws RepositoryException
      */
-    public static InternalValue create(Value value, int targetType, NamespaceResolver nsResolver)
+    public static InternalValue create(Value value, int targetType,
+                                       NamespaceResolver nsResolver)
             throws ValueFormatException, RepositoryException {
         if (value == null) {
             throw new IllegalArgumentException("null value");
@@ -144,7 +145,8 @@
      * @throws ValueFormatException
      * @throws RepositoryException
      */
-    public static InternalValue create(String value, int targetType, NamespaceResolver nsResolver)
+    public static InternalValue create(String value, int targetType,
+                                       NamespaceResolver nsResolver)
             throws ValueFormatException, RepositoryException {
         if (value == null) {
             throw new IllegalArgumentException("null value");
@@ -206,7 +208,8 @@
      * @return
      * @throws IOException
      */
-    public static InternalValue create(FileSystemResource value) throws IOException {
+    public static InternalValue create(FileSystemResource value)
+            throws IOException {
         return new InternalValue(new BLOBFileValue(value));
     }
 
@@ -285,7 +288,8 @@
      * @return
      * @throws RepositoryException
      */
-    public Value toJCRValue(NamespaceResolver nsResolver) throws RepositoryException {
+    public Value toJCRValue(NamespaceResolver nsResolver)
+            throws RepositoryException {
         switch (type) {
             case PropertyType.BINARY:
                 return new BinaryValue(((BLOBFileValue) val).getStream());

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemImpl.java?view=diff&r1=158926&r2=158927
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemImpl.java Thu Mar 24 09:52:33 2005
@@ -839,7 +839,6 @@
      * @throws RepositoryException
      */
     private boolean initVersionHistories(Iterator iter) throws RepositoryException {
-        // todo consolidate version history creation code (currently in NodeImpl.addMixin & ItemImpl.initVersionHistories
         // walk through list of transient items and search for new versionable nodes
         boolean createdTransientState = false;
         while (iter.hasNext()) {
@@ -1315,7 +1314,7 @@
 
         if (isNode()) {
             // check if this is the root node
-            if (((NodeImpl) this).getDepth() == 0) {
+            if (getDepth() == 0) {
                 // optimization
                 stateMgr.disposeAllTransientItemStates();
                 return;

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java?view=diff&r1=158926&r2=158927
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java Thu Mar 24 09:52:33 2005
@@ -278,6 +278,15 @@
         return state;
     }
 
+    /**
+     * Computes the values of well-known system (i.e. protected) properties.
+     * todo: duplicate code in WorkspaceImporter: consolidate and delegate to NodeTypeInstanceHandler
+     *
+     * @param name
+     * @param def
+     * @return
+     * @throws RepositoryException
+     */
     protected InternalValue[] computeSystemGeneratedPropertyValues(QName name,
                                                                    PropertyDefImpl def)
             throws RepositoryException {
@@ -290,16 +299,16 @@
 
         NodeState thisState = (NodeState) state;
 
-        // compute/apply system generated values
+        // compute system generated values
         NodeTypeImpl nt = (NodeTypeImpl) def.getDeclaringNodeType();
         if (nt.getQName().equals(MIX_REFERENCEABLE)) {
             // mix:referenceable node type
             if (name.equals(JCR_UUID)) {
                 // jcr:uuid property
-                genValues = new InternalValue[]{InternalValue.create(((NodeState) state).getUUID())};
+                genValues = new InternalValue[]{InternalValue.create(thisState.getUUID())};
             }
 /*
-	todo consolidate version history creation code (currently in NodeImpl.addMixin & ItemImpl.initVersionHistories
+	todo consolidate version history creation code (currently in ItemImpl.initVersionHistories)
 	} else if (nt.getQName().equals(MIX_VERSIONABLE)) {
 	    // mix:versionable node type
 	    VersionHistory hist = session.getVersionManager().getOrCreateVersionHistory(this);
@@ -324,13 +333,13 @@
                 genValues = new InternalValue[]{InternalValue.create(Calendar.getInstance())};
             }
         } else if (nt.getQName().equals(NT_RESOURCE)) {
-            // nt:mimeResource node type
+            // nt:resource node type
             if (name.equals(JCR_LASTMODIFIED)) {
                 // jcr:lastModified property
                 genValues = new InternalValue[]{InternalValue.create(Calendar.getInstance())};
             }
         } else if (nt.getQName().equals(NT_VERSION)) {
-            // nt:hierarchyNode node type
+            // nt:version node type
             if (name.equals(JCR_CREATED)) {
                 // jcr:created property
                 genValues = new InternalValue[]{InternalValue.create(Calendar.getInstance())};
@@ -413,19 +422,13 @@
             propState.setMultiValued(def.isMultiple());
             propState.setDefinitionId(new PropDefId(def.unwrap()));
             // compute system generated values if necessary
-            InternalValue[] genValues = computeSystemGeneratedPropertyValues(name, def);
+            InternalValue[] genValues =
+                    computeSystemGeneratedPropertyValues(name, def);
+            InternalValue[] defValues = def.unwrap().getDefaultValues();
             if (genValues != null) {
                 propState.setValues(genValues);
-            } else if (def.getDefaultValues() != null) {
-                Value[] vals = def.getDefaultValues();
-                if (vals.length > 0) {
-                    int length = (def.isMultiple() ? vals.length : 1);
-                    InternalValue[] defVals = new InternalValue[length];
-                    for (int i = 0; i < length; i++) {
-                        defVals[i] = InternalValue.create(vals[i], session.getNamespaceResolver());
-                    }
-                    propState.setValues(defVals);
-                }
+            } else if (defValues != null) {
+                propState.setValues(defValues);
             }
         } catch (ItemStateException ise) {
             String msg = "failed to add property " + name + " to " + safeGetJCRPath();
@@ -788,7 +791,7 @@
      * @return the effective node type
      * @throws RepositoryException
      */
-    protected EffectiveNodeType getEffectiveNodeType() throws RepositoryException {
+    public EffectiveNodeType getEffectiveNodeType() throws RepositoryException {
         // build effective node type of mixins & primary type
         NodeTypeRegistry ntReg = session.getNodeTypeManager().getNodeTypeRegistry();
         // existing mixin's
@@ -879,7 +882,7 @@
 
     /**
      * Same as <code>{@link Node#getReferences()}</code> except that
-     * this method also filters out the references that appear to non-existent
+     * this method also filters out the references that appear to be non-existent
      * in this workspace if <code>skipInexistent</code> is set to <code>true</code>.
      *
      * @param skipInexistent if set to <code>true</code> inexistent items are skipped

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java?view=diff&r1=158926&r2=158927
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java Thu Mar 24 09:52:33 2005
@@ -431,7 +431,7 @@
                 // should never happen, ignore...
             }
         }
-        return names;
+        return (String[]) list.toArray(new String[list.size()]);
     }
 
     /**

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java?view=diff&r1=158926&r2=158927
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java Thu Mar 24 09:52:33 2005
@@ -37,13 +37,15 @@
 import org.apache.jackrabbit.core.state.PropertyState;
 import org.apache.jackrabbit.core.state.SharedItemStateManager;
 import org.apache.jackrabbit.core.state.TransactionalItemStateManager;
-import org.apache.jackrabbit.core.util.uuid.UUID;
 import org.apache.jackrabbit.core.util.ReferenceChangeTracker;
+import org.apache.jackrabbit.core.util.uuid.UUID;
 import org.apache.jackrabbit.core.version.GenericVersionSelector;
 import org.apache.jackrabbit.core.version.InternalVersion;
 import org.apache.jackrabbit.core.version.VersionImpl;
 import org.apache.jackrabbit.core.version.VersionSelector;
 import org.apache.jackrabbit.core.xml.ImportHandler;
+import org.apache.jackrabbit.core.xml.WorkspaceImporter;
+import org.apache.jackrabbit.core.xml.Importer;
 import org.apache.log4j.Logger;
 import org.xml.sax.Attributes;
 import org.xml.sax.ContentHandler;
@@ -439,7 +441,8 @@
             EffectiveNodeType entParent = getEffectiveNodeType(parentState);
             entParent.checkAddNodeConstraints(nodeName, nodeTypeName);
             ChildNodeDef newNodeDef =
-                    findApplicableDefinition(nodeName, nodeTypeName, parentState);
+                    findApplicableNodeDefinition(nodeName, nodeTypeName,
+                            parentState);
 
             // check for name collisions
             if (parentState.hasPropertyEntry(nodeName)) {
@@ -701,7 +704,7 @@
             throws RepositoryException {
         // build effective node type of mixins & primary type:
         // existing mixin's
-        HashSet set = new HashSet((state).getMixinTypeNames());
+        HashSet set = new HashSet(state.getMixinTypeNames());
         // primary type
         set.add(state.getNodeTypeName());
         NodeTypeRegistry ntReg = rep.getNodeTypeRegistry();
@@ -717,9 +720,9 @@
     }
 
     /**
-     * Helper method that finds the applicable definition for the
-     * a child node with the given name and node type in the parent node's
-     * node type and mixin types.
+     * Helper method that finds the applicable definition for a child node with
+     * the given name and node type in the parent node's node type and
+     * mixin types.
      *
      * @param name
      * @param nodeTypeName
@@ -729,20 +732,44 @@
      *                                      could be found
      * @throws RepositoryException          if another error occurs
      */
-    public ChildNodeDef findApplicableDefinition(QName name,
-                                                 QName nodeTypeName,
-                                                 NodeState parentState)
+    public ChildNodeDef findApplicableNodeDefinition(QName name,
+                                                     QName nodeTypeName,
+                                                     NodeState parentState)
             throws RepositoryException, ConstraintViolationException {
         EffectiveNodeType entParent = getEffectiveNodeType(parentState);
         return entParent.getApplicableChildNodeDef(name, nodeTypeName);
     }
 
     /**
+     * Helper method that finds the applicable definition for a property with
+     * the given name, type and multiValued characteristic in the parent node's
+     * node type and mixin types.
+     *
+     * @param name
+     * @param type
+     * @param multiValued
+     * @param parentState
+     * @return a <code>PropDef</code>
+     * @throws ConstraintViolationException if no applicable property definition
+     *                                      could be found
+     * @throws RepositoryException          if another error occurs
+     */
+    public PropDef findApplicablePropertyDefinition(QName name,
+                                                    int type,
+                                                    boolean multiValued,
+                                                    NodeState parentState)
+            throws RepositoryException, ConstraintViolationException {
+        EffectiveNodeType entParent = getEffectiveNodeType(parentState);
+        return entParent.getApplicablePropertyDef(name, type, multiValued);
+    }
+
+    /**
      * Recursively removes the specified node state including its properties and
      * child nodes.
      * <p/>
      * <b>Precondition:</b> the state manager of this workspace needs to be in
      * edit mode.
+     * todo duplicate code in WorkspaceImporter; consolidate in WorkspaceOperations class
      *
      * @param targetState
      * @param parentUUID
@@ -1090,7 +1117,7 @@
 
             // change definition (id) of new node
             ChildNodeDef newNodeDef =
-                    findApplicableDefinition(destName.getName(),
+                    findApplicableNodeDefinition(destName.getName(),
                             srcState.getNodeTypeName(), destParentState);
             newState.setDefinitionId(new NodeDefId(newNodeDef));
 
@@ -1385,7 +1412,9 @@
             destParentState.addChildNodeEntry(destName.getName(), targetState.getUUID());
 
             // change definition (id) of target node
-            ChildNodeDef newTargetDef = findApplicableDefinition(destName.getName(), targetState.getNodeTypeName(), destParentState);
+            ChildNodeDef newTargetDef =
+                    findApplicableNodeDefinition(destName.getName(),
+                            targetState.getNodeTypeName(), destParentState);
             targetState.setDefinitionId(new NodeDefId(newTargetDef));
 
             // remove from old parent
@@ -1663,7 +1692,8 @@
         // check locked-status
         getLockManager().checkLock(parentPath, session);
 
-        Importer importer = new WorkspaceImporter(parentState, this, uuidBehavior);
+        Importer importer = new WorkspaceImporter(parentState, this,
+                rep.getNodeTypeRegistry(), uuidBehavior);
         return new ImportHandler(importer, session.getNamespaceResolver(),
                 rep.getNamespaceRegistry());
 */

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/EffectiveNodeType.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/EffectiveNodeType.java?view=diff&r1=158926&r2=158927
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/EffectiveNodeType.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/EffectiveNodeType.java Thu Mar 24 09:52:33 2005
@@ -441,7 +441,7 @@
             // no constraints to check
             return;
         }
-        if (values != null || values.length > 0) {
+        if (values != null && values.length > 0) {
             // check value constraints on every value
             for (int i = 0; i < values.length; i++) {
                 // constraints are OR-ed together
@@ -572,7 +572,7 @@
 
     /**
      * Returns the applicable property definition for a property with the
-     * specified name and type.
+     * specified name, type and multiValued characteristic.
      *
      * @param name
      * @param type
@@ -581,7 +581,8 @@
      * @throws ConstraintViolationException if no applicable property definition
      *                                      could be found
      */
-    public PropDef getApplicablePropertyDef(QName name, int type, boolean multiValued)
+    public PropDef getApplicablePropertyDef(QName name, int type,
+                                            boolean multiValued)
             throws ConstraintViolationException {
         // try named property definitions first
         ChildItemDef[] defs = getNamedItemDefs(name);

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeImpl.java?view=diff&r1=158926&r2=158927
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/NodeTypeImpl.java Thu Mar 24 09:52:33 2005
@@ -429,8 +429,8 @@
         }
         try {
             QName name = QName.fromJCRName(propertyName, nsResolver);
-            int type = (value == null) ? PropertyType.UNDEFINED : value.getType();
-            PropertyDefImpl def = getApplicablePropertyDef(name, type, false);
+            PropertyDefImpl def =
+                    getApplicablePropertyDef(name, value.getType(), false);
             if (def.isProtected()) {
                 return false;
             }
@@ -458,7 +458,7 @@
         }
         try {
             QName name = QName.fromJCRName(propertyName, nsResolver);
-            int type = (values == null || values.length == 0) ? PropertyType.UNDEFINED : values[0].getType();
+            int type = (values.length == 0) ? PropertyType.UNDEFINED : values[0].getType();
             PropertyDefImpl def = getApplicablePropertyDef(name, type, true);
             if (def.isProtected()) {
                 return false;

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&r1=158926&r2=158927
==============================================================================
--- 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 Thu Mar 24 09:52:33 2005
@@ -19,13 +19,13 @@
 import org.apache.commons.collections.ReferenceMap;
 import org.apache.jackrabbit.core.Constants;
 import org.apache.jackrabbit.core.InternalValue;
-import org.apache.jackrabbit.core.NamespaceRegistryImpl;
 import org.apache.jackrabbit.core.QName;
 import org.apache.jackrabbit.core.fs.FileSystem;
 import org.apache.jackrabbit.core.fs.FileSystemException;
 import org.apache.jackrabbit.core.fs.FileSystemResource;
 import org.apache.log4j.Logger;
 
+import javax.jcr.NamespaceRegistry;
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 import javax.jcr.nodetype.ConstraintViolationException;
@@ -88,7 +88,7 @@
      * namespace registry for resolving prefixes and namespace URI's;
      * used for (de)serializing node type definitions
      */
-    private final NamespaceRegistryImpl nsReg;
+    private final NamespaceRegistry nsReg;
 
     /**
      * FIXME
@@ -115,7 +115,7 @@
      * @return <code>NodeTypeRegistry</codes> object
      * @throws RepositoryException
      */
-    public static NodeTypeRegistry create(NamespaceRegistryImpl nsReg, FileSystem ntStore)
+    public static NodeTypeRegistry create(NamespaceRegistry nsReg, FileSystem ntStore)
             throws RepositoryException {
         NodeTypeRegistry ntMgr = new NodeTypeRegistry(nsReg, ntStore);
         return ntMgr;
@@ -128,7 +128,7 @@
      * @param ntStore
      * @throws RepositoryException
      */
-    private NodeTypeRegistry(NamespaceRegistryImpl nsReg, FileSystem ntStore)
+    private NodeTypeRegistry(NamespaceRegistry nsReg, FileSystem ntStore)
             throws RepositoryException {
         this.nsReg = nsReg;
         this.ntStore = ntStore;
@@ -352,7 +352,7 @@
         iter = keys.iterator();
         while (iter.hasNext()) {
             WeightedKey k = (WeightedKey) iter.next();
-            EffectiveNodeType ent = (EffectiveNodeType) entCache.get(k);
+            EffectiveNodeType ent = entCache.get(k);
             if (ent.includesNodeType(name)) {
                 entCache.remove(k);
             }
@@ -959,8 +959,8 @@
                  */
                 QName[] remainder = key.toArray();
                 for (int i = 0; i < remainder.length; i++) {
-                    EffectiveNodeType ent = null;
-                    ent = EffectiveNodeType.create(this, remainder[i]);
+                    EffectiveNodeType ent =
+                            EffectiveNodeType.create(this, remainder[i]);
                     // store new effective node type
                     entCache.put(ent);
                     if (result == null) {
@@ -1210,7 +1210,7 @@
             msg.append(name + " could not be removed because the following node types are referencing it: ");
             Iterator iterator = dependentNTs.iterator();
             while (iterator.hasNext()) {
-                msg.append((QName) iterator.next());
+                msg.append(iterator.next());
                 msg.append(" ");
             }
             throw new RepositoryException(msg.toString());

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/xml/XMLPersistenceManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/xml/XMLPersistenceManager.java?view=diff&r1=158926&r2=158927
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/xml/XMLPersistenceManager.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/xml/XMLPersistenceManager.java Thu Mar 24 09:52:33 2005
@@ -881,8 +881,7 @@
         }
 
         try {
-            NodeId nodeId = (NodeId) id;
-            String nodeFilePath = buildNodeFilePath(nodeId.getUUID());
+            String nodeFilePath = buildNodeFilePath(id.getUUID());
             FileSystemResource nodeFile = new FileSystemResource(itemStateStore, nodeFilePath);
             return nodeFile.exists();
         } catch (FileSystemException fse) {

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/DocViewImportHandler.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/DocViewImportHandler.java?view=diff&r1=158926&r2=158927
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/DocViewImportHandler.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/DocViewImportHandler.java Thu Mar 24 09:52:33 2005
@@ -19,6 +19,7 @@
 import org.apache.jackrabbit.core.BaseException;
 import org.apache.jackrabbit.core.Constants;
 import org.apache.jackrabbit.core.IllegalNameException;
+import org.apache.jackrabbit.core.InternalValue;
 import org.apache.jackrabbit.core.NamespaceResolver;
 import org.apache.jackrabbit.core.QName;
 import org.apache.jackrabbit.core.UnknownPrefixException;
@@ -30,8 +31,6 @@
 
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
-import javax.jcr.StringValue;
-import javax.jcr.Value;
 import java.util.ArrayList;
 import java.util.Stack;
 
@@ -80,11 +79,12 @@
             try {
                 Importer.NodeInfo node =
                         new Importer.NodeInfo(JCR_XMLTEXT, null, null, null);
-                Value[] values =
-                        new Value[]{new StringValue(text.toString())};
+                InternalValue[] values = new InternalValue[1];
+                values[0] = InternalValue.create(text.toString());
                 ArrayList props = new ArrayList();
                 Importer.PropInfo prop =
-                        new Importer.PropInfo(JCR_XMLCHARACTERS, PropertyType.STRING, values);
+                        new Importer.PropInfo(JCR_XMLCHARACTERS,
+                                PropertyType.STRING, values);
                 props.add(prop);
                 // call Importer
                 importer.startNode(node, props, nsContext);
@@ -150,9 +150,11 @@
                     try {
                         propName = QName.fromJCRName(atts.getQName(i), nsContext);
                     } catch (IllegalNameException ine) {
-                        throw new SAXException("illegal property name: " + atts.getQName(i), ine);
+                        throw new SAXException("illegal property name: "
+                                + atts.getQName(i), ine);
                     } catch (UnknownPrefixException upe) {
-                        throw new SAXException("illegal property name: " + atts.getQName(i), upe);
+                        throw new SAXException("illegal property name: "
+                                + atts.getQName(i), upe);
                     }
                 }
                 // decode property name
@@ -160,7 +162,7 @@
 
                 // value(s)
                 String attrValue = atts.getValue(i);
-                Value[] propValues;
+                InternalValue[] propValues;
 /*
                 // @todo should attribute value be interpreted as LIST type (i.e. multi-valued property)?
                 String[] strings = Text.explode(attrValue, ' ', true);
@@ -168,29 +170,40 @@
                 for (int j = 0; j < strings.length; j++) {
                     // decode encoded blanks in value
                     strings[j] = Text.replace(strings[j], "_x0020_", " ");
-                    propValues[j] = new StringValue(strings[j]);
+                    propValues[j] = InternalValue.create(strings[j]);
                 }
 */
                 if (propName.equals(JCR_PRIMARYTYPE)) {
                     // jcr:primaryType
-                    try {
-                        nodeTypeName = QName.fromJCRName(attrValue, nsContext);
-                    } catch (BaseException be) {
-                        throw new SAXException("illegal jcr:primaryType value: " + attrValue, be);
+                    if (attrValue.length() > 0) {
+                        try {
+                            nodeTypeName = QName.fromJCRName(attrValue, nsContext);
+                        } catch (BaseException be) {
+                            throw new SAXException("illegal jcr:primaryType value: "
+                                    + attrValue, be);
+                        }
                     }
                 } else if (propName.equals(JCR_MIXINTYPES)) {
                     // jcr:mixinTypes
-                    try {
-                        mixinTypes = new QName[]{QName.fromJCRName(attrValue, nsContext)};
-                    } catch (BaseException be) {
-                        throw new SAXException("illegal jcr:mixinTypes value: " + attrValue, be);
+                    if (attrValue.length() > 0) {
+                        try {
+                            mixinTypes =
+                                    new QName[]{QName.fromJCRName(attrValue, nsContext)};
+                        } catch (BaseException be) {
+                            throw new SAXException("illegal jcr:mixinTypes value: "
+                                    + attrValue, be);
+                        }
                     }
                 } else if (propName.equals(JCR_UUID)) {
                     // jcr:uuid
-                    uuid = attrValue;
+                    if (attrValue.length() > 0) {
+                        uuid = attrValue;
+                    }
                 } else {
-                    propValues = new Value[]{new StringValue(atts.getValue(i))};
-                    props.add(new Importer.PropInfo(propName, PropertyType.STRING, propValues));
+                    propValues = new InternalValue[1];
+                    propValues[0] = InternalValue.create(atts.getValue(i));
+                    props.add(new Importer.PropInfo(propName,
+                            PropertyType.UNDEFINED, propValues));
                 }
             }
 

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/ImportHandler.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/ImportHandler.java?view=diff&r1=158926&r2=158927
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/ImportHandler.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/ImportHandler.java Thu Mar 24 09:52:33 2005
@@ -221,7 +221,8 @@
                     nsURI = QName.fromJCRName(qName, nsResolver).getNamespaceURI();
                 } catch (BaseException e) {
                     // should never happen...
-                    String msg = "internal error: failed to parse/resolve element name " + qName;
+                    String msg = "internal error: failed to parse/resolve element name "
+                            + qName;
                     log.debug(msg);
                     throw new SAXException(msg, e);
                 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/Importer.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/Importer.java?view=diff&r1=158926&r2=158927
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/Importer.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/Importer.java Thu Mar 24 09:52:33 2005
@@ -16,11 +16,11 @@
  */
 package org.apache.jackrabbit.core.xml;
 
+import org.apache.jackrabbit.core.InternalValue;
 import org.apache.jackrabbit.core.NamespaceResolver;
 import org.apache.jackrabbit.core.QName;
 
 import javax.jcr.RepositoryException;
-import javax.jcr.Value;
 import javax.jcr.Workspace;
 import java.util.List;
 
@@ -113,12 +113,12 @@
     public static class PropInfo {
         private QName name;
         private int type;
-        private Value[] values;
+        private InternalValue[] values;
 
         public PropInfo() {
         }
 
-        public PropInfo(QName name, int type, Value[] values) {
+        public PropInfo(QName name, int type, InternalValue[] values) {
             this.name = name;
             this.type = type;
             this.values = values;
@@ -140,11 +140,11 @@
             return type;
         }
 
-        public void setValues(Value[] values) {
+        public void setValues(InternalValue[] values) {
             this.values = values;
         }
 
-        public Value[] getValues() {
+        public InternalValue[] getValues() {
             return values;
         }
     }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SessionImporter.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SessionImporter.java?view=diff&r1=158926&r2=158927
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SessionImporter.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SessionImporter.java Thu Mar 24 09:52:33 2005
@@ -17,11 +17,15 @@
 package org.apache.jackrabbit.core.xml;
 
 import org.apache.jackrabbit.core.Constants;
+import org.apache.jackrabbit.core.InternalValue;
 import org.apache.jackrabbit.core.NamespaceResolver;
 import org.apache.jackrabbit.core.NodeImpl;
 import org.apache.jackrabbit.core.QName;
 import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.nodetype.EffectiveNodeType;
+import org.apache.jackrabbit.core.nodetype.PropDef;
 import org.apache.jackrabbit.core.util.ReferenceChangeTracker;
+import org.apache.jackrabbit.core.util.ValueHelper;
 import org.apache.log4j.Logger;
 
 import javax.jcr.ItemExistsException;
@@ -33,10 +37,7 @@
 import javax.jcr.Value;
 import javax.jcr.ValueFormatException;
 import javax.jcr.nodetype.ConstraintViolationException;
-import javax.jcr.nodetype.PropertyDef;
 import javax.jcr.nodetype.NodeDef;
-import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Stack;
@@ -81,7 +82,7 @@
             throws RepositoryException {
         NodeImpl node;
         // add node
-        node = (NodeImpl) parent.addNode(nodeName, nodeTypeName, uuid);
+        node = parent.addNode(nodeName, nodeTypeName, uuid);
         // add mixins
         if (mixinNames != null) {
             for (int i = 0; i < mixinNames.length; i++) {
@@ -224,32 +225,79 @@
         while (iter.hasNext()) {
             PropInfo pi = (PropInfo) iter.next();
             QName propName = pi.getName();
-            Value[] vals = pi.getValues();
+            InternalValue[] iva = pi.getValues();
             int type = pi.getType();
-            if (node.hasProperty(propName)) {
-                PropertyDef def = node.getProperty(propName).getDefinition();
-                if (def.isProtected()) {
-                    // skip protected property
-                    log.debug("skipping protected property " + propName);
-                    continue;
+
+            // find applicable definition
+            EffectiveNodeType ent = node.getEffectiveNodeType();
+            PropDef def;
+            // multi- or single-valued property?
+            if (iva.length == 1) {
+                // could be single- or multi-valued (n == 1)
+                try {
+                    // try single-valued
+                    def = ent.getApplicablePropertyDef(propName, type, false);
+                } catch (ConstraintViolationException cve) {
+                    // try multi-valued
+                    def = ent.getApplicablePropertyDef(propName, type, true);
+                }
+            } else {
+                // can only be multi-valued (n == 0 || n > 1)
+                def = ent.getApplicablePropertyDef(propName, type, true);
+            }
+
+            if (def.isProtected()) {
+                // skip protected property
+                log.debug("skipping protected property " + propName);
+                continue;
+            }
+
+            // convert InternalValue objects to Value objects using this
+            // session's namespace mappings
+            Value[] va = new Value[iva.length];
+            // check whether type conversion is required
+            if (def.getRequiredType() != PropertyType.UNDEFINED
+                    && def.getRequiredType() != type) {
+                // type doesn't match required type,
+                // type conversion required
+                // FIXME: awkward code
+                for (int i = 0; i < iva.length; i++) {
+                    // convert InternalValue to Value of required type
+                    Value v =
+                            ValueHelper.convert(iva[i].toJCRValue(nsContext),
+                                    def.getRequiredType());
+                    // convert Value to InternalValue using
+                    // current namespace context of xml document
+                    InternalValue ival = InternalValue.create(v, nsContext);
+                    // convert InternalValue back to Value using this
+                    // session's namespace mappings
+                    va[i] = ival.toJCRValue(session.getNamespaceResolver());
+                }
+            } else {
+                // no type conversion required:
+                // convert InternalValue to Value using this
+                // session's namespace mappings
+                for (int i = 0; i < iva.length; i++) {
+                    va[i] = iva[i].toJCRValue(session.getNamespaceResolver());
                 }
             }
+
             // multi- or single-valued property?
-            if (vals.length == 1) {
+            if (va.length == 1) {
                 // could be single- or multi-valued (n == 1)
                 try {
                     // try setting single-value
-                    node.setProperty(propName, vals[0]);
+                    node.setProperty(propName, va[0]);
                 } catch (ValueFormatException vfe) {
                     // try setting value array
-                    node.setProperty(propName, vals, type);
-                } catch (ConstraintViolationException vfe) {
+                    node.setProperty(propName, va, type);
+                } catch (ConstraintViolationException cve) {
                     // try setting value array
-                    node.setProperty(propName, vals, type);
+                    node.setProperty(propName, va, type);
                 }
             } else {
                 // can only be multi-valued (n == 0 || n > 1)
-                node.setProperty(propName, vals, type);
+                node.setProperty(propName, va, type);
             }
             if (type == PropertyType.REFERENCE) {
                 // store reference for later resolution

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&r1=158926&r2=158927
==============================================================================
--- 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 Thu Mar 24 09:52:33 2005
@@ -19,21 +19,20 @@
 import org.apache.jackrabbit.core.BaseException;
 import org.apache.jackrabbit.core.Constants;
 import org.apache.jackrabbit.core.IllegalNameException;
+import org.apache.jackrabbit.core.InternalValue;
 import org.apache.jackrabbit.core.NamespaceResolver;
 import org.apache.jackrabbit.core.QName;
 import org.apache.jackrabbit.core.UnknownPrefixException;
 import org.apache.jackrabbit.core.util.Base64;
-import org.apache.jackrabbit.core.util.ValueHelper;
 import org.apache.log4j.Logger;
 import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
 import org.xml.sax.helpers.DefaultHandler;
 
-import javax.jcr.BinaryValue;
 import javax.jcr.InvalidSerializedDataException;
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
-import javax.jcr.Value;
+import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.util.ArrayList;
@@ -282,8 +281,8 @@
                 } else if (currentPropName.equals(JCR_UUID)) {
                     state.uuid = (String) currentPropValues.get(0);
                 } else {
-                    // convert values to native type and set property
-                    Value[] vals = new Value[currentPropValues.size()];
+                    // convert values to native type
+                    InternalValue[] vals = new InternalValue[currentPropValues.size()];
                     for (int i = 0; i < currentPropValues.size(); i++) {
                         String value = (String) currentPropValues.get(i);
                         if (currentPropType == PropertyType.BINARY) {
@@ -292,12 +291,13 @@
                             try {
                                 Base64.decode(value, baos);
                                 baos.close();
+                                vals[i] = InternalValue.create(new ByteArrayInputStream(baos.toByteArray()));
                             } 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);
+                            vals[i] = InternalValue.create(value,
+                                    currentPropType, nsContext);
                         }
                     }
                     Importer.PropInfo prop = new Importer.PropInfo();

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java?view=diff&r1=158926&r2=158927
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java Thu Mar 24 09:52:33 2005
@@ -16,34 +16,59 @@
  */
 package org.apache.jackrabbit.core.xml;
 
+import org.apache.jackrabbit.core.Constants;
 import org.apache.jackrabbit.core.HierarchyManager;
+import org.apache.jackrabbit.core.InternalValue;
+import org.apache.jackrabbit.core.ItemId;
+import org.apache.jackrabbit.core.MalformedPathException;
 import org.apache.jackrabbit.core.NamespaceResolver;
+import org.apache.jackrabbit.core.NoPrefixDeclaredException;
+import org.apache.jackrabbit.core.NodeId;
+import org.apache.jackrabbit.core.Path;
+import org.apache.jackrabbit.core.PropertyId;
 import org.apache.jackrabbit.core.QName;
+import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.WorkspaceImpl;
 import org.apache.jackrabbit.core.nodetype.ChildNodeDef;
+import org.apache.jackrabbit.core.nodetype.EffectiveNodeType;
 import org.apache.jackrabbit.core.nodetype.NodeDefId;
+import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
+import org.apache.jackrabbit.core.nodetype.PropDef;
+import org.apache.jackrabbit.core.nodetype.PropDefId;
 import org.apache.jackrabbit.core.state.ItemStateException;
+import org.apache.jackrabbit.core.state.NoSuchItemStateException;
 import org.apache.jackrabbit.core.state.NodeState;
+import org.apache.jackrabbit.core.state.PropertyState;
 import org.apache.jackrabbit.core.state.UpdatableItemStateManager;
+import org.apache.jackrabbit.core.util.ReferenceChangeTracker;
+import org.apache.jackrabbit.core.util.ValueHelper;
+import org.apache.jackrabbit.core.util.uuid.UUID;
 import org.apache.log4j.Logger;
 
+import javax.jcr.ItemExistsException;
+import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.nodetype.ConstraintViolationException;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashMap;
+import java.util.Calendar;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
 import java.util.Stack;
 
 /**
  * <code>WorkspaceImporter</code> ...
  */
-public class WorkspaceImporter implements Importer {
+public class WorkspaceImporter implements Importer, Constants {
 
     private static Logger log = Logger.getLogger(WorkspaceImporter.class);
 
     private final NodeState importTarget;
     private final WorkspaceImpl wsp;
+    private final NodeTypeRegistry ntReg;
     private final HierarchyManager hierMgr;
     private final UpdatableItemStateManager stateMgr;
 
@@ -53,19 +78,26 @@
     private Stack parents;
 
     /**
-     * mapping <original uuid> to <new uuid> of mix:referenceable nodes
+     * helper object that keeps track of remapped uuid's and imported reference
+     * properties that might need correcting depending on the uuid mappings
      */
-    private final HashMap uuidMap;
+    private final ReferenceChangeTracker refTracker;
+
     /**
-     * list of imported reference properties that might need correcting
+     * Creates a <code>WorkspaceImporter</code> instance.
+     *
+     * @param importTarget
+     * @param wsp
+     * @param ntReg
+     * @param uuidBehavior
      */
-    private final ArrayList references;
-
     public WorkspaceImporter(NodeState importTarget,
                              WorkspaceImpl wsp,
+                             NodeTypeRegistry ntReg,
                              int uuidBehavior) {
         this.importTarget = importTarget;
         this.wsp = wsp;
+        this.ntReg = ntReg;
 
         hierMgr = wsp.getHierarchyManager();
         stateMgr = wsp.getItemStateManager();
@@ -74,76 +106,450 @@
 
         aborted = false;
 
-        uuidMap = new HashMap();
-        references = new ArrayList();
+        refTracker = new ReferenceChangeTracker();
 
         parents = new Stack();
         parents.push(importTarget);
     }
 
+    /**
+     * Failsafe translation of internal <code>ItemId</code> to JCR path for
+     * use in error messages etc.
+     *
+     * @param id id to translate
+     * @return JCR path
+     */
+    private String resolveJCRPath(ItemId id) {
+        Path path;
+        try {
+            path = hierMgr.getPath(id);
+        } catch (RepositoryException re) {
+            log.error(id + ": failed to determine path to");
+            // return string representation if id as a fallback
+            return id.toString();
+        }
+        try {
+            return path.toJCRPath(((SessionImpl) wsp.getSession()).getNamespaceResolver());
+        } catch (NoPrefixDeclaredException npde) {
+            log.error("failed to convert " + path.toString() + " to JCR path.");
+            // return string representation of internal path as a fallback
+            return path.toString();
+        }
+    }
+
     protected NodeState createNode(NodeState parent,
                                    QName nodeName,
                                    QName nodeTypeName,
                                    QName[] mixinNames,
                                    String uuid)
             throws RepositoryException {
+        ChildNodeDef def =
+                wsp.findApplicableNodeDefinition(nodeName, nodeTypeName, parent);
+        return createNode(parent, nodeName, nodeTypeName, mixinNames, uuid, def);
+    }
+
+    protected NodeState createNode(NodeState parent,
+                                   QName nodeName,
+                                   QName nodeTypeName,
+                                   QName[] mixinNames,
+                                   String uuid,
+                                   ChildNodeDef def)
+            throws RepositoryException {
+        // check for name collisions with existing properties
+        if (parent.hasPropertyEntry(nodeName)) {
+            String msg = "there's already a property with name " + nodeName;
+            log.debug(msg);
+            throw new RepositoryException(msg);
+        }
+        // check for name collisions with existing nodes
+        if (!def.allowSameNameSibs() && parent.hasChildNodeEntry(nodeName)) {
+            NodeId id = new NodeId(parent.getChildNodeEntry(nodeName, 1).getUUID());
+            throw new ItemExistsException(resolveJCRPath(id));
+        }
+        if (uuid == null) {
+            // create new uuid
+            uuid = UUID.randomUUID().toString();    // create new version 4 uuid
+        }
+        if (nodeTypeName == null) {
+            // no primary node type specified,
+            // try default primary type from definition
+            nodeTypeName = def.getDefaultPrimaryType();
+            if (nodeTypeName == null) {
+                String msg = "an applicable node type could not be determined for "
+                        + nodeName;
+                log.debug(msg);
+                throw new ConstraintViolationException (msg);
+            }
+        }
         NodeState node = stateMgr.createNew(uuid, nodeTypeName, parent.getUUID());
-        node.setMixinTypeNames(new HashSet(Arrays.asList(mixinNames)));
-        ChildNodeDef nodeDef =
-                wsp.findApplicableDefinition(nodeName, nodeTypeName, parent);
-        node.setDefinitionId(new NodeDefId(nodeDef));
+        if (mixinNames != null && mixinNames.length > 0) {
+            node.setMixinTypeNames(new HashSet(Arrays.asList(mixinNames)));
+        }
+        node.setDefinitionId(new NodeDefId(def));
 
         // now add new child node entry to parent
         parent.addChildNodeEntry(nodeName, node.getUUID());
 
+        EffectiveNodeType ent = wsp.getEffectiveNodeType(node);
+        // add 'auto-create' properties defined in node type
+        PropDef[] pda = ent.getAutoCreatePropDefs();
+        for (int i = 0; i < pda.length; i++) {
+            PropDef pd = pda[i];
+            createProperty(node, pd.getName(), pd.getRequiredType(), pd);
+        }
+
+        // recursively add 'auto-create' child nodes defined in node type
+        ChildNodeDef[] nda = ent.getAutoCreateNodeDefs();
+        for (int i = 0; i < nda.length; i++) {
+            ChildNodeDef nd = nda[i];
+            createNode(node, nd.getName(), nd.getDefaultPrimaryType(),
+                    null, null, nd);
+        }
+
         return node;
     }
 
+    protected PropertyState createProperty(NodeState parent,
+                                           QName propName,
+                                           int type,
+                                           int numValues)
+            throws RepositoryException {
+        // find applicable definition
+        PropDef def;
+        // multi- or single-valued property?
+        if (numValues == 1) {
+            // could be single- or multi-valued (n == 1)
+            try {
+                // try single-valued
+                def = wsp.findApplicablePropertyDefinition(propName,
+                        type, false, parent);
+            } catch (ConstraintViolationException cve) {
+                // try multi-valued
+                def = wsp.findApplicablePropertyDefinition(propName,
+                        type, true, parent);
+            }
+        } else {
+            // can only be multi-valued (n == 0 || n > 1)
+            def = wsp.findApplicablePropertyDefinition(propName,
+                    type, true, parent);
+        }
+        return createProperty(parent, propName, type, def);
+    }
+
+    protected PropertyState createProperty(NodeState parent,
+                                           QName propName,
+                                           int type,
+                                           PropDef def)
+            throws RepositoryException {
+        // check for name collisions with existing child nodes
+        if (parent.hasChildNodeEntry(propName)) {
+            String msg = "there's already a child node with name " + propName;
+            log.debug(msg);
+            throw new RepositoryException(msg);
+        }
+
+        // create property
+        PropertyState prop = stateMgr.createNew(propName, parent.getUUID());
+
+        prop.setDefinitionId(new PropDefId(def));
+        if (def.getRequiredType() != PropertyType.UNDEFINED) {
+            prop.setType(def.getRequiredType());
+        } else if (type != PropertyType.UNDEFINED) {
+            prop.setType(type);
+        } else {
+            prop.setType(PropertyType.STRING);
+        }
+        prop.setMultiValued(def.isMultiple());
+
+        // compute system generated values if necessary
+        InternalValue[] genValues =
+                computeSystemGeneratedPropertyValues(parent, propName, def);
+        if (genValues != null) {
+            prop.setValues(genValues);
+        } else if (def.getDefaultValues() != null) {
+            prop.setValues(def.getDefaultValues());
+        }
+
+        // now add new property entry to parent
+        parent.addPropertyEntry(propName);
+
+        return prop;
+    }
+
+    /**
+     * Computes the values of well-known system (i.e. protected) properties.
+     * todo: duplicate code in NodeImpl: consolidate and delegate to NodeTypeInstanceHandler
+     *
+     * @param parent
+     * @param name
+     * @param def
+     * @return
+     * @throws RepositoryException
+     */
+    protected InternalValue[] computeSystemGeneratedPropertyValues(NodeState parent,
+                                                                   QName name,
+                                                                   PropDef def)
+            throws RepositoryException {
+        InternalValue[] genValues = null;
+
+        /**
+         * todo: need to come up with some callback mechanism for applying system generated values
+         * (e.g. using a NodeTypeInstanceHandler interface)
+         */
+
+        // compute system generated values
+        QName declaringNT = def.getDeclaringNodeType();
+        if (MIX_REFERENCEABLE.equals(declaringNT)) {
+            // mix:referenceable node type
+            if (JCR_UUID.equals(name)) {
+                // jcr:uuid property
+                genValues = new InternalValue[]{InternalValue.create(parent.getUUID())};
+            }
+        } else if (NT_BASE.equals(declaringNT)) {
+            // nt:base node type
+            if (JCR_PRIMARYTYPE.equals(name)) {
+                // jcr:primaryType property
+                genValues = new InternalValue[]{InternalValue.create(parent.getNodeTypeName())};
+            } else if (JCR_MIXINTYPES.equals(name)) {
+                // jcr:mixinTypes property
+                Set mixins = parent.getMixinTypeNames();
+                ArrayList values = new ArrayList(mixins.size());
+                Iterator iter = mixins.iterator();
+                while (iter.hasNext()) {
+                    values.add(InternalValue.create((QName) iter.next()));
+                }
+                genValues = (InternalValue[]) values.toArray(new InternalValue[values.size()]);
+            }
+        } else if (NT_HIERARCHYNODE.equals(declaringNT)) {
+            // nt:hierarchyNode node type
+            if (JCR_CREATED.equals(name)) {
+                // jcr:created property
+                genValues = new InternalValue[]{InternalValue.create(Calendar.getInstance())};
+            }
+        } else if (NT_RESOURCE.equals(declaringNT)) {
+            // nt:resource node type
+            if (JCR_LASTMODIFIED.equals(name)) {
+                // jcr:lastModified property
+                genValues = new InternalValue[]{InternalValue.create(Calendar.getInstance())};
+            }
+        } else if (NT_VERSION.equals(declaringNT)) {
+            // nt:version node type
+            if (JCR_CREATED.equals(name)) {
+                // jcr:created property
+                genValues = new InternalValue[]{InternalValue.create(Calendar.getInstance())};
+            }
+/*
+        // FIXME delegate to NodeTypeInstanceHandler
+        } else if (MIX_VERSIONABLE.equals(declaringNT)) {
+	    // mix:versionable node type
+	    if (JCR_VERSIONHISTORY.equals(name)) {
+		// jcr:versionHistory property
+		genValues = new InternalValue[]{InternalValue.create(new UUID(hist.getUUID()))};
+	    } else if (JCR_BASEVERSION.equals(name)) {
+		// jcr:baseVersion property
+		genValues = new InternalValue[]{InternalValue.create(new UUID(hist.getRootVersion().getUUID()))};
+	    } else if (JCR_ISCHECKEDOUT.equals(name)) {
+		// jcr:isCheckedOut property
+		genValues = new InternalValue[]{InternalValue.create(true)};
+	    } else if (JCR_PREDECESSORS.equals(name)) {
+		// jcr:predecessors property
+		genValues = new InternalValue[]{InternalValue.create(new UUID(hist.getRootVersion().getUUID()))};
+	    }
+*/
+        }
+
+        return genValues;
+    }
+
+    /**
+     * Recursively removes the specified node state including its properties and
+     * child nodes.
+     * <p/>
+     * todo duplicate code in WorkspaceImpl; consolidate in WorkspaceOperations class
+     *
+     * @param target
+     * @param parentUUID
+     * @throws RepositoryException if an error occurs
+     */
+    protected void removeNode(NodeState target, String parentUUID)
+            throws RepositoryException {
+        // check if this node state would be orphaned after unlinking it from parent
+        ArrayList parentUUIDs = new ArrayList(target.getParentUUIDs());
+        parentUUIDs.remove(parentUUID);
+        boolean orphaned = parentUUIDs.isEmpty();
+
+        if (orphaned) {
+            // remove child nodes
+            // use temp array to avoid ConcurrentModificationException
+            ArrayList tmp = new ArrayList(target.getChildNodeEntries());
+            // remove from tail to avoid problems with same-name siblings
+            for (int i = tmp.size() - 1; i >= 0; i--) {
+                NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) tmp.get(i);
+                NodeId nodeId = new NodeId(entry.getUUID());
+                try {
+                    NodeState node = (NodeState) stateMgr.getItemState(nodeId);
+                    // check if existing can be removed
+                    // (access rights, locking & versioning status)
+                    wsp.checkRemoveNode(node,
+                            WorkspaceImpl.CHECK_ACCESS | WorkspaceImpl.CHECK_LOCK
+                            | WorkspaceImpl.CHECK_VERSIONING);
+                    // remove child node (recursive)
+                    removeNode(node, target.getUUID());
+                } catch (ItemStateException ise) {
+                    String msg = "internal error: failed to retrieve state of "
+                            + nodeId;
+                    log.debug(msg);
+                    throw new RepositoryException(msg, ise);
+                }
+                // remove child node entry
+                target.removeChildNodeEntry(entry.getName(), entry.getIndex());
+            }
+
+            // remove properties
+            // use temp array to avoid ConcurrentModificationException
+            tmp = new ArrayList(target.getPropertyEntries());
+            // remove from tail to avoid problems with same-name siblings
+            for (int i = tmp.size() - 1; i >= 0; i--) {
+                NodeState.PropertyEntry entry = (NodeState.PropertyEntry) tmp.get(i);
+                PropertyId propId =
+                        new PropertyId(target.getUUID(), entry.getName());
+                try {
+                    PropertyState prop = (PropertyState) stateMgr.getItemState(propId);
+                    // remove property entry
+                    target.removePropertyEntry(propId.getName());
+                    // destroy property state
+                    stateMgr.destroy(prop);
+                } catch (ItemStateException ise) {
+                    String msg = "internal error: failed to retrieve state of "
+                            + propId;
+                    log.debug(msg);
+                    throw new RepositoryException(msg, ise);
+                }
+            }
+        }
+
+        // now actually do unlink target state from specified parent state
+        // (i.e. remove uuid of parent state from target state's parent list)
+        target.removeParentUUID(parentUUID);
+
+        if (orphaned) {
+            // destroy target state
+            stateMgr.destroy(target);
+        } else {
+            // store target state
+            stateMgr.store(target);
+        }
+    }
+
     protected NodeState resolveUUIDConflict(NodeState parent,
                                             NodeState conflicting,
                                             NodeInfo nodeInfo)
             throws RepositoryException {
-        NodeState node = null;
-/*
+
+        NodeState node;
         if (uuidBehavior == IMPORT_UUID_CREATE_NEW) {
-            // create new with new uuid
+            // create new with new uuid:
+            // check if new node can be added (check access rights &
+            // node type constraints only, assume locking & versioning status
+            // has already been checked on ancestor)
+            wsp.checkAddNode(parent, nodeInfo.getName(),
+                    nodeInfo.getNodeTypeName(),
+                    WorkspaceImpl.CHECK_ACCESS
+                    | WorkspaceImpl.CHECK_CONSTRAINTS);
             node = createNode(parent, nodeInfo.getName(),
                     nodeInfo.getNodeTypeName(), nodeInfo.getMixinNames(), null);
             // remember uuid mapping
-            if (node.isNodeType(Constants.MIX_REFERENCEABLE)) {
-                uuidMap.put(nodeInfo.getUUID(), node.getUUID());
+            EffectiveNodeType ent = wsp.getEffectiveNodeType(node);
+            if (ent.includesNodeType(MIX_REFERENCEABLE)) {
+                refTracker.mappedUUID(nodeInfo.getUUID(), node.getUUID());
             }
         } else if (uuidBehavior == IMPORT_UUID_COLLISION_THROW) {
-            String msg = "a node with uuid " + nodeInfo.getUUID() + " already exists!";
+            String msg = "a node with uuid " + nodeInfo.getUUID()
+                    + " already exists!";
             log.debug(msg);
             throw new ItemExistsException(msg);
         } else if (uuidBehavior == IMPORT_UUID_COLLISION_REMOVE_EXISTING) {
-            // make sure conflicting node is not importTargetNode or an ancestor thereof
-            if (importTargetNode.getPath().startsWith(conflicting.getPath())) {
-                String msg = "cannot remove ancestor node";
-                log.debug(msg);
-                throw new RepositoryException(msg);
-            }
-            // remove conflicting
-            conflicting.remove();
-            // create new with given uuid
+            // make sure conflicting node is not importTarget or an ancestor thereof
+            Path p0 = hierMgr.getPath(importTarget.getId());
+            Path p1 = hierMgr.getPath(conflicting.getId());
+            try {
+                if (p0.equals(p1) || p0.isAncestorOf(p1)) {
+                    String msg = "cannot remove ancestor node";
+                    log.debug(msg);
+                    throw new RepositoryException(msg);
+                }
+            } catch (MalformedPathException mpe) {
+                // should never get here...
+                String msg = "internal error: failed to determine degree of relationship";
+                log.error(msg, mpe);
+                throw new RepositoryException(msg, mpe);
+            }
+            // remove conflicting:
+            // check if conflicting can be removed
+            // (access rights, node type constraints, locking & versioning status)
+            wsp.checkRemoveNode(conflicting,
+                    WorkspaceImpl.CHECK_ACCESS
+                    | WorkspaceImpl.CHECK_LOCK
+                    | WorkspaceImpl.CHECK_VERSIONING
+                    | WorkspaceImpl.CHECK_CONSTRAINTS);
+            // do remove conflicting (recursive)
+            removeNode(conflicting, conflicting.getParentUUID());
+            // create new with given uuid:
+            // check if new node can be added (check access rights &
+            // node type constraints only, assume locking & versioning status
+            // has already been checked on ancestor)
+            wsp.checkAddNode(parent, nodeInfo.getName(),
+                    nodeInfo.getNodeTypeName(),
+                    WorkspaceImpl.CHECK_ACCESS
+                    | WorkspaceImpl.CHECK_CONSTRAINTS);
+            // do create new node
             node = createNode(parent, nodeInfo.getName(),
                     nodeInfo.getNodeTypeName(), nodeInfo.getMixinNames(),
                     nodeInfo.getUUID());
         } else if (uuidBehavior == IMPORT_UUID_COLLISION_REPLACE_EXISTING) {
-            if (conflicting.getDepth() == 0) {
+            if (conflicting.getParentUUID() == null) {
                 String msg = "root node cannot be replaced";
                 log.debug(msg);
                 throw new RepositoryException(msg);
             }
-            // @todo implement IMPORT_UUID_COLLISION_REPLACE_EXISTING behavior
-            throw new RepositoryException("uuidBehavior IMPORT_UUID_COLLISION_REPLACE_EXISTING is not yet implemented");
+            // 'replace' current parent with parent of conflicting
+            NodeId parentId = new NodeId(conflicting.getParentUUID());
+            try {
+                parent = (NodeState) stateMgr.getItemState(parentId);
+            } catch (ItemStateException ise) {
+                // should never get here...
+                String msg = "internal error: failed to retrieve parent state";
+                log.error(msg, ise);
+                throw new RepositoryException(msg, ise);
+            }
+            // remove conflicting:
+            // check if conflicting can be removed
+            wsp.checkRemoveNode(conflicting,
+                    WorkspaceImpl.CHECK_ACCESS
+                    | WorkspaceImpl.CHECK_LOCK
+                    | WorkspaceImpl.CHECK_VERSIONING
+                    | WorkspaceImpl.CHECK_CONSTRAINTS);
+            // do remove conflicting (recursive)
+            removeNode(conflicting, conflicting.getParentUUID());
+            // create new with given uuid at same location as conflicting:
+            // check if new node can be added at other location
+            // (access rights, node type constraints, locking & versioning status)
+            wsp.checkAddNode(parent, nodeInfo.getName(),
+                    nodeInfo.getNodeTypeName(),
+                    WorkspaceImpl.CHECK_ACCESS
+                    | WorkspaceImpl.CHECK_LOCK
+                    | WorkspaceImpl.CHECK_VERSIONING
+                    | WorkspaceImpl.CHECK_CONSTRAINTS);
+            // do create new node
+            node = createNode(parent, nodeInfo.getName(),
+                    nodeInfo.getNodeTypeName(), nodeInfo.getMixinNames(),
+                    nodeInfo.getUUID());
         } else {
             String msg = "unknown uuidBehavior: " + uuidBehavior;
             log.debug(msg);
             throw new RepositoryException(msg);
         }
-*/
+
         return node;
     }
 
@@ -175,15 +581,16 @@
         }
 
         boolean succeeded = false;
+        NodeState parent = null;
         try {
             // check sanity of workspace/session first
             wsp.sanityCheck();
 
-            NodeState parent = (NodeState) parents.peek();
+            parent = (NodeState) parents.peek();
 
             // process node
 
-            NodeState node;
+            NodeState node = null;
             String uuid = nodeInfo.getUUID();
             QName nodeName = nodeInfo.getName();
             QName ntName = nodeInfo.getNodeTypeName();
@@ -195,53 +602,166 @@
                 log.debug("skipping node " + nodeName);
                 return;
             }
-/*
             if (parent.hasChildNodeEntry(nodeName)) {
                 // a node with that name already exists...
-                ChildNodeDef nodeDef =
-                        wsp.findApplicableDefinition(nodeName, ntName, parent);
-                if (nodeDef.isProtected()) {
-                    // skip protected node
-                    parents.push(null); // push null onto stack for skipped node
-                    log.debug("skipping protected node " + nodeName);
-                    return;
-                }
-                if (nodeDef.isAutoCreate() && existing.isNodeType(ntName)) {
-                    // this node has already been auto-created, no need to create it
-                    node = existing;
-                } else {
-                    throw new ItemExistsException(existing.safeGetJCRPath());
+                NodeState.ChildNodeEntry entry =
+                        parent.getChildNodeEntry(nodeName, 1);
+                NodeId idExisting = new NodeId(entry.getUUID());
+                NodeState existing = (NodeState) stateMgr.getItemState(idExisting);
+                ChildNodeDef def = ntReg.getNodeDef(existing.getDefinitionId());
+
+                if (!def.allowSameNameSibs()) {
+                    // existing doesn't allow same-name siblings,
+                    // check for potential conflicts
+                    EffectiveNodeType entExisting =
+                            wsp.getEffectiveNodeType(existing);
+                    if (def.isProtected() && entExisting.includesNodeType(ntName)) {
+                        // skip protected node
+                        parents.push(null); // push null onto stack for skipped node
+                        log.debug("skipping protected node "
+                                + resolveJCRPath(existing.getId()));
+                        return;
+                    }
+                    if (def.isAutoCreate() && entExisting.includesNodeType(ntName)) {
+                        // this node has already been auto-created,
+                        // no need to create it
+                        node = existing;
+                    } else {
+                        throw new ItemExistsException(resolveJCRPath(existing.getId()));
+                    }
                 }
-            } else {
+            }
+
+            if (node == null) {
                 // there's no node with that name...
                 if (uuid == null) {
-                    // no potential uuid conflict, always add new node
+                    // no potential uuid conflict, always create new node:
+                    // check if new node can be added (check access rights &
+                    // node type constraints only, assume locking & versioning status
+                    // has already been checked on ancestor)
+                    wsp.checkAddNode(parent, nodeName, ntName,
+                            WorkspaceImpl.CHECK_ACCESS
+                            | WorkspaceImpl.CHECK_CONSTRAINTS);
+                    // do create new node
                     node = createNode(parent, nodeName, ntName, mixins, null);
                 } else {
                     // potential uuid conflict
                     NodeState conflicting;
+
                     try {
-                        conflicting = (NodeImpl) session.getNodeByUUID(uuid);
-                    } catch (ItemNotFoundException infe) {
+                        conflicting =
+                                (NodeState) stateMgr.getItemState(new NodeId(uuid));
+                    } catch (NoSuchItemStateException nsise) {
                         conflicting = null;
                     }
                     if (conflicting != null) {
                         // resolve uuid conflict
                         node = resolveUUIDConflict(parent, conflicting, nodeInfo);
                     } else {
-                        // create new with given uuid
+                        // create new with given uuid:
+                        // check if new node can be added (check access rights &
+                        // node type constraints only, assume locking & versioning status
+                        // has already been checked on ancestor)
+                        wsp.checkAddNode(parent, nodeName, ntName,
+                                WorkspaceImpl.CHECK_ACCESS
+                                | WorkspaceImpl.CHECK_CONSTRAINTS);
+                        // do create new node
                         node = createNode(parent, nodeName, ntName, mixins, uuid);
                     }
                 }
             }
-            // store state
-            stateMgr.store(state);
+
+            // process properties
+
+            Iterator iter = propInfos.iterator();
+            while (iter.hasNext()) {
+                PropInfo pi = (PropInfo) iter.next();
+                QName propName = pi.getName();
+                InternalValue[] vals = pi.getValues();
+                int type = pi.getType();
+
+                PropertyState prop = null;
+
+                if (node.hasPropertyEntry(propName)) {
+                    // a property with that name already exists...
+                    PropertyId idExisting = new PropertyId(node.getUUID(), propName);
+                    PropertyState existing =
+                            (PropertyState) stateMgr.getItemState(idExisting);
+                    PropDef propDef = ntReg.getPropDef(existing.getDefinitionId());
+                    if (propDef.isProtected()) {
+                        // skip protected property
+                        log.debug("skipping protected property "
+                                + resolveJCRPath(idExisting));
+                        continue;
+                    }
+                    if (propDef.isAutoCreate() && (existing.getType() == type
+                            || type == PropertyType.UNDEFINED)
+                            && propDef.isMultiple() == existing.isMultiValued()) {
+                        // this property has already been auto-created,
+                        // no need to create it
+                        prop = existing;
+                    } else {
+                        throw new ItemExistsException(resolveJCRPath(existing.getId()));
+                    }
+                }
+                if (prop == null) {
+                    // there's no property with that name,
+                    // create new property
+                    prop = createProperty(node, propName, type, vals.length);
+                }
+
+                PropDef propDef = ntReg.getPropDef(prop.getDefinitionId());
+
+                // check multi-valued characteristic
+                if ((vals.length == 0 || vals.length > 1) && !propDef.isMultiple()) {
+                    throw new ConstraintViolationException(resolveJCRPath(prop.getId())
+                            + " is not multi-valued");
+                }
+
+                // check whether type conversion is required
+                if (propDef.getRequiredType() != PropertyType.UNDEFINED
+                        && propDef.getRequiredType() != type) {
+                    // type doesn't match required type,
+                    // type conversion required
+                    for (int i = 0; i < vals.length; i++) {
+                        // convert InternalValue to Value of required type
+                        Value v =
+                                ValueHelper.convert(vals[i].toJCRValue(nsContext),
+                                        propDef.getRequiredType());
+                        // convert Value to InternalValue using
+                        // current namespace context of xml document
+                        vals[i] = InternalValue.create(v, nsContext);
+                    }
+                }
+
+                // set values
+                prop.setValues(vals);
+
+                // make sure node is valid according to its definition
+                wsp.validate(prop);
+
+                if (prop.getType() == PropertyType.REFERENCE) {
+                    // store reference for later resolution
+                    refTracker.processedReference(prop);
+                }
+
+                // store property
+                stateMgr.store(prop);
+            }
+
+            // store affected nodes
+            stateMgr.store(node);
+            stateMgr.store(parent);
+
+            // push current node onto stack of parents
+            parents.push(node);
+
             succeeded = true;
         } catch (ItemStateException ise) {
-            String msg = "internal error: failed to persist state of " + parentAbsPath;
+            String msg = "internal error: failed to store state of "
+                    + resolveJCRPath(parent.getId());
             log.debug(msg);
             throw new RepositoryException(msg, ise);
-*/
         } finally {
             if (!succeeded) {
                 // update operation failed, cancel all modifications
@@ -249,77 +769,6 @@
                 stateMgr.cancel();
             }
         }
-
-/*
-
-        // process node
-
-        NodeImpl node;
-        String uuid = nodeInfo.getUUID();
-        QName nodeName = nodeInfo.getName();
-        QName ntName = nodeInfo.getNodeTypeName();
-        QName[] mixins = nodeInfo.getMixinNames();
-        if (uuid == null) {
-            // no potential uuid conflict, always add new node
-            node = createNode(parent, nodeName, ntName, mixins, null);
-        } else {
-            // potential uuid conflict
-            NodeImpl conflicting;
-            try {
-                conflicting = (NodeImpl) session.getNodeByUUID(uuid);
-            } catch (ItemNotFoundException infe) {
-                conflicting = null;
-            }
-            if (conflicting != null) {
-                // resolve uuid conflict
-                node = resolveUUIDConflict(parent, conflicting, nodeInfo);
-            } else {
-                // create new with given uuid
-                node = createNode(parent, nodeName, ntName, mixins, uuid);
-            }
-        }
-
-        // process properties
-
-        Iterator iter = propInfos.iterator();
-        while (iter.hasNext()) {
-            PropInfo pi = (PropInfo) iter.next();
-            QName propName = pi.getName();
-            Value[] vals = pi.getValues();
-            int type = pi.getType();
-            if (node.hasProperty(propName)) {
-                PropertyDef def = node.getProperty(propName).getDefinition();
-                if (def.isProtected()) {
-                    // skip protected property
-                    log.debug("skipping protected property " + propName);
-                    continue;
-                }
-            }
-            // multi- or single-valued property?
-            if (vals.length == 1) {
-                // could be single- or multi-valued (n == 1)
-                try {
-                    // try setting single-value
-                    node.setProperty(propName, vals[0]);
-                } catch (ValueFormatException vfe) {
-                    // try setting value array
-                    node.setProperty(propName, vals, type);
-                } catch (ConstraintViolationException vfe) {
-                    // try setting value array
-                    node.setProperty(propName, vals, type);
-                }
-            } else {
-                // can only be multi-valued (n == 0 || n > 1)
-                node.setProperty(propName, vals, type);
-            }
-            if (type == PropertyType.REFERENCE) {
-                // store reference for later resolution
-                references.add(node.getProperty(propName));
-            }
-        }
-
-        parents.push(node);
-*/
     }
 
     /**
@@ -340,6 +789,9 @@
             // check sanity of workspace/session first
             wsp.sanityCheck();
 
+            // make sure node is valid according to its definition
+            wsp.validate(node);
+
             // we're done with that node, now store its state
             stateMgr.store(node);
             succeeded = true;
@@ -370,39 +822,38 @@
              * adjust references that refer to uuid's which have been mapped to
              * newly gererated uuid's on import
              */
-/*
-            Iterator iter = references.iterator();
+            Iterator iter = refTracker.getProcessedReferences();
             while (iter.hasNext()) {
                 PropertyState prop = (PropertyState) iter.next();
                 // being paranoid...
                 if (prop.getType() != PropertyType.REFERENCE) {
                     continue;
                 }
-                if (prop.getDefinition().isMultiple()) {
-                    Value[] values = prop.getValues();
-                    Value[] newVals = new Value[values.length];
-                    for (int i = 0; i < values.length; i++) {
-                        Value val = values[i];
-                        String original = val.getString();
-                        String adjusted = (String) uuidMap.get(original);
-                        if (adjusted != null) {
-                            newVals[i] = new ReferenceValue(wsp.getSession().getNodeByUUID(adjusted));
-                        } else {
-                            // reference doesn't need adjusting, just copy old value
-                            newVals[i] = val;
-                        }
-                    }
-                    prop.setValue(newVals);
-                } else {
-                    Value val = prop.getValue();
-                    String original = val.getString();
-                    String adjusted = (String) uuidMap.get(original);
+                boolean modified = false;
+                InternalValue[] values = prop.getValues();
+                InternalValue[] newVals = new InternalValue[values.length];
+                for (int i = 0; i < values.length; i++) {
+                    InternalValue val = values[i];
+                    String original = ((UUID) val.internalValue()).toString();
+                    String adjusted = refTracker.getMappedUUID(original);
                     if (adjusted != null) {
-                        prop.setValue(session.getNodeByUUID(adjusted));
+                        newVals[i] = InternalValue.create(UUID.fromString(adjusted));
+                        modified = true;
+                    } else {
+                        // reference doesn't need adjusting, just copy old value
+                        newVals[i] = val;
                     }
                 }
+                if (modified) {
+                    prop.setValues(newVals);
+                    stateMgr.store(prop);
+                }
             }
-*/
+            refTracker.clear();
+
+            // make sure import target is valid according to its definition
+            wsp.validate(importTarget);
+
             // finally store the state of the import target
             // (the parent of the imported subtree)
             stateMgr.store(importTarget);



Mime
View raw message