[dna-commits] DNA SVN: r1115 - in trunk: dna-graph/src/main/java/org/jboss/dna/graph/connector/map and 13 other directories.

dna-commits at lists.jboss.org dna-commits at lists.jboss.org
Mon Jul 20 08:18:59 EDT 2009


Author: bcarothers
Date: 2009-07-20 08:18:58 -0400 (Mon, 20 Jul 2009)
New Revision: 1115

Added:
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/DnaIntLexicon.java
   trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/AbstractRepositoryTckTest.java
   trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/JpaRepositoryTckTest.java
   trunk/dna-integration-tests/src/test/resources/tck/jpa/
   trunk/dna-integration-tests/src/test/resources/tck/jpa/configRepository.xml
   trunk/dna-integration-tests/src/test/resources/tck/jpa/repositoryOverlay.properties
Modified:
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/ExecutionContext.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/map/AbstractMapWorkspace.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/WritableConnectorTest.java
   trunk/dna-integration-tests/pom.xml
   trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/InfinispanRepositoryTckTest.java
   trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/JBossCacheRepositoryTckTest.java
   trunk/dna-integration-tests/src/test/resources/log4j.properties
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaIntLexicon.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrContentHandler.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java
   trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/DnaRepositoryStub.java
   trunk/dna-jcr/src/test/resources/repositoryStubImpl.properties
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaSource.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicRequestProcessor.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ChildEntity.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/util/Serializer.java
   trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaConnectorWritingTest.java
   trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaSourceTest.java
Log:
DNA-486 Add integration test that uses the JPA connector

Applied patch that fixes a number of minor issues with the JPA connector, adds additional testing of the move operation for writable connectors, cleans up the TCK integration tests, and adds a TCK integration test for the JPA connector.

Added: trunk/dna-graph/src/main/java/org/jboss/dna/graph/DnaIntLexicon.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/DnaIntLexicon.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/DnaIntLexicon.java	2009-07-20 12:18:58 UTC (rev 1115)
@@ -0,0 +1,36 @@
+/*
+ * 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.graph;
+
+
+/**
+ * A lexicon of internal and implementation-specific information
+ */
+public class DnaIntLexicon {
+
+    public static class Namespace {
+        public static final String URI = "http://www.jboss.org/dna/internal/1.0";
+        public static final String PREFIX = "dnaint";
+    }
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/DnaIntLexicon.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/ExecutionContext.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/ExecutionContext.java	2009-07-17 19:12:26 UTC (rev 1114)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/ExecutionContext.java	2009-07-20 12:18:58 UTC (rev 1115)
@@ -327,6 +327,7 @@
         namespaceRegistry.register(JcrMixLexicon.Namespace.PREFIX, JcrMixLexicon.Namespace.URI);
         namespaceRegistry.register(JcrNtLexicon.Namespace.PREFIX, JcrNtLexicon.Namespace.URI);
         namespaceRegistry.register(DnaLexicon.Namespace.PREFIX, DnaLexicon.Namespace.URI);
+        namespaceRegistry.register(DnaIntLexicon.Namespace.PREFIX, DnaIntLexicon.Namespace.URI);
         // namespaceRegistry.register("dnadtd", "http://www.jboss.org/dna/dtd/1.0");
         // namespaceRegistry.register("dnaxml", "http://www.jboss.org/dna/xml/1.0");
     }

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/map/AbstractMapWorkspace.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/map/AbstractMapWorkspace.java	2009-07-17 19:12:26 UTC (rev 1114)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/map/AbstractMapWorkspace.java	2009-07-20 12:18:58 UTC (rev 1115)
@@ -357,6 +357,13 @@
         assert this.getRoot().equals(node) != true;
         MapNode oldParent = node.getParent();
         Name oldName = node.getName().getName();
+        
+        if (this.equals(newAbstractMapWorkspace) && node.getParent().getUuid().equals(newParent.getUuid())
+            && node.equals(beforeNode)) {
+            // Trivial move of a node to its parent before itself
+            return;
+        }
+        
         if (oldParent != null) {
             boolean removed = oldParent.getChildren().remove(node);
             assert removed == true;

Modified: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/WritableConnectorTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/WritableConnectorTest.java	2009-07-17 19:12:26 UTC (rev 1114)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/WritableConnectorTest.java	2009-07-20 12:18:58 UTC (rev 1115)
@@ -1055,6 +1055,46 @@
     }
 
     @Test
+    public void shouldMoveNodeBeforeSibling() {
+
+        String initialPath = "";
+        int depth = 1;
+        int numChildrenPerNode = 3;
+        int numPropertiesPerNode = 3;
+        Stopwatch sw = new Stopwatch();
+        boolean batch = true;
+        createSubgraph(graph, initialPath, depth, numChildrenPerNode, numPropertiesPerNode, batch, sw, System.out, null);
+
+        // Move last node to front ...
+        graph.move("/node3").before("/node1");
+
+        assertThat(graph.getChildren().of("/"), hasChildren(segment("node3"), segment("node1"), segment("node2")));
+
+        // Move last node to front ...
+        graph.move("/node3").before("/node1");
+
+        assertThat(graph.getChildren().of("/"), hasChildren(segment("node2"), segment("node3"), segment("node1")));
+
+    }
+
+    @Test
+    public void shouldMoveNodeBeforeSelf() {
+
+        String initialPath = "";
+        int depth = 1;
+        int numChildrenPerNode = 3;
+        int numPropertiesPerNode = 3;
+        Stopwatch sw = new Stopwatch();
+        boolean batch = true;
+        createSubgraph(graph, initialPath, depth, numChildrenPerNode, numPropertiesPerNode, batch, sw, System.out, null);
+
+        // Move node before itself (trivial change) ...
+        graph.move("/node2").before("/node2");
+
+        assertThat(graph.getChildren().of("/"), hasChildren(segment("node1"), segment("node2"), segment("node3")));
+    }    
+
+    @Test
     public void shouldMoveNodes() {
         // Create the tree (at total of 40 nodes, plus the extra 6 added later)...
         // /

Modified: trunk/dna-integration-tests/pom.xml
===================================================================
--- trunk/dna-integration-tests/pom.xml	2009-07-17 19:12:26 UTC (rev 1114)
+++ trunk/dna-integration-tests/pom.xml	2009-07-20 12:18:58 UTC (rev 1115)
@@ -75,12 +75,34 @@
 			<version>${pom.version}</version>
 			<scope>test</scope>
 		</dependency>
+
+		<!-- 
+          JPA Connector Dependencies
+          -->
 		<dependency>
 			<groupId>org.jboss.dna</groupId>
 			<artifactId>dna-connector-store-jpa</artifactId>
 			<version>${pom.version}</version>
 			<scope>test</scope>
 		</dependency>
+		<dependency>
+			<groupId>org.hibernate</groupId>
+			<artifactId>hibernate-entitymanager</artifactId>
+			<version>3.4.0.GA</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.hibernate</groupId>
+			<artifactId>hibernate-c3p0</artifactId>
+			<version>3.3.1.GA</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>hsqldb</groupId>
+			<artifactId>hsqldb</artifactId>
+			<version>1.8.0.2</version>
+			<scope>test</scope>
+		</dependency>
 
 		<!--
 			Logging (require SLF4J API for compiling, but use Log4J and its SLF4J

Added: trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/AbstractRepositoryTckTest.java
===================================================================
--- trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/AbstractRepositoryTckTest.java	                        (rev 0)
+++ trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/AbstractRepositoryTckTest.java	2009-07-20 12:18:58 UTC (rev 1115)
@@ -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. 
+ *
+ * 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.test.integration;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.jboss.dna.jcr.DnaRepositoryStub;
+import org.jboss.dna.jcr.DnaTckTest;
+import org.jboss.dna.jcr.JcrTckTest;
+
+/**
+ * Container for the standard integration test suites that should be run against various read-only and read-write repository
+ * configurations.
+ * <p>
+ * The tests require the repository implementation for the TCK tests to change between runs. This is accomplished by adding a
+ * {@link ChangeRepositoryTestCase trivial test} to the beginning of the suite that
+ * {@link DnaRepositoryStub#setCurrentConfigurationName(String) changes the repository configuration} in the
+ * {@link DnaRepositoryStub}.
+ * </p>
+ */
+public abstract class AbstractRepositoryTckTest {
+
+    public static TestSuite readWriteRepositorySuite( final String name ) {
+        TestSuite suite = new TestSuite("Tests for " + name + "(read-write)");
+        suite.addTest(new ChangeRepositoryTestCase(name));
+        suite.addTest(JcrTckTest.suite());
+        suite.addTestSuite(DnaTckTest.class);
+
+        return suite;
+    }
+
+    public static TestSuite readOnlyRepositorySuite( String name ) {
+        TestSuite suite = new TestSuite("Tests for " + name + "(read-only)");
+        suite.addTest(new ChangeRepositoryTestCase(name));
+        suite.addTest(JcrTckTest.suite());
+        suite.addTestSuite(DnaTckTest.class);
+
+        return suite;
+    }
+
+    /**
+     * Trivial test case that invokes {@link DnaRepositoryStub#setCurrentConfigurationName(String)} to change the currently used
+     * TCK configuration. If this test fails, that is an indication that the configuration is incorrect or that the {@code name}
+     * parameter does not match a valid configuration name.
+     */
+    public static class ChangeRepositoryTestCase extends TestCase {
+        private final String configurationName;
+
+        public ChangeRepositoryTestCase( final String configurationName ) {
+            super("testConfigurationNameChange");
+
+            this.configurationName = configurationName;
+        }
+
+        public void testConfigurationNameChange() {
+            DnaRepositoryStub.setCurrentConfigurationName(configurationName);
+        }
+    }
+}


Property changes on: trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/AbstractRepositoryTckTest.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Modified: trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/InfinispanRepositoryTckTest.java
===================================================================
--- trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/InfinispanRepositoryTckTest.java	2009-07-17 19:12:26 UTC (rev 1114)
+++ trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/InfinispanRepositoryTckTest.java	2009-07-20 12:18:58 UTC (rev 1115)
@@ -24,21 +24,9 @@
 package org.jboss.dna.test.integration;
 
 import junit.framework.Test;
-import junit.framework.TestSuite;
-import org.jboss.dna.jcr.DnaRepositoryStub;
-import org.jboss.dna.jcr.DnaTckTest;
-import org.jboss.dna.jcr.JcrTckTest;
 
-public class InfinispanRepositoryTckTest extends JcrTckTest {
-
-    private static final String NAME = "infinispan";
-
+public class InfinispanRepositoryTckTest {
     public static Test suite() {
-        DnaRepositoryStub.setCurrentConfigurationName(NAME);
-        TestSuite suite = new TestSuite("TCK Tests for " + NAME);
-        suite.addTest(JcrTckTest.suite());
-        suite.addTestSuite(DnaTckTest.class);
-
-        return suite;
+        return AbstractRepositoryTckTest.readWriteRepositorySuite("infinispan");
     }
 }

Modified: trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/JBossCacheRepositoryTckTest.java
===================================================================
--- trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/JBossCacheRepositoryTckTest.java	2009-07-17 19:12:26 UTC (rev 1114)
+++ trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/JBossCacheRepositoryTckTest.java	2009-07-20 12:18:58 UTC (rev 1115)
@@ -24,21 +24,10 @@
 package org.jboss.dna.test.integration;
 
 import junit.framework.Test;
-import junit.framework.TestSuite;
-import org.jboss.dna.jcr.DnaRepositoryStub;
-import org.jboss.dna.jcr.DnaTckTest;
-import org.jboss.dna.jcr.JcrTckTest;
 
-public class JBossCacheRepositoryTckTest extends JcrTckTest {
+public class JBossCacheRepositoryTckTest {
 
-    private static final String NAME = "jbosscache";
-    
     public static Test suite() {
-        DnaRepositoryStub.setCurrentConfigurationName(NAME);
-        TestSuite suite = new TestSuite("TCK Tests for " + NAME);
-        suite.addTest(JcrTckTest.suite());
-        suite.addTestSuite(DnaTckTest.class);
-        
-        return suite;
+        return AbstractRepositoryTckTest.readWriteRepositorySuite("jbosscache");
     }
 }

Added: trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/JpaRepositoryTckTest.java
===================================================================
--- trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/JpaRepositoryTckTest.java	                        (rev 0)
+++ trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/JpaRepositoryTckTest.java	2009-07-20 12:18:58 UTC (rev 1115)
@@ -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.
+ */
+package org.jboss.dna.test.integration;
+
+import junit.framework.Test;
+
+public class JpaRepositoryTckTest {
+
+    public static Test suite() {
+        return AbstractRepositoryTckTest.readWriteRepositorySuite("jpa");
+    }
+}


Property changes on: trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/JpaRepositoryTckTest.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Modified: trunk/dna-integration-tests/src/test/resources/log4j.properties
===================================================================
--- trunk/dna-integration-tests/src/test/resources/log4j.properties	2009-07-17 19:12:26 UTC (rev 1114)
+++ trunk/dna-integration-tests/src/test/resources/log4j.properties	2009-07-20 12:18:58 UTC (rev 1115)
@@ -9,8 +9,11 @@
 
 # Set up the default logging to be INFO level, then override specific units
 log4j.logger.org.jboss.dna=INFO
-log4j.logger.org.jboss.dna.tests.integration.jackrabbit.JackrabbitMySqlStressTest=DEBUG
+log4j.logger.org.junit=DEBUG
+# log4j.logger.org.jboss.dna.tests.integration.jackrabbit.JackrabbitMySqlStressTest=DEBUG
+log4j.logger.org.hibernate=WARN, stdout
 
+
 # Jackrabbit logging
 log4j.logger.org.apache.jackrabbit=WARN, stdout
 log4j.logger.org.apache.derby=INFO, stdout

Added: trunk/dna-integration-tests/src/test/resources/tck/jpa/configRepository.xml
===================================================================
--- trunk/dna-integration-tests/src/test/resources/tck/jpa/configRepository.xml	                        (rev 0)
+++ trunk/dna-integration-tests/src/test/resources/tck/jpa/configRepository.xml	2009-07-20 12:18:58 UTC (rev 1115)
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  ~ 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 distribution; if not, write to:
+  ~ Free Software Foundation, Inc.
+  ~ 51 Franklin Street, Fifth Floor
+  ~ Boston, MA  02110-1301  USA
+  -->
+<configuration xmlns:dna="http://www.jboss.org/dna/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0">
+    <!-- 
+    Define the sources for the content.  These sources are directly accessible using the DNA-specific Graph API.
+    In fact, this is how the DNA JCR implementation works.  You can think of these as being similar to
+    JDBC DataSource objects, except that they expose graph content via the Graph API instead of records via SQL or JDBC. 
+    -->
+    <dna:sources jcr:primaryType="nt:unstructured">
+        <!-- 
+        The 'JCR' repository is a JBoss Cache source with a single default workspace (though others could be created, too).
+        -->
+        <dna:source jcr:name="Store" dna:classname="org.jboss.dna.connector.store.jpa.JpaSource"
+        	dna:dialect="org.hibernate.dialect.HSQLDialect"
+        	dna:driverClassName="org.hsqldb.jdbcDriver"
+        	dna:username="sa"
+        	dna:password=""
+        	dna:url="jdbc:hsqldb:."
+        	dna:maximumConnectionsInPool="1"
+        	dna:referentialIntegrityEnforced="true"
+        	dna:largeValueSizeInBytes="150"
+        	dna:retryLimit="3" 
+        	dna:compressData="true"
+        	dna:predefinedWorkspaceNames="default"
+        	dna:showSql="false"
+        	dna:defaultWorkspaceName="default"/>    
+    </dna:sources>
+    <!-- 
+    Define the mime type detectors. This is an optional section.  By default, each engine will use the 
+    MIME type detector that uses filename extensions.  So we wouldn't need to define the same detector again,
+    but this is how you'd define another extension.
+    -->
+    <dna:mimeTypeDetectors>
+        <dna:mimeTypeDetector jcr:name="Detector">
+            <dna:description>Standard extension-based MIME type detector</dna:description>        
+            <!-- 
+            Specify the implementation class (required), as a child element or attribute on parent element.
+            -->
+            <dna:classname>org.jboss.dna.graph.mimetype.ExtensionBasedMimeTypeDetector</dna:classname>
+            <!-- 
+            Specify the classpath (optional) as an ordered list of 'names', where each name is significant to 
+            the classpath factory.  For example, a name could be an OSGI identifier or a Maven coordinate,
+            depending upon the classpath factory being used.  If there is only one 'name' in the classpath,
+            it may be specified as an attribute on the 'mimeTypeDetector' element.  If there is more than one
+            'name', then they must be specified as child 'classpath' elements. Blank or empty values are ignored. 
+             -->
+            <dna:classpath></dna:classpath>
+        </dna:mimeTypeDetector>
+    </dna:mimeTypeDetectors>
+    <!-- 
+    Define the JCR repositories 
+    -->
+    <dna:repositories>
+        <!-- 
+        Define a JCR repository that accesses the 'JCR' source directly.
+        This of course is optional, since we could access the same content through 'JCR'.
+        -->
+        <dna:repository jcr:name="Test Repository Source">
+            <!-- Specify the source that should be used for the repository -->
+            <dna:source>Store</dna:source>
+            <!-- Define the options for the JCR repository, using camelcase version of JcrRepository.Option names
+-->
+            <dna:options jcr:primaryType="dna:options">
+                <jaasLoginConfigName jcr:primaryType="dna:option" dna:value="dna-jcr"/>
+                <projectNodeTypes jcr:primaryType="dna:option" dna:value="false"/>
+            </dna:options>
+            <!-- Define any namespaces for this repository, other than those already defined by JCR or DNA
+-->
+            <namespaces jcr:primaryType="dna:namespaces">
+                <dnatest jcr:primaryType="dna:namespace" dna:uri="http://jboss.org/dna/test/1.0"/>
+            </namespaces>
+        </dna:repository>
+    </dna:repositories>
+</configuration>


Property changes on: trunk/dna-integration-tests/src/test/resources/tck/jpa/configRepository.xml
___________________________________________________________________
Name: svn:keywords
   + Id Revision

Added: trunk/dna-integration-tests/src/test/resources/tck/jpa/repositoryOverlay.properties
===================================================================
--- trunk/dna-integration-tests/src/test/resources/tck/jpa/repositoryOverlay.properties	                        (rev 0)
+++ trunk/dna-integration-tests/src/test/resources/tck/jpa/repositoryOverlay.properties	2009-07-20 12:18:58 UTC (rev 1115)
@@ -0,0 +1 @@
+# Placeholder for any overlaid properties for this repo configuration

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaIntLexicon.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaIntLexicon.java	2009-07-17 19:12:26 UTC (rev 1114)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaIntLexicon.java	2009-07-20 12:18:58 UTC (rev 1115)
@@ -29,13 +29,7 @@
 /**
  * A lexicon of internal and implementation-specific information
  */
-public class DnaIntLexicon {
-
-    public static class Namespace {
-        public static final String URI = "http://www.jboss.org/dna/internal/1.0";
-        public static final String PREFIX = "dnaint";
-    }
-
+public class DnaIntLexicon extends org.jboss.dna.graph.DnaIntLexicon {
     public static final Name NODE_DEFINITON = new BasicName(Namespace.URI, "nodeDefinition");
     public static final Name MULTI_VALUED_PROPERTIES = new BasicName(Namespace.URI, "multiValuedProperties");
 }

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrContentHandler.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrContentHandler.java	2009-07-17 19:12:26 UTC (rev 1114)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrContentHandler.java	2009-07-20 12:18:58 UTC (rev 1115)
@@ -282,7 +282,7 @@
     }
 
     private class SystemViewContentHandler extends DefaultHandler {
-        private Stack<AbstractJcrNode> parentStack;
+        private final Stack<AbstractJcrNode> parentStack;
 
         private final String svNameName;
         private final String svTypeName;
@@ -292,7 +292,7 @@
         private int currentPropType;
 
         private StringBuffer valueBuffer;
-        private Map<String, List<Value>> currentProps;
+        private final Map<String, List<Value>> currentProps;
 
         /**
          * @param currentNode
@@ -346,6 +346,31 @@
                     if (rawUuid != null) {
                         assert rawUuid.size() == 1;
                         uuid = UUID.fromString(rawUuid.get(0).getString());
+                        
+                        try {
+                            // Deal with any existing node ...
+                            AbstractJcrNode existingNodeWithUuid = cache().findJcrNode(Location.create(uuid));
+                            switch (uuidBehavior) {
+                                case ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING:
+                                    parentNode = existingNodeWithUuid.getParent();
+                                    existingNodeWithUuid.remove();
+                                    break;
+                                case ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW:
+                                    uuid = UUID.randomUUID();
+                                    break;
+                                case ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING:
+                                    if (existingNodeWithUuid.path().isAtOrAbove(parentStack.firstElement().path())) {
+                                        throw new ConstraintViolationException();
+                                    }
+                                    existingNodeWithUuid.remove();
+                                    break;
+                                case ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW:
+                                    throw new ItemExistsException();
+                            }
+                        } catch (ItemNotFoundException e) {
+                            // there wasn't an existing item, so just continue
+                        }
+                        
                     }
 
                     String typeName = currentProps.get(primaryTypeName).get(0).getString();
@@ -427,7 +452,7 @@
     }
 
     private class DocumentViewContentHandler extends DefaultHandler {
-        private Stack<AbstractJcrNode> parentStack;
+        private final Stack<AbstractJcrNode> parentStack;
 
         /**
          * @param currentNode

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java	2009-07-17 19:12:26 UTC (rev 1114)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java	2009-07-20 12:18:58 UTC (rev 1115)
@@ -442,6 +442,11 @@
         }
     }
 
+    @Override
+    public String toString() {
+        return (value == null ? "null" : value.toString()) + " (" + PropertyType.nameFromValue(type) + ")";
+    }
+    
     private enum State {
         NEVER_CONSUMED,
         INPUT_STREAM_CONSUMED,

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java	2009-07-17 19:12:26 UTC (rev 1114)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java	2009-07-20 12:18:58 UTC (rev 1115)
@@ -139,7 +139,7 @@
     protected final Path rootPath;
     protected final Name residualName;
 
-    private GraphSession<JcrNodePayload, JcrPropertyPayload> graphSession;
+    private final GraphSession<JcrNodePayload, JcrPropertyPayload> graphSession;
 
     public SessionCache( JcrSession session ) {
         this(session, session.workspace().getName(), session.getExecutionContext(), session.nodeTypeManager(), session.graph());
@@ -1320,6 +1320,7 @@
                 if (JcrMixLexicon.REFERENCEABLE.equals(mixinCandidateType.getInternalName())) {
                     // This node is now referenceable, so make sure there is a UUID property ...
                     UUID uuid = node.getLocation().getUuid();
+                    if (uuid == null) uuid = (UUID)node.getLocation().getIdProperty(JcrLexicon.UUID).getFirstValue();
                     if (uuid == null) uuid = UUID.randomUUID();
                     JcrValue value = new JcrValue(factories(), SessionCache.this, PropertyType.STRING, uuid);
                     setProperty(JcrLexicon.UUID, value, false);

Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/DnaRepositoryStub.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/DnaRepositoryStub.java	2009-07-17 19:12:26 UTC (rev 1114)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/DnaRepositoryStub.java	2009-07-20 12:18:58 UTC (rev 1115)
@@ -43,8 +43,10 @@
 
     private static String currentConfigurationName = "default";
 
-    private final Properties configProps;
-    private final JcrRepository repository;
+    private Properties configProps;
+    private String repositoryConfigurationName;
+    private JcrRepository repository;
+    
 
     static {
 
@@ -62,15 +64,21 @@
     public DnaRepositoryStub( Properties env ) {
         super(env);
 
+        configureRepository();
+    }
+
+    private void configureRepository() {
+        repositoryConfigurationName = currentConfigurationName;
+        
         // Create the in-memory (DNA) repository
         JcrConfiguration configuration = new JcrConfiguration();
         try {
             configProps = new Properties();
-            String propsFileName = "/tck/" + currentConfigurationName + "/repositoryOverlay.properties";
+            String propsFileName = "/tck/" + repositoryConfigurationName + "/repositoryOverlay.properties";
             InputStream propsStream = getClass().getResourceAsStream(propsFileName);
             configProps.load(propsStream);
 
-            String configFileName = "/tck/" + currentConfigurationName + "/configRepository.xml";
+            String configFileName = "/tck/" + repositoryConfigurationName + "/configRepository.xml";
             configuration.loadFrom(getClass().getResourceAsStream(configFileName));
 
             // Add the the node types for the source ...
@@ -86,8 +94,8 @@
         JcrEngine engine = configuration.build();
         engine.start();
 
-        // Problems problems = engine.getRepositoryService().getStartupProblems();
-        Problems problems = engine.getProblems();
+        Problems problems = engine.getRepositoryService().getStartupProblems();
+        // Problems problems = engine.getProblems();
         // Print all of the problems from the engine configuration ...
         for (Problem problem : problems) {
             System.err.println(problem);
@@ -96,17 +104,11 @@
             throw new IllegalStateException("Problems starting JCR repository");
         }
 
-        repository = getAndLoadRepository(engine, REPOSITORY_SOURCE_NAME);
-    }
-
-    private JcrRepository getAndLoadRepository( JcrEngine engine,
-                                                String repositoryName ) {
-
         ExecutionContext executionContext = engine.getExecutionContext();
         executionContext.getNamespaceRegistry().register(TestLexicon.Namespace.PREFIX, TestLexicon.Namespace.URI);
 
         try {
-            JcrRepository repository = engine.getRepository(REPOSITORY_SOURCE_NAME);
+            repository = engine.getRepository(REPOSITORY_SOURCE_NAME);
 
             // Set up some sample nodes in the graph to match the expected test configuration
             Graph graph = Graph.create(repository.getRepositorySourceName(),
@@ -118,7 +120,6 @@
             graph.importXmlFrom(xmlStream).into(destinationPath);
 
             graph.createWorkspace().named("otherWorkspace");
-            return repository;
 
         } catch (Exception ex) {
             // The TCK tries to quash this exception. Print it out to be more obvious.
@@ -126,6 +127,7 @@
             throw new IllegalStateException("Failed to initialize the repository with text content.", ex);
         }
 
+
     }
 
     public static void setCurrentConfigurationName( String newConfigName ) {
@@ -139,6 +141,9 @@
      */
     @Override
     public JcrRepository getRepository() {
+        if (!currentConfigurationName.equals(repositoryConfigurationName)) {
+            configureRepository();
+        }
         return repository;
     }
 

Modified: trunk/dna-jcr/src/test/resources/repositoryStubImpl.properties
===================================================================
--- trunk/dna-jcr/src/test/resources/repositoryStubImpl.properties	2009-07-17 19:12:26 UTC (rev 1114)
+++ trunk/dna-jcr/src/test/resources/repositoryStubImpl.properties	2009-07-20 12:18:58 UTC (rev 1115)
@@ -14,7 +14,8 @@
 javax.jcr.tck.targetFolderName=target
 javax.jcr.tck.rootNodeName=rootNode
 javax.jcr.tck.propertySkipped=propertySkipped
-javax.jcr.tck.propertyValueMayChange=propertyValueMayChange
+# The spaces on either side of this property are important - DO NOT DELETE THEM
+javax.jcr.tck.propertyValueMayChange= jcr:uuid 
 javax.jcr.tck.nodeTypesTestNode=nodeTypesTestNode
 javax.jcr.tck.mixinTypeTestNode=mixinTypeTestNode
 javax.jcr.tck.propertyTypesTestNode=propertyTypesTestNode

Modified: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaSource.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaSource.java	2009-07-17 19:12:26 UTC (rev 1114)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaSource.java	2009-07-20 12:18:58 UTC (rev 1115)
@@ -142,6 +142,10 @@
      */
     public static final boolean DEFAULT_SUPPORTS_UPDATES = true;
     /**
+     * This source does not output executed SQL by default, but this can be overridden by calling {@link #setShowSql(boolean)}.
+     */
+    public static final boolean DEFAULT_SHOW_SQL = false;
+    /**
      * This source does support creating workspaces.
      */
     public static final boolean DEFAULT_SUPPORTS_CREATING_WORKSPACES = true;
@@ -152,7 +156,7 @@
     public static final String DEFAULT_ROOT_NODE_UUID = "1497b6fe-8c7e-4bbb-aaa2-24f3d4942668";
 
     /**
-     * The initial {@link #getNameOfDefaultWorkspace() name of the default workspace} is "{@value} ", unless otherwise specified.
+     * The initial {@link #getDefaultWorkspaceName() name of the default workspace} is "{@value} ", unless otherwise specified.
      */
     public static final String DEFAULT_NAME_OF_DEFAULT_WORKSPACE = "default";
 
@@ -192,6 +196,7 @@
     private volatile int retryLimit = DEFAULT_RETRY_LIMIT;
     private volatile int cacheTimeToLiveInMilliseconds = DEFAULT_CACHE_TIME_TO_LIVE_IN_SECONDS * 1000;
     private volatile long largeValueSizeInBytes = DEFAULT_LARGE_VALUE_SIZE_IN_BYTES;
+    private volatile boolean showSql = DEFAULT_SHOW_SQL;
     private volatile boolean compressData = DEFAULT_COMPRESS_DATA;
     private volatile boolean referentialIntegrityEnforced = DEFAULT_ENFORCE_REFERENTIAL_INTEGRITY;
     private volatile String defaultWorkspace = DEFAULT_NAME_OF_DEFAULT_WORKSPACE;
@@ -263,6 +268,24 @@
     }
 
     /**
+     * Get whether this source outputs the SQL that it executes
+     * 
+     * @return whether this source outputs the SQL that it executes
+     */
+    public boolean getShowSql() {
+        return this.showSql;
+    }
+
+    /**
+     * Sets whether this source should output the SQL that it executes
+     * 
+     * @param showSql true if this source should output the SQL that it executes, otherwise false
+     */
+    public synchronized void setShowSql( boolean showSql ) {
+        this.showSql = showSql;
+    }
+
+    /**
      * {@inheritDoc}
      * 
      * @see org.jboss.dna.graph.connector.RepositorySource#getRetryLimit()
@@ -324,7 +347,7 @@
      * 
      * @return the name of the workspace that should be used by default, or null if there is no default workspace
      */
-    public String getNameOfDefaultWorkspace() {
+    public String getDefaultWorkspaceName() {
         return defaultWorkspace;
     }
 
@@ -334,7 +357,7 @@
      * @param nameOfDefaultWorkspace the name of the workspace that should be used by default, or null if the
      *        {@link #DEFAULT_NAME_OF_DEFAULT_WORKSPACE default name} should be used
      */
-    public synchronized void setNameOfDefaultWorkspace( String nameOfDefaultWorkspace ) {
+    public synchronized void setDefaultWorkspaceName( String nameOfDefaultWorkspace ) {
         this.defaultWorkspace = nameOfDefaultWorkspace != null ? nameOfDefaultWorkspace : DEFAULT_NAME_OF_DEFAULT_WORKSPACE;
     }
 
@@ -733,7 +756,7 @@
         ref.add(new StringRefAddr(LARGE_VALUE_SIZE_IN_BYTES, Long.toString(getLargeValueSizeInBytes())));
         ref.add(new StringRefAddr(COMPRESS_DATA, Boolean.toString(isCompressData())));
         ref.add(new StringRefAddr(ENFORCE_REFERENTIAL_INTEGRITY, Boolean.toString(isReferentialIntegrityEnforced())));
-        ref.add(new StringRefAddr(DEFAULT_WORKSPACE, getNameOfDefaultWorkspace()));
+        ref.add(new StringRefAddr(DEFAULT_WORKSPACE, getDefaultWorkspaceName()));
         ref.add(new StringRefAddr(ALLOW_CREATING_WORKSPACES, Boolean.toString(isCreatingWorkspacesAllowed())));
         String[] workspaceNames = getPredefinedWorkspaceNames();
         if (workspaceNames != null && workspaceNames.length != 0) {
@@ -819,7 +842,7 @@
             if (largeModelSize != null) source.setLargeValueSizeInBytes(Long.parseLong(largeModelSize));
             if (compressData != null) source.setCompressData(Boolean.parseBoolean(compressData));
             if (refIntegrity != null) source.setReferentialIntegrityEnforced(Boolean.parseBoolean(refIntegrity));
-            if (defaultWorkspace != null) source.setNameOfDefaultWorkspace(defaultWorkspace);
+            if (defaultWorkspace != null) source.setDefaultWorkspaceName(defaultWorkspace);
             if (createWorkspaces != null) source.setCreatingWorkspacesAllowed(Boolean.parseBoolean(createWorkspaces));
             if (workspaceNames != null && workspaceNames.length != 0) source.setPredefinedWorkspaceNames(workspaceNames);
             return source;
@@ -886,7 +909,7 @@
                 setProperty(configurator, "hibernate.connection.url", this.url);
                 setProperty(configurator, "hibernate.connection.max_fetch_depth", DEFAULT_MAXIMUM_FETCH_DEPTH);
                 setProperty(configurator, "hibernate.connection.pool_size", 0); // don't use the built-in pool
-                setProperty(configurator, "hibernate.show_sql", "false");
+                setProperty(configurator, "hibernate.show_sql", String.valueOf(this.showSql));
             }
 
             entityManagerFactory = configurator.buildEntityManagerFactory();

Modified: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicRequestProcessor.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicRequestProcessor.java	2009-07-17 19:12:26 UTC (rev 1114)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicRequestProcessor.java	2009-07-20 12:18:58 UTC (rev 1115)
@@ -76,6 +76,7 @@
 import org.jboss.dna.graph.property.PathFactory;
 import org.jboss.dna.graph.property.PathNotFoundException;
 import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.PropertyFactory;
 import org.jboss.dna.graph.property.PropertyType;
 import org.jboss.dna.graph.property.Reference;
 import org.jboss.dna.graph.property.ReferentialIntegrityException;
@@ -116,6 +117,7 @@
     protected final EntityManager entities;
     protected final ValueFactory<String> stringFactory;
     protected final PathFactory pathFactory;
+    protected final PropertyFactory propertyFactory;
     protected final NameFactory nameFactory;
     protected final UuidFactory uuidFactory;
     protected final Namespaces namespaces;
@@ -138,7 +140,7 @@
         REPLACE_EXISTING_NODE,
         THROW_EXCEPTION
     }
-    
+
     /**
      * @param sourceName
      * @param context
@@ -171,6 +173,7 @@
         ValueFactories valuesFactory = context.getValueFactories();
         this.stringFactory = valuesFactory.getStringFactory();
         this.pathFactory = valuesFactory.getPathFactory();
+        this.propertyFactory = context.getPropertyFactory();
         this.nameFactory = valuesFactory.getNameFactory();
         this.uuidFactory = valuesFactory.getUuidFactory();
         this.namespaces = new Namespaces(entityManager);
@@ -460,7 +463,9 @@
             actualLocation = actual.location;
 
             // Record the UUID as a property, since it's not stored in the serialized properties...
-            request.addProperty(actualLocation.getIdProperty(DnaLexicon.UUID));
+            // This gets pulled from the actual location uuid instead of the property to avoid the
+            // having to add the dna:uuid onto locations that already have a jcr:uuid
+            request.addProperty(propertyFactory.create(DnaLexicon.UUID, UUID.fromString(parentUuidString)));
 
             // Find the properties entity for this node ...
             Query query = entities.createNamedQuery("PropertiesEntity.findByUuid");
@@ -828,7 +833,7 @@
 
             // Small optimization ...
             final Name propertyName = request.named();
-            if (DnaLexicon.UUID.equals(propertyName)) {
+            if (DnaLexicon.UUID.equals(propertyName) || JcrLexicon.UUID.equals(propertyName)) {
                 try {
                     // Just get the UUID ...
                     Location location = request.on();
@@ -918,8 +923,16 @@
                 boolean compressed = entity.isCompressed();
                 byte[] originalData = entity.getData();
                 ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                OutputStream os = compressed ? new GZIPOutputStream(baos) : baos;
-                ObjectOutputStream oos = new ObjectOutputStream(os);
+                ObjectOutputStream oos;
+                GZIPOutputStream gos = null;
+                if (compressed) {
+                    gos = new GZIPOutputStream(baos);
+                    oos = new ObjectOutputStream(gos);
+                } else {
+                    oos = new ObjectOutputStream(baos);
+                }
+                // OutputStream os = compressed ? new GZIPOutputStream(baos) : baos;
+                // oos = new ObjectOutputStream(os);
                 int numProps = 0;
                 LargeValueSerializer largeValues = null;
                 Map<Name, Property> props = request.properties();
@@ -928,6 +941,7 @@
                     largeValues = new LargeValueSerializer(entity);
                     numProps = props.size();
                     serializer.serializeProperties(oos, numProps, props.values(), largeValues, refs);
+                    if (gos != null) gos.finish();
                 } else {
                     boolean hadLargeValues = !entity.getLargeValues().isEmpty();
                     Set<String> largeValueHashesWritten = hadLargeValues ? new HashSet<String>() : null;
@@ -939,6 +953,7 @@
                     try {
                         Serializer.ReferenceValues refValues = refs != null ? refs : Serializer.NO_REFERENCES_VALUES;
                         numProps = serializer.reserializeProperties(ois, oos, props, largeValues, removedValues, refValues);
+                        if (gos != null) gos.finish();
                     } finally {
                         try {
                             ois.close();
@@ -946,6 +961,7 @@
                             oos.close();
                         }
                     }
+                    
                     // The new large values were recorded and associated with the properties entity during reserialization.
                     // However, any values no longer used now need to be removed ...
                     if (hadLargeValues) {
@@ -1806,12 +1822,232 @@
         }
     }
 
+    private Location moveNodeToLastChild( WorkspaceEntity workspace,
+                                          ActualLocation actualFromLocation,
+                                          ActualLocation actualIntoLocation,
+                                          Name desiredName ) {
+        long workspaceId = workspace.getId();
+        Path oldPath = actualFromLocation.location.getPath();
+
+        ChildEntity fromEntity = actualFromLocation.childEntity;
+
+        // Now we know that the new parent is not the existing parent ...
+        final int oldIndex = fromEntity.getIndexInParent();
+        final String oldParentUuid = fromEntity.getParentUuidString();
+
+        String toUuidString = actualIntoLocation.uuid;
+
+        // Make sure the child name is set correctly ...
+        String childOldLocalName = fromEntity.getChildName();
+        String childLocalName = null;
+        NamespaceEntity ns = null;
+        Name childName = desiredName;
+        if (childName != null) {
+            childLocalName = desiredName.getLocalName();
+            String childNsUri = childName.getNamespaceUri();
+            ns = namespaces.get(childNsUri, true);
+        } else {
+            childName = oldPath.getLastSegment().getName();
+            childLocalName = fromEntity.getChildName();
+            ns = fromEntity.getChildNamespace();
+        }
+
+        int nextSnsIndex = 1;
+        int nextIndexInParent = 1;
+
+        // Find the largest SNS index in the existing ChildEntity objects with the same name ...
+        Query query = entities.createNamedQuery("ChildEntity.findMaximumSnsIndex");
+        query.setParameter("workspaceId", workspaceId);
+        query.setParameter("parentUuid", toUuidString);
+        query.setParameter("ns", ns.getId());
+        query.setParameter("childName", childLocalName);
+        try {
+            Integer index = (Integer)query.getSingleResult();
+            if (index != null) nextSnsIndex = index.intValue() + 1;
+        } catch (NoResultException e) {
+        }
+
+        // Find the largest child index in the existing ChildEntity objects ...
+        query = entities.createNamedQuery("ChildEntity.findMaximumChildIndex");
+        query.setParameter("workspaceId", workspaceId);
+        query.setParameter("parentUuid", toUuidString);
+        try {
+            Integer index = (Integer)query.getSingleResult();
+            if (index != null) nextIndexInParent = index + 1;
+        } catch (NoResultException e) {
+        }
+
+        fromEntity.setParentUuidString(toUuidString);
+        fromEntity.setChildName(childLocalName);
+        fromEntity.setChildNamespace(ns);
+        fromEntity.setIndexInParent(nextIndexInParent);
+        fromEntity.setSameNameSiblingIndex(nextSnsIndex);
+
+        // Flush the entities to the database ...
+        entities.flush();
+
+        // Determine the new location ...
+        Path newParentPath = actualIntoLocation.location.getPath();
+        Path newPath = pathFactory.create(newParentPath, childName, nextSnsIndex);
+        Location newLocation = actualFromLocation.location.with(newPath);
+
+        // And adjust the SNS index and indexes ...
+        ChildEntity.adjustSnsIndexesAndIndexesAfterRemoving(entities,
+                                                            workspaceId,
+                                                            oldParentUuid,
+                                                            childOldLocalName,
+                                                            ns.getId(),
+                                                            oldIndex);
+
+        // Update the cache ...
+        cache.moveNode(workspaceId, actualFromLocation.location, oldIndex, newLocation);
+
+        return newLocation;
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private Location moveNodeBefore( WorkspaceEntity workspace,
+                                     ActualLocation actualFromLocation,
+                                     ActualLocation actualIntoLocation,
+                                     ActualLocation actualBeforeLocation ) {
+
+        long workspaceId = workspace.getId();
+
+        ChildEntity fromEntity = actualFromLocation.childEntity;
+        assert fromEntity != null;
+
+        Path oldPath = actualFromLocation.location.getPath();
+        String oldParentUuid = fromEntity.getParentUuidString();
+
+        String toUuidString = actualIntoLocation.uuid;
+        Location beforeLocation = actualBeforeLocation.location;
+        ChildEntity beforeEntity = actualBeforeLocation.childEntity;
+
+        /*
+         * getActualLocation (which populates actualBeforeLocation) can return null for the childEntity
+         * if the location was retrieved from the cache.  Since we need the beforeEntity, try to force the load.
+         */
+        if (beforeEntity == null) {
+            beforeEntity = findNode(workspaceId, actualBeforeLocation.uuid);
+        }
+
+        assert beforeEntity != null;
+        
+        Name childName = oldPath.getLastSegment().getName();
+        String childLocalName = fromEntity.getChildName();
+        NamespaceEntity ns = fromEntity.getChildNamespace();
+
+        boolean sameParent = oldParentUuid.equals(toUuidString);
+
+        if (sameParent) {
+            int oldIndex;
+            if (fromEntity.getIndexInParent() < beforeEntity.getIndexInParent()) {
+                oldIndex = beforeEntity.getIndexInParent();
+
+                int snsCount = ChildEntity.adjustSnsIndexesAndIndexes(entities,
+                                                                      workspaceId,
+                                                                      fromEntity.getParentUuidString(),
+                                                                      fromEntity.getIndexInParent(),
+                                                                      beforeEntity.getIndexInParent(),
+                                                                      fromEntity.getChildNamespace().getId(),
+                                                                      fromEntity.getChildName(),
+                                                                      -1);
+
+                fromEntity.setIndexInParent(oldIndex);
+                fromEntity.setSameNameSiblingIndex(fromEntity.getSameNameSiblingIndex() + snsCount);
+            } else {
+                oldIndex = beforeEntity.getIndexInParent();
+
+                int snsCount = ChildEntity.adjustSnsIndexesAndIndexes(entities,
+                                                                      workspaceId,
+                                                                      fromEntity.getParentUuidString(),
+                                                                      beforeEntity.getIndexInParent() - 1,
+                                                                      fromEntity.getIndexInParent() - 1,
+                                                                      fromEntity.getChildNamespace().getId(),
+                                                                      fromEntity.getChildName(),
+                                                                      +1);
+
+                fromEntity.setIndexInParent(oldIndex);
+                fromEntity.setSameNameSiblingIndex(fromEntity.getSameNameSiblingIndex() - snsCount);
+
+            }
+
+            Path newPath = pathFactory.create(oldPath.getParent(),
+                                              pathFactory.createSegment(fromEntity.getChildName(),
+                                                                        fromEntity.getSameNameSiblingIndex()));
+            return actualFromLocation.location.with(newPath);
+        }
+
+        int oldIndex = fromEntity.getIndexInParent();
+
+        /*
+         * This is a sub-optimal approach, particularly for inserts to the front
+         * of a long list of child nodes, but it guarantees that we won't have
+         * the JPA-cached entities and the database out of sync.
+         */
+
+        Query query = entities.createNamedQuery("ChildEntity.findAllUnderParent");
+        query.setParameter("workspaceId", workspaceId);
+        query.setParameter("parentUuidString", toUuidString);
+
+        int nextIndexInParent = 0;
+        int nextSnsIndex = 1;
+        try {
+            List<ChildEntity> children = query.getResultList();
+            Path beforePath = beforeLocation.getPath();
+            Path.Segment beforeSegment = beforePath.getLastSegment();
+
+            boolean foundBefore = false;
+            for (ChildEntity child : children) {
+                NamespaceEntity namespace = child.getChildNamespace();
+                if (namespace.getUri().equals(ns.getUri()) && child.getChildName().equals(childLocalName)
+                    && child.getSameNameSiblingIndex() == beforeSegment.getIndex()) {
+                    foundBefore = true;
+                    nextIndexInParent = child.getIndexInParent();
+                    nextSnsIndex = beforeSegment.getIndex();
+                }
+
+                if (foundBefore) {
+                    child.setIndexInParent(child.getIndexInParent() + 1);
+                    if (child.getChildName().equals(childLocalName) && namespace.getUri().equals(ns.getUri())) {
+                        child.setSameNameSiblingIndex(child.getSameNameSiblingIndex() + 1);
+                    }
+                    entities.persist(child);
+                }
+            }
+
+        } catch (NoResultException e) {
+        }
+
+        fromEntity.setParentUuidString(toUuidString);
+        fromEntity.setChildName(childLocalName);
+        fromEntity.setChildNamespace(ns);
+        fromEntity.setIndexInParent(nextIndexInParent);
+        fromEntity.setSameNameSiblingIndex(nextSnsIndex);
+
+        // Flush the entities to the database ...
+        entities.flush();
+
+        // Determine the new location ...
+        Path newParentPath = actualIntoLocation.location.getPath();
+        Path newPath = pathFactory.create(newParentPath, childName, nextSnsIndex);
+        Location oldLocation = actualFromLocation.location;
+        Location newLocation = oldLocation.with(newPath);
+
+        // And adjust the SNS index and indexes ...
+        ChildEntity.adjustSnsIndexesAndIndexesAfterRemoving(entities, workspaceId, oldParentUuid, childLocalName, ns.getId(), -1);
+
+        // Update the cache ...
+        cache.moveNode(workspaceId, oldLocation, oldIndex, newLocation);
+
+        return newLocation;
+    }
+
     /**
      * {@inheritDoc}
      * 
      * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.MoveBranchRequest)
      */
-    @SuppressWarnings( "unchecked" )
     @Override
     public void process( MoveBranchRequest request ) {
         logger.trace(request.toString());
@@ -1835,143 +2071,25 @@
                 throw new InvalidRequestException(msg);
             }
 
-            // Find the ChildEntity of the existing 'from' node ...
-            ChildEntity fromEntity = actualLocation.childEntity;
-            final String oldParentUuid = fromEntity.getParentUuidString();
-
-            // Find the actual new location ...
-            Location toLocation = request.into();
-            Location beforeLocation = request.before();
-
-            if (beforeLocation != null) {
-                if (beforeLocation.hasPath()) {
-                    toLocation = Location.create(beforeLocation.getPath().getParent());
-                } else {
-                    ActualLocation actualBeforeLocation = getActualLocation(workspace, beforeLocation);
-
-                    // Ensure that the beforeLocation has a path - actualBeforeLocation has a path
-                    beforeLocation = actualBeforeLocation.location;
-                    toLocation = Location.create(actualBeforeLocation.location.getPath().getParent());
-                }
-            }
-
-            String toUuidString = null;
             if (request.hasNoEffect()) {
                 actualNewLocation = actualOldLocation;
             } else {
                 // We have to proceed as normal ...
-                ActualLocation actualIntoLocation = getActualLocation(workspace, toLocation);
-                toUuidString = actualIntoLocation.uuid;
-                if (!toUuidString.equals(oldParentUuid)) {
-                    // Now we know that the new parent is not the existing parent ...
-                    final int oldIndex = fromEntity.getIndexInParent();
 
-                    // Make sure the child name is set correctly ...
-                    String childOldLocalName = fromEntity.getChildName();
-                    String childLocalName = null;
-                    NamespaceEntity ns = null;
-                    Name childName = request.desiredName();
-                    if (childName != null) {
-                        childLocalName = request.desiredName().getLocalName();
-                        String childNsUri = childName.getNamespaceUri();
-                        ns = namespaces.get(childNsUri, true);
-                    } else {
-                        childName = oldPath.getLastSegment().getName();
-                        childLocalName = fromEntity.getChildName();
-                        ns = fromEntity.getChildNamespace();
-                    }
+                Location beforeLocation = request.before();
+                if (beforeLocation == null) {
+                    ActualLocation actualIntoLocation = getActualLocation(workspace, request.into());
 
-                    int nextSnsIndex = 1;
-                    int nextIndexInParent = 1;
-                    if (beforeLocation == null) {
-                        // Find the largest SNS index in the existing ChildEntity objects with the same name ...
-                        Query query = entities.createNamedQuery("ChildEntity.findMaximumSnsIndex");
-                        query.setParameter("workspaceId", workspaceId);
-                        query.setParameter("parentUuid", toUuidString);
-                        query.setParameter("ns", ns.getId());
-                        query.setParameter("childName", childLocalName);
-                        try {
-                            Integer index = (Integer)query.getSingleResult();
-                            if (index != null) nextSnsIndex = index.intValue() + 1;
-                        } catch (NoResultException e) {
-                        }
+                    actualNewLocation = moveNodeToLastChild(workspace, actualLocation, actualIntoLocation, request.desiredName());
+                } else {
 
-                        // Find the largest child index in the existing ChildEntity objects ...
-                        query = entities.createNamedQuery("ChildEntity.findMaximumChildIndex");
-                        query.setParameter("workspaceId", workspaceId);
-                        query.setParameter("parentUuid", toUuidString);
-                        try {
-                            Integer index = (Integer)query.getSingleResult();
-                            if (index != null) nextIndexInParent = index + 1;
-                        } catch (NoResultException e) {
-                        }
-                    } else {
-                        /*
-                         * This is a sub-optimal approach, particularly for inserts to the front
-                         * of a long list of child nodes, but it guarantees that we won't have
-                         * the JPA-cached entities and the database out of sync.
-                         */
+                    ActualLocation actualBeforeLocation = getActualLocation(workspace, beforeLocation);
+                    ActualLocation actualIntoLocation = getActualLocation(workspace,
+                                                                          Location.create(beforeLocation.getPath().getParent()));
 
-                        Query query = entities.createNamedQuery("ChildEntity.findAllUnderParent");
-                        query.setParameter("workspaceId", workspaceId);
-                        query.setParameter("parentUuidString", toUuidString);
-                        try {
-                            List<ChildEntity> children = query.getResultList();
-                            Path beforePath = beforeLocation.getPath();
-                            Path.Segment beforeSegment = beforePath.getLastSegment();
-
-                            boolean foundBefore = false;
-                            for (ChildEntity child : children) {
-                                NamespaceEntity namespace = child.getChildNamespace();
-                                if (namespace.getUri().equals(ns.getUri()) && child.getChildName().equals(childLocalName)
-                                    && child.getSameNameSiblingIndex() == beforeSegment.getIndex()) {
-                                    foundBefore = true;
-                                    nextIndexInParent = child.getIndexInParent();
-                                    nextSnsIndex = beforeSegment.getIndex();
-                                }
-
-                                if (foundBefore) {
-                                    child.setIndexInParent(child.getIndexInParent() + 1);
-                                    if (child.getChildName().equals(childLocalName) && namespace.getUri().equals(ns.getUri())) {
-                                        child.setSameNameSiblingIndex(child.getSameNameSiblingIndex() + 1);
-                                    }
-                                    entities.persist(child);
-                                }
-                            }
-
-                        } catch (NoResultException e) {
-                        }
-
-                    }
-
-                    fromEntity.setParentUuidString(toUuidString);
-                    fromEntity.setChildName(childLocalName);
-                    fromEntity.setChildNamespace(ns);
-                    fromEntity.setIndexInParent(nextIndexInParent);
-                    fromEntity.setSameNameSiblingIndex(nextSnsIndex);
-
-                    // Flush the entities to the database ...
-                    entities.flush();
-
-                    // Determine the new location ...
-                    Path newParentPath = actualIntoLocation.location.getPath();
-                    Path newPath = pathFactory.create(newParentPath, childName, nextSnsIndex);
-                    actualNewLocation = actualOldLocation.with(newPath);
-
-                    // And adjust the SNS index and indexes ...
-                    ChildEntity.adjustSnsIndexesAndIndexesAfterRemoving(entities,
-                                                                        workspaceId,
-                                                                        oldParentUuid,
-                                                                        childOldLocalName,
-                                                                        ns.getId(),
-                                                                        oldIndex);
-
-                    // Update the cache ...
-                    cache.moveNode(workspaceId, actualOldLocation, oldIndex, actualNewLocation);
+                    actualNewLocation = moveNodeBefore(workspace, actualLocation, actualIntoLocation, actualBeforeLocation);
                 }
-
             }
-
         } catch (Throwable e) { // Includes PathNotFoundException
             System.err.flush();
             System.out.flush();
@@ -2311,7 +2429,7 @@
 
             props.setData(baos.toByteArray());
             props.setPropertyCount(numProperties);
-
+            
             // Record the changes to the references ...
             if (refs != null && refs.hasWritten()) {
                 for (Reference reference : refs.getWritten()) {
@@ -2402,7 +2520,7 @@
             // See if the location is already in the cache ...
             Location cached = cache.getLocationFor(workspaceId, path);
             if (cached != null) {
-                return new ActualLocation(cached, cached.getUuid().toString(), null);
+                return new ActualLocation(original, cached.getUuid().toString(), null);
             }
         }
 
@@ -2437,7 +2555,7 @@
                 }
             }
             Path fullPath = pathFactory.createAbsolutePath(segments);
-            Location newLocation = Location.create(fullPath, uuidProperty);
+            Location newLocation = original.with(fullPath); 
             cache.addNewNode(workspaceId, newLocation);
             return new ActualLocation(newLocation, nodeUuidString, originalEntity);
         }
@@ -2460,10 +2578,17 @@
         if (cachedParent != null) {
             // We know the UUID of the parent, so we can find the child a little faster ...
             ChildEntity child = findByPathSegment(workspaceId, cachedParent.getUuid().toString(), path.getLastSegment());
+            
+            // If there is no matching child, throw an exception
+            if (child == null) {
+                // Could not find the node given the supplied path, so find the lowest path that does exist ...
+                throw new PathNotFoundException(original, cachedParent.getPath(), JpaConnectorI18n.nodeDoesNotExist.text(path));
+            }
+            
             uuidString = child.getId().getChildUuidString();
             Location newLocation = original.with(UUID.fromString(uuidString));
             cache.addNewNode(workspaceId, newLocation);
-            return new ActualLocation(newLocation, uuidString, child);
+            return new ActualLocation(original, uuidString, child);
         }
 
         // We couldn't find the parent, so we need to search by path ...
@@ -2489,6 +2614,18 @@
         return new ActualLocation(newLocation, uuidString, child);
     }
 
+    protected ChildEntity findNode( long workspaceId, String uuidString) {
+        Query query = entities.createNamedQuery("ChildEntity.findByChildUuid");
+        query.setParameter("workspaceId", workspaceId);
+        query.setParameter("childUuidString", uuidString);
+        try {
+            // Find the parent of the UUID ...
+            return (ChildEntity)query.getSingleResult();
+        } catch (NoResultException e) {
+            return null;
+        }
+    }
+    
     /**
      * Find the node with the supplied path segment that is a child of the supplied parent.
      * 

Modified: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ChildEntity.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ChildEntity.java	2009-07-17 19:12:26 UTC (rev 1114)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ChildEntity.java	2009-07-20 12:18:58 UTC (rev 1115)
@@ -310,4 +310,38 @@
         }
     }
 
+    @SuppressWarnings( "unchecked" )
+    public static int adjustSnsIndexesAndIndexes( EntityManager entities,
+                                                   Long workspaceId,
+                                                   String uuidParent,
+                                                   int afterIndex,
+                                                   int untilIndex,
+                                                   long childNamespaceIndex,
+                                                   String childName,
+                                                   int modifier ) {
+        int snsCount = 0;
+        
+        // Decrement the 'indexInParent' index values for all nodes above the previously removed sibling ...
+        Query query = entities.createNamedQuery("ChildEntity.findChildrenAfterIndexUnderParent");
+        query.setParameter("workspaceId", workspaceId);
+        query.setParameter("parentUuidString", uuidParent);
+        query.setParameter("afterIndex", afterIndex);
+
+        int index = afterIndex;
+        for (ChildEntity entity : (List<ChildEntity>)query.getResultList()) {
+            if (++index > untilIndex) {
+                break;
+            }
+
+            // Decrement the index in parent ...
+            entity.setIndexInParent(entity.getIndexInParent() + modifier);
+            if (entity.getChildName().equals(childName) && entity.getChildNamespace().getId() == childNamespaceIndex) {
+                // The name matches, so decrement the SNS index ...
+                entity.setSameNameSiblingIndex(entity.getSameNameSiblingIndex() + modifier);
+                snsCount++;
+            }
+        }
+
+        return snsCount;
+    }
 }

Modified: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/util/Serializer.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/util/Serializer.java	2009-07-17 19:12:26 UTC (rev 1114)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/util/Serializer.java	2009-07-20 12:18:58 UTC (rev 1115)
@@ -217,7 +217,7 @@
         final Name name = property.getName();
         if (this.excludeUuidProperty && DnaLexicon.UUID.equals(name)) return false;
         // Write the name ...
-        stream.writeObject(name.getString());
+        stream.writeObject(name.getString(Path.NO_OP_ENCODER));
         // Write the number of values ...
         stream.writeInt(property.size());
         for (Object value : property) {
@@ -277,7 +277,7 @@
                 }
             } else if (value instanceof Name) {
                 stream.writeChar('N');
-                stream.writeObject(((Name)value).getString());
+                stream.writeObject(((Name)value).getString(Path.NO_OP_ENCODER));
             } else if (value instanceof Path) {
                 stream.writeChar('P');
                 stream.writeObject(((Path)value).getString());

Modified: trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaConnectorWritingTest.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaConnectorWritingTest.java	2009-07-17 19:12:26 UTC (rev 1114)
+++ trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaConnectorWritingTest.java	2009-07-20 12:18:58 UTC (rev 1115)
@@ -57,6 +57,7 @@
         source.setMaximumConnectionIdleTimeInSeconds(0);
         source.setReferentialIntegrityEnforced(true);
         source.setLargeValueSizeInBytes(150);
+        source.setCompressData(true);
 
         return source;
     }

Modified: trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaSourceTest.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaSourceTest.java	2009-07-17 19:12:26 UTC (rev 1114)
+++ trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaSourceTest.java	2009-07-20 12:18:58 UTC (rev 1115)
@@ -58,7 +58,7 @@
         this.source.setNumberOfConnectionsToAcquireAsNeeded(1);
         this.source.setMaximumSizeOfStatementCache(100);
         this.source.setMaximumConnectionIdleTimeInSeconds(0);
-        this.source.setNameOfDefaultWorkspace("default");
+        this.source.setDefaultWorkspaceName("default");
         this.source.setCreatingWorkspacesAllowed(true);
     }
 



More information about the dna-commits mailing list