[dna-commits] DNA SVN: r840 - in trunk: dna-cnd and 31 other directories.

dna-commits at lists.jboss.org dna-commits at lists.jboss.org
Mon Apr 20 15:07:48 EDT 2009


Author: rhauch
Date: 2009-04-20 15:07:48 -0400 (Mon, 20 Apr 2009)
New Revision: 840

Added:
   trunk/dna-cnd/
   trunk/dna-cnd/.classpath
   trunk/dna-cnd/.project
   trunk/dna-cnd/.settings/
   trunk/dna-cnd/.settings/org.eclipse.jdt.core.prefs
   trunk/dna-cnd/pom.xml
   trunk/dna-cnd/src/
   trunk/dna-cnd/src/main/
   trunk/dna-cnd/src/main/antlr/
   trunk/dna-cnd/src/main/antlr/org/
   trunk/dna-cnd/src/main/antlr/org/jboss/
   trunk/dna-cnd/src/main/antlr/org/jboss/dna/
   trunk/dna-cnd/src/main/antlr/org/jboss/dna/cnd/
   trunk/dna-cnd/src/main/antlr/org/jboss/dna/cnd/Cnd.g
   trunk/dna-cnd/src/main/antlr3/
   trunk/dna-cnd/src/main/antlr3/org/
   trunk/dna-cnd/src/main/antlr3/org/jboss/
   trunk/dna-cnd/src/main/antlr3/org/jboss/dna/
   trunk/dna-cnd/src/main/antlr3/org/jboss/dna/cnd/
   trunk/dna-cnd/src/main/antlr3/org/jboss/dna/cnd/Cnd.g
   trunk/dna-cnd/src/main/java/
   trunk/dna-cnd/src/main/java/org/
   trunk/dna-cnd/src/main/java/org/jboss/
   trunk/dna-cnd/src/main/java/org/jboss/dna/
   trunk/dna-cnd/src/main/java/org/jboss/dna/cnd/
   trunk/dna-cnd/src/main/java/org/jboss/dna/cnd/CndI18n.java
   trunk/dna-cnd/src/main/java/org/jboss/dna/cnd/CndImporter.java
   trunk/dna-cnd/src/main/java/org/jboss/dna/cnd/QueryOperator.java
   trunk/dna-cnd/src/main/resources/
   trunk/dna-cnd/src/main/resources/org/
   trunk/dna-cnd/src/main/resources/org/jboss/
   trunk/dna-cnd/src/main/resources/org/jboss/dna/
   trunk/dna-cnd/src/main/resources/org/jboss/dna/cnd/
   trunk/dna-cnd/src/main/resources/org/jboss/dna/cnd/CndI18n.properties
   trunk/dna-cnd/src/test/
   trunk/dna-cnd/src/test/java/
   trunk/dna-cnd/src/test/java/org/
   trunk/dna-cnd/src/test/java/org/jboss/
   trunk/dna-cnd/src/test/java/org/jboss/dna/
   trunk/dna-cnd/src/test/java/org/jboss/dna/cnd/
   trunk/dna-cnd/src/test/java/org/jboss/dna/cnd/CndImporterTest.java
   trunk/dna-cnd/src/test/resources/
   trunk/dna-cnd/src/test/resources/cnd/
   trunk/dna-cnd/src/test/resources/cnd/empty.cnd
   trunk/dna-cnd/src/test/resources/cnd/images.cnd
   trunk/dna-cnd/src/test/resources/cnd/invalid.cnd
   trunk/dna-cnd/src/test/resources/cnd/jcr-builtins-170.cnd
   trunk/dna-cnd/src/test/resources/cnd/jcr-builtins-283-early-draft.cnd
   trunk/dna-cnd/src/test/resources/cnd/mp3.cnd
   trunk/dna-cnd/src/test/resources/log4j.properties
Modified:
   trunk/pom.xml
Log:
DNA-363 Define node types via CND files

Added a new 'dna-cnd' project containing a graph importer that reads JCR CND files and populates a repository with the content (based upon the JCR 'nt:nodeType', 'nt:propertyDefinition', and 'nt:childNodeDefinition').


Property changes on: trunk/dna-cnd
___________________________________________________________________
Name: svn:ignore
   + target


Added: trunk/dna-cnd/.classpath
===================================================================
--- trunk/dna-cnd/.classpath	                        (rev 0)
+++ trunk/dna-cnd/.classpath	2009-04-20 19:07:48 UTC (rev 840)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src/main/java"/>
+	<classpathentry kind="src" path="src/main/resources"/>
+	<classpathentry kind="src" path="src/main/antlr3"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="src" path="target/generated-sources/antlr3"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>

Added: trunk/dna-cnd/.project
===================================================================
--- trunk/dna-cnd/.project	                        (rev 0)
+++ trunk/dna-cnd/.project	2009-04-20 19:07:48 UTC (rev 840)
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>dna-cnd</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+        <buildCommand>
+            <name>org.eclipse.jdt.core.javabuilder</name>
+            <arguments>
+            </arguments>
+        </buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+        <buildCommand>
+            <name>org.antlr.eclipse.core.warningcleanerbuilder</name>
+            <arguments>
+            </arguments>
+        </buildCommand>
+        <buildCommand>
+            <name>org.antlr.eclipse.core.smapbuilder</name>
+            <arguments>
+            </arguments>
+        </buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>

Added: trunk/dna-cnd/.settings/org.eclipse.jdt.core.prefs
===================================================================
--- trunk/dna-cnd/.settings/org.eclipse.jdt.core.prefs	                        (rev 0)
+++ trunk/dna-cnd/.settings/org.eclipse.jdt.core.prefs	2009-04-20 19:07:48 UTC (rev 840)
@@ -0,0 +1,60 @@
+#Fri Apr 17 14:06:37 CDT 2009
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=error
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=error
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=error
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=error
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=error
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=disabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=ignore
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=enabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning

Added: trunk/dna-cnd/pom.xml
===================================================================
--- trunk/dna-cnd/pom.xml	                        (rev 0)
+++ trunk/dna-cnd/pom.xml	2009-04-20 19:07:48 UTC (rev 840)
@@ -0,0 +1,107 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <artifactId>dna</artifactId>
+    <groupId>org.jboss.dna</groupId>
+    <version>0.4-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.jboss.dna</groupId>
+  <artifactId>dna-cnd</artifactId>
+  <name>JBoss DNA CND Utility</name>
+  <description>JBoss DNA utility for processing and working with JCR CND files</description>
+  <dependencies>
+    <dependency>
+      <groupId>org.jboss.dna</groupId>
+      <artifactId>dna-common</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.dna</groupId>
+      <artifactId>dna-graph</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.antlr</groupId>
+      <artifactId>antlr-runtime</artifactId>
+      <version>3.1.3</version>        
+      <exclusions>
+        <exclusion>
+          <groupId>org.antlr</groupId>
+          <artifactId>stringtemplate</artifactId>
+        </exclusion>                                  
+      </exclusions>                        
+    </dependency>
+    
+    <!-- Testing -->
+    <dependency>
+      <groupId>org.jboss.dna</groupId>
+      <artifactId>dna-graph</artifactId>
+      <version>${pom.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+	  <dependency>
+	    <groupId>org.antlr</groupId>
+	    <artifactId>antlr</artifactId>
+	    <version>3.1.3</version>
+      <exclusions>
+        <exclusion>
+          <groupId>org.antlr</groupId>
+          <artifactId>stringtemplate</artifactId>
+        </exclusion>      
+        <exclusion>
+          <groupId>org.apache.maven</groupId>
+          <artifactId>maven-project</artifactId>
+        </exclusion>                                                                
+      </exclusions>                                             
+	    <!-- we try to use scope to hide it from transitivity -->
+	    <scope>test</scope> <!-- or perhaps 'provided' (see later discussion) or 'import' (maven >= 2.0.9) -->
+	  </dependency>
+		<dependency>
+      <groupId>org.hamcrest</groupId>
+      <artifactId>hamcrest-library</artifactId>
+    </dependency>
+    <!-- 
+    Logging (require SLF4J API for compiling, but use Log4J and its SLF4J binding for testing) 
+    -->
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>log4j</groupId>
+      <artifactId>log4j</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <!-- 
+    Java Concurrency in Practice annotations
+    -->
+    <dependency>
+      <groupId>net.jcip</groupId>
+      <artifactId>jcip-annotations</artifactId>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.antlr</groupId>
+        <artifactId>antlr3-maven-plugin</artifactId>
+        <version>3.1.3-1</version>
+        <executions>
+          <execution>
+            <goals>
+              <goal>antlr</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
\ No newline at end of file

Added: trunk/dna-cnd/src/main/antlr/org/jboss/dna/cnd/Cnd.g
===================================================================
--- trunk/dna-cnd/src/main/antlr/org/jboss/dna/cnd/Cnd.g	                        (rev 0)
+++ trunk/dna-cnd/src/main/antlr/org/jboss/dna/cnd/Cnd.g	2009-04-20 19:07:48 UTC (rev 840)
@@ -0,0 +1,360 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of 
+ * individual contributors. 
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+grammar Cnd;
+
+options {
+	output=AST;
+}
+
+
+tokens {
+	NAMESPACES;
+	PREFIX;
+	URI;
+	NODE;
+	NAME;
+	PRIMARY_TYPE;
+	SUPERTYPES;
+	NODE_TYPES;
+	NODE_TYPE_ATTRIBUTES;
+	HAS_ORDERABLE_CHILD_NODES;
+	IS_MIXIN;
+	IS_ABSTRACT;
+	IS_QUERYABLE;
+	PRIMARY_ITEM_NAME;
+	PROPERTY_DEFINITION;
+	REQUIRED_TYPE;
+	DEFAULT_VALUES;
+	VALUE_CONSTRAINTS;
+	AUTO_CREATED;
+	MANDATORY;
+	PROTECTED;
+	REQUIRED_TYPE;
+	ON_PARENT_VERSION;
+	MULTIPLE;
+	QUERY_OPERATORS;
+	IS_FULL_TEXT_SEARCHABLE;
+	IS_QUERY_ORDERERABLE;
+	CHILD_NODE_DEFINITION;
+	REQUIRED_PRIMARY_TYPES;
+	DEFAULT_PRIMARY_TYPE;
+	SAME_NAME_SIBLINGS;
+}
+
+ at header {
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of 
+ * individual contributors. 
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.cnd;
+}
+
+ at members {
+ at Override
+public void emitErrorMessage( String msg ) {
+    // don't write messages to System.err ...
+    //super.emitErrorMessage(msg);
+}
+}
+
+ at lexer::header {
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of 
+ * individual contributors. 
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.cnd;
+}
+
+ at rulecatch {
+  catch (RecognitionException re) {
+    reportError(re);
+  }
+}
+
+// ------------
+// Parser rules
+// ------------
+
+// These rules generate an AST that was designed with a structure that may be 
+// automatically processed into a graph structure.  This structure is:
+//
+//   NAMESPACES
+//    +- NODE (multiple)
+//        +- PREFIX
+//            +- string value
+//        +- URI
+//            +- string value
+//   NODE_TYPES
+//    +- NODE (multiple)
+//        +- NAME                                 [nt:nodeType/@jcr:name]
+//            +- string value
+//        +- PRIMARY_TYPE                         [nt:base/@jcr:primaryType]
+//            +- string with value 'nt:nodeType'
+//        +- SUPERTYPES                           [nt:nodeType/@jcr:supertypes]
+//            +- string value(s)
+//        +- IS_ABSTRACT                          [nt:nodeType/@jcr:isAbstract]
+//            +- string containing boolean value (or false if not present)
+//        +- HAS_ORDERABLE_CHILD_NODES            [nt:nodeType/@jcr:hasOrderableChildNodes]
+//            +- string containing boolean value (or false if not present)
+//        +- IS_MIXIN                             [nt:nodeType/@jcr:isMixin]
+//            +- string containing boolean value (or false if not present)
+//        +- IS_QUERYABLE                         [nt:nodeType/@jcr:isQueryable]
+//            +- string containing boolean value (or true if not present)
+//        +- PRIMARY_ITEM_NAME                    [nt:nodeType/@jcr:primaryItemName]
+//            +- string containing string value
+//        +- PROPERTY_DEFINITION                  [nt:nodeType/@jcr:propertyDefinition]
+//            +- NODE (multiple)
+//                +- NAME                         [nt:propertyDefinition/@jcr:name]
+//                    +- string value
+//                +- PRIMARY_TYPE                 [nt:base/@jcr:primaryType]
+//                    +- string with value 'nt:propertyDefinition'
+//                +- REQUIRED_TYPE                [nt:propertyDefinition/@jcr:propertyType]
+//                    +- string value (limited to one of the predefined types)
+//                +- DEFAULT_VALUES               [nt:propertyDefinition/@jcr:defaultValues]
+//                    +- string value(s)
+//                +- MULTIPLE                     [nt:propertyDefinition/@jcr:multiple]
+//                    +- string containing boolean value (or false if not present)
+//                +- MANDATORY                    [nt:propertyDefinition/@jcr:mandatory]
+//                    +- string containing boolean value (or false if not present)
+//                +- AUTO_CREATED                 [nt:propertyDefinition/@jcr:autoCreated]
+//                    +- string containing boolean value (or false if not present)
+//                +- PROTECTED                    [nt:propertyDefinition/@jcr:protected]
+//                    +- string containing boolean value (or false if not present)
+//                +- ON_PARENT_VERSION            [nt:propertyDefinition/@jcr:onParentVersion]
+//                    +- string value (limited to one of the predefined literal values)
+//                +- QUERY_OPERATORS              
+//                    +- string value (containing a comma-separated list of operator literals)
+//                +- IS_FULL_TEXT_SEARCHABLE      [nt:propertyDefinition/@jcr:isFullTextSearchable]
+//                    +- string containing boolean value (or true if not present)
+//                +- IS_QUERY_ORDERABLE           [nt:propertyDefinition/@jcr:isQueryOrderable]
+//                    +- string containing boolean value (or true if not present)
+//                +- VALUE_CONSTRAINTS            [nt:propertyDefinition/@jcr:valueConstraints]
+//                    +- string value(s)
+//        +- CHILD_NODE_DEFINITION                [nt:nodeType/@jcr:childNodeDefinition]
+//            +- NODE (multiple)
+//                +- NAME                         [nt:childNodeDefinition/@jcr:name]
+//                    +- string value
+//                +- PRIMARY_TYPE                 [nt:base/@jcr:primaryType]
+//                    +- string with value 'nt:childNodeDefinition'
+//                +- REQUIRED_PRIMARY_TYPES       [nt:childNodeDefinition/@jcr:requiredPrimaryTypes]
+//                    +- string values (limited to names)
+//                +- DEFAULT_PRIMARY_TYPE         [nt:childNodeDefinition/@jcr:defaultPrimaryType]
+//                    +- string value (limited to a name)
+//                +- MANDATORY                    [nt:childNodeDefinition/@jcr:mandatory]
+//                    +- string containing boolean value (or false if not present)
+//                +- AUTO_CREATED                 [nt:childNodeDefinition/@jcr:autoCreated]
+//                    +- string containing boolean value (or false if not present)
+//                +- PROTECTED                    [nt:childNodeDefinition/@jcr:protected]
+//                    +- string containing boolean value (or false if not present)
+//                +- SAME_NAME_SIBLINGS           [nt:childNodeDefinition/@jcr:sameNameSiblings]
+//                    +- string containing boolean value (or false if not present)
+//                +- ON_PARENT_VERSION            [nt:childNodeDefinition/@jcr:onParentVersion]
+//                    +- string value (limited to one of the predefined literal values)
+//
+// Comments
+// --------
+// The JSR-283 specification states that comments are allowed in CND files but are to be removed prior
+// to parsing and processing.  This grammar accomplishes this by sending the MULTI_LINE_COMMENT and
+// SINGLE_LINE_COMMENT tokens to the HIDDEN channel (along with all whitespace tokens).
+//
+// Case sensitivity
+// ----------------
+// ANTLR 3 has no way of generating a case-insensitive lexer/parser (since this is dependent upon locale).
+// However, it's possible to do this as outlined at http://www.antlr.org/wiki/pages/viewpage.action?pageId=1782.
+// Note that the approach that overrides the "LT" method does not change the content but merely changes the
+// character returned by the method, which are the characters used to match the rules.
+//
+// And this must be done for this grammar, since the CND tokens are case-insensitive.  Note that this
+// grammar defines all tokens as lower-case, so the ANTLRFileStream subclass must perform a 'toLowerCase()'
+// rather than a 'toUpperCase()'.
+//
+// Post Processing
+// ---------------
+// A number of the values in the AST must be post-processed to perform the requisite validation.
+//
+// The string values may or may not be wrapped in quotes (single or double).  Any quotes will
+// need to be removed in post-processing.
+//
+// Also, the QUERY_OPERATORS string value should contain a comma-separated list of operators 
+// wrapped by single quotes.  As noted below, this is a side effect of how this grammar's lexer
+// automatically produces a STRING token whenever single-quoted strings are found, so by the
+// time the parser rules are run, the operators are encapsulated in a STRING token.
+// (It's arguable whether this is a defect in the CND grammar, or a side effect of how this grammar
+// uses ANTLR; other parser and lexer rules were considered, but most caused a massive increase in
+// the size of the generated code and a massive decrease in performance.)  In short, these
+// operators must be validated in a post-processing step.
+//
+// Generating JCR content
+// ----------------------
+//
+// The resulting AST's structure was designed such that it directly corresponds to the "nt:nodeType", 
+// "nt:propertyDefinition", and "nt:childNodeDefinition" node types that are specified in JSR-283
+// (proposed draft), in the hopes that this approach could be used with a "standard" AST tree walker
+// that could automatically generate the JCR content.
+//
+// First of all, the structure follows a repeating multi-level pattern, where the "NODE" appears 
+// in the AST when a new node should be created, with JCR properties
+// identified by AST nodes under "NODE" that have a single child (e.g., the property's value),
+// or with JCR child nodes identified by AST nodes under "NODE" that also contain an AST "NODE"
+// (with properties below it).
+//
+// The AST node names were designed to be easily translated into property names.  ANTLR uses
+// all-caps for AST node names and '_' to separate words in those names.  To produce the JCR name,
+// simply convert the first word to lowercase, and convert to lowercase all but the first character
+// of each remaining word, and finally remove all '_' characters.
+//
+// This grammar (mostly) uses the "jcr" prefix (the namespaces should probably be "dna").
+// This could be automated by defining a mapping between the AST node names and the property names
+// (as well as defining a default namespace for any AST node name that is to be converted automatically).
+//
+cnd : (namespaceMapping|nodeTypeDefinition)* EOF
+	-> ^(NAMESPACES namespaceMapping*)? ^(NODE_TYPES nodeTypeDefinition*)? ;
+
+// Namespace mappings 
+namespaceMapping : '<' prefix '=' uri '>' -> ^(NODE prefix uri);
+prefix : STRING -> ^(PREFIX STRING);
+uri : STRING -> ^(URI STRING);
+
+// Node type definitions
+nodeTypeDefinition :	nodeTypeName supertypes? nodeTypeOptions? ( propertyDefinition | childNodeDefinition )* 
+	-> ^(NODE nodeTypeName ^(PRIMARY_TYPE STRING["nt:nodeType"]) supertypes? nodeTypeOptions? ^(PROPERTY_DEFINITION propertyDefinition*) ^(CHILD_NODE_DEFINITION childNodeDefinition*)) ;
+nodeTypeName : '[' STRING ']' -> ^(NAME STRING) ;
+supertypes : '>' stringList -> ^(SUPERTYPES stringList);
+nodeTypeOptions :	nodeTypeOption+;
+nodeTypeOption :	orderable | mixin | isAbstract | noQuery | primaryItem ;
+orderable :	('o'|'ord'|'orderable') -> ^(HAS_ORDERABLE_CHILD_NODES STRING["true"]);
+mixin :	('m' | 'mix' | 'mixin') -> ^(IS_MIXIN STRING["true"]);
+isAbstract :	('a'|'abs'|'abstract') -> ^(IS_ABSTRACT STRING["true"]);
+noQuery :	('nq'|'noquery') -> ^(IS_QUERYABLE STRING["false"]);
+primaryItem : ('primaryitem'|'!')	STRING -> ^(PRIMARY_ITEM_NAME STRING);
+
+// Property definitions ...
+propertyDefinition : propertyName propertyType? defaultValues? ( propertyAttributes | valueConstraints )*
+	-> ^(NODE propertyName ^(PRIMARY_TYPE STRING["nt:propertyDefinition"]) propertyType? defaultValues? propertyAttributes* valueConstraints*);
+propertyName : '-' STRING -> ^(NAME STRING);
+propertyType : '(' propertyTypeLiteral ')' -> ^(REQUIRED_TYPE propertyTypeLiteral); 
+propertyTypeLiteral	: ('string'|'binary'|'long'|'double'|'boolean'|'date'|'name'|'path'|'reference'|'*');
+defaultValues :	'=' stringList -> ^(DEFAULT_VALUES stringList);
+propertyAttributes : ( (onParentVersioningLiteral)=>onParentVersioning | (autoCreated)=> autoCreated | (multiple)=>multiple | (mandatory)=>mandatory | (isProtected)=>isProtected | (queryOperators)=>queryOperators | (noFullText)=>noFullText | (noQueryOrder)=>noQueryOrder)+ ;
+//propertyAttributes : ( (onParentVersioning)=> onParentVersioning | ('a')=>autoCreated | ('m')=>mandatory |('p')=>isProtected | ('mul'|'*')=>multiple | ('q')=>queryOperators | ('nof')=>noFullText | ('nqord'|'noq')=>noQueryOrder)+ ;
+valueConstraints : '<' stringList -> ^(VALUE_CONSTRAINTS stringList);
+autoCreated :	('a'|'aut'|'autocreated') -> ^(AUTO_CREATED STRING["true"]);
+mandatory :	('m'|'man'|'mandatory') -> ^(MANDATORY STRING["true"]);
+isProtected :	('p'|'pro'|'protected') -> ^(PROTECTED STRING["true"]);
+onParentVersioning :	onParentVersioningLiteral -> ^(ON_PARENT_VERSION onParentVersioningLiteral);
+onParentVersioningLiteral : ('copy'|'version'|'initialize'|'compute'|'ignore'|'abort');
+multiple :	('*'|'mul'|'multiple') -> ^(MULTIPLE STRING["true"]);
+noFullText :	('nof'|'nofulltext') -> ^(IS_FULL_TEXT_SEARCHABLE STRING["false"]);
+noQueryOrder :	('nqord'|'noqueryorder') -> ^(IS_QUERY_ORDERERABLE STRING["false"]);
+queryOperators :	('qop'|'queryops') STRING -> ^(QUERY_OPERATORS STRING);
+// The grammar defines the query operators to be wrapped by single quotes, and therefore the lexer produces a single STRING token.
+// Since we cannot break this token up, we simply store the operators as a STRING literal, and will have to process
+// at a later step.
+
+// Child node definitions ...
+childNodeDefinition : nodeName requiredTypes? defaultType? nodeAttributes?
+  -> ^(NODE nodeName ^(PRIMARY_TYPE STRING["nt:childNodeDefinition"]) requiredTypes? defaultType? nodeAttributes?);
+nodeName : '+' STRING -> ^(NAME STRING);
+requiredTypes :'(' stringList ')' -> ^(REQUIRED_PRIMARY_TYPES stringList); 
+defaultType :	'=' STRING -> ^(DEFAULT_PRIMARY_TYPE STRING);
+nodeAttributes : nodeAttribute+;
+nodeAttribute : autoCreated | mandatory | isProtected | onParentVersioning | sns ;
+sns : ('sns'|'*') -> ^(SAME_NAME_SIBLINGS STRING["true"]) ;
+
+// General rules
+stringList : STRING (',' STRING )* -> STRING*;
+
+// ------------
+// Lexer rules
+// ------------
+
+// Comments are currently sent to a separate channel
+MULTI_LINE_COMMENT : ('/*' (options {greedy=false;} : . )* '*/') { $channel=HIDDEN;};
+SINGLE_LINE_COMMENT : '//' ~('\n' | '\r')*  { $channel=HIDDEN;};
+
+// Quoted strings allow for strings containing characters that otherwise would be CND delimiters.
+// Note that the single- and double-quote characters must be escaped within the string.
+// Also note that escape sequences are allowed as well.
+STRING : QUOTED_STRING | UNQUOTED_STRING;
+
+// Quoted strings may contain escaped characters.
+fragment QUOTED_STRING
+    : '"' ( EscapeSequence | ~('\\'|'"'))* '"'
+    | '\'' ( EscapeSequence | ~('\\'|'\''))* '\'' 
+    ;
+
+fragment EscapeSequence 
+  : '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\'
+         |('0'..'3') (('0'..'7') ('0'..'7')?)?
+         |'u'(('0'..'9')|('a'..'f')) (('0'..'9')|('a'..'f')) (('0'..'9')|('a'..'f'))
+         )
+;
+
+// An unquoted string is a word delimited by whitespace and CND tokens.
+fragment UNQUOTED_STRING
+: (~(' '|'\r'|'\t'|'\u000C'|'\n'	// whitespace
+    |'='|'<'|'>'|'['|']'|','|'-'|'('|')'	// tokens
+  ))+;
+
+WS : (' '|'\r'|'\t'|'\u000C'|'\n')+	{$channel=HIDDEN;} ;
+
+

Added: trunk/dna-cnd/src/main/antlr3/org/jboss/dna/cnd/Cnd.g
===================================================================
--- trunk/dna-cnd/src/main/antlr3/org/jboss/dna/cnd/Cnd.g	                        (rev 0)
+++ trunk/dna-cnd/src/main/antlr3/org/jboss/dna/cnd/Cnd.g	2009-04-20 19:07:48 UTC (rev 840)
@@ -0,0 +1,368 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of 
+ * individual contributors. 
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+grammar Cnd;
+
+options {
+    output=AST;
+}
+
+
+tokens {
+    NAMESPACES;
+    PREFIX;
+    URI;
+    NODE;
+    NAME;
+    PRIMARY_TYPE;
+    SUPERTYPES;
+    NODE_TYPES;
+    NODE_TYPE_ATTRIBUTES;
+    HAS_ORDERABLE_CHILD_NODES;
+    IS_MIXIN;
+    IS_ABSTRACT;
+    IS_QUERYABLE;
+    PRIMARY_ITEM_NAME;
+    PROPERTY_DEFINITION;
+    REQUIRED_TYPE;
+    DEFAULT_VALUES;
+    VALUE_CONSTRAINTS;
+    AUTO_CREATED;
+    MANDATORY;
+    PROTECTED;
+    REQUIRED_TYPE;
+    ON_PARENT_VERSION;
+    MULTIPLE;
+    IS_PRIMARY_PROPERTY;
+    QUERY_OPERATORS;
+    IS_FULL_TEXT_SEARCHABLE;
+    IS_QUERY_ORDERERABLE;
+    CHILD_NODE_DEFINITION;
+    REQUIRED_PRIMARY_TYPES;
+    DEFAULT_PRIMARY_TYPE;
+    SAME_NAME_SIBLINGS;
+}
+
+ at header {
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of 
+ * individual contributors. 
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.cnd;
+}
+
+ at members {
+ at Override
+public void emitErrorMessage( String msg ) {
+    // don't write messages to System.err ...
+    //super.emitErrorMessage(msg);
+}
+}
+
+ at lexer::header {
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of 
+ * individual contributors. 
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.cnd;
+}
+
+ at rulecatch {
+  catch (RecognitionException re) {
+    reportError(re);
+  }
+}
+
+// ------------
+// Parser rules
+// ------------
+
+// These rules generate an AST that was designed with a structure that may be 
+// automatically processed into a graph structure.  This structure is:
+//
+//   NAMESPACES
+//    +- NODE (multiple)
+//        +- PREFIX
+//            +- string value
+//        +- URI
+//            +- string value
+//   NODE_TYPES
+//    +- NODE (multiple)
+//        +- NAME                                 [nt:nodeType/@jcr:name]
+//            +- string value
+//        +- PRIMARY_TYPE                         [nt:base/@jcr:primaryType]
+//            +- string with value 'nt:nodeType'
+//        +- SUPERTYPES                           [nt:nodeType/@jcr:supertypes]
+//            +- string value(s)
+//        +- IS_ABSTRACT                          [nt:nodeType/@jcr:isAbstract]
+//            +- string containing boolean value (or false if not present)
+//        +- HAS_ORDERABLE_CHILD_NODES            [nt:nodeType/@jcr:hasOrderableChildNodes]
+//            +- string containing boolean value (or false if not present)
+//        +- IS_MIXIN                             [nt:nodeType/@jcr:isMixin]
+//            +- string containing boolean value (or false if not present)
+//        +- IS_QUERYABLE                         [nt:nodeType/@jcr:isQueryable]
+//            +- string containing boolean value (or true if not present)
+//        +- PRIMARY_ITEM_NAME                    [nt:nodeType/@jcr:primaryItemName]
+//            +- string containing string value
+//        +- PROPERTY_DEFINITION                  [nt:nodeType/@jcr:propertyDefinition]
+//            +- NODE (multiple)
+//                +- NAME                         [nt:propertyDefinition/@jcr:name]
+//                    +- string value
+//                +- PRIMARY_TYPE                 [nt:base/@jcr:primaryType]
+//                    +- string with value 'nt:propertyDefinition'
+//                +- REQUIRED_TYPE                [nt:propertyDefinition/@jcr:propertyType]
+//                    +- string value (limited to one of the predefined types)
+//                +- DEFAULT_VALUES               [nt:propertyDefinition/@jcr:defaultValues]
+//                    +- string value(s)
+//                +- MULTIPLE                     [nt:propertyDefinition/@jcr:multiple]
+//                    +- string containing boolean value (or false if not present)
+//                +- MANDATORY                    [nt:propertyDefinition/@jcr:mandatory]
+//                    +- string containing boolean value (or false if not present)
+//                +- AUTO_CREATED                 [nt:propertyDefinition/@jcr:autoCreated]
+//                    +- string containing boolean value (or false if not present)
+//                +- PROTECTED                    [nt:propertyDefinition/@jcr:protected]
+//                    +- string containing boolean value (or false if not present)
+//                +- ON_PARENT_VERSION            [nt:propertyDefinition/@jcr:onParentVersion]
+//                    +- string value (limited to one of the predefined literal values)
+//                +- QUERY_OPERATORS              
+//                    +- string value (containing a comma-separated list of operator literals)
+//                +- IS_FULL_TEXT_SEARCHABLE      [nt:propertyDefinition/@jcr:isFullTextSearchable]
+//                    +- string containing boolean value (or true if not present)
+//                +- IS_QUERY_ORDERABLE           [nt:propertyDefinition/@jcr:isQueryOrderable]
+//                    +- string containing boolean value (or true if not present)
+//                +- VALUE_CONSTRAINTS            [nt:propertyDefinition/@jcr:valueConstraints]
+//                    +- string value(s)
+//        +- CHILD_NODE_DEFINITION                [nt:nodeType/@jcr:childNodeDefinition]
+//            +- NODE (multiple)
+//                +- NAME                         [nt:childNodeDefinition/@jcr:name]
+//                    +- string value
+//                +- PRIMARY_TYPE                 [nt:base/@jcr:primaryType]
+//                    +- string with value 'nt:childNodeDefinition'
+//                +- REQUIRED_PRIMARY_TYPES       [nt:childNodeDefinition/@jcr:requiredPrimaryTypes]
+//                    +- string values (limited to names)
+//                +- DEFAULT_PRIMARY_TYPE         [nt:childNodeDefinition/@jcr:defaultPrimaryType]
+//                    +- string value (limited to a name)
+//                +- MANDATORY                    [nt:childNodeDefinition/@jcr:mandatory]
+//                    +- string containing boolean value (or false if not present)
+//                +- AUTO_CREATED                 [nt:childNodeDefinition/@jcr:autoCreated]
+//                    +- string containing boolean value (or false if not present)
+//                +- PROTECTED                    [nt:childNodeDefinition/@jcr:protected]
+//                    +- string containing boolean value (or false if not present)
+//                +- SAME_NAME_SIBLINGS           [nt:childNodeDefinition/@jcr:sameNameSiblings]
+//                    +- string containing boolean value (or false if not present)
+//                +- ON_PARENT_VERSION            [nt:childNodeDefinition/@jcr:onParentVersion]
+//                    +- string value (limited to one of the predefined literal values)
+//
+// JSR-283 node types
+// ------------------
+// This grammar does support reading in the new 'decimal', 'weakreference' and 'uri' property types.  Therefore, it
+// is up to the calling component to verify that these types are allowed.  Supporting these new types means
+// that this CND grammar can be used for both JSR-170 and JSR-283.
+//
+// Comments
+// --------
+// The JSR-283 specification states that comments are allowed in CND files but are to be removed prior
+// to parsing and processing.  This grammar accomplishes this by sending the MULTI_LINE_COMMENT and
+// SINGLE_LINE_COMMENT tokens to the HIDDEN channel (along with all whitespace tokens).
+//
+// Case sensitivity
+// ----------------
+// ANTLR 3 has no way of generating a case-insensitive lexer/parser (since this is dependent upon locale).
+// However, it's possible to do this as outlined at http://www.antlr.org/wiki/pages/viewpage.action?pageId=1782.
+// Note that the approach that overrides the "LT" method does not change the content but merely changes the
+// character returned by the method, which are the characters used to match the rules.
+//
+// And this must be done for this grammar, since the CND tokens are case-insensitive.  Note that this
+// grammar defines all tokens as lower-case, so the ANTLRFileStream subclass must perform a 'toLowerCase()'
+// rather than a 'toUpperCase()'.
+//
+// Post Processing
+// ---------------
+// A number of the values in the AST must be post-processed to perform the requisite validation.
+//
+// The string values may or may not be wrapped in quotes (single or double).  Any quotes will
+// need to be removed in post-processing.
+//
+// Also, the QUERY_OPERATORS string value should contain a comma-separated list of operators 
+// wrapped by single quotes.  As noted below, this is a side effect of how this grammar's lexer
+// automatically produces a STRING token whenever single-quoted strings are found, so by the
+// time the parser rules are run, the operators are encapsulated in a STRING token.
+// (It's arguable whether this is a defect in the CND grammar, or a side effect of how this grammar
+// uses ANTLR; other parser and lexer rules were considered, but most caused a massive increase in
+// the size of the generated code and a massive decrease in performance.)  In short, these
+// operators must be validated in a post-processing step.
+//
+// Generating JCR content
+// ----------------------
+//
+// The resulting AST's structure was designed such that it directly corresponds to the "nt:nodeType", 
+// "nt:propertyDefinition", and "nt:childNodeDefinition" node types that are specified in JSR-283
+// (proposed draft), in the hopes that this approach could be used with a "standard" AST tree walker
+// that could automatically generate the JCR content.
+//
+// First of all, the structure follows a repeating multi-level pattern, where the "NODE" appears 
+// in the AST when a new node should be created, with JCR properties
+// identified by AST nodes under "NODE" that have a single child (e.g., the property's value),
+// or with JCR child nodes identified by AST nodes under "NODE" that also contain an AST "NODE"
+// (with properties below it).
+//
+// The AST node names were designed to be easily translated into property names.  ANTLR uses
+// all-caps for AST node names and '_' to separate words in those names.  To produce the JCR name,
+// simply convert the first word to lowercase, and convert to lowercase all but the first character
+// of each remaining word, and finally remove all '_' characters.
+//
+// This grammar (mostly) uses the "jcr" prefix (the namespaces should probably be "dna").
+// This could be automated by defining a mapping between the AST node names and the property names
+// (as well as defining a default namespace for any AST node name that is to be converted automatically).
+//
+cnd : (namespaceMapping|nodeTypeDefinition)* EOF
+    -> ^(NAMESPACES namespaceMapping*)? ^(NODE_TYPES nodeTypeDefinition*)? ;
+
+// Namespace mappings 
+namespaceMapping : '<' prefix '=' uri '>' -> ^(NODE prefix uri);
+prefix :
+  | 'mix' -> ^(PREFIX 'mix')    // Must break out this built-in prefix because it happens to be a keyword
+    |   STRING -> ^(PREFIX STRING);
+uri : STRING -> ^(URI STRING);
+
+// Node type definitions
+nodeTypeDefinition :    nodeTypeName supertypes? nodeTypeOptions? ( propertyDefinition | childNodeDefinition )* 
+    -> ^(NODE nodeTypeName ^(PRIMARY_TYPE STRING["nt:nodeType"]) supertypes? nodeTypeOptions? ^(PROPERTY_DEFINITION propertyDefinition*) ^(CHILD_NODE_DEFINITION childNodeDefinition*)) ;
+nodeTypeName : '[' STRING ']' -> ^(NAME STRING) ;
+supertypes : '>' stringList -> ^(SUPERTYPES stringList);
+nodeTypeOptions :   nodeTypeOption+;
+nodeTypeOption :    orderable | mixin | isAbstract | noQuery | primaryItem ;
+orderable : ('o'|'ord'|'orderable') -> ^(HAS_ORDERABLE_CHILD_NODES STRING["true"]);
+mixin : ('m' | 'mix' | 'mixin') -> ^(IS_MIXIN STRING["true"]);
+isAbstract :    ('a'|'abs'|'abstract') -> ^(IS_ABSTRACT STRING["true"]);
+noQuery :   ('nq'|'noquery') -> ^(IS_QUERYABLE STRING["false"]);
+primaryItem : ('primaryitem'|'!')   STRING -> ^(PRIMARY_ITEM_NAME STRING);
+
+// Property definitions ...
+propertyDefinition : propertyName propertyType? defaultValues? ( propertyAttributes | valueConstraints )*
+    -> ^(NODE propertyName ^(PRIMARY_TYPE STRING["nt:propertyDefinition"]) propertyType? defaultValues? propertyAttributes* valueConstraints*);
+propertyName : '-' ('*' -> ^(NAME '*') | STRING -> ^(NAME STRING));
+propertyType : '(' propertyTypeLiteral ')' -> ^(REQUIRED_TYPE propertyTypeLiteral); 
+propertyTypeLiteral : ('string'|'binary'|'long'|'double'|'boolean'|'decimal'|'date'|'name'|'path'|'reference'|'*'|'undefined'|'weakreference'|'uri');
+defaultValues : '=' stringList -> ^(DEFAULT_VALUES stringList);
+propertyAttributes : ( (isPrimary)=>isPrimary | (onParentVersioningLiteral)=>onParentVersioning | (autoCreated)=> autoCreated | (multiple)=>multiple | (mandatory)=>mandatory | (isProtected)=>isProtected | (queryOperators)=>queryOperators | (noFullText)=>noFullText | (noQueryOrder)=>noQueryOrder)+ ;
+//propertyAttributes : ( (onParentVersioning)=> onParentVersioning | ('a')=>autoCreated | ('m')=>mandatory |('p')=>isProtected | ('mul'|'*')=>multiple | ('q')=>queryOperators | ('nof')=>noFullText | ('nqord'|'noq')=>noQueryOrder)+ ;
+valueConstraints : '<' stringList -> ^(VALUE_CONSTRAINTS stringList);
+isPrimary : ('!'|'pri'|'primary') -> ^(IS_PRIMARY_PROPERTY STRING["true"]);
+autoCreated :   ('a'|'aut'|'autocreated') -> ^(AUTO_CREATED STRING["true"]);
+mandatory : ('m'|'man'|'mandatory') -> ^(MANDATORY STRING["true"]);
+isProtected :   ('p'|'pro'|'protected') -> ^(PROTECTED STRING["true"]);
+onParentVersioning :    onParentVersioningLiteral -> ^(ON_PARENT_VERSION onParentVersioningLiteral);
+onParentVersioningLiteral : ('copy'|'version'|'initialize'|'compute'|'ignore'|'abort');
+multiple :  ('*'|'mul'|'multiple') -> ^(MULTIPLE STRING["true"]);
+noFullText :    ('nof'|'nofulltext') -> ^(IS_FULL_TEXT_SEARCHABLE STRING["false"]);
+noQueryOrder :  ('nqord'|'noqueryorder') -> ^(IS_QUERY_ORDERERABLE STRING["false"]);
+queryOperators :    ('qop'|'queryops') STRING -> ^(QUERY_OPERATORS STRING);
+// The grammar defines the query operators to be wrapped by single quotes, and therefore the lexer produces a single STRING token.
+// Since we cannot break this token up, we simply store the operators as a STRING literal, and will have to process
+// at a later step.
+
+// Child node definitions ...
+childNodeDefinition : nodeName requiredTypes? defaultType? nodeAttributes?
+  -> ^(NODE nodeName ^(PRIMARY_TYPE STRING["nt:childNodeDefinition"]) requiredTypes? defaultType? nodeAttributes?);
+nodeName : '+' ('*' -> ^(NAME '*') | STRING -> ^(NAME STRING));
+requiredTypes :'(' stringList ')' -> ^(REQUIRED_PRIMARY_TYPES stringList); 
+defaultType :   '=' STRING -> ^(DEFAULT_PRIMARY_TYPE STRING);
+nodeAttributes : nodeAttribute+;
+nodeAttribute : autoCreated | mandatory | (isPrimary)=>isPrimary| (isProtected)=>isProtected | onParentVersioning | sns ;
+sns : ('sns'|'*'|'multiple') -> ^(SAME_NAME_SIBLINGS STRING["true"]) ;
+
+// General rules
+stringList : STRING (',' STRING )* -> STRING*;
+
+// ------------
+// Lexer rules
+// ------------
+
+// Comments are currently sent to a separate channel
+MULTI_LINE_COMMENT : ('/*' (options {greedy=false;} : . )* '*/') { $channel=HIDDEN;};
+SINGLE_LINE_COMMENT : '//' ~('\n' | '\r')*  { $channel=HIDDEN;};
+
+// Quoted strings allow for strings containing characters that otherwise would be CND delimiters.
+// Note that the single- and double-quote characters must be escaped within the string.
+// Also note that escape sequences are allowed as well.
+STRING : QUOTED_STRING | UNQUOTED_STRING;
+
+// Quoted strings may contain escaped characters.
+fragment QUOTED_STRING
+    : '"' ( EscapeSequence | ~('\\'|'"'))* '"'
+    | '\'' ( EscapeSequence | ~('\\'|'\''))* '\'' 
+    ;
+
+fragment EscapeSequence 
+  : '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\'
+         |('0'..'3') (('0'..'7') ('0'..'7')?)?
+         |'u'(('0'..'9')|('a'..'f')) (('0'..'9')|('a'..'f')) (('0'..'9')|('a'..'f'))
+         )
+;
+
+// An unquoted string is a word delimited by whitespace and CND tokens.
+fragment UNQUOTED_STRING
+: (~(' '|'\r'|'\t'|'\u000C'|'\n'    // whitespace
+    |'='|'<'|'>'|'['|']'|','|'-'|'('|')'    // tokens
+  ))+;
+
+WS : (' '|'\r'|'\t'|'\u000C'|'\n')+ {$channel=HIDDEN;} ;
\ No newline at end of file

Added: trunk/dna-cnd/src/main/java/org/jboss/dna/cnd/CndI18n.java
===================================================================
--- trunk/dna-cnd/src/main/java/org/jboss/dna/cnd/CndI18n.java	                        (rev 0)
+++ trunk/dna-cnd/src/main/java/org/jboss/dna/cnd/CndI18n.java	2009-04-20 19:07:48 UTC (rev 840)
@@ -0,0 +1,51 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+* See the AUTHORS.txt file in the distribution for a full listing of 
+* individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.cnd;
+
+import org.jboss.dna.common.i18n.I18n;
+
+/**
+ * @author John Verhaeg
+ * @author Randall Hauch
+ */
+public final class CndI18n {
+
+    public static I18n passthrough;
+    public static I18n errorImportingCndContent;
+    public static I18n expectedBooleanLiteral;
+    public static I18n expectedStringLiteral;
+    public static I18n expectedValidNameLiteral;
+    public static I18n expectedValidQueryOperator;
+    public static I18n expectedValidPropertyTypeName;
+    public static I18n expectedValidOnParentVersion;
+    public static I18n locationFromLineNumberAndCharacter;
+
+    static {
+        try {
+            I18n.initialize(CndI18n.class);
+        } catch (final Exception err) {
+            System.err.println(err);
+        }
+    }
+}

Added: trunk/dna-cnd/src/main/java/org/jboss/dna/cnd/CndImporter.java
===================================================================
--- trunk/dna-cnd/src/main/java/org/jboss/dna/cnd/CndImporter.java	                        (rev 0)
+++ trunk/dna-cnd/src/main/java/org/jboss/dna/cnd/CndImporter.java	2009-04-20 19:07:48 UTC (rev 840)
@@ -0,0 +1,743 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of 
+ * individual contributors.
+ *
+ * Unless otherwise indicated, all code in JBoss DNA is licensed
+ * to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ * 
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.cnd;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import net.jcip.annotations.NotThreadSafe;
+import org.antlr.runtime.ANTLRFileStream;
+import org.antlr.runtime.ANTLRInputStream;
+import org.antlr.runtime.CharStream;
+import org.antlr.runtime.CommonTokenStream;
+import org.antlr.runtime.RecognitionException;
+import org.antlr.runtime.TokenStream;
+import org.antlr.runtime.tree.CommonTree;
+import org.antlr.runtime.tree.RewriteCardinalityException;
+import org.jboss.dna.common.collection.Problems;
+import org.jboss.dna.common.i18n.I18n;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.JcrLexicon;
+import org.jboss.dna.graph.JcrNtLexicon;
+import org.jboss.dna.graph.io.Destination;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NameFactory;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.PropertyFactory;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.graph.property.ValueFormatException;
+import org.jboss.dna.graph.property.basic.LocalNamespaceRegistry;
+
+/**
+ * A class that imports the node types contained in a JCR Compact Node Definition (CND) file into graph content. The content is
+ * written using the graph structured defined by JCR and the "{@code nt:nodeType}", "{@code nt:propertyDefinition}", and "{@code
+ * nt:childNodeDefinition}" node types.
+ * <p>
+ * Although instances of this class never change their behavior and all processing is done in local contexts, {@link Destination}
+ * is not thread-safe and therefore this component may not be considered thread-safe.
+ * </p>
+ */
+ at NotThreadSafe
+public class CndImporter {
+
+    private static final Set<String> VALID_PROPERTY_TYPES = Collections.unmodifiableSet(new HashSet<String>(
+                                                                                                            Arrays.asList(new String[] {
+                                                                                                                "STRING",
+                                                                                                                "BINARY", "LONG",
+                                                                                                                "DOUBLE",
+                                                                                                                "BOOLEAN",
+                                                                                                                "DECIMAL",
+                                                                                                                "DATE", "NAME",
+                                                                                                                "PATH",
+                                                                                                                "REFERENCE",
+                                                                                                                "WEAKREFERENCE",
+                                                                                                                "URI",
+                                                                                                                "UNDEFINED"})));
+    private static final Set<String> VALID_ON_PARENT_VERSION = Collections.unmodifiableSet(new HashSet<String>(
+                                                                                                               Arrays.asList(new String[] {
+                                                                                                                   "COPY",
+                                                                                                                   "VERSION",
+                                                                                                                   "INITIALIZE",
+                                                                                                                   "COMPUTE",
+                                                                                                                   "IGNORE",
+                                                                                                                   "ABORT"})));
+    protected final Destination destination;
+    protected final Path parentPath;
+    private boolean debug = false;
+
+    /**
+     * Create a new importer that will place the content in the supplied destination under the supplied path.
+     * 
+     * @param destination the destination where content is to be written
+     * @param parentPath the path in the destination below which the generated content is to appear
+     * @throws IllegalArgumentException if either parameter is null
+     */
+    public CndImporter( Destination destination,
+                        Path parentPath ) {
+        CheckArg.isNotNull(destination, "destination");
+        CheckArg.isNotNull(parentPath, "parentPath");
+        this.destination = destination;
+        this.parentPath = parentPath;
+    }
+
+    void setDebug( boolean value ) {
+        this.debug = value;
+    }
+
+    protected ExecutionContext context() {
+        return this.destination.getExecutionContext();
+    }
+
+    protected NamespaceRegistry namespaces() {
+        return context().getNamespaceRegistry();
+    }
+
+    protected NameFactory nameFactory() {
+        return context().getValueFactories().getNameFactory();
+    }
+
+    protected ValueFactory<String> stringFactory() {
+        return context().getValueFactories().getStringFactory();
+    }
+
+    protected ValueFactory<Boolean> booleanFactory() {
+        return context().getValueFactories().getBooleanFactory();
+    }
+
+    /**
+     * Import the CND content from the supplied stream, placing the content into the importer's destination.
+     * 
+     * @param stream the stream containing the CND content
+     * @param problems where any problems encountered during import should be reported
+     * @param resourceName a logical name for the resource name to be used when reporting problems; may be null if there is no
+     *        useful name
+     * @throws IOException if there is a problem reading from the supplied stream
+     */
+    public void importFrom( InputStream stream,
+                            Problems problems,
+                            String resourceName ) throws IOException {
+        CndLexer lex = new CndLexer(new CaseInsensitiveInputStream(stream));
+        importFrom(lex, resourceName, problems);
+    }
+
+    /**
+     * Import the CND content from the supplied stream, placing the content into the importer's destination.
+     * 
+     * @param content the string containing the CND content
+     * @param problems where any problems encountered during import should be reported
+     * @param resourceName a logical name for the resource name to be used when reporting problems; may be null if there is no
+     *        useful name
+     * @throws IOException if there is a problem reading from the supplied stream
+     */
+    public void importFrom( String content,
+                            Problems problems,
+                            String resourceName ) throws IOException {
+        ByteArrayInputStream stream = new ByteArrayInputStream(content.getBytes());
+        importFrom(stream, problems, resourceName);
+    }
+
+    /**
+     * Import the CND content from the supplied stream, placing the content into the importer's destination.
+     * 
+     * @param file the file containing the CND content
+     * @param problems where any problems encountered during import should be reported
+     * @throws IOException if there is a problem reading from the supplied stream
+     */
+    public void importFrom( File file,
+                            Problems problems ) throws IOException {
+        CndLexer lex = new CndLexer(new CaseInsensitiveFileStream(file.getAbsolutePath()));
+        importFrom(lex, file.getCanonicalPath(), problems);
+    }
+
+    protected void importFrom( CndLexer lexer,
+                               String resourceName,
+                               Problems problems ) {
+        CommonTokenStream tokens = new CommonTokenStream(lexer);
+        CndParser parser = new Parser(tokens, problems, resourceName);
+
+        // Create a new context with our own namespace registry ...
+        ImportContext context = new ImportContext(context(), problems, resourceName);
+        CommonTree ast = null;
+        try {
+            ast = (CommonTree)parser.cnd().getTree();
+        } catch (RecognitionException e) {
+            // already handled by Parser, so we should not handle twice
+        } catch (RewriteCardinalityException e) {
+            // already handled by Parser, so we should not handle twice
+        } catch (RuntimeException e) {
+            problems.addError(e, CndI18n.errorImportingCndContent, (Object)resourceName, e.getMessage());
+        }
+
+        if (ast != null && problems.isEmpty()) {
+
+            // --------------
+            // Namespaces ...
+            // --------------
+
+            /* 
+              NAMESPACES
+               +- NODE (multiple)
+                   +- PREFIX
+                       +- string value
+                   +- URI
+                       +- string value
+             */
+
+            // Get the namespaces before we do anything else ...
+            CommonTree namespaces = (CommonTree)ast.getFirstChildWithType(CndLexer.NAMESPACES);
+            if (namespaces != null) {
+                for (int i = 0; i != namespaces.getChildCount(); ++i) {
+                    CommonTree namespace = (CommonTree)namespaces.getChild(i);
+                    String prefix = namespace.getFirstChildWithType(CndLexer.PREFIX).getChild(0).getText();
+                    String uri = namespace.getFirstChildWithType(CndLexer.URI).getChild(0).getText();
+                    // Register the namespace ...
+                    context.namespaces().register(removeQuotes(prefix), removeQuotes(uri));
+                }
+            }
+
+            // --------------
+            // Node Types ...
+            // --------------
+
+            /*
+            NODE_TYPES
+             +- NODE (multiple)
+                 +- NAME                                 [nt:nodeType/@jcr:name]
+                     +- string value
+                 +- PRIMARY_TYPE                         [nt:base/@jcr:primaryType]
+                     +- string with value 'nt:nodeType'
+                 +- SUPERTYPES                           [nt:nodeType/@jcr:supertypes]
+                     +- string value(s)
+                 +- IS_ABSTRACT                          [nt:nodeType/@jcr:isAbstract]
+                     +- string containing boolean value (or false if not present)
+                 +- HAS_ORDERABLE_CHILD_NODES            [nt:nodeType/@jcr:hasOrderableChildNodes]
+                     +- string containing boolean value (or false if not present)
+                 +- IS_MIXIN                             [nt:nodeType/@jcr:isMixin]
+                     +- string containing boolean value (or false if not present)
+                 +- IS_QUERYABLE                         [nt:nodeType/@jcr:isQueryable]
+                     +- string containing boolean value (or true if not present)
+                 +- PRIMARY_ITEM_NAME                    [nt:nodeType/@jcr:primaryItemName]
+                     +- string containing string value
+                 +- PROPERTY_DEFINITION                  [nt:nodeType/@jcr:propertyDefinition]
+                     +- NODE (multiple)
+                         +- NAME                         [nt:propertyDefinition/@jcr:name]
+                             +- string value
+                         +- PRIMARY_TYPE                 [nt:base/@jcr:primaryType]
+                             +- string with value 'nt:propertyDefinition'
+                         +- REQUIRED_TYPE                [nt:propertyDefinition/@jcr:propertyType]
+                             +- string value (limited to one of the predefined types)
+                         +- DEFAULT_VALUES               [nt:propertyDefinition/@jcr:defaultValues]
+                             +- string value(s)
+                         +- MULTIPLE                     [nt:propertyDefinition/@jcr:multiple]
+                             +- string containing boolean value (or false if not present)
+                         +- MANDATORY                    [nt:propertyDefinition/@jcr:mandatory]
+                             +- string containing boolean value (or false if not present)
+                         +- AUTO_CREATED                 [nt:propertyDefinition/@jcr:autoCreated]
+                             +- string containing boolean value (or false if not present)
+                         +- PROTECTED                    [nt:propertyDefinition/@jcr:protected]
+                             +- string containing boolean value (or false if not present)
+                         +- ON_PARENT_VERSION            [nt:propertyDefinition/@jcr:onParentVersion]
+                             +- string value (limited to one of the predefined literal values)
+                         +- QUERY_OPERATORS              
+                             +- string value (containing a comma-separated list of operator literals)
+                         +- IS_FULL_TEXT_SEARCHABLE      [nt:propertyDefinition/@jcr:isFullTextSearchable]
+                             +- string containing boolean value (or true if not present)
+                         +- IS_QUERY_ORDERABLE           [nt:propertyDefinition/@jcr:isQueryOrderable]
+                             +- string containing boolean value (or true if not present)
+                         +- VALUE_CONSTRAINTS            [nt:propertyDefinition/@jcr:valueConstraints]
+                             +- string value(s)
+                 +- CHILD_NODE_DEFINITION                [nt:nodeType/@jcr:childNodeDefinition]
+                     +- NODE (multiple)
+                         +- NAME                         [nt:childNodeDefinition/@jcr:name]
+                             +- string value
+                         +- PRIMARY_TYPE                 [nt:base/@jcr:primaryType]
+                             +- string with value 'nt:childNodeDefinition'
+                         +- REQUIRED_PRIMARY_TYPES       [nt:childNodeDefinition/@jcr:requiredPrimaryTypes]
+                             +- string values (limited to names)
+                         +- DEFAULT_PRIMARY_TYPE         [nt:childNodeDefinition/@jcr:defaultPrimaryType]
+                             +- string value (limited to a name)
+                         +- MANDATORY                    [nt:childNodeDefinition/@jcr:mandatory]
+                             +- string containing boolean value (or false if not present)
+                         +- AUTO_CREATED                 [nt:childNodeDefinition/@jcr:autoCreated]
+                             +- string containing boolean value (or false if not present)
+                         +- PROTECTED                    [nt:childNodeDefinition/@jcr:protected]
+                             +- string containing boolean value (or false if not present)
+                         +- SAME_NAME_SIBLINGS           [nt:childNodeDefinition/@jcr:sameNameSiblings]
+                             +- string containing boolean value (or false if not present)
+                         +- ON_PARENT_VERSION            [nt:childNodeDefinition/@jcr:onParentVersion]
+                             +- string value (limited to one of the predefined literal values)
+            */
+
+            // Get the node types ...
+            CommonTree nodeTypes = (CommonTree)ast.getFirstChildWithType(CndLexer.NODE_TYPES);
+            if (nodeTypes != null) {
+                int numNodeTypes = 0;
+                // Walk each of the nodes underneath the NODE_TYPES parent node ...
+                for (int i = 0; i != nodeTypes.getChildCount(); ++i) {
+                    CommonTree nodeType = (CommonTree)nodeTypes.getChild(i);
+                    if (this.debug) System.out.println(nodeType.toStringTree());
+                    Path nodeTypePath = context.createNodeType(nodeType, parentPath);
+                    if (nodeTypePath == null) continue;
+                    ++numNodeTypes;
+
+                    CommonTree propertyDefinitions = (CommonTree)nodeType.getFirstChildWithType(CndLexer.PROPERTY_DEFINITION);
+                    if (propertyDefinitions != null) {
+                        // Walk each of the nodes under PROPERTY_DEFINITION ...
+                        for (int j = 0; j != propertyDefinitions.getChildCount(); ++j) {
+                            CommonTree propDefn = (CommonTree)propertyDefinitions.getChild(j);
+                            context.createPropertyDefinition(propDefn, nodeTypePath);
+                        }
+                    }
+
+                    CommonTree childNodeDefinitions = (CommonTree)nodeType.getFirstChildWithType(CndLexer.CHILD_NODE_DEFINITION);
+                    if (childNodeDefinitions != null) {
+                        // Walk each of the nodes under CHILD_NODE_DEFINITION ...
+                        for (int j = 0; j != childNodeDefinitions.getChildCount(); ++j) {
+                            CommonTree childDefn = (CommonTree)childNodeDefinitions.getChild(j);
+                            context.createChildDefinition(childDefn, nodeTypePath);
+                        }
+                    }
+                }
+
+                // Submit the destination
+                destination.submit();
+            }
+        }
+    }
+
+    protected final String removeQuotes( String text ) {
+        // Remove leading and trailing quotes, if there are any ...
+        return text.replaceFirst("^['\"]+", "").replaceAll("['\"]+$", "");
+    }
+
+    /**
+     * Utility class that uses a context with a local namespace registry, along with the problems and resource name.
+     */
+    protected final class ImportContext {
+        private final ExecutionContext context;
+        private final Problems problems;
+        private final String resourceName;
+
+        protected ImportContext( ExecutionContext context,
+                                 Problems problems,
+                                 String resourceName ) {
+            // Create a context that has a local namespace registry
+            NamespaceRegistry localNamespaces = new LocalNamespaceRegistry(context.getNamespaceRegistry());
+            this.context = context.with(localNamespaces);
+            this.problems = problems;
+            this.resourceName = resourceName;
+        }
+
+        protected ExecutionContext context() {
+            return this.context;
+        }
+
+        protected NamespaceRegistry namespaces() {
+            return this.context.getNamespaceRegistry();
+        }
+
+        protected NameFactory nameFactory() {
+            return this.context.getValueFactories().getNameFactory();
+        }
+
+        protected PathFactory pathFactory() {
+            return this.context.getValueFactories().getPathFactory();
+        }
+
+        protected ValueFactory<String> stringFactory() {
+            return this.context.getValueFactories().getStringFactory();
+        }
+
+        protected ValueFactory<Boolean> booleanFactory() {
+            return this.context.getValueFactories().getBooleanFactory();
+        }
+
+        protected void recordError( CommonTree node,
+                                    I18n msg,
+                                    Object... params ) {
+            String location = CndI18n.locationFromLineNumberAndCharacter.text(node.getLine(), node.getCharPositionInLine());
+            problems.addError(msg, resourceName, location, params);
+        }
+
+        protected void recordError( Throwable throwable,
+                                    CommonTree node,
+                                    I18n msg,
+                                    Object... params ) {
+            String location = CndI18n.locationFromLineNumberAndCharacter.text(node.getLine(), node.getCharPositionInLine());
+            problems.addError(throwable, msg, resourceName, location, params);
+        }
+
+        protected Name nameFrom( CommonTree node,
+                                 int childType ) {
+            CommonTree childNode = (CommonTree)node.getFirstChildWithType(childType);
+            if (childNode != null && childNode.getChildCount() > 0) {
+                CommonTree textNode = (CommonTree)childNode.getChild(0);
+                if (textNode.getToken().getTokenIndex() < 0) return null;
+                String text = removeQuotes(childNode.getChild(0).getText());
+                try {
+                    return nameFactory().create(text);
+                } catch (ValueFormatException e) {
+                    recordError(e, node, CndI18n.expectedValidNameLiteral, text);
+                }
+            }
+            return null;
+        }
+
+        protected Name[] namesFrom( CommonTree node,
+                                    int childType ) {
+            CommonTree childNode = (CommonTree)node.getFirstChildWithType(childType);
+            if (childNode != null && childNode.getChildCount() > 0) {
+                List<Name> names = new ArrayList<Name>();
+                for (int i = 0; i != childNode.getChildCount(); ++i) {
+                    String text = removeQuotes(childNode.getChild(i).getText());
+                    try {
+                        names.add(nameFactory().create(text));
+                    } catch (ValueFormatException e) {
+                        recordError(e, node, CndI18n.expectedValidNameLiteral, text);
+                    }
+                }
+                return names.toArray(new Name[names.size()]);
+            }
+            return new Name[] {};
+        }
+
+        protected String stringFrom( CommonTree node,
+                                     int childType ) {
+            CommonTree childNode = (CommonTree)node.getFirstChildWithType(childType);
+            if (childNode != null && childNode.getChildCount() > 0) {
+                String text = removeQuotes(childNode.getChild(0).getText().trim());
+                try {
+                    return stringFactory().create(text);
+                } catch (ValueFormatException e) {
+                    recordError(e, node, CndI18n.expectedStringLiteral, text);
+                }
+            }
+            return null;
+        }
+
+        protected String[] stringsFrom( CommonTree node,
+                                        int childType ) {
+            CommonTree childNode = (CommonTree)node.getFirstChildWithType(childType);
+            if (childNode != null && childNode.getChildCount() > 0) {
+                List<String> names = new ArrayList<String>();
+                for (int i = 0; i != childNode.getChildCount(); ++i) {
+                    String text = removeQuotes(childNode.getChild(i).getText().trim());
+                    try {
+                        names.add(stringFactory().create(text));
+                    } catch (ValueFormatException e) {
+                        recordError(e, node, CndI18n.expectedStringLiteral, text);
+                    }
+                }
+                return names.toArray(new String[names.size()]);
+            }
+            return new String[] {};
+        }
+
+        protected boolean booleanFrom( CommonTree node,
+                                       int childType,
+                                       boolean defaultValue ) {
+            CommonTree childNode = (CommonTree)node.getFirstChildWithType(childType);
+            if (childNode != null && childNode.getChildCount() > 0) {
+                String text = removeQuotes(childNode.getChild(0).getText());
+                try {
+                    return booleanFactory().create(text);
+                } catch (ValueFormatException e) {
+                    recordError(e, node, CndI18n.expectedBooleanLiteral, text);
+                }
+            }
+            return defaultValue;
+        }
+
+        protected QueryOperator[] queryOperatorsFrom( CommonTree node,
+                                                      int childType ) {
+            String text = stringFrom(node, childType);
+            if (text != null) {
+                String[] literals = text.split(",");
+                if (literals.length != 0) {
+                    Set<QueryOperator> operators = new HashSet<QueryOperator>();
+                    for (String literal : literals) {
+                        literal = literal.trim();
+                        if (literal.length() == 0) continue;
+                        QueryOperator operator = QueryOperator.forText(literal);
+                        if (operator != null) {
+                            operators.add(operator);
+                        } else {
+                            recordError(node, CndI18n.expectedValidQueryOperator, literal);
+                        }
+                    }
+                    return operators.toArray(new QueryOperator[operators.size()]);
+                }
+            }
+            return new QueryOperator[] {};
+        }
+
+        protected String propertyTypeNameFrom( CommonTree node,
+                                               int childType ) {
+            String text = stringFrom(node, childType);
+            if (text.equals("*")) text = "undefined";
+            String upperText = text.toUpperCase();
+            if (!VALID_PROPERTY_TYPES.contains(upperText)) {
+                recordError(node, CndI18n.expectedValidPropertyTypeName, text, VALID_PROPERTY_TYPES);
+                return null;
+            }
+            return upperText;
+        }
+
+        protected String onParentVersionFrom( CommonTree node,
+                                              int childType ) {
+            String text = stringFrom(node, childType);
+            if (text == null) return "COPY";
+            String upperText = text.toUpperCase();
+            if (!VALID_ON_PARENT_VERSION.contains(upperText)) {
+                recordError(node, CndI18n.expectedValidOnParentVersion, text, VALID_ON_PARENT_VERSION);
+                return null;
+            }
+            return upperText;
+        }
+
+        protected Path createNodeType( CommonTree nodeType,
+                                       Path parentPath ) {
+            Name name = nameFrom(nodeType, CndLexer.NAME);
+            Name[] supertypes = namesFrom(nodeType, CndLexer.SUPERTYPES);
+            boolean isAbstract = booleanFrom(nodeType, CndLexer.IS_ABSTRACT, false);
+            boolean hasOrderableChildNodes = booleanFrom(nodeType, CndLexer.HAS_ORDERABLE_CHILD_NODES, false);
+            boolean isMixin = booleanFrom(nodeType, CndLexer.IS_MIXIN, false);
+            boolean isQueryable = booleanFrom(nodeType, CndLexer.IS_QUERYABLE, true);
+            Name primaryItemName = nameFrom(nodeType, CndLexer.PRIMARY_ITEM_NAME);
+
+            if (primaryItemName == null) {
+                // See if one of the property definitions is marked as the primary ...
+                CommonTree propertyDefinitions = (CommonTree)nodeType.getFirstChildWithType(CndLexer.PROPERTY_DEFINITION);
+                if (propertyDefinitions != null) {
+                    // Walk each of the nodes under PROPERTY_DEFINITION ...
+                    for (int j = 0; j != propertyDefinitions.getChildCount(); ++j) {
+                        CommonTree propDefn = (CommonTree)propertyDefinitions.getChild(j);
+                        if (booleanFrom(propDefn, CndLexer.IS_PRIMARY_PROPERTY, false)) {
+                            primaryItemName = nameFrom(propDefn, CndLexer.NAME);
+                            break;
+                        }
+                    }
+                }
+            }
+            if (primaryItemName == null) {
+                // See if one of the child definitions is marked as the primary ...
+                CommonTree childNodeDefinitions = (CommonTree)nodeType.getFirstChildWithType(CndLexer.CHILD_NODE_DEFINITION);
+                if (childNodeDefinitions != null) {
+                    // Walk each of the nodes under CHILD_NODE_DEFINITION ...
+                    for (int j = 0; j != childNodeDefinitions.getChildCount(); ++j) {
+                        CommonTree childDefn = (CommonTree)childNodeDefinitions.getChild(j);
+                        if (booleanFrom(childDefn, CndLexer.IS_PRIMARY_PROPERTY, false)) {
+                            primaryItemName = nameFrom(childDefn, CndLexer.NAME);
+                            break;
+                        }
+                    }
+                }
+            }
+
+            // Create the node for the node type ...
+            if (name == null) return null;
+            Path path = pathFactory().create(parentPath, name);
+
+            PropertyFactory factory = context.getPropertyFactory();
+            destination.create(path,
+                               factory.create(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.NODE_TYPE),
+                               factory.create(JcrLexicon.SUPERTYPES, (Object[])supertypes),
+                               factory.create(JcrLexicon.IS_ABSTRACT, isAbstract),
+                               factory.create(JcrLexicon.HAS_ORDERABLE_CHILD_NODES, hasOrderableChildNodes),
+                               factory.create(JcrLexicon.IS_MIXIN, isMixin),
+                               factory.create(JcrLexicon.IS_QUERYABLE, isQueryable),
+                               factory.create(JcrLexicon.PRIMARY_ITEM_NAME, primaryItemName));
+
+            return path;
+        }
+
+        protected Path createPropertyDefinition( CommonTree propDefn,
+                                                 Path parentPath ) {
+            Name name = nameFrom(propDefn, CndLexer.NAME);
+            String requiredType = propertyTypeNameFrom(propDefn, CndLexer.REQUIRED_TYPE);
+            String[] defaultValues = stringsFrom(propDefn, CndLexer.DEFAULT_VALUES);
+            boolean multiple = booleanFrom(propDefn, CndLexer.MULTIPLE, false);
+            boolean mandatory = booleanFrom(propDefn, CndLexer.MANDATORY, false);
+            boolean autoCreated = booleanFrom(propDefn, CndLexer.AUTO_CREATED, false);
+            boolean isProtected = booleanFrom(propDefn, CndLexer.PROTECTED, false);
+            String onParentVersion = onParentVersionFrom(propDefn, CndLexer.ON_PARENT_VERSION);
+            /*QueryOperator[] queryOperators =*/queryOperatorsFrom(propDefn, CndLexer.QUERY_OPERATORS);
+            boolean isFullTextSearchable = booleanFrom(propDefn, CndLexer.IS_FULL_TEXT_SEARCHABLE, true);
+            boolean isQueryOrderable = booleanFrom(propDefn, CndLexer.IS_QUERY_ORDERERABLE, true);
+            String[] valueConstraints = stringsFrom(propDefn, CndLexer.VALUE_CONSTRAINTS);
+
+            // Create the node for the node type ...
+            if (name == null) return null;
+            Path path = pathFactory().create(parentPath, name);
+
+            PropertyFactory factory = context.getPropertyFactory();
+            destination.create(path,
+                               factory.create(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.PROPERTY_DEFINITION),
+                               factory.create(JcrLexicon.REQUIRED_TYPE, requiredType),
+                               factory.create(JcrLexicon.DEFAULT_VALUES, (Object[])defaultValues),
+                               factory.create(JcrLexicon.MULTIPLE, multiple),
+                               factory.create(JcrLexicon.MANDATORY, mandatory),
+                               factory.create(JcrLexicon.AUTO_CREATED, autoCreated),
+                               factory.create(JcrLexicon.PROTECTED, isProtected),
+                               factory.create(JcrLexicon.ON_PARENT_VERSION, onParentVersion),
+                               // factory.create(DnaLexicon.QUERY_OPERATORS, queryOperators),
+                               factory.create(JcrLexicon.IS_FULL_TEXT_SEARCHABLE, isFullTextSearchable),
+                               factory.create(JcrLexicon.IS_QUERY_ORDERABLE, isQueryOrderable),
+                               factory.create(JcrLexicon.VALUE_CONSTRAINTS, (Object[])valueConstraints));
+
+            return path;
+        }
+
+        protected Path createChildDefinition( CommonTree childDefn,
+                                              Path parentPath ) {
+            Name name = nameFrom(childDefn, CndLexer.NAME);
+            Name[] requiredPrimaryTypes = namesFrom(childDefn, CndLexer.REQUIRED_PRIMARY_TYPES);
+            Name defaultPrimaryType = nameFrom(childDefn, CndLexer.DEFAULT_PRIMARY_TYPE);
+            boolean mandatory = booleanFrom(childDefn, CndLexer.MANDATORY, false);
+            boolean autoCreated = booleanFrom(childDefn, CndLexer.AUTO_CREATED, false);
+            boolean isProtected = booleanFrom(childDefn, CndLexer.PROTECTED, false);
+            String onParentVersion = onParentVersionFrom(childDefn, CndLexer.ON_PARENT_VERSION);
+            boolean sameNameSiblings = booleanFrom(childDefn, CndLexer.SAME_NAME_SIBLINGS, false);
+
+            // Create the node for the node type ...
+            if (name == null) return null;
+            Path path = pathFactory().create(parentPath, name);
+
+            PropertyFactory factory = context.getPropertyFactory();
+            destination.create(path,
+                               factory.create(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.CHILD_NODE_DEFINITION),
+                               factory.create(JcrLexicon.REQUIRED_PRIMARY_TYPES, (Object[])requiredPrimaryTypes),
+                               factory.create(JcrLexicon.DEFAULT_PRIMARY_TYPE, defaultPrimaryType),
+                               factory.create(JcrLexicon.MANDATORY, mandatory),
+                               factory.create(JcrLexicon.AUTO_CREATED, autoCreated),
+                               factory.create(JcrLexicon.PROTECTED, isProtected),
+                               factory.create(JcrLexicon.ON_PARENT_VERSION, onParentVersion),
+                               factory.create(JcrLexicon.SAME_NAME_SIBLINGS, sameNameSiblings));
+
+            return path;
+        }
+    }
+
+    protected class Parser extends CndParser {
+        private final Problems problems;
+        private final String nameOfResource;
+
+        public Parser( TokenStream input,
+                       Problems problems,
+                       String nameOfResource ) {
+            super(input);
+            this.problems = problems;
+            this.nameOfResource = nameOfResource;
+        }
+
+        @Override
+        public void displayRecognitionError( String[] tokenNames,
+                                             RecognitionException e ) {
+            if (problems != null) {
+                String hdr = getErrorHeader(e);
+                String msg = getErrorMessage(e, tokenNames);
+                problems.addError(CndI18n.passthrough, nameOfResource, hdr, msg);
+            } else {
+                super.displayRecognitionError(tokenNames, e);
+            }
+        }
+    }
+
+    /**
+     * Specialization of an {@link ANTLRInputStream} that converts all tokens to lowercase, allowing the grammar to be
+     * case-insensitive. See the <a href="http://www.antlr.org/wiki/pages/viewpage.action?pageId=1782">ANTLR documentation</a>.
+     */
+    protected class CaseInsensitiveInputStream extends ANTLRInputStream {
+        protected CaseInsensitiveInputStream( InputStream stream ) throws IOException {
+            super(stream);
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.antlr.runtime.ANTLRStringStream#LA(int)
+         */
+        @Override
+        public int LA( int i ) {
+            if (i == 0) {
+                return 0; // undefined
+            }
+            if (i < 0) {
+                i++; // e.g., translate LA(-1) to use offset 0
+            }
+
+            if ((p + i - 1) >= n) {
+                return CharStream.EOF;
+            }
+            return Character.toLowerCase(data[p + i - 1]);
+        }
+    }
+
+    /**
+     * Specialization of an {@link ANTLRInputStream} that converts all tokens to lowercase, allowing the grammar to be
+     * case-insensitive. See the <a href="http://www.antlr.org/wiki/pages/viewpage.action?pageId=1782">ANTLR documentation</a>.
+     */
+    protected class CaseInsensitiveFileStream extends ANTLRFileStream {
+        protected CaseInsensitiveFileStream( String fileName ) throws IOException {
+            super(fileName, null);
+        }
+
+        protected CaseInsensitiveFileStream( String fileName,
+                                             String encoding ) throws IOException {
+            super(fileName, encoding);
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.antlr.runtime.ANTLRStringStream#LA(int)
+         */
+        @Override
+        public int LA( int i ) {
+            if (i == 0) {
+                return 0; // undefined
+            }
+            if (i < 0) {
+                i++; // e.g., translate LA(-1) to use offset 0
+            }
+
+            if ((p + i - 1) >= n) {
+
+                return CharStream.EOF;
+            }
+            return Character.toLowerCase(data[p + i - 1]);
+        }
+    }
+
+}

Added: trunk/dna-cnd/src/main/java/org/jboss/dna/cnd/QueryOperator.java
===================================================================
--- trunk/dna-cnd/src/main/java/org/jboss/dna/cnd/QueryOperator.java	                        (rev 0)
+++ trunk/dna-cnd/src/main/java/org/jboss/dna/cnd/QueryOperator.java	2009-04-20 19:07:48 UTC (rev 840)
@@ -0,0 +1,80 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of 
+ * individual contributors.
+ *
+ * Unless otherwise indicated, all code in JBoss DNA is licensed
+ * to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ * 
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.cnd;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import org.jboss.dna.common.util.CheckArg;
+
+/**
+ * Enumeration of the query operators allowed in a CND file.
+ */
+public enum QueryOperator {
+
+    EQUAL("="),
+    NOT_EQUAL("<>"),
+    LESS_THAN("<"),
+    LESS_THAN_OR_EQUALS("<="),
+    GREATER_THAN("<"),
+    GREATER_THAN_OR_EQUALS("<="),
+    LIKE("LIKE");
+
+    private static final Map<String, QueryOperator> ALL_OPERATORS;
+    static {
+        Map<String, QueryOperator> operators = new HashMap<String, QueryOperator>();
+        for (QueryOperator operator : QueryOperator.values()) {
+            operators.put(operator.getText(), operator);
+        }
+        ALL_OPERATORS = Collections.unmodifiableMap(operators);
+    }
+
+    private final String text;
+
+    private QueryOperator( String text ) {
+        this.text = text;
+    }
+
+    /**
+     * @return text
+     */
+    public String getText() {
+        return text;
+    }
+
+    public static QueryOperator forText( String text ) {
+        CheckArg.isNotNull(text, "text");
+        return ALL_OPERATORS.get(text.trim().toUpperCase());
+    }
+
+    /**
+     * Return an iterator over all the operator enumeration literals.
+     * 
+     * @return an immutable iterator
+     */
+    public static Iterator<QueryOperator> iterator() {
+        return ALL_OPERATORS.values().iterator();
+    }
+}

Added: trunk/dna-cnd/src/main/resources/org/jboss/dna/cnd/CndI18n.properties
===================================================================
--- trunk/dna-cnd/src/main/resources/org/jboss/dna/cnd/CndI18n.properties	                        (rev 0)
+++ trunk/dna-cnd/src/main/resources/org/jboss/dna/cnd/CndI18n.properties	2009-04-20 19:07:48 UTC (rev 840)
@@ -0,0 +1,33 @@
+#
+# JBoss DNA (http://www.jboss.org/dna)
+# See the COPYRIGHT.txt file distributed with this work for information
+# regarding copyright ownership.  Some portions may be licensed
+# to Red Hat, Inc. under one or more contributor license agreements.
+# See the AUTHORS.txt file in the distribution for a full listing of 
+# individual contributors. 
+#
+# JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+# is licensed to you under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# JBoss DNA is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this software; if not, write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+#
+
+passthrough = {0}
+errorImportingCndContent = Error importing {0}: {1}
+expectedBooleanLiteral = Expected 'true' or 'false', but was "{0}"
+expectedStringLiteral = Expected a valid string, but was "{0}"
+expectedValidNameLiteral = Expected a valid name, but was "{0}"
+expectedValidPropertyTypeName = Property type name was "{0}" but should be one of "{1}"
+expectedValidOnParentVersion = On parent version value was "{0}" but should be one of "{1}"
+expectedValidQueryOperator = Expected a valid query operator ('=', '<>', '<', '<=', '>', '>=', or 'LIKE'), but was {0}
+locationFromLineNumberAndCharacter = Line {0} column {1}
\ No newline at end of file

Added: trunk/dna-cnd/src/test/java/org/jboss/dna/cnd/CndImporterTest.java
===================================================================
--- trunk/dna-cnd/src/test/java/org/jboss/dna/cnd/CndImporterTest.java	                        (rev 0)
+++ trunk/dna-cnd/src/test/java/org/jboss/dna/cnd/CndImporterTest.java	2009-04-20 19:07:48 UTC (rev 840)
@@ -0,0 +1,611 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of 
+ * individual contributors.
+ *
+ * Unless otherwise indicated, all code in JBoss DNA is licensed
+ * to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ * 
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.cnd;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.jboss.dna.graph.IsNodeWithProperty.hasProperty;
+import static org.junit.Assert.assertThat;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URISyntaxException;
+import java.util.HashSet;
+import java.util.Set;
+import org.jboss.dna.common.collection.Problem;
+import org.jboss.dna.common.collection.SimpleProblems;
+import org.jboss.dna.graph.DnaLexicon;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.JcrLexicon;
+import org.jboss.dna.graph.JcrNtLexicon;
+import org.jboss.dna.graph.Node;
+import org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource;
+import org.jboss.dna.graph.io.Destination;
+import org.jboss.dna.graph.io.GraphBatchDestination;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * 
+ */
+public class CndImporterTest {
+
+    public static final String CND_FILE_PATH = "src/test/resources/cnd/";
+
+    private ExecutionContext context;
+    private InMemoryRepositorySource repository;
+    private Graph graph;
+    private Destination destination;
+    private Path rootPath;
+    private CndImporter importer;
+    private SimpleProblems problems;
+
+    @Before
+    public void beforeEach() {
+        problems = new SimpleProblems();
+        context = new ExecutionContext();
+        context.getNamespaceRegistry().register(DnaLexicon.Namespace.PREFIX, DnaLexicon.Namespace.URI);
+        context.getNamespaceRegistry().register(JcrLexicon.Namespace.PREFIX, JcrLexicon.Namespace.URI);
+        context.getNamespaceRegistry().register(JcrNtLexicon.Namespace.PREFIX, JcrNtLexicon.Namespace.URI);
+
+        // Set up the repository and graph ...
+        repository = new InMemoryRepositorySource();
+        repository.setName("NodeTypes");
+        graph = Graph.create(repository, context);
+
+        // Set up the path where the content will go, and make sure that path exists in the repository ...
+        rootPath = context.getValueFactories().getPathFactory().create("/a");
+        graph.create(rootPath);
+
+        // Now set up the destination ...
+        destination = new GraphBatchDestination(graph.batch());
+
+        // Set up the importer ...
+        importer = new CndImporter(destination, rootPath);
+    }
+
+    protected Name name( String name ) {
+        return context.getValueFactories().getNameFactory().create(name);
+    }
+
+    protected void printProblems() {
+        for (Problem problem : problems) {
+            System.out.println(problem);
+        }
+    }
+
+    protected Node node( String pathToNode ) {
+        return graph.getNodeAt("/a/" + pathToNode);
+    }
+
+    protected InputStream openCndStream( String cndFileName ) throws IOException {
+        return this.getClass().getClassLoader().getResourceAsStream("cnd/" + cndFileName);
+    }
+
+    protected File openCndFile( String cndFileName ) throws IOException, URISyntaxException {
+        File result = new File(CND_FILE_PATH + cndFileName);
+        assertThat(result.exists(), is(true));
+        return result;
+    }
+
+    @Test
+    public void shouldReportErrorIfTheNodeTypeNameIsEmpty() throws IOException {
+        String cnd = "<ns = 'http://namespace.com/ns'> [] abstract";
+        importer.importFrom(cnd, problems, "string");
+        // printProblems();
+        assertThat(problems.size(), is(1));
+        assertThat(problems.iterator().next().getMessageString(), is("missing STRING at ']'"));
+    }
+
+    @Test
+    public void shouldReportErrorIfTheNodeTypeNameIsBlank() throws IOException {
+        String cnd = "<ns = 'http://namespace.com/ns'> [ ] abstract";
+        importer.importFrom(cnd, problems, "string");
+        // printProblems();
+        assertThat(problems.size(), is(1));
+        assertThat(problems.iterator().next().getMessageString(), is("missing STRING at ']'"));
+    }
+
+    @Test
+    public void shouldReportErrorIfTheNodeTypeNameIsNotFollowedByClosingBracket() throws IOException {
+        String cnd = "<ns = 'http://namespace.com/ns'> [  abstract";
+        importer.importFrom(cnd, problems, "string");
+        // printProblems();
+        assertThat(problems.size(), is(1));
+        assertThat(problems.iterator().next().getMessageString(), is("mismatched input 'abstract' expecting STRING"));
+    }
+
+    @Test
+    public void shouldReportErrorIfTheNodeTypeNameUsesInvalidNamespace() throws IOException {
+        String cnd = "<ns = 'http://namespace.com/ns'> [xyz:acme] abstract";
+        importer.importFrom(cnd, problems, "string");
+        // printProblems();
+        assertThat(problems.size(), is(1));
+        assertThat(problems.iterator().next().getMessage(), is(CndI18n.expectedValidNameLiteral));
+    }
+
+    @Test
+    public void shouldImportCndThatUsesAllFeatures() throws IOException {
+        // importer.setDebug(true);
+        String cnd = "<ex = 'http://namespace.com/ns'>\n"
+                     + "[ex:NodeType] > ex:ParentType1, ex:ParentType2 abstract orderable mixin noquery primaryitem ex:property\n"
+                     + "- ex:property (STRING) = 'default1', 'default2' mandatory autocreated protected multiple VERSION < 'constraint1', 'constraint2'\n"
+                     + " queryops '=, <>, <, <=, >, >=, LIKE' nofulltext noqueryorder\n"
+                     + "+ ex:node (ex:reqType1, ex:reqType2) = ex:defaultType mandatory autocreated protected sns version";
+        importer.importFrom(cnd, problems, "string");
+        // assertThat(problems.size(), is(1));
+        // printProblems();
+        context.getNamespaceRegistry().register("ex", "http://namespace.com/ns");
+        Node nodeType = node("ex:NodeType");
+        assertThat(nodeType, hasProperty(JcrLexicon.IS_ABSTRACT, true));
+        Node prop = node("ex:NodeType/ex:property");
+        assertThat(prop, hasProperty(JcrLexicon.REQUIRED_TYPE, "STRING"));
+        assertThat(prop, hasProperty(JcrLexicon.DEFAULT_VALUES, new Object[] {"default1", "default2"}));
+        assertThat(prop, hasProperty(JcrLexicon.AUTO_CREATED, true));
+        assertThat(prop, hasProperty(JcrLexicon.MANDATORY, true));
+        assertThat(prop, hasProperty(JcrLexicon.PROTECTED, true));
+        assertThat(prop, hasProperty(JcrLexicon.MULTIPLE, true));
+        assertThat(prop, hasProperty(JcrLexicon.ON_PARENT_VERSION, "VERSION"));
+        assertThat(prop, hasProperty(JcrLexicon.VALUE_CONSTRAINTS, new Object[] {"constraint1", "constraint2"}));
+        assertThat(prop, hasProperty(JcrLexicon.IS_FULL_TEXT_SEARCHABLE, false));
+        assertThat(prop, hasProperty(JcrLexicon.IS_QUERY_ORDERABLE, false));
+        Node node = node("ex:NodeType/ex:node");
+        assertThat(node, hasProperty(JcrLexicon.REQUIRED_PRIMARY_TYPES, new Object[] {name("ex:reqType1"), name("ex:reqType2")}));
+        assertThat(node, hasProperty(JcrLexicon.DEFAULT_PRIMARY_TYPE, name("ex:defaultType")));
+        assertThat(node, hasProperty(JcrLexicon.AUTO_CREATED, true));
+        assertThat(node, hasProperty(JcrLexicon.MANDATORY, true));
+        assertThat(node, hasProperty(JcrLexicon.PROTECTED, true));
+        assertThat(node, hasProperty(JcrLexicon.SAME_NAME_SIBLINGS, true));
+        assertThat(node, hasProperty(JcrLexicon.ON_PARENT_VERSION, "VERSION"));
+    }
+
+    @Test
+    public void shouldImportCndThatIsOnOneLine() throws IOException {
+        String cnd = "<ns = 'http://namespace.com/ns'> "
+                     + "[ns:NodeType] > ns:ParentType1, ns:ParentType2 abstract orderable mixin noquery primaryitem ex:property "
+                     + "- ex:property (STRING) = 'default1', 'default2' mandatory autocreated protected multiple VERSION < 'constraint1', 'constraint2' "
+                     + " queryops '=, <>, <, <=, >, >=, LIKE' nofulltext noqueryorder "
+                     + "+ ns:node (ns:reqType1, ns:reqType2) = ns:defaultType mandatory autocreated protected sns version";
+        // importer.importFrom(cnd, problems, "string");
+    }
+
+    @Test
+    public void shouldImportCndThatHasNoChildren() throws IOException {
+        String cnd = "<ns = 'http://namespace.com/ns'>\n"
+                     + "[ns:NodeType] > ns:ParentType1, ns:ParentType2 abstract orderable mixin noquery primaryitem ex:property\n"
+                     + "- ex:property (STRING) = 'default1', 'default2' mandatory autocreated protected multiple VERSION < 'constraint1', 'constraint2'\n"
+                     + " queryops '=, <>, <, <=, >, >=, LIKE' nofulltext noqueryorder";
+        // importer.importFrom(cnd, problems, "string");
+    }
+
+    @Test
+    public void shouldImportJcrBuiltinNodeTypesForJSR170() throws Exception {
+        importer.importFrom(openCndFile("jcr-builtins-170.cnd"), problems);
+        if (problems.size() != 0) printProblems();
+        assertThat(problems.size(), is(0));
+
+        // [nt:base]
+        // - jcr:primaryType (name) mandatory autocreated protected compute
+        // - jcr:mixinTypes (name) protected multiple compute
+        assertNodeType("nt:base", NO_SUPERTYPES, NO_PRIMARY_NAME);
+        assertProperty("nt:base", "jcr:primaryType", "Name", NO_DEFAULTS, new PropertyOptions[] {PropertyOptions.Mandatory,
+            PropertyOptions.Autocreated, PropertyOptions.Protected}, OnParentVersion.Compute);
+        assertProperty("nt:base", "jcr:mixinTypes", "Name", NO_DEFAULTS, new PropertyOptions[] {PropertyOptions.Multiple,
+            PropertyOptions.Protected}, OnParentVersion.Compute);
+
+        // [nt:unstructured]
+        // orderable
+        // - * (undefined) multiple
+        // - * (undefined)
+        // + * (nt:base) = nt:unstructured multiple version
+        assertNodeType("nt:unstructured", NO_SUPERTYPES, NO_PRIMARY_NAME, NodeOptions.Ordered);
+        assertProperty("nt:unstructured", "*[1]", "Undefined", NO_DEFAULTS, PropertyOptions.Multiple);
+        assertProperty("nt:unstructured", "*[2]", "Undefined", NO_DEFAULTS);
+        assertChild("nt:unstructured", "*[3]", "nt:base", "nt:unstructured", OnParentVersion.Version, ChildOptions.Multiple);
+
+        // [mix:referenceable]
+        // mixin
+        // - jcr:uuid (string) mandatory autocreated protected initialize
+        assertNodeType("mix:referenceable", NO_SUPERTYPES, NO_PRIMARY_NAME, NodeOptions.Mixin);
+        assertProperty("mix:referenceable",
+                       "jcr:uuid",
+                       "String",
+                       NO_DEFAULTS,
+                       OnParentVersion.Initialize,
+                       PropertyOptions.Mandatory,
+                       PropertyOptions.Autocreated,
+                       PropertyOptions.Protected);
+
+        // [mix:lockable]
+        // mixin
+        // - jcr:lockOwner (string) protected ignore
+        // - jcr:lockIsDeep (boolean) protected ignore
+        assertNodeType("mix:lockable", NO_SUPERTYPES, NO_PRIMARY_NAME, NodeOptions.Mixin);
+        assertProperty("mix:lockable", "jcr:lockOwner", "String", NO_DEFAULTS, OnParentVersion.Ignore, PropertyOptions.Protected);
+        assertProperty("mix:lockable",
+                       "jcr:lockIsDeep",
+                       "Boolean",
+                       NO_DEFAULTS,
+                       OnParentVersion.Ignore,
+                       PropertyOptions.Protected);
+
+        // [nt:propertyDefinition]
+        // - jcr:name (name)
+        // - jcr:autoCreated (boolean) mandatory
+        // - jcr:mandatory (boolean) mandatory
+        // - jcr:onParentVersion (string) mandatory
+        // < 'COPY', 'VERSION', 'INITIALIZE', 'COMPUTE', 'IGNORE', 'ABORT'
+        // - jcr:protected (boolean) mandatory
+        // - jcr:requiredType (string) mandatory
+        // < 'STRING', 'BINARY', 'LONG', 'DOUBLE', 'BOOLEAN', 'DATE', 'NAME', 'PATH', 'REFERENCE', 'UNDEFINED'
+        // - jcr:valueConstraints (string) multiple
+        // - jcr:defaultValues (undefined) multiple
+        // - jcr:multiple (boolean) mandatory
+        assertNodeType("nt:propertyDefinition", NO_SUPERTYPES, NO_PRIMARY_NAME);
+        assertProperty("nt:propertyDefinition", "jcr:name", "Name", NO_DEFAULTS);
+        assertProperty("nt:propertyDefinition", "jcr:autoCreated", "Boolean", NO_DEFAULTS, PropertyOptions.Mandatory);
+        assertProperty("nt:propertyDefinition", "jcr:mandatory", "Boolean", NO_DEFAULTS, PropertyOptions.Mandatory);
+        assertProperty("nt:propertyDefinition",
+                       "jcr:onParentVersion",
+                       "String",
+                       NO_DEFAULTS,
+                       new PropertyOptions[] {PropertyOptions.Mandatory},
+                       null,
+                       new String[] {"COPY", "VERSION", "INITIALIZE", "COMPUTE", "IGNORE", "ABORT"});
+        assertProperty("nt:propertyDefinition", "jcr:protected", "Boolean", NO_DEFAULTS, PropertyOptions.Mandatory);
+        assertProperty("nt:propertyDefinition",
+                       "jcr:requiredType",
+                       "String",
+                       NO_DEFAULTS,
+                       new PropertyOptions[] {PropertyOptions.Mandatory},
+                       null,
+                       new String[] {"STRING", "BINARY", "LONG", "DOUBLE", "BOOLEAN", "DATE", "NAME", "PATH", "REFERENCE",
+                           "UNDEFINED"});
+        assertProperty("nt:propertyDefinition", "jcr:valueConstraints", "String", NO_DEFAULTS, PropertyOptions.Multiple);
+        assertProperty("nt:propertyDefinition", "jcr:defaultValues", "Undefined", NO_DEFAULTS, PropertyOptions.Multiple);
+        assertProperty("nt:propertyDefinition", "jcr:multiple", "Boolean", NO_DEFAULTS, PropertyOptions.Mandatory);
+    }
+
+    @Test
+    public void shouldImportJcrBuiltinNodeTypesForJSR283() throws Exception {
+        importer.importFrom(openCndFile("jcr-builtins-283-early-draft.cnd"), problems);
+        if (problems.size() != 0) printProblems();
+        assertThat(problems.size(), is(0));
+
+        // [nt:base]
+        // - jcr:primaryType (name) mandatory autocreated protected compute
+        // - jcr:mixinTypes (name) protected multiple compute
+        assertNodeType("nt:base", NO_SUPERTYPES, NO_PRIMARY_NAME, NodeOptions.Abstract);
+        assertProperty("nt:base", "jcr:primaryType", "Name", NO_DEFAULTS, new PropertyOptions[] {PropertyOptions.Mandatory,
+            PropertyOptions.Autocreated, PropertyOptions.Protected}, OnParentVersion.Compute);
+        assertProperty("nt:base", "jcr:mixinTypes", "Name", NO_DEFAULTS, new PropertyOptions[] {PropertyOptions.Multiple,
+            PropertyOptions.Protected}, OnParentVersion.Compute);
+
+        // [nt:unstructured]
+        // orderable
+        // - * (undefined) multiple
+        // - * (undefined)
+        // + * (nt:base) = nt:unstructured multiple version
+        assertNodeType("nt:unstructured", NO_SUPERTYPES, NO_PRIMARY_NAME, NodeOptions.Ordered);
+        assertProperty("nt:unstructured", "*[1]", "Undefined", NO_DEFAULTS, PropertyOptions.Multiple);
+        assertProperty("nt:unstructured", "*[2]", "Undefined", NO_DEFAULTS);
+        assertChild("nt:unstructured", "*[3]", "nt:base", "nt:unstructured", OnParentVersion.Version, ChildOptions.Multiple);
+
+        // [mix:referenceable]
+        // mixin
+        // - jcr:uuid (string) mandatory autocreated protected initialize
+        assertNodeType("mix:referenceable", NO_SUPERTYPES, NO_PRIMARY_NAME, NodeOptions.Mixin);
+        assertProperty("mix:referenceable",
+                       "jcr:uuid",
+                       "String",
+                       NO_DEFAULTS,
+                       OnParentVersion.Initialize,
+                       PropertyOptions.Mandatory,
+                       PropertyOptions.Autocreated,
+                       PropertyOptions.Protected);
+
+        // [mix:lockable]
+        // mixin
+        // - jcr:lockOwner (string) protected ignore
+        // - jcr:lockIsDeep (boolean) protected ignore
+        assertNodeType("mix:lockable", NO_SUPERTYPES, NO_PRIMARY_NAME, NodeOptions.Mixin);
+        assertProperty("mix:lockable", "jcr:lockOwner", "String", NO_DEFAULTS, OnParentVersion.Ignore, PropertyOptions.Protected);
+        assertProperty("mix:lockable",
+                       "jcr:lockIsDeep",
+                       "Boolean",
+                       NO_DEFAULTS,
+                       OnParentVersion.Ignore,
+                       PropertyOptions.Protected);
+
+        // [nt:propertyDefinition]
+        // - jcr:name (name)
+        // - jcr:autoCreated (boolean) mandatory
+        // - jcr:mandatory (boolean) mandatory
+        // - jcr:onParentVersion (string) mandatory
+        // < 'COPY', 'VERSION', 'INITIALIZE', 'COMPUTE', 'IGNORE', 'ABORT'
+        // - jcr:protected (boolean) mandatory
+        // - jcr:requiredType (string) mandatory
+        // < 'STRING', 'BINARY', 'LONG', 'DOUBLE', 'BOOLEAN', 'DATE', 'NAME', 'PATH', 'REFERENCE', 'UNDEFINED'
+        // - jcr:valueConstraints (string) multiple
+        // - jcr:defaultValues (undefined) multiple
+        // - jcr:multiple (boolean) mandatory
+        assertNodeType("nt:propertyDefinition", NO_SUPERTYPES, NO_PRIMARY_NAME);
+        assertProperty("nt:propertyDefinition", "jcr:name", "Name", NO_DEFAULTS);
+        assertProperty("nt:propertyDefinition", "jcr:autoCreated", "Boolean", NO_DEFAULTS, PropertyOptions.Mandatory);
+        assertProperty("nt:propertyDefinition", "jcr:mandatory", "Boolean", NO_DEFAULTS, PropertyOptions.Mandatory);
+        assertProperty("nt:propertyDefinition",
+                       "jcr:onParentVersion",
+                       "String",
+                       NO_DEFAULTS,
+                       new PropertyOptions[] {PropertyOptions.Mandatory},
+                       null,
+                       new String[] {"COPY", "VERSION", "INITIALIZE", "COMPUTE", "IGNORE", "ABORT"});
+        assertProperty("nt:propertyDefinition", "jcr:protected", "Boolean", NO_DEFAULTS, PropertyOptions.Mandatory);
+        assertProperty("nt:propertyDefinition",
+                       "jcr:requiredType",
+                       "String",
+                       NO_DEFAULTS,
+                       new PropertyOptions[] {PropertyOptions.Mandatory},
+                       null,
+                       new String[] {"STRING", "BINARY", "LONG", "DOUBLE", "BOOLEAN", "DATE", "NAME", "PATH", "REFERENCE",
+                           "UNDEFINED"});
+        assertProperty("nt:propertyDefinition", "jcr:valueConstraints", "String", NO_DEFAULTS, PropertyOptions.Multiple);
+        assertProperty("nt:propertyDefinition", "jcr:defaultValues", "Undefined", NO_DEFAULTS, PropertyOptions.Multiple);
+        assertProperty("nt:propertyDefinition", "jcr:multiple", "Boolean", NO_DEFAULTS, PropertyOptions.Mandatory);
+    }
+
+    @Test
+    public void shouldImportCndThatIsEmpty() throws Exception {
+        importer.importFrom(openCndFile("empty.cnd"), problems);
+        if (problems.size() != 0) printProblems();
+        assertThat(problems.size(), is(0));
+    }
+
+    @Test
+    public void shouldImportCndForImageSequencer() throws Exception {
+        importer.importFrom(openCndFile("images.cnd"), problems);
+        if (problems.size() != 0) printProblems();
+        assertThat(problems.size(), is(0));
+    }
+
+    @Test
+    public void shouldImportCndForMp3Sequencer() throws Exception {
+        importer.importFrom(openCndFile("mp3.cnd"), problems);
+        if (problems.size() != 0) printProblems();
+        assertThat(problems.size(), is(0));
+    }
+
+    @Test
+    public void shouldNotImportFileThatIsNotAValidCnd() throws Exception {
+        importer.importFrom(openCndFile("invalid.cnd"), problems);
+        assertThat(problems.size(), is(1));
+    }
+
+    public static final String[] NO_DEFAULTS = {};
+    public static final String[] NO_SUPERTYPES = {};
+    public static final String[] NO_VALUE_CONSTRAINTS = {};
+    public static final String NO_PRIMARY_NAME = null;
+
+    public static enum PropertyOptions {
+        Mandatory,
+        Autocreated,
+        Protected,
+        Multiple,
+        FullTextSearchable,
+        QueryOrderable
+    }
+
+    public static enum ChildOptions {
+        Mandatory,
+        Autocreated,
+        Protected,
+        Multiple
+    }
+
+    public static enum NodeOptions {
+        Abstract,
+        Mixin,
+        Ordered,
+        Queryable
+    }
+
+    public static enum OnParentVersion {
+        Copy,
+        Version,
+        Initialize,
+        Compute,
+        Ignore,
+        Abort
+    }
+
+    protected void assertNodeType( String name,
+                                   String[] superTypes,
+                                   String primaryItemName,
+                                   NodeOptions... nodeOptions ) {
+        Set<NodeOptions> options = new HashSet<NodeOptions>();
+        for (NodeOptions option : nodeOptions)
+            options.add(option);
+
+        Node nodeType = node(name);
+        assertThat(nodeType, hasProperty(JcrLexicon.IS_MIXIN, options.contains(NodeOptions.Mixin)));
+        assertThat(nodeType, hasProperty(JcrLexicon.IS_ABSTRACT, options.contains(NodeOptions.Abstract)));
+        assertThat(nodeType, hasProperty(JcrLexicon.HAS_ORDERABLE_CHILD_NODES, options.contains(NodeOptions.Ordered)));
+        assertThat(nodeType, hasProperty(JcrLexicon.IS_QUERYABLE, !options.contains(NodeOptions.Queryable)));
+        assertThat(nodeType, hasProperty(JcrLexicon.PRIMARY_ITEM_NAME, name(primaryItemName)));
+        if (superTypes.length != 0) {
+            Name[] superTypeNames = new Name[superTypes.length];
+            for (int i = 0; i != superTypes.length; ++i) {
+                String requiredType = superTypes[i];
+                superTypeNames[i] = name(requiredType);
+            }
+            assertThat(nodeType, hasProperty(JcrLexicon.SUPERTYPES, (Object[])superTypeNames));
+        } else {
+            assertThat(nodeType.getProperty(JcrLexicon.SUPERTYPES), is(nullValue()));
+        }
+    }
+
+    protected void assertProperty( String nodeTypeName,
+                                   String propertyName,
+                                   String requiredType,
+                                   String[] defaultValues,
+                                   PropertyOptions... propertyOptions ) {
+        assertProperty(nodeTypeName, propertyName, requiredType, defaultValues, propertyOptions, null);
+    }
+
+    protected void assertProperty( String nodeTypeName,
+                                   String propertyName,
+                                   String requiredType,
+                                   String[] defaultValues,
+                                   OnParentVersion onParentVersion,
+                                   PropertyOptions... propertyOptions ) {
+        assertProperty(nodeTypeName, propertyName, requiredType, defaultValues, propertyOptions, onParentVersion);
+    }
+
+    protected void assertProperty( String nodeTypeName,
+                                   String propertyName,
+                                   String requiredType,
+                                   String[] defaultValues,
+                                   PropertyOptions[] propertyOptions,
+                                   OnParentVersion onParentVersioning,
+                                   String... valueConstraints ) {
+        Set<PropertyOptions> options = new HashSet<PropertyOptions>();
+        for (PropertyOptions option : propertyOptions)
+            options.add(option);
+
+        Node nodeType = node(nodeTypeName + "/" + propertyName);
+        assertThat(nodeType, hasProperty(JcrLexicon.REQUIRED_TYPE, requiredType.toUpperCase()));
+        assertThat(nodeType, hasProperty(JcrLexicon.MULTIPLE, options.contains(PropertyOptions.Multiple)));
+        assertThat(nodeType, hasProperty(JcrLexicon.MANDATORY, options.contains(PropertyOptions.Mandatory)));
+        assertThat(nodeType, hasProperty(JcrLexicon.AUTO_CREATED, options.contains(PropertyOptions.Autocreated)));
+        assertThat(nodeType, hasProperty(JcrLexicon.PROTECTED, options.contains(PropertyOptions.Protected)));
+        if (onParentVersioning != null) {
+            switch (onParentVersioning) {
+                case Abort:
+                    assertThat(nodeType, hasProperty(JcrLexicon.ON_PARENT_VERSION, "ABORT"));
+                    break;
+                case Compute:
+                    assertThat(nodeType, hasProperty(JcrLexicon.ON_PARENT_VERSION, "COMPUTE"));
+                    break;
+                case Copy:
+                    assertThat(nodeType, hasProperty(JcrLexicon.ON_PARENT_VERSION, "COPY"));
+                    break;
+                case Ignore:
+                    assertThat(nodeType, hasProperty(JcrLexicon.ON_PARENT_VERSION, "IGNORE"));
+                    break;
+                case Initialize:
+                    assertThat(nodeType, hasProperty(JcrLexicon.ON_PARENT_VERSION, "INITIALIZE"));
+                    break;
+                case Version:
+                    assertThat(nodeType, hasProperty(JcrLexicon.ON_PARENT_VERSION, "VERSION"));
+                    break;
+            }
+        } else {
+            assertThat(nodeType, hasProperty(JcrLexicon.ON_PARENT_VERSION, "COPY")); // it's copy by default
+        }
+        assertThat(nodeType, hasProperty(JcrLexicon.IS_FULL_TEXT_SEARCHABLE,
+                                         !options.contains(PropertyOptions.FullTextSearchable)));
+        assertThat(nodeType, hasProperty(JcrLexicon.IS_QUERY_ORDERABLE, !options.contains(PropertyOptions.QueryOrderable)));
+        if (valueConstraints.length != 0) {
+            assertThat(nodeType, hasProperty(JcrLexicon.VALUE_CONSTRAINTS, (Object[])valueConstraints));
+        } else {
+            assertThat(nodeType.getProperty(JcrLexicon.VALUE_CONSTRAINTS), is(nullValue()));
+        }
+        if (defaultValues.length != 0) {
+            assertThat(nodeType, hasProperty(JcrLexicon.DEFAULT_VALUES, (Object[])defaultValues));
+        } else {
+            assertThat(nodeType.getProperty(JcrLexicon.DEFAULT_VALUES), is(nullValue()));
+        }
+    }
+
+    protected void assertChild( String nodeTypeName,
+                                String childName,
+                                String requiredType,
+                                String defaultPrimaryType,
+                                ChildOptions[] childOptions,
+                                OnParentVersion onParentVersioning ) {
+        assertChild(nodeTypeName, childName, new String[] {requiredType}, defaultPrimaryType, childOptions, onParentVersioning);
+    }
+
+    protected void assertChild( String nodeTypeName,
+                                String childName,
+                                String requiredType,
+                                String defaultPrimaryType,
+                                OnParentVersion onParentVersioning,
+                                ChildOptions... childOptions ) {
+        assertChild(nodeTypeName, childName, new String[] {requiredType}, defaultPrimaryType, childOptions, onParentVersioning);
+    }
+
+    protected void assertChild( String nodeTypeName,
+                                String childName,
+                                String[] requiredTypes,
+                                String defaultPrimaryType,
+                                ChildOptions[] childOptions,
+                                OnParentVersion onParentVersioning ) {
+        Set<ChildOptions> options = new HashSet<ChildOptions>();
+        for (ChildOptions option : childOptions)
+            options.add(option);
+
+        Node nodeType = node(nodeTypeName + "/" + childName);
+        assertThat(nodeType, hasProperty(JcrLexicon.DEFAULT_PRIMARY_TYPE, name(defaultPrimaryType)));
+        assertThat(nodeType, hasProperty(JcrLexicon.SAME_NAME_SIBLINGS, options.contains(ChildOptions.Multiple)));
+        assertThat(nodeType, hasProperty(JcrLexicon.MANDATORY, options.contains(ChildOptions.Mandatory)));
+        assertThat(nodeType, hasProperty(JcrLexicon.AUTO_CREATED, options.contains(ChildOptions.Autocreated)));
+        assertThat(nodeType, hasProperty(JcrLexicon.PROTECTED, options.contains(ChildOptions.Protected)));
+        switch (onParentVersioning) {
+            case Abort:
+                assertThat(nodeType, hasProperty(JcrLexicon.ON_PARENT_VERSION, "ABORT"));
+                break;
+            case Compute:
+                assertThat(nodeType, hasProperty(JcrLexicon.ON_PARENT_VERSION, "COMPUTE"));
+                break;
+            case Copy:
+                assertThat(nodeType, hasProperty(JcrLexicon.ON_PARENT_VERSION, "COPY"));
+                break;
+            case Ignore:
+                assertThat(nodeType, hasProperty(JcrLexicon.ON_PARENT_VERSION, "IGNORE"));
+                break;
+            case Initialize:
+                assertThat(nodeType, hasProperty(JcrLexicon.ON_PARENT_VERSION, "INITIALIZE"));
+                break;
+            case Version:
+                assertThat(nodeType, hasProperty(JcrLexicon.ON_PARENT_VERSION, "VERSION"));
+                break;
+            default:
+                assertThat(nodeType, hasProperty(JcrLexicon.ON_PARENT_VERSION, is(nullValue())));
+        }
+        if (requiredTypes.length != 0) {
+            Name[] requiredTypeNames = new Name[requiredTypes.length];
+            for (int i = 0; i != requiredTypes.length; ++i) {
+                String requiredType = requiredTypes[i];
+                requiredTypeNames[i] = name(requiredType);
+            }
+            assertThat(nodeType, hasProperty(JcrLexicon.REQUIRED_PRIMARY_TYPES, (Object[])requiredTypeNames));
+        } else {
+            assertThat(nodeType.getProperty(JcrLexicon.REQUIRED_PRIMARY_TYPES), is(nullValue()));
+        }
+    }
+}

Added: trunk/dna-cnd/src/test/resources/cnd/empty.cnd
===================================================================

Added: trunk/dna-cnd/src/test/resources/cnd/images.cnd
===================================================================
--- trunk/dna-cnd/src/test/resources/cnd/images.cnd	                        (rev 0)
+++ trunk/dna-cnd/src/test/resources/cnd/images.cnd	2009-04-20 19:07:48 UTC (rev 840)
@@ -0,0 +1,63 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of 
+ * individual contributors. 
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+ 
+//------------------------------------------------------------------------------
+// N A M E S P A C E S
+//------------------------------------------------------------------------------
+<jcr='http://www.jcp.org/jcr/1.0'>
+<nt='http://www.jcp.org/jcr/nt/1.0'>
+<mix='http://www.jcp.org/jcr/mix/1.0'>
+<image='http://jboss.org/dna/images/1.0'>
+
+// ----------------------------------------------------------
+// JCR Pre-defined Mixin Types that are not loaded by default
+// ----------------------------------------------------------
+
+[mix:mimeType] mixin 
+  - jcr:mimeType (string)  
+  - jcr:encoding (string)
+
+
+//------------------------------------------------------------------------------
+// N O D E T Y P E S
+//------------------------------------------------------------------------------
+
+/**
+ * Mixin that defines the metadata for an image
+ */
+[image:metadata] > nt:unstructured, mix:mimeType
+  - image:formatName (string) mandatory
+    < 'JPEG', 'GIF', 'PNG', 'BMP', 'PCX', 'IFF', 'RAS', 'PBM', 'PGM', 'PPM', 'PSD'
+  - image:width (long)
+  - image:height (long)
+  - image:bitsPerPixel (long)
+  - image:progressive (boolean)
+  - image:numberOfImages (long)
+  - image:physicalWidthDpi (long)
+  - image:physicalHeightDpi (long)
+  - image:physicalWidthInches (long)
+  - image:physicalHeightInches (long)
+
+
+ 
\ No newline at end of file

Added: trunk/dna-cnd/src/test/resources/cnd/invalid.cnd
===================================================================
--- trunk/dna-cnd/src/test/resources/cnd/invalid.cnd	                        (rev 0)
+++ trunk/dna-cnd/src/test/resources/cnd/invalid.cnd	2009-04-20 19:07:48 UTC (rev 840)
@@ -0,0 +1 @@
+This is not a valid cnd file.
\ No newline at end of file

Added: trunk/dna-cnd/src/test/resources/cnd/jcr-builtins-170.cnd
===================================================================
--- trunk/dna-cnd/src/test/resources/cnd/jcr-builtins-170.cnd	                        (rev 0)
+++ trunk/dna-cnd/src/test/resources/cnd/jcr-builtins-170.cnd	2009-04-20 19:07:48 UTC (rev 840)
@@ -0,0 +1,173 @@
+/*
+ * 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.
+ */
+
+<rep='internal'>
+<jcr='http://www.jcp.org/jcr/1.0'>
+<nt='http://www.jcp.org/jcr/nt/1.0'>
+
+//------------------------------------------------------------------------------
+// B A S E  T Y P E S
+//------------------------------------------------------------------------------
+
+[nt:base]
+  - jcr:primaryType (name) mandatory autocreated protected compute
+  - jcr:mixinTypes (name) protected multiple compute
+
+[nt:unstructured]
+  orderable
+  - * (undefined) multiple
+  - * (undefined)
+  + * (nt:base) = nt:unstructured multiple version
+
+[mix:referenceable]
+  mixin
+  - jcr:uuid (string) mandatory autocreated protected initialize
+
+[mix:lockable]
+  mixin
+  - jcr:lockOwner (string) protected ignore
+  - jcr:lockIsDeep (boolean) protected ignore
+
+//------------------------------------------------------------------------------
+// V E R S I O N I N G
+//------------------------------------------------------------------------------
+
+[mix:versionable] > mix:referenceable
+  mixin
+  - jcr:versionHistory (reference) mandatory protected
+    < 'nt:versionHistory'
+  - jcr:baseVersion (reference) mandatory protected ignore
+    < 'nt:version'
+  - jcr:isCheckedOut (boolean) = 'true' mandatory autocreated protected ignore
+  - jcr:predecessors (reference) mandatory protected multiple
+    < 'nt:version'
+  - jcr:mergeFailed (reference) protected multiple abort
+
+[nt:versionHistory] > mix:referenceable
+  - jcr:versionableUuid (string) mandatory autocreated protected abort
+  + jcr:rootVersion (nt:version) = nt:version mandatory autocreated protected abort
+  + jcr:versionLabels (nt:versionLabels) = nt:versionLabels mandatory autocreated protected abort
+  + * (nt:version) = nt:version protected abort
+
+[nt:versionLabels]
+  - * (reference) protected abort
+    < 'nt:version'
+
+[nt:version] > mix:referenceable
+  - jcr:created (date) mandatory autocreated protected abort
+  - jcr:predecessors (reference) protected multiple abort
+    < 'nt:version'
+  - jcr:successors (reference) protected multiple abort
+    < 'nt:version'
+  + jcr:frozenNode (nt:frozenNode) protected abort
+
+[nt:frozenNode] > mix:referenceable
+  orderable
+  - jcr:frozenPrimaryType (name) mandatory autocreated protected abort
+  - jcr:frozenMixinTypes (name) protected multiple abort
+  - jcr:frozenUuid (string) mandatory autocreated protected abort
+  - * (undefined) protected abort
+  - * (undefined) protected multiple abort
+  + * (nt:base) protected multiple abort
+
+[nt:versionedChild]
+  - jcr:childVersionHistory (reference) mandatory autocreated protected abort
+    < 'nt:versionHistory'
+
+//------------------------------------------------------------------------------
+// N O D E T Y P E S
+//------------------------------------------------------------------------------
+
+[nt:nodeType]
+  - jcr:nodeTypeName (name) mandatory
+  - jcr:supertypes (name) multiple
+  - jcr:isMixin (boolean) mandatory
+  - jcr:hasOrderableChildNodes (boolean) mandatory
+  - jcr:primaryItemName (name)
+  + jcr:propertyDefinition (nt:propertyDefinition) = nt:propertyDefinition multiple version
+  + jcr:childNodeDefinition (nt:childNodeDefinition) = nt:childNodeDefinition multiple version
+
+[nt:propertyDefinition]
+  - jcr:name (name)
+  - jcr:autoCreated (boolean) mandatory
+  - jcr:mandatory (boolean) mandatory
+  - jcr:onParentVersion (string) mandatory
+    < 'COPY', 'VERSION', 'INITIALIZE', 'COMPUTE', 'IGNORE', 'ABORT'
+  - jcr:protected (boolean) mandatory
+  - jcr:requiredType (string) mandatory
+    < 'STRING', 'BINARY', 'LONG', 'DOUBLE', 'BOOLEAN', 'DATE', 'NAME', 'PATH', 'REFERENCE', 'UNDEFINED'
+  - jcr:valueConstraints (string) multiple
+  - jcr:defaultValues (undefined) multiple
+  - jcr:multiple (boolean) mandatory
+
+[nt:childNodeDefinition]
+  - jcr:name (name)
+  - jcr:autoCreated (boolean) mandatory
+  - jcr:mandatory (boolean) mandatory
+  - jcr:onParentVersion (string) mandatory
+    < 'COPY', 'VERSION', 'INITIALIZE', 'COMPUTE', 'IGNORE', 'ABORT'
+  - jcr:protected (boolean) mandatory
+  - jcr:requiredPrimaryTypes (name) = 'nt:base' mandatory multiple
+  - jcr:defaultPrimaryType (name)
+  - jcr:sameNameSiblings (boolean) mandatory
+
+//------------------------------------------------------------------------------
+// M I S C
+//------------------------------------------------------------------------------
+
+[nt:hierarchyNode]
+  - jcr:created (date) autocreated protected initialize
+
+[nt:folder] > nt:hierarchyNode
+  + * (nt:hierarchyNode) version
+
+[nt:file] > nt:hierarchyNode
+  + jcr:content (nt:base) primary mandatory
+
+[nt:linkedFile] > nt:hierarchyNode
+  - jcr:content (reference) primary mandatory
+
+[nt:resource] > mix:referenceable
+  - jcr:encoding (string)
+  - jcr:mimeType (string) mandatory
+  - jcr:data (binary) primary mandatory
+  - jcr:lastModified (date) mandatory ignore
+
+[nt:query]
+  - jcr:statement (string)
+  - jcr:language (string)
+
+//------------------------------------------------------------------------------
+// J A C K R A B B I T   I N T E R N A L S
+//------------------------------------------------------------------------------
+
+[rep:nodeTypes]
+  + * (nt:nodeType) = nt:nodeType protected abort
+
+[rep:root] > nt:unstructured
+  orderable
+  + jcr:system (rep:system) = rep:system mandatory ignore
+
+[rep:system]
+  orderable
+  + jcr:versionStorage (rep:versionStorage) = rep:versionStorage mandatory protected abort
+  + jcr:nodeTypes (rep:nodeTypes) = rep:nodeTypes mandatory protected abort
+  + * (nt:base) = nt:unstructured multiple ignore
+
+[rep:versionStorage]
+  + * (nt:versionHistory) = nt:versionHistory protected multiple abort
+  + * (rep:versionStorage) = rep:versionStorage protected multiple abort

Added: trunk/dna-cnd/src/test/resources/cnd/jcr-builtins-283-early-draft.cnd
===================================================================
--- trunk/dna-cnd/src/test/resources/cnd/jcr-builtins-283-early-draft.cnd	                        (rev 0)
+++ trunk/dna-cnd/src/test/resources/cnd/jcr-builtins-283-early-draft.cnd	2009-04-20 19:07:48 UTC (rev 840)
@@ -0,0 +1,218 @@
+<jcr=http://www.jcp.org/jcr/1.0>
+<nt=http://www.jcp.org/jcr/nt/1.0>
+<mix=http://www.jcp.org/jcr/mix/1.0>
+<sv=http://www.jcp.org/jcr/sv/1.0>
+
+// ------------------------------------------------------------------------
+//                             Pre-defined Node Types
+// ------------------------------------------------------------------------
+
+[nt:base] abstract 
+  - jcr:primaryType (name) mandatory autocreated 
+      protected compute 
+  - jcr:mixinTypes (name) protected multiple compute
+  
+[nt:unstructured] 
+  orderable 
+  - * (undefined) multiple 
+  - * (undefined) 
+  + * (nt:base) = nt:unstructured multiple version 
+
+[nt:hierarchyNode] > mix:created abstract 
+
+[nt:file] > nt:hierarchyNode 
+  + jcr:content (nt:base) primary mandatory
+
+[nt:linkedFile] > nt:hierarchyNode 
+  - jcr:content (reference) primary mandatory
+
+[nt:folder] > nt:hierarchyNode 
+  + * (nt:hierarchyNode) version
+  
+[nt:resource] > mix:referenceable, 
+                mix:mimeTyped, 
+                mix:lastModified 
+  - jcr:data (binary) primary mandatory
+
+[nt:nodeType] 
+  - jcr:nodeTypeName (name) mandatory 
+  - jcr:supertypes (name) multiple 
+  - jcr:isAbstract (boolean) mandatory 
+  - jcr:isMixin (boolean) mandatory 
+  - jcr:hasOrderableChildNodes (boolean) mandatory 
+  - jcr:primaryItemName (name) 
+  + jcr:propertyDefinition (nt:propertyDefinition) 
+      = nt:propertyDefinition multiple version 
+  + jcr:childNodeDefinition (nt:childNodeDefinition) 
+      = nt:childNodeDefinition multiple version
+
+[nt:propertyDefinition] 
+  - jcr:name (name) 
+  - jcr:autoCreated (boolean) mandatory 
+  - jcr:mandatory (boolean) mandatory 
+  - jcr:onParentVersion (string) mandatory 
+      < 'COPY', 'VERSION', 'INITIALIZE', 'COMPUTE', 
+        'IGNORE', 'ABORT' 
+  - jcr:protected (boolean) mandatory 
+  - jcr:requiredType (string) mandatory 
+    < 'STRING', 'BINARY', 'LONG', 'DOUBLE', 'BOOLEAN', 
+      'DATE', 'NAME', 'PATH', 'REFERENCE', 'UNDEFINED' 
+  - jcr:valueConstraints (string) multiple 
+  - jcr:defaultValues (undefined) multiple 
+  - jcr:multiple (boolean) mandatory
+
+[nt:childNodeDefinition] 
+  - jcr:name (name) 
+  - jcr:autoCreated (boolean) mandatory 
+  - jcr:mandatory (boolean) mandatory 
+  - jcr:onParentVersion (string) mandatory 
+      < 'COPY', 'VERSION', 'INITIALIZE', 'COMPUTE', 
+        'IGNORE', 'ABORT' 
+  - jcr:protected (boolean) mandatory 
+  - jcr:requiredPrimaryTypes (name) = 'nt:base' mandatory
+      multiple 
+  - jcr:defaultPrimaryType (name) 
+  - jcr:sameNameSiblings (boolean) mandatory 
+
+[nt:versionHistory] > mix:referenceable 
+  - jcr:versionableUuid (string) mandatory autocreated 
+      protected abort 
+  - jcr:copiedFrom (reference) protected abort 
+      < 'nt:version' 
+  + jcr:rootVersion (nt:version) = nt:version mandatory 
+      autocreated protected abort 
+  + jcr:versionLabels (nt:versionLabels) 
+      = nt:versionLabels mandatory autocreated protected 
+      abort 
+  + * (nt:version) = nt:version protected abort
+
+[nt:versionLabels] 
+  - * (reference) protected abort 
+      < 'nt:version'
+
+[nt:version] > mix:referenceable 
+  - jcr:created (date) mandatory autocreated protected 
+      abort 
+  - jcr:predecessors (reference) protected multiple abort 
+      < 'nt:version' 
+  - jcr:successors (reference) protected multiple abort 
+      < 'nt:version' 
+  - jcr:activity (reference) protected abort 
+      < 'nt:activity' 
+  + jcr:frozenNode (nt:frozenNode) protected abort
+
+[nt:frozenNode] > mix:referenceable 
+  orderable 
+  - jcr:frozenPrimaryType (name) mandatory autocreated 
+      protected abort 
+  - jcr:frozenMixinTypes (name) protected multiple abort 
+  - jcr:frozenUuid (string) mandatory autocreated 
+      protected abort 
+  - * (undefined) protected abort 
+  - * (undefined) protected multiple abort 
+  + * (nt:base) protected multiple abort
+
+[nt:versionedChild] 
+  - jcr:childVersionHistory (reference) mandatory 
+      autocreated protected abort 
+      < 'nt:versionHistory'
+
+[nt:query] 
+  - jcr:statement (string) 
+  - jcr:language (string)
+
+[nt:activity] > mix:referenceable 
+  - jcr:title (string) 
+    mandatory autocreated protected
+
+[nt:configuration] > mix:versionable 
+  - jcr:root (reference) 
+    mandatory autocreated protected
+
+[nt:address] 
+  - jcr:protocol (string) 
+  - jcr:host (string)  
+  - jcr:port (string) 
+  - jcr:repository (string) 
+  - jcr:workspace (string) 
+  - jcr:path (path) 
+  - jcr:id (weakreference)
+
+[nt:naturalText] 
+  - jcr:text (string) 
+  - jcr:messageId (string)
+
+
+// ------------------------------------------------------------------------
+//                             Pre-defined Mixins
+// ------------------------------------------------------------------------
+
+[mix:lockable] 
+  mixin 
+  - jcr:lockOwner (string) protected ignore 
+  - jcr:lockIsDeep (boolean) protected ignore 
+
+[mix:referenceable] 
+  mixin 
+  - jcr:uuid (string) mandatory autocreated protected 
+      initialize 
+
+[mix:simpleVersionable] > mix:referenceable 
+  mixin 
+  - jcr:isCheckedOut (boolean) = 'true' mandatory 
+      autocreated protected ignore 
+  - jcr:versionLabels (name) mandatory protected multiple
+
+[mix:versionable] > mix:simpleVersionable 
+  mixin 
+  - jcr:versionHistory (reference) mandatory protected 
+      < 'nt:versionHistory' 
+  - jcr:baseVersion (reference) mandatory protected 
+      ignore 
+      < 'nt:version' 
+  - jcr:predecessors (reference) mandatory protected 
+      multiple 
+      < 'nt:version' 
+  - jcr:mergeFailed (reference) protected multiple abort 
+  - jcr:activity (reference) 
+      < 'nt:version' 
+  - jcr:configuration (reference) 
+      < 'nt:configuration'
+
+[mix:lifecycle] 
+  mixin 
+  - jcr:lifecyclePolicy (reference) protected initialize 
+  - jcr:currentLifecycleState (string) protected 
+initialize
+
+[mix:managedRetention] > mix:referenceable    
+ mixin 
+  - jcr:hold (string) protected multiple 
+  - jcr:isDeep (boolean) protected multiple 
+  - jcr:retentionPolicy (reference) protected
+
+[mix:shareable] > mix:referenceable mixin
+
+[mix:title] mixin 
+  - jcr:title (string) 
+  - jcr:description (string)  
+
+[mix:created] mixin 
+  - jcr:created (date)  
+  - jcr:createdBy (string)
+
+[mix:lastModified] mixin 
+  - jcr:lastModified (date) 
+  - jcr:lastModifiedBy (string)
+
+[mix:language] mixin 
+  - jcr:language (string) 
+
+[mix:mimeType] mixin 
+  - jcr:mimeType (string)  
+  - jcr:encoding (string)
+
+
+
+
+    
\ No newline at end of file

Added: trunk/dna-cnd/src/test/resources/cnd/mp3.cnd
===================================================================
--- trunk/dna-cnd/src/test/resources/cnd/mp3.cnd	                        (rev 0)
+++ trunk/dna-cnd/src/test/resources/cnd/mp3.cnd	2009-04-20 19:07:48 UTC (rev 840)
@@ -0,0 +1,53 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of 
+ * individual contributors. 
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+ 
+//------------------------------------------------------------------------------
+// N A M E S P A C E S
+//------------------------------------------------------------------------------
+<jcr='http://www.jcp.org/jcr/1.0'>
+<nt='http://www.jcp.org/jcr/nt/1.0'>
+<mix='http://www.jcp.org/jcr/mix/1.0'>
+<mp3='http://jboss.org/dna/mp3/1.0'>
+
+// ----------------------------------------------------------
+// JCR Pre-defined Mixin Types that are not loaded by default
+// ----------------------------------------------------------
+
+[mix:mimeType] mixin 
+  - jcr:mimeType (string)  
+  - jcr:encoding (string)
+
+
+//------------------------------------------------------------------------------
+// N O D E T Y P E S
+//------------------------------------------------------------------------------
+
+[mp3:metadata] > nt:unstructured, mix:mimeTyped
+  - mp3:title (string)
+  - mp3:author (string)
+  - mp3:album (string)
+  - mp3:year (long)
+  - mp3:comment (string)
+ 
+ 
\ No newline at end of file

Added: trunk/dna-cnd/src/test/resources/log4j.properties
===================================================================
--- trunk/dna-cnd/src/test/resources/log4j.properties	                        (rev 0)
+++ trunk/dna-cnd/src/test/resources/log4j.properties	2009-04-20 19:07:48 UTC (rev 840)
@@ -0,0 +1,13 @@
+# Direct log messages to stdout
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %m%n
+
+# Root logger option
+log4j.rootLogger=INFO, stdout
+
+# Set up the default logging to be INFO level, then override specific units
+log4j.logger.org.jboss.dna=INFO
+log4j.logger.org.jboss.dna.cnd=INFO
+

Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml	2009-04-17 14:23:57 UTC (rev 839)
+++ trunk/pom.xml	2009-04-20 19:07:48 UTC (rev 840)
@@ -114,7 +114,8 @@
 		<module>dna-common</module>
 		<module>dna-graph</module>
 		<module>dna-repository</module>
-		<module>dna-jcr</module>
+		<module>dna-cnd</module>
+		<!--module>dna-jcr</module-->
 		<module>extensions/dna-classloader-maven</module>
 		<module>extensions/dna-sequencer-images</module>
 		<module>extensions/dna-sequencer-mp3</module>




More information about the dna-commits mailing list