[dna-commits] DNA SVN: r684 - in trunk/extensions/dna-connector-store-jpa/src: test/java/org/jboss/dna/connector/store/jpa/models/basic and 1 other directory.

dna-commits at lists.jboss.org dna-commits at lists.jboss.org
Thu Dec 11 19:05:33 EST 2008


Author: rhauch
Date: 2008-12-11 19:05:32 -0500 (Thu, 11 Dec 2008)
New Revision: 684

Added:
   trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/models/basic/ChildEntityTest.java
Modified:
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/BasicRequestProcessor.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/ChildEntity.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/SubgraphNodeEntity.java
   trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/SubgraphQuery.java
   trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/models/basic/BasicModelTest.java
Log:
DNA-40
Implemented the logic to adjust the indexes in parent and same-name-sibling indexes when a node is removed from a parent (either deleted or moved to another parent).

Modified: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/BasicRequestProcessor.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/BasicRequestProcessor.java	2008-12-11 22:02:26 UTC (rev 683)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/BasicRequestProcessor.java	2008-12-12 00:05:32 UTC (rev 684)
@@ -237,6 +237,9 @@
             // Since we've just created this node, we know about all the children (actually, there are none).
             cache.setAllChildren(path, new LinkedList<Location>());
 
+            // Flush the entities ...
+            // entities.flush();
+
         } catch (Throwable e) { // Includes PathNotFoundException
             request.setError(e);
             logger.trace(e, "Problem " + request);
@@ -666,6 +669,11 @@
 
             // Compute the subgraph, including the root ...
             SubgraphQuery query = SubgraphQuery.create(getExecutionContext(), entities, actualLocation.getUuid(), path, 0);
+            ChildEntity deleted = query.getNode();
+            String parentUuidString = deleted.getId().getParentUuidString();
+            String childName = deleted.getChildName();
+            long nsId = deleted.getChildNamespace().getId();
+            int indexInParent = deleted.getIndexInParent();
 
             // Get the locations of all deleted nodes, which will be required by events ...
             List<Location> deletedLocations = query.getNodeLocations(true, true);
@@ -674,7 +682,8 @@
             query.deleteSubgraph(true);
 
             // And adjust the SNS index and indexes ...
-            // adjustSnsIndexesAndIndexesAfterRemoving(oldParentUuid, childLocalName, ns.getId(), oldIndex, oldSnsIndex);
+            ChildEntity.adjustSnsIndexesAndIndexesAfterRemoving(entities, parentUuidString, childName, nsId, indexInParent);
+            entities.flush();
 
             // Remove from the cache of children locations all entries for deleted nodes ...
             cache.removeBranch(deletedLocations);
@@ -724,7 +733,6 @@
                 toUuidString = actualIntoLocation.uuid;
                 if (!toUuidString.equals(oldParentUuid)) {
                     // Now we know that the new parent is not the existing parent ...
-                    final int oldSnsIndex = fromEntity.getSameNameSiblingIndex();
                     final int oldIndex = fromEntity.getIndexInParent();
 
                     // Find the largest SNS index in the existing ChildEntity objects with the same name ...
@@ -754,6 +762,9 @@
                     fromEntity.setIndexInParent(nextIndexInParent);
                     fromEntity.setSameNameSiblingIndex(nextSnsIndex);
 
+                    // Flush the entities to the database ...
+                    entities.flush();
+
                     // Determine the new location ...
                     Path newParentPath = actualIntoLocation.location.getPath();
                     Name childName = oldPath.getLastSegment().getName();
@@ -761,10 +772,15 @@
                     actualNewLocation = actualOldLocation.with(newPath);
 
                     // And adjust the SNS index and indexes ...
-                    adjustSnsIndexesAndIndexesAfterRemoving(oldParentUuid, childLocalName, ns.getId(), oldIndex, oldSnsIndex);
+                    ChildEntity.adjustSnsIndexesAndIndexesAfterRemoving(entities,
+                                                                        oldParentUuid,
+                                                                        childLocalName,
+                                                                        ns.getId(),
+                                                                        oldIndex);
 
                     // Update the cache ...
                     cache.moveNode(actualOldLocation, oldIndex, actualNewLocation);
+
                 }
 
             }
@@ -776,15 +792,6 @@
         request.setActualLocations(actualOldLocation, actualNewLocation);
     }
 
-    protected void adjustSnsIndexesAndIndexesAfterRemoving( String uuidParent,
-                                                            String childName,
-                                                            long childNamespaceIndex,
-                                                            int childIndex,
-                                                            int childSnsIndex ) {
-        // TODO: Now update the 'index in parent' and SNS indexes of the siblings of the deleted node.
-
-    }
-
     protected String createProperties( String uuidString,
                                        Collection<Property> properties ) throws IOException {
         assert uuidString != null;

Modified: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/ChildEntity.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/ChildEntity.java	2008-12-11 22:02:26 UTC (rev 683)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/ChildEntity.java	2008-12-12 00:05:32 UTC (rev 684)
@@ -21,15 +21,19 @@
  */
 package org.jboss.dna.connector.store.jpa.models.basic;
 
+import java.util.List;
 import javax.persistence.Column;
 import javax.persistence.Entity;
+import javax.persistence.EntityManager;
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
 import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
+import javax.persistence.Query;
 import javax.persistence.Table;
 import org.hibernate.annotations.Index;
+import org.jboss.dna.common.text.Inflector;
 import org.jboss.dna.common.util.HashCode;
 import org.jboss.dna.connector.store.jpa.models.common.NamespaceEntity;
 
@@ -48,11 +52,13 @@
     @Index( name = "CHILDUUID_INX", columnNames = {"CHILD_UUID"} ),
     @Index( name = "CHILDNAME_INX", columnNames = {"PARENT_UUID", "CHILD_NAME_NS_ID", "CHILD_NAME_LOCAL", "SNS_INDEX"} )} )
 @NamedQueries( {
-    @NamedQuery( name = "ChildEntity.findByPathSegment", query = "select child from ChildEntity as child where child.id.parentUuidString = :parentUuidString AND child.childNamespace.id = :ns AND child.childName = :childName AND child.sameNameSiblingIndex = :sns and child.deleted is null" ),
-    @NamedQuery( name = "ChildEntity.findAllUnderParent", query = "select child from ChildEntity as child where child.id.parentUuidString = :parentUuidString and child.deleted is null" ),
-    @NamedQuery( name = "ChildEntity.findByChildUuid", query = "select child from ChildEntity as child where child.id.childUuidString = :childUuidString and child.deleted is null" ),
-    @NamedQuery( name = "ChildEntity.findMaximumSnsIndex", query = "select max(child.sameNameSiblingIndex) from ChildEntity as child where child.id.parentUuidString = :parentUuid AND child.childNamespace.id = :ns AND child.childName = :childName and child.deleted is null" ),
-    @NamedQuery( name = "ChildEntity.findMaximumChildIndex", query = "select max(child.indexInParent) from ChildEntity as child where child.id.parentUuidString = :parentUuid and child.deleted is null" )} )
+    @NamedQuery( name = "ChildEntity.findByPathSegment", query = "select child from ChildEntity as child where child.id.parentUuidString = :parentUuidString AND child.childNamespace.id = :ns AND child.childName = :childName AND child.sameNameSiblingIndex = :sns" ),
+    @NamedQuery( name = "ChildEntity.findAllUnderParent", query = "select child from ChildEntity as child where child.id.parentUuidString = :parentUuidString order by child.indexInParent" ),
+    @NamedQuery( name = "ChildEntity.findRangeUnderParent", query = "select child from ChildEntity as child where child.id.parentUuidString = :parentUuidString and child.indexInParent >= :firstIndex and child.indexInParent < :afterIndex order by child.indexInParent" ),
+    @NamedQuery( name = "ChildEntity.findChildrenAfterIndexUnderParent", query = "select child from ChildEntity as child where child.id.parentUuidString = :parentUuidString and child.indexInParent >= :afterIndex order by child.indexInParent" ),
+    @NamedQuery( name = "ChildEntity.findByChildUuid", query = "select child from ChildEntity as child where child.id.childUuidString = :childUuidString" ),
+    @NamedQuery( name = "ChildEntity.findMaximumSnsIndex", query = "select max(child.sameNameSiblingIndex) from ChildEntity as child where child.id.parentUuidString = :parentUuid AND child.childNamespace.id = :ns AND child.childName = :childName" ),
+    @NamedQuery( name = "ChildEntity.findMaximumChildIndex", query = "select max(child.indexInParent) from ChildEntity as child where child.id.parentUuidString = :parentUuid" )} )
 public class ChildEntity {
 
     @Id
@@ -71,9 +77,6 @@
     @Column( name = "SNS_INDEX", nullable = false, unique = false )
     private int sameNameSiblingIndex;
 
-    @Column( name = "DELETED", nullable = true, unique = false )
-    private Boolean deleted;
-
     public ChildEntity() {
     }
 
@@ -85,6 +88,7 @@
         this.indexInParent = indexInParent;
         this.childNamespace = ns;
         this.childName = name;
+        this.sameNameSiblingIndex = 1;
     }
 
     public ChildEntity( ChildId id,
@@ -170,20 +174,6 @@
     }
 
     /**
-     * @return deleted
-     */
-    public boolean isDeleted() {
-        return Boolean.TRUE.equals(deleted);
-    }
-
-    /**
-     * @param deleted Sets deleted to the specified value.
-     */
-    public void setDeleted( boolean deleted ) {
-        this.deleted = deleted ? Boolean.TRUE : null;
-    }
-
-    /**
      * {@inheritDoc}
      * 
      * @see java.lang.Object#hashCode()
@@ -232,7 +222,10 @@
             sb.append(" (id=").append(id.getChildUuidString()).append(")");
             String parentId = id.getParentUuidString();
             if (parentId != null) {
-                sb.append(" is child of ").append(parentId);
+                sb.append(" is ");
+                sb.append(Inflector.getInstance().ordinalize(indexInParent));
+                sb.append(" child of ");
+                sb.append(parentId);
             } else {
                 sb.append(" is root");
             }
@@ -240,4 +233,24 @@
         return sb.toString();
     }
 
+    @SuppressWarnings( "unchecked" )
+    public static void adjustSnsIndexesAndIndexesAfterRemoving( EntityManager entities,
+                                                                String uuidParent,
+                                                                String childName,
+                                                                long childNamespaceIndex,
+                                                                int childIndex ) {
+        // Decrement the 'indexInParent' index values for all nodes above the previously removed sibling ...
+        Query query = entities.createNamedQuery("ChildEntity.findChildrenAfterIndexUnderParent");
+        query.setParameter("parentUuidString", uuidParent);
+        query.setParameter("afterIndex", childIndex);
+        for (ChildEntity entity : (List<ChildEntity>)query.getResultList()) {
+            // Decrement the index in parent ...
+            entity.setIndexInParent(entity.getIndexInParent() - 1);
+            if (entity.getChildName().equals(childName) && entity.getChildNamespace().getId() == childNamespaceIndex) {
+                // The name matches, so decrement the SNS index ...
+                entity.setSameNameSiblingIndex(entity.getSameNameSiblingIndex() - 1);
+            }
+        }
+    }
+
 }

Modified: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/SubgraphNodeEntity.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/SubgraphNodeEntity.java	2008-12-11 22:02:26 UTC (rev 683)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/SubgraphNodeEntity.java	2008-12-12 00:05:32 UTC (rev 684)
@@ -41,7 +41,7 @@
 @Table( name = "DNA_SUBGRAPH_NODES" )
 @org.hibernate.annotations.Table( appliesTo = "DNA_SUBGRAPH_NODES", indexes = @Index( name = "QUERYID_INX", columnNames = {"QUERY_ID"} ) )
 @NamedQueries( {
-    @NamedQuery( name = "SubgraphNodeEntity.insertChildren", query = "insert into SubgraphNodeEntity(queryId,nodeUuid,depth,parentIndexInParent,indexInParent) select parentNode.queryId, child.id.childUuidString, parentNode.depth+1, parentNode.indexInParent, child.indexInParent from ChildEntity child, SubgraphNodeEntity parentNode where child.deleted is null and child.id.parentUuidString = parentNode.nodeUuid and parentNode.queryId = :queryId and parentNode.depth = :parentDepth" ),
+    @NamedQuery( name = "SubgraphNodeEntity.insertChildren", query = "insert into SubgraphNodeEntity(queryId,nodeUuid,depth,parentIndexInParent,indexInParent) select parentNode.queryId, child.id.childUuidString, parentNode.depth+1, parentNode.indexInParent, child.indexInParent from ChildEntity child, SubgraphNodeEntity parentNode where child.id.parentUuidString = parentNode.nodeUuid and parentNode.queryId = :queryId and parentNode.depth = :parentDepth" ),
     @NamedQuery( name = "SubgraphNodeEntity.getCount", query = "select count(*) from SubgraphNodeEntity where queryId = :queryId" ),
     @NamedQuery( name = "SubgraphNodeEntity.getPropertiesEntities", query = "select props from PropertiesEntity props, SubgraphNodeEntity node where props.id.uuidString = node.nodeUuid and node.queryId = :queryId and node.depth >= :depth and node.depth <= :maxDepth order by node.depth, node.parentIndexInParent, node.indexInParent" ),
     @NamedQuery( name = "SubgraphNodeEntity.getPropertiesEntitiesWithLargeValues", query = "select props from PropertiesEntity props, SubgraphNodeEntity node where props.id.uuidString = node.nodeUuid and node.queryId = :queryId and node.depth >= :depth and size(props.largeValues) > 0" ),

Modified: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/SubgraphQuery.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/SubgraphQuery.java	2008-12-11 22:02:26 UTC (rev 683)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/SubgraphQuery.java	2008-12-12 00:05:32 UTC (rev 684)
@@ -175,6 +175,22 @@
     }
 
     /**
+     * Get the {@link ChildEntity root node} of the subgraph. This must be called before the query is {@link #close() closed}.
+     * 
+     * @return the subgraph's root nodes
+     */
+    public ChildEntity getNode() {
+        // Now query for all the nodes and put into a list ...
+        Query search = manager.createNamedQuery("SubgraphNodeEntity.getChildEntities");
+        search.setParameter("queryId", query.getId());
+        search.setParameter("depth", 0);
+        search.setParameter("maxDepth", 0);
+
+        // Now process the nodes below the subgraph's root ...
+        return (ChildEntity)search.getSingleResult();
+    }
+
+    /**
      * Get the {@link ChildEntity nodes} in the subgraph. This must be called before the query is {@link #close() closed}.
      * 
      * @param includeRoot true if the subgraph's root node is to be included, or false otherwise

Modified: trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/models/basic/BasicModelTest.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/models/basic/BasicModelTest.java	2008-12-11 22:02:26 UTC (rev 683)
+++ trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/models/basic/BasicModelTest.java	2008-12-12 00:05:32 UTC (rev 684)
@@ -334,13 +334,13 @@
             assertThat(child1a.getIndexInParent(), is(1));
             assertThat(child1a.getChildName(), is("child1"));
             assertThat(child1a.getChildNamespace(), is(ns));
-            assertThat(child1a.getSameNameSiblingIndex(), is(0));
+            assertThat(child1a.getSameNameSiblingIndex(), is(1));
 
             assertThat(child2a.getId(), is(childId2));
             assertThat(child2a.getIndexInParent(), is(2));
             assertThat(child2a.getChildName(), is("child2"));
             assertThat(child2a.getChildNamespace(), is(ns));
-            assertThat(child2a.getSameNameSiblingIndex(), is(0));
+            assertThat(child2a.getSameNameSiblingIndex(), is(1));
 
             assertThat(child3a.getId(), is(childId3));
             assertThat(child3a.getIndexInParent(), is(3));

Added: trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/models/basic/ChildEntityTest.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/models/basic/ChildEntityTest.java	                        (rev 0)
+++ trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/models/basic/ChildEntityTest.java	2008-12-12 00:05:32 UTC (rev 684)
@@ -0,0 +1,404 @@
+/*
+ * 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.connector.store.jpa.models.basic;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertThat;
+import java.util.List;
+import java.util.UUID;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Query;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.jboss.dna.connector.store.jpa.models.common.NamespaceEntity;
+import org.jboss.dna.graph.BasicExecutionContext;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.properties.Path;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class ChildEntityTest {
+
+    private EntityManagerFactory factory;
+    private EntityManager manager;
+    private BasicModel model;
+    private ExecutionContext context;
+
+    @Before
+    public void beforeEach() throws Exception {
+        model = new BasicModel();
+        context = new BasicExecutionContext();
+        // Connect to the database ...
+        Ejb3Configuration configurator = new Ejb3Configuration();
+        model.configure(configurator);
+        configurator.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
+        configurator.setProperty("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver");
+        configurator.setProperty("hibernate.connection.username", "sa");
+        configurator.setProperty("hibernate.connection.password", "");
+        configurator.setProperty("hibernate.connection.url", "jdbc:hsqldb:.");
+        configurator.setProperty("hibernate.show_sql", "false");
+        configurator.setProperty("hibernate.format_sql", "true");
+        configurator.setProperty("hibernate.use_sql_comments", "true");
+        configurator.setProperty("hibernate.hbm2ddl.auto", "create");
+        factory = configurator.buildEntityManagerFactory();
+        manager = factory.createEntityManager();
+    }
+
+    @After
+    public void afterEach() throws Exception {
+        try {
+            if (manager != null) manager.close();
+        } finally {
+            manager = null;
+            if (factory != null) {
+                try {
+                    factory.close();
+                } finally {
+                    factory = null;
+                }
+            }
+        }
+    }
+
+    protected ChildId[] createChildren( UUID parentUuid,
+                                        NamespaceEntity ns,
+                                        int startingIndex,
+                                        int numChildren,
+                                        String localName,
+                                        boolean useSns ) {
+
+        ChildId[] result = new ChildId[numChildren];
+        manager.getTransaction().begin();
+        try {
+            // Create the child entities ...
+            for (int i = 0; i != numChildren; ++i) {
+                int indexInParent = i + startingIndex;
+                ChildId id = new ChildId(parentUuid.toString(), UUID.randomUUID().toString());
+                ChildEntity child = null;
+                if (useSns) {
+                    child = new ChildEntity(id, indexInParent, ns, localName, i + 1);
+                } else {
+                    String name = numChildren == 1 ? localName : localName + indexInParent;
+                    child = new ChildEntity(id, indexInParent, ns, name);
+                }
+                result[i] = id;
+                manager.persist(child);
+            }
+            manager.getTransaction().commit();
+        } catch (RuntimeException t) {
+            // manager.getTransaction().rollback();
+            throw t;
+        }
+        return result;
+    }
+
+    protected ChildId[] createMixtureOfChildren( UUID parentUuid,
+                                                 NamespaceEntity ns ) {
+        ChildId[] ids1 = createChildren(parentUuid, ns, 1, 10, "child", false);
+        ChildId[] ids2 = createChildren(parentUuid, ns, 11, 10, "childWithSameName", true);
+        ChildId[] ids3 = createChildren(parentUuid, ns, 21, 1, "anotherChild", false);
+        ChildId[] ids4 = createChildren(parentUuid, ns, 22, 1, "nextToLastChild", false);
+        ChildId[] ids5 = createChildren(parentUuid, ns, 23, 1, "lastChild", false);
+        ChildId[][] ids = new ChildId[][] {ids1, ids2, ids3, ids4, ids5};
+        ChildId[] results = new ChildId[ids1.length + ids2.length + ids3.length + ids4.length + ids5.length];
+        int i = 0;
+        for (ChildId[] idArray : ids) {
+            for (ChildId id : idArray)
+                results[i++] = id;
+        }
+        return results;
+    }
+
+    protected ChildEntity getChild( String childUuid ) {
+        Query query = manager.createNamedQuery("ChildEntity.findByChildUuid");
+        query.setParameter("childUuidString", childUuid);
+        return (ChildEntity)query.getSingleResult();
+    }
+
+    @Test
+    public void shouldCreateChildrenWithDifferentNames() {
+        UUID parentUuid = UUID.randomUUID();
+        NamespaceEntity ns = NamespaceEntity.findByUri(manager, "http://www.example.com");
+        ChildId[] ids = createChildren(parentUuid, ns, 1, 10, "child", false);
+
+        // Look up the object ...
+        manager.getTransaction().begin();
+        try {
+            int index = 1;
+            for (ChildId id : ids) {
+                ChildEntity child = manager.find(ChildEntity.class, id);
+                assertThat(child.getId(), is(id));
+                assertThat(child.getIndexInParent(), is(index));
+                assertThat(child.getChildName(), is("child" + index));
+                assertThat(child.getChildNamespace(), is(ns));
+                assertThat(child.getSameNameSiblingIndex(), is(1));
+                ++index;
+            }
+        } finally {
+            manager.getTransaction().rollback();
+        }
+    }
+
+    @Test
+    public void shouldCreateChildrenWithSameNameSiblingIndex() {
+        UUID parentUuid = UUID.randomUUID();
+        NamespaceEntity ns = NamespaceEntity.findByUri(manager, "http://www.example.com");
+        ChildId[] ids = createChildren(parentUuid, ns, 1, 10, "child", true);
+
+        // Look up the object ...
+        manager.getTransaction().begin();
+        try {
+            int index = 1;
+            for (ChildId id : ids) {
+                ChildEntity child = manager.find(ChildEntity.class, id);
+                assertThat(child.getId(), is(id));
+                assertThat(child.getIndexInParent(), is(index));
+                assertThat(child.getChildName(), is("child"));
+                assertThat(child.getChildNamespace(), is(ns));
+                assertThat(child.getSameNameSiblingIndex(), is(index));
+                ++index;
+            }
+        } finally {
+            manager.getTransaction().rollback();
+        }
+    }
+
+    @SuppressWarnings( "unchecked" )
+    @Test
+    public void shouldCreateMixtureOfChildrenWithDifferentNamesAndSameNameSiblingIndexes() {
+        UUID parentUuid = UUID.randomUUID();
+        NamespaceEntity ns = NamespaceEntity.findByUri(manager, "http://www.example.com");
+        createChildren(parentUuid, ns, 1, 10, "child", false);
+        createChildren(parentUuid, ns, 11, 10, "childWithSameName", true);
+        createChildren(parentUuid, ns, 21, 1, "anotherChild", false);
+        createChildren(parentUuid, ns, 22, 1, "nextToLastChild", false);
+        createChildren(parentUuid, ns, 23, 1, "lastChild", false);
+
+        // Look up the object ...
+        manager.getTransaction().begin();
+        try {
+            Query query = manager.createNamedQuery("ChildEntity.findAllUnderParent");
+            query.setParameter("parentUuidString", parentUuid.toString());
+            List<ChildEntity> children = query.getResultList();
+            int index = 1;
+            assertThat(children.size(), is(23));
+            for (ChildEntity child : children) {
+                assertThat(child.getIndexInParent(), is(index++));
+            }
+        } finally {
+            manager.getTransaction().rollback();
+        }
+    }
+
+    @SuppressWarnings( "unchecked" )
+    @Test
+    public void shouldCreateMixtureOfChildrenWithDifferentNamesAndSameNameSiblingIndexesMethod2() {
+        UUID parentUuid = UUID.randomUUID();
+        NamespaceEntity ns = NamespaceEntity.findByUri(manager, "http://www.example.com");
+        ChildId[] ids = createMixtureOfChildren(parentUuid, ns);
+        assertThat(ids.length, is(23));
+
+        // Look up the object ...
+        manager.getTransaction().begin();
+        try {
+            Query query = manager.createNamedQuery("ChildEntity.findAllUnderParent");
+            query.setParameter("parentUuidString", parentUuid.toString());
+            List<ChildEntity> children = query.getResultList();
+            int index = 1;
+            assertThat(children.size(), is(23));
+            for (ChildEntity child : children) {
+                assertThat(child.getIndexInParent(), is(index++));
+            }
+
+            index = 1;
+            for (ChildId id : ids) {
+                ChildEntity entity = getChild(id.getChildUuidString());
+                assertThat(entity.getIndexInParent(), is(index++));
+            }
+        } finally {
+            manager.getTransaction().rollback();
+        }
+    }
+
+    @SuppressWarnings( "unchecked" )
+    @Test
+    public void shouldFindEntitiesInIndexRange() {
+        UUID parentUuid = UUID.randomUUID();
+        NamespaceEntity ns = NamespaceEntity.findByUri(manager, "http://www.example.com");
+        ChildId[] ids = createMixtureOfChildren(parentUuid, ns);
+        assertThat(ids.length, is(23));
+
+        // Look up the objects ...
+        manager.getTransaction().begin();
+        try {
+            Query query = manager.createNamedQuery("ChildEntity.findAllUnderParent");
+            query.setParameter("parentUuidString", parentUuid.toString());
+            List<ChildEntity> children = query.getResultList();
+            int index = 1;
+            assertThat(children.size(), is(23));
+            for (ChildEntity child : children) {
+                assertThat(child.getIndexInParent(), is(index++));
+            }
+
+            query = manager.createNamedQuery("ChildEntity.findRangeUnderParent");
+            query.setParameter("parentUuidString", parentUuid.toString());
+            query.setParameter("firstIndex", 3);
+            query.setParameter("afterIndex", 6);
+            children = query.getResultList();
+            assertThat(children.size(), is(3));
+            assertThat(children.get(0).getIndexInParent(), is(3));
+            assertThat(children.get(1).getIndexInParent(), is(4));
+            assertThat(children.get(2).getIndexInParent(), is(5));
+
+        } finally {
+            manager.getTransaction().rollback();
+        }
+    }
+
+    @SuppressWarnings( "unchecked" )
+    @Test
+    public void shouldFindEntitiesAfterIndex() {
+        UUID parentUuid = UUID.randomUUID();
+        NamespaceEntity ns = NamespaceEntity.findByUri(manager, "http://www.example.com");
+        ChildId[] ids = createMixtureOfChildren(parentUuid, ns);
+        assertThat(ids.length, is(23));
+
+        // Look up the objects ...
+        manager.getTransaction().begin();
+        try {
+            Query query = manager.createNamedQuery("ChildEntity.findAllUnderParent");
+            query.setParameter("parentUuidString", parentUuid.toString());
+            List<ChildEntity> children = query.getResultList();
+            int index = 1;
+            assertThat(children.size(), is(23));
+            for (ChildEntity child : children) {
+                assertThat(child.getIndexInParent(), is(index++));
+            }
+
+            query = manager.createNamedQuery("ChildEntity.findChildrenAfterIndexUnderParent");
+            query.setParameter("parentUuidString", parentUuid.toString());
+            query.setParameter("afterIndex", 18);
+            children = query.getResultList();
+            assertThat(children.size(), is(6));
+            assertThat(children.get(0).getIndexInParent(), is(18));
+            assertThat(children.get(1).getIndexInParent(), is(19));
+            assertThat(children.get(2).getIndexInParent(), is(20));
+            assertThat(children.get(3).getIndexInParent(), is(21));
+            assertThat(children.get(4).getIndexInParent(), is(22));
+            assertThat(children.get(5).getIndexInParent(), is(23));
+
+        } finally {
+            manager.getTransaction().rollback();
+        }
+    }
+
+    @SuppressWarnings( "unchecked" )
+    @Test
+    public void shouldFindAdjustChildIndexesAfterRemovalOfFirstSibling() {
+        UUID parentUuid = UUID.randomUUID();
+        NamespaceEntity ns = NamespaceEntity.findByUri(manager, "http://www.example.com");
+        ChildId[] ids = createMixtureOfChildren(parentUuid, ns);
+        assertThat(ids.length, is(23));
+
+        // Look up the objects ...
+        manager.getTransaction().begin();
+        try {
+            Query query = manager.createNamedQuery("ChildEntity.findAllUnderParent");
+            query.setParameter("parentUuidString", parentUuid.toString());
+            List<ChildEntity> children = query.getResultList();
+            int index = 1;
+            assertThat(children.size(), is(23));
+            for (ChildEntity child : children) {
+                assertThat(child.getIndexInParent(), is(index++));
+            }
+
+            // Remove the first child ...
+            ChildEntity child = getChild(ids[0].getChildUuidString());
+            assertThat(child, is(notNullValue()));
+            String childName = child.getChildName();
+            manager.remove(child);
+
+            ChildEntity.adjustSnsIndexesAndIndexesAfterRemoving(manager, parentUuid.toString(), childName, ns.getId(), 0);
+
+            assertChildren(parentUuid.toString(),
+            // "child1",
+                           "child2",
+                           "child3",
+                           "child4",
+                           "child5",
+                           "child6",
+                           "child7",
+                           "child8",
+                           "child9",
+                           "child10",
+                           "childWithSameName[1]",
+                           "childWithSameName[2]",
+                           "childWithSameName[3]",
+                           "childWithSameName[4]",
+                           "childWithSameName[5]",
+                           "childWithSameName[6]",
+                           "childWithSameName[7]",
+                           "childWithSameName[8]",
+                           "childWithSameName[9]",
+                           "childWithSameName[10]",
+                           "anotherChild",
+                           "nextToLastChild",
+                           "lastChild");
+
+        } finally {
+            manager.getTransaction().rollback();
+        }
+    }
+
+    @SuppressWarnings( "unchecked" )
+    protected void assertChildren( String parentUuid,
+                                   String... childNames ) {
+        Query query = manager.createNamedQuery("ChildEntity.findAllUnderParent");
+        query.setParameter("parentUuidString", parentUuid.toString());
+        List<ChildEntity> children = query.getResultList();
+        int index = 0;
+        for (ChildEntity child : children) {
+            // System.out.println("found " + child);
+            String childName = childNames[index++];
+            Path.Segment segment = context.getValueFactories().getPathFactory().createSegment(childName);
+            assertThat(child.getChildName(), is(segment.getName().getLocalName()));
+            assertThat(child.getSameNameSiblingIndex(), is(segment.hasIndex() ? segment.getIndex() : 1));
+            assertThat(child.getIndexInParent(), is(index)); // index is incremented
+        }
+    }
+
+    @SuppressWarnings( "unchecked" )
+    protected void printChildren( String parentUuid ) {
+        Query query = manager.createNamedQuery("ChildEntity.findAllUnderParent");
+        query.setParameter("parentUuidString", parentUuid.toString());
+        List<ChildEntity> children = query.getResultList();
+        for (ChildEntity child : children) {
+            System.out.println("found " + child);
+        }
+
+    }
+}




More information about the dna-commits mailing list