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

svn commit: r644745 [2/3] - in /jackrabbit/trunk: jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/nodetype/ jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ jackrabbit-spi-commons/ jackrabbit-spi-commons/src/main/jav...

Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefReader.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefReader.java?rev=644745&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefReader.java (added)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefReader.java Fri Apr  4 08:55:26 2008
@@ -0,0 +1,709 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.spi.commons.nodetype.compact;
+
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.jcr.NamespaceException;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.ValueFormatException;
+import javax.jcr.version.OnParentVersionAction;
+
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.QNodeDefinition;
+import org.apache.jackrabbit.spi.QPropertyDefinition;
+import org.apache.jackrabbit.spi.QValue;
+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.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.util.ISO9075;
+
+/**
+ * CompactNodeTypeDefReader. Parses node type definitions written in the compact
+ * node type definition format and returns a list of QNodeTypeDefinition objects that
+ * can then be used to register node types.
+ * <p/>
+ * The EBNF grammar of the compact node type definition:<br>
+ * <pre>
+ * cnd ::= ns_mapping* node_type_def+
+ *
+ * ns_mapping ::= "&lt;" prefix "=" namespace "&gt;"
+ *
+ * prefix ::= string
+ *
+ * namespace ::= string
+ *
+ * node_type_def ::= node_type_name [super_types] [options] {property_def | node_def}
+ *
+ * node_type_name ::= "[" string "]"
+ *
+ * super_types ::= "&gt;" string_list
+ *
+ * options ::= orderable_opt | mixin_opt | orderable_opt mixin_opt | mixin_opt orderable_opt
+ *
+ * orderable_opt ::= "orderable" | "ord" | "o"
+ *
+ * mixin_opt ::= "mixin" | "mix" | "m"
+ *
+ * property_def ::= "-" property_name [property_type_decl] [default_values] [attributes] [value_constraints]
+ *
+ * property_name ::= string
+ *
+ * property_type_decl ::= "(" property_type ")"
+ *
+ * property_type ::= "STRING" | "String |"string" |
+ *                   "BINARY" | "Binary" | "binary" |
+ *                   "LONG" | "Long" | "long" |
+ *                   "DOUBLE" | "Double" | "double" |
+ *                   "BOOLEAN" | "Boolean" | "boolean" |
+ *                   "DATE" | "Date" | "date" |
+ *                   "NAME | "Name | "name |
+ *                   "PATH" | "Path" | "path" |
+ *                   "REFERENCE" | "Reference" | "reference" |
+ *                   "UNDEFINED" | "Undefined" | "undefined" | "*"
+ *
+ *
+ * default_values ::= "=" string_list
+ *
+ * value_constraints ::= "&lt;" string_list
+ *
+ * node_def ::= "+" node_name [required_types] [default_type] [attributes]
+ *
+ * node_name ::= string
+ *
+ * required_types ::= "(" string_list ")"
+ *
+ * default_type ::= "=" string
+ *
+ * attributes ::= "primary" | "pri" | "!" |
+ *                "autocreated" | "aut" | "a" |
+ *                "mandatory" | "man" | "m" |
+ *                "protected" | "pro" | "p" |
+ *                "multiple" | "mul" | "*" |
+ *                "COPY" | "Copy" | "copy" |
+ *                "VERSION" | "Version" | "version" |
+ *                "INITIALIZE" | "Initialize" | "initialize" |
+ *                "COMPUTE" | "Compute" | "compute" |
+ *                "IGNORE" | "Ignore" | "ignore" |
+ *                "ABORT" | "Abort" | "abort"
+ *
+ * string_list ::= string {"," string}
+ *
+ * string ::= quoted_string | unquoted_string
+ *
+ * quoted_string :: = "'" unquoted_string "'"
+ *
+ * unquoted_string ::= [A-Za-z0-9:_]+
+ * </pre>
+ */
+public class CompactNodeTypeDefReader {
+
+    /**
+     * Empty array of value constraints
+     */
+    private final static String[] EMPTY_VALUE_CONSTRAINTS = new String[0];
+
+    /**
+     * the list of parsed QNodeTypeDefinition
+     */
+    private final List nodeTypeDefs = new LinkedList();
+
+    /**
+     * the current namespace mapping
+     */
+    private final NamespaceMapping nsMapping;
+
+    /**
+     * Name and Path resolver
+     */
+    private final NamePathResolver resolver;
+
+    /**
+     * the underlying lexer
+     */
+    private final Lexer lexer;
+
+    /**
+     * the current token
+     */
+    private String currentToken;
+
+    /**
+     * The builder for QNodeTypeDefinitions
+     */
+    private final QNodeTypeDefinitionsBuilder builder;
+
+    /**
+     * Creates a new CND reader.
+     * @param r
+     * @param systemId
+     * @param builder
+     * @throws ParseException
+     */
+    public CompactNodeTypeDefReader(Reader r, String systemId, QNodeTypeDefinitionsBuilder builder) throws ParseException {
+        this(r, systemId, new NamespaceMapping(), builder);
+    }
+
+
+    /**
+     * Creates a new CND reader.
+     * @param r
+     * @param builder
+     * @throws ParseException
+     */
+    public CompactNodeTypeDefReader(Reader r, String systemId, NamespaceMapping mapping,
+            QNodeTypeDefinitionsBuilder builder) throws ParseException {
+
+        this.builder = builder;
+        lexer = new Lexer(r, systemId);
+        this.nsMapping = mapping;
+        this.resolver = new DefaultNamePathResolver(nsMapping);
+        nextToken();
+        parse();
+    }
+
+    /**
+     * Returns the list of parsed QNodeTypeDefinition definitions.
+     *
+     * @return a List of QNodeTypeDefinition objects
+     */
+    public List getNodeTypeDefs() {
+        return nodeTypeDefs;
+    }
+
+    /**
+     * Returns the namespace mapping.
+     *
+     * @return a NamespaceMapping object.
+     */
+    public NamespaceMapping getNamespaceMapping() {
+        return nsMapping;
+    }
+
+    /**
+     * Parses the definition
+     *
+     * @throws ParseException
+     */
+    private void parse() throws ParseException {
+        while (!currentTokenEquals(Lexer.EOF)) {
+            if (!doNameSpace()) {
+                break;
+            }
+        }
+        while (!currentTokenEquals(Lexer.EOF)) {
+            QNodeTypeDefinitionBuilder ntd = builder.newQNodeTypeDefinition();
+            ntd.setOrderableChildNodes(false);
+            ntd.setMixin(false);
+            ntd.setPrimaryItemName(null);
+            doNodeTypeName(ntd);
+            doSuperTypes(ntd);
+            doOptions(ntd);
+            doItemDefs(ntd);
+            nodeTypeDefs.add(ntd.build());
+        }
+    }
+
+
+
+    /**
+     * processes the namespace declaration
+     *
+     * @return
+     * @throws ParseException
+     */
+    private boolean doNameSpace() throws ParseException {
+        if (!currentTokenEquals('<')) {
+            return false;
+        }
+        nextToken();
+        String prefix = currentToken;
+        nextToken();
+        if (!currentTokenEquals('=')) {
+            lexer.fail("Missing = in namespace decl.");
+        }
+        nextToken();
+        String uri = currentToken;
+        nextToken();
+        if (!currentTokenEquals('>')) {
+            lexer.fail("Missing > in namespace decl.");
+        }
+        try {
+            nsMapping.setMapping(prefix, uri);
+        } catch (NamespaceException e) {
+            // ignore
+        }
+        nextToken();
+        return true;
+    }
+
+    /**
+     * processes the nodetype name
+     *
+     * @param ntd
+     * @throws ParseException
+     */
+    private void doNodeTypeName(QNodeTypeDefinitionBuilder ntd) throws ParseException {
+        if (!currentTokenEquals(Lexer.BEGIN_NODE_TYPE_NAME)) {
+            lexer.fail("Missing '" + Lexer.BEGIN_NODE_TYPE_NAME + "' delimiter for beginning of node type name");
+        }
+        nextToken();
+        ntd.setName(toName(currentToken));
+
+        nextToken();
+        if (!currentTokenEquals(Lexer.END_NODE_TYPE_NAME)) {
+            lexer.fail("Missing '" + Lexer.END_NODE_TYPE_NAME + "' delimiter for end of node type name, found " + currentToken);
+        }
+        nextToken();
+    }
+
+    /**
+     * processes the superclasses
+     *
+     * @param ntd
+     * @throws ParseException
+     */
+    private void doSuperTypes(QNodeTypeDefinitionBuilder ntd) throws ParseException {
+        // a set would be nicer here, in case someone defines a supertype twice.
+        // but due to issue [JCR-333], the resulting node type definition is
+        // not symmetric anymore and the tests will fail.
+        ArrayList supertypes = new ArrayList();
+        if (currentTokenEquals(Lexer.EXTENDS))
+            do {
+                nextToken();
+                supertypes.add(toName(currentToken));
+                nextToken();
+            } while (currentTokenEquals(Lexer.LIST_DELIMITER));
+
+        ntd.setSupertypes((Name[]) supertypes.toArray(new Name[0]));
+    }
+
+    /**
+     * processes the options
+     *
+     * @param ntd
+     * @throws ParseException
+     */
+    private void doOptions(QNodeTypeDefinitionBuilder ntd) throws ParseException {
+        if (currentTokenEquals(Lexer.ORDERABLE)) {
+            ntd.setOrderableChildNodes(true);
+            nextToken();
+            if (currentTokenEquals(Lexer.MIXIN)) {
+                ntd.setMixin(true);
+                nextToken();
+            }
+        } else if (currentTokenEquals(Lexer.MIXIN)) {
+            ntd.setMixin(true);
+            nextToken();
+            if (currentTokenEquals(Lexer.ORDERABLE)) {
+                ntd.setOrderableChildNodes(true);
+                nextToken();
+            }
+        }
+    }
+
+    /**
+     * processes the item definitions
+     *
+     * @param ntd
+     * @throws ParseException
+     */
+    private void doItemDefs(QNodeTypeDefinitionBuilder ntd) throws ParseException {
+        List propertyDefinitions = new ArrayList();
+        List nodeDefinitions = new ArrayList();
+        while (currentTokenEquals(Lexer.PROPERTY_DEFINITION) || currentTokenEquals(Lexer.CHILD_NODE_DEFINITION)) {
+            if (currentTokenEquals(Lexer.PROPERTY_DEFINITION)) {
+                QPropertyDefinitionBuilder pd = ntd.newQPropertyDefinition();
+
+                pd.setAutoCreated(false);
+                pd.setDeclaringNodeType(ntd.getName());
+                pd.setDefaultValues(null);
+                pd.setMandatory(false);
+                pd.setMultiple(false);
+                pd.setOnParentVersion(OnParentVersionAction.COPY);
+                pd.setProtected(false);
+                pd.setRequiredType(PropertyType.STRING);
+                pd.setValueConstraints(EMPTY_VALUE_CONSTRAINTS);
+
+                nextToken();
+                doPropertyDefinition(pd, ntd);
+                propertyDefinitions.add(pd.build());
+
+            } else if (currentTokenEquals(Lexer.CHILD_NODE_DEFINITION)) {
+                QNodeDefinitionBuilder nd = ntd.newQNodeDefinitionBuilder();
+
+                nd.setAllowsSameNameSiblings(false);
+                nd.setAutoCreated(false);
+                nd.setDeclaringNodeType(ntd.getName());
+                nd.setMandatory(false);
+                nd.setOnParentVersion(OnParentVersionAction.COPY);
+                nd.setProtected(false);
+                nd.setDefaultPrimaryType(null);
+                nd.setRequiredPrimaryTypes(new Name[]{NameConstants.NT_BASE});
+
+                nextToken();
+                doChildNodeDefinition(nd, ntd);
+                nodeDefinitions.add(nd.build());
+            }
+        }
+
+        ntd.setPropertyDefs((QPropertyDefinition[]) propertyDefinitions
+                .toArray(new QPropertyDefinition[0]));
+
+        ntd.setChildNodeDefs((QNodeDefinition[]) nodeDefinitions.toArray(new QNodeDefinition[0]));
+    }
+
+    /**
+     * processes the property definition
+     *
+     * @param pd
+     * @param ntd
+     * @throws ParseException
+     */
+    private void doPropertyDefinition(QPropertyDefinitionBuilder pd, QNodeTypeDefinitionBuilder ntd)
+            throws ParseException {
+        if (currentToken.equals("*")) {
+            pd.setName(NameConstants.ANY_NAME);
+        } else {
+            pd.setName(toName(currentToken));
+        }
+        nextToken();
+        doPropertyType(pd);
+        doPropertyDefaultValue(pd);
+        doPropertyAttributes(pd, ntd);
+        doPropertyValueConstraints(pd);
+    }
+
+    /**
+     * processes the property type
+     *
+     * @param pd
+     * @throws ParseException
+     */
+    private void doPropertyType(QPropertyDefinitionBuilder pd) throws ParseException {
+        if (!currentTokenEquals(Lexer.BEGIN_TYPE)) {
+            return;
+        }
+        nextToken();
+        if (currentTokenEquals(Lexer.STRING)) {
+            pd.setRequiredType(PropertyType.STRING);
+        } else if (currentTokenEquals(Lexer.BINARY)) {
+            pd.setRequiredType(PropertyType.BINARY);
+        } else if (currentTokenEquals(Lexer.LONG)) {
+            pd.setRequiredType(PropertyType.LONG);
+        } else if (currentTokenEquals(Lexer.DOUBLE)) {
+            pd.setRequiredType(PropertyType.DOUBLE);
+        } else if (currentTokenEquals(Lexer.BOOLEAN)) {
+            pd.setRequiredType(PropertyType.BOOLEAN);
+        } else if (currentTokenEquals(Lexer.DATE)) {
+            pd.setRequiredType(PropertyType.DATE);
+        } else if (currentTokenEquals(Lexer.NAME)) {
+            pd.setRequiredType(PropertyType.NAME);
+        } else if (currentTokenEquals(Lexer.PATH)) {
+            pd.setRequiredType(PropertyType.PATH);
+        } else if (currentTokenEquals(Lexer.REFERENCE)) {
+            pd.setRequiredType(PropertyType.REFERENCE);
+        } else if (currentTokenEquals(Lexer.UNDEFINED)) {
+            pd.setRequiredType(PropertyType.UNDEFINED);
+        } else {
+            lexer.fail("Unkown property type '" + currentToken + "' specified");
+        }
+        nextToken();
+        if (!currentTokenEquals(Lexer.END_TYPE)) {
+            lexer.fail("Missing '" + Lexer.END_TYPE + "' delimiter for end of property type");
+        }
+        nextToken();
+    }
+
+    /**
+     * processes the property attributes
+     *
+     * @param pd
+     * @param ntd
+     * @throws ParseException
+     */
+    private void doPropertyAttributes(QPropertyDefinitionBuilder pd, QNodeTypeDefinitionBuilder ntd) throws ParseException {
+        while (currentTokenEquals(Lexer.ATTRIBUTE)) {
+            if (currentTokenEquals(Lexer.PRIMARY)) {
+                if (ntd.getPrimaryItemName() != null) {
+                    String name = null;
+                    try {
+                        name = resolver.getJCRName(ntd.getName());
+                    } catch (NamespaceException e) {
+                        // Should never happen, checked earlier
+                    }
+                    lexer.fail("More than one primary item specified in node type '" + name + "'");
+                }
+                ntd.setPrimaryItemName(pd.getName());
+            } else if (currentTokenEquals(Lexer.AUTOCREATED)) {
+                pd.setAutoCreated(true);
+            } else if (currentTokenEquals(Lexer.MANDATORY)) {
+                pd.setMandatory(true);
+            } else if (currentTokenEquals(Lexer.PROTECTED)) {
+                pd.setProtected(true);
+            } else if (currentTokenEquals(Lexer.MULTIPLE)) {
+                pd.setMultiple(true);
+            } else if (currentTokenEquals(Lexer.COPY)) {
+                pd.setOnParentVersion(OnParentVersionAction.COPY);
+            } else if (currentTokenEquals(Lexer.VERSION)) {
+                pd.setOnParentVersion(OnParentVersionAction.VERSION);
+            } else if (currentTokenEquals(Lexer.INITIALIZE)) {
+                pd.setOnParentVersion(OnParentVersionAction.INITIALIZE);
+            } else if (currentTokenEquals(Lexer.COMPUTE)) {
+                pd.setOnParentVersion(OnParentVersionAction.COMPUTE);
+            } else if (currentTokenEquals(Lexer.IGNORE)) {
+                pd.setOnParentVersion(OnParentVersionAction.IGNORE);
+            } else if (currentTokenEquals(Lexer.ABORT)) {
+                pd.setOnParentVersion(OnParentVersionAction.ABORT);
+            }
+            nextToken();
+        }
+    }
+
+    /**
+     * processes the property default values
+     *
+     * @param pd
+     * @throws ParseException
+     */
+    private void doPropertyDefaultValue(QPropertyDefinitionBuilder pd) throws ParseException {
+        if (!currentTokenEquals(Lexer.DEFAULT)) {
+            return;
+        }
+        List defaultValues = new ArrayList();
+        do {
+            nextToken();
+            QValue value = null;
+            try {
+                value = 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 + "'");
+            }
+            defaultValues.add(value);
+            nextToken();
+        } while (currentTokenEquals(Lexer.LIST_DELIMITER));
+        pd.setDefaultValues((QValue[]) defaultValues.toArray(new QValue[0]));
+    }
+
+    /**
+     * processes the property value constraints
+     *
+     * @param pd
+     * @throws ParseException
+     */
+    private void doPropertyValueConstraints(QPropertyDefinitionBuilder pd) throws ParseException {
+        if (!currentTokenEquals(Lexer.CONSTRAINT)) {
+            return;
+        }
+        List constraints = new ArrayList();
+        do {
+            nextToken();
+            String constraint = null;
+            try {
+                constraint = pd.createValueConstraint(currentToken, resolver);
+            } catch (InvalidConstraintException e) {
+                lexer.fail("'" + currentToken + "' is not a valid constraint expression for a value of type " + pd.getRequiredType());
+            }
+            constraints.add(constraint);
+            nextToken();
+        } while (currentTokenEquals(Lexer.LIST_DELIMITER));
+        pd.setValueConstraints((String[]) constraints.toArray(new String[0]));
+    }
+
+    /**
+     * processes the childnode definition
+     *
+     * @param nd
+     * @param ntd
+     * @throws ParseException
+     */
+    private void doChildNodeDefinition(QNodeDefinitionBuilder nd, QNodeTypeDefinitionBuilder ntd)
+            throws ParseException {
+        if (currentTokenEquals('*')) {
+            nd.setName(NameConstants.ANY_NAME);
+        } else {
+            nd.setName(toName(currentToken));
+        }
+        nextToken();
+        doChildNodeRequiredTypes(nd);
+        doChildNodeDefaultType(nd);
+        doChildNodeAttributes(nd, ntd);
+    }
+
+    /**
+     * processes the childnode required types
+     *
+     * @param nd
+     * @throws ParseException
+     */
+    private void doChildNodeRequiredTypes(QNodeDefinitionBuilder nd) throws ParseException {
+        if (!currentTokenEquals(Lexer.BEGIN_TYPE)) {
+            return;
+        }
+        List types = new ArrayList();
+        do {
+            nextToken();
+            types.add(toName(currentToken));
+            nextToken();
+        } while (currentTokenEquals(Lexer.LIST_DELIMITER));
+        nd.setRequiredPrimaryTypes((Name[]) types.toArray(new Name[0]));
+        nextToken();
+    }
+
+    /**
+     * processes the childnode default types
+     *
+     * @param nd
+     * @throws ParseException
+     */
+    private void doChildNodeDefaultType(QNodeDefinitionBuilder nd) throws ParseException {
+        if (!currentTokenEquals(Lexer.DEFAULT)) {
+            return;
+        }
+        nextToken();
+        nd.setDefaultPrimaryType(toName(currentToken));
+        nextToken();
+    }
+
+    /**
+     * processes the childnode attributes
+     *
+     * @param nd
+     * @param ntd
+     * @throws ParseException
+     */
+    private void doChildNodeAttributes(QNodeDefinitionBuilder nd, QNodeTypeDefinitionBuilder ntd) throws ParseException {
+        while (currentTokenEquals(Lexer.ATTRIBUTE)) {
+            if (currentTokenEquals(Lexer.PRIMARY)) {
+                if (ntd.getPrimaryItemName() != null) {
+                    String name = null;
+                    try {
+                        name = resolver.getJCRName(ntd.getName());
+                    } catch (NamespaceException e) {
+                        // Should never happen, checked earlier
+                    }
+                    lexer.fail("More than one primary item specified in node type '" + name + "'");
+                }
+                ntd.setPrimaryItemName(nd.getName());
+            } else if (currentTokenEquals(Lexer.AUTOCREATED)) {
+                nd.setAutoCreated(true);
+            } else if (currentTokenEquals(Lexer.MANDATORY)) {
+                nd.setMandatory(true);
+            } else if (currentTokenEquals(Lexer.PROTECTED)) {
+                nd.setProtected(true);
+            } else if (currentTokenEquals(Lexer.MULTIPLE)) {
+                nd.setAllowsSameNameSiblings(true);
+            } else if (currentTokenEquals(Lexer.COPY)) {
+                nd.setOnParentVersion(OnParentVersionAction.COPY);
+            } else if (currentTokenEquals(Lexer.VERSION)) {
+                nd.setOnParentVersion(OnParentVersionAction.VERSION);
+            } else if (currentTokenEquals(Lexer.INITIALIZE)) {
+                nd.setOnParentVersion(OnParentVersionAction.INITIALIZE);
+            } else if (currentTokenEquals(Lexer.COMPUTE)) {
+                nd.setOnParentVersion(OnParentVersionAction.COMPUTE);
+            } else if (currentTokenEquals(Lexer.IGNORE)) {
+                nd.setOnParentVersion(OnParentVersionAction.IGNORE);
+            } else if (currentTokenEquals(Lexer.ABORT)) {
+                nd.setOnParentVersion(OnParentVersionAction.ABORT);
+            }
+            nextToken();
+        }
+    }
+
+    /**
+     * Converts the given string into a qualified name using the current
+     * namespace mapping.
+     *
+     * @param stringName
+     * @return the qualified name
+     * @throws ParseException if the conversion fails
+     */
+    private Name toName(String stringName) throws ParseException {
+        try {
+            Name n = resolver.getQName(stringName);
+            String decodedLocalName = ISO9075.decode(n.getLocalName());
+            return builder.createName(n.getNamespaceURI(), decodedLocalName);
+        } catch (NameException e) {
+            lexer.fail("Error while parsing '" + stringName + "'", e);
+            return null;
+        } catch (NamespaceException e) {
+            lexer.fail("Error while parsing '" + stringName + "'", e);
+            return null;
+        }
+    }
+
+    /**
+     * Gets the next token from the underlying lexer.
+     *
+     * @see Lexer#getNextToken()
+     * @throws ParseException if the lexer fails to get the next token.
+     */
+    private void nextToken() throws ParseException {
+        currentToken = lexer.getNextToken();
+    }
+
+    /**
+     * Checks if the {@link #currentToken} is semantically equal to the given
+     * argument.
+     *
+     * @param s the tokens to compare with
+     * @return <code>true</code> if equals; <code>false</code> otherwise.
+     */
+    private boolean currentTokenEquals(String[] s) {
+        for (int i = 0; i < s.length; i++) {
+            if (currentToken.equals(s[i])) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Checks if the {@link #currentToken} is semantically equal to the given
+     * argument.
+     *
+     * @param c the tokens to compare with
+     * @return <code>true</code> if equals; <code>false</code> otherwise.
+     */
+    private boolean currentTokenEquals(char c) {
+        return currentToken.length() == 1 && currentToken.charAt(0) == c;
+    }
+
+    /**
+     * Checks if the {@link #currentToken} is semantically equal to the given
+     * argument.
+     *
+     * @param s the tokens to compare with
+     * @return <code>true</code> if equals; <code>false</code> otherwise.
+     */
+    private boolean currentTokenEquals(String s) {
+        return currentToken.equals(s);
+    }
+
+}

Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefReader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefReader.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefWriter.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefWriter.java?rev=644745&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefWriter.java (added)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefWriter.java Fri Apr  4 08:55:26 2008
@@ -0,0 +1,470 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.spi.commons.nodetype.compact;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.jcr.NamespaceException;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+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.commons.conversion.NamePathResolver;
+import org.apache.jackrabbit.spi.commons.name.NameConstants;
+import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
+import org.apache.jackrabbit.spi.commons.value.QValueFactoryImpl;
+import org.apache.jackrabbit.spi.commons.value.ValueFormat;
+import org.apache.jackrabbit.util.ISO9075;
+
+/**
+ * Prints node type defs in a compact notation
+ * Print Format:
+ * <ex = "http://apache.org/jackrabbit/example">
+ * [ex:NodeType] > ex:ParentType1, ex:ParentType2
+ * orderable mixin
+ *   - ex:property (STRING) = 'default1', 'default2'
+ *     primary mandatory autocreated protected multiple VERSION
+ *     < 'constraint1', 'constraint2'
+ *   + ex:node (ex:reqType1, ex:reqType2) = ex:defaultType
+ *     mandatory autocreated protected multiple VERSION
+ */
+public class CompactNodeTypeDefWriter {
+
+    /**
+     * the indention string
+     */
+    private static final String INDENT = "  ";
+
+    /**
+     * the current namespace resolver
+     */
+    private final NamespaceResolver resolver;
+
+    /**
+     * the current name/path resolver
+     */
+    private final NamePathResolver npResolver;
+
+    /**
+     * the current value factory
+     */
+    private final ValueFactory valueFactory;
+
+    /**
+     * the underlying writer
+     */
+    private Writer out;
+
+    /**
+     * special writer used for namespaces
+     */
+    private Writer nsWriter;
+
+    /**
+     * namespaces(prefixes) that are used
+     */
+    private final HashSet usedNamespaces = new HashSet();
+
+    /**
+     * Creates a new nodetype writer
+     *
+     * @param out the underlying writer
+     * @param r the namespace resolver
+     * @param npResolver
+     * @param valueFactory
+     */
+    public CompactNodeTypeDefWriter(Writer out, NamespaceResolver r, NamePathResolver npResolver,
+            ValueFactory valueFactory) {
+        this(out, r, npResolver, valueFactory, false);
+    }
+
+    /**
+     * Creates a new nodetype writer
+     *
+     * @param out the underlaying writer
+     * @param r the naespace resolver
+     * @param npResolver
+     * @param valueFactory
+     * @param includeNS if <code>true</code> all used namespace decl. are also
+     */
+    public CompactNodeTypeDefWriter(Writer out, NamespaceResolver r, NamePathResolver npResolver,
+            ValueFactory valueFactory, boolean includeNS) {
+        this.resolver = r;
+        this.npResolver = npResolver;
+        this.valueFactory = valueFactory;
+        if (includeNS) {
+            this.out = new StringWriter();
+            this.nsWriter = out;
+        } else {
+            this.out = out;
+            this.nsWriter = null;
+        }
+    }
+
+    /**
+     * Writes the given list of QNodeTypeDefinition to the output writer including the
+     * used namespaces.
+     *
+     * @param l
+     * @param r
+     * @param npResolver
+     * @param valueFactory
+     * @param out
+     * @throws IOException
+     */
+    public static void write(List l, NamespaceResolver r, NamePathResolver npResolver,
+            ValueFactory valueFactory, Writer out)
+            throws IOException {
+        CompactNodeTypeDefWriter w = new CompactNodeTypeDefWriter(out, r, npResolver, valueFactory, true);
+        Iterator iter = l.iterator();
+        while (iter.hasNext()) {
+            QNodeTypeDefinition def = (QNodeTypeDefinition) iter.next();
+            w.write(def);
+        }
+        w.close();
+    }
+
+    /**
+     * Write one QNodeTypeDefinition to this writer
+     *
+     * @param ntd
+     * @throws IOException
+     */
+    public void write(QNodeTypeDefinition ntd) throws IOException {
+        writeName(ntd);
+        writeSupertypes(ntd);
+        writeOptions(ntd);
+        writePropDefs(ntd);
+        writeNodeDefs(ntd);
+        out.write("\n\n");
+    }
+
+    /**
+     * Flushes all pending write operations and Closes this writer. please note,
+     * that the underlying writer remains open.
+     *
+     * @throws IOException
+     */
+    public void close() throws IOException {
+        if (nsWriter != null) {
+            nsWriter.write("\n");
+            out.close();
+            nsWriter.write(((StringWriter) out).getBuffer().toString());
+            out = nsWriter;
+            nsWriter = null;
+        }
+        out.flush();
+        out = null;
+    }
+
+    /**
+     * write name
+     */
+    private void writeName(QNodeTypeDefinition ntd) throws IOException {
+        out.write("[");
+        out.write(resolve(ntd.getName()));
+        out.write("]");
+    }
+
+    /**
+     * write supertypes
+     */
+    private void writeSupertypes(QNodeTypeDefinition ntd) throws IOException {
+        Name[] sta = ntd.getSupertypes();
+        String delim = " > ";
+        for (int i = 0; i < sta.length; i++) {
+            out.write(delim);
+            out.write(resolve(sta[i]));
+            delim = ", ";
+        }
+    }
+
+    /**
+     * write options
+     */
+    private void writeOptions(QNodeTypeDefinition ntd) throws IOException {
+        if (ntd.hasOrderableChildNodes()) {
+            out.write("\n" + INDENT);
+            out.write("orderable");
+            if (ntd.isMixin()) {
+                out.write(" mixin");
+            }
+        } else if (ntd.isMixin()) {
+            out.write("\n" + INDENT);
+            out.write("mixin");
+        }
+    }
+
+    /**
+     * write prop defs
+     */
+    private void writePropDefs(QNodeTypeDefinition ntd) throws IOException {
+        QPropertyDefinition[] pda = ntd.getPropertyDefs();
+        for (int i = 0; i < pda.length; i++) {
+            QPropertyDefinition pd = pda[i];
+            writePropDef(ntd, pd);
+        }
+    }
+
+    /**
+     * write node defs
+     */
+    private void writeNodeDefs(QNodeTypeDefinition ntd) throws IOException {
+        QNodeDefinition[] nda = ntd.getChildNodeDefs();
+        for (int i = 0; i < nda.length; i++) {
+            QNodeDefinition nd = nda[i];
+            writeNodeDef(ntd, nd);
+        }
+    }
+
+    /**
+     * write prop def
+     * @param pd
+     */
+    private void writePropDef(QNodeTypeDefinition ntd, QPropertyDefinition pd) throws IOException {
+        out.write("\n" + INDENT + "- ");
+
+        Name name = pd.getName();
+        if (name.equals(NameConstants.ANY_NAME)) {
+            out.write('*');
+        } else {
+            writeItemDefName(name);
+        }
+
+        out.write(" (");
+        out.write(PropertyType.nameFromValue(pd.getRequiredType()).toLowerCase());
+        out.write(")");
+        writeDefaultValues(pd.getDefaultValues());
+        out.write(ntd.getPrimaryItemName() != null && ntd.getPrimaryItemName().equals(pd.getName()) ? " primary" : "");
+        if (pd.isMandatory()) {
+            out.write(" mandatory");
+        }
+        if (pd.isAutoCreated()) {
+            out.write(" autocreated");
+        }
+        if (pd.isProtected()) {
+            out.write(" protected");
+        }
+        if (pd.isMultiple()) {
+            out.write(" multiple");
+        }
+        if (pd.getOnParentVersion() != OnParentVersionAction.COPY) {
+            out.write(" ");
+            out.write(OnParentVersionAction.nameFromValue(pd.getOnParentVersion()).toLowerCase());
+        }
+        writeValueConstraints(pd.getValueConstraints(), pd.getRequiredType());
+    }
+
+    /**
+     * write default values
+     * @param dva
+     */
+    private void writeDefaultValues(QValue[] dva) throws IOException {
+        if (dva != null && dva.length > 0) {
+            String delim = " = '";
+            for (int i = 0; i < dva.length; i++) {
+                out.write(delim);
+                try {
+                    Value v = ValueFormat.getJCRValue(dva[i], npResolver, valueFactory);
+                    out.write(escape(v.getString()));
+                } catch (RepositoryException e) {
+                    out.write(escape(dva[i].toString()));
+                }
+                out.write("'");
+                delim = ", '";
+            }
+        }
+    }
+
+    /**
+     * write value constraints
+     * @param vca
+     */
+    private void writeValueConstraints(String[] vca, int type) throws IOException {
+        if (vca != null && vca.length > 0) {
+            String vc = convertConstraint(vca[0], type);
+            out.write(" < '");
+            out.write(escape(vc));
+            out.write("'");
+            for (int i = 1; i < vca.length; i++) {
+                vc = convertConstraint(vca[i], type);
+                out.write(", '");
+                out.write(escape(vc));
+                out.write("'");
+            }
+        }
+    }
+
+    private String convertConstraint(String vc, int type) {
+        if (type == PropertyType.REFERENCE || type == PropertyType.NAME || type == PropertyType.PATH) {
+            if (type == PropertyType.REFERENCE)
+                type = PropertyType.NAME;
+
+            try {
+                QValue qv = QValueFactoryImpl.getInstance().create(vc, type);
+                vc = ValueFormat.getJCRValue(qv, npResolver, valueFactory).getString();
+            }
+            catch (RepositoryException e) {
+                // ignore -> return unconverted constraint
+            }
+        }
+
+        return vc;
+    }
+
+    /**
+     * write node def
+     *
+     * @param nd
+     */
+    private void writeNodeDef(QNodeTypeDefinition ntd, QNodeDefinition nd) throws IOException {
+        out.write("\n" + INDENT + "+ ");
+
+        Name name = nd.getName();
+        if (name.equals(NameConstants.ANY_NAME)) {
+            out.write('*');
+        } else {
+            writeItemDefName(name);
+        }
+        writeRequiredTypes(nd.getRequiredPrimaryTypes());
+        writeDefaultType(nd.getDefaultPrimaryType());
+        out.write(ntd.getPrimaryItemName() != null && ntd.getPrimaryItemName().equals(nd.getName()) ? " primary" : "");
+        if (nd.isMandatory()) {
+            out.write(" mandatory");
+        }
+        if (nd.isAutoCreated()) {
+            out.write(" autocreated");
+        }
+        if (nd.isProtected()) {
+            out.write(" protected");
+        }
+        if (nd.allowsSameNameSiblings()) {
+            out.write(" multiple");
+        }
+        if (nd.getOnParentVersion() != OnParentVersionAction.COPY) {
+            out.write(" ");
+            out.write(OnParentVersionAction.nameFromValue(nd.getOnParentVersion()).toLowerCase());
+        }
+    }
+
+    /**
+     * Write item def name
+     * @param name
+     * @throws IOException
+     */
+    private void writeItemDefName(Name name) throws IOException {
+        out.write(resolve(name));
+    }
+    /**
+     * write required types
+     * @param reqTypes
+     */
+    private void writeRequiredTypes(Name[] reqTypes) throws IOException {
+        if (reqTypes != null && reqTypes.length > 0) {
+            String delim = " (";
+            for (int i = 0; i < reqTypes.length; i++) {
+                out.write(delim);
+                out.write(resolve(reqTypes[i]));
+                delim = ", ";
+            }
+            out.write(")");
+        }
+    }
+
+    /**
+     * write default types
+     * @param defType
+     */
+    private void writeDefaultType(Name defType) throws IOException {
+        if (defType != null && !defType.getLocalName().equals("*")) {
+            out.write(" = ");
+            out.write(resolve(defType));
+        }
+    }
+
+    /**
+     * resolve
+     * @param name
+     * @return the resolved name
+     */
+    private String resolve(Name name) throws IOException {
+        if (name == null) {
+            return "";
+        }
+        try {
+            String prefix = resolver.getPrefix(name.getNamespaceURI());
+            if (prefix != null && !prefix.equals(Name.NS_EMPTY_PREFIX)) {
+                // check for writing namespaces
+                if (nsWriter != null) {
+                    if (!usedNamespaces.contains(prefix)) {
+                        usedNamespaces.add(prefix);
+                        nsWriter.write("<'");
+                        nsWriter.write(prefix);
+                        nsWriter.write("'='");
+                        nsWriter.write(escape(name.getNamespaceURI()));
+                        nsWriter.write("'>\n");
+                    }
+                }
+                prefix += ":";
+            }
+
+            String encLocalName = ISO9075.encode(name.getLocalName());
+            String resolvedName = prefix + encLocalName;
+
+            // check for '-' and '+'
+            if (resolvedName.indexOf('-') >= 0 || resolvedName.indexOf('+') >= 0) {
+                return "'" + resolvedName + "'";
+            } else {
+                return resolvedName;
+            }
+
+        } catch (NamespaceException e) {
+            return name.toString();
+        }
+    }
+
+    /**
+     * escape
+     * @param s
+     * @return the escaped string
+     */
+    private String escape(String s) {
+        StringBuffer sb = new StringBuffer(s);
+        for (int i = 0; i < sb.length(); i++) {
+            if (sb.charAt(i) == '\\') {
+                sb.insert(i, '\\');
+                i++;
+            } else if (sb.charAt(i) == '\'') {
+                sb.insert(i, '\'');
+                i++;
+            }
+        }
+        return sb.toString();
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefWriter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/CompactNodeTypeDefWriter.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/Lexer.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/Lexer.java?rev=644745&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/Lexer.java (added)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/Lexer.java Fri Apr  4 08:55:26 2008
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.spi.commons.nodetype.compact;
+
+import java.io.StreamTokenizer;
+import java.io.Reader;
+import java.io.IOException;
+
+/**
+ * Lexer
+ */
+public class Lexer {
+    public static final char SINGLE_QUOTE = '\'';
+    public static final char DOUBLE_QUOTE = '\"';
+    public static final char BEGIN_NODE_TYPE_NAME = '[';
+    public static final char END_NODE_TYPE_NAME = ']';
+    public static final char EXTENDS = '>';
+    public static final char LIST_DELIMITER = ',';
+    public static final char PROPERTY_DEFINITION = '-';
+    public static final char CHILD_NODE_DEFINITION = '+';
+    public static final char BEGIN_TYPE = '(';
+    public static final char END_TYPE = ')';
+    public static final char DEFAULT = '=';
+    public static final char CONSTRAINT = '<';
+
+    public static final String[] ORDERABLE = new String[] {"orderable", "ord", "o"};
+    public static final String[] MIXIN = new String[]{"mixin", "mix", "m"};
+
+    public static final String[] PRIMARY = new String[]{"primary", "pri", "!"};
+    public static final String[] AUTOCREATED = new String[]{"autocreated", "aut", "a"};
+    public static final String[] MANDATORY = new String[]{"mandatory", "man", "m"};
+    public static final String[] PROTECTED = new String[]{"protected", "pro", "p"};
+    public static final String[] MULTIPLE = new String[]{"multiple", "mul", "*"};
+
+    public static final String[] COPY = new String[]{"copy", "Copy", "COPY"};
+    public static final String[] VERSION = new String[]{"version", "Version", "VERSION"};
+    public static final String[] INITIALIZE = new String[]{"initialize", "Initialize", "INITIALIZE"};
+    public static final String[] COMPUTE = new String[]{"compute", "Compute", "COMPUTE"};
+    public static final String[] IGNORE = new String[]{"ignore", "Ignore", "IGNORE"};
+    public static final String[] ABORT = new String[]{"abort", "Abort", "ABORT"};
+
+    public static final String[] ATTRIBUTE = new String[]{"primary", "pri", "!",
+                                                          "autocreated", "aut", "a",
+                                                          "mandatory", "man", "m",
+                                                          "protected", "pro", "p",
+                                                          "multiple", "mul", "*",
+                                                          "copy", "Copy", "COPY",
+                                                          "version", "Version", "VERSION",
+                                                          "initialize", "Initialize", "INITIALIZE",
+                                                          "compute", "Compute", "COMPUTE",
+                                                          "ignore", "Ignore", "IGNORE",
+                                                          "abort", "Abort", "ABORT"};
+
+    public static final String[] STRING = {"string", "String", "STRING"};
+    public static final String[] BINARY = {"binary", "Binary", "BINARY"};
+    public static final String[] LONG = {"long", "Long", "LONG"};
+    public static final String[] DOUBLE = {"double", "Double", "DOUBLE"};
+    public static final String[] BOOLEAN = {"boolean", "Boolean", "BOOLEAN"};
+    public static final String[] DATE = {"date", "Date", "DATE"};
+    public static final String[] NAME = {"name", "Name", "NAME"};
+    public static final String[] PATH = {"path", "Path", "PATH"};
+    public static final String[] REFERENCE = {"reference", "Reference", "REFERENCE"};
+
+    public static final String[] UNDEFINED = new String[]{"undefined", "Undefined", "UNDEFINED", "*"};
+
+    public static final String EOF = "eof";
+
+    private final StreamTokenizer st;
+
+    private final String systemId;
+
+    /**
+     * Constructor
+     * @param r
+     */
+    public Lexer(Reader r, String systemId) {
+        this.systemId = systemId;
+        st = new StreamTokenizer(r);
+
+        st.eolIsSignificant(false);
+
+        st.lowerCaseMode(false);
+
+        st.slashSlashComments(true);
+        st.slashStarComments(true);
+
+        st.wordChars('a', 'z');
+        st.wordChars('A', 'Z');
+        st.wordChars(':', ':');
+        st.wordChars('_', '_');
+
+        st.quoteChar(SINGLE_QUOTE);
+        st.quoteChar(DOUBLE_QUOTE);
+
+        st.ordinaryChar(BEGIN_NODE_TYPE_NAME);
+        st.ordinaryChar(END_NODE_TYPE_NAME);
+        st.ordinaryChar(EXTENDS);
+        st.ordinaryChar(LIST_DELIMITER);
+        st.ordinaryChar(PROPERTY_DEFINITION);
+        st.ordinaryChar(CHILD_NODE_DEFINITION);
+        st.ordinaryChar(BEGIN_TYPE);
+        st.ordinaryChar(END_TYPE);
+        st.ordinaryChar(DEFAULT);
+        st.ordinaryChar(CONSTRAINT);
+    }
+
+    /**
+     * getNextToken
+     *
+     * @return
+     * @throws ParseException
+     */
+    public String getNextToken() throws ParseException {
+        try {
+            int tokenType = st.nextToken();
+            if (tokenType == StreamTokenizer.TT_EOF) {
+                return EOF;
+            } else if (tokenType == StreamTokenizer.TT_WORD
+                    || tokenType == SINGLE_QUOTE
+                    || tokenType == DOUBLE_QUOTE) {
+                return st.sval;
+            } else if (tokenType == StreamTokenizer.TT_NUMBER) {
+                return String.valueOf(st.nval);
+            } else {
+                return new String(new char[] {(char) tokenType});
+            }
+        } catch (IOException e) {
+            fail("IOException while attempting to read input stream", e);
+            return null;
+        }
+    }
+
+    public void fail(String message) throws ParseException {
+        throw new ParseException(message, st.lineno(), -1, systemId);
+    }
+
+    public void fail(String message, Throwable e) throws ParseException {
+        throw new ParseException(message, e, st.lineno(), -1, systemId);
+    }
+
+    public void fail(Throwable e) throws ParseException {
+        throw new ParseException(e, st.lineno(), -1, systemId);
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/Lexer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/Lexer.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/ParseException.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/ParseException.java?rev=644745&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/ParseException.java (added)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/ParseException.java Fri Apr  4 08:55:26 2008
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.spi.commons.nodetype.compact;
+
+/**
+ * ParseException
+ */
+public class ParseException extends Exception {
+
+    /**
+     * the line number where the error occurred
+     */
+    private final int lineNumber;
+
+    /**
+     * the column number where the error occurred
+     */
+    private final int colNumber;
+
+    /**
+     * the systemid of the source that produced the error
+     */
+    private final String systemId;
+
+
+    /**
+     * Constructs a new instance of this class with <code>null</code> as its
+     * detail message.
+     */
+    public ParseException(int lineNumber, int colNumber, String systemId) {
+        super();
+        this.lineNumber = lineNumber;
+        this.colNumber = colNumber;
+        this.systemId = systemId;
+    }
+
+    /**
+     * Constructs a new instance of this class with the specified detail
+     * message.
+     *
+     * @param message the detail message. The detail message is saved for
+     *                later retrieval by the {@link #getMessage()} method.
+     */
+    public ParseException(String message, int lineNumber, int colNumber, String systemId) {
+        super(message);
+        this.lineNumber = lineNumber;
+        this.colNumber = colNumber;
+        this.systemId = systemId;
+    }
+
+    /**
+     * Constructs a new instance of this class with the specified detail
+     * message and root cause.
+     *
+     * @param message   the detail message. The detail message is saved for
+     *                  later retrieval by the {@link #getMessage()} method.
+     * @param rootCause root failure cause
+     */
+    public ParseException(String message, Throwable rootCause, int lineNumber, int colNumber, String systemId) {
+        super(message, rootCause);
+        this.lineNumber = lineNumber;
+        this.colNumber = colNumber;
+        this.systemId = systemId;
+    }
+
+    /**
+     * Constructs a new instance of this class with the specified root cause.
+     *
+     * @param rootCause root failure cause
+     */
+    public ParseException(Throwable rootCause, int lineNumber, int colNumber, String systemId) {
+        super(rootCause);
+        this.lineNumber = lineNumber;
+        this.colNumber = colNumber;
+        this.systemId = systemId;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getMessage() {
+        StringBuffer b = new StringBuffer(super.getMessage());
+        String delim = " (";
+        if (systemId != null && !systemId.equals("")) {
+            b.append(delim);
+            b.append(systemId);
+            delim = ", ";
+        }
+        if (lineNumber >= 0) {
+            b.append(delim);
+            b.append("line ");
+            b.append(lineNumber);
+            delim = ", ";
+        }
+        if (colNumber >= 0) {
+            b.append(delim);
+            b.append("col ");
+            b.append(colNumber);
+            delim = ", ";
+        }
+        if (delim.equals(", ")) {
+            b.append(")");
+        }
+        return b.toString();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String toString() {
+        return super.toString(); // + " (" + systemId + ", line " + lineNumber +", col " + colNumber +")";
+    }
+
+}

Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/ParseException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/ParseException.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QNodeTypeDefinitionsBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QNodeTypeDefinitionsBuilder.java?rev=644745&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QNodeTypeDefinitionsBuilder.java (added)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QNodeTypeDefinitionsBuilder.java Fri Apr  4 08:55:26 2008
@@ -0,0 +1,453 @@
+/*
+ * 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.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.commons.conversion.NamePathResolver;
+import org.apache.jackrabbit.spi.commons.nodetype.InvalidConstraintException;
+
+/**
+ * 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
+     * @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;
+
+        /**
+         * Set the name of the node type definition being built
+         * @param name
+         */
+        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.
+         */
+        public Name getName() {
+            return name;
+        }
+
+        /**
+         * Specifies the supertypes of the node type definition being built
+         * @param supertypes
+         */
+        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
+         */
+        public Name[] getSuperTypes() {
+            return supertypes;
+        }
+
+        /**
+         * @param isMixin true if building a mixin node type definition; false otherwise.
+         */
+        public void setMixin(boolean isMixin) {
+            this.isMixin = isMixin;
+        }
+
+        /**
+         * @return true if building a mixin node type definition; false otherwise.
+         */
+        public boolean getMixin() {
+            return isMixin;
+        }
+
+        /**
+         * @param isOrderable true if building a node type having orderable child nodes; false
+         *                otherwise.
+         */
+        public void setOrderableChildNodes(boolean isOrderable) {
+            this.isOrderable = isOrderable;
+        }
+
+        /**
+         * @return true if building a node type having orderable child nodes; false otherwise.
+         */
+        public boolean getOrderableChildNodes() {
+            return isOrderable;
+        }
+
+        /**
+         * @param primaryItemName  the name of the primary item or <code>null</code> if not set.
+         */
+        public void setPrimaryItemName(Name primaryItemName) {
+            this.primaryItemName = primaryItemName;
+        }
+
+        /**
+         * @return the name of the primary item or <code>null</code> if not set.
+         */
+        public Name getPrimaryItemName() {
+            return primaryItemName;
+        }
+
+        /**
+         * @param propDefs an array containing the property definitions of the node type definition
+         *                being built.
+         */
+        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.
+         */
+        public QPropertyDefinition[] getPropertyDefs() {
+            return propertyDefinitions;
+        }
+
+        /**
+         * @param childDefs an array containing the child node definitions of the node type
+         *                definition being.
+         */
+        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.
+         */
+        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
+         */
+        public void setName(Name name) {
+            this.name = name;
+        }
+
+        /**
+         * @return the name of the child item definition being build.
+         */
+        public Name getName() {
+            return name;
+        }
+
+        /**
+         * @param type  the name of the declaring node type.
+         */
+        public void setDeclaringNodeType(Name type) {
+            declaringType = type;
+        }
+
+        /**
+         * @return the name of the declaring node type.
+         */
+        public Name getDeclaringNodeType() {
+            return declaringType;
+        }
+
+        /**
+         * @param autocreate  true if building a 'autocreate' child item definition, false otherwise.
+         */
+        public void setAutoCreated(boolean autocreate) {
+            isAutocreated = autocreate;
+        }
+
+        /**
+         * @return true if building a 'autocreate' child item definition, false otherwise.
+         */
+        public boolean getAutoCreated() {
+            return isAutocreated;
+        }
+
+        /**
+         * @param onParent the 'onParentVersion' attribute of the child item definition being built
+         */
+        public void setOnParentVersion(int onParent) {
+            onParentVersion = onParent;
+        }
+
+        /**
+         * @return the 'onParentVersion' attribute of the child item definition being built
+         */
+        public int getOnParentVersion() {
+            return onParentVersion;
+        }
+
+        /**
+         * @param isProtected true if building a 'protected' child item definition, false otherwise.
+         */
+        public void setProtected(boolean isProtected) {
+            this.isProtected = isProtected;
+        }
+
+        /**
+         * @return  true if building a 'protected' child item definition, false otherwise.
+         */
+        public boolean getProtected() {
+            return isProtected;
+        }
+
+        /**
+         * @param isMandatory true if building a 'mandatory' child item definition, false otherwise.
+         */
+        public void setMandatory(boolean isMandatory) {
+            this.isMandatory = isMandatory;
+        }
+
+        /**
+         * @return  true if building a 'mandatory' child item definition, false otherwise.
+         */
+        public boolean getMandatory() {
+            return isMandatory;
+        }
+    }
+
+    /**
+     * A builder for a {@link QNodeDefinition}
+     */
+    public abstract class QPropertyDefinitionBuilder extends QItemDefinitionBuilder {
+        private int requiredType;
+        private String[] valueConstraints;
+        private QValue[] defaultValues;
+        private boolean isMultiple;
+
+        /**
+         * @param type the required type of the property definition being built.
+         */
+        public void setRequiredType(int type) {
+            requiredType = type;
+        }
+
+        /**
+         * @return the required type of the property definition being built.
+         */
+        public int getRequiredType() {
+            return requiredType;
+        }
+
+        /**
+         * @param constraints array of value constraints of the property definition being built.
+         */
+        public void setValueConstraints(String[] constraints) {
+            valueConstraints = constraints;
+        }
+
+        /**
+         * @return array of value constraints of the property definition being built.
+         */
+        public String[] getValueConstraints() {
+            return valueConstraints;
+        }
+
+        /**
+         * @param values array of default values of the property definition being built.
+         */
+        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.
+         */
+        public QValue[] getDefaultValues() {
+            return defaultValues;
+        }
+
+        /**
+         * @param isMultiple true if building a 'multiple' property definition.
+         */
+        public void setMultiple(boolean isMultiple) {
+            this.isMultiple = isMultiple;
+        }
+
+        /**
+         * @return true if building a 'multiple' property definition.
+         */
+        public boolean getMultiple() {
+            return isMultiple;
+        }
+
+        /**
+         * Validate the given <code>constraint</code> and resolve any prefixes.
+         *
+         * @param constraint
+         * @param resolver
+         * @return A syntactically valid value constrained which refers to fully qualified names and
+         *         paths only.
+         * @throws InvalidConstraintException if <code>constraint</code> cannot be converted to a
+         *                 valid value constrained.
+         */
+        public abstract String 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
+         * @param 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;
+    }
+
+}

Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QNodeTypeDefinitionsBuilder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QNodeTypeDefinitionsBuilder.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QNodeTypeDefinitionsBuilderImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QNodeTypeDefinitionsBuilderImpl.java?rev=644745&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QNodeTypeDefinitionsBuilderImpl.java (added)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QNodeTypeDefinitionsBuilderImpl.java Fri Apr  4 08:55:26 2008
@@ -0,0 +1,138 @@
+/*
+ * 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.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.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(),
+                    this.getMixin(),
+                    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 String createValueConstraint(String constraint, NamePathResolver resolver)
+                throws InvalidConstraintException {
+
+            return ValueConstraint.create(getRequiredType(), constraint, resolver).getQualifiedDefinition();
+        }
+
+        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());
+        }
+
+    }
+
+    /**
+     * 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());
+        }
+
+    }
+
+}

Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QNodeTypeDefinitionsBuilderImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/nodetype/compact/QNodeTypeDefinitionsBuilderImpl.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/nodetype/BooleanConstraintTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/nodetype/BooleanConstraintTest.java?rev=644745&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/nodetype/BooleanConstraintTest.java (added)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/nodetype/BooleanConstraintTest.java Fri Apr  4 08:55:26 2008
@@ -0,0 +1,79 @@
+/*
+ * 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;
+
+import org.apache.jackrabbit.spi.QValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.ConstraintViolationException;
+
+/**
+ * <code>BooleanConstraintTest</code>...
+ */
+public class BooleanConstraintTest extends ValueConstraintTest {
+
+    private static Logger log = LoggerFactory.getLogger(BooleanConstraintTest.class);
+
+    protected ValueConstraint createInvalidConstraint() throws RepositoryException {
+        return new BooleanConstraint("test");
+    }
+
+    protected ValueConstraint createValueConstraint(String definition) throws RepositoryException {
+        return new BooleanConstraint(definition);
+    }
+
+    protected int getType() {
+        return PropertyType.BOOLEAN;
+    }
+
+    protected String[] getInvalidQualifiedDefinitions() {
+        return new String[] {"test", "/abc/d", "12345"};
+    }
+
+    protected String[] getDefinitions() {
+        return new String[] { Boolean.TRUE.toString()};
+    }
+
+    protected String[] getQualifiedDefinitions() {
+        return getDefinitions();
+    }
+
+    protected QValue[] createNonMatchingValues() throws RepositoryException {
+        return new QValue[] {
+                valueFactory.create(Boolean.FALSE.toString(), PropertyType.BOOLEAN),
+                valueFactory.create(Boolean.TRUE.toString(), PropertyType.BOOLEAN)
+        };
+    }
+
+    protected QValue createOtherValueType() throws RepositoryException {
+        return valueFactory.create(1345);
+    }
+
+    public void testTrueConstraint() throws RepositoryException, ConstraintViolationException {
+        ValueConstraint vc = new BooleanConstraint(Boolean.TRUE.toString());
+        vc.check(valueFactory.create(Boolean.TRUE.toString(), PropertyType.BOOLEAN));
+        try {
+           vc.check(valueFactory.create(Boolean.FALSE.toString(), PropertyType.BOOLEAN));
+            fail();
+        } catch (ConstraintViolationException e) {
+            // ok
+        }
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/nodetype/BooleanConstraintTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/nodetype/BooleanConstraintTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/nodetype/DateConstraintTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/nodetype/DateConstraintTest.java?rev=644745&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/nodetype/DateConstraintTest.java (added)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/nodetype/DateConstraintTest.java Fri Apr  4 08:55:26 2008
@@ -0,0 +1,75 @@
+/*
+ * 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;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.spi.QValue;
+import org.apache.jackrabbit.value.DateValue;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.PropertyType;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * <code>DateConstraintTest</code>...
+ */
+public class DateConstraintTest extends ValueConstraintTest {
+
+    private static Logger log = LoggerFactory.getLogger(DateConstraintTest.class);
+
+    protected int getType() {
+        return PropertyType.DATE;
+    }
+
+    protected String[] getInvalidQualifiedDefinitions() {
+        return new String[] {"abc", "-18", "1234567"};
+    }
+
+    protected String[] getDefinitions() throws RepositoryException {
+        Calendar c1 = Calendar.getInstance();
+        c1.setTimeInMillis(234567);
+
+        Calendar c2 = Calendar.getInstance();
+        c2.setTime(new Date());
+
+        StringBuffer b = new StringBuffer("(");
+        b.append(new DateValue(c1).getString());
+        b.append(",");
+        b.append(new DateValue(c2).getString());
+        b.append(")");
+
+        return new String[] {b.toString()};
+    }
+
+    protected String[] getQualifiedDefinitions() throws RepositoryException {
+        return getDefinitions();
+    }
+
+    protected QValue[] createNonMatchingValues() throws RepositoryException {
+        Calendar cd = Calendar.getInstance();
+        cd.setTimeInMillis(997);
+        return new QValue[] {valueFactory.create(cd)};
+    }
+
+    protected QValue createOtherValueType() throws RepositoryException {
+        return valueFactory.create(resolver.getQName("abc"));
+    }
+
+    // TODO: add more
+}

Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/nodetype/DateConstraintTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/nodetype/DateConstraintTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url