Index: src/main/java/org/apache/jackrabbit/spi/commons/AbstractRepositoryService.java
===================================================================
--- src/main/java/org/apache/jackrabbit/spi/commons/AbstractRepositoryService.java	(revision 808006)
+++ src/main/java/org/apache/jackrabbit/spi/commons/AbstractRepositoryService.java	(working copy)
@@ -77,6 +77,7 @@
 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.QItemsTypeDefinitionsBuilderImpl;
 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 QItemsTypeDefinitionsBuilderImpl());
+
             List<QNodeTypeDefinition> ntds = reader.getNodeTypeDefinitions();
             nodeTypeDefs.registerNodeTypes(ntds.toArray(new QNodeTypeDefinition[ntds.size()]), true);
         }
Index: src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/AbstractItemTypeDefinitionsBuilder.java
===================================================================
--- src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/AbstractItemTypeDefinitionsBuilder.java	(revision 808006)
+++ src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/AbstractItemTypeDefinitionsBuilder.java	(working copy)
@@ -16,75 +16,29 @@
  */
 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 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;
+public abstract class AbstractItemTypeDefinitionsBuilder<T, N> {
+    public abstract AbstractNodeTypeDefinitionBuilder<T> newQNodeTypeDefinition();
 
-/**
- * A builder for {@link QNodeTypeDefinition}s
- */
-public abstract class QNodeTypeDefinitionsBuilder {
+    public abstract void setNamespaceMapping(N nsMapping);
+    public abstract N getNamespaceMapping();
+    public abstract void setNamespace(String prefix, String uri) throws ParseException;
 
-    /**
-     * @return a new instance of a builder for a {@link QNodeTypeDefinition}
-     */
-    public abstract QNodeTypeDefinitionBuilder newQNodeTypeDefinition();
+    public static abstract class AbstractNodeTypeDefinitionBuilder<T> {
+        protected String name;
+        protected boolean isMixin;
+        protected boolean isOrderable;
+        protected boolean isAbstract;
+        protected boolean queryable;
 
-    /**
-     * 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) {
+        public void setName(String name) throws ParseException {
             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() {
+        public String getName() {
             return name;
         }
 
@@ -93,186 +47,72 @@
          * @param supertypes the supertypes
          * @see NodeTypeDefinition#getDeclaredSupertypeNames()
          */
-        public void setSupertypes(Name[] supertypes) {
-            this.supertypes = supertypes;
-        }
+        public abstract void addSupertype(String name) throws ParseException;
 
         /**
-         * 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) {
+        public void setMixin(boolean isMixin) throws ParseException {
             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) {
+        public void setOrderableChildNodes(boolean isOrderable) throws ParseException {
             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;
-        }
+        public abstract void setPrimaryItemName(String name) throws ParseException;
 
         /**
-         * @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) {
+        public void setAbstract(boolean isAbstract) throws ParseException {
             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;
+        public void setQueryable(boolean queryable) throws ParseException {
+            this.queryable = 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;
-        }
+        public abstract AbstractPropertyDefinitionBuilder<T> newQPropertyDefinition();
 
-        /**
-         * @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;
-        }
+        public abstract AbstractNodeDefinitionBuilder<T> newQNodeDefinitionBuilder();
 
-        /**
-         * @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;
+        public abstract T build();
     }
 
-    /**
-     * 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;
+    public static abstract class AbstractItemDefinitionBuilder<T> {
+        protected String name;
+        protected boolean autocreate;
+        protected int onParent;
+        protected boolean isProtected;
+        protected boolean isMandatory;
 
         /**
          * @param name  the name of the child item definition being build
          * @see ItemDefinition#getName()
          */
-        public void setName(Name name) {
+        public void setName(String name) throws ParseException {
             this.name = name;
         }
 
-        /**
-         * @return the name of the child item definition being build.
-         * @see ItemDefinition#getName()
-         */
-        public Name getName() {
+        public String getName() {
             return name;
         }
 
@@ -280,315 +120,131 @@
          * @param type  the name of the declaring node type.
          * @see ItemDefinition#getDeclaringNodeType()
          */
-        public void setDeclaringNodeType(Name type) {
-            declaringType = type;
-        }
+        public abstract void setDeclaringNodeType(String name) throws ParseException;
 
         /**
-         * @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.
          * @see ItemDefinition#isAutoCreated()
          */
-        public void setAutoCreated(boolean autocreate) {
-            isAutocreated = autocreate;
+        public void setAutoCreated(boolean autocreate) throws ParseException {
+            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
          * @see ItemDefinition#getOnParentVersion()
          */
-        public void setOnParentVersion(int onParent) {
-            onParentVersion = onParent;
+        public void setOnParentVersion(int onParent) throws ParseException {
+            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.
          * @see ItemDefinition#isProtected()
          */
-        public void setProtected(boolean isProtected) {
+        public void setProtected(boolean isProtected) throws ParseException {
             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) {
+        public void setMandatory(boolean isMandatory) throws ParseException {
             this.isMandatory = isMandatory;
         }
 
-        /**
-         * @return <code>true</code> if building a 'mandatory' child item
-         * definition, false otherwise.
-         * @see ItemDefinition#isMandatory()
-         */
-        public boolean getMandatory() {
-            return isMandatory;
-        }
+        public abstract void build();
     }
 
-    /**
-     * A builder for a {@link QPropertyDefinition}
-     * @see PropertyDefinition
-     */
-    public abstract class QPropertyDefinitionBuilder extends QItemDefinitionBuilder {
+    public static abstract class AbstractPropertyDefinitionBuilder<T> extends AbstractItemDefinitionBuilder<T> {
+        protected int type;
+        protected boolean isMultiple;
+        protected boolean fullTextSearchable;
+        protected boolean queryOrderable;
+        protected String[] queryOperators;
 
-        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;
+        public void setRequiredType(int type) throws ParseException {
+            this.type = type;
         }
 
-        /**
-         * @return the required type of the property definition being built.
-         * @see PropertyDefinition#getRequiredType()
-         */
         public int getRequiredType() {
-            return requiredType;
+            return type;
         }
 
         /**
          * @param constraints array of value constraints of the property definition being built.
          * @see PropertyDefinition#getValueConstraints()
          */
-        public void setValueConstraints(QValueConstraint[] constraints) {
-            valueConstraints = constraints;
-        }
+        public abstract void addValueConstraint(String constraint) throws ParseException;
 
         /**
-         * @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;
-        }
+        public abstract void addDefaultValues(String value) throws ParseException;
 
-        /**
-         * @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) {
+        public void setMultiple(boolean isMultiple) throws ParseException {
             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) {
+        public void setFullTextSearchable(boolean fullTextSearchable) throws ParseException {
             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) {
+        public void setQueryOrderable(boolean queryOrderable) throws ParseException {
             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) {
+        public void setAvailableQueryOperators(String[] queryOperators) throws ParseException {
             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;
+    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.
          */
-        public void setDefaultPrimaryType(Name name) {
-            defaultPrimaryType = name;
-        }
+        public abstract void setDefaultPrimaryType(String name) throws ParseException;
 
         /**
-         * @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;
-        }
+        public abstract void addRequiredPrimaryType(String name) throws ParseException;
 
         /**
-         * @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;
+        public void setAllowsSameNameSiblings(boolean allowSns) throws ParseException {
+            this.allowSns = 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: src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefReader.java
===================================================================
--- src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefReader.java	(revision 812902)
+++ src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefReader.java	(working copy)
@@ -22,38 +22,18 @@
 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.spi.commons.nodetype.compact.AbstractItemTypeDefinitionsBuilder.AbstractNodeDefinitionBuilder;
+import org.apache.jackrabbit.spi.commons.nodetype.compact.AbstractItemTypeDefinitionsBuilder.AbstractNodeTypeDefinitionBuilder;
+import org.apache.jackrabbit.spi.commons.nodetype.compact.AbstractItemTypeDefinitionsBuilder.AbstractPropertyDefinitionBuilder;
 
 /**
  * CompactNodeTypeDefReader. Parses node type definitions written in the compact
@@ -121,42 +101,14 @@
  * XmlChar ::= see 3.2.2 Local Names
  * </pre>
  */
-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,8 +121,9 @@
     /**
      * The builder for QNodeTypeDefinitions
      */
-    private final QNodeTypeDefinitionsBuilder builder;
+    private final AbstractItemTypeDefinitionsBuilder<T, N> builder;
 
+    // fixme: move method to utility classes for jcr-commons and spi-commons
     /**
      * Convenience method that creates a new CND reader and parses the given
      * file directly.
@@ -180,14 +133,16 @@
      * @throws ParseException if an error occurs
      * @throws IOException if an I/O error occurs.
      */
-    public static CompactNodeTypeDefReader read(File file)
+    public static CompactNodeTypeDefReader<QNodeTypeDefinition, NamespaceMapping> 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());
+            QItemsTypeDefinitionsBuilderImpl builder = new QItemsTypeDefinitionsBuilderImpl();
+            return new CompactNodeTypeDefReader<QNodeTypeDefinition, NamespaceMapping>(r, file.getPath(),
+                    builder);
         } finally {
             if (r != null) {
                 try {
@@ -208,72 +163,49 @@
 
 
     /**
-     * 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}.
+     * default {@link QItemsTypeDefinitionsBuilderImpl}.
      *
      * @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)
+    public CompactNodeTypeDefReader(Reader r, String systemId, AbstractItemTypeDefinitionsBuilder<T, N> 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}.
+     * default {@link QItemsTypeDefinitionsBuilderImpl}.
      *
      * @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 build for creating new definitions
      * @throws ParseException if an error occurs
      */
-    public CompactNodeTypeDefReader(Reader r, String systemId, NamespaceMapping mapping,
-            QNodeTypeDefinitionsBuilder builder) throws ParseException {
+    public CompactNodeTypeDefReader(Reader r, String systemId, N nsMapping,
+            AbstractItemTypeDefinitionsBuilder<T, N> builder) throws ParseException {
 
-        this.builder = builder == null
-                ? new QNodeTypeDefinitionsBuilderImpl()
-                : builder;
+        super();
+
+        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();
     }
 
+
+
     /**
      * Returns the previously assigned system id
      * @return the system id
@@ -287,31 +219,17 @@
      *
      * @return a collection of QNodeTypeDefinition 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.
      */
-    public NamespaceMapping getNamespaceMapping() {
-        return nsMapping;
+    public N getNamespaceMapping() {
+        return builder.getNamespaceMapping();
     }
 
     /**
@@ -320,23 +238,27 @@
      * @throws ParseException if an error during parsing occurs
      */
     private void parse() throws ParseException {
-        while (!currentTokenEquals(Lexer.EOF)) {
-            if (!doNameSpace()) {
-                break;
+        try {
+            while (!currentTokenEquals(Lexer.EOF)) {
+                if (!doNameSpace()) {
+                    break;
+                }
             }
+            while (!currentTokenEquals(Lexer.EOF)) {
+                AbstractNodeTypeDefinitionBuilder<T> ntd = builder.newQNodeTypeDefinition();
+                ntd.setOrderableChildNodes(false);
+                ntd.setMixin(false);
+                ntd.setAbstract(false);
+                ntd.setQueryable(true);
+                doNodeTypeName(ntd);
+                doSuperTypes(ntd);
+                doOptions(ntd);
+                doItemDefs(ntd);
+                nodeTypeDefs.add(ntd.build());
+            }
         }
-        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());
+        catch (ParseException e) {
+            e.rethrow(lexer.getLineNumber());
         }
     }
 
@@ -344,7 +266,6 @@
 
     /**
      * processes the namespace declaration
-     *
      * @return <code>true</code> if a namespace was parsed
      * @throws ParseException if an error during parsing occurs
      */
@@ -364,11 +285,7 @@
         if (!currentTokenEquals('>')) {
             lexer.fail("Missing > in namespace decl.");
         }
-        try {
-            nsMapping.setMapping(prefix, uri);
-        } catch (NamespaceException e) {
-            // ignore
-        }
+        builder.setNamespace(prefix, uri);
         nextToken();
         return true;
     }
@@ -379,12 +296,12 @@
      * @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));
+        ntd.setName(currentToken);
 
         nextToken();
         if (!currentTokenEquals(Lexer.END_NODE_TYPE_NAME)) {
@@ -399,16 +316,13 @@
      * @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));
+                ntd.addSupertype(currentToken);
                 nextToken();
             } while (currentTokenEquals(Lexer.LIST_DELIMITER));
-
-        ntd.setSupertypes(supertypes.toArray(new Name[supertypes.size()]));
     }
 
     /**
@@ -417,7 +331,7 @@
      * @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)) {
@@ -437,7 +351,7 @@
                 ntd.setQueryable(true);
             } else if (currentTokenEquals(Lexer.PRIMARYITEM)) {
                 nextToken();
-                ntd.setPrimaryItemName(toName(currentToken));
+                ntd.setPrimaryItemName(currentToken);
                 nextToken();
             } else {
                 hasOption = false;
@@ -451,32 +365,27 @@
      * @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();
+                AbstractPropertyDefinitionBuilder<T> 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());
+                pd.build();
 
             } else if (currentTokenEquals(Lexer.CHILD_NODE_DEFINITION)) {
-                QNodeDefinitionBuilder nd = ntd.newQNodeDefinitionBuilder();
+                AbstractNodeDefinitionBuilder<T> nd = ntd.newQNodeDefinitionBuilder();
 
                 nd.setAllowsSameNameSiblings(false);
                 nd.setAutoCreated(false);
@@ -484,16 +393,12 @@
                 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());
+                nd.build();
             }
         }
-        ntd.setPropertyDefs(propertyDefinitions.toArray(new QPropertyDefinition[propertyDefinitions.size()]));
-        ntd.setChildNodeDefs(nodeDefinitions.toArray(new QNodeDefinition[nodeDefinitions.size()]));
     }
 
     /**
@@ -503,13 +408,10 @@
      * @param ntd declaring nodetype definition builder
      * @throws ParseException if an error during parsing occurs
      */
-    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));
-        }
+
+        pd.setName(currentToken);
         nextToken();
         doPropertyType(pd);
         doPropertyDefaultValue(pd);
@@ -523,7 +425,7 @@
      * @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;
         }
@@ -571,20 +473,11 @@
      * @param ntd declaring nodetype definition builder
      * @throws ParseException if an error during parsing occurs
      */
-    private void doPropertyAttributes(QPropertyDefinitionBuilder pd,
-                                      QNodeTypeDefinitionBuilder ntd)
+    private void doPropertyAttributes(AbstractPropertyDefinitionBuilder<T> pd,
+                                      AbstractNodeTypeDefinitionBuilder<T> 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);
@@ -623,7 +516,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;
@@ -661,24 +554,17 @@
      * @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);
             nextToken();
         } while (currentTokenEquals(Lexer.LIST_DELIMITER));
-        pd.setDefaultValues(defaultValues.toArray(new QValue[defaultValues.size()]));
     }
 
     /**
@@ -687,22 +573,17 @@
      * @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);
             nextToken();
         } while (currentTokenEquals(Lexer.LIST_DELIMITER));
-        pd.setValueConstraints(constraints.toArray(new QValueConstraint[constraints.size()]));
     }
 
     /**
@@ -712,14 +593,11 @@
      * @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));
-        }
+
+        nd.setName(currentToken);
         nextToken();
         doChildNodeRequiredTypes(nd);
         doChildNodeDefaultType(nd);
@@ -732,18 +610,17 @@
      * @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));
+            nd.addRequiredPrimaryType(currentToken);
             nextToken();
         } while (currentTokenEquals(Lexer.LIST_DELIMITER));
-        nd.setRequiredPrimaryTypes(types.toArray(new Name[types.size()]));
         nextToken();
     }
 
@@ -753,13 +630,13 @@
      * @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));
+        nd.setDefaultPrimaryType(currentToken);
         nextToken();
     }
 
@@ -770,20 +647,11 @@
      * @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 + "'");
-                }
                 ntd.setPrimaryItemName(nd.getName());
             } else if (currentTokenEquals(Lexer.AUTOCREATED)) {
                 nd.setAutoCreated(true);
@@ -811,28 +679,6 @@
     }
 
     /**
-     * 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()
Index: src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/Lexer.java
===================================================================
--- src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/Lexer.java	(revision 808006)
+++ src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/Lexer.java	(working copy)
@@ -16,9 +16,9 @@
  */
 package org.apache.jackrabbit.spi.commons.nodetype.compact;
 
+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: src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/ParseException.java
===================================================================
--- src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/ParseException.java	(revision 808006)
+++ src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/ParseException.java	(working copy)
@@ -24,7 +24,7 @@
     /**
      * the line number where the error occurred
      */
-    private final int lineNumber;
+    private int lineNumber;
 
     /**
      * the column number where the error occurred
@@ -36,8 +36,30 @@
      */
     private final String 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.
+     */
+    public ParseException(String message) {
+        this(message, 0, 0, null);
+    }
 
     /**
+     * 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 rootCause root failure cause
+     */
+    public ParseException(String message, Throwable rootCause) {
+        this(message, rootCause, 0, 0, null);
+    }
+
+    /**
      * Constructs a new instance of this class with <code>null</code> as its
      * detail message.
      * @param lineNumber line number
@@ -101,11 +123,19 @@
         this.systemId = systemId;
     }
 
+    public void rethrow(int lineNumber) throws ParseException {
+        if (this.lineNumber == 0) {
+            this.lineNumber = lineNumber;
+        }
+        throw this;
+    }
+
     /**
      * {@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: src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QItemsTypeDefinitionsBuilderImpl.java
===================================================================
--- src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QItemsTypeDefinitionsBuilderImpl.java	(revision 808006)
+++ src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QItemsTypeDefinitionsBuilderImpl.java	(working copy)
@@ -16,6 +16,10 @@
  */
 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;
 
@@ -29,117 +33,291 @@
 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.NameException;
 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
+ * Default implementations of a {@link AbstractItemTypeDefinitionsBuilder}. 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 {
-
+public class QItemsTypeDefinitionsBuilderImpl extends AbstractItemTypeDefinitionsBuilder<QNodeTypeDefinition, NamespaceMapping> {
     private static final NameFactory NAME_FACTORY = NameFactoryImpl.getInstance();
 
-    public QNodeTypeDefinitionBuilder newQNodeTypeDefinition() {
+    /**
+     * 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());
+        }
+    }
+
+    private NamespaceMapping nsMappings = new NamespaceMapping(NS_DEFAULTS);
+    private final NamePathResolver resolver = new DefaultNamePathResolver(nsMappings);
+
+    @Override
+    public AbstractNodeTypeDefinitionBuilder<QNodeTypeDefinition> newQNodeTypeDefinition() {
         return new QNodeTypeDefinitionBuilderImpl();
     }
 
+    @Override
+    public void setNamespaceMapping(NamespaceMapping nsMapping) {
+        this.nsMappings = nsMapping;
+    }
+
+    @Override
+    public NamespaceMapping getNamespaceMapping() {
+        return nsMappings;
+    }
+
+    @Override
+    public void setNamespace(String prefix, String uri) {
+        try {
+            nsMappings.setMapping(prefix, uri);
+        }
+        catch (NamespaceException e) {
+            // ignore
+        }
+    }
+
     public Name createName(String namespaceURI, String localName) {
         return NAME_FACTORY.create(namespaceURI, localName);
     }
 
     /**
-     * Default implementation of a {@link QNodeTypeDefinitionBuilder}.
+     * Default implementation of a {@link AbstractNodeTypeDefinitionBuilder}.
      */
-    public class QNodeTypeDefinitionBuilderImpl extends QNodeTypeDefinitionBuilder {
+    public class QNodeTypeDefinitionBuilderImpl 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>();
 
-        public QNodeDefinitionBuilder newQNodeDefinitionBuilder() {
-            return new QNodeDefinitionBuilderImpl();
+        @Override
+        public AbstractNodeDefinitionBuilder<QNodeTypeDefinition> newQNodeDefinitionBuilder() {
+            return new QNodeDefinitionBuilderImpl(this);
         }
 
-        public QPropertyDefinitionBuilder newQPropertyDefinition() {
-            return new QPropertyDefinitionBuilderImpl();
+        @Override
+        public AbstractPropertyDefinitionBuilder<QNodeTypeDefinition> newQPropertyDefinition() {
+            return new QPropertyDefinitionBuilderImpl(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 ParseException {
+            super.setName(name);
+            this.name = toName(name);
+        }
+
+        @Override
+        public void addSupertype(String name) throws ParseException {
+            supertypes.add(toName(name));
+        }
+
+        @Override
+        public void setPrimaryItemName(String name) throws ParseException {
+            if (primaryItem == null) {
+                primaryItem = toName(name);
+            }
+            else {
+                throw new ParseException("More than one primary item specified in node type '" + this.name + "'");
+            }
+        }
+
     }
 
     /**
-     * Default implementation of a {@link QPropertyDefinitionBuilder}.
+     * Default implementation of a {@link AbstractPropertyDefinitionBuilder}.
      */
-    public class QPropertyDefinitionBuilderImpl extends QPropertyDefinitionBuilder {
+    public class QPropertyDefinitionBuilderImpl extends AbstractPropertyDefinitionBuilder<QNodeTypeDefinition> {
+        private Name name;
+        private final QNodeTypeDefinitionBuilderImpl 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 QPropertyDefinitionBuilderImpl(QNodeTypeDefinitionBuilderImpl ntd) {
+            super();
+            this.ntd = ntd;
+        }
 
-            return ValueFormat.getQValue(value, getRequiredType(), resolver, QValueFactoryImpl
-                    .getInstance());
+        @Override
+        public void setName(String name) throws ParseException {
+            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 ParseException {
+            try {
+                values.add(ValueFormat.getQValue(value, getRequiredType(), resolver, QValueFactoryImpl.getInstance()));
+            }
+            catch (ValueFormatException e) {
+                throw new ParseException("'" + value
+                        + "' is not a valid string representation of a value of type " + this.type, e);
+            }
+            catch (RepositoryException e) {
+                throw new ParseException("An error occured during value conversion of '" + value + "'", e);
+            }
+        }
 
-            return ValueConstraint.create(getRequiredType(), constraint, resolver);
+        @Override
+        public void addValueConstraint(String constraint) throws ParseException {
+            try {
+                constraints.add(ValueConstraint.create(getRequiredType(), constraint, resolver));
+            }
+            catch (InvalidConstraintException e) {
+                throw new ParseException("'" + constraint
+                        + "' is not a valid constraint expression for a value of type " + type);
+            }
         }
 
-        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 ParseException {
+            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.type,
+                    constraints.toArray(new QValueConstraint[constraints.size()]),
+                    super.queryOperators,
+                    super.fullTextSearchable,
+                    super.queryOrderable));
+        }
+
     }
 
     /**
-     * Default implementation of a {@link QNodeDefinitionBuilder}.
+     * Default implementation of a {@link AbstractNodeDefinitionBuilder}.
      */
-    public class QNodeDefinitionBuilderImpl extends QNodeDefinitionBuilder {
+    public class QNodeDefinitionBuilderImpl extends AbstractNodeDefinitionBuilder<QNodeTypeDefinition> {
+        private final QNodeTypeDefinitionBuilderImpl 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 QNodeDefinitionBuilderImpl(QNodeTypeDefinitionBuilderImpl ntd) {
+            super();
+            this.ntd = ntd;
         }
 
+        @Override
+        public void setName(String name) throws ParseException {
+            super.setName(name);
+            if ("*".equals(name)) {
+                this.name = NameConstants.ANY_NAME;
+            }
+            else {
+                this.name = toName(name);
+            }
+        }
+
+        @Override
+        public void addRequiredPrimaryType(String name) throws ParseException {
+            requiredPrimaryTypes.add(toName(name));
+        }
+
+        @Override
+        public void setDefaultPrimaryType(String name) throws ParseException {
+            defaultPrimaryType = toName(name);
+        }
+
+        @Override
+        public void setDeclaringNodeType(String name) throws ParseException {
+            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 ParseException {
+        try {
+            Name n = resolver.getQName(name);
+            String decodedLocalName = ISO9075.decode(n.getLocalName());
+            return createName(n.getNamespaceURI(), decodedLocalName);
+        }
+        catch (NameException e) {
+            throw new ParseException("Error while parsing '" + name + "'", e);
+        }
+        catch (NamespaceException e) {
+            throw new ParseException("Error while parsing '" + name + "'", e);
+        }
+    }
+
 }
Index: src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QNodeTypeDefinitionsBuilder.java
===================================================================
--- src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QNodeTypeDefinitionsBuilder.java	(revision 808006)
+++ 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: src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QNodeTypeDefinitionsBuilderImpl.java
===================================================================
--- src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QNodeTypeDefinitionsBuilderImpl.java	(revision 808006)
+++ 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: src/test/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefTest.java
===================================================================
--- src/test/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefTest.java	(revision 808006)
+++ src/test/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefTest.java	(working copy)
@@ -23,14 +23,14 @@
 import java.io.StringWriter;
 import java.util.List;
 
+import junit.framework.TestCase;
+
 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 +39,8 @@
 
         // 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 QItemsTypeDefinitionsBuilderImpl());
 
         List<QNodeTypeDefinition> ntdList1 = cndReader.getNodeTypeDefinitions();
         NamespaceMapping nsm = cndReader.getNamespaceMapping();
@@ -50,7 +51,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 QItemsTypeDefinitionsBuilderImpl());
 
         List<QNodeTypeDefinition> ntdList2 = cndReader.getNodeTypeDefinitions();
 
