Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/journal/AbstractRecord.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/journal/AbstractRecord.java	(revision 808006)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/journal/AbstractRecord.java	(working copy)
@@ -25,6 +25,8 @@
 
 import org.apache.commons.collections.BidiMap;
 import org.apache.commons.collections.bidimap.DualHashBidiMap;
+import org.apache.jackrabbit.commons.cnd.CompactNodeTypeDefReader;
+import org.apache.jackrabbit.commons.cnd.ParseException;
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.id.PropertyId;
 import org.apache.jackrabbit.core.nodetype.NodeTypeDef;
@@ -37,9 +39,8 @@
 import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
 import org.apache.jackrabbit.spi.commons.namespace.NamespaceMapping;
 import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
-import org.apache.jackrabbit.spi.commons.nodetype.compact.CompactNodeTypeDefReader;
 import org.apache.jackrabbit.spi.commons.nodetype.compact.CompactNodeTypeDefWriter;
-import org.apache.jackrabbit.spi.commons.nodetype.compact.ParseException;
+import org.apache.jackrabbit.spi.commons.nodetype.compact.QItemDefinitionsBuilder;
 
 /**
  * Base implementation for a record.
@@ -248,8 +249,12 @@
     public NodeTypeDef readNodeTypeDef() throws JournalException {
         try {
             StringReader sr = new StringReader(readString());
-            CompactNodeTypeDefReader reader = new CompactNodeTypeDefReader(
-                    sr, "(internal)", new NamespaceMapping(nsResolver));
+
+            CompactNodeTypeDefReader<QNodeTypeDefinition, NamespaceMapping> reader =
+                new CompactNodeTypeDefReader<QNodeTypeDefinition, NamespaceMapping>(
+                    sr, "(internal)", new NamespaceMapping(nsResolver),
+                    new QItemDefinitionsBuilder());
+
             Collection<QNodeTypeDefinition> ntds = reader.getNodeTypeDefinitions();
             if (ntds.size() != 1) {
                 throw new JournalException("Expected one node type definition: got " + ntds.size());
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeDefStore.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeDefStore.java	(revision 808006)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeDefStore.java	(working copy)
@@ -28,12 +28,14 @@
 import javax.jcr.NamespaceRegistry;
 import javax.jcr.RepositoryException;
 
+import org.apache.jackrabbit.commons.cnd.CompactNodeTypeDefReader;
+import org.apache.jackrabbit.commons.cnd.ParseException;
 import org.apache.jackrabbit.core.nodetype.xml.NodeTypeReader;
 import org.apache.jackrabbit.core.nodetype.xml.NodeTypeWriter;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.QNodeTypeDefinition;
-import org.apache.jackrabbit.spi.commons.nodetype.compact.CompactNodeTypeDefReader;
-import org.apache.jackrabbit.spi.commons.nodetype.compact.ParseException;
+import org.apache.jackrabbit.spi.commons.namespace.NamespaceMapping;
+import org.apache.jackrabbit.spi.commons.nodetype.compact.QItemDefinitionsBuilder;
 
 /**
  * <code>NodeTypeDefStore</code> ...
@@ -66,7 +68,7 @@
 
     /**
      * Loads node types from a CND stream.
-     * 
+     *
      * @param in reader containing the nodetype definitions
      * @param systemId optional name of the stream
      *
@@ -76,7 +78,10 @@
     public void loadCND(Reader in, String systemId)
             throws IOException, InvalidNodeTypeDefException {
         try {
-            CompactNodeTypeDefReader r = new CompactNodeTypeDefReader(in, systemId);
+            CompactNodeTypeDefReader<QNodeTypeDefinition, NamespaceMapping> r =
+                new CompactNodeTypeDefReader<QNodeTypeDefinition, NamespaceMapping>(
+                    in, systemId, new QItemDefinitionsBuilder());
+
             for (QNodeTypeDefinition qdef: r.getNodeTypeDefinitions()) {
                 add(new NodeTypeDef(qdef));
             }
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeManagerImpl.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeManagerImpl.java	(revision 808006)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeManagerImpl.java	(working copy)
@@ -50,6 +50,8 @@
 import org.apache.commons.collections.map.ReferenceMap;
 import org.apache.jackrabbit.api.JackrabbitNodeTypeManager;
 import org.apache.jackrabbit.commons.NamespaceHelper;
+import org.apache.jackrabbit.commons.cnd.CompactNodeTypeDefReader;
+import org.apache.jackrabbit.commons.cnd.ParseException;
 import org.apache.jackrabbit.commons.iterator.NodeTypeIteratorAdapter;
 import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.data.DataStore;
@@ -64,8 +66,7 @@
 import org.apache.jackrabbit.spi.commons.namespace.NamespaceMapping;
 import org.apache.jackrabbit.spi.commons.nodetype.AbstractNodeTypeManager;
 import org.apache.jackrabbit.spi.commons.nodetype.InvalidConstraintException;
-import org.apache.jackrabbit.spi.commons.nodetype.compact.CompactNodeTypeDefReader;
-import org.apache.jackrabbit.spi.commons.nodetype.compact.ParseException;
+import org.apache.jackrabbit.spi.commons.nodetype.compact.QItemDefinitionsBuilder;
 import org.apache.jackrabbit.spi.commons.nodetype.constraint.ValueConstraint;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
@@ -208,7 +209,7 @@
     }
 
     /**
-     * @see org.apache.jackrabbit.spi.commons.nodetype.AbstractNodeTypeManager#getNamePathResolver() 
+     * @see org.apache.jackrabbit.spi.commons.nodetype.AbstractNodeTypeManager#getNamePathResolver()
      */
     public NamePathResolver getNamePathResolver() {
         return session;
@@ -267,9 +268,12 @@
             } else if (contentType.equalsIgnoreCase(TEXT_X_JCR_CND)) {
                 try {
                     NamespaceMapping mapping = new NamespaceMapping(session);
-                    CompactNodeTypeDefReader reader = new CompactNodeTypeDefReader(
-                            new InputStreamReader(in), "cnd input stream", mapping);
 
+                    CompactNodeTypeDefReader<QNodeTypeDefinition, NamespaceMapping> reader =
+                        new CompactNodeTypeDefReader<QNodeTypeDefinition, NamespaceMapping>(
+                            new InputStreamReader(in), "cnd input stream", mapping,
+                            new QItemDefinitionsBuilder());
+
                     namespaceMap.putAll(mapping.getPrefixToURIMapping());
                     for (QNodeTypeDefinition ntDef: reader.getNodeTypeDefinitions()) {
                         nodeTypeDefs.add(new NodeTypeDef(ntDef));
Index: jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/cnd/AbstractItemTypeDefinitionsBuilder.java
===================================================================
--- jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/cnd/AbstractItemTypeDefinitionsBuilder.java	(revision 0)
+++ jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/cnd/AbstractItemTypeDefinitionsBuilder.java	(working copy)
@@ -14,581 +14,377 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.jackrabbit.spi.commons.nodetype.compact;
+package org.apache.jackrabbit.commons.cnd;
 
 import javax.jcr.RepositoryException;
-import javax.jcr.ValueFormatException;
-import javax.jcr.nodetype.PropertyDefinition;
 import javax.jcr.nodetype.ItemDefinition;
 import javax.jcr.nodetype.NodeTypeDefinition;
+import javax.jcr.nodetype.PropertyDefinition;
 
-import org.apache.jackrabbit.spi.Name;
-import org.apache.jackrabbit.spi.QItemDefinition;
-import org.apache.jackrabbit.spi.QNodeDefinition;
-import org.apache.jackrabbit.spi.QNodeTypeDefinition;
-import org.apache.jackrabbit.spi.QPropertyDefinition;
-import org.apache.jackrabbit.spi.QValue;
-import org.apache.jackrabbit.spi.QValueConstraint;
-import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
-import org.apache.jackrabbit.spi.commons.nodetype.InvalidConstraintException;
-import org.apache.jackrabbit.spi.commons.query.qom.Operator;
-
 /**
- * A builder for {@link QNodeTypeDefinition}s
+ * Builder for node type definitions, node definitions and property definitions.
+ * @param <T>  type of the node type definition
+ * @param <N>  type of the namespace mapping
  */
-public abstract class QNodeTypeDefinitionsBuilder {
+public abstract class AbstractItemTypeDefinitionsBuilder<T, N> {
 
     /**
-     * @return a new instance of a builder for a {@link QNodeTypeDefinition}
+     * Create a new instance of a {@link AbstractNodeTypeDefinitionBuilder}
+     * @return
+     * @throws RepositoryException
      */
-    public abstract QNodeTypeDefinitionBuilder newQNodeTypeDefinition();
+    public abstract AbstractNodeTypeDefinitionBuilder<T> newNodeTypeDefinitionBuilder()
+            throws RepositoryException;
 
     /**
-     * Returns a <code>Name</code> with the given namespace URI and
-     * local part and validates the given parameters.
-     *
-     * @param namespaceURI namespace uri
-     * @param localName local part
-     * @return the created name
-     * @throws IllegalArgumentException if <code>namespaceURI</code> or
-     * <code>localName</code> is invalid.
+     * Set the namespace mapping to use for the node type definition being built
+     * @param nsMapping
      */
-    public abstract Name createName(String namespaceURI, String localName)
-            throws IllegalArgumentException;
+    public abstract void setNamespaceMapping(N nsMapping);
 
     /**
-     * A builder for a {@link QNodeTypeDefinition}
+     * @return  the namespace mapping used for the node type definition being built
      */
-    public abstract class QNodeTypeDefinitionBuilder {
-        private Name name;
-        private Name[] supertypes;
-        private boolean isMixin;
-        private boolean isOrderable;
-        private Name primaryItemName;
-        private QPropertyDefinition[] propertyDefinitions;
-        private QNodeDefinition[] childNodeDefinitions;
-        private boolean isAbstract;
-        private boolean isQueryable = true;
+    public abstract N getNamespaceMapping();
 
+    /**
+     * Add a mapping to the namespace map
+     * @param prefix
+     * @param uri
+     * @throws RepositoryException
+     */
+    public abstract void setNamespace(String prefix, String uri) throws RepositoryException;
+
+    /**
+     * Builder for a node type definition of type T.
+     * @param <T>
+     */
+    public static abstract class AbstractNodeTypeDefinitionBuilder<T> {
+
+        /** See {@link #setName(String)} */
+        protected String name;
+
+        /** See {@link #setMixin(boolean)} */
+        protected boolean isMixin;
+
+        /** See {@link #setOrderableChildNodes(boolean)} */
+        protected boolean isOrderable;
+
+        /** See {@link #setAbstract(boolean)} */
+        protected boolean isAbstract;
+
+        /** See {@link #setQueryable(boolean)} */
+        protected boolean queryable;
+
         /**
          * Set the name of the node type definition being built
-         * @param name the name
+         * @param name
+         * @throws RepositoryException  if the name is not valid
          * @see NodeTypeDefinition#getName()
          */
-        public void setName(Name name) {
+        public void setName(String name) throws RepositoryException {
             this.name = name;
         }
 
         /**
-         * @return the name of the node type definition being built or
-         * <code>null</code> if not set.
-         * @see NodeTypeDefinition#getName()
+         * Returns the name of the node type definition being built
+         * @return
          */
-        public Name getName() {
+        public String getName() {
             return name;
         }
 
         /**
-         * Specifies the supertypes of the node type definition being built
-         * @param supertypes the supertypes
+         * Add the given name to the set of supertypes of the node type definition
+         * being built
+         * @param name  name of the the supertype
+         * @throws RepositoryException  if the name is not valid
          * @see NodeTypeDefinition#getDeclaredSupertypeNames()
          */
-        public void setSupertypes(Name[] supertypes) {
-            this.supertypes = supertypes;
-        }
+        public abstract void addSupertype(String name) throws RepositoryException;
 
         /**
-         * Returns an array containing the names of the supertypes of the node
-         * type definition being built.
-         *
-         * @return an array of supertype names
-         * @see NodeTypeDefinition#getDeclaredSupertypeNames()
-         */
-        public Name[] getSuperTypes() {
-            return supertypes;
-        }
-
-        /**
          * @param isMixin <code>true</code> if building a mixin node type
          * definition; <code>false</code> otherwise.
+         * @throws RepositoryException
          * @see NodeTypeDefinition#isMixin()
          */
-        public void setMixin(boolean isMixin) {
+        public void setMixin(boolean isMixin) throws RepositoryException {
             this.isMixin = isMixin;
         }
 
         /**
-         * @return <code>true</code> if building a mixin node type definition;
-         * <code>false</code> otherwise.
-         * @see NodeTypeDefinition#isMixin()
-         */
-        public boolean getMixin() {
-            return isMixin;
-        }
-
-        /**
          * @param isOrderable <code>true</code> if building a node type having
          * orderable child nodes; <code>false</code> otherwise.
+         * @throws RepositoryException
          * @see NodeTypeDefinition#hasOrderableChildNodes()
          */
-        public void setOrderableChildNodes(boolean isOrderable) {
+        public void setOrderableChildNodes(boolean isOrderable) throws RepositoryException {
             this.isOrderable = isOrderable;
         }
 
         /**
-         * @return <code>true</code> if building a node type having orderable
-         * child nodes; <code>false</code> otherwise.
-         * @see NodeTypeDefinition#hasOrderableChildNodes()
-         */
-        public boolean getOrderableChildNodes() {
-            return isOrderable;
-        }
-
-        /**
-         * @param primaryItemName the name of the primary item or
-         * <code>null</code> if not set.
+         * @param name  the name of the primary item.
+         * @throws RepositoryException
          * @see NodeTypeDefinition#getPrimaryItemName()
          */
-        public void setPrimaryItemName(Name primaryItemName) {
-            this.primaryItemName = primaryItemName;
-        }
+        public abstract void setPrimaryItemName(String name) throws RepositoryException;
 
         /**
-         * @return the name of the primary item or <code>null</code> if not set.
-         * @see NodeTypeDefinition#getPrimaryItemName()
-         */
-        public Name getPrimaryItemName() {
-            return primaryItemName;
-        }
-
-        /**
-         * @return <code>true</code> if the node type is abstract.
-         * @see NodeTypeDefinition#isAbstract()
-         */
-        public boolean getAbstract() {
-            return isAbstract;
-        }
-
-        /**
          * @param isAbstract <code>true</code> if building a node type that is abstract.
+         * @throws RepositoryException
          * @see NodeTypeDefinition#isAbstract()
          */
-        public void setAbstract(boolean isAbstract) {
+        public void setAbstract(boolean isAbstract) throws RepositoryException {
             this.isAbstract = isAbstract;
         }
 
         /**
-         * @return <code>true</code> if the node type is queryable
-         * @see NodeTypeDefinition#isQueryable()
-         */
-        public boolean getQueryable() {
-            return isQueryable;
-        }
-
-        /**
          * @param queryable <code>true</code> if building a node type that is queryable
+         * @throws RepositoryException
          * @see NodeTypeDefinition#isQueryable()
          */
-        public void setQueryable(boolean queryable) {
-            isQueryable = queryable;
+        public void setQueryable(boolean queryable) throws RepositoryException {
+            this.queryable = queryable;
         }
 
         /**
-         * @param propDefs an array containing the property definitions of the node type definition
-         *                being built.
-         * @see NodeTypeDefinition#getDeclaredPropertyDefinitions()
+         * Create a new instance of a {@link AbstractItemTypeDefinitionsBuilder.AbstractPropertyDefinitionBuilder}
+         * which can be used to add property definitions to the node type definition being built.
+         * @return
+         * @throws RepositoryException
          */
-        public void setPropertyDefs(QPropertyDefinition[] propDefs) {
-            propertyDefinitions = propDefs;
-        }
+        public abstract AbstractPropertyDefinitionBuilder<T> newPropertyDefinitionBuilder()
+                throws RepositoryException;
 
         /**
-         * @return an array containing the property definitions of the node type definition being
-         *         built or <code>null</code> if not set.
-         * @see NodeTypeDefinition#getDeclaredPropertyDefinitions()
+         * Create a new instance fo a {@link AbstractItemTypeDefinitionsBuilder.AbstractNodeDefinitionBuilder}
+         * which can be used to add child node definitions to the node type definition being built.
+         * @return
+         * @throws RepositoryException
          */
-        public QPropertyDefinition[] getPropertyDefs() {
-            return propertyDefinitions;
-        }
+        public abstract AbstractNodeDefinitionBuilder<T> newNodeDefinitionBuilder() throws RepositoryException;
 
         /**
-         * @param childDefs an array containing the child node definitions of the node type
-         *                definition being.
-         * @see NodeTypeDefinition#getDeclaredChildNodeDefinitions()
+         * Build this node type definition
+         * @return
+         * @throws RepositoryException
          */
-        public void setChildNodeDefs(QNodeDefinition[] childDefs) {
-            childNodeDefinitions = childDefs;
-        }
+        public abstract T build() throws RepositoryException;
+    }
 
-        /**
-         * @return an array containing the child node definitions of the node type definition being
-         *         built or <code>null</code> if not set.
-         * @see NodeTypeDefinition#getDeclaredChildNodeDefinitions()
-         */
-        public QNodeDefinition[] getChildNodeDefs() {
-            return childNodeDefinitions;
-        }
+    /**
+     * Builder for item definitions of type <code>T</code>
+     * @param <T>
+     */
+    public static abstract class AbstractItemDefinitionBuilder<T> {
 
-        /**
-         * @return  a new instance of a builder for a {@link QNodeDefinition}.
-         */
-        public abstract QPropertyDefinitionBuilder newQPropertyDefinition();
+        /** See {@link #setName(String)} */
+        protected String name;
 
-        /**
-         * @return  a new instance of a builder for a {@link QNodeDefinition}.
-         */
-        public abstract QNodeDefinitionBuilder newQNodeDefinitionBuilder();
+        /** See {@link #setAutoCreated(boolean)} */
+        protected boolean autocreate;
 
-        /**
-         * Creates a new {@link QNodeTypeDefinition} instance based on the state of this builder.
-         *
-         * @return a new {@link QNodeTypeDefinition} instance.
-         * @throws IllegalStateException if the instance has not the necessary information to build
-         *                 the QNodeTypeDefinition instance.
-         */
-        public abstract QNodeTypeDefinition build() throws IllegalStateException;
-    }
+        /** See {@link #setOnParentVersion(int)} */
+        protected int onParent;
 
-    /**
-     * A builder for a {@link QItemDefinition}
-     */
-    abstract class QItemDefinitionBuilder {
-        private Name name;
-        private Name declaringType;
-        private boolean isAutocreated;
-        private int onParentVersion;
-        private boolean isProtected;
-        private boolean isMandatory;
+        /** See {@link #setProtected(boolean)} */
+        protected boolean isProtected;
 
+        /** See {@link #setMandatory(boolean)} */
+        protected boolean isMandatory;
+
         /**
          * @param name  the name of the child item definition being build
+         * @throws RepositoryException
          * @see ItemDefinition#getName()
          */
-        public void setName(Name name) {
+        public void setName(String name) throws RepositoryException {
             this.name = name;
         }
 
         /**
-         * @return the name of the child item definition being build.
-         * @see ItemDefinition#getName()
+         * Name of the child item definition being built
+         * @return
          */
-        public Name getName() {
+        public String getName() {
             return name;
         }
 
         /**
-         * @param type  the name of the declaring node type.
+         * @param name the name of the declaring node type.
+         * @throws RepositoryException
          * @see ItemDefinition#getDeclaringNodeType()
          */
-        public void setDeclaringNodeType(Name type) {
-            declaringType = type;
-        }
+        public abstract void setDeclaringNodeType(String name) throws RepositoryException;
 
         /**
-         * @return the name of the declaring node type.
-         * @see ItemDefinition#getDeclaringNodeType()
-         */
-        public Name getDeclaringNodeType() {
-            return declaringType;
-        }
-
-        /**
-         * @param autocreate <code>true</code> if building a 'autocreate' child item 
+         * @param autocreate <code>true</code> if building a 'autocreate' child item
          * definition, false otherwise.
+         * @throws RepositoryException
          * @see ItemDefinition#isAutoCreated()
          */
-        public void setAutoCreated(boolean autocreate) {
-            isAutocreated = autocreate;
+        public void setAutoCreated(boolean autocreate) throws RepositoryException {
+            this.autocreate = autocreate;
         }
 
         /**
-         * @return <code>true</code> if building a 'autocreate' child item
-         * definition, false otherwise.
-         * @see ItemDefinition#isAutoCreated()
-         */
-        public boolean getAutoCreated() {
-            return isAutocreated;
-        }
-
-        /**
          * @param onParent the 'onParentVersion' attribute of the child item definition being built
+         * @throws RepositoryException
          * @see ItemDefinition#getOnParentVersion()
          */
-        public void setOnParentVersion(int onParent) {
-            onParentVersion = onParent;
+        public void setOnParentVersion(int onParent) throws RepositoryException {
+            this.onParent = onParent;
         }
 
         /**
-         * @return the 'onParentVersion' attribute of the child item definition being built
-         * @see ItemDefinition#getOnParentVersion()
-         */
-        public int getOnParentVersion() {
-            return onParentVersion;
-        }
-
-        /**
          * @param isProtected <code>true</code> if building a 'protected' child
          * item definition, false otherwise.
+         * @throws RepositoryException
          * @see ItemDefinition#isProtected()
          */
-        public void setProtected(boolean isProtected) {
+        public void setProtected(boolean isProtected) throws RepositoryException {
             this.isProtected = isProtected;
         }
 
         /**
-         * @return <code>true</code> if building a 'protected' child item
-         * definition, false otherwise.
-         * @see ItemDefinition#isProtected()
-         */
-        public boolean getProtected() {
-            return isProtected;
-        }
-
-        /**
          * @param isMandatory <code>true</code> if building a 'mandatory' child
          * item definition, false otherwise.
-         * @see ItemDefinition#isMandatory()
+         * @throws RepositoryException
          */
-        public void setMandatory(boolean isMandatory) {
+        public void setMandatory(boolean isMandatory) throws RepositoryException {
             this.isMandatory = isMandatory;
         }
 
         /**
-         * @return <code>true</code> if building a 'mandatory' child item
-         * definition, false otherwise.
-         * @see ItemDefinition#isMandatory()
+         * Build this item definition an add it to its parent node type definition
+         * @throws RepositoryException
          */
-        public boolean getMandatory() {
-            return isMandatory;
-        }
+        public abstract void build() throws RepositoryException;
     }
 
     /**
-     * A builder for a {@link QPropertyDefinition}
-     * @see PropertyDefinition
+     * Builder for property definitions of type <code>T</code>
+     * @param <T>
      */
-    public abstract class QPropertyDefinitionBuilder extends QItemDefinitionBuilder {
+    public static abstract class AbstractPropertyDefinitionBuilder<T> extends AbstractItemDefinitionBuilder<T> {
 
-        private int requiredType;
-        private QValueConstraint[] valueConstraints;
-        private QValue[] defaultValues;
-        private boolean isMultiple;
-        private boolean fullTextSearchable = true;
-        private boolean queryOrderable = true;
-        private String[] queryOperators = Operator.getAllQueryOperators();
+        /** See {@link #setRequiredType(int)} */
+        protected int requiredType;
 
+        /** See {@link #setMultiple(boolean)} */
+        protected boolean isMultiple;
+
+        /** See {@link #setFullTextSearchable(boolean)} */
+        protected boolean fullTextSearchable;
+
+        /** See {@link #setQueryOrderable(boolean)} */
+        protected boolean queryOrderable;
+
+        /** See {@link #setAvailableQueryOperators(String[])} */
+        protected String[] queryOperators;
+
         /**
          * @param type the required type of the property definition being built.
+         * @throws RepositoryException
          * @see PropertyDefinition#getRequiredType()
          */
-        public void setRequiredType(int type) {
-            requiredType = type;
+        public void setRequiredType(int type) throws RepositoryException {
+            this.requiredType = type;
         }
 
         /**
-         * @return the required type of the property definition being built.
-         * @see PropertyDefinition#getRequiredType()
+         * The required type of the property definition being built.
+         * @return
          */
         public int getRequiredType() {
             return requiredType;
         }
 
         /**
-         * @param constraints array of value constraints of the property definition being built.
+         * @param constraint  add a value constraint to the list of value constraints of the property
+         * definition being built.
+         * @throws RepositoryException
          * @see PropertyDefinition#getValueConstraints()
          */
-        public void setValueConstraints(QValueConstraint[] constraints) {
-            valueConstraints = constraints;
-        }
+        public abstract void addValueConstraint(String constraint) throws RepositoryException;
 
         /**
-         * @return array of value constraints of the property definition being built.
-         * @see PropertyDefinition#getValueConstraints()
-         */
-        public QValueConstraint[] getValueConstraints() {
-            return valueConstraints;
-        }
-
-        /**
-         * @param values array of default values of the property definition being built.
+         * @param value  add a default value to the list of default values of the property definition
+         * being built.
+         * @throws RepositoryException
          * @see PropertyDefinition#getDefaultValues()
          */
-        public void setDefaultValues(QValue[] values) {
-            defaultValues = values;
-        }
+        public abstract void addDefaultValues(String value) throws RepositoryException;
 
-        /**
-         * @return array of default values of the property definition being built or
-         *         <code>null</code> if no default values are defined.
-         * @see PropertyDefinition#getDefaultValues()
-         */
-        public QValue[] getDefaultValues() {
-            return defaultValues;
-        }
-
-        /**
+         /**
          * @param isMultiple true if building a 'multiple' property definition.
+         * @throws RepositoryException
          * @see PropertyDefinition#isMultiple()
          */
-        public void setMultiple(boolean isMultiple) {
+        public void setMultiple(boolean isMultiple) throws RepositoryException {
             this.isMultiple = isMultiple;
         }
 
         /**
-         * @return true if building a 'multiple' property definition.
-         * @see PropertyDefinition#isMultiple()
-         */
-        public boolean getMultiple() {
-            return isMultiple;
-        }
-
-        /**
-         * @return <code>true</code> if the property is fulltext searchable
-         * @see PropertyDefinition#isFullTextSearchable()
-         */
-        public boolean getFullTextSearchable() {
-            return fullTextSearchable;
-        }
-
-        /**
          * @param fullTextSearchable <code>true</code> if building a
          * 'fulltext searchable' property definition
+         * @throws RepositoryException
          * @see PropertyDefinition#isFullTextSearchable()
          */
-        public void setFullTextSearchable(boolean fullTextSearchable) {
+        public void setFullTextSearchable(boolean fullTextSearchable) throws RepositoryException {
             this.fullTextSearchable = fullTextSearchable;
         }
 
         /**
-         * @return <code>true</code> if the property is orderable in a query
+         * @param queryOrderable <code>true</code> if the property is orderable in a query
+         * @throws RepositoryException
          * @see PropertyDefinition#isQueryOrderable()
          */
-        public boolean getQueryOrderable() {
-            return queryOrderable;
-        }
-
-        /**
-         * @param queryOrderable <code>true</code> if the property is orderable
-         *        in a query
-         * @see PropertyDefinition#isQueryOrderable()
-         */
-        public void setQueryOrderable(boolean queryOrderable) {
+        public void setQueryOrderable(boolean queryOrderable) throws RepositoryException {
             this.queryOrderable = queryOrderable;
         }
 
         /**
-         * @return the query operators of the property
-         * @see PropertyDefinition#getAvailableQueryOperators()
-         */
-        public String[] getAvailableQueryOperators() {
-            return queryOperators;
-        }
-
-        /**
          * @param queryOperators the query operators of the property
+         * @throws RepositoryException
          * @see PropertyDefinition#getAvailableQueryOperators()
          */
-        public void setAvailableQueryOperators(String[] queryOperators) {
+        public void setAvailableQueryOperators(String[] queryOperators) throws RepositoryException {
             this.queryOperators = queryOperators;
         }
-
-        /**
-         * Validate the given <code>constraint</code> and resolve any prefixes.
-         *
-         * @param constraint the contraint
-         * @param resolver the resolver
-         * @return A syntactically valid value constrained which refers to
-         * internal names and paths representations only.
-         * @throws InvalidConstraintException if <code>constraint</code> cannot
-         * be converted to a valid value constrained.
-         */
-        public abstract QValueConstraint createValueConstraint(String constraint, NamePathResolver resolver)
-                throws InvalidConstraintException;
-
-        /**
-         * Create a new <code>QValue</code> for <code>value</code> of the type this instance
-         * represents using the given <code>resolver</code>.
-         *
-         * @param value the value
-         * @param resolver the resolver
-         * @return a new <code>QValue</code>.
-         * @throws ValueFormatException If the given <code>value</code> cannot be converted to the
-         *                 specified <code>type</code>.
-         * @throws RepositoryException If another error occurs.
-         */
-        public abstract QValue createValue(String value, NamePathResolver resolver)
-                throws ValueFormatException, RepositoryException;
-
-        /**
-         * Creates a new {@link QPropertyDefinition} instance based on the state of this builder.
-         *
-         * @return a new {@link QPropertyDefinition} instance.
-         * @throws IllegalStateException if the instance has not the necessary information to build
-         *                 the QPropertyDefinition instance.
-         */
-        public abstract QPropertyDefinition build() throws IllegalStateException;
     }
 
     /**
-     * A builder for a {@link QNodeDefinition}
+     * Builder for child node definitions of type <code>T</code>
+     * @param <T>
      */
-    public abstract class QNodeDefinitionBuilder extends QItemDefinitionBuilder {
-        private Name defaultPrimaryType;
-        private Name[] requiredPrimaryTypes;
-        private boolean allowsSameNameSiblings;
+    public static abstract class AbstractNodeDefinitionBuilder<T> extends AbstractItemDefinitionBuilder<T> {
+        protected boolean allowSns;
 
         /**
          * @param name the name of the default primary type of the node definition being built.
+         * @throws RepositoryException
          */
-        public void setDefaultPrimaryType(Name name) {
-            defaultPrimaryType = name;
-        }
+        public abstract void setDefaultPrimaryType(String name) throws RepositoryException;
 
         /**
-         * @return the name of the default primary type of the node definition being built.
+         * @param name  add a required primary type to the list of names of the required primary types of
+         * the node definition being built.
+         * @throws RepositoryException
          */
-        public Name getDefaultPrimaryType() {
-            return defaultPrimaryType;
-        }
+        public abstract void addRequiredPrimaryType(String name) throws RepositoryException;
 
         /**
-         * @param names array of names of the required primary types of the node definition being
-         *                built.
+         * @param allowSns true if building a node definition with same name siblings, false otherwise.
+         * @throws RepositoryException
          */
-        public void setRequiredPrimaryTypes(Name[] names) {
-            requiredPrimaryTypes = names;
+        public void setAllowsSameNameSiblings(boolean allowSns) throws RepositoryException {
+            this.allowSns = allowSns;
         }
 
-        /**
-         * @return array of names of the required primary types of the node definition being built.
-         */
-        public Name[] getRequiredPrimaryTypes() {
-            return requiredPrimaryTypes;
-        }
-
-        /**
-         * @param allowSns true if building a node definition with same name siblings, false
-         *                otherwise.
-         */
-        public void setAllowsSameNameSiblings(boolean allowSns) {
-            allowsSameNameSiblings = allowSns;
-        }
-
-        /**
-         * @return true if building a node definition with same name siblings, false otherwise.
-         */
-        public boolean getAllowsSameNameSiblings() {
-            return allowsSameNameSiblings;
-        }
-
-        /**
-         * Creates a new {@link QNodeDefinition} instance based on the state of this builder.
-         *
-         * @return a new {@link QNodeDefinition} instance.
-         * @throws IllegalStateException if the instance has not the necessary information to build
-         *                 the QNodeDefinition instance.
-         */
-        public abstract QNodeDefinition build() throws IllegalStateException;
     }
 
 }
+
+
Index: jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/cnd/CompactNodeTypeDefReader.java
===================================================================
--- jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/cnd/CompactNodeTypeDefReader.java	(revision 0)
+++ jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/cnd/CompactNodeTypeDefReader.java	(working copy)
@@ -14,52 +14,32 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.jackrabbit.spi.commons.nodetype.compact;
+package org.apache.jackrabbit.commons.cnd;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
 import java.io.Reader;
-import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Set;
 
-import javax.jcr.NamespaceException;
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.ValueFormatException;
-import javax.jcr.nodetype.NodeTypeDefinition;
 import javax.jcr.query.qom.QueryObjectModelConstants;
 import javax.jcr.version.OnParentVersionAction;
 
-import org.apache.jackrabbit.spi.Name;
-import org.apache.jackrabbit.spi.QNodeDefinition;
-import org.apache.jackrabbit.spi.QNodeTypeDefinition;
-import org.apache.jackrabbit.spi.QPropertyDefinition;
-import org.apache.jackrabbit.spi.QValue;
-import org.apache.jackrabbit.spi.QValueConstraint;
-import org.apache.jackrabbit.spi.commons.conversion.DefaultNamePathResolver;
-import org.apache.jackrabbit.spi.commons.conversion.NameException;
-import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
-import org.apache.jackrabbit.spi.commons.name.NameConstants;
-import org.apache.jackrabbit.spi.commons.namespace.NamespaceMapping;
-import org.apache.jackrabbit.spi.commons.nodetype.InvalidConstraintException;
-import org.apache.jackrabbit.spi.commons.nodetype.NodeTypeDefinitionFactory;
-import org.apache.jackrabbit.spi.commons.nodetype.compact.QNodeTypeDefinitionsBuilder.QNodeDefinitionBuilder;
-import org.apache.jackrabbit.spi.commons.nodetype.compact.QNodeTypeDefinitionsBuilder.QNodeTypeDefinitionBuilder;
-import org.apache.jackrabbit.spi.commons.nodetype.compact.QNodeTypeDefinitionsBuilder.QPropertyDefinitionBuilder;
-import org.apache.jackrabbit.spi.commons.query.qom.Operator;
-import org.apache.jackrabbit.util.ISO9075;
+import org.apache.jackrabbit.commons.cnd.AbstractItemTypeDefinitionsBuilder.AbstractNodeDefinitionBuilder;
+import org.apache.jackrabbit.commons.cnd.AbstractItemTypeDefinitionsBuilder.AbstractNodeTypeDefinitionBuilder;
+import org.apache.jackrabbit.commons.cnd.AbstractItemTypeDefinitionsBuilder.AbstractPropertyDefinitionBuilder;
 
 /**
  * CompactNodeTypeDefReader. Parses node type definitions written in the compact
- * node type definition format and provides a list of QNodeTypeDefinition
+ * node type definition format and provides a list of type definition
  * objects that can then be used to register node types.
  *
+ * The CompactNodeTypeDefReader is parameterizable in the type of the node type
+ * definition <code>T</code> and the type of the namespace mapping <code>N</code>
+ * which the parser should build. For types <code>T</code> and <code>N</code> the
+ * parser's constructor takes a {@link AbstractItemTypeDefinitionsBuilder} for
+ * <code>T</code> and <code>N</code>.
+ *
  * <p/>
  * The EBNF grammar of the compact node type definition:<br>
  * <pre>
@@ -120,43 +100,18 @@
  * UnquotedString ::= XmlChar {XmlChar}
  * XmlChar ::= see 3.2.2 Local Names
  * </pre>
+ *
+ * @param <T>
+ * @param <N>
  */
-public class CompactNodeTypeDefReader {
+public class CompactNodeTypeDefReader<T, N> {
 
     /**
-     * Default namespace mappings
-     */
-    public static final NamespaceMapping NS_DEFAULTS;
-    static {
-        try {
-            NS_DEFAULTS = new NamespaceMapping();
-            NS_DEFAULTS.setMapping(Name.NS_EMPTY_PREFIX, Name.NS_DEFAULT_URI);
-            NS_DEFAULTS.setMapping(Name.NS_JCR_PREFIX, Name.NS_JCR_URI);
-            NS_DEFAULTS.setMapping(Name.NS_MIX_PREFIX, Name.NS_MIX_URI);
-            NS_DEFAULTS.setMapping(Name.NS_NT_PREFIX, Name.NS_NT_URI);
-            NS_DEFAULTS.setMapping(Name.NS_REP_PREFIX, Name.NS_REP_URI);
-        } catch (NamespaceException e) {
-            throw new InternalError(e.toString());
-        }
-    }
-
-    /**
      * the list of parsed QNodeTypeDefinition
      */
-    private final List<QNodeTypeDefinition> nodeTypeDefs
-            = new LinkedList<QNodeTypeDefinition>();
+    private final List<T> nodeTypeDefs = new LinkedList<T>();
 
     /**
-     * the current namespace mapping
-     */
-    private final NamespaceMapping nsMapping;
-
-    /**
-     * Name and Path resolver
-     */
-    private final NamePathResolver resolver;
-
-    /**
      * the underlying lexer
      */
     private final Lexer lexer;
@@ -169,107 +124,42 @@
     /**
      * The builder for QNodeTypeDefinitions
      */
-    private final QNodeTypeDefinitionsBuilder builder;
+    private final AbstractItemTypeDefinitionsBuilder<T, N> builder;
 
     /**
-     * Convenience method that creates a new CND reader and parses the given
-     * file directly.
+     * Creates a new CND reader and parses the given stream.
      *
-     * @param file A CND file
-     * @return a new 'parsed' reader object
-     * @throws ParseException if an error occurs
-     * @throws IOException if an I/O error occurs.
-     */
-    public static CompactNodeTypeDefReader read(File file)
-            throws ParseException, IOException {
-        InputStream in = null;
-        Reader r = null;
-        try {
-            in = new FileInputStream(file);
-            r = new InputStreamReader(in, "utf8");
-            return new CompactNodeTypeDefReader(r, file.getPath());
-        } finally {
-            if (r != null) {
-                try {
-                    r.close();
-                } catch (IOException e) {
-                    // ignore
-                }
-            }
-            if (in != null) {
-                try {
-                    in.close();
-                } catch (IOException e) {
-                    // ignore
-                }
-            }
-        }
-    }
-
-
-    /**
-     * Creates a new CND reader and parses the given stream directly.
-     *
      * @param r a reader to the CND
      * @param systemId a informative id of the given stream
+     * @param builder builder for creating new definitions and handling namespaces
      * @throws ParseException if an error occurs
      */
-    public CompactNodeTypeDefReader(Reader r, String systemId)
-            throws ParseException {
-        this(r, systemId, null, null);
-    }
-
-    /**
-     * Creates a new CND reader and parses the given stream it directly.
-     * If <code>builder</code> is <code>null</code> the reader uses the
-     * default {@link QNodeTypeDefinitionsBuilderImpl}.
-     *
-     * @param r a reader to the CND
-     * @param systemId a informative id of the given stream
-     * @param builder build for creating new definitions or <code>null</code>
-     * @throws ParseException if an error occurs
-     */
     public CompactNodeTypeDefReader(Reader r, String systemId,
-                                    QNodeTypeDefinitionsBuilder builder)
-            throws ParseException {
+            AbstractItemTypeDefinitionsBuilder<T, N> builder) throws ParseException {
+
         this(r, systemId, null, builder);
     }
 
     /**
-     * Creates a new CND reader and parses the given stream it directly.
+     * Creates a new CND reader and parses the given stream.
      *
      * @param r a reader to the CND
      * @param systemId a informative id of the given stream
-     * @param mapping default namespace mapping to use
+     * @param nsMapping default namespace mapping to use
+     * @param builder builder for creating new definitions and handling namespaces
      * @throws ParseException if an error occurs
      */
-    public CompactNodeTypeDefReader(Reader r, String systemId, NamespaceMapping mapping)
-            throws ParseException {
-        this(r, systemId, mapping, null);
-    }
+    public CompactNodeTypeDefReader(Reader r, String systemId, N nsMapping,
+            AbstractItemTypeDefinitionsBuilder<T, N> builder) throws ParseException {
 
-    /**
-     * Creates a new CND reader and parses the given stream it directly.
-     * If <code>builder</code> is <code>null</code> the reader uses the
-     * default {@link QNodeTypeDefinitionsBuilderImpl}.
-     *
-     * @param r a reader to the CND
-     * @param systemId a informative id of the given stream
-     * @param mapping default namespace mapping to use
-     * @param builder build for creating new definitions
-     * @throws ParseException if an error occurs
-     */
-    public CompactNodeTypeDefReader(Reader r, String systemId, NamespaceMapping mapping,
-            QNodeTypeDefinitionsBuilder builder) throws ParseException {
+        super();
 
-        this.builder = builder == null
-                ? new QNodeTypeDefinitionsBuilderImpl()
-                : builder;
+        this.builder = builder;
         lexer = new Lexer(r, systemId);
-        this.nsMapping = mapping == null
-                ? new NamespaceMapping(NS_DEFAULTS)
-                : mapping;
-        this.resolver = new DefaultNamePathResolver(nsMapping);
+        if (nsMapping != null) {
+            builder.setNamespaceMapping(nsMapping);
+        }
+
         nextToken();
         parse();
     }
@@ -283,35 +173,21 @@
     }
 
     /**
-     * Returns the list of parsed QNodeTypeDefinition definitions.
+     * Returns the list of parsed node type definitions definitions.
      *
-     * @return a collection of QNodeTypeDefinition objects
+     * @return a collection of node type definition objects
      */
-    public List<QNodeTypeDefinition> getNodeTypeDefinitions() {
+    public List<T> getNodeTypeDefinitions() {
         return nodeTypeDefs;
     }
 
     /**
-     * Convenience method that returns the list of parsed NodeTypeDefinition
-     * definitions, using the {@link NodeTypeDefinitionFactory}.
-     *
-     * @param session repository session used for converting the definitions.
-     * @return a collection of NodeTypeDefinition objects
-     * @throws RepositoryException if an error occurs
-     */
-    public List<NodeTypeDefinition> getNodeTypeDefinitions(Session session)
-            throws RepositoryException {
-        NodeTypeDefinitionFactory fac = new NodeTypeDefinitionFactory(session);
-        return fac.create(nodeTypeDefs);
-    }
-
-    /**
      * Returns the namespace mapping.
      *
-     * @return a NamespaceMapping object.
+     * @return
      */
-    public NamespaceMapping getNamespaceMapping() {
-        return nsMapping;
+    public N getNamespaceMapping() {
+        return builder.getNamespaceMapping();
     }
 
     /**
@@ -325,26 +201,29 @@
                 break;
             }
         }
-        while (!currentTokenEquals(Lexer.EOF)) {
-            QNodeTypeDefinitionBuilder ntd = builder.newQNodeTypeDefinition();
-            ntd.setOrderableChildNodes(false);
-            ntd.setMixin(false);
-            ntd.setAbstract(false);
-            ntd.setQueryable(true);
-            ntd.setPrimaryItemName(null);
-            doNodeTypeName(ntd);
-            doSuperTypes(ntd);
-            doOptions(ntd);
-            doItemDefs(ntd);
-            nodeTypeDefs.add(ntd.build());
+        try {
+            while (!currentTokenEquals(Lexer.EOF)) {
+                AbstractNodeTypeDefinitionBuilder<T> ntd = builder.newNodeTypeDefinitionBuilder();
+                ntd.setOrderableChildNodes(false);
+                ntd.setMixin(false);
+                ntd.setAbstract(false);
+                ntd.setQueryable(true);
+                doNodeTypeName(ntd);
+                doSuperTypes(ntd);
+                doOptions(ntd);
+                doItemDefs(ntd);
+                nodeTypeDefs.add(ntd.build());
+            }
         }
+        catch (RepositoryException e) {
+            lexer.fail(e);
+        }
     }
 
 
 
     /**
      * processes the namespace declaration
-     *
      * @return <code>true</code> if a namespace was parsed
      * @throws ParseException if an error during parsing occurs
      */
@@ -365,10 +244,11 @@
             lexer.fail("Missing > in namespace decl.");
         }
         try {
-            nsMapping.setMapping(prefix, uri);
-        } catch (NamespaceException e) {
-            // ignore
+            builder.setNamespace(prefix, uri);
         }
+        catch (RepositoryException e) {
+            lexer.fail("Error setting namespace mapping " + currentToken, e);
+        }
         nextToken();
         return true;
     }
@@ -379,12 +259,17 @@
      * @param ntd nodetype definition builder
      * @throws ParseException if an error during parsing occurs
      */
-    private void doNodeTypeName(QNodeTypeDefinitionBuilder ntd) throws ParseException {
+    private void doNodeTypeName(AbstractNodeTypeDefinitionBuilder<T> ntd) throws ParseException {
         if (!currentTokenEquals(Lexer.BEGIN_NODE_TYPE_NAME)) {
             lexer.fail("Missing '" + Lexer.BEGIN_NODE_TYPE_NAME + "' delimiter for beginning of node type name");
         }
         nextToken();
-        ntd.setName(toName(currentToken));
+        try {
+            ntd.setName(currentToken);
+        }
+        catch (RepositoryException e) {
+            lexer.fail("Error setting node type name " + currentToken, e);
+        }
 
         nextToken();
         if (!currentTokenEquals(Lexer.END_NODE_TYPE_NAME)) {
@@ -399,16 +284,19 @@
      * @param ntd nodetype definition builder
      * @throws ParseException if an error during parsing occurs
      */
-    private void doSuperTypes(QNodeTypeDefinitionBuilder ntd) throws ParseException {
-        Set<Name> supertypes = new HashSet<Name>();
+    private void doSuperTypes(AbstractNodeTypeDefinitionBuilder<T> ntd) throws ParseException  {
+
         if (currentTokenEquals(Lexer.EXTENDS))
             do {
                 nextToken();
-                supertypes.add(toName(currentToken));
+                try {
+                    ntd.addSupertype(currentToken);
+                }
+                catch (RepositoryException e) {
+                    lexer.fail("Error setting super type of " + ntd.getName() + " to " + currentToken, e);
+                }
                 nextToken();
             } while (currentTokenEquals(Lexer.LIST_DELIMITER));
-
-        ntd.setSupertypes(supertypes.toArray(new Name[supertypes.size()]));
     }
 
     /**
@@ -417,32 +305,38 @@
      * @param ntd nodetype definition builder
      * @throws ParseException if an error during parsing occurs
      */
-    private void doOptions(QNodeTypeDefinitionBuilder ntd) throws ParseException {
+    private void doOptions(AbstractNodeTypeDefinitionBuilder<T> ntd) throws ParseException {
+
         boolean hasOption = true;
-        while (hasOption) {
-            if (currentTokenEquals(Lexer.ORDERABLE)) {
-                nextToken();
-                ntd.setOrderableChildNodes(true);
-            } else if (currentTokenEquals(Lexer.MIXIN)) {
-                nextToken();
-                ntd.setMixin(true);
-            } else if (currentTokenEquals(Lexer.ABSTRACT)) {
-                nextToken();
-                ntd.setAbstract(true);
-            } else if (currentTokenEquals(Lexer.NOQUERY)) {
-                nextToken();
-                ntd.setQueryable(false);
-            } else if (currentTokenEquals(Lexer.QUERY)) {
-                nextToken();
-                ntd.setQueryable(true);
-            } else if (currentTokenEquals(Lexer.PRIMARYITEM)) {
-                nextToken();
-                ntd.setPrimaryItemName(toName(currentToken));
-                nextToken();
-            } else {
-                hasOption = false;
+        try {
+            while (hasOption) {
+                if (currentTokenEquals(Lexer.ORDERABLE)) {
+                    nextToken();
+                    ntd.setOrderableChildNodes(true);
+                } else if (currentTokenEquals(Lexer.MIXIN)) {
+                    nextToken();
+                    ntd.setMixin(true);
+                } else if (currentTokenEquals(Lexer.ABSTRACT)) {
+                    nextToken();
+                    ntd.setAbstract(true);
+                } else if (currentTokenEquals(Lexer.NOQUERY)) {
+                    nextToken();
+                    ntd.setQueryable(false);
+                } else if (currentTokenEquals(Lexer.QUERY)) {
+                    nextToken();
+                    ntd.setQueryable(true);
+                } else if (currentTokenEquals(Lexer.PRIMARYITEM)) {
+                    nextToken();
+                    ntd.setPrimaryItemName(currentToken);
+                    nextToken();
+                } else {
+                    hasOption = false;
+                }
             }
         }
+        catch (RepositoryException e) {
+            lexer.fail("Error setting option of " + ntd.getName() + " to " + currentToken, e);
+        }
     }
 
     /**
@@ -451,49 +345,57 @@
      * @param ntd nodetype definition builder
      * @throws ParseException if an error during parsing occurs
      */
-    private void doItemDefs(QNodeTypeDefinitionBuilder ntd) throws ParseException {
-        List<QPropertyDefinition> propertyDefinitions = new LinkedList<QPropertyDefinition>();
-        List<QNodeDefinition> nodeDefinitions = new LinkedList<QNodeDefinition>();
+    private void doItemDefs(AbstractNodeTypeDefinitionBuilder<T> ntd) throws ParseException {
         while (currentTokenEquals(Lexer.PROPERTY_DEFINITION) || currentTokenEquals(Lexer.CHILD_NODE_DEFINITION)) {
             if (currentTokenEquals(Lexer.PROPERTY_DEFINITION)) {
-                QPropertyDefinitionBuilder pd = ntd.newQPropertyDefinition();
+                try {
+                    AbstractPropertyDefinitionBuilder<T> pd = ntd.newPropertyDefinitionBuilder();
+                    try {
+                        pd.setAutoCreated(false);
+                        pd.setDeclaringNodeType(ntd.getName());
+                        pd.setMandatory(false);
+                        pd.setMultiple(false);
+                        pd.setOnParentVersion(OnParentVersionAction.COPY);
+                        pd.setProtected(false);
+                        pd.setRequiredType(PropertyType.STRING);
+                        pd.setFullTextSearchable(true);
+                        pd.setQueryOrderable(true);
+                    }
+                    catch (RepositoryException e) {
+                        lexer.fail("Error setting property definitions of " + pd.getName() + " to " + currentToken, e);
+                    }
+                    nextToken();
+                    doPropertyDefinition(pd, ntd);
+                    pd.build();
+                }
+                catch (RepositoryException e) {
+                    lexer.fail("Error building property definition for " + ntd.getName(), e);
+                }
 
-                pd.setAutoCreated(false);
-                pd.setDeclaringNodeType(ntd.getName());
-                pd.setDefaultValues(null);
-                pd.setMandatory(false);
-                pd.setMultiple(false);
-                pd.setOnParentVersion(OnParentVersionAction.COPY);
-                pd.setProtected(false);
-                pd.setRequiredType(PropertyType.STRING);
-                pd.setValueConstraints(QValueConstraint.EMPTY_ARRAY);
-                pd.setFullTextSearchable(true);
-                pd.setQueryOrderable(true);
-                pd.setAvailableQueryOperators(Operator.getAllQueryOperators());
-
-                nextToken();
-                doPropertyDefinition(pd, ntd);
-                propertyDefinitions.add(pd.build());
-
             } else if (currentTokenEquals(Lexer.CHILD_NODE_DEFINITION)) {
-                QNodeDefinitionBuilder nd = ntd.newQNodeDefinitionBuilder();
+                try {
+                    AbstractNodeDefinitionBuilder<T> nd = ntd.newNodeDefinitionBuilder();
+                    try {
+                        nd.setAllowsSameNameSiblings(false);
+                        nd.setAutoCreated(false);
+                        nd.setDeclaringNodeType(ntd.getName());
+                        nd.setMandatory(false);
+                        nd.setOnParentVersion(OnParentVersionAction.COPY);
+                        nd.setProtected(false);
+                    }
+                    catch (RepositoryException e) {
+                        lexer.fail("Error setting node definitions of " + nd.getName() + " to " + currentToken, e);
+                    }
 
-                nd.setAllowsSameNameSiblings(false);
-                nd.setAutoCreated(false);
-                nd.setDeclaringNodeType(ntd.getName());
-                nd.setMandatory(false);
-                nd.setOnParentVersion(OnParentVersionAction.COPY);
-                nd.setProtected(false);
-                nd.setDefaultPrimaryType(null);
-                nd.setRequiredPrimaryTypes(new Name[]{NameConstants.NT_BASE});
-
-                nextToken();
-                doChildNodeDefinition(nd, ntd);
-                nodeDefinitions.add(nd.build());
+                    nextToken();
+                    doChildNodeDefinition(nd, ntd);
+                    nd.build();
+                }
+                catch (RepositoryException e) {
+                    lexer.fail("Error building node definition for " + ntd.getName(), e);
+                }
             }
         }
-        ntd.setPropertyDefs(propertyDefinitions.toArray(new QPropertyDefinition[propertyDefinitions.size()]));
-        ntd.setChildNodeDefs(nodeDefinitions.toArray(new QNodeDefinition[nodeDefinitions.size()]));
     }
 
     /**
@@ -501,15 +403,17 @@
      *
      * @param pd property definition builder
      * @param ntd declaring nodetype definition builder
-     * @throws ParseException if an error during parsing occurs
+     * @throws ParseException if an error during parsing occur
      */
-    private void doPropertyDefinition(QPropertyDefinitionBuilder pd, QNodeTypeDefinitionBuilder ntd)
+    private void doPropertyDefinition(AbstractPropertyDefinitionBuilder<T> pd, AbstractNodeTypeDefinitionBuilder<T> ntd)
             throws ParseException {
-        if (currentToken.equals("*")) {
-            pd.setName(NameConstants.ANY_NAME);
-        } else {
-            pd.setName(toName(currentToken));
+
+        try {
+            pd.setName(currentToken);
         }
+        catch (RepositoryException e) {
+            lexer.fail("Error setting name of " + pd.getName() + " to " + currentToken);
+        }
         nextToken();
         doPropertyType(pd);
         doPropertyDefaultValue(pd);
@@ -523,40 +427,46 @@
      * @param pd property definition builder
      * @throws ParseException if an error during parsing occurs
      */
-    private void doPropertyType(QPropertyDefinitionBuilder pd) throws ParseException {
+    private void doPropertyType(AbstractPropertyDefinitionBuilder<T> pd) throws ParseException {
+
         if (!currentTokenEquals(Lexer.BEGIN_TYPE)) {
             return;
         }
         nextToken();
-        if (currentTokenEquals(Lexer.STRING)) {
-            pd.setRequiredType(PropertyType.STRING);
-        } else if (currentTokenEquals(Lexer.BINARY)) {
-            pd.setRequiredType(PropertyType.BINARY);
-        } else if (currentTokenEquals(Lexer.LONG)) {
-            pd.setRequiredType(PropertyType.LONG);
-        } else if (currentTokenEquals(Lexer.DECIMAL)) {
-            pd.setRequiredType(PropertyType.DECIMAL);
-        } else if (currentTokenEquals(Lexer.DOUBLE)) {
-            pd.setRequiredType(PropertyType.DOUBLE);
-        } else if (currentTokenEquals(Lexer.BOOLEAN)) {
-            pd.setRequiredType(PropertyType.BOOLEAN);
-        } else if (currentTokenEquals(Lexer.DATE)) {
-            pd.setRequiredType(PropertyType.DATE);
-        } else if (currentTokenEquals(Lexer.NAME)) {
-            pd.setRequiredType(PropertyType.NAME);
-        } else if (currentTokenEquals(Lexer.PATH)) {
-            pd.setRequiredType(PropertyType.PATH);
-        } else if (currentTokenEquals(Lexer.URI)) {
-            pd.setRequiredType(PropertyType.URI);
-        } else if (currentTokenEquals(Lexer.REFERENCE)) {
-            pd.setRequiredType(PropertyType.REFERENCE);
-        } else if (currentTokenEquals(Lexer.WEAKREFERENCE)) {
-            pd.setRequiredType(PropertyType.WEAKREFERENCE);
-        } else if (currentTokenEquals(Lexer.UNDEFINED)) {
-            pd.setRequiredType(PropertyType.UNDEFINED);
-        } else {
-            lexer.fail("Unkown property type '" + currentToken + "' specified");
+        try {
+            if (currentTokenEquals(Lexer.STRING)) {
+                pd.setRequiredType(PropertyType.STRING);
+            } else if (currentTokenEquals(Lexer.BINARY)) {
+                pd.setRequiredType(PropertyType.BINARY);
+            } else if (currentTokenEquals(Lexer.LONG)) {
+                pd.setRequiredType(PropertyType.LONG);
+            } else if (currentTokenEquals(Lexer.DECIMAL)) {
+                pd.setRequiredType(PropertyType.DECIMAL);
+            } else if (currentTokenEquals(Lexer.DOUBLE)) {
+                pd.setRequiredType(PropertyType.DOUBLE);
+            } else if (currentTokenEquals(Lexer.BOOLEAN)) {
+                pd.setRequiredType(PropertyType.BOOLEAN);
+            } else if (currentTokenEquals(Lexer.DATE)) {
+                pd.setRequiredType(PropertyType.DATE);
+            } else if (currentTokenEquals(Lexer.NAME)) {
+                pd.setRequiredType(PropertyType.NAME);
+            } else if (currentTokenEquals(Lexer.PATH)) {
+                pd.setRequiredType(PropertyType.PATH);
+            } else if (currentTokenEquals(Lexer.URI)) {
+                pd.setRequiredType(PropertyType.URI);
+            } else if (currentTokenEquals(Lexer.REFERENCE)) {
+                pd.setRequiredType(PropertyType.REFERENCE);
+            } else if (currentTokenEquals(Lexer.WEAKREFERENCE)) {
+                pd.setRequiredType(PropertyType.WEAKREFERENCE);
+            } else if (currentTokenEquals(Lexer.UNDEFINED)) {
+                pd.setRequiredType(PropertyType.UNDEFINED);
+            } else {
+                lexer.fail("Unkown property type '" + currentToken + "' specified");
+            }
         }
+        catch (RepositoryException e) {
+            lexer.fail("Error setting property type of " + pd.getName() + " to " + currentToken);
+        }
         nextToken();
         if (!currentTokenEquals(Lexer.END_TYPE)) {
             lexer.fail("Missing '" + Lexer.END_TYPE + "' delimiter for end of property type");
@@ -571,50 +481,46 @@
      * @param ntd declaring nodetype definition builder
      * @throws ParseException if an error during parsing occurs
      */
-    private void doPropertyAttributes(QPropertyDefinitionBuilder pd,
-                                      QNodeTypeDefinitionBuilder ntd)
-            throws ParseException {
-        while (currentTokenEquals(Lexer.PROP_ATTRIBUTE)) {
-            if (currentTokenEquals(Lexer.PRIMARY)) {
-                if (ntd.getPrimaryItemName() != null) {
-                    String name = null;
-                    try {
-                        name = resolver.getJCRName(ntd.getName());
-                    } catch (NamespaceException e) {
-                        // Should never happen, checked earlier
-                    }
-                    lexer.fail("More than one primary item specified in node type '" + name + "'");
+    private void doPropertyAttributes(AbstractPropertyDefinitionBuilder<T> pd,
+            AbstractNodeTypeDefinitionBuilder<T> ntd) throws ParseException {
+
+        try {
+            while (currentTokenEquals(Lexer.PROP_ATTRIBUTE)) {
+                if (currentTokenEquals(Lexer.PRIMARY)) {
+                    ntd.setPrimaryItemName(pd.getName());
+                } else if (currentTokenEquals(Lexer.AUTOCREATED)) {
+                    pd.setAutoCreated(true);
+                } else if (currentTokenEquals(Lexer.MANDATORY)) {
+                    pd.setMandatory(true);
+                } else if (currentTokenEquals(Lexer.PROTECTED)) {
+                    pd.setProtected(true);
+                } else if (currentTokenEquals(Lexer.MULTIPLE)) {
+                    pd.setMultiple(true);
+                } else if (currentTokenEquals(Lexer.COPY)) {
+                    pd.setOnParentVersion(OnParentVersionAction.COPY);
+                } else if (currentTokenEquals(Lexer.VERSION)) {
+                    pd.setOnParentVersion(OnParentVersionAction.VERSION);
+                } else if (currentTokenEquals(Lexer.INITIALIZE)) {
+                    pd.setOnParentVersion(OnParentVersionAction.INITIALIZE);
+                } else if (currentTokenEquals(Lexer.COMPUTE)) {
+                    pd.setOnParentVersion(OnParentVersionAction.COMPUTE);
+                } else if (currentTokenEquals(Lexer.IGNORE)) {
+                    pd.setOnParentVersion(OnParentVersionAction.IGNORE);
+                } else if (currentTokenEquals(Lexer.ABORT)) {
+                    pd.setOnParentVersion(OnParentVersionAction.ABORT);
+                } else if (currentTokenEquals(Lexer.NOFULLTEXT)) {
+                    pd.setFullTextSearchable(false);
+                } else if (currentTokenEquals(Lexer.NOQUERYORDER)) {
+                    pd.setQueryOrderable(false);
+                } else if (currentTokenEquals(Lexer.QUERYOPS)) {
+                    doPropertyQueryOperators(pd);
                 }
-                ntd.setPrimaryItemName(pd.getName());
-            } else if (currentTokenEquals(Lexer.AUTOCREATED)) {
-                pd.setAutoCreated(true);
-            } else if (currentTokenEquals(Lexer.MANDATORY)) {
-                pd.setMandatory(true);
-            } else if (currentTokenEquals(Lexer.PROTECTED)) {
-                pd.setProtected(true);
-            } else if (currentTokenEquals(Lexer.MULTIPLE)) {
-                pd.setMultiple(true);
-            } else if (currentTokenEquals(Lexer.COPY)) {
-                pd.setOnParentVersion(OnParentVersionAction.COPY);
-            } else if (currentTokenEquals(Lexer.VERSION)) {
-                pd.setOnParentVersion(OnParentVersionAction.VERSION);
-            } else if (currentTokenEquals(Lexer.INITIALIZE)) {
-                pd.setOnParentVersion(OnParentVersionAction.INITIALIZE);
-            } else if (currentTokenEquals(Lexer.COMPUTE)) {
-                pd.setOnParentVersion(OnParentVersionAction.COMPUTE);
-            } else if (currentTokenEquals(Lexer.IGNORE)) {
-                pd.setOnParentVersion(OnParentVersionAction.IGNORE);
-            } else if (currentTokenEquals(Lexer.ABORT)) {
-                pd.setOnParentVersion(OnParentVersionAction.ABORT);
-            } else if (currentTokenEquals(Lexer.NOFULLTEXT)) {
-                pd.setFullTextSearchable(false);
-            } else if (currentTokenEquals(Lexer.NOQUERYORDER)) {
-                pd.setQueryOrderable(false);
-            } else if (currentTokenEquals(Lexer.QUERYOPS)) {
-                doPropertyQueryOperators(pd);
+                nextToken();
             }
-            nextToken();
         }
+        catch (RepositoryException e) {
+            lexer.fail("Error setting property attribute of " + pd.getName() + " to " + currentToken);
+        }
     }
 
     /**
@@ -623,7 +529,7 @@
      * @param pd the property definition builder
      * @throws ParseException if an error occurs
      */
-    private void doPropertyQueryOperators(QPropertyDefinitionBuilder pd)
+    private void doPropertyQueryOperators(AbstractPropertyDefinitionBuilder<T> pd)
             throws ParseException {
         if (!currentTokenEquals(Lexer.QUERYOPS)) {
             return;
@@ -652,7 +558,12 @@
                 lexer.fail("'" + s + "' is not a valid query operator");
             }
         }
-        pd.setAvailableQueryOperators(queryOps.toArray(new String[queryOps.size()]));
+        try {
+            pd.setAvailableQueryOperators(queryOps.toArray(new String[queryOps.size()]));
+        }
+        catch (RepositoryException e) {
+            lexer.fail("Error query operators for " + pd.getName() + " to " + currentToken);
+        }
     }
 
     /**
@@ -661,24 +572,23 @@
      * @param pd property definition builder
      * @throws ParseException if an error during parsing occurs
      */
-    private void doPropertyDefaultValue(QPropertyDefinitionBuilder pd)
+    private void doPropertyDefaultValue(AbstractPropertyDefinitionBuilder<T> pd)
             throws ParseException {
+
         if (!currentTokenEquals(Lexer.DEFAULT)) {
             return;
         }
-        List<QValue> defaultValues = new LinkedList<QValue>();
+
         do {
             nextToken();
             try {
-                defaultValues.add(pd.createValue(currentToken, resolver));
-            } catch (ValueFormatException e) {
-                lexer.fail("'" + currentToken + "' is not a valid string representation of a value of type " + pd.getRequiredType());
-            } catch (RepositoryException e) {
-                lexer.fail("An error occured during value conversion of '" + currentToken + "'");
+                pd.addDefaultValues(currentToken);
             }
+            catch (RepositoryException e) {
+                lexer.fail("Error adding default value for " + pd.getName() + " to " + currentToken);
+            }
             nextToken();
         } while (currentTokenEquals(Lexer.LIST_DELIMITER));
-        pd.setDefaultValues(defaultValues.toArray(new QValue[defaultValues.size()]));
     }
 
     /**
@@ -687,22 +597,23 @@
      * @param pd property definition builder
      * @throws ParseException if an error during parsing occurs
      */
-    private void doPropertyValueConstraints(QPropertyDefinitionBuilder pd)
+    private void doPropertyValueConstraints(AbstractPropertyDefinitionBuilder<T> pd)
             throws ParseException {
+
         if (!currentTokenEquals(Lexer.CONSTRAINT)) {
             return;
         }
-        List<QValueConstraint> constraints = new LinkedList<QValueConstraint>();
+
         do {
             nextToken();
             try {
-                constraints.add(pd.createValueConstraint(currentToken, resolver));
-            } catch (InvalidConstraintException e) {
-                lexer.fail("'" + currentToken + "' is not a valid constraint expression for a value of type " + pd.getRequiredType());
+                pd.addValueConstraint(currentToken);
             }
+            catch (RepositoryException e) {
+                lexer.fail("Error adding value constraint for " + pd.getName() + " to " + currentToken);
+            }
             nextToken();
         } while (currentTokenEquals(Lexer.LIST_DELIMITER));
-        pd.setValueConstraints(constraints.toArray(new QValueConstraint[constraints.size()]));
     }
 
     /**
@@ -712,14 +623,16 @@
      * @param ntd declaring nodetype definition builder
      * @throws ParseException if an error during parsing occurs
      */
-    private void doChildNodeDefinition(QNodeDefinitionBuilder nd,
-                                       QNodeTypeDefinitionBuilder ntd)
+    private void doChildNodeDefinition(AbstractNodeDefinitionBuilder<T> nd,
+                                       AbstractNodeTypeDefinitionBuilder<T> ntd)
             throws ParseException {
-        if (currentTokenEquals('*')) {
-            nd.setName(NameConstants.ANY_NAME);
-        } else {
-            nd.setName(toName(currentToken));
+
+        try {
+            nd.setName(currentToken);
         }
+        catch (RepositoryException e) {
+            lexer.fail("Error setting child name of " + nd.getName() + " to " + currentToken);
+        }
         nextToken();
         doChildNodeRequiredTypes(nd);
         doChildNodeDefaultType(nd);
@@ -732,18 +645,23 @@
      * @param nd node definition builder
      * @throws ParseException if an error during parsing occurs
      */
-    private void doChildNodeRequiredTypes(QNodeDefinitionBuilder nd)
+    private void doChildNodeRequiredTypes(AbstractNodeDefinitionBuilder<T> nd)
             throws ParseException {
+
         if (!currentTokenEquals(Lexer.BEGIN_TYPE)) {
             return;
         }
-        List<Name> types = new LinkedList<Name>();
+
         do {
             nextToken();
-            types.add(toName(currentToken));
+            try {
+                nd.addRequiredPrimaryType(currentToken);
+            }
+            catch (RepositoryException e) {
+                lexer.fail("Error setting required primary type of " + nd.getName() + " to " + currentToken);
+            }
             nextToken();
         } while (currentTokenEquals(Lexer.LIST_DELIMITER));
-        nd.setRequiredPrimaryTypes(types.toArray(new Name[types.size()]));
         nextToken();
     }
 
@@ -753,13 +671,19 @@
      * @param nd node definition builder
      * @throws ParseException if an error during parsing occurs
      */
-    private void doChildNodeDefaultType(QNodeDefinitionBuilder nd)
+    private void doChildNodeDefaultType(AbstractNodeDefinitionBuilder<T> nd)
             throws ParseException {
+
         if (!currentTokenEquals(Lexer.DEFAULT)) {
             return;
         }
         nextToken();
-        nd.setDefaultPrimaryType(toName(currentToken));
+        try {
+            nd.setDefaultPrimaryType(currentToken);
+        }
+        catch (RepositoryException e) {
+            lexer.fail("Error setting default primary type of " + nd.getName() + " to " + currentToken);
+        }
         nextToken();
     }
 
@@ -770,65 +694,40 @@
      * @param ntd declaring nodetype definition builder
      * @throws ParseException if an error during parsing occurs
      */
-    private void doChildNodeAttributes(QNodeDefinitionBuilder nd,
-                                       QNodeTypeDefinitionBuilder ntd)
+    private void doChildNodeAttributes(AbstractNodeDefinitionBuilder<T> nd,
+                                       AbstractNodeTypeDefinitionBuilder<T> ntd)
             throws ParseException {
-        while (currentTokenEquals(Lexer.NODE_ATTRIBUTE)) {
-            if (currentTokenEquals(Lexer.PRIMARY)) {
-                if (ntd.getPrimaryItemName() != null) {
-                    String name = null;
-                    try {
-                        name = resolver.getJCRName(ntd.getName());
-                    } catch (NamespaceException e) {
-                        // Should never happen, checked earlier
-                    }
-                    lexer.fail("More than one primary item specified in node type '" + name + "'");
+
+        try {
+            while (currentTokenEquals(Lexer.NODE_ATTRIBUTE)) {
+                if (currentTokenEquals(Lexer.PRIMARY)) {
+                    ntd.setPrimaryItemName(nd.getName());
+                } else if (currentTokenEquals(Lexer.AUTOCREATED)) {
+                    nd.setAutoCreated(true);
+                } else if (currentTokenEquals(Lexer.MANDATORY)) {
+                    nd.setMandatory(true);
+                } else if (currentTokenEquals(Lexer.PROTECTED)) {
+                    nd.setProtected(true);
+                } else if (currentTokenEquals(Lexer.SNS)) {
+                    nd.setAllowsSameNameSiblings(true);
+                } else if (currentTokenEquals(Lexer.COPY)) {
+                    nd.setOnParentVersion(OnParentVersionAction.COPY);
+                } else if (currentTokenEquals(Lexer.VERSION)) {
+                    nd.setOnParentVersion(OnParentVersionAction.VERSION);
+                } else if (currentTokenEquals(Lexer.INITIALIZE)) {
+                    nd.setOnParentVersion(OnParentVersionAction.INITIALIZE);
+                } else if (currentTokenEquals(Lexer.COMPUTE)) {
+                    nd.setOnParentVersion(OnParentVersionAction.COMPUTE);
+                } else if (currentTokenEquals(Lexer.IGNORE)) {
+                    nd.setOnParentVersion(OnParentVersionAction.IGNORE);
+                } else if (currentTokenEquals(Lexer.ABORT)) {
+                    nd.setOnParentVersion(OnParentVersionAction.ABORT);
                 }
-                ntd.setPrimaryItemName(nd.getName());
-            } else if (currentTokenEquals(Lexer.AUTOCREATED)) {
-                nd.setAutoCreated(true);
-            } else if (currentTokenEquals(Lexer.MANDATORY)) {
-                nd.setMandatory(true);
-            } else if (currentTokenEquals(Lexer.PROTECTED)) {
-                nd.setProtected(true);
-            } else if (currentTokenEquals(Lexer.SNS)) {
-                nd.setAllowsSameNameSiblings(true);
-            } else if (currentTokenEquals(Lexer.COPY)) {
-                nd.setOnParentVersion(OnParentVersionAction.COPY);
-            } else if (currentTokenEquals(Lexer.VERSION)) {
-                nd.setOnParentVersion(OnParentVersionAction.VERSION);
-            } else if (currentTokenEquals(Lexer.INITIALIZE)) {
-                nd.setOnParentVersion(OnParentVersionAction.INITIALIZE);
-            } else if (currentTokenEquals(Lexer.COMPUTE)) {
-                nd.setOnParentVersion(OnParentVersionAction.COMPUTE);
-            } else if (currentTokenEquals(Lexer.IGNORE)) {
-                nd.setOnParentVersion(OnParentVersionAction.IGNORE);
-            } else if (currentTokenEquals(Lexer.ABORT)) {
-                nd.setOnParentVersion(OnParentVersionAction.ABORT);
+                nextToken();
             }
-            nextToken();
         }
-    }
-
-    /**
-     * Converts the given string into a <code>Name</code> using the current
-     * namespace mapping.
-     *
-     * @param stringName jcr name
-     * @return A <code>Name</code> object.
-     * @throws ParseException if the conversion fails
-     */
-    private Name toName(String stringName) throws ParseException {
-        try {
-            Name n = resolver.getQName(stringName);
-            String decodedLocalName = ISO9075.decode(n.getLocalName());
-            return builder.createName(n.getNamespaceURI(), decodedLocalName);
-        } catch (NameException e) {
-            lexer.fail("Error while parsing '" + stringName + "'", e);
-            return null;
-        } catch (NamespaceException e) {
-            lexer.fail("Error while parsing '" + stringName + "'", e);
-            return null;
+        catch (RepositoryException e) {
+            lexer.fail("Error setting child node attribute of " + nd.getName() + " to " + currentToken);
         }
     }
 
Index: jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/cnd/ItemTemplatesBuilder.java
===================================================================
--- jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/cnd/ItemTemplatesBuilder.java	(revision 0)
+++ jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/cnd/ItemTemplatesBuilder.java	(revision 0)
@@ -0,0 +1,245 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.commons.cnd;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.jcr.NamespaceRegistry;
+import javax.jcr.RepositoryException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+import javax.jcr.ValueFormatException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.NodeDefinitionTemplate;
+import javax.jcr.nodetype.NodeTypeManager;
+import javax.jcr.nodetype.NodeTypeTemplate;
+import javax.jcr.nodetype.PropertyDefinitionTemplate;
+
+
+/**
+ * This implementation of {@link AbstractItemTypeDefinitionsBuilder} can be used with
+ * the {@link CompactNodeTypeDefReader} to produce node type definitions of type
+ * {@link NodeTypeTemplate} and a namespace map of type {@link NamespaceRegistry}.
+ * It uses {@link NodeTypeTemplateBuilder} for building node type definitions,
+ * {@link PropertyDefinitionTemplateBuilder} for building property definitions, and
+ * {@link NodeDefinitionTemplateBuilder} for building node definitions.
+ */
+public class ItemTemplatesBuilder extends
+        AbstractItemTypeDefinitionsBuilder<NodeTypeTemplate, NamespaceRegistry> {
+
+    private final NodeTypeManager nodeTypeManager;
+    private final ValueFactory valueFactory;
+    private NamespaceRegistry namespaceRegistry;
+
+    public ItemTemplatesBuilder(NodeTypeManager nodeTypeManager, ValueFactory valueFactory,
+            NamespaceRegistry namespaceRegistry) {
+
+        this.nodeTypeManager = nodeTypeManager;
+        this.valueFactory = valueFactory;
+        this.namespaceRegistry = namespaceRegistry;
+    }
+
+    @Override
+    public AbstractNodeTypeDefinitionBuilder<NodeTypeTemplate> newNodeTypeDefinitionBuilder()
+            throws UnsupportedRepositoryOperationException, RepositoryException {
+
+        return new NodeTypeTemplateBuilder();
+    }
+
+    @Override
+    public void setNamespaceMapping(NamespaceRegistry namespaceRegistry) {
+        this.namespaceRegistry = namespaceRegistry;
+    }
+
+    @Override
+    public NamespaceRegistry getNamespaceMapping() {
+        return namespaceRegistry;
+    }
+
+    @Override
+    public void setNamespace(String prefix, String uri) {
+        try {
+            namespaceRegistry.registerNamespace(prefix, uri);
+        }
+        catch (RepositoryException e) {
+            // ignore
+        }
+    }
+
+    public class NodeTypeTemplateBuilder extends AbstractNodeTypeDefinitionBuilder<NodeTypeTemplate> {
+        private final NodeTypeTemplate template;
+        private final List<String> supertypes = new ArrayList<String>();
+
+        public NodeTypeTemplateBuilder() throws UnsupportedRepositoryOperationException, RepositoryException {
+            super();
+            template = nodeTypeManager.createNodeTypeTemplate();
+        }
+
+        @Override
+        public AbstractNodeDefinitionBuilder<NodeTypeTemplate> newNodeDefinitionBuilder()
+                throws UnsupportedRepositoryOperationException, RepositoryException {
+
+            return new NodeDefinitionTemplateBuilder(this);
+        }
+
+        @Override
+        public AbstractPropertyDefinitionBuilder<NodeTypeTemplate> newPropertyDefinitionBuilder()
+                throws UnsupportedRepositoryOperationException, RepositoryException {
+
+            return new PropertyDefinitionTemplateBuilder(this);
+        }
+
+        @Override
+        public NodeTypeTemplate build() throws ConstraintViolationException {
+            template.setMixin(super.isMixin);
+            template.setOrderableChildNodes(super.isOrderable);
+            template.setAbstract(super.isAbstract);
+            template.setQueryable(super.queryable);
+            template.setDeclaredSuperTypeNames(supertypes.toArray(new String[supertypes.size()]));
+            return template;
+        }
+
+        @Override
+        public void setName(String name) throws RepositoryException {
+            super.setName(name);
+            template.setName(name);
+        }
+
+        @Override
+        public void addSupertype(String name) {
+            supertypes.add(name);
+        }
+
+        @Override
+        public void setPrimaryItemName(String name) throws ConstraintViolationException {
+            template.setPrimaryItemName(name);
+        }
+
+    }
+
+    public class PropertyDefinitionTemplateBuilder extends
+            AbstractPropertyDefinitionBuilder<NodeTypeTemplate> {
+
+        private final NodeTypeTemplateBuilder ntd;
+        private final PropertyDefinitionTemplate template;
+        private final List<Value> values = new ArrayList<Value>();
+        private final List<String> constraints = new ArrayList<String>();
+
+        public PropertyDefinitionTemplateBuilder(NodeTypeTemplateBuilder ntd)
+                throws UnsupportedRepositoryOperationException, RepositoryException {
+
+            super();
+            this.ntd = ntd;
+            template = nodeTypeManager.createPropertyDefinitionTemplate();
+        }
+
+        @Override
+        public void setName(String name) throws RepositoryException {
+            super.setName(name);
+            template.setName(name);
+        }
+
+        @Override
+        public void addDefaultValues(String value) throws ValueFormatException {
+            values.add(valueFactory.createValue(value, getRequiredType()));
+        }
+
+        @Override
+        public void addValueConstraint(String constraint) {
+            constraints.add(constraint);
+        }
+
+        @Override
+        public void setDeclaringNodeType(String name) {
+            // empty
+        }
+
+        @Override
+        public void build() throws IllegalStateException {
+            template.setAutoCreated(super.autocreate);
+            template.setMandatory(super.isMandatory);
+            template.setOnParentVersion(super.onParent);
+            template.setProtected(super.isProtected);
+            template.setRequiredType(super.requiredType);
+            template.setValueConstraints(constraints.toArray(new String[constraints.size()]));
+            template.setDefaultValues(values.toArray(new Value[values.size()]));
+            template.setMultiple(super.isMultiple);
+            template.setAvailableQueryOperators(super.queryOperators);
+            template.setFullTextSearchable(super.fullTextSearchable);
+            template.setQueryOrderable(super.queryOrderable);
+
+            @SuppressWarnings("unchecked")
+            List<PropertyDefinitionTemplate> templates = ntd.template.getPropertyDefinitionTemplates();
+            templates.add(template);
+        }
+
+    }
+
+    public class NodeDefinitionTemplateBuilder extends AbstractNodeDefinitionBuilder<NodeTypeTemplate> {
+        private final NodeTypeTemplateBuilder ntd;
+        private final NodeDefinitionTemplate template;
+        private final List<String> requiredPrimaryTypes = new ArrayList<String>();
+
+        public NodeDefinitionTemplateBuilder(NodeTypeTemplateBuilder ntd)
+                throws UnsupportedRepositoryOperationException, RepositoryException {
+
+            super();
+            this.ntd = ntd;
+            template = nodeTypeManager.createNodeDefinitionTemplate();
+        }
+
+        @Override
+        public void setName(String name) throws RepositoryException {
+            super.setName(name);
+            template.setName(name);
+        }
+
+        @Override
+        public void addRequiredPrimaryType(String name) {
+            requiredPrimaryTypes.add(name);
+        }
+
+        @Override
+        public void setDefaultPrimaryType(String name) throws ConstraintViolationException {
+            template.setDefaultPrimaryTypeName(name);
+        }
+
+        @Override
+        public void setDeclaringNodeType(String name) {
+            // empty
+        }
+
+        @Override
+        public void build() throws ConstraintViolationException {
+            template.setAutoCreated(super.autocreate);
+            template.setMandatory(super.isMandatory);
+            template.setOnParentVersion(super.onParent);
+            template.setProtected(super.isProtected);
+            template.setRequiredPrimaryTypeNames(requiredPrimaryTypes
+                    .toArray(new String[requiredPrimaryTypes.size()]));
+            template.setSameNameSiblings(super.allowSns);
+
+            @SuppressWarnings("unchecked")
+            List<NodeDefinitionTemplate> templates = ntd.template.getNodeDefinitionTemplates();
+            templates.add(template);
+        }
+
+    }
+
+}

Property changes on: jackrabbit-jcr-commons\src\main\java\org\apache\jackrabbit\commons\cnd\ItemTemplatesBuilder.java
___________________________________________________________________
Added: svn:eol-style
   + native

Index: jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/cnd/Lexer.java
===================================================================
--- jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/cnd/Lexer.java	(revision 0)
+++ jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/cnd/Lexer.java	(working copy)
@@ -14,11 +14,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.jackrabbit.spi.commons.nodetype.compact;
+package org.apache.jackrabbit.commons.cnd;
 
+import java.io.IOException;
+import java.io.Reader;
 import java.io.StreamTokenizer;
-import java.io.Reader;
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 
@@ -196,13 +196,17 @@
         return systemId;
     }
 
+    public int getLineNumber() {
+        return st.lineno();
+    }
+
     /**
      * Creates a failure exception including the current line number and systemid.
      * @param message message
      * @throws ParseException the created exception
      */
     public void fail(String message) throws ParseException {
-        throw new ParseException(message, st.lineno(), -1, systemId);
+        throw new ParseException(message, getLineNumber(), -1, systemId);
     }
 
     /**
@@ -212,7 +216,7 @@
      * @throws ParseException the created exception
      */
     public void fail(String message, Throwable e) throws ParseException {
-        throw new ParseException(message, e, st.lineno(), -1, systemId);
+        throw new ParseException(message, e, getLineNumber(), -1, systemId);
     }
 
     /**
@@ -221,6 +225,6 @@
      * @throws ParseException the created exception
      */
     public void fail(Throwable e) throws ParseException {
-        throw new ParseException(e, st.lineno(), -1, systemId);
+        throw new ParseException(e, getLineNumber(), -1, systemId);
     }
 }
Index: jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/cnd/ParseException.java
===================================================================
--- jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/cnd/ParseException.java	(revision 0)
+++ jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/cnd/ParseException.java	(working copy)
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.jackrabbit.spi.commons.nodetype.compact;
+package org.apache.jackrabbit.commons.cnd;
 
 /**
  * ParseException
@@ -36,7 +36,6 @@
      */
     private final String systemId;
 
-
     /**
      * Constructs a new instance of this class with <code>null</code> as its
      * detail message.
@@ -105,7 +104,8 @@
      * {@inheritDoc}
      */
     public String getMessage() {
-        StringBuffer b = new StringBuffer(super.getMessage());
+        String message = super.getMessage();
+        StringBuffer b = new StringBuffer(message == null ? "" : message);
         String delim = " (";
         if (systemId != null && !systemId.equals("")) {
             b.append(delim);
Index: jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/AbstractJCR2SPITest.java
===================================================================
--- jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/AbstractJCR2SPITest.java	(revision 808006)
+++ jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/AbstractJCR2SPITest.java	(working copy)
@@ -37,6 +37,7 @@
 
 import junit.framework.TestCase;
 
+import org.apache.jackrabbit.commons.cnd.ParseException;
 import org.apache.jackrabbit.jcr2spi.config.RepositoryConfig;
 import org.apache.jackrabbit.spi.Batch;
 import org.apache.jackrabbit.spi.ChildInfo;
@@ -64,7 +65,6 @@
 import org.apache.jackrabbit.spi.SessionInfo;
 import org.apache.jackrabbit.spi.Subscription;
 import org.apache.jackrabbit.spi.commons.AbstractReadableRepositoryService;
-import org.apache.jackrabbit.spi.commons.nodetype.compact.ParseException;
 import org.apache.jackrabbit.spi.commons.value.QValueFactoryImpl;
 
 /**
Index: jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AbstractReadableRepositoryService.java
===================================================================
--- jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AbstractReadableRepositoryService.java	(revision 808007)
+++ jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AbstractReadableRepositoryService.java	(working copy)
@@ -32,13 +32,13 @@
 import javax.jcr.RepositoryException;
 import javax.jcr.UnsupportedRepositoryOperationException;
 
+import org.apache.jackrabbit.commons.cnd.ParseException;
 import org.apache.jackrabbit.spi.ItemId;
 import org.apache.jackrabbit.spi.ItemInfo;
 import org.apache.jackrabbit.spi.NodeId;
 import org.apache.jackrabbit.spi.NodeInfo;
 import org.apache.jackrabbit.spi.QValue;
 import org.apache.jackrabbit.spi.SessionInfo;
-import org.apache.jackrabbit.spi.commons.nodetype.compact.ParseException;
 
 /**
  * <code>AbstractReadableRepositoryService</code> provides an abstract base
Index: jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AbstractRepositoryService.java
===================================================================
--- jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AbstractRepositoryService.java	(revision 808006)
+++ jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AbstractRepositoryService.java	(working copy)
@@ -48,6 +48,8 @@
 import javax.jcr.query.InvalidQueryException;
 import javax.jcr.version.VersionException;
 
+import org.apache.jackrabbit.commons.cnd.CompactNodeTypeDefReader;
+import org.apache.jackrabbit.commons.cnd.ParseException;
 import org.apache.jackrabbit.spi.Batch;
 import org.apache.jackrabbit.spi.EventBundle;
 import org.apache.jackrabbit.spi.EventFilter;
@@ -75,8 +77,7 @@
 import org.apache.jackrabbit.spi.commons.namespace.NamespaceMapping;
 import org.apache.jackrabbit.spi.commons.nodetype.NodeTypeStorage;
 import org.apache.jackrabbit.spi.commons.nodetype.NodeTypeStorageImpl;
-import org.apache.jackrabbit.spi.commons.nodetype.compact.CompactNodeTypeDefReader;
-import org.apache.jackrabbit.spi.commons.nodetype.compact.ParseException;
+import org.apache.jackrabbit.spi.commons.nodetype.compact.QItemDefinitionsBuilder;
 import org.apache.jackrabbit.spi.commons.value.QValueFactoryImpl;
 
 /**
@@ -205,9 +206,11 @@
             this.namespaces.setMapping(entry.getKey(), entry.getValue());
         }
 
-        CompactNodeTypeDefReader reader;
+        CompactNodeTypeDefReader<QNodeTypeDefinition, NamespaceMapping> reader;
         try {
-            reader = new CompactNodeTypeDefReader(cnd, "", this.namespaces);
+            reader = new CompactNodeTypeDefReader<QNodeTypeDefinition, NamespaceMapping>(cnd, "",
+                    this.namespaces, new QItemDefinitionsBuilder());
+
             List<QNodeTypeDefinition> ntds = reader.getNodeTypeDefinitions();
             nodeTypeDefs.registerNodeTypes(ntds.toArray(new QNodeTypeDefinition[ntds.size()]), true);
         }
Index: jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefReader.java
===================================================================
--- jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefReader.java	(revision 812902)
+++ jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefReader.java	(working copy)
@@ -1,883 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.jackrabbit.spi.commons.nodetype.compact;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-
-import javax.jcr.NamespaceException;
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.ValueFormatException;
-import javax.jcr.nodetype.NodeTypeDefinition;
-import javax.jcr.query.qom.QueryObjectModelConstants;
-import javax.jcr.version.OnParentVersionAction;
-
-import org.apache.jackrabbit.spi.Name;
-import org.apache.jackrabbit.spi.QNodeDefinition;
-import org.apache.jackrabbit.spi.QNodeTypeDefinition;
-import org.apache.jackrabbit.spi.QPropertyDefinition;
-import org.apache.jackrabbit.spi.QValue;
-import org.apache.jackrabbit.spi.QValueConstraint;
-import org.apache.jackrabbit.spi.commons.conversion.DefaultNamePathResolver;
-import org.apache.jackrabbit.spi.commons.conversion.NameException;
-import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
-import org.apache.jackrabbit.spi.commons.name.NameConstants;
-import org.apache.jackrabbit.spi.commons.namespace.NamespaceMapping;
-import org.apache.jackrabbit.spi.commons.nodetype.InvalidConstraintException;
-import org.apache.jackrabbit.spi.commons.nodetype.NodeTypeDefinitionFactory;
-import org.apache.jackrabbit.spi.commons.nodetype.compact.QNodeTypeDefinitionsBuilder.QNodeDefinitionBuilder;
-import org.apache.jackrabbit.spi.commons.nodetype.compact.QNodeTypeDefinitionsBuilder.QNodeTypeDefinitionBuilder;
-import org.apache.jackrabbit.spi.commons.nodetype.compact.QNodeTypeDefinitionsBuilder.QPropertyDefinitionBuilder;
-import org.apache.jackrabbit.spi.commons.query.qom.Operator;
-import org.apache.jackrabbit.util.ISO9075;
-
-/**
- * CompactNodeTypeDefReader. Parses node type definitions written in the compact
- * node type definition format and provides a list of QNodeTypeDefinition
- * objects that can then be used to register node types.
- *
- * <p/>
- * The EBNF grammar of the compact node type definition:<br>
- * <pre>
- * Cnd ::= {NamespaceMapping | NodeTypeDef}
- * NamespaceMapping ::= '<' Prefix '=' Uri '>'
- * Prefix ::= String
- * Uri ::= String
- * NodeTypeDef ::= NodeTypeName [Supertypes]
- *                 [NodeTypeAttribute {NodeTypeAttribute}]
- *                 {PropertyDef | ChildNodeDef}
- * NodeTypeName ::= '[' String ']'
- * Supertypes ::= '>' (StringList | '?')
- * NodeTypeAttribute ::= Orderable | Mixin | Abstract | Query |
- *                       PrimaryItem
- * Orderable ::= ('orderable' | 'ord' | 'o') ['?']
- * Mixin ::= ('mixin' | 'mix' | 'm') ['?']
- * Abstract ::= ('abstract' | 'abs' | 'a') ['?']
- * Query ::= ('noquery' | 'nq') | ('query' | 'q' )
- * PrimaryItem ::= ('primaryitem'| '!')(String | '?')
- * PropertyDef ::= PropertyName [PropertyType] [DefaultValues]
- *                 [PropertyAttribute {PropertyAttribute}]
- *                 [ValueConstraints]
- * PropertyName ::= '-' String
- * PropertyType ::= '(' ('STRING' | 'BINARY' | 'LONG' | 'DOUBLE' |
- *                       'BOOLEAN' | 'DATE' | 'NAME' | 'PATH' |
- *                       'REFERENCE' | 'WEAKREFERENCE' |
- *                       'DECIMAL' | 'URI' | 'UNDEFINED' | '*' |
- *                       '?') ')'
- * DefaultValues ::= '=' (StringList | '?')
- * ValueConstraints ::= '<' (StringList | '?')
- * ChildNodeDef ::= NodeName [RequiredTypes] [DefaultType]
- *                  [NodeAttribute {NodeAttribute}]
- * NodeName ::= '+' String
- * RequiredTypes ::= '(' (StringList | '?') ')'
- * DefaultType ::= '=' (String | '?')
- * PropertyAttribute ::= Autocreated | Mandatory | Protected |
- *                       Opv | Multiple | QueryOps | NoFullText |
- *                       NoQueryOrder
- * NodeAttribute ::= Autocreated | Mandatory | Protected |
- *                   Opv | Sns
- * Autocreated ::= ('autocreated' | 'aut' | 'a' )['?']
- * Mandatory ::= ('mandatory' | 'man' | 'm') ['?']
- * Protected ::= ('protected' | 'pro' | 'p') ['?']
- * Opv ::= 'COPY' | 'VERSION' | 'INITIALIZE' | 'COMPUTE' |
- *         'IGNORE' | 'ABORT' | ('OPV' '?')
- * Multiple ::= ('multiple' | 'mul' | '*') ['?']
- * QueryOps ::= ('queryops' | 'qop')
- *              (('''Operator {','Operator}''') | '?')
- * Operator ::= '=' | '<>' | '<' | '<=' | '>' | '>=' | 'LIKE'
- * NoFullText ::= ('nofulltext' | 'nof') ['?']
- * NoQueryOrder ::= ('noqueryorder' | 'nqord') ['?']
- * Sns ::= ('sns' | '*') ['?']
- * StringList ::= String {',' String}
- * String ::= QuotedString | UnquotedString
- * QuotedString ::= SingleQuotedString | DoubleQuotedString
- * SingleQuotedString ::= ''' UnquotedString '''
- * DoubleQuotedString ::= '"' UnquotedString '"'
- * UnquotedString ::= XmlChar {XmlChar}
- * XmlChar ::= see 3.2.2 Local Names
- * </pre>
- */
-public class CompactNodeTypeDefReader {
-
-    /**
-     * Default namespace mappings
-     */
-    public static final NamespaceMapping NS_DEFAULTS;
-    static {
-        try {
-            NS_DEFAULTS = new NamespaceMapping();
-            NS_DEFAULTS.setMapping(Name.NS_EMPTY_PREFIX, Name.NS_DEFAULT_URI);
-            NS_DEFAULTS.setMapping(Name.NS_JCR_PREFIX, Name.NS_JCR_URI);
-            NS_DEFAULTS.setMapping(Name.NS_MIX_PREFIX, Name.NS_MIX_URI);
-            NS_DEFAULTS.setMapping(Name.NS_NT_PREFIX, Name.NS_NT_URI);
-            NS_DEFAULTS.setMapping(Name.NS_REP_PREFIX, Name.NS_REP_URI);
-        } catch (NamespaceException e) {
-            throw new InternalError(e.toString());
-        }
-    }
-
-    /**
-     * the list of parsed QNodeTypeDefinition
-     */
-    private final List<QNodeTypeDefinition> nodeTypeDefs
-            = new LinkedList<QNodeTypeDefinition>();
-
-    /**
-     * the current namespace mapping
-     */
-    private final NamespaceMapping nsMapping;
-
-    /**
-     * Name and Path resolver
-     */
-    private final NamePathResolver resolver;
-
-    /**
-     * the underlying lexer
-     */
-    private final Lexer lexer;
-
-    /**
-     * the current token
-     */
-    private String currentToken;
-
-    /**
-     * The builder for QNodeTypeDefinitions
-     */
-    private final QNodeTypeDefinitionsBuilder builder;
-
-    /**
-     * Convenience method that creates a new CND reader and parses the given
-     * file directly.
-     *
-     * @param file A CND file
-     * @return a new 'parsed' reader object
-     * @throws ParseException if an error occurs
-     * @throws IOException if an I/O error occurs.
-     */
-    public static CompactNodeTypeDefReader read(File file)
-            throws ParseException, IOException {
-        InputStream in = null;
-        Reader r = null;
-        try {
-            in = new FileInputStream(file);
-            r = new InputStreamReader(in, "utf8");
-            return new CompactNodeTypeDefReader(r, file.getPath());
-        } finally {
-            if (r != null) {
-                try {
-                    r.close();
-                } catch (IOException e) {
-                    // ignore
-                }
-            }
-            if (in != null) {
-                try {
-                    in.close();
-                } catch (IOException e) {
-                    // ignore
-                }
-            }
-        }
-    }
-
-
-    /**
-     * Creates a new CND reader and parses the given stream directly.
-     *
-     * @param r a reader to the CND
-     * @param systemId a informative id of the given stream
-     * @throws ParseException if an error occurs
-     */
-    public CompactNodeTypeDefReader(Reader r, String systemId)
-            throws ParseException {
-        this(r, systemId, null, null);
-    }
-
-    /**
-     * Creates a new CND reader and parses the given stream it directly.
-     * If <code>builder</code> is <code>null</code> the reader uses the
-     * default {@link QNodeTypeDefinitionsBuilderImpl}.
-     *
-     * @param r a reader to the CND
-     * @param systemId a informative id of the given stream
-     * @param builder build for creating new definitions or <code>null</code>
-     * @throws ParseException if an error occurs
-     */
-    public CompactNodeTypeDefReader(Reader r, String systemId,
-                                    QNodeTypeDefinitionsBuilder builder)
-            throws ParseException {
-        this(r, systemId, null, builder);
-    }
-
-    /**
-     * Creates a new CND reader and parses the given stream it directly.
-     *
-     * @param r a reader to the CND
-     * @param systemId a informative id of the given stream
-     * @param mapping default namespace mapping to use
-     * @throws ParseException if an error occurs
-     */
-    public CompactNodeTypeDefReader(Reader r, String systemId, NamespaceMapping mapping)
-            throws ParseException {
-        this(r, systemId, mapping, null);
-    }
-
-    /**
-     * Creates a new CND reader and parses the given stream it directly.
-     * If <code>builder</code> is <code>null</code> the reader uses the
-     * default {@link QNodeTypeDefinitionsBuilderImpl}.
-     *
-     * @param r a reader to the CND
-     * @param systemId a informative id of the given stream
-     * @param mapping default namespace mapping to use
-     * @param builder build for creating new definitions
-     * @throws ParseException if an error occurs
-     */
-    public CompactNodeTypeDefReader(Reader r, String systemId, NamespaceMapping mapping,
-            QNodeTypeDefinitionsBuilder builder) throws ParseException {
-
-        this.builder = builder == null
-                ? new QNodeTypeDefinitionsBuilderImpl()
-                : builder;
-        lexer = new Lexer(r, systemId);
-        this.nsMapping = mapping == null
-                ? new NamespaceMapping(NS_DEFAULTS)
-                : mapping;
-        this.resolver = new DefaultNamePathResolver(nsMapping);
-        nextToken();
-        parse();
-    }
-
-    /**
-     * Returns the previously assigned system id
-     * @return the system id
-     */
-    public String getSystemId() {
-        return lexer.getSystemId();
-    }
-
-    /**
-     * Returns the list of parsed QNodeTypeDefinition definitions.
-     *
-     * @return a collection of QNodeTypeDefinition objects
-     */
-    public List<QNodeTypeDefinition> getNodeTypeDefinitions() {
-        return nodeTypeDefs;
-    }
-
-    /**
-     * Convenience method that returns the list of parsed NodeTypeDefinition
-     * definitions, using the {@link NodeTypeDefinitionFactory}.
-     *
-     * @param session repository session used for converting the definitions.
-     * @return a collection of NodeTypeDefinition objects
-     * @throws RepositoryException if an error occurs
-     */
-    public List<NodeTypeDefinition> getNodeTypeDefinitions(Session session)
-            throws RepositoryException {
-        NodeTypeDefinitionFactory fac = new NodeTypeDefinitionFactory(session);
-        return fac.create(nodeTypeDefs);
-    }
-
-    /**
-     * Returns the namespace mapping.
-     *
-     * @return a NamespaceMapping object.
-     */
-    public NamespaceMapping getNamespaceMapping() {
-        return nsMapping;
-    }
-
-    /**
-     * Parses the definition
-     *
-     * @throws ParseException if an error during parsing occurs
-     */
-    private void parse() throws ParseException {
-        while (!currentTokenEquals(Lexer.EOF)) {
-            if (!doNameSpace()) {
-                break;
-            }
-        }
-        while (!currentTokenEquals(Lexer.EOF)) {
-            QNodeTypeDefinitionBuilder ntd = builder.newQNodeTypeDefinition();
-            ntd.setOrderableChildNodes(false);
-            ntd.setMixin(false);
-            ntd.setAbstract(false);
-            ntd.setQueryable(true);
-            ntd.setPrimaryItemName(null);
-            doNodeTypeName(ntd);
-            doSuperTypes(ntd);
-            doOptions(ntd);
-            doItemDefs(ntd);
-            nodeTypeDefs.add(ntd.build());
-        }
-    }
-
-
-
-    /**
-     * processes the namespace declaration
-     *
-     * @return <code>true</code> if a namespace was parsed
-     * @throws ParseException if an error during parsing occurs
-     */
-    private boolean doNameSpace() throws ParseException {
-        if (!currentTokenEquals('<')) {
-            return false;
-        }
-        nextToken();
-        String prefix = currentToken;
-        nextToken();
-        if (!currentTokenEquals('=')) {
-            lexer.fail("Missing = in namespace decl.");
-        }
-        nextToken();
-        String uri = currentToken;
-        nextToken();
-        if (!currentTokenEquals('>')) {
-            lexer.fail("Missing > in namespace decl.");
-        }
-        try {
-            nsMapping.setMapping(prefix, uri);
-        } catch (NamespaceException e) {
-            // ignore
-        }
-        nextToken();
-        return true;
-    }
-
-    /**
-     * processes the nodetype name
-     *
-     * @param ntd nodetype definition builder
-     * @throws ParseException if an error during parsing occurs
-     */
-    private void doNodeTypeName(QNodeTypeDefinitionBuilder ntd) throws ParseException {
-        if (!currentTokenEquals(Lexer.BEGIN_NODE_TYPE_NAME)) {
-            lexer.fail("Missing '" + Lexer.BEGIN_NODE_TYPE_NAME + "' delimiter for beginning of node type name");
-        }
-        nextToken();
-        ntd.setName(toName(currentToken));
-
-        nextToken();
-        if (!currentTokenEquals(Lexer.END_NODE_TYPE_NAME)) {
-            lexer.fail("Missing '" + Lexer.END_NODE_TYPE_NAME + "' delimiter for end of node type name, found " + currentToken);
-        }
-        nextToken();
-    }
-
-    /**
-     * processes the superclasses
-     *
-     * @param ntd nodetype definition builder
-     * @throws ParseException if an error during parsing occurs
-     */
-    private void doSuperTypes(QNodeTypeDefinitionBuilder ntd) throws ParseException {
-        Set<Name> supertypes = new HashSet<Name>();
-        if (currentTokenEquals(Lexer.EXTENDS))
-            do {
-                nextToken();
-                supertypes.add(toName(currentToken));
-                nextToken();
-            } while (currentTokenEquals(Lexer.LIST_DELIMITER));
-
-        ntd.setSupertypes(supertypes.toArray(new Name[supertypes.size()]));
-    }
-
-    /**
-     * processes the options
-     *
-     * @param ntd nodetype definition builder
-     * @throws ParseException if an error during parsing occurs
-     */
-    private void doOptions(QNodeTypeDefinitionBuilder ntd) throws ParseException {
-        boolean hasOption = true;
-        while (hasOption) {
-            if (currentTokenEquals(Lexer.ORDERABLE)) {
-                nextToken();
-                ntd.setOrderableChildNodes(true);
-            } else if (currentTokenEquals(Lexer.MIXIN)) {
-                nextToken();
-                ntd.setMixin(true);
-            } else if (currentTokenEquals(Lexer.ABSTRACT)) {
-                nextToken();
-                ntd.setAbstract(true);
-            } else if (currentTokenEquals(Lexer.NOQUERY)) {
-                nextToken();
-                ntd.setQueryable(false);
-            } else if (currentTokenEquals(Lexer.QUERY)) {
-                nextToken();
-                ntd.setQueryable(true);
-            } else if (currentTokenEquals(Lexer.PRIMARYITEM)) {
-                nextToken();
-                ntd.setPrimaryItemName(toName(currentToken));
-                nextToken();
-            } else {
-                hasOption = false;
-            }
-        }
-    }
-
-    /**
-     * processes the item definitions
-     *
-     * @param ntd nodetype definition builder
-     * @throws ParseException if an error during parsing occurs
-     */
-    private void doItemDefs(QNodeTypeDefinitionBuilder ntd) throws ParseException {
-        List<QPropertyDefinition> propertyDefinitions = new LinkedList<QPropertyDefinition>();
-        List<QNodeDefinition> nodeDefinitions = new LinkedList<QNodeDefinition>();
-        while (currentTokenEquals(Lexer.PROPERTY_DEFINITION) || currentTokenEquals(Lexer.CHILD_NODE_DEFINITION)) {
-            if (currentTokenEquals(Lexer.PROPERTY_DEFINITION)) {
-                QPropertyDefinitionBuilder pd = ntd.newQPropertyDefinition();
-
-                pd.setAutoCreated(false);
-                pd.setDeclaringNodeType(ntd.getName());
-                pd.setDefaultValues(null);
-                pd.setMandatory(false);
-                pd.setMultiple(false);
-                pd.setOnParentVersion(OnParentVersionAction.COPY);
-                pd.setProtected(false);
-                pd.setRequiredType(PropertyType.STRING);
-                pd.setValueConstraints(QValueConstraint.EMPTY_ARRAY);
-                pd.setFullTextSearchable(true);
-                pd.setQueryOrderable(true);
-                pd.setAvailableQueryOperators(Operator.getAllQueryOperators());
-
-                nextToken();
-                doPropertyDefinition(pd, ntd);
-                propertyDefinitions.add(pd.build());
-
-            } else if (currentTokenEquals(Lexer.CHILD_NODE_DEFINITION)) {
-                QNodeDefinitionBuilder nd = ntd.newQNodeDefinitionBuilder();
-
-                nd.setAllowsSameNameSiblings(false);
-                nd.setAutoCreated(false);
-                nd.setDeclaringNodeType(ntd.getName());
-                nd.setMandatory(false);
-                nd.setOnParentVersion(OnParentVersionAction.COPY);
-                nd.setProtected(false);
-                nd.setDefaultPrimaryType(null);
-                nd.setRequiredPrimaryTypes(new Name[]{NameConstants.NT_BASE});
-
-                nextToken();
-                doChildNodeDefinition(nd, ntd);
-                nodeDefinitions.add(nd.build());
-            }
-        }
-        ntd.setPropertyDefs(propertyDefinitions.toArray(new QPropertyDefinition[propertyDefinitions.size()]));
-        ntd.setChildNodeDefs(nodeDefinitions.toArray(new QNodeDefinition[nodeDefinitions.size()]));
-    }
-
-    /**
-     * processes the property definition
-     *
-     * @param pd property definition builder
-     * @param ntd declaring nodetype definition builder
-     * @throws ParseException if an error during parsing occurs
-     */
-    private void doPropertyDefinition(QPropertyDefinitionBuilder pd, QNodeTypeDefinitionBuilder ntd)
-            throws ParseException {
-        if (currentToken.equals("*")) {
-            pd.setName(NameConstants.ANY_NAME);
-        } else {
-            pd.setName(toName(currentToken));
-        }
-        nextToken();
-        doPropertyType(pd);
-        doPropertyDefaultValue(pd);
-        doPropertyAttributes(pd, ntd);
-        doPropertyValueConstraints(pd);
-    }
-
-    /**
-     * processes the property type
-     *
-     * @param pd property definition builder
-     * @throws ParseException if an error during parsing occurs
-     */
-    private void doPropertyType(QPropertyDefinitionBuilder pd) throws ParseException {
-        if (!currentTokenEquals(Lexer.BEGIN_TYPE)) {
-            return;
-        }
-        nextToken();
-        if (currentTokenEquals(Lexer.STRING)) {
-            pd.setRequiredType(PropertyType.STRING);
-        } else if (currentTokenEquals(Lexer.BINARY)) {
-            pd.setRequiredType(PropertyType.BINARY);
-        } else if (currentTokenEquals(Lexer.LONG)) {
-            pd.setRequiredType(PropertyType.LONG);
-        } else if (currentTokenEquals(Lexer.DECIMAL)) {
-            pd.setRequiredType(PropertyType.DECIMAL);
-        } else if (currentTokenEquals(Lexer.DOUBLE)) {
-            pd.setRequiredType(PropertyType.DOUBLE);
-        } else if (currentTokenEquals(Lexer.BOOLEAN)) {
-            pd.setRequiredType(PropertyType.BOOLEAN);
-        } else if (currentTokenEquals(Lexer.DATE)) {
-            pd.setRequiredType(PropertyType.DATE);
-        } else if (currentTokenEquals(Lexer.NAME)) {
-            pd.setRequiredType(PropertyType.NAME);
-        } else if (currentTokenEquals(Lexer.PATH)) {
-            pd.setRequiredType(PropertyType.PATH);
-        } else if (currentTokenEquals(Lexer.URI)) {
-            pd.setRequiredType(PropertyType.URI);
-        } else if (currentTokenEquals(Lexer.REFERENCE)) {
-            pd.setRequiredType(PropertyType.REFERENCE);
-        } else if (currentTokenEquals(Lexer.WEAKREFERENCE)) {
-            pd.setRequiredType(PropertyType.WEAKREFERENCE);
-        } else if (currentTokenEquals(Lexer.UNDEFINED)) {
-            pd.setRequiredType(PropertyType.UNDEFINED);
-        } else {
-            lexer.fail("Unkown property type '" + currentToken + "' specified");
-        }
-        nextToken();
-        if (!currentTokenEquals(Lexer.END_TYPE)) {
-            lexer.fail("Missing '" + Lexer.END_TYPE + "' delimiter for end of property type");
-        }
-        nextToken();
-    }
-
-    /**
-     * processes the property attributes
-     *
-     * @param pd property definition builder
-     * @param ntd declaring nodetype definition builder
-     * @throws ParseException if an error during parsing occurs
-     */
-    private void doPropertyAttributes(QPropertyDefinitionBuilder pd,
-                                      QNodeTypeDefinitionBuilder ntd)
-            throws ParseException {
-        while (currentTokenEquals(Lexer.PROP_ATTRIBUTE)) {
-            if (currentTokenEquals(Lexer.PRIMARY)) {
-                if (ntd.getPrimaryItemName() != null) {
-                    String name = null;
-                    try {
-                        name = resolver.getJCRName(ntd.getName());
-                    } catch (NamespaceException e) {
-                        // Should never happen, checked earlier
-                    }
-                    lexer.fail("More than one primary item specified in node type '" + name + "'");
-                }
-                ntd.setPrimaryItemName(pd.getName());
-            } else if (currentTokenEquals(Lexer.AUTOCREATED)) {
-                pd.setAutoCreated(true);
-            } else if (currentTokenEquals(Lexer.MANDATORY)) {
-                pd.setMandatory(true);
-            } else if (currentTokenEquals(Lexer.PROTECTED)) {
-                pd.setProtected(true);
-            } else if (currentTokenEquals(Lexer.MULTIPLE)) {
-                pd.setMultiple(true);
-            } else if (currentTokenEquals(Lexer.COPY)) {
-                pd.setOnParentVersion(OnParentVersionAction.COPY);
-            } else if (currentTokenEquals(Lexer.VERSION)) {
-                pd.setOnParentVersion(OnParentVersionAction.VERSION);
-            } else if (currentTokenEquals(Lexer.INITIALIZE)) {
-                pd.setOnParentVersion(OnParentVersionAction.INITIALIZE);
-            } else if (currentTokenEquals(Lexer.COMPUTE)) {
-                pd.setOnParentVersion(OnParentVersionAction.COMPUTE);
-            } else if (currentTokenEquals(Lexer.IGNORE)) {
-                pd.setOnParentVersion(OnParentVersionAction.IGNORE);
-            } else if (currentTokenEquals(Lexer.ABORT)) {
-                pd.setOnParentVersion(OnParentVersionAction.ABORT);
-            } else if (currentTokenEquals(Lexer.NOFULLTEXT)) {
-                pd.setFullTextSearchable(false);
-            } else if (currentTokenEquals(Lexer.NOQUERYORDER)) {
-                pd.setQueryOrderable(false);
-            } else if (currentTokenEquals(Lexer.QUERYOPS)) {
-                doPropertyQueryOperators(pd);
-            }
-            nextToken();
-        }
-    }
-
-    /**
-     * processes the property query operators
-     *
-     * @param pd the property definition builder
-     * @throws ParseException if an error occurs
-     */
-    private void doPropertyQueryOperators(QPropertyDefinitionBuilder pd)
-            throws ParseException {
-        if (!currentTokenEquals(Lexer.QUERYOPS)) {
-            return;
-        }
-        nextToken();
-
-        String[] ops = currentToken.split(",");
-        List<String> queryOps = new LinkedList<String>();
-        for (String op : ops) {
-            String s = op.trim();
-            if (s.equals(Lexer.QUEROPS_EQUAL)) {
-                queryOps.add(QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO);
-            } else if (s.equals(Lexer.QUEROPS_NOTEQUAL)) {
-                queryOps.add(QueryObjectModelConstants.JCR_OPERATOR_NOT_EQUAL_TO);
-            } else if (s.equals(Lexer.QUEROPS_LESSTHAN)) {
-                queryOps.add(QueryObjectModelConstants.JCR_OPERATOR_LESS_THAN);
-            } else if (s.equals(Lexer.QUEROPS_LESSTHANOREQUAL)) {
-                queryOps.add(QueryObjectModelConstants.JCR_OPERATOR_LESS_THAN_OR_EQUAL_TO);
-            } else if (s.equals(Lexer.QUEROPS_GREATERTHAN)) {
-                queryOps.add(QueryObjectModelConstants.JCR_OPERATOR_GREATER_THAN);
-            } else if (s.equals(Lexer.QUEROPS_GREATERTHANOREQUAL)) {
-                queryOps.add(QueryObjectModelConstants.JCR_OPERATOR_GREATER_THAN_OR_EQUAL_TO);
-            } else if (s.equals(Lexer.QUEROPS_LIKE)) {
-                queryOps.add(QueryObjectModelConstants.JCR_OPERATOR_LIKE);
-            } else {
-                lexer.fail("'" + s + "' is not a valid query operator");
-            }
-        }
-        pd.setAvailableQueryOperators(queryOps.toArray(new String[queryOps.size()]));
-    }
-
-    /**
-     * processes the property default values
-     *
-     * @param pd property definition builder
-     * @throws ParseException if an error during parsing occurs
-     */
-    private void doPropertyDefaultValue(QPropertyDefinitionBuilder pd)
-            throws ParseException {
-        if (!currentTokenEquals(Lexer.DEFAULT)) {
-            return;
-        }
-        List<QValue> defaultValues = new LinkedList<QValue>();
-        do {
-            nextToken();
-            try {
-                defaultValues.add(pd.createValue(currentToken, resolver));
-            } catch (ValueFormatException e) {
-                lexer.fail("'" + currentToken + "' is not a valid string representation of a value of type " + pd.getRequiredType());
-            } catch (RepositoryException e) {
-                lexer.fail("An error occured during value conversion of '" + currentToken + "'");
-            }
-            nextToken();
-        } while (currentTokenEquals(Lexer.LIST_DELIMITER));
-        pd.setDefaultValues(defaultValues.toArray(new QValue[defaultValues.size()]));
-    }
-
-    /**
-     * processes the property value constraints
-     *
-     * @param pd property definition builder
-     * @throws ParseException if an error during parsing occurs
-     */
-    private void doPropertyValueConstraints(QPropertyDefinitionBuilder pd)
-            throws ParseException {
-        if (!currentTokenEquals(Lexer.CONSTRAINT)) {
-            return;
-        }
-        List<QValueConstraint> constraints = new LinkedList<QValueConstraint>();
-        do {
-            nextToken();
-            try {
-                constraints.add(pd.createValueConstraint(currentToken, resolver));
-            } catch (InvalidConstraintException e) {
-                lexer.fail("'" + currentToken + "' is not a valid constraint expression for a value of type " + pd.getRequiredType());
-            }
-            nextToken();
-        } while (currentTokenEquals(Lexer.LIST_DELIMITER));
-        pd.setValueConstraints(constraints.toArray(new QValueConstraint[constraints.size()]));
-    }
-
-    /**
-     * processes the childnode definition
-     *
-     * @param nd node definition builder
-     * @param ntd declaring nodetype definition builder
-     * @throws ParseException if an error during parsing occurs
-     */
-    private void doChildNodeDefinition(QNodeDefinitionBuilder nd,
-                                       QNodeTypeDefinitionBuilder ntd)
-            throws ParseException {
-        if (currentTokenEquals('*')) {
-            nd.setName(NameConstants.ANY_NAME);
-        } else {
-            nd.setName(toName(currentToken));
-        }
-        nextToken();
-        doChildNodeRequiredTypes(nd);
-        doChildNodeDefaultType(nd);
-        doChildNodeAttributes(nd, ntd);
-    }
-
-    /**
-     * processes the childnode required types
-     *
-     * @param nd node definition builder
-     * @throws ParseException if an error during parsing occurs
-     */
-    private void doChildNodeRequiredTypes(QNodeDefinitionBuilder nd)
-            throws ParseException {
-        if (!currentTokenEquals(Lexer.BEGIN_TYPE)) {
-            return;
-        }
-        List<Name> types = new LinkedList<Name>();
-        do {
-            nextToken();
-            types.add(toName(currentToken));
-            nextToken();
-        } while (currentTokenEquals(Lexer.LIST_DELIMITER));
-        nd.setRequiredPrimaryTypes(types.toArray(new Name[types.size()]));
-        nextToken();
-    }
-
-    /**
-     * processes the childnode default types
-     *
-     * @param nd node definition builder
-     * @throws ParseException if an error during parsing occurs
-     */
-    private void doChildNodeDefaultType(QNodeDefinitionBuilder nd)
-            throws ParseException {
-        if (!currentTokenEquals(Lexer.DEFAULT)) {
-            return;
-        }
-        nextToken();
-        nd.setDefaultPrimaryType(toName(currentToken));
-        nextToken();
-    }
-
-    /**
-     * processes the childnode attributes
-     *
-     * @param nd node definition builder
-     * @param ntd declaring nodetype definition builder
-     * @throws ParseException if an error during parsing occurs
-     */
-    private void doChildNodeAttributes(QNodeDefinitionBuilder nd,
-                                       QNodeTypeDefinitionBuilder ntd)
-            throws ParseException {
-        while (currentTokenEquals(Lexer.NODE_ATTRIBUTE)) {
-            if (currentTokenEquals(Lexer.PRIMARY)) {
-                if (ntd.getPrimaryItemName() != null) {
-                    String name = null;
-                    try {
-                        name = resolver.getJCRName(ntd.getName());
-                    } catch (NamespaceException e) {
-                        // Should never happen, checked earlier
-                    }
-                    lexer.fail("More than one primary item specified in node type '" + name + "'");
-                }
-                ntd.setPrimaryItemName(nd.getName());
-            } else if (currentTokenEquals(Lexer.AUTOCREATED)) {
-                nd.setAutoCreated(true);
-            } else if (currentTokenEquals(Lexer.MANDATORY)) {
-                nd.setMandatory(true);
-            } else if (currentTokenEquals(Lexer.PROTECTED)) {
-                nd.setProtected(true);
-            } else if (currentTokenEquals(Lexer.SNS)) {
-                nd.setAllowsSameNameSiblings(true);
-            } else if (currentTokenEquals(Lexer.COPY)) {
-                nd.setOnParentVersion(OnParentVersionAction.COPY);
-            } else if (currentTokenEquals(Lexer.VERSION)) {
-                nd.setOnParentVersion(OnParentVersionAction.VERSION);
-            } else if (currentTokenEquals(Lexer.INITIALIZE)) {
-                nd.setOnParentVersion(OnParentVersionAction.INITIALIZE);
-            } else if (currentTokenEquals(Lexer.COMPUTE)) {
-                nd.setOnParentVersion(OnParentVersionAction.COMPUTE);
-            } else if (currentTokenEquals(Lexer.IGNORE)) {
-                nd.setOnParentVersion(OnParentVersionAction.IGNORE);
-            } else if (currentTokenEquals(Lexer.ABORT)) {
-                nd.setOnParentVersion(OnParentVersionAction.ABORT);
-            }
-            nextToken();
-        }
-    }
-
-    /**
-     * Converts the given string into a <code>Name</code> using the current
-     * namespace mapping.
-     *
-     * @param stringName jcr name
-     * @return A <code>Name</code> object.
-     * @throws ParseException if the conversion fails
-     */
-    private Name toName(String stringName) throws ParseException {
-        try {
-            Name n = resolver.getQName(stringName);
-            String decodedLocalName = ISO9075.decode(n.getLocalName());
-            return builder.createName(n.getNamespaceURI(), decodedLocalName);
-        } catch (NameException e) {
-            lexer.fail("Error while parsing '" + stringName + "'", e);
-            return null;
-        } catch (NamespaceException e) {
-            lexer.fail("Error while parsing '" + stringName + "'", e);
-            return null;
-        }
-    }
-
-    /**
-     * Gets the next token from the underlying lexer.
-     *
-     * @see Lexer#getNextToken()
-     * @throws ParseException if the lexer fails to get the next token.
-     */
-    private void nextToken() throws ParseException {
-        currentToken = lexer.getNextToken();
-    }
-
-    /**
-     * Checks if the {@link #currentToken} is semantically equal to the given
-     * argument ignoring the case.
-     *
-     * @param s the tokens to compare with
-     * @return <code>true</code> if equals; <code>false</code> otherwise.
-     */
-    private boolean currentTokenEquals(String[] s) {
-        for (String value : s) {
-            if (currentToken.equalsIgnoreCase(value)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Checks if the {@link #currentToken} is semantically equal to the given
-     * argument.
-     *
-     * @param c the tokens to compare with
-     * @return <code>true</code> if equals; <code>false</code> otherwise.
-     */
-    private boolean currentTokenEquals(char c) {
-        return currentToken.length() == 1 && currentToken.charAt(0) == c;
-    }
-
-    /**
-     * Checks if the {@link #currentToken} is semantically equal to the given
-     * argument.
-     *
-     * @param s the tokens to compare with
-     * @return <code>true</code> if equals; <code>false</code> otherwise.
-     */
-    private boolean currentTokenEquals(String s) {
-        return currentToken.equals(s);
-    }
-
-}
Index: jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefWriter.java
===================================================================
--- jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefWriter.java	(revision 808006)
+++ jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefWriter.java	(working copy)
@@ -36,6 +36,7 @@
 import javax.jcr.query.qom.QueryObjectModelConstants;
 import javax.jcr.version.OnParentVersionAction;
 
+import org.apache.jackrabbit.commons.cnd.Lexer;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.QNodeDefinition;
 import org.apache.jackrabbit.spi.QNodeTypeDefinition;
Index: jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/Lexer.java
===================================================================
--- jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/Lexer.java	(revision 808006)
+++ jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/Lexer.java	(working copy)
@@ -1,226 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.jackrabbit.spi.commons.nodetype.compact;
-
-import java.io.StreamTokenizer;
-import java.io.Reader;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-/**
- * Lexer of the CND definition.
- */
-public class Lexer {
-    public static final char SINGLE_QUOTE = '\'';
-    public static final char DOUBLE_QUOTE = '\"';
-    public static final char BEGIN_NODE_TYPE_NAME = '[';
-    public static final char END_NODE_TYPE_NAME = ']';
-    public static final char EXTENDS = '>';
-    public static final char LIST_DELIMITER = ',';
-    public static final char PROPERTY_DEFINITION = '-';
-    public static final char CHILD_NODE_DEFINITION = '+';
-    public static final char BEGIN_TYPE = '(';
-    public static final char END_TYPE = ')';
-    public static final char DEFAULT = '=';
-    public static final char CONSTRAINT = '<';
-
-    public static final String[] ORDERABLE = new String[] {"orderable", "ord", "o"};
-    public static final String[] MIXIN = new String[]{"mixin", "mix", "m"};
-    public static final String[] ABSTRACT = new String[]{"abstract", "abs", "a"};
-    public static final String[] NOQUERY = new String[]{"noquery", "nq"};
-    public static final String[] QUERY = new String[]{"query", "q"};
-    public static final String[] PRIMARYITEM = new String[]{"primaryitem", "!"};
-
-    public static final String[] PRIMARY = new String[]{"primary", "pri", "!"};
-    public static final String[] AUTOCREATED = new String[]{"autocreated", "aut", "a"};
-    public static final String[] MANDATORY = new String[]{"mandatory", "man", "m"};
-    public static final String[] PROTECTED = new String[]{"protected", "pro", "p"};
-    public static final String[] MULTIPLE = new String[]{"multiple", "mul", "*"};
-    public static final String[] SNS = new String[]{"sns", "*", "multiple"};
-    public static final String[] QUERYOPS = new String[]{"queryops", "qop"};
-    public static final String[] NOFULLTEXT = new String[]{"nofulltext", "nof"};
-    public static final String[] NOQUERYORDER = new String[]{"noqueryorder", "nqord"};
-
-    public static final String[] COPY = new String[]{"COPY"};
-    public static final String[] VERSION = new String[]{"VERSION"};
-    public static final String[] INITIALIZE = new String[]{"INITIALIZE"};
-    public static final String[] COMPUTE = new String[]{"COMPUTE"};
-    public static final String[] IGNORE = new String[]{"IGNORE"};
-    public static final String[] ABORT = new String[]{"ABORT"};
-
-    public static final String[] PROP_ATTRIBUTE;
-    public static final String[] NODE_ATTRIBUTE;
-    static {
-        ArrayList<String> attr = new ArrayList<String>();
-        attr.addAll(Arrays.asList(PRIMARY));
-        attr.addAll(Arrays.asList(AUTOCREATED));
-        attr.addAll(Arrays.asList(MANDATORY));
-        attr.addAll(Arrays.asList(PROTECTED));
-        attr.addAll(Arrays.asList(MULTIPLE));
-        attr.addAll(Arrays.asList(QUERYOPS));
-        attr.addAll(Arrays.asList(NOFULLTEXT));
-        attr.addAll(Arrays.asList(NOQUERYORDER));
-        attr.addAll(Arrays.asList(COPY));
-        attr.addAll(Arrays.asList(VERSION));
-        attr.addAll(Arrays.asList(INITIALIZE));
-        attr.addAll(Arrays.asList(COMPUTE));
-        attr.addAll(Arrays.asList(IGNORE));
-        attr.addAll(Arrays.asList(ABORT));
-        PROP_ATTRIBUTE = attr.toArray(new String[attr.size()]);
-        attr = new ArrayList<String>();
-        attr.addAll(Arrays.asList(PRIMARY));
-        attr.addAll(Arrays.asList(AUTOCREATED));
-        attr.addAll(Arrays.asList(MANDATORY));
-        attr.addAll(Arrays.asList(PROTECTED));
-        attr.addAll(Arrays.asList(SNS));
-        attr.addAll(Arrays.asList(COPY));
-        attr.addAll(Arrays.asList(VERSION));
-        attr.addAll(Arrays.asList(INITIALIZE));
-        attr.addAll(Arrays.asList(COMPUTE));
-        attr.addAll(Arrays.asList(IGNORE));
-        attr.addAll(Arrays.asList(ABORT));
-        NODE_ATTRIBUTE = attr.toArray(new String[attr.size()]);
-    }
-
-    public static final String QUEROPS_EQUAL = "=";
-    public static final String QUEROPS_NOTEQUAL = "<>";
-    public static final String QUEROPS_LESSTHAN = "<";
-    public static final String QUEROPS_LESSTHANOREQUAL = "<=";
-    public static final String QUEROPS_GREATERTHAN = ">";
-    public static final String QUEROPS_GREATERTHANOREQUAL = ">=";
-    public static final String QUEROPS_LIKE = "LIKE";
-
-    public static final String[] STRING = {"STRING"};
-    public static final String[] BINARY = {"BINARY"};
-    public static final String[] LONG = {"LONG"};
-    public static final String[] DOUBLE = {"DOUBLE"};
-    public static final String[] BOOLEAN = {"BOOLEAN"};
-    public static final String[] DATE = {"DATE"};
-    public static final String[] NAME = {"NAME"};
-    public static final String[] PATH = {"PATH"};
-    public static final String[] REFERENCE = {"REFERENCE"};
-    public static final String[] WEAKREFERENCE = {"WEAKREFERENCE"};
-    public static final String[] URI = {"URI"};
-    public static final String[] DECIMAL = {"DECIMAL"};
-
-    public static final String[] UNDEFINED = new String[]{"UNDEFINED", "*"};
-
-    public static final String EOF = "eof";
-
-    private final StreamTokenizer st;
-
-    private final String systemId;
-
-    /**
-     * Creates an unitialized lexer on top of the given reader.
-     * @param r the reader
-     * @param systemId informational systemid of the given stream
-     */
-    public Lexer(Reader r, String systemId) {
-        this.systemId = systemId;
-        st = new StreamTokenizer(r);
-
-        st.eolIsSignificant(false);
-
-        st.lowerCaseMode(false);
-
-        st.slashSlashComments(true);
-        st.slashStarComments(true);
-
-        st.wordChars('a', 'z');
-        st.wordChars('A', 'Z');
-        st.wordChars(':', ':');
-        st.wordChars('_', '_');
-
-        st.quoteChar(SINGLE_QUOTE);
-        st.quoteChar(DOUBLE_QUOTE);
-
-        st.ordinaryChar(BEGIN_NODE_TYPE_NAME);
-        st.ordinaryChar(END_NODE_TYPE_NAME);
-        st.ordinaryChar(EXTENDS);
-        st.ordinaryChar(LIST_DELIMITER);
-        st.ordinaryChar(PROPERTY_DEFINITION);
-        st.ordinaryChar(CHILD_NODE_DEFINITION);
-        st.ordinaryChar(BEGIN_TYPE);
-        st.ordinaryChar(END_TYPE);
-        st.ordinaryChar(DEFAULT);
-        st.ordinaryChar(CONSTRAINT);
-    }
-
-    /**
-     * getNextToken
-     *
-     * @return the next token
-     * @throws ParseException if an error during parsing occurs
-     */
-    public String getNextToken() throws ParseException {
-        try {
-            int tokenType = st.nextToken();
-            if (tokenType == StreamTokenizer.TT_EOF) {
-                return EOF;
-            } else if (tokenType == StreamTokenizer.TT_WORD
-                    || tokenType == SINGLE_QUOTE
-                    || tokenType == DOUBLE_QUOTE) {
-                return st.sval;
-            } else if (tokenType == StreamTokenizer.TT_NUMBER) {
-                return String.valueOf(st.nval);
-            } else {
-                return new String(new char[] {(char) tokenType});
-            }
-        } catch (IOException e) {
-            fail("IOException while attempting to read input stream", e);
-            return null;
-        }
-    }
-
-    /**
-     * Returns the system id
-     * @return the system id
-     */
-    public String getSystemId() {
-        return systemId;
-    }
-
-    /**
-     * Creates a failure exception including the current line number and systemid.
-     * @param message message
-     * @throws ParseException the created exception
-     */
-    public void fail(String message) throws ParseException {
-        throw new ParseException(message, st.lineno(), -1, systemId);
-    }
-
-    /**
-     * Creates a failure exception including the current line number and systemid.
-     * @param message message
-     * @param e root cause
-     * @throws ParseException the created exception
-     */
-    public void fail(String message, Throwable e) throws ParseException {
-        throw new ParseException(message, e, st.lineno(), -1, systemId);
-    }
-
-    /**
-     * Creates a failure exception including the current line number and systemid.
-     * @param e root cause
-     * @throws ParseException the created exception
-     */
-    public void fail(Throwable e) throws ParseException {
-        throw new ParseException(e, st.lineno(), -1, systemId);
-    }
-}
Index: jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/ParseException.java
===================================================================
--- jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/ParseException.java	(revision 808006)
+++ jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/ParseException.java	(working copy)
@@ -1,140 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.jackrabbit.spi.commons.nodetype.compact;
-
-/**
- * ParseException
- */
-public class ParseException extends Exception {
-
-    /**
-     * the line number where the error occurred
-     */
-    private final int lineNumber;
-
-    /**
-     * the column number where the error occurred
-     */
-    private final int colNumber;
-
-    /**
-     * the systemid of the source that produced the error
-     */
-    private final String systemId;
-
-
-    /**
-     * Constructs a new instance of this class with <code>null</code> as its
-     * detail message.
-     * @param lineNumber line number
-     * @param colNumber columns number
-     * @param systemId system id
-     */
-    public ParseException(int lineNumber, int colNumber, String systemId) {
-        super();
-        this.lineNumber = lineNumber;
-        this.colNumber = colNumber;
-        this.systemId = systemId;
-    }
-
-    /**
-     * Constructs a new instance of this class with the specified detail
-     * message.
-     *
-     * @param message the detail message. The detail message is saved for
-     *                later retrieval by the {@link #getMessage()} method.
-     * @param lineNumber line number
-     * @param colNumber columns number
-     * @param systemId system id
-     */
-    public ParseException(String message, int lineNumber, int colNumber, String systemId) {
-        super(message);
-        this.lineNumber = lineNumber;
-        this.colNumber = colNumber;
-        this.systemId = systemId;
-    }
-
-    /**
-     * Constructs a new instance of this class with the specified detail
-     * message and root cause.
-     *
-     * @param message   the detail message. The detail message is saved for
-     *                  later retrieval by the {@link #getMessage()} method.
-     * @param lineNumber line number
-     * @param colNumber columns number
-     * @param systemId system id
-     * @param rootCause root failure cause
-     */
-    public ParseException(String message, Throwable rootCause, int lineNumber, int colNumber, String systemId) {
-        super(message, rootCause);
-        this.lineNumber = lineNumber;
-        this.colNumber = colNumber;
-        this.systemId = systemId;
-    }
-
-    /**
-     * Constructs a new instance of this class with the specified root cause.
-     *
-     * @param lineNumber line number
-     * @param colNumber columns number
-     * @param systemId system id
-     * @param rootCause root failure cause
-     */
-    public ParseException(Throwable rootCause, int lineNumber, int colNumber, String systemId) {
-        super(rootCause);
-        this.lineNumber = lineNumber;
-        this.colNumber = colNumber;
-        this.systemId = systemId;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getMessage() {
-        StringBuffer b = new StringBuffer(super.getMessage());
-        String delim = " (";
-        if (systemId != null && !systemId.equals("")) {
-            b.append(delim);
-            b.append(systemId);
-            delim = ", ";
-        }
-        if (lineNumber >= 0) {
-            b.append(delim);
-            b.append("line ");
-            b.append(lineNumber);
-            delim = ", ";
-        }
-        if (colNumber >= 0) {
-            b.append(delim);
-            b.append("col ");
-            b.append(colNumber);
-            delim = ", ";
-        }
-        if (delim.equals(", ")) {
-            b.append(")");
-        }
-        return b.toString();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String toString() {
-        return super.toString(); // + " (" + systemId + ", line " + lineNumber +", col " + colNumber +")";
-    }
-
-}
Index: jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QItemDefinitionsBuilder.java
===================================================================
--- jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QItemDefinitionsBuilder.java	(revision 808006)
+++ jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QItemDefinitionsBuilder.java	(working copy)
@@ -16,9 +16,14 @@
  */
 package org.apache.jackrabbit.spi.commons.nodetype.compact;
 
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.jcr.NamespaceException;
 import javax.jcr.RepositoryException;
-import javax.jcr.ValueFormatException;
 
+import org.apache.jackrabbit.commons.cnd.AbstractItemTypeDefinitionsBuilder;
+import org.apache.jackrabbit.commons.cnd.CompactNodeTypeDefReader;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.NameFactory;
 import org.apache.jackrabbit.spi.QNodeDefinition;
@@ -29,117 +34,255 @@
 import org.apache.jackrabbit.spi.commons.QNodeDefinitionImpl;
 import org.apache.jackrabbit.spi.commons.QNodeTypeDefinitionImpl;
 import org.apache.jackrabbit.spi.commons.QPropertyDefinitionImpl;
+import org.apache.jackrabbit.spi.commons.conversion.DefaultNamePathResolver;
+import org.apache.jackrabbit.spi.commons.conversion.IllegalNameException;
 import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
+import org.apache.jackrabbit.spi.commons.name.NameConstants;
 import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
+import org.apache.jackrabbit.spi.commons.namespace.NamespaceMapping;
 import org.apache.jackrabbit.spi.commons.nodetype.InvalidConstraintException;
 import org.apache.jackrabbit.spi.commons.nodetype.constraint.ValueConstraint;
+import org.apache.jackrabbit.spi.commons.query.qom.Operator;
 import org.apache.jackrabbit.spi.commons.value.QValueFactoryImpl;
 import org.apache.jackrabbit.spi.commons.value.ValueFormat;
+import org.apache.jackrabbit.util.ISO9075;
 
 /**
- * Default implementations of a {@link QNodeTypeDefinitionsBuilder}. This implementations uses
- * {@link QNodeTypeDefinitionBuilderImpl} for building node type definitions,
- * {@link QPropertyDefinitionBuilderImpl} for building property definitions, and
- * {@link QNodeDefinitionBuilderImpl} for building node definitions. It further uses
+ * This implementation of {@link AbstractItemTypeDefinitionsBuilder} can be used with
+ * the {@link CompactNodeTypeDefReader} to produce node type definitions of type
+ * {@link QNodeTypeDefinition} and a namespace map of type {@link NamespaceMapping}.
+ * It uses {@link QNodeTypeDefinitionBuilder} for building node type definitions,
+ * {@link QPropertyDefinitionBuilder} for building property definitions, and
+ * {@link QNodeDefinitionBuilder} for building node definitions. It further uses
  * {@link NameFactoryImpl} for creating <code>Name</code>s and {@link QValueFactoryImpl} for
  * creating <code>QValue</code>s.
  */
-public class QNodeTypeDefinitionsBuilderImpl extends QNodeTypeDefinitionsBuilder {
+public class QItemDefinitionsBuilder extends
+        AbstractItemTypeDefinitionsBuilder<QNodeTypeDefinition, NamespaceMapping> {
 
     private static final NameFactory NAME_FACTORY = NameFactoryImpl.getInstance();
 
-    public QNodeTypeDefinitionBuilder newQNodeTypeDefinition() {
-        return new QNodeTypeDefinitionBuilderImpl();
+    /**
+     * Default namespace mappings
+     */
+    public static final NamespaceMapping NS_DEFAULTS;
+    static {
+        try {
+            NS_DEFAULTS = new NamespaceMapping();
+            NS_DEFAULTS.setMapping(Name.NS_EMPTY_PREFIX, Name.NS_DEFAULT_URI);
+            NS_DEFAULTS.setMapping(Name.NS_JCR_PREFIX, Name.NS_JCR_URI);
+            NS_DEFAULTS.setMapping(Name.NS_MIX_PREFIX, Name.NS_MIX_URI);
+            NS_DEFAULTS.setMapping(Name.NS_NT_PREFIX, Name.NS_NT_URI);
+            NS_DEFAULTS.setMapping(Name.NS_REP_PREFIX, Name.NS_REP_URI);
+        } catch (NamespaceException e) {
+            throw new InternalError(e.toString());
+        }
     }
 
-    public Name createName(String namespaceURI, String localName) {
-        return NAME_FACTORY.create(namespaceURI, localName);
+    private NamespaceMapping nsMappings = new NamespaceMapping(NS_DEFAULTS);
+    private NamePathResolver resolver = new DefaultNamePathResolver(nsMappings);
+
+    @Override
+    public AbstractNodeTypeDefinitionBuilder<QNodeTypeDefinition> newNodeTypeDefinitionBuilder() {
+        return new QNodeTypeDefinitionBuilder();
     }
 
-    /**
-     * Default implementation of a {@link QNodeTypeDefinitionBuilder}.
-     */
-    public class QNodeTypeDefinitionBuilderImpl extends QNodeTypeDefinitionBuilder {
+    @Override
+    public void setNamespaceMapping(NamespaceMapping nsMapping) {
+        this.nsMappings = nsMapping;
+        this.resolver = new DefaultNamePathResolver(nsMapping);
+    }
 
-        public QNodeDefinitionBuilder newQNodeDefinitionBuilder() {
-            return new QNodeDefinitionBuilderImpl();
+    @Override
+    public NamespaceMapping getNamespaceMapping() {
+        return nsMappings;
+    }
+
+    @Override
+    public void setNamespace(String prefix, String uri) {
+        try {
+            nsMappings.setMapping(prefix, uri);
         }
+        catch (NamespaceException e) {
+            // ignore
+        }
+    }
 
-        public QPropertyDefinitionBuilder newQPropertyDefinition() {
-            return new QPropertyDefinitionBuilderImpl();
+    public class QNodeTypeDefinitionBuilder extends AbstractNodeTypeDefinitionBuilder<QNodeTypeDefinition> {
+        private Name name;
+        private final List<Name> supertypes = new ArrayList<Name>();
+        private Name primaryItem;
+        private final List<QPropertyDefinition> propertyDefs = new ArrayList<QPropertyDefinition>();
+        private final List<QNodeDefinition> childNodeDefs = new ArrayList<QNodeDefinition>();
+
+        @Override
+        public AbstractNodeDefinitionBuilder<QNodeTypeDefinition> newNodeDefinitionBuilder() {
+            return new QNodeDefinitionBuilder(this);
         }
 
+        @Override
+        public AbstractPropertyDefinitionBuilder<QNodeTypeDefinition> newPropertyDefinitionBuilder() {
+            return new QPropertyDefinitionBuilder(this);
+        }
+
+        @Override
         public QNodeTypeDefinition build() {
             return new QNodeTypeDefinitionImpl(
-                    this.getName(),
-                    this.getSuperTypes(),
+                    name,
+                    supertypes.toArray(new Name[supertypes.size()]),
                     null,
-                    this.getMixin(),
-                    this.getAbstract(),
-                    this.getQueryable(),
-                    this.getOrderableChildNodes(),
-                    this.getPrimaryItemName(),
-                    this.getPropertyDefs(),
-                    this.getChildNodeDefs());
+                    super.isMixin,
+                    super.isAbstract,
+                    super.queryable,
+                    super.isOrderable,
+                    primaryItem,
+                    propertyDefs.toArray(new QPropertyDefinition[propertyDefs.size()]),
+                    childNodeDefs.toArray(new QNodeDefinition[childNodeDefs.size()]));
         }
 
+        @Override
+        public void setName(String name) throws RepositoryException {
+            super.setName(name);
+            this.name = toName(name);
+        }
+
+        @Override
+        public void addSupertype(String name) throws IllegalNameException, NamespaceException {
+            supertypes.add(toName(name));
+        }
+
+        @Override
+        public void setPrimaryItemName(String name) throws IllegalNameException, NamespaceException {
+            primaryItem = toName(name);
+        }
+
     }
 
-    /**
-     * Default implementation of a {@link QPropertyDefinitionBuilder}.
-     */
-    public class QPropertyDefinitionBuilderImpl extends QPropertyDefinitionBuilder {
+    public class QPropertyDefinitionBuilder extends AbstractPropertyDefinitionBuilder<QNodeTypeDefinition> {
+        private Name name;
+        private final QNodeTypeDefinitionBuilder ntd;
+        private final List<QValue> values = new ArrayList<QValue>();
+        private final List<QValueConstraint> constraints = new ArrayList<QValueConstraint>();
+        private Name declaringType;
 
-        public QValue createValue(String value, NamePathResolver resolver)
-                throws ValueFormatException, RepositoryException {
+        public QPropertyDefinitionBuilder(QNodeTypeDefinitionBuilder ntd) {
+            super();
+            this.ntd = ntd;
+        }
 
-            return ValueFormat.getQValue(value, getRequiredType(), resolver, QValueFactoryImpl
-                    .getInstance());
+        @Override
+        public void setName(String name) throws RepositoryException {
+            super.setName(name);
+            if ("*".equals(name)) {
+                this.name = NameConstants.ANY_NAME;
+            }
+            else {
+                this.name = toName(name);
+            }
         }
 
-        public QValueConstraint createValueConstraint(String constraint, NamePathResolver resolver)
-                throws InvalidConstraintException {
+        @Override
+        public void addDefaultValues(String value) throws RepositoryException {
+            values.add(ValueFormat.getQValue(value, getRequiredType(), resolver, QValueFactoryImpl.getInstance()));
+        }
 
-            return ValueConstraint.create(getRequiredType(), constraint, resolver);
+        @Override
+        public void addValueConstraint(String constraint) throws InvalidConstraintException {
+            constraints.add(ValueConstraint.create(getRequiredType(), constraint, resolver));
         }
 
-        public QPropertyDefinition build() {
-            return new QPropertyDefinitionImpl(
-                    this.getName(),
-                    this.getDeclaringNodeType(),
-                    this.getAutoCreated(),
-                    this.getMandatory(),
-                    this.getOnParentVersion(),
-                    this.getProtected(),
-                    this.getDefaultValues(),
-                    this.getMultiple(),
-                    this.getRequiredType(),
-                    this.getValueConstraints(),
-                    this.getAvailableQueryOperators(),
-                    this.getFullTextSearchable(),
-                    this.getQueryOrderable());
+        @Override
+        public void setDeclaringNodeType(String name) throws IllegalNameException, NamespaceException {
+            this.declaringType = toName(name);
         }
 
+        @Override
+        public void build() throws IllegalStateException {
+            if (queryOperators == null) {
+                queryOperators = Operator.getAllQueryOperators();
+            }
+
+            ntd.propertyDefs.add(new QPropertyDefinitionImpl(
+                    name,
+                    declaringType,
+                    super.autocreate,
+                    super.isMandatory,
+                    super.onParent,
+                    super.isProtected,
+                    values.toArray(new QValue[values.size()]),
+                    super.isMultiple,
+                    super.requiredType,
+                    constraints.toArray(new QValueConstraint[constraints.size()]),
+                    super.queryOperators,
+                    super.fullTextSearchable,
+                    super.queryOrderable));
+        }
+
     }
 
-    /**
-     * Default implementation of a {@link QNodeDefinitionBuilder}.
-     */
-    public class QNodeDefinitionBuilderImpl extends QNodeDefinitionBuilder {
+    public class QNodeDefinitionBuilder extends AbstractNodeDefinitionBuilder<QNodeTypeDefinition> {
+        private final QNodeTypeDefinitionBuilder ntd;
+        private Name name;
+        private final List<Name> requiredPrimaryTypes = new ArrayList<Name>();
+        private Name defaultPrimaryType;
+        private Name declaringNodeType;
 
-        public QNodeDefinition build() {
-            return new QNodeDefinitionImpl(
-                    this.getName(),
-                    this.getDeclaringNodeType(),
-                    this.getAutoCreated(),
-                    this.getMandatory(),
-                    this.getOnParentVersion(),
-                    this.getProtected(),
-                    this.getDefaultPrimaryType(),
-                    this.getRequiredPrimaryTypes(),
-                    this.getAllowsSameNameSiblings());
+        public QNodeDefinitionBuilder(QNodeTypeDefinitionBuilder ntd) {
+            super();
+            this.ntd = ntd;
         }
 
+        @Override
+        public void setName(String name) throws RepositoryException {
+            super.setName(name);
+            if ("*".equals(name)) {
+                this.name = NameConstants.ANY_NAME;
+            }
+            else {
+                this.name = toName(name);
+            }
+        }
+
+        @Override
+        public void addRequiredPrimaryType(String name) throws IllegalNameException, NamespaceException {
+            requiredPrimaryTypes.add(toName(name));
+        }
+
+        @Override
+        public void setDefaultPrimaryType(String name) throws IllegalNameException, NamespaceException {
+            defaultPrimaryType = toName(name);
+        }
+
+        @Override
+        public void setDeclaringNodeType(String name) throws IllegalNameException, NamespaceException {
+            declaringNodeType = toName(name);
+        }
+
+        @Override
+        public void build() {
+            if (requiredPrimaryTypes.isEmpty()) {
+                requiredPrimaryTypes.add(NameConstants.NT_BASE);
+            }
+
+            ntd.childNodeDefs.add(new QNodeDefinitionImpl(
+                    name,
+                    declaringNodeType,
+                    super.autocreate,
+                    super.isMandatory,
+                    super.onParent,
+                    super.isProtected,
+                    defaultPrimaryType,
+                    requiredPrimaryTypes.toArray(new Name[requiredPrimaryTypes.size()]),
+                    super.allowSns));
+        }
+
     }
 
+
+    private Name toName(String name) throws IllegalNameException, NamespaceException {
+        Name n = resolver.getQName(name);
+        String decodedLocalName = ISO9075.decode(n.getLocalName());
+        return NAME_FACTORY.create(n.getNamespaceURI(), decodedLocalName);
+    }
+
 }
Index: jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QNodeTypeDefinitionsBuilder.java
===================================================================
--- jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QNodeTypeDefinitionsBuilder.java	(revision 808006)
+++ jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QNodeTypeDefinitionsBuilder.java	(working copy)
@@ -1,594 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.jackrabbit.spi.commons.nodetype.compact;
-
-import javax.jcr.RepositoryException;
-import javax.jcr.ValueFormatException;
-import javax.jcr.nodetype.PropertyDefinition;
-import javax.jcr.nodetype.ItemDefinition;
-import javax.jcr.nodetype.NodeTypeDefinition;
-
-import org.apache.jackrabbit.spi.Name;
-import org.apache.jackrabbit.spi.QItemDefinition;
-import org.apache.jackrabbit.spi.QNodeDefinition;
-import org.apache.jackrabbit.spi.QNodeTypeDefinition;
-import org.apache.jackrabbit.spi.QPropertyDefinition;
-import org.apache.jackrabbit.spi.QValue;
-import org.apache.jackrabbit.spi.QValueConstraint;
-import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
-import org.apache.jackrabbit.spi.commons.nodetype.InvalidConstraintException;
-import org.apache.jackrabbit.spi.commons.query.qom.Operator;
-
-/**
- * A builder for {@link QNodeTypeDefinition}s
- */
-public abstract class QNodeTypeDefinitionsBuilder {
-
-    /**
-     * @return a new instance of a builder for a {@link QNodeTypeDefinition}
-     */
-    public abstract QNodeTypeDefinitionBuilder newQNodeTypeDefinition();
-
-    /**
-     * Returns a <code>Name</code> with the given namespace URI and
-     * local part and validates the given parameters.
-     *
-     * @param namespaceURI namespace uri
-     * @param localName local part
-     * @return the created name
-     * @throws IllegalArgumentException if <code>namespaceURI</code> or
-     * <code>localName</code> is invalid.
-     */
-    public abstract Name createName(String namespaceURI, String localName)
-            throws IllegalArgumentException;
-
-    /**
-     * A builder for a {@link QNodeTypeDefinition}
-     */
-    public abstract class QNodeTypeDefinitionBuilder {
-        private Name name;
-        private Name[] supertypes;
-        private boolean isMixin;
-        private boolean isOrderable;
-        private Name primaryItemName;
-        private QPropertyDefinition[] propertyDefinitions;
-        private QNodeDefinition[] childNodeDefinitions;
-        private boolean isAbstract;
-        private boolean isQueryable = true;
-
-        /**
-         * Set the name of the node type definition being built
-         * @param name the name
-         * @see NodeTypeDefinition#getName()
-         */
-        public void setName(Name name) {
-            this.name = name;
-        }
-
-        /**
-         * @return the name of the node type definition being built or
-         * <code>null</code> if not set.
-         * @see NodeTypeDefinition#getName()
-         */
-        public Name getName() {
-            return name;
-        }
-
-        /**
-         * Specifies the supertypes of the node type definition being built
-         * @param supertypes the supertypes
-         * @see NodeTypeDefinition#getDeclaredSupertypeNames()
-         */
-        public void setSupertypes(Name[] supertypes) {
-            this.supertypes = supertypes;
-        }
-
-        /**
-         * Returns an array containing the names of the supertypes of the node
-         * type definition being built.
-         *
-         * @return an array of supertype names
-         * @see NodeTypeDefinition#getDeclaredSupertypeNames()
-         */
-        public Name[] getSuperTypes() {
-            return supertypes;
-        }
-
-        /**
-         * @param isMixin <code>true</code> if building a mixin node type
-         * definition; <code>false</code> otherwise.
-         * @see NodeTypeDefinition#isMixin()
-         */
-        public void setMixin(boolean isMixin) {
-            this.isMixin = isMixin;
-        }
-
-        /**
-         * @return <code>true</code> if building a mixin node type definition;
-         * <code>false</code> otherwise.
-         * @see NodeTypeDefinition#isMixin()
-         */
-        public boolean getMixin() {
-            return isMixin;
-        }
-
-        /**
-         * @param isOrderable <code>true</code> if building a node type having
-         * orderable child nodes; <code>false</code> otherwise.
-         * @see NodeTypeDefinition#hasOrderableChildNodes()
-         */
-        public void setOrderableChildNodes(boolean isOrderable) {
-            this.isOrderable = isOrderable;
-        }
-
-        /**
-         * @return <code>true</code> if building a node type having orderable
-         * child nodes; <code>false</code> otherwise.
-         * @see NodeTypeDefinition#hasOrderableChildNodes()
-         */
-        public boolean getOrderableChildNodes() {
-            return isOrderable;
-        }
-
-        /**
-         * @param primaryItemName the name of the primary item or
-         * <code>null</code> if not set.
-         * @see NodeTypeDefinition#getPrimaryItemName()
-         */
-        public void setPrimaryItemName(Name primaryItemName) {
-            this.primaryItemName = primaryItemName;
-        }
-
-        /**
-         * @return the name of the primary item or <code>null</code> if not set.
-         * @see NodeTypeDefinition#getPrimaryItemName()
-         */
-        public Name getPrimaryItemName() {
-            return primaryItemName;
-        }
-
-        /**
-         * @return <code>true</code> if the node type is abstract.
-         * @see NodeTypeDefinition#isAbstract()
-         */
-        public boolean getAbstract() {
-            return isAbstract;
-        }
-
-        /**
-         * @param isAbstract <code>true</code> if building a node type that is abstract.
-         * @see NodeTypeDefinition#isAbstract()
-         */
-        public void setAbstract(boolean isAbstract) {
-            this.isAbstract = isAbstract;
-        }
-
-        /**
-         * @return <code>true</code> if the node type is queryable
-         * @see NodeTypeDefinition#isQueryable()
-         */
-        public boolean getQueryable() {
-            return isQueryable;
-        }
-
-        /**
-         * @param queryable <code>true</code> if building a node type that is queryable
-         * @see NodeTypeDefinition#isQueryable()
-         */
-        public void setQueryable(boolean queryable) {
-            isQueryable = queryable;
-        }
-
-        /**
-         * @param propDefs an array containing the property definitions of the node type definition
-         *                being built.
-         * @see NodeTypeDefinition#getDeclaredPropertyDefinitions()
-         */
-        public void setPropertyDefs(QPropertyDefinition[] propDefs) {
-            propertyDefinitions = propDefs;
-        }
-
-        /**
-         * @return an array containing the property definitions of the node type definition being
-         *         built or <code>null</code> if not set.
-         * @see NodeTypeDefinition#getDeclaredPropertyDefinitions()
-         */
-        public QPropertyDefinition[] getPropertyDefs() {
-            return propertyDefinitions;
-        }
-
-        /**
-         * @param childDefs an array containing the child node definitions of the node type
-         *                definition being.
-         * @see NodeTypeDefinition#getDeclaredChildNodeDefinitions()
-         */
-        public void setChildNodeDefs(QNodeDefinition[] childDefs) {
-            childNodeDefinitions = childDefs;
-        }
-
-        /**
-         * @return an array containing the child node definitions of the node type definition being
-         *         built or <code>null</code> if not set.
-         * @see NodeTypeDefinition#getDeclaredChildNodeDefinitions()
-         */
-        public QNodeDefinition[] getChildNodeDefs() {
-            return childNodeDefinitions;
-        }
-
-        /**
-         * @return  a new instance of a builder for a {@link QNodeDefinition}.
-         */
-        public abstract QPropertyDefinitionBuilder newQPropertyDefinition();
-
-        /**
-         * @return  a new instance of a builder for a {@link QNodeDefinition}.
-         */
-        public abstract QNodeDefinitionBuilder newQNodeDefinitionBuilder();
-
-        /**
-         * Creates a new {@link QNodeTypeDefinition} instance based on the state of this builder.
-         *
-         * @return a new {@link QNodeTypeDefinition} instance.
-         * @throws IllegalStateException if the instance has not the necessary information to build
-         *                 the QNodeTypeDefinition instance.
-         */
-        public abstract QNodeTypeDefinition build() throws IllegalStateException;
-    }
-
-    /**
-     * A builder for a {@link QItemDefinition}
-     */
-    abstract class QItemDefinitionBuilder {
-        private Name name;
-        private Name declaringType;
-        private boolean isAutocreated;
-        private int onParentVersion;
-        private boolean isProtected;
-        private boolean isMandatory;
-
-        /**
-         * @param name  the name of the child item definition being build
-         * @see ItemDefinition#getName()
-         */
-        public void setName(Name name) {
-            this.name = name;
-        }
-
-        /**
-         * @return the name of the child item definition being build.
-         * @see ItemDefinition#getName()
-         */
-        public Name getName() {
-            return name;
-        }
-
-        /**
-         * @param type  the name of the declaring node type.
-         * @see ItemDefinition#getDeclaringNodeType()
-         */
-        public void setDeclaringNodeType(Name type) {
-            declaringType = type;
-        }
-
-        /**
-         * @return the name of the declaring node type.
-         * @see ItemDefinition#getDeclaringNodeType()
-         */
-        public Name getDeclaringNodeType() {
-            return declaringType;
-        }
-
-        /**
-         * @param autocreate <code>true</code> if building a 'autocreate' child item 
-         * definition, false otherwise.
-         * @see ItemDefinition#isAutoCreated()
-         */
-        public void setAutoCreated(boolean autocreate) {
-            isAutocreated = autocreate;
-        }
-
-        /**
-         * @return <code>true</code> if building a 'autocreate' child item
-         * definition, false otherwise.
-         * @see ItemDefinition#isAutoCreated()
-         */
-        public boolean getAutoCreated() {
-            return isAutocreated;
-        }
-
-        /**
-         * @param onParent the 'onParentVersion' attribute of the child item definition being built
-         * @see ItemDefinition#getOnParentVersion()
-         */
-        public void setOnParentVersion(int onParent) {
-            onParentVersion = onParent;
-        }
-
-        /**
-         * @return the 'onParentVersion' attribute of the child item definition being built
-         * @see ItemDefinition#getOnParentVersion()
-         */
-        public int getOnParentVersion() {
-            return onParentVersion;
-        }
-
-        /**
-         * @param isProtected <code>true</code> if building a 'protected' child
-         * item definition, false otherwise.
-         * @see ItemDefinition#isProtected()
-         */
-        public void setProtected(boolean isProtected) {
-            this.isProtected = isProtected;
-        }
-
-        /**
-         * @return <code>true</code> if building a 'protected' child item
-         * definition, false otherwise.
-         * @see ItemDefinition#isProtected()
-         */
-        public boolean getProtected() {
-            return isProtected;
-        }
-
-        /**
-         * @param isMandatory <code>true</code> if building a 'mandatory' child
-         * item definition, false otherwise.
-         * @see ItemDefinition#isMandatory()
-         */
-        public void setMandatory(boolean isMandatory) {
-            this.isMandatory = isMandatory;
-        }
-
-        /**
-         * @return <code>true</code> if building a 'mandatory' child item
-         * definition, false otherwise.
-         * @see ItemDefinition#isMandatory()
-         */
-        public boolean getMandatory() {
-            return isMandatory;
-        }
-    }
-
-    /**
-     * A builder for a {@link QPropertyDefinition}
-     * @see PropertyDefinition
-     */
-    public abstract class QPropertyDefinitionBuilder extends QItemDefinitionBuilder {
-
-        private int requiredType;
-        private QValueConstraint[] valueConstraints;
-        private QValue[] defaultValues;
-        private boolean isMultiple;
-        private boolean fullTextSearchable = true;
-        private boolean queryOrderable = true;
-        private String[] queryOperators = Operator.getAllQueryOperators();
-
-        /**
-         * @param type the required type of the property definition being built.
-         * @see PropertyDefinition#getRequiredType()
-         */
-        public void setRequiredType(int type) {
-            requiredType = type;
-        }
-
-        /**
-         * @return the required type of the property definition being built.
-         * @see PropertyDefinition#getRequiredType()
-         */
-        public int getRequiredType() {
-            return requiredType;
-        }
-
-        /**
-         * @param constraints array of value constraints of the property definition being built.
-         * @see PropertyDefinition#getValueConstraints()
-         */
-        public void setValueConstraints(QValueConstraint[] constraints) {
-            valueConstraints = constraints;
-        }
-
-        /**
-         * @return array of value constraints of the property definition being built.
-         * @see PropertyDefinition#getValueConstraints()
-         */
-        public QValueConstraint[] getValueConstraints() {
-            return valueConstraints;
-        }
-
-        /**
-         * @param values array of default values of the property definition being built.
-         * @see PropertyDefinition#getDefaultValues()
-         */
-        public void setDefaultValues(QValue[] values) {
-            defaultValues = values;
-        }
-
-        /**
-         * @return array of default values of the property definition being built or
-         *         <code>null</code> if no default values are defined.
-         * @see PropertyDefinition#getDefaultValues()
-         */
-        public QValue[] getDefaultValues() {
-            return defaultValues;
-        }
-
-        /**
-         * @param isMultiple true if building a 'multiple' property definition.
-         * @see PropertyDefinition#isMultiple()
-         */
-        public void setMultiple(boolean isMultiple) {
-            this.isMultiple = isMultiple;
-        }
-
-        /**
-         * @return true if building a 'multiple' property definition.
-         * @see PropertyDefinition#isMultiple()
-         */
-        public boolean getMultiple() {
-            return isMultiple;
-        }
-
-        /**
-         * @return <code>true</code> if the property is fulltext searchable
-         * @see PropertyDefinition#isFullTextSearchable()
-         */
-        public boolean getFullTextSearchable() {
-            return fullTextSearchable;
-        }
-
-        /**
-         * @param fullTextSearchable <code>true</code> if building a
-         * 'fulltext searchable' property definition
-         * @see PropertyDefinition#isFullTextSearchable()
-         */
-        public void setFullTextSearchable(boolean fullTextSearchable) {
-            this.fullTextSearchable = fullTextSearchable;
-        }
-
-        /**
-         * @return <code>true</code> if the property is orderable in a query
-         * @see PropertyDefinition#isQueryOrderable()
-         */
-        public boolean getQueryOrderable() {
-            return queryOrderable;
-        }
-
-        /**
-         * @param queryOrderable <code>true</code> if the property is orderable
-         *        in a query
-         * @see PropertyDefinition#isQueryOrderable()
-         */
-        public void setQueryOrderable(boolean queryOrderable) {
-            this.queryOrderable = queryOrderable;
-        }
-
-        /**
-         * @return the query operators of the property
-         * @see PropertyDefinition#getAvailableQueryOperators()
-         */
-        public String[] getAvailableQueryOperators() {
-            return queryOperators;
-        }
-
-        /**
-         * @param queryOperators the query operators of the property
-         * @see PropertyDefinition#getAvailableQueryOperators()
-         */
-        public void setAvailableQueryOperators(String[] queryOperators) {
-            this.queryOperators = queryOperators;
-        }
-
-        /**
-         * Validate the given <code>constraint</code> and resolve any prefixes.
-         *
-         * @param constraint the contraint
-         * @param resolver the resolver
-         * @return A syntactically valid value constrained which refers to
-         * internal names and paths representations only.
-         * @throws InvalidConstraintException if <code>constraint</code> cannot
-         * be converted to a valid value constrained.
-         */
-        public abstract QValueConstraint createValueConstraint(String constraint, NamePathResolver resolver)
-                throws InvalidConstraintException;
-
-        /**
-         * Create a new <code>QValue</code> for <code>value</code> of the type this instance
-         * represents using the given <code>resolver</code>.
-         *
-         * @param value the value
-         * @param resolver the resolver
-         * @return a new <code>QValue</code>.
-         * @throws ValueFormatException If the given <code>value</code> cannot be converted to the
-         *                 specified <code>type</code>.
-         * @throws RepositoryException If another error occurs.
-         */
-        public abstract QValue createValue(String value, NamePathResolver resolver)
-                throws ValueFormatException, RepositoryException;
-
-        /**
-         * Creates a new {@link QPropertyDefinition} instance based on the state of this builder.
-         *
-         * @return a new {@link QPropertyDefinition} instance.
-         * @throws IllegalStateException if the instance has not the necessary information to build
-         *                 the QPropertyDefinition instance.
-         */
-        public abstract QPropertyDefinition build() throws IllegalStateException;
-    }
-
-    /**
-     * A builder for a {@link QNodeDefinition}
-     */
-    public abstract class QNodeDefinitionBuilder extends QItemDefinitionBuilder {
-        private Name defaultPrimaryType;
-        private Name[] requiredPrimaryTypes;
-        private boolean allowsSameNameSiblings;
-
-        /**
-         * @param name the name of the default primary type of the node definition being built.
-         */
-        public void setDefaultPrimaryType(Name name) {
-            defaultPrimaryType = name;
-        }
-
-        /**
-         * @return the name of the default primary type of the node definition being built.
-         */
-        public Name getDefaultPrimaryType() {
-            return defaultPrimaryType;
-        }
-
-        /**
-         * @param names array of names of the required primary types of the node definition being
-         *                built.
-         */
-        public void setRequiredPrimaryTypes(Name[] names) {
-            requiredPrimaryTypes = names;
-        }
-
-        /**
-         * @return array of names of the required primary types of the node definition being built.
-         */
-        public Name[] getRequiredPrimaryTypes() {
-            return requiredPrimaryTypes;
-        }
-
-        /**
-         * @param allowSns true if building a node definition with same name siblings, false
-         *                otherwise.
-         */
-        public void setAllowsSameNameSiblings(boolean allowSns) {
-            allowsSameNameSiblings = allowSns;
-        }
-
-        /**
-         * @return true if building a node definition with same name siblings, false otherwise.
-         */
-        public boolean getAllowsSameNameSiblings() {
-            return allowsSameNameSiblings;
-        }
-
-        /**
-         * Creates a new {@link QNodeDefinition} instance based on the state of this builder.
-         *
-         * @return a new {@link QNodeDefinition} instance.
-         * @throws IllegalStateException if the instance has not the necessary information to build
-         *                 the QNodeDefinition instance.
-         */
-        public abstract QNodeDefinition build() throws IllegalStateException;
-    }
-
-}
Index: jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QNodeTypeDefinitionsBuilderImpl.java
===================================================================
--- jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QNodeTypeDefinitionsBuilderImpl.java	(revision 808006)
+++ jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QNodeTypeDefinitionsBuilderImpl.java	(working copy)
@@ -1,145 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.jackrabbit.spi.commons.nodetype.compact;
-
-import javax.jcr.RepositoryException;
-import javax.jcr.ValueFormatException;
-
-import org.apache.jackrabbit.spi.Name;
-import org.apache.jackrabbit.spi.NameFactory;
-import org.apache.jackrabbit.spi.QNodeDefinition;
-import org.apache.jackrabbit.spi.QNodeTypeDefinition;
-import org.apache.jackrabbit.spi.QPropertyDefinition;
-import org.apache.jackrabbit.spi.QValue;
-import org.apache.jackrabbit.spi.QValueConstraint;
-import org.apache.jackrabbit.spi.commons.QNodeDefinitionImpl;
-import org.apache.jackrabbit.spi.commons.QNodeTypeDefinitionImpl;
-import org.apache.jackrabbit.spi.commons.QPropertyDefinitionImpl;
-import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
-import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
-import org.apache.jackrabbit.spi.commons.nodetype.InvalidConstraintException;
-import org.apache.jackrabbit.spi.commons.nodetype.constraint.ValueConstraint;
-import org.apache.jackrabbit.spi.commons.value.QValueFactoryImpl;
-import org.apache.jackrabbit.spi.commons.value.ValueFormat;
-
-/**
- * Default implementations of a {@link QNodeTypeDefinitionsBuilder}. This implementations uses
- * {@link QNodeTypeDefinitionBuilderImpl} for building node type definitions,
- * {@link QPropertyDefinitionBuilderImpl} for building property definitions, and
- * {@link QNodeDefinitionBuilderImpl} for building node definitions. It further uses
- * {@link NameFactoryImpl} for creating <code>Name</code>s and {@link QValueFactoryImpl} for
- * creating <code>QValue</code>s.
- */
-public class QNodeTypeDefinitionsBuilderImpl extends QNodeTypeDefinitionsBuilder {
-
-    private static final NameFactory NAME_FACTORY = NameFactoryImpl.getInstance();
-
-    public QNodeTypeDefinitionBuilder newQNodeTypeDefinition() {
-        return new QNodeTypeDefinitionBuilderImpl();
-    }
-
-    public Name createName(String namespaceURI, String localName) {
-        return NAME_FACTORY.create(namespaceURI, localName);
-    }
-
-    /**
-     * Default implementation of a {@link QNodeTypeDefinitionBuilder}.
-     */
-    public class QNodeTypeDefinitionBuilderImpl extends QNodeTypeDefinitionBuilder {
-
-        public QNodeDefinitionBuilder newQNodeDefinitionBuilder() {
-            return new QNodeDefinitionBuilderImpl();
-        }
-
-        public QPropertyDefinitionBuilder newQPropertyDefinition() {
-            return new QPropertyDefinitionBuilderImpl();
-        }
-
-        public QNodeTypeDefinition build() {
-            return new QNodeTypeDefinitionImpl(
-                    this.getName(),
-                    this.getSuperTypes(),
-                    null,
-                    this.getMixin(),
-                    this.getAbstract(),
-                    this.getQueryable(),
-                    this.getOrderableChildNodes(),
-                    this.getPrimaryItemName(),
-                    this.getPropertyDefs(),
-                    this.getChildNodeDefs());
-        }
-
-    }
-
-    /**
-     * Default implementation of a {@link QPropertyDefinitionBuilder}.
-     */
-    public class QPropertyDefinitionBuilderImpl extends QPropertyDefinitionBuilder {
-
-        public QValue createValue(String value, NamePathResolver resolver)
-                throws ValueFormatException, RepositoryException {
-
-            return ValueFormat.getQValue(value, getRequiredType(), resolver, QValueFactoryImpl
-                    .getInstance());
-        }
-
-        public QValueConstraint createValueConstraint(String constraint, NamePathResolver resolver)
-                throws InvalidConstraintException {
-
-            return ValueConstraint.create(getRequiredType(), constraint, resolver);
-        }
-
-        public QPropertyDefinition build() {
-            return new QPropertyDefinitionImpl(
-                    this.getName(),
-                    this.getDeclaringNodeType(),
-                    this.getAutoCreated(),
-                    this.getMandatory(),
-                    this.getOnParentVersion(),
-                    this.getProtected(),
-                    this.getDefaultValues(),
-                    this.getMultiple(),
-                    this.getRequiredType(),
-                    this.getValueConstraints(),
-                    this.getAvailableQueryOperators(),
-                    this.getFullTextSearchable(),
-                    this.getQueryOrderable());
-        }
-
-    }
-
-    /**
-     * Default implementation of a {@link QNodeDefinitionBuilder}.
-     */
-    public class QNodeDefinitionBuilderImpl extends QNodeDefinitionBuilder {
-
-        public QNodeDefinition build() {
-            return new QNodeDefinitionImpl(
-                    this.getName(),
-                    this.getDeclaringNodeType(),
-                    this.getAutoCreated(),
-                    this.getMandatory(),
-                    this.getOnParentVersion(),
-                    this.getProtected(),
-                    this.getDefaultPrimaryType(),
-                    this.getRequiredPrimaryTypes(),
-                    this.getAllowsSameNameSiblings());
-        }
-
-    }
-
-}
Index: jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefTest.java
===================================================================
--- jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefTest.java	(revision 808006)
+++ jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefTest.java	(working copy)
@@ -23,14 +23,15 @@
 import java.io.StringWriter;
 import java.util.List;
 
+import junit.framework.TestCase;
+
+import org.apache.jackrabbit.commons.cnd.CompactNodeTypeDefReader;
 import org.apache.jackrabbit.spi.QNodeTypeDefinition;
 import org.apache.jackrabbit.spi.commons.conversion.DefaultNamePathResolver;
 import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
 import org.apache.jackrabbit.spi.commons.namespace.NamespaceMapping;
 import org.apache.jackrabbit.spi.commons.nodetype.NodeTypeDefDiff;
 
-import junit.framework.TestCase;
-
 public class CompactNodeTypeDefTest extends TestCase {
 
     private static final String TEST_FILE = "cnd-reader-test-input.cnd";
@@ -39,7 +40,9 @@
 
         // Read in node type def from test file
         Reader reader = new InputStreamReader(getClass().getClassLoader().getResourceAsStream(TEST_FILE));
-        CompactNodeTypeDefReader cndReader = new CompactNodeTypeDefReader(reader, TEST_FILE);
+        CompactNodeTypeDefReader<QNodeTypeDefinition, NamespaceMapping> cndReader =
+            new CompactNodeTypeDefReader<QNodeTypeDefinition, NamespaceMapping>(
+                reader, TEST_FILE, new QItemDefinitionsBuilder());
 
         List<QNodeTypeDefinition> ntdList1 = cndReader.getNodeTypeDefinitions();
         NamespaceMapping nsm = cndReader.getNamespaceMapping();
@@ -50,7 +53,8 @@
         CompactNodeTypeDefWriter.write(ntdList1, nsm, resolver, sw);
 
         // Rerun the reader on the product of the writer
-        cndReader = new CompactNodeTypeDefReader(new StringReader(sw.toString()), TEST_FILE);
+        cndReader = new CompactNodeTypeDefReader<QNodeTypeDefinition, NamespaceMapping>(
+                new StringReader(sw.toString()), TEST_FILE, new QItemDefinitionsBuilder());
 
         List<QNodeTypeDefinition> ntdList2 = cndReader.getNodeTypeDefinitions();
 
