You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by an...@apache.org on 2007/01/17 17:36:20 UTC

svn commit: r497068 - in /jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi: ./ name/ nodetype/ state/ xml/

Author: angela
Date: Wed Jan 17 08:36:19 2007
New Revision: 497068

URL: http://svn.apache.org/viewvc?view=rev&rev=497068
Log:
work in progress

- minor improvement and some sync


Removed:
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/name/CachingNamespaceResolver.java
Modified:
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/name/LocalNamespaceMappings.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/name/NamespaceRegistryImpl.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/EffectiveNodeType.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/EffectiveNodeTypeImpl.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/NodeTypeImpl.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/NodeTypeManagerImpl.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/NodeTypeRegistryImpl.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateValidator.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateFactory.java
    jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/DocViewImportHandler.java

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java?view=diff&rev=497068&r1=497067&r2=497068
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java Wed Jan 17 08:36:19 2007
@@ -22,8 +22,6 @@
 import org.apache.jackrabbit.value.ValueFormat;
 import org.apache.jackrabbit.value.QValue;
 import org.apache.jackrabbit.name.MalformedPathException;
-import org.apache.jackrabbit.name.IllegalNameException;
-import org.apache.jackrabbit.name.UnknownPrefixException;
 import org.apache.jackrabbit.name.NoPrefixDeclaredException;
 import org.apache.jackrabbit.name.NameException;
 import org.apache.jackrabbit.name.QName;
@@ -281,10 +279,11 @@
      */
     public Property setProperty(String name, Value value, int type) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
         checkIsWritable();
+        QName propQName = getQName(name);
         Property prop;
-        if (hasProperty(name)) {
+        if (hasProperty(propQName)) {
             // property already exists: pass call to property
-            prop = getProperty(name);
+            prop = getProperty(propQName);
             Value v = (type == PropertyType.UNDEFINED) ? value : ValueHelper.convert(value, type, session.getValueFactory());
             prop.setValue(v);
         } else {
@@ -294,7 +293,7 @@
                 prop = null;
             } else {
                 // new property to be added
-                prop = createProperty(getQName(name), value, type);
+                prop = createProperty(propQName, value, type);
             }
         }
         return prop;
@@ -319,10 +318,11 @@
      */
     public Property setProperty(String name, Value[] values, int type) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
         checkIsWritable();
+        QName propName = getQName(name);
         Property prop;
-        if (hasProperty(name)) {
+        if (hasProperty(propName)) {
             // property already exists: pass call to property
-            prop = getProperty(name);
+            prop = getProperty(propName);
             Value[] vs = (type == PropertyType.UNDEFINED) ? values : ValueHelper.convert(values, type, session.getValueFactory());
             prop.setValue(vs);
         } else {
@@ -332,7 +332,7 @@
                 prop = null;
             } else {
                 // new property to be added
-                prop = createProperty(getQName(name), values, type);
+                prop = createProperty(propName, values, type);
             }
         }
         return prop;
@@ -652,6 +652,15 @@
      */
     public boolean isNodeType(String nodeTypeName) throws RepositoryException {
         checkStatus();        
+        // try shortcut first (avoids parsing of name)
+        try {
+            if (NameFormat.format(primaryTypeName, session.getNamespaceResolver()).equals(nodeTypeName)) {
+                return true;
+            }
+        } catch (NoPrefixDeclaredException npde) {
+            throw new RepositoryException("Invalid node type name: " + nodeTypeName, npde);
+        }
+        // parse to QName and check against effective nodetype
         return isNodeType(getQName(nodeTypeName));
     }
 
@@ -1319,7 +1328,7 @@
         try {
             List cne = getNodeState().getChildNodeEntries(nodeName);
             if (definition.allowsSameNameSiblings()) {
-                // TODO: find proper solution. problem with SNSs
+                // TODO TOBEFIXED find proper solution. problem with SNSs
                 childState = ((ChildNodeEntry)cne.get(cne.size()-1)).getNodeState();
             } else {
                 childState = ((ChildNodeEntry)cne.get(0)).getNodeState();
@@ -1452,9 +1461,7 @@
         QName qName;
         try {
             qName = NameFormat.parse(jcrName, session.getNamespaceResolver());
-        } catch (IllegalNameException ine) {
-            throw new RepositoryException("invalid name: " + jcrName, ine);
-        } catch (UnknownPrefixException upe) {
+        } catch (NameException upe) {
             throw new RepositoryException("invalid name: "+ jcrName, upe);
         }
         return qName;

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java?view=diff&rev=497068&r1=497067&r2=497068
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java Wed Jan 17 08:36:19 2007
@@ -56,9 +56,6 @@
 import org.xml.sax.ContentHandler;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
-import org.xml.sax.ErrorHandler;
-import org.xml.sax.helpers.XMLReaderFactory;
 
 import javax.jcr.AccessDeniedException;
 import javax.jcr.Credentials;
@@ -87,6 +84,9 @@
 import javax.xml.transform.stream.StreamResult;
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.TransformerException;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.ParserConfigurationException;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -440,17 +440,15 @@
      */
     public void importXML(String parentAbsPath, InputStream in, int uuidBehavior) throws IOException, PathNotFoundException, ItemExistsException, ConstraintViolationException, VersionException, InvalidSerializedDataException, LockException, RepositoryException {
         // NOTE: checks are performed by 'getImportContentHandler'
-        ContentHandler handler = getImportContentHandler(parentAbsPath, uuidBehavior);
+        ImportHandler handler = (ImportHandler) getImportContentHandler(parentAbsPath, uuidBehavior);
         try {
-            XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
-            parser.setContentHandler(handler);
-            if (handler instanceof ErrorHandler) {
-                parser.setErrorHandler((ErrorHandler)handler);
-            }
-            // being paranoid...
-            parser.setFeature("http://xml.org/sax/features/namespaces", true);
-            parser.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
-            parser.parse(new InputSource(in));
+            SAXParserFactory factory = SAXParserFactory.newInstance();
+            factory.setNamespaceAware(true);
+            factory.setFeature(
+                    "http://xml.org/sax/features/namespace-prefixes", false);
+
+            SAXParser parser = factory.newSAXParser();
+            parser.parse(new InputSource(in), handler);
         } catch (SAXException se) {
             // check for wrapped repository exception
             Exception e = se.getException();
@@ -461,6 +459,8 @@
                 log.debug(msg);
                 throw new InvalidSerializedDataException(msg, se);
             }
+        } catch (ParserConfigurationException e) {
+            throw new RepositoryException("SAX parser configuration error", e);
         }
     }
 

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/name/LocalNamespaceMappings.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/name/LocalNamespaceMappings.java?view=diff&rev=497068&r1=497067&r2=497068
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/name/LocalNamespaceMappings.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/name/LocalNamespaceMappings.java Wed Jan 17 08:36:19 2007
@@ -20,6 +20,7 @@
 import org.apache.jackrabbit.name.AbstractNamespaceResolver;
 import org.apache.jackrabbit.name.NamespaceListener;
 import org.apache.jackrabbit.name.QName;
+import org.apache.jackrabbit.name.NameCache;
 import org.apache.jackrabbit.jcr2spi.SessionImpl;
 import org.apache.jackrabbit.util.XMLChar;
 
@@ -46,7 +47,7 @@
  * underlying namespace registry.
  */
 public class LocalNamespaceMappings extends AbstractNamespaceResolver
-    implements NamespaceListener {
+    implements NamespaceListener, NameCache {
 
     /** The underlying global and persistent namespace registry. */
     private final NamespaceRegistryImpl nsReg;
@@ -166,6 +167,46 @@
         return new HashMap(prefixToURI);
     }
 
+    //-------------------------------------------------------------< NameCache >
+
+    /**
+     * {@inheritDoc}
+     */
+    public QName retrieveName(String jcrName) {
+        if (prefixToURI.size() == 0) {
+            return nsReg.retrieveName(jcrName);
+        }
+        return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String retrieveName(QName name) {
+        if (prefixToURI.size() == 0
+                || !uriToPrefix.containsKey(name.getNamespaceURI())) {
+            return nsReg.retrieveName(name);
+        }
+        return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void cacheName(String jcrName, QName name) {
+        if (prefixToURI.size() == 0
+                || !uriToPrefix.containsKey(name.getNamespaceURI())) {
+            nsReg.cacheName(jcrName, name);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void evictAllNames() {
+        nsReg.evictAllNames();
+    }
+
     //--------------------------------------------------< NamespaceResolver >---
     /**
      * {@inheritDoc}
@@ -264,6 +305,9 @@
 
     /**
      * @inheritDoc
+     * This method gets called when an existing namespace is removed
+     * in the global NamespaceRegistry. Overridden in order to check
+     * for/resolve collision of new global prefix with existing local prefix.
      */
     public void namespaceRemoved(String uri) {
         if (uriToPrefix.containsKey(uri)) {

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/name/NamespaceRegistryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/name/NamespaceRegistryImpl.java?view=diff&rev=497068&r1=497067&r2=497068
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/name/NamespaceRegistryImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/name/NamespaceRegistryImpl.java Wed Jan 17 08:36:19 2007
@@ -23,6 +23,10 @@
 import org.apache.jackrabbit.name.QName;
 import org.apache.jackrabbit.name.NameCache;
 import org.apache.jackrabbit.name.NameFormat;
+import org.apache.jackrabbit.name.CachingNameResolver;
+import org.apache.jackrabbit.name.ParsingNameResolver;
+import org.apache.jackrabbit.name.NameResolver;
+import org.apache.jackrabbit.name.NameException;
 import org.apache.jackrabbit.util.XMLChar;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -71,7 +75,7 @@
     private final HashMap prefixToURI = new HashMap();
     private final HashMap uriToPrefix = new HashMap();
 
-    private final CachingNamespaceResolver resolver;
+    private final NameResolver resolver;
     private final NamespaceStorage storage;
 
     private final boolean level2Repository;
@@ -87,7 +91,7 @@
         throws RepositoryException {
         super(true); // enable listener support
 
-        resolver = new CachingNamespaceResolver(this, 1000);
+        resolver = new CachingNameResolver(new ParsingNameResolver(this));
         this.storage = storage;
         this.level2Repository = level2Repository;
 
@@ -330,31 +334,35 @@
      * {@inheritDoc}
      */
     public QName retrieveName(String jcrName) {
-        // just delegate to internal cache
-        return resolver.retrieveName(jcrName);
+        try {
+            return resolver.getQName(jcrName);
+        } catch (NameException e) {
+            return null;
+        } catch (NamespaceException e) {
+            return null;
+        }
     }
 
     /**
      * {@inheritDoc}
      */
     public String retrieveName(QName name) {
-        // just delegate to internal cache
-        return resolver.retrieveName(name);
+        try {
+            return resolver.getJCRName(name);
+        } catch (NamespaceException e) {
+            return null;
+        }
     }
 
     /**
      * {@inheritDoc}
      */
     public void cacheName(String jcrName, QName name) {
-        // just delegate to internal cache
-        resolver.cacheName(jcrName, name);
     }
 
     /**
      * {@inheritDoc}
      */
     public void evictAllNames() {
-        // just delegate to internal cache
-        resolver.evictAllNames();
     }
 }

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/EffectiveNodeType.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/EffectiveNodeType.java?view=diff&rev=497068&r1=497067&r2=497068
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/EffectiveNodeType.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/EffectiveNodeType.java Wed Jan 17 08:36:19 2007
@@ -43,7 +43,17 @@
      *         <code>false</code>
      */
     public boolean includesNodeType(QName nodeTypeName);
-    
+
+    /**
+     * Determines whether this effective node type representation includes
+     * (either through inheritance or aggregation) all of the given node types.
+     *
+     * @param nodeTypeNames array of node type names
+     * @return <code>true</code> if all of the given node types are included,
+     *         otherwise <code>false</code>
+     */
+    public boolean includesNodeTypes(QName[] nodeTypeNames);
+
     public QNodeDefinition[] getAllNodeDefs();
 
     public QPropertyDefinition[] getAllPropDefs();
@@ -67,7 +77,8 @@
      * @throws ConstraintViolationException if no applicable child node definition
      * could be found
      */
-    public QNodeDefinition getApplicableNodeDefinition(QName name, QName nodeTypeName)
+    public QNodeDefinition getApplicableNodeDefinition(QName name, QName nodeTypeName,
+                                                       NodeTypeRegistry ntReg)
             throws NoSuchNodeTypeException, ConstraintViolationException;
 
     /**
@@ -88,7 +99,7 @@
      *                                      could be found
      */
     public QPropertyDefinition getApplicablePropertyDefinition(QName name, int type,
-                                            boolean multiValued)
+                                                               boolean multiValued)
             throws ConstraintViolationException;
 
     /**
@@ -117,18 +128,20 @@
 
     /**
      * @param name
+     * @param ntReg
      * @throws ConstraintViolationException
      */
-    public void checkAddNodeConstraints(QName name)
+    public void checkAddNodeConstraints(QName name, NodeTypeRegistry ntReg)
             throws ConstraintViolationException;
 
     /**
      * @param name
      * @param nodeTypeName
+     * @param ntReg
      * @throws ConstraintViolationException
      * @throws NoSuchNodeTypeException
      */
-    public void checkAddNodeConstraints(QName name, QName nodeTypeName)
+    public void checkAddNodeConstraints(QName name, QName nodeTypeName, NodeTypeRegistry ntReg)
             throws ConstraintViolationException, NoSuchNodeTypeException;
 
     /**

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/EffectiveNodeTypeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/EffectiveNodeTypeImpl.java?view=diff&rev=497068&r1=497067&r2=497068
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/EffectiveNodeTypeImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/EffectiveNodeTypeImpl.java Wed Jan 17 08:36:19 2007
@@ -47,9 +47,6 @@
 public class EffectiveNodeTypeImpl implements Cloneable, EffectiveNodeType {
     private static Logger log = LoggerFactory.getLogger(EffectiveNodeTypeImpl.class);
 
-    // node type registry
-    private final NodeTypeRegistry ntReg;
-
     // list of explicitly aggregated {i.e. merged) node types
     private final TreeSet mergedNodeTypes;
     // list of implicitly aggregated {through inheritance) node types
@@ -65,8 +62,7 @@
     /**
      * private constructor.
      */
-    private EffectiveNodeTypeImpl(NodeTypeRegistry ntReg) {
-        this.ntReg = ntReg;
+    private EffectiveNodeTypeImpl() {
         mergedNodeTypes = new TreeSet();
         inheritedNodeTypes = new TreeSet();
         allNodeTypes = new TreeSet();
@@ -82,7 +78,7 @@
      *
      * @param ntReg
      * @param ntd
-     * @param ntdMap
+     * @param ntdMap 
      * @return
      * @throws NodeTypeConflictException
      * @throws NoSuchNodeTypeException
@@ -90,7 +86,7 @@
     static EffectiveNodeTypeImpl create(NodeTypeRegistry ntReg, QNodeTypeDefinition ntd, Map ntdMap)
             throws NodeTypeConflictException, NoSuchNodeTypeException {
         // create empty effective node type instance
-        EffectiveNodeTypeImpl ent = new EffectiveNodeTypeImpl(ntReg);
+        EffectiveNodeTypeImpl ent = new EffectiveNodeTypeImpl();
         QName ntName = ntd.getQName();
 
         // prepare new instance
@@ -213,10 +209,10 @@
     /**
      * Factory method: creates a new 'empty' effective node type instance
      *
-     * @return
+     * @return a new EffectiveNodeType
      */
-    static EffectiveNodeType create(NodeTypeRegistryImpl ntReg) {
-        return new EffectiveNodeTypeImpl(ntReg);
+    static EffectiveNodeType create() {
+        return new EffectiveNodeTypeImpl();
     }
 
     //--------------------------------------------------< EffectiveNodeType >---
@@ -423,10 +419,17 @@
     /**
      * @inheritDoc
      */
-    public void checkAddNodeConstraints(QName name)
+    public boolean includesNodeTypes(QName[] nodeTypeNames) {
+        return allNodeTypes.containsAll(Arrays.asList(nodeTypeNames));
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public void checkAddNodeConstraints(QName name, NodeTypeRegistry ntReg)
             throws ConstraintViolationException {
         try {
-            getApplicableNodeDefinition(name, null);
+            getApplicableNodeDefinition(name, null, ntReg);
         } catch (NoSuchNodeTypeException nsnte) {
             String msg = "internal eror: inconsistent node type";
             log.debug(msg);
@@ -437,9 +440,9 @@
     /**
      * @inheritDoc
      */
-    public void checkAddNodeConstraints(QName name, QName nodeTypeName)
+    public void checkAddNodeConstraints(QName name, QName nodeTypeName, NodeTypeRegistry ntReg)
             throws ConstraintViolationException, NoSuchNodeTypeException {
-        QNodeDefinition nd = getApplicableNodeDefinition(name, nodeTypeName);
+        QNodeDefinition nd = getApplicableNodeDefinition(name, nodeTypeName, ntReg);
         if (nd.isProtected()) {
             throw new ConstraintViolationException(name + " is protected");
         }
@@ -472,26 +475,30 @@
     /**
      * @inheritDoc
      */
-    public QNodeDefinition getApplicableNodeDefinition(QName name, QName nodeTypeName)
+    public QNodeDefinition getApplicableNodeDefinition(QName name, QName nodeTypeName,
+                                                       NodeTypeRegistry ntReg)
             throws NoSuchNodeTypeException, ConstraintViolationException {
+        EffectiveNodeType entTarget;
+        if (nodeTypeName != null) {
+            entTarget = ntReg.getEffectiveNodeType(nodeTypeName);
+        } else {
+            entTarget = null;
+        }
+
         // try named node definitions first
         QItemDefinition[] defs = getNamedItemDefs(name);
         if (defs != null) {
             for (int i = 0; i < defs.length; i++) {
-                QItemDefinition qDef = defs[i];
-                if (qDef.definesNode()) {
-                    QNodeDefinition nd = (QNodeDefinition) qDef;
+                QItemDefinition def = defs[i];
+                if (def.definesNode()) {
+                    QNodeDefinition nd = (QNodeDefinition) def;
                     // node definition with that name exists
-                    if (nodeTypeName != null) {
-                        try {
-                            // check node type constraints
-                            checkRequiredPrimaryType(nodeTypeName, nd.getRequiredPrimaryTypes());
-                        } catch (ConstraintViolationException cve) {
-                            // ignore and try next
-                            continue;
+                    if (entTarget != null && nd.getRequiredPrimaryTypes() != null) {
+                        // check 'required primary types' constraint
+                        if (entTarget.includesNodeTypes(nd.getRequiredPrimaryTypes())) {
+                            // found named node definition
+                            return nd;
                         }
-                        // found node definition
-                        return nd;
                     } else {
                         if (nd.getDefaultPrimaryType() != null) {
                             // found node definition with default node type
@@ -507,16 +514,12 @@
         QNodeDefinition[] nda = getUnnamedNodeDefs();
         for (int i = 0; i < nda.length; i++) {
             QNodeDefinition nd = nda[i];
-            if (nodeTypeName != null) {
-                try {
-                    // check node type constraint
-                    checkRequiredPrimaryType(nodeTypeName, nd.getRequiredPrimaryTypes());
-                } catch (ConstraintViolationException e) {
-                    // ignore and try next
-                    continue;
+            if (entTarget != null && nd.getRequiredPrimaryTypes() != null) {
+                // check 'required primary types' constraint
+                if (entTarget.includesNodeTypes(nd.getRequiredPrimaryTypes())) {
+                    // found residual node definition
+                    return nd;
                 }
-                // found residual node definition
-                return nd;
             } else {
                 // since no node type has been specified for the new node,
                 // it must be determined from the default node type;
@@ -535,8 +538,8 @@
      * @inheritDoc
      */
     public QPropertyDefinition getApplicablePropertyDefinition(QName name, int type,
-                                            boolean multiValued)
-            throws ConstraintViolationException {
+                                                               boolean multiValued)
+        throws ConstraintViolationException {
         // try named property definitions first
         QPropertyDefinition match =
                 getMatchingPropDef(getNamedPropDefs(name), type, multiValued);
@@ -578,21 +581,6 @@
     }
 
     //---------------------------------------------< impl. specific methods >---
-    private QItemDefinition[] getAllItemDefs() {
-        if (namedItemDefs.size() == 0 && unnamedItemDefs.size() == 0) {
-            return QItemDefinition.EMPTY_ARRAY;
-        }
-        ArrayList defs = new ArrayList(namedItemDefs.size() + unnamedItemDefs.size());
-        Iterator iter = namedItemDefs.values().iterator();
-        while (iter.hasNext()) {
-            defs.addAll((List) iter.next());
-        }
-        defs.addAll(unnamedItemDefs);
-        if (defs.size() == 0) {
-            return QItemDefinition.EMPTY_ARRAY;
-        }
-        return (QItemDefinition[]) defs.toArray(new QItemDefinition[defs.size()]);
-    }
 
     private QItemDefinition[] getNamedItemDefs() {
         if (namedItemDefs.size() == 0) {
@@ -616,10 +604,6 @@
         return (QItemDefinition[]) unnamedItemDefs.toArray(new QItemDefinition[unnamedItemDefs.size()]);
     }
 
-    private boolean hasNamedItemDef(QName name) {
-        return namedItemDefs.containsKey(name);
-    }
-
     private QItemDefinition[] getNamedItemDefs(QName name) {
         List defs = (List) namedItemDefs.get(name);
         if (defs == null || defs.size() == 0) {
@@ -628,47 +612,6 @@
         return (QItemDefinition[]) defs.toArray(new QItemDefinition[defs.size()]);
     }
 
-    private QNodeDefinition[] getNamedNodeDefs() {
-        if (namedItemDefs.size() == 0) {
-            return QNodeDefinition.EMPTY_ARRAY;
-        }
-        ArrayList defs = new ArrayList(namedItemDefs.size());
-        Iterator iter = namedItemDefs.values().iterator();
-        while (iter.hasNext()) {
-            List list = (List) iter.next();
-            Iterator iter1 = list.iterator();
-            while (iter1.hasNext()) {
-                QItemDefinition qDef = (QItemDefinition) iter1.next();
-                if (qDef.definesNode()) {
-                    defs.add(qDef);
-                }
-            }
-        }
-        if (defs.size() == 0) {
-            return QNodeDefinition.EMPTY_ARRAY;
-        }
-        return (QNodeDefinition[]) defs.toArray(new QNodeDefinition[defs.size()]);
-    }
-
-    private QNodeDefinition[] getNamedNodeDefs(QName name) {
-        List list = (List) namedItemDefs.get(name);
-        if (list == null || list.size() == 0) {
-            return QNodeDefinition.EMPTY_ARRAY;
-        }
-        ArrayList defs = new ArrayList(list.size());
-        Iterator iter = list.iterator();
-        while (iter.hasNext()) {
-            QItemDefinition qDef = (QItemDefinition) iter.next();
-            if (qDef.definesNode()) {
-                defs.add(qDef);
-            }
-        }
-        if (defs.size() == 0) {
-            return QNodeDefinition.EMPTY_ARRAY;
-        }
-        return (QNodeDefinition[]) defs.toArray(new QNodeDefinition[defs.size()]);
-    }
-
     private QNodeDefinition[] getUnnamedNodeDefs() {
         if (unnamedItemDefs.size() == 0) {
             return QNodeDefinition.EMPTY_ARRAY;
@@ -687,28 +630,6 @@
         return (QNodeDefinition[]) defs.toArray(new QNodeDefinition[defs.size()]);
     }
 
-    private QPropertyDefinition[] getNamedPropDefs() {
-        if (namedItemDefs.size() == 0) {
-            return QPropertyDefinition.EMPTY_ARRAY;
-        }
-        ArrayList defs = new ArrayList(namedItemDefs.size());
-        Iterator iter = namedItemDefs.values().iterator();
-        while (iter.hasNext()) {
-            List list = (List) iter.next();
-            Iterator iter1 = list.iterator();
-            while (iter1.hasNext()) {
-                QItemDefinition qDef = (QItemDefinition) iter1.next();
-                if (!qDef.definesNode()) {
-                    defs.add(qDef);
-                }
-            }
-        }
-        if (defs.size() == 0) {
-            return QPropertyDefinition.EMPTY_ARRAY;
-        }
-        return (QPropertyDefinition[]) defs.toArray(new QPropertyDefinition[defs.size()]);
-    }
-
     private QPropertyDefinition[] getNamedPropDefs(QName name) {
         List list = (List) namedItemDefs.get(name);
         if (list == null || list.size() == 0) {
@@ -816,26 +737,6 @@
     }
 
     /**
-     * @param nodeTypeName
-     * @param requiredPrimaryTypes
-     * @throws ConstraintViolationException
-     * @throws NoSuchNodeTypeException
-     */
-    private void checkRequiredPrimaryType(QName nodeTypeName, QName[] requiredPrimaryTypes)
-            throws ConstraintViolationException, NoSuchNodeTypeException {
-        if (requiredPrimaryTypes == null) {
-            // no constraint
-            return;
-        }
-        EffectiveNodeType ent = ntReg.getEffectiveNodeType(nodeTypeName);
-        for (int i = 0; i < requiredPrimaryTypes.length; i++) {
-            if (!ent.includesNodeType(requiredPrimaryTypes[i])) {
-                throw new ConstraintViolationException("node type constraint not satisfied: " + requiredPrimaryTypes[i]);
-            }
-        }
-    }
-
-    /**
      * Merges another <code>EffectiveNodeType</code> with this one.
      * Checks for merge conflicts.
      *
@@ -1037,7 +938,7 @@
     }
 
     protected Object clone() {
-        EffectiveNodeTypeImpl clone = new EffectiveNodeTypeImpl(ntReg);
+        EffectiveNodeTypeImpl clone = new EffectiveNodeTypeImpl();
 
         clone.mergedNodeTypes.addAll(mergedNodeTypes);
         clone.inheritedNodeTypes.addAll(inheritedNodeTypes);

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/NodeTypeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/NodeTypeImpl.java?view=diff&rev=497068&r1=497067&r2=497068
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/NodeTypeImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/NodeTypeImpl.java Wed Jan 17 08:36:19 2007
@@ -42,7 +42,6 @@
 import javax.jcr.nodetype.NodeType;
 import javax.jcr.nodetype.PropertyDefinition;
 import java.util.ArrayList;
-import java.util.HashSet;
 
 /**
  * A <code>NodeTypeImpl</code> ...
@@ -90,35 +89,6 @@
     }
 
     /**
-     * Returns the applicable child node definition for a child node with the
-     * specified name.
-     *
-     * @param nodeName
-     * @return
-     * @throws RepositoryException if no applicable child node definition
-     *                             could be found
-     */
-    private QNodeDefinition getApplicableNodeDef(QName nodeName)
-            throws RepositoryException {
-        return getApplicableNodeDef(nodeName, null);
-    }
-
-    /**
-     * Returns the applicable child node definition for a child node with the
-     * specified name and node type.
-     *
-     * @param nodeName
-     * @param nodeTypeName
-     * @return
-     * @throws RepositoryException if no applicable child node definition
-     *                             could be found
-     */
-    private QNodeDefinition getApplicableNodeDef(QName nodeName, QName nodeTypeName)
-            throws RepositoryException {
-        return ent.getApplicableNodeDefinition(nodeName, nodeTypeName);
-    }
-
-    /**
      * Returns the applicable property definition for a property with the
      * specified name and type.
      *
@@ -147,78 +117,6 @@
     }
 
     /**
-     * Returns an array containing only those child node definitions of this
-     * node type (including the child node definitions inherited from supertypes
-     * of this node type) where <code>{@link NodeDefinition#isAutoCreated()}</code>
-     * returns <code>true</code>.
-     *
-     * @return an array of child node definitions.
-     * @see NodeDefinition#isAutoCreated
-     */
-    private NodeDefinition[] getAutoCreatedNodeDefinitions() {
-        QNodeDefinition[] cnda = ent.getAutoCreateNodeDefs();
-        NodeDefinition[] nodeDefs = new NodeDefinition[cnda.length];
-        for (int i = 0; i < cnda.length; i++) {
-            nodeDefs[i] = ntMgr.getNodeDefinition(cnda[i]);
-        }
-        return nodeDefs;
-    }
-
-    /**
-     * Returns an array containing only those property definitions of this
-     * node type (including the property definitions inherited from supertypes
-     * of this node type) where <code>{@link PropertyDefinition#isAutoCreated()}</code>
-     * returns <code>true</code>.
-     *
-     * @return an array of property definitions.
-     * @see PropertyDefinition#isAutoCreated
-     */
-    private PropertyDefinition[] getAutoCreatedPropertyDefinitions() {
-        QPropertyDefinition[] pda = ent.getAutoCreatePropDefs();
-        PropertyDefinition[] propDefs = new PropertyDefinition[pda.length];
-        for (int i = 0; i < pda.length; i++) {
-            propDefs[i] = ntMgr.getPropertyDefinition(pda[i]);
-        }
-        return propDefs;
-    }
-
-    /**
-     * Returns an array containing only those property definitions of this
-     * node type (including the property definitions inherited from supertypes
-     * of this node type) where <code>{@link PropertyDefinition#isMandatory()}</code>
-     * returns <code>true</code>.
-     *
-     * @return an array of property definitions.
-     * @see PropertyDefinition#isMandatory
-     */
-    private PropertyDefinition[] getMandatoryPropertyDefinitions() {
-        QPropertyDefinition[] pda = ent.getMandatoryPropDefs();
-        PropertyDefinition[] propDefs = new PropertyDefinition[pda.length];
-        for (int i = 0; i < pda.length; i++) {
-            propDefs[i] = ntMgr.getPropertyDefinition(pda[i]);
-        }
-        return propDefs;
-    }
-
-    /**
-     * Returns an array containing only those child node definitions of this
-     * node type (including the child node definitions inherited from supertypes
-     * of this node type) where <code>{@link NodeDefinition#isMandatory()}</code>
-     * returns <code>true</code>.
-     *
-     * @return an array of child node definitions.
-     * @see NodeDefinition#isMandatory
-     */
-    private NodeDefinition[] getMandatoryNodeDefinitions() {
-        QNodeDefinition[] cnda = ent.getMandatoryNodeDefs();
-        NodeDefinition[] nodeDefs = new NodeDefinition[cnda.length];
-        for (int i = 0; i < cnda.length; i++) {
-            nodeDefs[i] = ntMgr.getNodeDefinition(cnda[i]);
-        }
-        return nodeDefs;
-    }
-
-    /**
      * Tests if the value constraints defined in the property definition
      * <code>def</code> are satisfied by the the specified <code>values</code>.
      * <p/>
@@ -246,41 +144,7 @@
         return ntd.getQName();
     }
 
-    /**
-     * Returns all <i>inherited</i> supertypes of this node type.
-     *
-     * @return an array of <code>NodeType</code> objects.
-     * @see #getSupertypes
-     * @see #getDeclaredSupertypes
-     */
-    private NodeType[] getInheritedSupertypes() {
-        // declared supertypes
-        QName[] ntNames = ntd.getSupertypes();
-        HashSet declared = new HashSet();
-        for (int i = 0; i < ntNames.length; i++) {
-            declared.add(ntNames[i]);
-        }
-        // all supertypes
-        ntNames = ent.getInheritedNodeTypes();
-
-        // filter from all supertypes those that are not declared
-        ArrayList inherited = new ArrayList();
-        for (int i = 0; i < ntNames.length; i++) {
-            if (!declared.contains(ntNames[i])) {
-                try {
-                    inherited.add(ntMgr.getNodeType(ntNames[i]));
-                } catch (NoSuchNodeTypeException e) {
-                    // should never get here
-                    log.error("undefined supertype", e);
-                    return new NodeType[0];
-                }
-            }
-        }
-
-        return (NodeType[]) inherited.toArray(new NodeType[inherited.size()]);
-    }
-
-    //-------------------------------------------------------------< NodeType >
+    //-----------------------------------------------------------< NodeType >---
     /**
      * {@inheritDoc}
      */
@@ -539,7 +403,8 @@
      */
     public boolean canAddChildNode(String childNodeName) {
         try {
-            ent.checkAddNodeConstraints(NameFormat.parse(childNodeName, nsResolver));
+            ent.checkAddNodeConstraints(NameFormat.parse(childNodeName, nsResolver),
+                ntMgr.getNodeTypeRegistry());
             return true;
         } catch (NameException be) {
             // implementation specific exception, fall through
@@ -554,7 +419,8 @@
      */
     public boolean canAddChildNode(String childNodeName, String nodeTypeName) {
         try {
-            ent.checkAddNodeConstraints(NameFormat.parse(childNodeName, nsResolver), NameFormat.parse(nodeTypeName, nsResolver));
+            ent.checkAddNodeConstraints(NameFormat.parse(childNodeName, nsResolver),
+                NameFormat.parse(nodeTypeName, nsResolver), ntMgr.getNodeTypeRegistry());
             return true;
         } catch (NameException be) {
             // implementation specific exception, fall through

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/NodeTypeManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/NodeTypeManagerImpl.java?view=diff&rev=497068&r1=497067&r2=497068
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/NodeTypeManagerImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/NodeTypeManagerImpl.java Wed Jan 17 08:36:19 2007
@@ -183,7 +183,13 @@
             return pdi;
         }
     }
-    
+
+    /**
+     * @return the NodeTypeRegistry
+     */
+    NodeTypeRegistry getNodeTypeRegistry() {
+        return ntReg;
+    }
     //-------------------------------------------< NodeTypeRegistryListener >---
     /**
      * {@inheritDoc}

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/NodeTypeRegistryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/NodeTypeRegistryImpl.java?view=diff&rev=497068&r1=497067&r2=497068
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/NodeTypeRegistryImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/NodeTypeRegistryImpl.java Wed Jan 17 08:36:19 2007
@@ -40,6 +40,8 @@
 import java.util.Map;
 import java.util.Set;
 
+import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap;
+
 /**
  * A <code>NodeTypeRegistry</code> ...
  */
@@ -51,14 +53,14 @@
     private final EffectiveNodeTypeCache entCache;
 
     // map of node type names and node type definitions
-    private final HashMap registeredNTDefs;
+    private final ConcurrentReaderHashMap registeredNTDefs;
 
     // definition of the root node
     private final QNodeDefinition rootNodeDef;
 
-    // map of id's and property definitions
+    // set of property definitions
     private final Set propDefs;
-    // map of id's and node definitions
+    // set of node definitions
     private final Set nodeDefs;
 
     /**
@@ -103,14 +105,16 @@
         this.validator = new DefinitionValidator(this, nsRegistry);
 
         entCache = new EffectiveNodeTypeCache();
-        registeredNTDefs = new HashMap();
+        registeredNTDefs = new ConcurrentReaderHashMap();
 
         propDefs = new HashSet();
         nodeDefs = new HashSet();
 
         // setup definition of root node
         this.rootNodeDef = rootNodeDef;
-        nodeDefs.add(rootNodeDef);
+        synchronized (nodeDefs) {
+            nodeDefs.add(rootNodeDef);
+        }
 
         try {
             // validate & register the definitions
@@ -147,7 +151,7 @@
     /**
      * @inheritDoc
      */
-    public synchronized QName[] getRegisteredNodeTypes() {
+    public QName[] getRegisteredNodeTypes() {
         return (QName[]) registeredNTDefs.keySet().toArray(new QName[registeredNTDefs.size()]);
     }
 
@@ -155,7 +159,7 @@
     /**
      * @inheritDoc
      */
-    public synchronized boolean isRegistered(QName nodeTypeName) {
+    public boolean isRegistered(QName nodeTypeName) {
         return registeredNTDefs.containsKey(nodeTypeName);
     }
 
@@ -185,8 +189,7 @@
     /**
      * @inheritDoc
      */
-    public synchronized EffectiveNodeType getEffectiveNodeType(QName[] ntNames,
-                                                               Map ntdMap)
+    public EffectiveNodeType getEffectiveNodeType(QName[] ntNames, Map ntdMap)
         throws NodeTypeConflictException, NoSuchNodeTypeException {
         return getEffectiveNodeType(ntNames, entCache, ntdMap);
     }
@@ -194,136 +197,138 @@
     /**
      *
      * @param ntName
-     * @param anEntCache
-     * @param aRegisteredNTDefCache
+     * @param entCache
+     * @param ntdCache
      * @return
      * @throws NoSuchNodeTypeException
      */
-    private synchronized EffectiveNodeType getEffectiveNodeType(QName ntName,
-                                                               EffectiveNodeTypeCache anEntCache,
-                                                               Map aRegisteredNTDefCache)
-            throws NoSuchNodeTypeException {
+    private EffectiveNodeType getEffectiveNodeType(QName ntName,
+                                                   EffectiveNodeTypeCache entCache,
+                                                   Map ntdCache)
+        throws NoSuchNodeTypeException {
         // 1. check if effective node type has already been built
-        EffectiveNodeType ent = anEntCache.get(new QName[]{ntName});
+        EffectiveNodeType ent = entCache.get(new QName[]{ntName});
         if (ent != null) {
             return ent;
         }
 
-        // 2. make sure that the specified node type exists
-        if (!aRegisteredNTDefCache.containsKey(ntName)) {
+        // 2. make sure we've got the definition of the specified node type
+        QNodeTypeDefinition ntd = (QNodeTypeDefinition) ntdCache.get(ntName);
+        if (ntd == null) {
             throw new NoSuchNodeTypeException(ntName.toString());
         }
 
         // 3. build effective node type
-        try {
-            QNodeTypeDefinition ntd = (QNodeTypeDefinition) aRegisteredNTDefCache.get(ntName);
-            ent = EffectiveNodeTypeImpl.create(this, ntd, aRegisteredNTDefCache);
-            // store new effective node type
-            anEntCache.put(ent);
-            return ent;
-        } catch (NodeTypeConflictException ntce) {
-            // should never get here as all registered node types have to be valid!
-            String msg = "internal error: encountered invalid registered node type " + ntName;
-            log.debug(msg);
-            throw new NoSuchNodeTypeException(msg, ntce);
+        synchronized (entCache) {
+            try {
+                ent = EffectiveNodeTypeImpl.create(this, ntd, ntdCache);
+                // store new effective node type
+                entCache.put(ent);
+                return ent;
+            } catch (NodeTypeConflictException ntce) {
+                // should never get here as all known node types should be valid!
+                String msg = "internal error: encountered invalid registered node type " + ntName;
+                log.debug(msg);
+                throw new NoSuchNodeTypeException(msg, ntce);
+            }
         }
     }
 
     /**
      * @param ntNames
-     * @param anEntCache
-     * @param aRegisteredNTDefCache
+     * @param entCache
+     * @param ntdCache
      * @return
      * @throws NodeTypeConflictException
      * @throws NoSuchNodeTypeException
      */
-    private synchronized EffectiveNodeType getEffectiveNodeType(QName[] ntNames,
-                                                               EffectiveNodeTypeCache anEntCache,
-                                                               Map aRegisteredNTDefCache)
-            throws NodeTypeConflictException, NoSuchNodeTypeException {
+    private EffectiveNodeType getEffectiveNodeType(QName[] ntNames,
+                                                   EffectiveNodeTypeCache entCache,
+                                                   Map ntdCache)
+        throws NodeTypeConflictException, NoSuchNodeTypeException {
 
-        EffectiveNodeTypeCache.WeightedKey key =
-                new EffectiveNodeTypeCache.WeightedKey(ntNames);
+        EffectiveNodeTypeCache.WeightedKey key = new EffectiveNodeTypeCache.WeightedKey(ntNames);
 
         // 1. check if aggregate has already been built
-        if (anEntCache.contains(key)) {
-            return anEntCache.get(key);
+        if (entCache.contains(key)) {
+            return entCache.get(key);
         }
 
-        // 2. make sure every single node type exists
+        // 2. make sure we've got the definitions of the specified node types
         for (int i = 0; i < ntNames.length; i++) {
-            if (!aRegisteredNTDefCache.containsKey(ntNames[i])) {
+            if (!ntdCache.containsKey(ntNames[i])) {
                 throw new NoSuchNodeTypeException(ntNames[i].toString());
             }
         }
+
         // 3. build aggregate
         EffectiveNodeTypeImpl result = null;
-
-        // build list of 'best' existing sub-aggregates
-        ArrayList tmpResults = new ArrayList();
-        while (key.getNames().length > 0) {
-            // check if we've already built this aggregate
-            if (anEntCache.contains(key)) {
-                tmpResults.add(anEntCache.get(key));
-                // subtract the result from the temporary key
-                // (which is 'empty' now)
-                key = key.subtract(key);
-                break;
-            }
-            /**
-             * walk list of existing aggregates sorted by 'weight' of
-             * aggregate (i.e. the cost of building it)
-             */
-            boolean foundSubResult = false;
-            Iterator iter = anEntCache.keyIterator();
-            while (iter.hasNext()) {
-                EffectiveNodeTypeCache.WeightedKey k =
-                        (EffectiveNodeTypeCache.WeightedKey) iter.next();
-                /**
-                 * check if the existing aggregate is a 'subset' of the one
-                 * we're looking for
-                 */
-                if (key.contains(k)) {
-                    tmpResults.add(anEntCache.get(k));
+        synchronized (entCache) {
+            // build list of 'best' existing sub-aggregates
+            ArrayList tmpResults = new ArrayList();
+            while (key.getNames().length > 0) {
+                // check if we've already built this aggregate
+                if (entCache.contains(key)) {
+                    tmpResults.add(entCache.get(key));
                     // subtract the result from the temporary key
-                    key = key.subtract(k);
-                    foundSubResult = true;
+                    // (which is 'empty' now)
+                    key = key.subtract(key);
                     break;
                 }
-            }
-            if (!foundSubResult) {
                 /**
-                 * no matching sub-aggregates found:
-                 * build aggregate of remaining node types through iteration
+                 * walk list of existing aggregates sorted by 'weight' of
+                 * aggregate (i.e. the cost of building it)
                  */
-                QName[] remainder = key.getNames();
-                for (int i = 0; i < remainder.length; i++) {
-                    QNodeTypeDefinition ntd = (QNodeTypeDefinition) aRegisteredNTDefCache.get(remainder[i]);
-                    EffectiveNodeTypeImpl ent =
-                            EffectiveNodeTypeImpl.create(this, ntd, aRegisteredNTDefCache);
-                    // store new effective node type
-                    anEntCache.put(ent);
-                    if (result == null) {
-                        result = ent;
-                    } else {
-                        result = result.merge(ent);
-                        // store intermediate result (sub-aggregate)
-                        anEntCache.put(result);
+                boolean foundSubResult = false;
+                Iterator iter = entCache.keyIterator();
+                while (iter.hasNext()) {
+                    EffectiveNodeTypeCache.WeightedKey k =
+                            (EffectiveNodeTypeCache.WeightedKey) iter.next();
+                    /**
+                     * check if the existing aggregate is a 'subset' of the one
+                     * we're looking for
+                     */
+                    if (key.contains(k)) {
+                        tmpResults.add(entCache.get(k));
+                        // subtract the result from the temporary key
+                        key = key.subtract(k);
+                        foundSubResult = true;
+                        break;
+                    }
+                }
+                if (!foundSubResult) {
+                    /**
+                     * no matching sub-aggregates found:
+                     * build aggregate of remaining node types through iteration
+                     */
+                    QName[] remainder = key.getNames();
+                    for (int i = 0; i < remainder.length; i++) {
+                        QNodeTypeDefinition ntd = (QNodeTypeDefinition) ntdCache.get(remainder[i]);
+                        EffectiveNodeTypeImpl ent = EffectiveNodeTypeImpl.create(this, ntd, ntdCache);
+                        // store new effective node type
+                        entCache.put(ent);
+                        if (result == null) {
+                            result = ent;
+                        } else {
+                            result = result.merge(ent);
+                            // store intermediate result (sub-aggregate)
+                            entCache.put(result);
+                        }
                     }
+                    // add aggregate of remaining node types to result list
+                    tmpResults.add(result);
+                    break;
                 }
-                // add aggregate of remaining node types to result list
-                tmpResults.add(result);
-                break;
             }
-        }
-        // merge the sub-aggregates into new effective node type
-        for (int i = 0; i < tmpResults.size(); i++) {
-            if (result == null) {
-                result = (EffectiveNodeTypeImpl) tmpResults.get(i);
-            } else {
-                result = result.merge((EffectiveNodeTypeImpl) tmpResults.get(i));
-                // store intermediate result
-                anEntCache.put(result);
+            // merge the sub-aggregates into new effective node type
+            for (int i = 0; i < tmpResults.size(); i++) {
+                if (result == null) {
+                    result = (EffectiveNodeTypeImpl) tmpResults.get(i);
+                } else {
+                    result = result.merge((EffectiveNodeTypeImpl) tmpResults.get(i));
+                    // store intermediate result
+                    entCache.put(result);
+                }
             }
         }
         // we're done
@@ -372,33 +377,10 @@
     /**
      * @inheritDoc
      */
-    public synchronized void unregisterNodeType(QName nodeTypeName)
-            throws NoSuchNodeTypeException, RepositoryException {
-
-        // perform basic validation
-        if (!registeredNTDefs.containsKey(nodeTypeName)) {
-            throw new NoSuchNodeTypeException(nodeTypeName.toString());
-        }
-
-        /**
-         * check if there are node types that have dependencies on the given
-         * node type
-         */
-        if (hasDependentNodeTypes(nodeTypeName)) {
-            StringBuffer msg = new StringBuffer();
-            msg.append(nodeTypeName + " could not be removed because registered node types are still referencing it.");
-            throw new RepositoryException(msg.toString());
-        }
-
-        // persist removal of node type definition
-        // NOTE: conflict with existing content not asserted on client
-        storage.unregisterNodeTypes(new QName[] {nodeTypeName});
-
-        // update internal cache
-        internalUnregister(nodeTypeName);
-
-        // notify listeners
-        notifyUnregistered(nodeTypeName);
+    public void unregisterNodeType(QName nodeTypeName) throws NoSuchNodeTypeException, RepositoryException {
+        HashSet ntNames = new HashSet();
+        ntNames.add(nodeTypeName);
+        unregisterNodeTypes(ntNames);
     }
 
     /**
@@ -473,12 +455,12 @@
     /**
      * @inheritDoc
      */
-    public synchronized QNodeTypeDefinition getNodeTypeDefinition(QName nodeTypeName)
-            throws NoSuchNodeTypeException {
-        if (!registeredNTDefs.containsKey(nodeTypeName)) {
+    public QNodeTypeDefinition getNodeTypeDefinition(QName nodeTypeName)
+        throws NoSuchNodeTypeException {
+        QNodeTypeDefinition def = (QNodeTypeDefinition) registeredNTDefs.get(nodeTypeName);
+        if (def == null) {
             throw new NoSuchNodeTypeException(nodeTypeName.toString());
         }
-        QNodeTypeDefinition def = (QNodeTypeDefinition) registeredNTDefs.get(nodeTypeName);
         return def;
     }
 
@@ -555,12 +537,16 @@
 
         // store property & child node definitions of new node type by id
         QPropertyDefinition[] pda = ntd.getPropertyDefs();
-        for (int i = 0; i < pda.length; i++) {
-            propDefs.add(pda[i]);
+        synchronized (propDefs) {
+            for (int i = 0; i < pda.length; i++) {
+                propDefs.add(pda[i]);
+            }
         }
         QNodeDefinition[] nda = ntd.getChildNodeDefs();
-        for (int i = 0; i < nda.length; i++) {
-            nodeDefs.add(nda[i]);
+        synchronized (nodeDefs) {
+            for (int i = 0; i < nda.length; i++) {
+                nodeDefs.add(nda[i]);
+            }
         }
     }
 
@@ -588,12 +574,16 @@
 
         // remove property & child node definitions
         QPropertyDefinition[] pda = ntd.getPropertyDefs();
-        for (int i = 0; i < pda.length; i++) {
-            propDefs.remove(pda[i]);
+        synchronized (propDefs) {
+            for (int i = 0; i < pda.length; i++) {
+                propDefs.remove(pda[i]);
+            }
         }
-        QNodeDefinition[] nda = ntd.getChildNodeDefs();
-        for (int i = 0; i < nda.length; i++) {
-            nodeDefs.remove(nda[i]);
+        synchronized (nodeDefs) {
+            QNodeDefinition[] nda = ntd.getChildNodeDefs();
+            for (int i = 0; i < nda.length; i++) {
+                nodeDefs.remove(nda[i]);
+            }
         }
     }
 
@@ -604,29 +594,6 @@
         }
     }
 
-    /**
-     * Returns the names of those registered node types that have
-     * dependencies on the given node type.
-     *
-     * @param nodeTypeName
-     * @return a set of node type <code>QName</code>s
-     * @throws NoSuchNodeTypeException
-     */
-    private synchronized boolean hasDependentNodeTypes(QName nodeTypeName)
-            throws NoSuchNodeTypeException {
-        if (!registeredNTDefs.containsKey(nodeTypeName)) {
-            throw new NoSuchNodeTypeException(nodeTypeName.toString());
-        }
-        Iterator iter = registeredNTDefs.values().iterator();
-        while (iter.hasNext()) {
-            QNodeTypeDefinition ntd = (QNodeTypeDefinition) iter.next();
-            if (ntd.getDependencies().contains(nodeTypeName)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
    /**
      * Returns the names of those registered node types that have
      * dependencies on the given node type.
@@ -635,16 +602,13 @@
      * @return a set of node type <code>QName</code>s
      * @throws NoSuchNodeTypeException
      */
-    private synchronized Set getDependentNodeTypes(QName nodeTypeName)
+    private Set getDependentNodeTypes(QName nodeTypeName)
             throws NoSuchNodeTypeException {
         if (!registeredNTDefs.containsKey(nodeTypeName)) {
             throw new NoSuchNodeTypeException(nodeTypeName.toString());
         }
 
-        /*
-         * collect names of those node types that have dependencies on the given
-         * node type
-         */
+        // get names of those node types that have dependencies on the given nt
         HashSet names = new HashSet();
         Iterator iter = registeredNTDefs.values().iterator();
         while (iter.hasNext()) {

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateValidator.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateValidator.java?view=diff&rev=497068&r1=497067&r2=497068
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateValidator.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemStateValidator.java Wed Jan 17 08:36:19 2007
@@ -245,7 +245,7 @@
                                                        NodeState parentState)
         throws NoSuchNodeTypeException, ConstraintViolationException, RepositoryException {
         EffectiveNodeType entParent = getEffectiveNodeType(parentState);
-        return entParent.getApplicableNodeDefinition(name, nodeTypeName);
+        return entParent.getApplicableNodeDefinition(name, nodeTypeName, ntReg);
     }
 
     /**
@@ -510,7 +510,7 @@
         if ((options & CHECK_CONSTRAINTS) == CHECK_CONSTRAINTS) {
             // make sure there's an applicable definition for new child node
             EffectiveNodeType entParent = getEffectiveNodeType(parentState);
-            entParent.checkAddNodeConstraints(nodeName, nodeTypeName);
+            entParent.checkAddNodeConstraints(nodeName, nodeTypeName, ntReg);
         }
         // collisions
         if ((options & CHECK_COLLISION) == CHECK_COLLISION) {

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateFactory.java?view=diff&rev=497068&r1=497067&r2=497068
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateFactory.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateFactory.java Wed Jan 17 08:36:19 2007
@@ -32,6 +32,7 @@
 import org.apache.jackrabbit.jcr2spi.WorkspaceManager;
 import org.apache.jackrabbit.jcr2spi.nodetype.EffectiveNodeType;
 import org.apache.jackrabbit.jcr2spi.nodetype.NodeTypeConflictException;
+import org.apache.jackrabbit.jcr2spi.nodetype.NodeTypeRegistry;
 
 import javax.jcr.PathNotFoundException;
 import javax.jcr.RepositoryException;
@@ -141,8 +142,9 @@
                 // special case for root state
                 definition = wspManager.getNodeTypeRegistry().getRootNodeDef();
             } else {
-                EffectiveNodeType ent = wspManager.getNodeTypeRegistry().getEffectiveNodeType(parent.getNodeTypeNames());
-                definition = ent.getApplicableNodeDefinition(info.getQName(), info.getNodetype());
+                NodeTypeRegistry ntReg = wspManager.getNodeTypeRegistry();
+                EffectiveNodeType ent = ntReg.getEffectiveNodeType(parent.getNodeTypeNames());
+                definition = ent.getApplicableNodeDefinition(info.getQName(), info.getNodetype(), ntReg);
             }
 
             // build the node state

Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/DocViewImportHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/DocViewImportHandler.java?view=diff&rev=497068&r1=497067&r2=497068
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/DocViewImportHandler.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/DocViewImportHandler.java Wed Jan 17 08:36:19 2007
@@ -175,22 +175,17 @@
 
             ArrayList props = new ArrayList(atts.getLength());
             for (int i = 0; i < atts.getLength(); i++) {
+                if (atts.getURI(i).equals(QName.NS_XMLNS_URI)) {
+                    // skip namespace declarations reported as attributes
+                    // see http://issues.apache.org/jira/browse/JCR-620#action_12448164
+                    continue;
+                }
                 QName propName = new QName(atts.getURI(i), atts.getLocalName(i));
                 // decode property name
                 propName = ISO9075.decode(propName);
 
-                // value(s)
+                // attribute value
                 String attrValue = atts.getValue(i);
-                Importer.TextValue[] propValues;
-
-                // always assume single-valued property for the time being
-                // until a way of properly serializing/detecting multi-valued
-                // properties on re-import is found (see JCR-325);
-                // see also DocViewSAXEventGenerator#leavingProperties(Node, int)
-                // TODO: proper multi-value serialization support
-                propValues = new Importer.TextValue[1];
-                propValues[0] = new StringValue(attrValue);
-
                 if (propName.equals(QName.JCR_PRIMARYTYPE)) {
                     // jcr:primaryType
                     if (attrValue.length() > 0) {
@@ -203,24 +198,20 @@
                     }
                 } else if (propName.equals(QName.JCR_MIXINTYPES)) {
                     // jcr:mixinTypes
-                    if (propValues.length > 0) {
-                        mixinTypes = new QName[propValues.length];
-                        for (int j = 0; j < propValues.length; j++) {
-                            String val = ((StringValue) propValues[j]).retrieve();
-                            try {
-                                mixinTypes[j] = NameFormat.parse(val, nsContext);
-                            } catch (NameException ne) {
-                                throw new SAXException("illegal jcr:mixinTypes value: "
-                                        + val, ne);
-                            }
-                        }
-                    }
+                    mixinTypes = parseNames(attrValue);
                 } else if (propName.equals(QName.JCR_UUID)) {
                     // jcr:uuid
                     if (attrValue.length() > 0) {
                         uuid = attrValue;
                     }
                 } else {
+                    // always assume single-valued property for the time being
+                    // until a way of properly serializing/detecting multi-valued
+                    // properties on re-import is found (see JCR-325);
+                    // see also DocViewSAXEventGenerator#leavingProperties(Node, int)
+                    // TODO: proper multi-value serialization support
+                    Importer.TextValue[] propValues = new Importer.TextValue[1];
+                    propValues[0] = new StringValue(attrValue);
                     props.add(new Importer.PropInfo(propName, PropertyType.UNDEFINED, propValues));
                 }
             }
@@ -233,6 +224,29 @@
         } catch (RepositoryException re) {
             throw new SAXException(re);
         }
+    }
+
+    /**
+     * Parses the given string as a list of JCR names. Any whitespace sequence
+     * is supported as a names separator instead of just a single space to
+     * be more liberal in what we accept. The current namespace context is
+     * used to convert the prefixed name strings to QNames.
+     *
+     * @param value string value
+     * @return the parsed names
+     * @throws SAXException if an invalid name was encountered
+     */
+    private QName[] parseNames(String value) throws SAXException {
+        String[] names = value.split("\\p{Space}+");
+        QName[] qnames = new QName[names.length];
+        for (int i = 0; i < names.length; i++) {
+            try {
+                qnames[i] = NameFormat.parse(names[i], nsContext);
+            } catch (NameException ne) {
+                throw new SAXException("Invalid name: " + names[i], ne);
+            }
+        }
+        return qnames;
     }
 
     /**