[dna-commits] DNA SVN: r597 - in trunk: dna-graph/src/main/java/org/jboss/dna/graph/properties and 7 other directories.

dna-commits at lists.jboss.org dna-commits at lists.jboss.org
Wed Oct 29 13:48:23 EDT 2008


Author: rhauch
Date: 2008-10-29 13:48:23 -0400 (Wed, 29 Oct 2008)
New Revision: 597

Added:
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphImporter.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/JcrLexicon.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/JcrNtLexicon.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphImporterTest.java
Removed:
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/util/
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/util/
Modified:
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/NameFactory.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/XmlHandler.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/XmlSequencer.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/xml/XmlHandlerTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/xml/XmlSequencerTest.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrLexicon.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerOutputMap.java
   trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencerNodeContextTest.java
   trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/RepositoryClient.java
Log:
DNA-242 - Change the XML importer code to no longer use XmlSequencer
http://jira.jboss.com/jira/browse/DNA-242

Changed the GraphImporter and Graph.importXmlFrom(...) methods to use the new XmlHandler (rather than the XmlSequencer).

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java	2008-10-29 15:16:23 UTC (rev 596)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java	2008-10-29 17:48:23 UTC (rev 597)
@@ -61,7 +61,7 @@
 import org.jboss.dna.graph.requests.RemovePropertiesRequest;
 import org.jboss.dna.graph.requests.Request;
 import org.jboss.dna.graph.requests.UpdatePropertiesRequest;
-import org.jboss.dna.graph.util.GraphImporter;
+import org.xml.sax.SAXException;
 
 /**
  * A graph representation of the content within a {@link RepositorySource}, including mechanisms to interact and manipulate that
@@ -993,31 +993,38 @@
      */
     public ImportInto<Conjunction<Graph>> importXmlFrom( final URI uri ) {
         return new ImportInto<Conjunction<Graph>>() {
-            public Conjunction<Graph> into( String path ) throws IOException {
+            private boolean skipRootElement = false;
+
+            public ImportInto<Conjunction<Graph>> skippingRootElement( boolean skipRootElement ) {
+                this.skipRootElement = skipRootElement;
+                return this;
+            }
+
+            public Conjunction<Graph> into( String path ) throws IOException, SAXException {
                 return into(new Location(createPath(path)));
             }
 
-            public Conjunction<Graph> into( Path path ) throws IOException {
+            public Conjunction<Graph> into( Path path ) throws IOException, SAXException {
                 return into(new Location(path));
             }
 
-            public Conjunction<Graph> into( Property idProperty ) throws IOException {
+            public Conjunction<Graph> into( Property idProperty ) throws IOException, SAXException {
                 return into(new Location(idProperty));
             }
 
             public Conjunction<Graph> into( Property firstIdProperty,
-                                            Property... additionalIdProperties ) throws IOException {
+                                            Property... additionalIdProperties ) throws IOException, SAXException {
                 return into(new Location(firstIdProperty, additionalIdProperties));
             }
 
-            public Conjunction<Graph> into( UUID uuid ) throws IOException {
+            public Conjunction<Graph> into( UUID uuid ) throws IOException, SAXException {
                 return into(new Location(uuid));
             }
 
             @SuppressWarnings( "synthetic-access" )
-            public Conjunction<Graph> into( Location at ) throws IOException {
+            public Conjunction<Graph> into( Location at ) throws IOException, SAXException {
                 GraphImporter importer = new GraphImporter(Graph.this);
-                importer.importXml(uri, at).execute(); // 'importXml' creates and uses a new batch
+                importer.importXml(uri, at, skipRootElement).execute(); // 'importXml' creates and uses a new batch
                 return Graph.this.nextGraph;
             }
         };
@@ -2482,13 +2489,23 @@
      */
     public interface ImportInto<Next> {
         /**
+         * Specify whether the root element in the XML document should be skipped (that is, not be represented by a node). By
+         * default, the root element is not skipped.
+         * 
+         * @param skip true if the root element should be skipped, or false if a node should be created for the root XML element
+         * @return the interface used to specify the location where the content should be placed
+         */
+        ImportInto<Next> skippingRootElement( boolean skip );
+
+        /**
          * Finish the import by specifying the new location into which the node should be copied/moved.
          * 
          * @param to the location of the new parent
          * @return the interface for additional requests or actions
          * @throws IOException if there is a problem reading the content being imported
+         * @throws SAXException if there is a problem with the SAX Parser
          */
-        Next into( Location to ) throws IOException;
+        Next into( Location to ) throws IOException, SAXException;
 
         /**
          * Finish the import by specifying the new location into which the node should be copied/moved.
@@ -2496,8 +2513,9 @@
          * @param toPath the path of the new parent
          * @return the interface for additional requests or actions
          * @throws IOException if there is a problem reading the content being imported
+         * @throws SAXException if there is a problem with the SAX Parser
          */
-        Next into( String toPath ) throws IOException;
+        Next into( String toPath ) throws IOException, SAXException;
 
         /**
          * Finish the import by specifying the new location into which the node should be copied/moved.
@@ -2505,8 +2523,9 @@
          * @param to the path of the new parent
          * @return the interface for additional requests or actions
          * @throws IOException if there is a problem reading the content being imported
+         * @throws SAXException if there is a problem with the SAX Parser
          */
-        Next into( Path to ) throws IOException;
+        Next into( Path to ) throws IOException, SAXException;
 
         /**
          * Finish the import by specifying the new location into which the node should be copied/moved.
@@ -2514,8 +2533,9 @@
          * @param to the UUID of the new parent
          * @return the interface for additional requests or actions
          * @throws IOException if there is a problem reading the content being imported
+         * @throws SAXException if there is a problem with the SAX Parser
          */
-        Next into( UUID to ) throws IOException;
+        Next into( UUID to ) throws IOException, SAXException;
 
         /**
          * Finish the import by specifying the new location into which the node should be copied/moved.
@@ -2523,8 +2543,9 @@
          * @param idProperty the property that uniquely identifies the new parent
          * @return the interface for additional requests or actions
          * @throws IOException if there is a problem reading the content being imported
+         * @throws SAXException if there is a problem with the SAX Parser
          */
-        Next into( Property idProperty ) throws IOException;
+        Next into( Property idProperty ) throws IOException, SAXException;
 
         /**
          * Finish the import by specifying the new location into which the node should be copied/moved.
@@ -2535,9 +2556,10 @@
          *        identifies the new parent
          * @return the interface for additional requests or actions
          * @throws IOException if there is a problem reading the content being imported
+         * @throws SAXException if there is a problem with the SAX Parser
          */
         Next into( Property firstIdProperty,
-                   Property... additionalIdProperties ) throws IOException;
+                   Property... additionalIdProperties ) throws IOException, SAXException;
     }
 
     public interface BatchConjunction extends Conjunction<Batch>, Executable {
@@ -2616,9 +2638,11 @@
         }
 
         public Results execute() {
-            // Execute the requests ...
-            Request request = CompositeRequest.with(requests);
-            Graph.this.execute(request);
+            if (!requests.isEmpty()) {
+                // Execute the requests ...
+                Request request = CompositeRequest.with(requests);
+                Graph.this.execute(request);
+            }
             return new BatchResults(requests);
         }
     }

Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphImporter.java (from rev 593, trunk/dna-graph/src/main/java/org/jboss/dna/graph/util/GraphImporter.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphImporter.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphImporter.java	2008-10-29 17:48:23 UTC (rev 597)
@@ -0,0 +1,173 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * 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.
+ *
+ * This software 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.graph;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.List;
+import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.common.text.TextDecoder;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.connectors.RepositorySource;
+import org.jboss.dna.graph.connectors.RepositorySourceException;
+import org.jboss.dna.graph.properties.Name;
+import org.jboss.dna.graph.properties.NamespaceRegistry;
+import org.jboss.dna.graph.properties.Path;
+import org.jboss.dna.graph.properties.Property;
+import org.jboss.dna.graph.xml.XmlHandler;
+import org.jboss.dna.graph.xml.XmlHandler.Destination;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+/**
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public class GraphImporter {
+
+    private final Graph graph;
+
+    public GraphImporter( Graph graph ) {
+        CheckArg.isNotNull(graph, "graph");
+        this.graph = graph;
+    }
+
+    /**
+     * Get the context in which the importer will be executed.
+     * 
+     * @return the execution context; never null
+     */
+    public ExecutionContext getContext() {
+        return this.graph.getContext();
+    }
+
+    /**
+     * The graph that this importer uses.
+     * 
+     * @return the graph; never null
+     */
+    public Graph getGraph() {
+        return graph;
+    }
+
+    /**
+     * Read the content from the supplied URI and import into the repository at the supplied location.
+     * 
+     * @param uri the URI where the importer can read the content that is to be imported
+     * @param location the location in the {@link RepositorySource repository source} where the content is to be written; may not
+     *        be null
+     * @return the batch of requests for creating the graph content that represents the imported content
+     * @throws IllegalArgumentException if the <code>uri</code> or destination path are null
+     * @throws IOException if there is a problem reading the content
+     * @throws SAXException if there is a problem with the SAX Parser
+     * @throws RepositorySourceException if there is a problem while writing the content to the {@link RepositorySource repository
+     *         source}
+     */
+    public Graph.Batch importXml( URI uri,
+                                  Location location ) throws IOException, SAXException, RepositorySourceException {
+        return importXml(uri, location, false);
+    }
+
+    /**
+     * Read the content from the supplied URI and import into the repository at the supplied location.
+     * 
+     * @param uri the URI where the importer can read the content that is to be imported
+     * @param location the location in the {@link RepositorySource repository source} where the content is to be written; may not
+     *        be null
+     * @param skip true if the root element should be skipped, or false if a node should be created for the root XML element
+     * @return the batch of requests for creating the graph content that represents the imported content
+     * @throws IllegalArgumentException if the <code>uri</code> or destination path are null
+     * @throws IOException if there is a problem reading the content
+     * @throws SAXException if there is a problem with the SAX Parser
+     * @throws RepositorySourceException if there is a problem while writing the content to the {@link RepositorySource repository
+     *         source}
+     */
+    public Graph.Batch importXml( URI uri,
+                                  Location location,
+                                  boolean skip ) throws IOException, SAXException, RepositorySourceException {
+        CheckArg.isNotNull(uri, "uri");
+        CheckArg.isNotNull(location, "location");
+        CheckArg.isNotNull(location.getPath(), "location.getPath()");
+
+        // Create the destination for the XmlHandler ...
+        Graph.Batch batch = graph.batch();
+        XmlHandler.Destination destination = new CreateOnGraphInBatch(batch);
+
+        // Determine where the content is to be placed ...
+        Path parentPath = location.getPath();
+        InputStream stream = null;
+        Name nameAttribute = JcrLexicon.NAME;
+        Name typeAttribute = JcrLexicon.PRIMARY_TYPE;
+        Name typeAttributeValue = null;
+        NamespaceRegistry reg = graph.getContext().getNamespaceRegistry();
+        if (reg.isRegisteredNamespaceUri(JcrNtLexicon.Namespace.URI)) {
+            typeAttributeValue = JcrNtLexicon.UNSTRUCTURED;
+        }
+
+        TextDecoder decoder = null;
+        XmlHandler.AttributeScoping scoping = XmlHandler.AttributeScoping.USE_DEFAULT_NAMESPACE;
+        XmlHandler handler = new XmlHandler(destination, skip, parentPath, decoder, nameAttribute, typeAttribute,
+                                            typeAttributeValue, scoping);
+        try {
+            stream = uri.toURL().openStream();
+            XMLReader reader = XMLReaderFactory.createXMLReader();
+            reader.setContentHandler(handler);
+            reader.setErrorHandler(handler);
+            reader.parse(new InputSource(stream));
+        } finally {
+            if (stream != null) stream.close();
+        }
+        return batch;
+    }
+
+    @NotThreadSafe
+    protected final static class CreateOnGraphInBatch implements Destination {
+        private final Graph.Batch batch;
+
+        protected CreateOnGraphInBatch( Graph.Batch batch ) {
+            assert batch != null;
+            this.batch = batch;
+        }
+
+        public ExecutionContext getExecutionContext() {
+            return batch.getGraph().getContext();
+        }
+
+        public void create( Path path,
+                            List<Property> properties,
+                            Name elementName ) {
+            assert properties != null;
+            if (properties.isEmpty()) {
+                batch.create(path).and();
+            } else {
+                batch.create(path, properties).and();
+            }
+        }
+
+        public void submit() {
+        }
+    }
+
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphImporter.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/dna-graph/src/main/java/org/jboss/dna/graph/JcrLexicon.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/JcrLexicon.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/JcrLexicon.java	2008-10-29 17:48:23 UTC (rev 597)
@@ -0,0 +1,40 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * 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.
+ *
+ * This software 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.graph;
+
+import org.jboss.dna.graph.properties.Name;
+import org.jboss.dna.graph.properties.basic.BasicName;
+
+/**
+ * @author Randall Hauch
+ */
+public class JcrLexicon {
+
+    public static class Namespace {
+        public static final String URI = "http://www.jcp.org/jcr/1.0";
+        public static final String PREFIX = "jcr";
+    }
+
+    public static final Name UUID = new BasicName(Namespace.URI, "uuid");
+    public static final Name NAME = new BasicName(Namespace.URI, "name");
+    public static final Name PRIMARY_TYPE = new BasicName(Namespace.URI, "primaryType");
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/JcrLexicon.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/dna-graph/src/main/java/org/jboss/dna/graph/JcrNtLexicon.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/JcrNtLexicon.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/JcrNtLexicon.java	2008-10-29 17:48:23 UTC (rev 597)
@@ -0,0 +1,38 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * 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.
+ *
+ * This software 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.graph;
+
+import org.jboss.dna.graph.properties.Name;
+import org.jboss.dna.graph.properties.basic.BasicName;
+
+/**
+ * @author Randall Hauch
+ */
+public class JcrNtLexicon {
+
+    public static class Namespace {
+        public static final String URI = "http://www.jcp.org/jcr/nt/1.0";
+        public static final String PREFIX = "nt";
+    }
+
+    public static final Name UNSTRUCTURED = new BasicName(Namespace.URI, "unstructured");
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/JcrNtLexicon.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/NameFactory.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/NameFactory.java	2008-10-29 15:16:23 UTC (rev 596)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/NameFactory.java	2008-10-29 17:48:23 UTC (rev 597)
@@ -30,8 +30,6 @@
  */
 public interface NameFactory extends ValueFactory<Name> {
 
-    String JCR_PRIMARY_TYPE = "jcr:primaryType";
-
     /**
      * Create a name from the given namespace URI and local name.
      * <p>
@@ -43,7 +41,8 @@
      * @return the new name
      * @throws IllegalArgumentException if the local name is <code>null</code> or empty
      */
-    Name create( String namespaceUri, String localName );
+    Name create( String namespaceUri,
+                 String localName );
 
     /**
      * Create a name from the given namespace URI and local name.
@@ -54,7 +53,9 @@
      * @return the new name
      * @throws IllegalArgumentException if the local name is <code>null</code> or empty
      */
-    Name create( String namespaceUri, String localName, TextDecoder decoder );
+    Name create( String namespaceUri,
+                 String localName,
+                 TextDecoder decoder );
 
     /**
      * Get the namespace registry.

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/XmlHandler.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/XmlHandler.java	2008-10-29 15:16:23 UTC (rev 596)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/XmlHandler.java	2008-10-29 17:48:23 UTC (rev 597)
@@ -31,7 +31,6 @@
 import org.jboss.dna.common.text.XmlNameEncoder;
 import org.jboss.dna.common.util.CheckArg;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.Graph;
 import org.jboss.dna.graph.properties.Name;
 import org.jboss.dna.graph.properties.NameFactory;
 import org.jboss.dna.graph.properties.NamespaceRegistry;
@@ -91,6 +90,16 @@
     protected final Name nameAttribute;
 
     /**
+     * The name of the property that is to be set with the type of the XML element. For example, "jcr:name".
+     */
+    protected final Name typeAttribute;
+
+    /**
+     * The value of the node type property, if the node's name is set with the {@link #nameAttribute}.
+     */
+    protected final Name typeAttributeValue;
+
+    /**
      * The cached reference to the graph's path factory.
      */
     protected final PathFactory pathFactory;
@@ -154,8 +163,12 @@
      * @param parent the path to the node in the graph under which the content should be placed; if null, the root node is assumed
      * @param textDecoder the text decoder that should be used to decode the XML element names and XML attribute names, prior to
      *        using those values to create names; or null if the default encoder should be used
-     * @param nameAttribute the name of the XML attribute whose value should be used for the names of the nodes (typically, this
-     *        is "jcr:name" or something equivalent); or null if the XML element name should always be used as the node name
+     * @param nameAttribute the name of the property whose value should be used for the names of the nodes (typically, this is
+     *        "jcr:name" or something equivalent); or null if the XML element name should always be used as the node name
+     * @param typeAttribute the name of the property that should be set with the type of the XML element, or null if there is no
+     *        such property
+     * @param typeAttributeValue the value of the type property that should be used if the node has no <code>nameAttribute</code>,
+     *        or null if the value should be set to the type of the XML element
      * @param scoping defines how to choose the namespace of attributes that do not have a namespace prefix; if null, the
      *        {@link #DEFAULT_ATTRIBUTE_SCOPING} value is used
      * @throws IllegalArgumentException if the destination reference is null
@@ -165,11 +178,15 @@
                        Path parent,
                        TextDecoder textDecoder,
                        Name nameAttribute,
+                       Name typeAttribute,
+                       Name typeAttributeValue,
                        AttributeScoping scoping ) {
         CheckArg.isNotNull(destination, "destination");
         assert destination != null;
         this.destination = destination;
         this.nameAttribute = nameAttribute;
+        this.typeAttribute = typeAttribute;
+        this.typeAttributeValue = typeAttributeValue;
         this.decoder = textDecoder != null ? textDecoder : DEFAULT_DECODER;
         this.skipFirstElement = skipRootElement;
         this.attributeScoping = scoping != null ? scoping : DEFAULT_ATTRIBUTE_SCOPING;
@@ -192,39 +209,6 @@
     }
 
     /**
-     * Create a handler that creates content in the supplied graph
-     * 
-     * @param graph the graph in which the content should be placed
-     * @param useBatch true if all of the actions to create the content in the graph should be submitted to the graph in a single
-     *        batch, or false if they should be submitted immediately after each is identified
-     * @param skipRootElement true if the root element of the document should be skipped, or false if the root element should be
-     *        converted to the top-level node of the content
-     * @param parent the path to the node in the graph under which the content should be placed; if null, the root node is assumed
-     * @param textDecoder the text decoder that should be used to decode the XML element names and XML attribute names, prior to
-     *        using those values to create names; or null if the default encoder should be used
-     * @param nameAttribute the name of the XML attribute whose value should be used for the names of the nodes (typically, this
-     *        is "jcr:name" or something equivalent); or null if the XML element name should always be used as the node name
-     * @param scoping defines how to choose the namespace of attributes that do not have a namespace prefix; if null, the
-     *        {@link #DEFAULT_ATTRIBUTE_SCOPING} value is used
-     * @throws IllegalArgumentException if the graph reference is null
-     */
-    public XmlHandler( Graph graph,
-                       boolean useBatch,
-                       boolean skipRootElement,
-                       Path parent,
-                       TextDecoder textDecoder,
-                       Name nameAttribute,
-                       AttributeScoping scoping ) {
-        this(createDestination(graph, useBatch), skipRootElement, parent, textDecoder, nameAttribute, scoping);
-    }
-
-    protected static Destination createDestination( Graph graph,
-                                                    boolean useBatch ) {
-        CheckArg.isNotNull(graph, "graph");
-        return useBatch ? new CreateOnGraphInBatches(graph.batch()) : new CreateOnGraph(graph);
-    }
-
-    /**
      * {@inheritDoc}
      * <p>
      * This method ensures that the namespace is registered with the {@link NamespaceRegistry registry}, using the supplied prefix
@@ -267,6 +251,7 @@
         Name nodeName = null;
 
         properties.clear();
+        Object typePropertyValue = null;
         // Convert each of the attributes to a property ...
         for (int i = 0; i != attributes.getLength(); ++i) {
             String attributeLocalName = attributes.getLocalName(i);
@@ -290,16 +275,34 @@
                 nodeName = nameFactory.create(attributes.getValue(i)); // don't use a decoder
                 continue;
             }
+            if (attributeName.equals(typeAttribute)) {
+                typePropertyValue = nameFactory.create(attributes.getValue(i)); // don't use a decoder
+                continue;
+            }
             // Create a property for this attribute ...
             Property property = createProperty(attributeName, attributes.getValue(i));
             properties.add(property);
         }
         // Create the node name if required ...
-        if (nodeName == null) nodeName = nameFactory.create(uri, localName, decoder);
+        Name elementName = nameFactory.create(uri, localName, decoder);
+        if (nodeName == null) {
+            // No attribute defines the node name ...
+            nodeName = elementName;
+        } else {
+            // A attribute defines the node name ...
+            typePropertyValue = elementName;
+        }
+        // Set the type property, if required
+        if (typeAttribute != null) {
+            if (typePropertyValue == null) typePropertyValue = typeAttributeValue;
+            propertyValues[0] = typePropertyValue;
+            Property property = propertyFactory.create(typeAttribute, propertyValues);
+            properties.add(property);
+        }
         // Update the current path ...
         currentPath = pathFactory.create(currentPath, nodeName);
         // Create the node, and note that we don't care about same-name siblings (as the graph will correct them) ...
-        destination.create(currentPath, properties);
+        destination.create(currentPath, properties, elementName);
     }
 
     /**
@@ -363,9 +366,12 @@
          * 
          * @param path the absolute path of the node
          * @param properties the properties for the node; never null, but may be empty if there are no properties
+         * @param elementName the name of the XML element from which the node should be created; never null, and may or may not be
+         *        the same name as the last segment of the path
          */
         public void create( Path path,
-                            List<Property> properties );
+                            List<Property> properties,
+                            Name elementName );
 
         /**
          * Signal to this destination that any enqueued create requests should be submitted. Usually this happens at the end of
@@ -373,61 +379,4 @@
          */
         public void submit();
     }
-
-    @NotThreadSafe
-    protected final static class CreateOnGraph implements Destination {
-        private final Graph graph;
-
-        protected CreateOnGraph( final Graph graph ) {
-            assert graph != null;
-            this.graph = graph;
-        }
-
-        public ExecutionContext getExecutionContext() {
-            return graph.getContext();
-        }
-
-        public final void create( Path path,
-                                  List<Property> properties ) {
-            assert properties != null;
-            if (properties.isEmpty()) {
-                graph.create(path);
-            } else {
-                graph.create(path, properties);
-            }
-        }
-
-        public void submit() {
-            // Nothing to do, since each call to 'create' immediate executes on the graph
-        }
-    }
-
-    @NotThreadSafe
-    protected final static class CreateOnGraphInBatches implements Destination {
-        private final Graph.Batch batch;
-
-        protected CreateOnGraphInBatches( Graph.Batch batch ) {
-            assert batch != null;
-            this.batch = batch;
-        }
-
-        public ExecutionContext getExecutionContext() {
-            return batch.getGraph().getContext();
-        }
-
-        public void create( Path path,
-                            List<Property> properties ) {
-            assert properties != null;
-            if (properties.isEmpty()) {
-                batch.create(path);
-            } else {
-                batch.create(path, properties);
-            }
-        }
-
-        public void submit() {
-            batch.execute();
-        }
-    }
-
 }

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/XmlSequencer.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/XmlSequencer.java	2008-10-29 15:16:23 UTC (rev 596)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/xml/XmlSequencer.java	2008-10-29 17:48:23 UTC (rev 597)
@@ -30,6 +30,7 @@
 import org.jboss.dna.common.monitor.ProgressMonitor;
 import org.jboss.dna.common.util.StringUtil;
 import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.JcrLexicon;
 import org.jboss.dna.graph.properties.Name;
 import org.jboss.dna.graph.properties.NameFactory;
 import org.jboss.dna.graph.properties.NamespaceRegistry;
@@ -128,7 +129,6 @@
 
         // Cached instances of the name factory and commonly referenced names
         private final NameFactory nameFactory;
-        private Name primaryTypeName;
         private Name defaultPrimaryType;
 
         // Recursive map used to track the number of occurrences of names for elements under a particular path
@@ -233,7 +233,7 @@
             stopIfCancelled();
             // Output separate nodes for each comment since multiple are allowed
             startElement(DnaXmlLexicon.COMMENT);
-            output.setProperty(path, getPrimaryTypeName(), DnaXmlLexicon.COMMENT);
+            output.setProperty(path, JcrLexicon.PRIMARY_TYPE, DnaXmlLexicon.COMMENT);
             output.setProperty(path, DnaXmlLexicon.COMMENT_CONTENT, String.valueOf(ch, start, length));
             endElement();
             updateProgress();
@@ -281,7 +281,7 @@
                 if (content.length() > 0) {
                     // Create separate node for each content entry since entries can be interspersed amongst child elements
                     startElement(DnaXmlLexicon.ELEMENT_CONTENT);
-                    output.setProperty(path, getPrimaryTypeName(), DnaXmlLexicon.ELEMENT_CONTENT);
+                    output.setProperty(path, JcrLexicon.PRIMARY_TYPE, DnaXmlLexicon.ELEMENT_CONTENT);
                     output.setProperty(path, DnaXmlLexicon.ELEMENT_CONTENT, content);
                     endElement();
                 }
@@ -380,7 +380,7 @@
             // Add "synthetic" entity container to path to help prevent name collisions with XML elements
             Name entityName = DnaDtdLexicon.ENTITY;
             startElement(entityName);
-            output.setProperty(path, getPrimaryTypeName(), entityName);
+            output.setProperty(path, JcrLexicon.PRIMARY_TYPE, entityName);
             output.setProperty(path, nameFactory.create(DnaDtdLexicon.NAME), name);
             output.setProperty(path, nameFactory.create(DnaDtdLexicon.PUBLIC_ID), publicId);
             output.setProperty(path, nameFactory.create(DnaDtdLexicon.SYSTEM_ID), systemId);
@@ -401,13 +401,6 @@
             monitor.getProblems().addError(error, GraphI18n.fatalErrorSequencingXmlDocument, error);
         }
 
-        private Name getPrimaryTypeName() {
-            if (primaryTypeName == null) {
-                primaryTypeName = nameFactory.create(NameFactory.JCR_PRIMARY_TYPE);
-            }
-            return primaryTypeName;
-        }
-
         private Name getDefaultPrimaryType() {
             if (defaultPrimaryType == null) {
                 defaultPrimaryType = nameFactory.create(DEFAULT_PRIMARY_TYPE);
@@ -443,7 +436,7 @@
             // Add "synthetic" entity container to path to help prevent name collisions with XML elements
             Name entityName = DnaDtdLexicon.ENTITY;
             startElement(entityName);
-            output.setProperty(path, getPrimaryTypeName(), entityName);
+            output.setProperty(path, JcrLexicon.PRIMARY_TYPE, entityName);
             output.setProperty(path, DnaDtdLexicon.NAME, name);
             output.setProperty(path, DnaDtdLexicon.VALUE, value);
             endElement();
@@ -478,7 +471,7 @@
             // Output separate nodes for each instruction since multiple are allowed
             Name name = DnaXmlLexicon.PROCESSING_INSTRUCTION;
             startElement(name);
-            output.setProperty(path, getPrimaryTypeName(), name);
+            output.setProperty(path, JcrLexicon.PRIMARY_TYPE, name);
             output.setProperty(path, DnaXmlLexicon.TARGET, target);
             output.setProperty(path, DnaXmlLexicon.PROCESSING_INSTRUCTION_CONTENT, data);
             endElement();
@@ -524,7 +517,7 @@
         @Override
         public void startDocument() throws SAXException {
             stopIfCancelled();
-            output.setProperty(path, getPrimaryTypeName(), DnaXmlLexicon.DOCUMENT);
+            output.setProperty(path, JcrLexicon.PRIMARY_TYPE, DnaXmlLexicon.DOCUMENT);
             updateProgress();
         }
 
@@ -603,7 +596,7 @@
                 }
             }
             startElement(nameObj);
-            output.setProperty(path, getPrimaryTypeName(), type);
+            output.setProperty(path, JcrLexicon.PRIMARY_TYPE, type);
             // Output this element's attributes using the attribute's namespace, if supplied, or the current namespace in scope.
             String inheritedNs = nsStack.getFirst();
             for (int ndx = 0, len = attributes.getLength(); ndx < len; ++ndx) {

Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphImporterTest.java (from rev 593, trunk/dna-graph/src/test/java/org/jboss/dna/graph/util/GraphImporterTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphImporterTest.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphImporterTest.java	2008-10-29 17:48:23 UTC (rev 597)
@@ -0,0 +1,182 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * 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.
+ *
+ * This software 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.graph;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.stub;
+import java.io.File;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.transaction.xa.XAResource;
+import org.jboss.dna.common.util.StringUtil;
+import org.jboss.dna.graph.cache.CachePolicy;
+import org.jboss.dna.graph.connectors.BasicExecutionContext;
+import org.jboss.dna.graph.connectors.RepositoryConnection;
+import org.jboss.dna.graph.connectors.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connectors.RepositorySourceException;
+import org.jboss.dna.graph.connectors.RepositorySourceListener;
+import org.jboss.dna.graph.properties.Name;
+import org.jboss.dna.graph.properties.Path;
+import org.jboss.dna.graph.properties.Property;
+import org.jboss.dna.graph.requests.CompositeRequest;
+import org.jboss.dna.graph.requests.CreateNodeRequest;
+import org.jboss.dna.graph.requests.Request;
+import org.jboss.dna.graph.xml.DnaDtdLexicon;
+import org.jboss.dna.graph.xml.DnaXmlLexicon;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoAnnotations.Mock;
+
+/**
+ * @author Randall Hauch
+ */
+public class GraphImporterTest {
+
+    private Graph graph;
+    private GraphImporter importer;
+    private String sourceName;
+    private ExecutionContext context;
+    private URI xmlContent;
+    private MockRepositoryConnection connection;
+    private Request lastExecutedRequest;
+    private Path destinationPath;
+    @Mock
+    private RepositoryConnectionFactory sources;
+
+    @Before
+    public void beforeEach() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        xmlContent = new File("src/test/resources/repositoryImporterTestData1.xml").toURI();
+        context = new BasicExecutionContext();
+        context.getNamespaceRegistry().register(DnaLexicon.Namespace.PREFIX, DnaLexicon.Namespace.URI);
+        context.getNamespaceRegistry().register(DnaXmlLexicon.Namespace.PREFIX, DnaXmlLexicon.Namespace.URI);
+        context.getNamespaceRegistry().register(DnaDtdLexicon.Namespace.PREFIX, DnaDtdLexicon.Namespace.URI);
+        context.getNamespaceRegistry().register("jcr", "http://www.jcp.org/jcr/1.0");
+        context.getNamespaceRegistry().register("nt", "http://www.jcp.org/jcr/nt/1.0");
+        sourceName = "sourceA";
+        destinationPath = context.getValueFactories().getPathFactory().create("/a/b");
+        graph = Graph.create(sourceName, sources, context);
+        importer = new GraphImporter(graph);
+        connection = new MockRepositoryConnection();
+        stub(sources.createConnection(sourceName)).toReturn(connection);
+    }
+
+    @Test
+    public void shouldImportXmlContentAndGenerateTheCorrectCommands() throws Exception {
+        System.out.println(xmlContent);
+        Graph.Batch batch = importer.importXml(xmlContent, new Location(destinationPath));
+        batch.execute();
+        // 'lastExecutedCommand'
+        assertThat(lastExecutedRequest, is(instanceOf(CompositeRequest.class)));
+        Iterator<Request> iter = ((CompositeRequest)lastExecutedRequest).iterator();
+        // assertCreateNode(iter, "/a/b/", "jcr:primaryType={http://www.jboss.org/dna/xml/1.0}document");
+        assertCreateNode(iter, "/a/b/dna:system[1]", "jcr:primaryType={http://www.jcp.org/jcr/nt/1.0}unstructured");
+        assertCreateNode(iter, "/a/b/dna:system[1]/dna:sources[1]", "jcr:primaryType={http://www.jcp.org/jcr/nt/1.0}unstructured");
+        assertCreateNode(iter,
+                         "/a/b/dna:system[1]/dna:sources[1]/sourceA[1]",
+                         "repositoryName=repositoryA",
+                         "retryLimit=3",
+                         "jcr:primaryType={http://www.jboss.org/dna}xyz",
+                         "dna:classname=org.jboss.dna.connector.inmemory.InMemoryRepositorySource");
+        assertCreateNode(iter,
+                         "/a/b/dna:system[1]/dna:sources[1]/sourceB[1]",
+                         "repositoryName=repositoryB",
+                         "jcr:primaryType={http://www.jcp.org/jcr/nt/1.0}unstructured",
+                         "dna:classname=org.jboss.dna.connector.inmemory.InMemoryRepositorySource");
+        assertThat(iter.hasNext(), is(false));
+    }
+
+    public void assertCreateNode( Iterator<Request> iterator,
+                                  String path,
+                                  String... properties ) {
+        Request nextCommand = iterator.next();
+        assertThat(nextCommand, is(instanceOf(CreateNodeRequest.class)));
+        CreateNodeRequest createNode = (CreateNodeRequest)nextCommand;
+        Path expectedPath = context.getValueFactories().getPathFactory().create(path);
+        assertThat(createNode.at().getPath(), is(expectedPath));
+        Map<Name, Property> propertiesByName = new HashMap<Name, Property>();
+        for (Property prop : createNode.properties()) {
+            propertiesByName.put(prop.getName(), prop);
+        }
+        for (String propertyStr : properties) {
+            if (propertyStr == "any properties") {
+                propertiesByName.clear();
+                break;
+            }
+            Matcher matcher = Pattern.compile("([^=]+)=(.*)").matcher(propertyStr);
+            if (!matcher.matches()) continue;
+            System.out.println("Property: " + propertyStr + " ==> " + matcher);
+            Name propertyName = context.getValueFactories().getNameFactory().create(matcher.group(1));
+            System.out.println("Property name: " + matcher.group(1));
+            String value = matcher.group(2); // doesn't handle multiple values!!
+            if (value.trim().length() == 0) value = null;
+            Property actual = propertiesByName.remove(propertyName);
+            Property expectedProperty = context.getPropertyFactory().create(propertyName, value);
+            assertThat("missing property " + propertyName, actual, is(expectedProperty));
+        }
+        if (!propertiesByName.isEmpty()) {
+            System.out.println("Properties for " + path + "\n" + StringUtil.readableString(propertiesByName));
+        }
+        assertThat(propertiesByName.isEmpty(), is(true));
+    }
+
+    protected class MockRepositoryConnection implements RepositoryConnection {
+        public void close() {
+        }
+
+        @SuppressWarnings( "synthetic-access" )
+        public void execute( ExecutionContext context,
+                             Request request ) throws RepositorySourceException {
+            lastExecutedRequest = request;
+        }
+
+        public CachePolicy getDefaultCachePolicy() {
+            return null;
+        }
+
+        @SuppressWarnings( "synthetic-access" )
+        public String getSourceName() {
+            return sourceName;
+        }
+
+        public XAResource getXAResource() {
+            return null;
+        }
+
+        public boolean ping( long time,
+                             TimeUnit unit ) {
+            return true;
+        }
+
+        public void setListener( RepositorySourceListener listener ) {
+        }
+    }
+
+}


Property changes on: trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphImporterTest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Modified: trunk/dna-graph/src/test/java/org/jboss/dna/graph/xml/XmlHandlerTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/xml/XmlHandlerTest.java	2008-10-29 15:16:23 UTC (rev 596)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/xml/XmlHandlerTest.java	2008-10-29 17:48:23 UTC (rev 597)
@@ -35,7 +35,7 @@
 import org.jboss.dna.common.text.Jsr283Encoder;
 import org.jboss.dna.common.text.TextDecoder;
 import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.JcrLexicon;
 import org.jboss.dna.graph.Location;
 import org.jboss.dna.graph.connectors.BasicExecutionContext;
 import org.jboss.dna.graph.properties.Name;
@@ -56,7 +56,7 @@
  */
 public class XmlHandlerTest {
 
-    private static final String JCR_NAMESPACE_URI = "http://www.jcp.org/jcr/1.0";
+    private static final String NT_NAMESPACE_URI = "http://www.jcp.org/jcr/nt/1.0";
 
     private XmlHandler handler;
     private ExecutionContext context;
@@ -65,37 +65,39 @@
     private Path parentPath;
     private TextDecoder decoder;
     private Name nameAttribute;
+    private Name typeAttribute;
+    private Name typeAttributeValue;
     private XmlHandler.AttributeScoping scoping;
     private LinkedList<CreateNodeRequest> requests;
 
     @Before
     public void beforeEach() {
         context = new BasicExecutionContext();
-        context.getNamespaceRegistry().register("jcr", JCR_NAMESPACE_URI);
+        context.getNamespaceRegistry().register(JcrLexicon.Namespace.PREFIX, JcrLexicon.Namespace.URI);
+        context.getNamespaceRegistry().register("nt", NT_NAMESPACE_URI);
         destination = new RecordingDestination();
         parentPath = context.getValueFactories().getPathFactory().create("/a/b");
         decoder = null;
-        nameAttribute = context.getValueFactories().getNameFactory().create("jcr:name");
+        nameAttribute = JcrLexicon.NAME;
+        typeAttribute = null;
+        typeAttributeValue = null;
         scoping = XmlHandler.AttributeScoping.USE_DEFAULT_NAMESPACE;
-        handler = new XmlHandler(destination, skipRootElement, parentPath, decoder, nameAttribute, scoping);
+        handler = new XmlHandler(destination, skipRootElement, parentPath, decoder, nameAttribute, typeAttribute,
+                                 typeAttributeValue, scoping);
     }
 
     @Test( expected = IllegalArgumentException.class )
     public void shouldNotConstructInstanceWhenGivenNullDestination() {
         destination = null;
-        new XmlHandler(destination, skipRootElement, parentPath, decoder, nameAttribute, scoping);
+        new XmlHandler(destination, skipRootElement, parentPath, decoder, nameAttribute, typeAttribute, typeAttributeValue,
+                       scoping);
     }
 
-    @Test( expected = IllegalArgumentException.class )
-    public void shouldNotConstructInstanceWhenGivenNullGraph() {
-        Graph graph = null;
-        new XmlHandler(graph, true, skipRootElement, parentPath, decoder, nameAttribute, scoping);
-    }
-
     @Test
     public void shouldUseDefaultDecoderIfNoneIsProvidedInConstructor() {
         decoder = null;
-        handler = new XmlHandler(destination, skipRootElement, parentPath, decoder, nameAttribute, scoping);
+        handler = new XmlHandler(destination, skipRootElement, parentPath, decoder, nameAttribute, typeAttribute,
+                                 typeAttributeValue, scoping);
         assertThat(handler.destination, is(sameInstance(destination)));
         assertThat(handler.currentPath, is(sameInstance(parentPath)));
         assertThat(handler.skipFirstElement, is(skipRootElement));
@@ -106,7 +108,8 @@
     @Test
     public void shouldUseDecoderProvidedInConstructor() {
         decoder = new Jsr283Encoder();
-        handler = new XmlHandler(destination, skipRootElement, parentPath, decoder, nameAttribute, scoping);
+        handler = new XmlHandler(destination, skipRootElement, parentPath, decoder, nameAttribute, typeAttribute,
+                                 typeAttributeValue, scoping);
         assertThat(handler.destination, is(sameInstance(destination)));
         assertThat(handler.currentPath, is(sameInstance(parentPath)));
         assertThat(handler.skipFirstElement, is(skipRootElement));
@@ -117,7 +120,8 @@
     @Test
     public void shouldPlaceContentUnderRootIfNoPathIsProvidedInConstructor() {
         parentPath = null;
-        handler = new XmlHandler(destination, skipRootElement, parentPath, decoder, nameAttribute, scoping);
+        handler = new XmlHandler(destination, skipRootElement, parentPath, decoder, nameAttribute, typeAttribute,
+                                 typeAttributeValue, scoping);
         assertThat(handler.destination, is(sameInstance(destination)));
         assertThat(handler.currentPath.isRoot(), is(true));
         assertThat(handler.skipFirstElement, is(skipRootElement));
@@ -128,7 +132,8 @@
     @Test
     public void shouldNotLookForNameAttributeIfNoneIsProvidedInConstructor() {
         nameAttribute = null;
-        handler = new XmlHandler(destination, skipRootElement, parentPath, decoder, nameAttribute, scoping);
+        handler = new XmlHandler(destination, skipRootElement, parentPath, decoder, nameAttribute, typeAttribute,
+                                 typeAttributeValue, scoping);
         assertThat(handler.destination, is(sameInstance(destination)));
         assertThat(handler.currentPath, is(sameInstance(parentPath)));
         assertThat(handler.skipFirstElement, is(skipRootElement));
@@ -199,9 +204,11 @@
     @Test
     public void shouldParseXmlDocumentWithNamespacesThatAreNotYetInRegistry() throws IOException, SAXException {
         NamespaceRegistry reg = context.getNamespaceRegistry();
-        reg.unregister(JCR_NAMESPACE_URI);
+        reg.unregister(JcrLexicon.Namespace.URI);
+        reg.unregister(NT_NAMESPACE_URI);
         // Verify the prefixes don't exist ...
-        assertThat(reg.getPrefixForNamespaceUri(JCR_NAMESPACE_URI, false), is(nullValue()));
+        assertThat(reg.getPrefixForNamespaceUri(JcrLexicon.Namespace.URI, false), is(nullValue()));
+        assertThat(reg.getPrefixForNamespaceUri(NT_NAMESPACE_URI, false), is(nullValue()));
         assertThat(reg.getPrefixForNamespaceUri("http://default.namespace.com", false), is(nullValue()));
         // Parse the XML file ...
         parse("xmlHandler/docWithNestedNamespaces.xml");
@@ -249,7 +256,8 @@
         context.getNamespaceRegistry().register("c", "http://default.namespace.com");
         parentPath = null;
         skipRootElement = true;
-        handler = new XmlHandler(destination, skipRootElement, parentPath, decoder, nameAttribute, scoping);
+        handler = new XmlHandler(destination, skipRootElement, parentPath, decoder, nameAttribute, typeAttribute,
+                                 typeAttributeValue, scoping);
         parse("xmlHandler/docWithNamespaces.xml");
         // Check the generated content; note that the attribute name DOES match, so the nodes names come from "jcr:name" attribute
         assertNode("c:Hybrid");
@@ -264,7 +272,8 @@
     @Test
     public void shouldParseXmlDocumentAndShouldPlaceContentUnderNonRootNode() throws IOException, SAXException {
         parentPath = context.getValueFactories().getPathFactory().create("/a/b");
-        handler = new XmlHandler(destination, skipRootElement, parentPath, decoder, nameAttribute, scoping);
+        handler = new XmlHandler(destination, skipRootElement, parentPath, decoder, nameAttribute, typeAttribute,
+                                 typeAttributeValue, scoping);
         context.getNamespaceRegistry().register("c", "http://default.namespace.com");
         parse("xmlHandler/docWithNamespaces.xml");
         // Check the generated content; note that the attribute name DOES match, so the nodes names come from "jcr:name" attribute
@@ -281,7 +290,8 @@
     @Test
     public void shouldParseXmlDocumentAndShouldPlaceContentUnderRootNode() throws IOException, SAXException {
         parentPath = null;
-        handler = new XmlHandler(destination, skipRootElement, parentPath, decoder, nameAttribute, scoping);
+        handler = new XmlHandler(destination, skipRootElement, parentPath, decoder, nameAttribute, typeAttribute,
+                                 typeAttributeValue, scoping);
         context.getNamespaceRegistry().register("c", "http://default.namespace.com");
         parse("xmlHandler/docWithNamespaces.xml");
         // Check the generated content; note that the attribute name DOES match, so the nodes names come from "jcr:name" attribute
@@ -309,6 +319,46 @@
         assertNode("c:Cars/c:Sports/Infiniti G37", "maker=Infiniti", "model=G37");
     }
 
+    @Test
+    public void shouldParseXmlDocumentWithoutNamespacesUsingTypeAttributeValue() throws IOException, SAXException {
+        typeAttribute = JcrLexicon.PRIMARY_TYPE;
+        typeAttributeValue = context.getValueFactories().getNameFactory().create("nt:unstructured");
+        handler = new XmlHandler(destination, skipRootElement, parentPath, decoder, nameAttribute, typeAttribute,
+                                 typeAttributeValue, scoping);
+        parse("xmlHandler/docWithoutNamespaces.xml");
+        // Check the generated content; note that the attribute name doesn't match, so the nodes don't get special names
+        String unstructPrimaryType = "jcr:primaryType={http://www.jcp.org/jcr/nt/1.0}unstructured";
+        assertNode("Cars", unstructPrimaryType);
+        assertNode("Cars/Hybrid", unstructPrimaryType);
+        assertNode("Cars/Hybrid/car", unstructPrimaryType, "name=Toyota Prius", "maker=Toyota", "model=Prius");
+        assertNode("Cars/Hybrid/car", unstructPrimaryType, "name=Toyota Highlander", "maker=Toyota", "model=Highlander");
+        assertNode("Cars/Hybrid/car", unstructPrimaryType, "name=Nissan Altima", "maker=Nissan", "model=Altima");
+        assertNode("Cars/Sports", unstructPrimaryType);
+        assertNode("Cars/Sports/car", unstructPrimaryType, "name=Aston Martin DB9", "maker=Aston Martin", "model=DB9");
+        assertNode("Cars/Sports/car", unstructPrimaryType, "name=Infiniti G37", "maker=Infiniti", "model=G37");
+    }
+
+    @Test
+    public void shouldParseXmlDocumentWithNamespacesUsingTypeAttributeValue() throws IOException, SAXException {
+        context.getNamespaceRegistry().register("c", "http://default.namespace.com");
+        typeAttribute = JcrLexicon.PRIMARY_TYPE;
+        typeAttributeValue = context.getValueFactories().getNameFactory().create("nt:unstructured");
+        handler = new XmlHandler(destination, skipRootElement, parentPath, decoder, nameAttribute, typeAttribute,
+                                 typeAttributeValue, scoping);
+        parse("xmlHandler/docWithNamespaces.xml");
+        // Check the generated content; note that the attribute name doesn't match, so the nodes don't get special names
+        String unstructPrimaryType = "jcr:primaryType={http://www.jcp.org/jcr/nt/1.0}unstructured";
+        String carPrimaryType = "jcr:primaryType={http://default.namespace.com}car";
+        assertNode("c:Cars", unstructPrimaryType);
+        assertNode("c:Cars/c:Hybrid", unstructPrimaryType);
+        assertNode("c:Cars/c:Hybrid/Toyota Prius", carPrimaryType, "maker=Toyota", "model=Prius");
+        assertNode("c:Cars/c:Hybrid/Toyota Highlander", carPrimaryType, "maker=Toyota", "model=Highlander");
+        assertNode("c:Cars/c:Hybrid/Nissan Altima", carPrimaryType, "maker=Nissan", "model=Altima");
+        assertNode("c:Cars/c:Sports", unstructPrimaryType);
+        assertNode("c:Cars/c:Sports/Aston Martin DB9", carPrimaryType, "maker=Aston Martin", "model=DB9");
+        assertNode("c:Cars/c:Sports/Infiniti G37", carPrimaryType, "maker=Infiniti", "model=G37");
+    }
+
     protected void assertNode( String path,
                                String... properties ) {
         // Create the expected path ...
@@ -335,7 +385,16 @@
             assertThat(expected, is(notNullValue()));
             assertThat(actual, is(expected));
         }
-        assertThat(expectedProperties.isEmpty(), is(true));
+        if (!expectedProperties.isEmpty()) {
+            StringBuilder msg = new StringBuilder("missing actual properties: ");
+            boolean isFirst = true;
+            for (Property expected : expectedProperties.values()) {
+                if (!isFirst) msg.append(", ");
+                else isFirst = false;
+                msg.append(expected.getName());
+            }
+            assertThat(msg.toString(), expectedProperties.isEmpty(), is(true));
+        }
     }
 
     protected void parse( String relativePathToXmlFile ) throws IOException, SAXException {
@@ -354,7 +413,8 @@
         private final LinkedList<CreateNodeRequest> requests = new LinkedList<CreateNodeRequest>();
 
         public void create( Path path,
-                            List<Property> properties ) {
+                            List<Property> properties,
+                            Name elementName ) {
             requests.add(new CreateNodeRequest(new Location(path), properties));
         }
 

Modified: trunk/dna-graph/src/test/java/org/jboss/dna/graph/xml/XmlSequencerTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/xml/XmlSequencerTest.java	2008-10-29 15:16:23 UTC (rev 596)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/xml/XmlSequencerTest.java	2008-10-29 17:48:23 UTC (rev 597)
@@ -31,7 +31,6 @@
 import org.jboss.dna.common.monitor.ProgressMonitor;
 import org.jboss.dna.common.monitor.SimpleProgressMonitor;
 import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NameFactory;
 import org.jboss.dna.graph.sequencers.MockSequencerContext;
 import org.jboss.dna.graph.sequencers.MockSequencerOutput;
 import org.jboss.dna.graph.sequencers.SequencerContext;
@@ -102,38 +101,38 @@
     @Test
     public void shouldSequenceXml() throws IOException {
         verifyDocument(xml1);
-        verifyName(COMMENT + "[1]", NameFactory.JCR_PRIMARY_TYPE, COMMENT);
+        verifyName(COMMENT + "[1]", "jcr:primaryType", COMMENT);
         String text = verify(COMMENT + "[1]", COMMENT_CONTENT, String.class);
         assertThat(text.startsWith("\n   Licensed to the Apache Software Foundation (ASF)"), is(true));
         assertThat(text.endsWith("   limitations under the License.\n"), is(true));
         verifyString("/", DTD_NAME, "Repository");
         verifyString("/", DTD_PUBLIC_ID, "-//The Apache Software Foundation//DTD Jackrabbit 1.2//EN");
         verifyString("/", DTD_SYSTEM_ID, "http://jackrabbit.apache.org/dtd/repository-1.2.dtd");
-        verifyName(COMMENT + "[2]", NameFactory.JCR_PRIMARY_TYPE, COMMENT);
+        verifyName(COMMENT + "[2]", "jcr:primaryType", COMMENT);
         verifyString(COMMENT + "[2]", COMMENT_CONTENT, " Example Repository Configuration File ");
-        verifyName("Repository[1]", NameFactory.JCR_PRIMARY_TYPE, "nt:unstructured");
-        verifyName("Repository[1]/" + COMMENT + "[1]", NameFactory.JCR_PRIMARY_TYPE, COMMENT);
+        verifyName("Repository[1]", "jcr:primaryType", "nt:unstructured");
+        verifyName("Repository[1]/" + COMMENT + "[1]", "jcr:primaryType", COMMENT);
     }
 
     @Test
     public void shouldHandleNamespaces() throws IOException {
         verifyDocument(xml2);
-        verifyName("book[1]/bookinfo[1]/xi:include[1]", NameFactory.JCR_PRIMARY_TYPE, "nt:unstructured");
+        verifyName("book[1]/bookinfo[1]/xi:include[1]", "jcr:primaryType", "nt:unstructured");
         verifyString("book[1]/bookinfo[1]/xi:include[1]", "xi:href", "Author_Group.xml");
-        verifyName("book[1]/bookinfo[1]/xi:include[2]", NameFactory.JCR_PRIMARY_TYPE, "nt:unstructured");
+        verifyName("book[1]/bookinfo[1]/xi:include[2]", "jcr:primaryType", "nt:unstructured");
         verifyString("book[1]/bookinfo[1]/xi:include[2]", "xi:href", "Legal_Notice.xml");
     }
 
     @Test
     public void shouldSequenceEntityDeclarations() throws IOException {
         verifyDocument(xml2);
-        verifyName(ENTITY + "[1]", NameFactory.JCR_PRIMARY_TYPE, ENTITY);
+        verifyName(ENTITY + "[1]", "jcr:primaryType", ENTITY);
         verifyString(ENTITY + "[1]", DTD_NAME, "%RH-ENTITIES");
         verifyString(ENTITY + "[1]", DTD_SYSTEM_ID, "Common_Config/rh-entities.ent");
-        verifyName(ENTITY + "[2]", NameFactory.JCR_PRIMARY_TYPE, ENTITY);
+        verifyName(ENTITY + "[2]", "jcr:primaryType", ENTITY);
         verifyString(ENTITY + "[2]", DTD_NAME, "versionNumber");
         verifyString(ENTITY + "[2]", DTD_VALUE, "0.1");
-        verifyName(ENTITY + "[3]", NameFactory.JCR_PRIMARY_TYPE, ENTITY);
+        verifyName(ENTITY + "[3]", "jcr:primaryType", ENTITY);
         verifyString(ENTITY + "[3]", DTD_NAME, "copyrightYear");
         verifyString(ENTITY + "[3]", DTD_VALUE, "2008");
     }
@@ -173,7 +172,7 @@
     @Test
     public void shouldSequenceProcessingInstructions() throws IOException {
         verifyDocument(xml4);
-        verifyName(PI + "[1]", NameFactory.JCR_PRIMARY_TYPE, PI);
+        verifyName(PI + "[1]", "jcr:primaryType", PI);
         verifyString(PI + "[1]", TARGET, "eclipse");
         verifyString(PI + "[1]", PI_CONTENT, "version=\"3.0\"");
     }
@@ -181,10 +180,10 @@
     @Test
     public void shouldSequenceXsds() throws IOException {
         verifyDocument(xsd);
-        verifyName("xs:schema[1]", NameFactory.JCR_PRIMARY_TYPE, "nt:unstructured");
+        verifyName("xs:schema[1]", "jcr:primaryType", "nt:unstructured");
         verifyString("xs:schema[1]", "xs:targetNamespace", "http://ns.adobe.com/air/application/1.0");
         verifyString("xs:schema[1]", "xs:elementFormDefault", "qualified");
-        verifyName("xs:schema[1]/xs:element[1]", NameFactory.JCR_PRIMARY_TYPE, "nt:unstructured");
+        verifyName("xs:schema[1]/xs:element[1]", "jcr:primaryType", "nt:unstructured");
         verifyString("xs:schema[1]/xs:element[1]", "xs:name", "application");
     }
 
@@ -203,7 +202,7 @@
         stream = url.openStream();
         assertThat(stream, is(notNullValue()));
         sequencer.sequence(stream, output, context, monitor);
-        verifyName("", NameFactory.JCR_PRIMARY_TYPE, DOCUMENT);
+        verifyName("", "jcr:primaryType", DOCUMENT);
     }
 
     private void verifyName( String nodePath,

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrLexicon.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrLexicon.java	2008-10-29 15:16:23 UTC (rev 596)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrLexicon.java	2008-10-29 17:48:23 UTC (rev 597)
@@ -21,18 +21,10 @@
  */
 package org.jboss.dna.jcr;
 
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.basic.BasicName;
 
 /**
  * @author Randall Hauch
  */
-class JcrLexicon {
+class JcrLexicon extends org.jboss.dna.graph.JcrLexicon {
 
-    public static class Namespace {
-        public static final String URI = "http://www.jcp.org/jcr/1.0";
-        public static final String PREFIX = "jcr";
-    }
-
-    public static final Name UUID = new BasicName(Namespace.URI, "uuid");
 }

Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerOutputMap.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerOutputMap.java	2008-10-29 15:16:23 UTC (rev 596)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerOutputMap.java	2008-10-29 17:48:23 UTC (rev 597)
@@ -32,8 +32,8 @@
 import net.jcip.annotations.NotThreadSafe;
 import org.jboss.dna.common.util.CheckArg;
 import org.jboss.dna.common.util.StringUtil;
+import org.jboss.dna.graph.JcrLexicon;
 import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.NameFactory;
 import org.jboss.dna.graph.properties.Path;
 import org.jboss.dna.graph.properties.PathFactory;
 import org.jboss.dna.graph.properties.ValueFactories;
@@ -230,8 +230,8 @@
          */
         public int compareTo( PropertyValue that ) {
             if (this == that) return 0;
-            if (this.name.equals(NameFactory.JCR_PRIMARY_TYPE)) return -1;
-            if (that.name.equals(NameFactory.JCR_PRIMARY_TYPE)) return 1;
+            if (this.name.equals(JcrLexicon.PRIMARY_TYPE)) return -1;
+            if (that.name.equals(JcrLexicon.PRIMARY_TYPE)) return 1;
             return this.name.compareTo(that.name);
         }
 

Modified: trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencerNodeContextTest.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencerNodeContextTest.java	2008-10-29 15:16:23 UTC (rev 596)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencerNodeContextTest.java	2008-10-29 17:48:23 UTC (rev 597)
@@ -30,7 +30,6 @@
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import org.jboss.dna.common.jcr.AbstractJcrRepositoryTest;
-import org.jboss.dna.graph.properties.NameFactory;
 import org.jboss.dna.graph.properties.NamespaceRegistry;
 import org.jboss.dna.graph.properties.Property;
 import org.jboss.dna.graph.sequencers.SequencerContext;
@@ -160,7 +159,7 @@
         assertThat(sequencerContext.getInputProperties().isEmpty(), is(false));
         assertThat(sequencerContext.getInputProperties().size(), is(3));
         verifyProperty(sequencerContext,
-                       NameFactory.JCR_PRIMARY_TYPE,
+                       "jcr:primaryType",
                        execContext.getValueFactories().getNameFactory().create("{http://www.jcp.org/jcr/nt/1.0}unstructured"));
         verifyProperty(sequencerContext, "x", true);
         verifyProperty(sequencerContext, "y", "asdf", "xyzzy");

Modified: trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/RepositoryClient.java
===================================================================
--- trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/RepositoryClient.java	2008-10-29 15:16:23 UTC (rev 596)
+++ trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/RepositoryClient.java	2008-10-29 17:48:23 UTC (rev 597)
@@ -54,6 +54,7 @@
 import org.jboss.dna.jcr.JcrRepository;
 import org.jboss.dna.repository.RepositoryLibrary;
 import org.jboss.dna.repository.RepositoryService;
+import org.xml.sax.SAXException;
 
 /**
  * @author Randall Hauch
@@ -122,9 +123,10 @@
      * repositories.
      * 
      * @throws IOException if there is a problem initializing the repositories from the files.
+     * @throws SAXException if there is a problem with the SAX Parser
      * @throws NamingException if there is a problem registering or looking up objects in JNDI
      */
-    public void startRepositories() throws IOException, NamingException {
+    public void startRepositories() throws IOException, SAXException, NamingException {
         if (repositoryService != null) return; // already started
 
         // Create the factory for execution contexts.




More information about the dna-commits mailing list