summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Stepper2006-10-14 06:26:18 (EDT)
committerEike Stepper2006-10-14 06:26:18 (EDT)
commit5af52456e645ff38c1162a71b3d08cf1dc27ef7c (patch)
tree2c0442bb0f43bb3ba7b648f79a761458c74a0ece
parent583d6fa73a5ac5f5b6fc752795b1da8dc49041df (diff)
downloadcdo-5af52456e645ff38c1162a71b3d08cf1dc27ef7c.zip
cdo-5af52456e645ff38c1162a71b3d08cf1dc27ef7c.tar.gz
cdo-5af52456e645ff38c1162a71b3d08cf1dc27ef7c.tar.bz2
[160832] Object deletion leaves some opposite references https://bugs.eclipse.org/bugs/show_bug.cgi?id=160832
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/impl/MapperImpl.java8
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/impl/SQLConstants.java6
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/protocol/CommitTransactionIndication.java23
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/EMFDetachTest.java131
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/model1/AbstractModel1Test.java13
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/model1/AllTests.java2
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/model1/BidiReferencesTest.java283
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/topology/AbstractTopologyTest.java4
-rw-r--r--plugins/org.eclipse.net4j.util/config/.cvsignore1
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/Net4jUtilPlugin.java9
10 files changed, 456 insertions, 24 deletions
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/impl/MapperImpl.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/impl/MapperImpl.java
index 2dd0f31..0023543 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/impl/MapperImpl.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/impl/MapperImpl.java
@@ -309,12 +309,12 @@ public class MapperImpl extends ServiceImpl implements Mapper, SQLConstants
referenceTable.addColumn(REFERENCE_FEATUREID_COLUMN, ColumnType.INTEGER_LITERAL);
referenceTable.addColumn(REFERENCE_ORDINAL_COLUMN, ColumnType.BIGINT_LITERAL);
referenceTable.addColumn(REFERENCE_TARGET_COLUMN, ColumnType.BIGINT_LITERAL, 0, "NOT NULL");
- referenceTable.addColumn(REFERENCE_CONTENT_COLUMN, ColumnType.BOOLEAN_LITERAL);
+ referenceTable.addColumn(REFERENCE_CONTAINMENT_COLUMN, ColumnType.BOOLEAN_LITERAL);
referenceTable.addSimpleIndex(REFERENCE_TARGET_COLUMN, IndexType.NON_UNIQUE_LITERAL);
// TODO Check if this compound index generally makes preceding simple index superfluous
referenceTable.addCompoundIndex(new String[] { REFERENCE_TARGET_COLUMN,
- REFERENCE_CONTENT_COLUMN,}, IndexType.NON_UNIQUE_LITERAL);
+ REFERENCE_CONTAINMENT_COLUMN,}, IndexType.NON_UNIQUE_LITERAL);
// This index can not be a real PK (UNIQUE), since during movement of allReferences
// it temporarily holds duplicate entries!!!
@@ -547,9 +547,9 @@ public class MapperImpl extends ServiceImpl implements Mapper, SQLConstants
sql(INSERT_RESOURCE, new Object[] { rid, path});
}
- public void insertReference(long oid, int feature, int ordinal, long target, boolean content)
+ public void insertReference(long oid, int feature, int ordinal, long target, boolean containment)
{
- sql(INSERT_REFERENCE, new Object[] { oid, feature, ordinal, target, content});
+ sql(INSERT_REFERENCE, new Object[] { oid, feature, ordinal, target, containment});
}
public void removeReference(long oid, int feature, int ordinal)
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/impl/SQLConstants.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/impl/SQLConstants.java
index a3e07f4..1c9344c 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/impl/SQLConstants.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/impl/SQLConstants.java
@@ -83,7 +83,7 @@ public interface SQLConstants
public static final String REFERENCE_FEATUREID_COLUMN = "FEATUREID";
- public static final String REFERENCE_CONTENT_COLUMN = "CONTENT";
+ public static final String REFERENCE_CONTAINMENT_COLUMN = "CONTENT";
public static final String REFERENCE_ORDINAL_COLUMN = "ORDINAL";
@@ -131,7 +131,7 @@ public interface SQLConstants
public static final String SELECT_CONTAINER_OF_OBJECT = "SELECT " + REFERENCE_TABLE + "."
+ REFERENCE_OID_COLUMN + ", " + OBJECT_TABLE + "." + OBJECT_CID_COLUMN + " FROM "
+ REFERENCE_TABLE + ", " + OBJECT_TABLE + " WHERE " + REFERENCE_TABLE + "."
- + REFERENCE_TARGET_COLUMN + "=? AND " + REFERENCE_TABLE + "." + REFERENCE_CONTENT_COLUMN
+ + REFERENCE_TARGET_COLUMN + "=? AND " + REFERENCE_TABLE + "." + REFERENCE_CONTAINMENT_COLUMN
+ "=? AND " + REFERENCE_TABLE + "." + REFERENCE_OID_COLUMN + "=" + OBJECT_TABLE + "."
+ OBJECT_OID_COLUMN;
@@ -139,7 +139,7 @@ public interface SQLConstants
+ REFERENCE_OID_COLUMN + ", " + REFERENCE_TABLE + "." + REFERENCE_FEATUREID_COLUMN + ", "
+ OBJECT_TABLE + "." + OBJECT_CID_COLUMN + " FROM " + REFERENCE_TABLE + ", " + OBJECT_TABLE
+ " WHERE " + REFERENCE_TABLE + "." + REFERENCE_TARGET_COLUMN + "=? AND " + REFERENCE_TABLE
- + "." + REFERENCE_CONTENT_COLUMN + "=FALSE AND " + REFERENCE_TABLE + "."
+ + "." + REFERENCE_CONTAINMENT_COLUMN + "=FALSE AND " + REFERENCE_TABLE + "."
+ REFERENCE_OID_COLUMN + "=" + OBJECT_TABLE + "." + OBJECT_OID_COLUMN;
public static final String SELECT_ALL_OBJECTS_OF_RESOURCE = "SELECT " + OBJECT_OID_COLUMN + ", "
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/protocol/CommitTransactionIndication.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/protocol/CommitTransactionIndication.java
index 229ae8d..70b4310 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/protocol/CommitTransactionIndication.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/protocol/CommitTransactionIndication.java
@@ -12,7 +12,6 @@ package org.eclipse.emf.cdo.server.protocol;
import org.eclipse.net4j.core.Channel;
-import org.eclipse.net4j.core.Protocol;
import org.eclipse.net4j.core.impl.AbstractIndicationWithResponse;
import org.eclipse.net4j.util.ImplementationError;
@@ -95,7 +94,7 @@ public class CommitTransactionIndication extends AbstractIndicationWithResponse
if (!optimisticControlException)
{
transmitInvalidations();
- transmitRescourceChanges();
+ transmitResourceChanges();
}
}
@@ -199,7 +198,7 @@ public class CommitTransactionIndication extends AbstractIndicationWithResponse
int feature = receiveInt();
int ordinal = receiveInt();
long target = receiveLong();
- boolean content = receiveBoolean();
+ boolean containment = receiveBoolean();
if (oid < 0)
{
@@ -211,7 +210,7 @@ public class CommitTransactionIndication extends AbstractIndicationWithResponse
target = resolveTempOID(target);
}
- getMapper().insertReference(oid, feature, ordinal, target, content);
+ getMapper().insertReference(oid, feature, ordinal, target, containment);
}
}
@@ -336,7 +335,7 @@ public class CommitTransactionIndication extends AbstractIndicationWithResponse
long oid = receiveLong();
int feature = receiveInt();
long target = receiveLong();
- boolean content = receiveBoolean();
+ boolean containment = receiveBoolean();
if (target < 0)
{
@@ -347,10 +346,10 @@ public class CommitTransactionIndication extends AbstractIndicationWithResponse
{
OIDEncoder oidEncoder = getMapper().getOidEncoder();
debug("received reference set: oid=" + oidEncoder.toString(oid) + ", feature=" + feature
- + ", target=" + oidEncoder.toString(target) + ", content=" + content);
+ + ", target=" + oidEncoder.toString(target) + ", containment=" + containment);
}
- getMapper().insertReference(oid, feature, 0, target, content);
+ getMapper().insertReference(oid, feature, 0, target, containment);
}
/**
@@ -381,7 +380,7 @@ public class CommitTransactionIndication extends AbstractIndicationWithResponse
int feature = receiveInt();
int ordinal = receiveInt() + 1;
long target = receiveLong();
- boolean content = receiveBoolean();
+ boolean containment = receiveBoolean();
if (target < 0)
{
@@ -392,8 +391,8 @@ public class CommitTransactionIndication extends AbstractIndicationWithResponse
{
OIDEncoder oidEncoder = getMapper().getOidEncoder();
debug("received reference add: oid=" + oidEncoder.toString(oid) + ", feature=" + feature
- + ", ordinal=" + ordinal + ", target=" + oidEncoder.toString(target) + ", content="
- + content);
+ + ", ordinal=" + ordinal + ", target=" + oidEncoder.toString(target) + ", containment="
+ + containment);
}
if (ordinal == 0)
@@ -402,7 +401,7 @@ public class CommitTransactionIndication extends AbstractIndicationWithResponse
}
getMapper().moveReferencesRelative(oid, feature, ordinal, Integer.MAX_VALUE, 1);
- getMapper().insertReference(oid, feature, ordinal, target, content);
+ getMapper().insertReference(oid, feature, ordinal, target, containment);
}
/**
@@ -605,7 +604,7 @@ public class CommitTransactionIndication extends AbstractIndicationWithResponse
}
}
- private void transmitRescourceChanges()
+ private void transmitResourceChanges()
{
if (!newResources.isEmpty())
{
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/EMFDetachTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/EMFDetachTest.java
new file mode 100644
index 0000000..b10eafa
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/EMFDetachTest.java
@@ -0,0 +1,131 @@
+/***************************************************************************
+ * Copyright (c) 2004, 2005, 2006 Eike Stepper, Germany.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ **************************************************************************/
+package org.eclipse.emf.cdo.tests;
+
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EFactory;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EcoreFactory;
+import org.eclipse.emf.ecore.EcorePackage;
+import org.eclipse.emf.ecore.change.ChangeDescription;
+import org.eclipse.emf.ecore.change.util.ChangeRecorder;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.impl.ResourceImpl;
+
+import java.util.Iterator;
+
+import junit.framework.TestCase;
+
+
+public class EMFDetachTest extends TestCase
+{
+ private EClass treeNodeClass;
+
+ private EAttribute nameAttribute;
+
+ private EReference childrenReference;
+
+ private EPackage modelPackage;
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ treeNodeClass = EcoreFactory.eINSTANCE.createEClass();
+ treeNodeClass.setName("TreeNode");
+
+ nameAttribute = EcoreFactory.eINSTANCE.createEAttribute();
+ nameAttribute.setName("nameAttribute");
+ nameAttribute.setEType(EcorePackage.eINSTANCE.getEString());
+
+ childrenReference = EcoreFactory.eINSTANCE.createEReference();
+ childrenReference.setName("childrenReference");
+ childrenReference.setEType(treeNodeClass);
+ childrenReference.setContainment(true);
+ childrenReference.setLowerBound(0);
+ childrenReference.setUpperBound(-1);
+
+ treeNodeClass.getEStructuralFeatures().add(nameAttribute);
+ treeNodeClass.getEStructuralFeatures().add(childrenReference);
+
+ modelPackage = EcoreFactory.eINSTANCE.createEPackage();
+ modelPackage.setName("modelPackage");
+ modelPackage.setNsPrefix("modelPackage");
+ modelPackage.setNsURI("http://modelPackage");
+ modelPackage.getEClassifiers().add(treeNodeClass);
+ }
+
+ @Override
+ protected void tearDown() throws Exception
+ {
+ modelPackage = null;
+ childrenReference = null;
+ nameAttribute = null;
+ treeNodeClass = null;
+ super.tearDown();
+ }
+
+ public void testDetachSingle()
+ {
+ EObject root = createNode("root", null);
+ for (int i = 0; i < 5; i++)
+ {
+ createNode("child" + i, root);
+ }
+
+ Resource resource = new ResourceImpl();
+ resource.getContents().add(root);
+
+ System.out.println();
+ ChangeRecorder recorder = new ChangeRecorder(root);
+ removeNode(root, 2);
+ ChangeDescription changeDescription = recorder.endRecording();
+
+ System.out.println();
+ EList objectsToAttach = changeDescription.getObjectsToAttach();
+ for (Iterator it = objectsToAttach.iterator(); it.hasNext();)
+ {
+ EObject node = (EObject) it.next();
+ System.out.println("Node to attach: " + node.eGet(nameAttribute));
+
+ }
+
+ assertEquals(1, objectsToAttach.size());
+ }
+
+ private EObject createNode(String name, EObject parent)
+ {
+ EFactory factory = modelPackage.getEFactoryInstance();
+ EObject node = factory.create(treeNodeClass);
+ node.eSet(nameAttribute, name);
+
+ if (parent != null)
+ {
+ EList children = (EList) parent.eGet(childrenReference);
+ children.add(node);
+ }
+
+ System.out.println("Created node " + name);
+ return node;
+ }
+
+ private void removeNode(EObject parent, int index)
+ {
+ EList children = (EList) parent.eGet(childrenReference);
+ EObject child = (EObject) children.remove(index);
+ System.out.println("Removed node " + child.eGet(nameAttribute));
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/model1/AbstractModel1Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/model1/AbstractModel1Test.java
index 4894da5..d64151f 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/model1/AbstractModel1Test.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/model1/AbstractModel1Test.java
@@ -177,6 +177,19 @@ public abstract class AbstractModel1Test extends AbstractTopologyTest
return node;
}
+ protected void createTree(ExtendedNode root, int levels, int children)
+ {
+ String name = root.getStringFeature();
+ for (int i = 0; i < children; i++)
+ {
+ ExtendedNode child = createExtended(name + (i + 1), root);
+ if (levels > 1)
+ {
+ createTree(child, levels - 1, children);
+ }
+ }
+ }
+
protected TreeNode findChild(String name, TreeNode parent)
{
return findNode(name, parent.getChildren());
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/model1/AllTests.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/model1/AllTests.java
index 4b5fdd1..d8c894b 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/model1/AllTests.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/model1/AllTests.java
@@ -28,7 +28,9 @@ public class AllTests
suite.addTestSuite(XRefsTest.class);
suite.addTestSuite(ExtentTest.class);
suite.addTestSuite(OCLTest.class);
+ suite.addTestSuite(BidiReferencesTest.class);
suite.addTestSuite(Bugzilla154389Test.class);
+ suite.addTestSuite(Bugzilla155899Test.class);
return suite;
}
}
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/model1/BidiReferencesTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/model1/BidiReferencesTest.java
new file mode 100644
index 0000000..5610756
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/model1/BidiReferencesTest.java
@@ -0,0 +1,283 @@
+/***************************************************************************
+ * Copyright (c) 2004, 2005, 2006 Eike Stepper, Germany.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ **************************************************************************/
+package org.eclipse.emf.cdo.tests.model1;
+
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+
+import testmodel1.ExtendedNode;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+
+public class BidiReferencesTest extends AbstractModel1Test
+{
+ private static final int LEVELS = 3;
+
+ private static final int CHILDREN = 4;
+
+ private static final int NODECOUNT = getNodeCount(LEVELS, CHILDREN);
+
+ private static final int CHILDCOUNT = NODECOUNT - 1;
+
+ public void testBasicTree() throws Exception
+ {
+ ExtendedNode created = createExtended("node");
+ createTree(created, LEVELS, CHILDREN);
+ saveRoot(created, "/test/resource");
+
+ ExtendedNode loaded = (ExtendedNode) loadRoot("/test/resource");
+ assertTree("node", loaded, LEVELS, CHILDREN);
+
+ assertEquals(1, jdbc().queryForInt("SELECT COUNT(*) FROM CDO_RESOURCE"));
+ assertEquals(NODECOUNT, jdbc().queryForInt("SELECT COUNT(*) FROM CDO_OBJECT"));
+ assertEquals(NODECOUNT, jdbc().queryForInt("SELECT COUNT(*) FROM EXTENDED_NODE"));
+ assertEquals(CHILDCOUNT * 2, jdbc().queryForInt("SELECT COUNT(*) FROM CDO_REFERENCE"));
+ assertEquals(CHILDCOUNT, jdbc().queryForInt("SELECT COUNT(*) FROM CDO_REFERENCE WHERE CONTENT"));
+ }
+
+ public void testBasicBidis() throws Exception
+ {
+ ExtendedNode created = createExtended("node");
+ createTree(created, LEVELS, CHILDREN);
+ createBidi(created, "111", "211");
+ createBidi(created, "111", "212");
+ createBidi(created, "111", "213");
+ createBidi(created, "111", "311");
+ createBidi(created, "111", "312");
+ createBidi(created, "111", "313");
+ saveRoot(created, "/test/resource");
+
+ ExtendedNode loaded = (ExtendedNode) loadRoot("/test/resource");
+ assertTree("node", loaded, LEVELS, CHILDREN);
+ assertBidi(loaded, "111", "211");
+ assertBidi(loaded, "111", "212");
+ assertBidi(loaded, "111", "213");
+ assertBidi(loaded, "111", "311");
+ assertBidi(loaded, "111", "312");
+ assertBidi(loaded, "111", "313");
+
+ assertEquals(1, jdbc().queryForInt("SELECT COUNT(*) FROM CDO_RESOURCE"));
+ assertEquals(NODECOUNT, jdbc().queryForInt("SELECT COUNT(*) FROM CDO_OBJECT"));
+ assertEquals(NODECOUNT, jdbc().queryForInt("SELECT COUNT(*) FROM EXTENDED_NODE"));
+ assertEquals(CHILDCOUNT * 2 + 6 * 2, jdbc().queryForInt("SELECT COUNT(*) FROM CDO_REFERENCE"));
+ assertEquals(CHILDCOUNT, jdbc().queryForInt("SELECT COUNT(*) FROM CDO_REFERENCE WHERE CONTENT"));
+ }
+
+ public void testDetachCount() throws Exception
+ {
+ ExtendedNode created = createExtended("node"); // root node
+ createTree(created, LEVELS, CHILDREN); // tree of degree 4, height = root + 3
+ saveRoot(created, "/test/resource"); // commit
+ int expected = NODECOUNT;
+ assertEquals(expected, getNodeCount(created));
+ created.cdoGetResource().getResourceManager().stop();
+
+ ExtendedNode loaded = (ExtendedNode) loadRoot("/test/resource"); // load another copy
+ assertEquals(expected, getNodeCount(loaded));
+ detachNode(loaded, "211"); // delete a leaf node
+ loaded.eResource().save(null); // commit
+ expected -= 1;
+ assertEquals(expected, getNodeCount(loaded));
+
+ detachNode(loaded, "4"); // delete a subtree
+ loaded.eResource().save(null); // commit
+ expected -= getNodeCount(LEVELS - 1, CHILDREN);
+ assertEquals(expected, getNodeCount(loaded));
+ }
+
+ public void testDetachWithoutBidi() throws Exception
+ {
+ ExtendedNode created = createExtended("node"); // root node
+ createTree(created, LEVELS, CHILDREN); // tree of degree 4, height = root + 3
+ saveRoot(created, "/test/resource"); // commit
+ int refs = CHILDCOUNT * 2; // expect num of refs = 2 per child
+ assertEquals(refs, jdbc().queryForInt("SELECT COUNT(*) FROM CDO_REFERENCE"));
+ created.cdoGetResource().getResourceManager().stop();
+
+ ExtendedNode loaded = (ExtendedNode) loadRoot("/test/resource"); // load another copy
+ detachNode(loaded, "211"); // delete a leaf node
+ loaded.eResource().save(null); // commit
+ refs -= 2; // expect -2 containment refs
+ assertEquals(refs, jdbc().queryForInt("SELECT COUNT(*) FROM CDO_REFERENCE"));
+
+ detachNode(loaded, "4"); // delete a subtree
+ loaded.eResource().save(null); // commit
+ refs -= getNodeCount(LEVELS - 1, CHILDREN) * 2;
+ assertEquals(refs, jdbc().queryForInt("SELECT COUNT(*) FROM CDO_REFERENCE"));
+ }
+
+ public void testDetachWithBidiSimple() throws Exception
+ {
+ ExtendedNode node = createExtended("node"); // root node
+ ExtendedNode node1 = createExtended("node1", node); // child node 1
+ ExtendedNode node2 = createExtended("node2", node); // child node 2
+
+ saveRoot(node, "/test/resource"); // commit
+ assertEquals(4, jdbc().queryForInt("SELECT COUNT(*) FROM CDO_REFERENCE"));
+
+ node1.getBidiSource().add(node2);
+ node.eResource().save(null); // commit
+ assertEquals(6, jdbc().queryForInt("SELECT COUNT(*) FROM CDO_REFERENCE"));
+
+ node.getChildren().remove(node1);
+ EList bidiTarget = node2.getBidiTarget();
+ assertTrue(bidiTarget.isEmpty());
+ node.eResource().save(null); // commit
+ assertEquals(2, jdbc().queryForInt("SELECT COUNT(*) FROM CDO_REFERENCE"));
+ }
+
+ public void testDetachWithBidi() throws Exception
+ {
+ ExtendedNode created = createExtended("node"); // root node
+ createTree(created, LEVELS, CHILDREN); // tree of degree 4, height = root + 3
+ saveRoot(created, "/test/resource"); // commit
+ int refs = CHILDCOUNT * 2; // expect num of refs = 2 per child
+ assertEquals(refs, jdbc().queryForInt("SELECT COUNT(*) FROM CDO_REFERENCE"));
+
+ // create 12 bidi refs
+ createBidi(created, "111", "211");
+ createBidi(created, "111", "212");
+ createBidi(created, "111", "213");
+ createBidi(created, "111", "214");
+ createBidi(created, "111", "311");
+ createBidi(created, "111", "312");
+ createBidi(created, "111", "313");
+ createBidi(created, "111", "314");
+ createBidi(created, "111", "411");
+ createBidi(created, "111", "412");
+ createBidi(created, "111", "413");
+ createBidi(created, "111", "414");
+ created.eResource().save(null); // commit
+ refs += 12 * 2; // expect 24 additional refs
+ assertEquals(refs, jdbc().queryForInt("SELECT COUNT(*) FROM CDO_REFERENCE"));
+ created.cdoGetResource().getResourceManager().stop();
+
+ ExtendedNode loaded = (ExtendedNode) loadRoot("/test/resource"); // load another copy
+ detachNode(loaded, "211"); // delete a leaf node with 1 bidi ref
+ loaded.eResource().save(null); // commit
+ refs -= 2 + 2; // expect -2 containment refs, -2 bidi refs
+ assertEquals(refs, jdbc().queryForInt("SELECT COUNT(*) FROM CDO_REFERENCE"));
+ }
+
+ public void testRemoveBidi() throws Exception
+ {
+ ExtendedNode created = createExtended("node"); // root node
+ createTree(created, LEVELS, CHILDREN); // tree of degree 4, height = root + 3
+ saveRoot(created, "/test/resource"); // commit
+ int refs = CHILDCOUNT * 2; // expect num of refs = 2 per child
+ assertEquals(refs, jdbc().queryForInt("SELECT COUNT(*) FROM CDO_REFERENCE"));
+
+ // create 12 bidi refs
+ createBidi(created, "111", "211");
+ createBidi(created, "111", "212");
+ createBidi(created, "111", "213");
+ createBidi(created, "111", "214");
+ createBidi(created, "111", "311");
+ createBidi(created, "111", "312");
+ createBidi(created, "111", "313");
+ createBidi(created, "111", "314");
+ createBidi(created, "111", "411");
+ createBidi(created, "111", "412");
+ createBidi(created, "111", "413");
+ createBidi(created, "111", "414");
+ created.eResource().save(null); // commit
+ refs += 12 * 2; // expect 24 additional refs
+ assertEquals(refs, jdbc().queryForInt("SELECT COUNT(*) FROM CDO_REFERENCE"));
+ created.cdoGetResource().getResourceManager().stop();
+
+ ExtendedNode loaded = (ExtendedNode) loadRoot("/test/resource"); // load another copy
+ ExtendedNode node211 = findPath(loaded, "211");
+ node211.getBidiSource().clear();
+ loaded.eResource().save(null); // commit
+ refs -= 2; // expect -2 bidi refs
+ assertEquals(refs, jdbc().queryForInt("SELECT COUNT(*) FROM CDO_REFERENCE"));
+ }
+
+ private void detachNode(ExtendedNode root, String path)
+ {
+ ExtendedNode node = findPath(root, path);
+ EList children = node.getParent().getChildren();
+ int size = children.size();
+ children.remove(node);
+ assertEquals(size - 1, children.size());
+ }
+
+ private void createBidi(ExtendedNode root, String path1, String path2)
+ {
+ ExtendedNode src = findPath(root, path1);
+ ExtendedNode dst = findPath(root, path2);
+ dst.getBidiSource().add(src);
+ }
+
+ private void assertBidi(ExtendedNode root, String path1, String path2)
+ {
+ ExtendedNode src = findPath(root, path1);
+ ExtendedNode dst = findPath(root, path2);
+ assertTrue(dst.getBidiSource().contains(src));
+ assertTrue(src.getBidiTarget().contains(dst));
+ }
+
+ private ExtendedNode findPath(ExtendedNode root, String path)
+ {
+ String name = "node";
+ List<String> list = new ArrayList<String>();
+ for (int i = 0; i < path.length(); i++)
+ {
+ name += path.charAt(i);
+ list.add(name);
+ }
+
+ return (ExtendedNode) findPath(list.toArray(new String[list.size()]), root);
+ }
+
+ private void assertTree(String name, ExtendedNode root, int levels, int children)
+ {
+ assertNode(name, root);
+ if (levels > 1)
+ {
+ assertEquals(children, root.getChildren().size());
+ for (int i = 0; i < children; i++)
+ {
+ assertTree(name + (i + 1), (ExtendedNode) root.getChildren().get(i), levels - 1, children);
+ }
+ }
+ }
+
+ private static int getNodeCount(EObject root)
+ {
+ int count = 1;
+ for (Iterator it = EcoreUtil.getAllContents(root, true); it.hasNext();)
+ {
+ it.next();
+ ++count;
+ }
+
+ return count;
+ }
+
+ private static int getNodeCount(int levels, int children)
+ {
+ int level = children;
+ int result = level;
+ for (int i = 1; i < levels; i++)
+ {
+ level *= children;
+ result += level;
+ }
+
+ return result + 1;
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/topology/AbstractTopologyTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/topology/AbstractTopologyTest.java
index fb665ea..f6ae274 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/topology/AbstractTopologyTest.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/topology/AbstractTopologyTest.java
@@ -80,7 +80,7 @@ public abstract class AbstractTopologyTest extends TestCase implements ITopology
@Override
protected void tearDown() throws Exception
{
- JdbcTemplate jdbc = getJdbcTemplate();
+ JdbcTemplate jdbc = jdbc();
wipeDatabase(jdbc);
topology.stop();
@@ -140,7 +140,7 @@ public abstract class AbstractTopologyTest extends TestCase implements ITopology
return topology.getDataSource();
}
- protected JdbcTemplate getJdbcTemplate()
+ protected JdbcTemplate jdbc()
{
return new JdbcTemplate(getDataSource());
}
diff --git a/plugins/org.eclipse.net4j.util/config/.cvsignore b/plugins/org.eclipse.net4j.util/config/.cvsignore
new file mode 100644
index 0000000..4dad498
--- /dev/null
+++ b/plugins/org.eclipse.net4j.util/config/.cvsignore
@@ -0,0 +1 @@
+log4j-user.xml
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/Net4jUtilPlugin.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/Net4jUtilPlugin.java
index 6115ab6..0be9a1d 100644
--- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/Net4jUtilPlugin.java
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/Net4jUtilPlugin.java
@@ -57,10 +57,13 @@ public class Net4jUtilPlugin extends AbstractPlugin
{
try
{
- URL pluginURL = getBundle().getEntry("/config/log4j.xml");
- URL absoluteURL = FileLocator.toFileURL(pluginURL);
+ URL pluginURL = getBundle().getEntry("/config/log4j-user.xml");
+ if (pluginURL == null)
+ {
+ pluginURL = getBundle().getEntry("/config/log4j.xml");
+ }
- DOMConfigurator.configure(absoluteURL);
+ DOMConfigurator.configure(FileLocator.toFileURL(pluginURL));
}
catch (Exception ex)
{