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);
+ }
+
+ }
+}