/* | |
* Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. | |
* 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: | |
* Simon McDuff - initial API and implementation | |
* Eike Stepper - maintenance | |
*/ | |
package org.eclipse.emf.cdo.tests; | |
import org.eclipse.emf.cdo.common.id.CDOID; | |
import org.eclipse.emf.cdo.common.revision.CDORevision; | |
import org.eclipse.emf.cdo.common.revision.CDORevisionUtil; | |
import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta; | |
import org.eclipse.emf.cdo.common.revision.delta.CDOClearFeatureDelta; | |
import org.eclipse.emf.cdo.common.revision.delta.CDOListFeatureDelta; | |
import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; | |
import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta; | |
import org.eclipse.emf.cdo.eresource.CDOResource; | |
import org.eclipse.emf.cdo.internal.common.revision.delta.CDOListFeatureDeltaImpl; | |
import org.eclipse.emf.cdo.internal.server.mem.MEMStore; | |
import org.eclipse.emf.cdo.server.IStore; | |
import org.eclipse.emf.cdo.session.CDOSession; | |
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; | |
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager; | |
import org.eclipse.emf.cdo.tests.model1.Category; | |
import org.eclipse.emf.cdo.tests.model1.Company; | |
import org.eclipse.emf.cdo.tests.model1.Customer; | |
import org.eclipse.emf.cdo.tests.model1.SalesOrder; | |
import org.eclipse.emf.cdo.tests.model3.NodeD; | |
import org.eclipse.emf.cdo.transaction.CDOTransaction; | |
import org.eclipse.emf.cdo.util.CDOUtil; | |
import org.eclipse.emf.cdo.util.CommitException; | |
import org.eclipse.emf.cdo.view.CDOView; | |
import org.eclipse.net4j.util.WrappedException; | |
import org.eclipse.net4j.util.io.IOUtil; | |
import org.eclipse.emf.common.util.BasicEList; | |
import org.eclipse.emf.common.util.EList; | |
import org.eclipse.emf.ecore.EObject; | |
import org.eclipse.emf.ecore.EStructuralFeature; | |
import org.eclipse.emf.spi.cdo.InternalCDOTransaction; | |
/** | |
* See bug 201266 | |
* | |
* @author Simon McDuff | |
*/ | |
public class RevisionDeltaTest extends AbstractCDOTest | |
{ | |
public RevisionDeltaTest() | |
{ | |
} | |
public void testBasicRevisionDelta() throws Exception | |
{ | |
CDOSession session = openSession(); | |
CDOTransaction transaction = session.openTransaction(); | |
CDOResource resource1 = transaction.createResource(getResourcePath("/test1")); | |
Company company1 = getModel1Factory().createCompany(); | |
Category category1 = getModel1Factory().createCategory(); | |
resource1.getContents().add(company1); | |
company1.getCategories().add(category1); | |
company1.setName("TEST"); | |
InternalCDORevision rev1 = getCopyCDORevision(company1); | |
// Test simple attributes | |
company1.setName("TEST3"); | |
InternalCDORevision rev2 = getCopyCDORevision(company1); | |
CDORevisionDelta revisionDelta = rev2.compare(rev1); | |
assertEquals(1, revisionDelta.getFeatureDeltas().size()); | |
CDOSetFeatureDelta setDelta = (CDOSetFeatureDelta)revisionDelta.getFeatureDeltas().get(0); | |
assertEquals("TEST3", setDelta.getValue()); | |
// Test List clear | |
company1.getCategories().clear(); | |
InternalCDORevision rev3 = getCopyCDORevision(company1); | |
CDORevisionDelta revisionDelta3 = rev3.compare(rev2); | |
assertEquals(1, revisionDelta3.getFeatureDeltas().size()); | |
CDOListFeatureDeltaImpl delta3List = (CDOListFeatureDeltaImpl)revisionDelta3.getFeatureDeltas().get(0); | |
assertEquals(1, delta3List.getListChanges().size()); | |
assertEquals(true, delta3List.getListChanges().get(0) instanceof CDOClearFeatureDelta); | |
// Test List Add | |
for (int i = 0; i < 5; i++) | |
{ | |
Category category = getModel1Factory().createCategory(); | |
company1.getCategories().add(category); | |
} | |
InternalCDORevision rev4 = getCopyCDORevision(company1); | |
CDORevisionDelta revisionDelta4 = rev4.compare(rev3); | |
assertEquals(1, revisionDelta4.getFeatureDeltas().size()); | |
CDOListFeatureDeltaImpl delta4List = (CDOListFeatureDeltaImpl)revisionDelta4.getFeatureDeltas().get(0); | |
assertEquals(5, delta4List.getListChanges().size()); | |
assertEquals(true, delta4List.getListChanges().get(0) instanceof CDOAddFeatureDelta); | |
transaction.rollback(); | |
transaction.close(); | |
session.close(); | |
} | |
/** | |
* Sending deltas doesn't adjust CDOIDs | |
* <p> | |
* See bug 214374 | |
*/ | |
public void testBugzilla214374() throws Exception | |
{ | |
CDOSession session = openSession(); | |
CDOTransaction transaction = session.openTransaction(); | |
CDOResource resource = transaction.createResource(getResourcePath("/test1")); | |
SalesOrder salesOrder = getModel1Factory().createSalesOrder(); | |
resource.getContents().add(salesOrder); | |
transaction.commit(); | |
Customer customer = getModel1Factory().createCustomer(); | |
salesOrder.setCustomer(customer); | |
resource.getContents().add(customer); | |
transaction.commit(); | |
transaction.close(); | |
CDOTransaction transaction2 = session.openTransaction(); | |
SalesOrder salesOrder2 = (SalesOrder)CDOUtil.getEObject(transaction2.getObject(CDOUtil.getCDOObject(salesOrder) | |
.cdoID(), true)); | |
CDORevision salesRevision = CDOUtil.getCDOObject(salesOrder2).cdoRevision(); | |
EStructuralFeature customerFeature = getModel1Package().getSalesOrder_Customer(); | |
Object value = salesRevision.data().get(customerFeature, 0); | |
assertEquals(true, value instanceof CDOID); | |
transaction2.close(); | |
session.close(); | |
} | |
/** | |
* CDOView.getRevision() does not work for transactions/dirty objects (INVALID) | |
* <p> | |
* See bug 214431 | |
*/ | |
public void testBugzilla214431() throws Exception | |
{ | |
CDOSession session = openSession(); | |
CDOTransaction transaction = session.openTransaction(); | |
CDOResource resource = transaction.createResource(getResourcePath("/test1")); | |
SalesOrder salesOrder = getModel1Factory().createSalesOrder(); | |
resource.getContents().add(salesOrder); | |
transaction.commit(); | |
salesOrder.setId(4711); | |
assertNotSame(CDOUtil.getCDOObject(salesOrder).cdoRevision(), | |
((InternalCDOTransaction)transaction).getRevision(CDOUtil.getCDOObject(salesOrder).cdoID(), true)); | |
assertEquals(CDOUtil.getCDOObject(salesOrder).cdoRevision(), | |
transaction.getDirtyObjects().get(CDOUtil.getCDOObject(salesOrder).cdoID()).cdoRevision()); | |
transaction.close(); | |
session.close(); | |
} | |
/** | |
* CDOView.getRevision() does not work for transactions/dirty objects (INVALID) | |
* <p> | |
* See bug 214374 | |
*/ | |
public void testBugzilla214374_HandleClear() throws Exception | |
{ | |
CDOSession session = openSession(); | |
CDOTransaction transaction = session.openTransaction(); | |
CDOResource resource = transaction.createResource(getResourcePath("/test1")); | |
Customer customer = getModel1Factory().createCustomer(); | |
resource.getContents().add(customer); | |
SalesOrder salesOrder = getModel1Factory().createSalesOrder(); | |
resource.getContents().add(salesOrder); | |
customer.getSalesOrders().add(salesOrder); | |
customer.getSalesOrders().add(salesOrder); | |
transaction.commit(); | |
salesOrder = getModel1Factory().createSalesOrder(); | |
customer = getModel1Factory().createCustomer(); | |
resource.getContents().add(salesOrder); | |
resource.getContents().add(customer); | |
salesOrder.setCustomer(customer); | |
transaction.commit(); | |
transaction.close(); | |
session.close(); | |
} | |
/** | |
* java.lang.IllegalStateException with MEMStore | |
* <p> | |
* See bug 243282 | |
*/ | |
public void testBugzilla243282_Exception() throws Exception | |
{ | |
CDOSession session = openSession(); | |
CDOTransaction transaction = session.openTransaction(); | |
CDOResource resource = transaction.createResource(getResourcePath("/test1")); | |
Customer customer = getModel1Factory().createCustomer(); | |
resource.getContents().add(customer); | |
transaction.commit(); | |
InternalCDORevisionManager revisionManager = getRepository().getRevisionManager(); | |
CDORevision revision = CDOUtil.getCDOObject(customer).cdoRevision(); | |
revisionManager.getCache().removeRevision(revision.getID(), revision); | |
SalesOrder salesOrder = getModel1Factory().createSalesOrder(); | |
resource.getContents().add(salesOrder); | |
customer.getSalesOrders().add(salesOrder); | |
IStore store = getRepository().getStore(); | |
if (store instanceof MEMStore) | |
{ | |
MEMStore memStore = (MEMStore)store; | |
CDORevisionUtil.dumpAllRevisions(memStore.getAllRevisions(), IOUtil.OUT()); | |
} | |
transaction.commit(); | |
transaction.close(); | |
session.close(); | |
} | |
@SuppressWarnings("unused") | |
public void testDetachWithXRef() throws Exception | |
{ | |
CDOSession session = openSession(); | |
CDOTransaction transaction = session.openTransaction(); | |
CDOResource resource = transaction.createResource(getResourcePath("/test1")); | |
NodeD a = getModel3Factory().createNodeD(); | |
NodeD b = getModel3Factory().createNodeD(); | |
NodeD c = getModel3Factory().createNodeD(); | |
a.getChildren().add(b); | |
c.getOtherNodes().add(b); | |
resource.getContents().add(a); | |
resource.getContents().add(c); | |
if (true) | |
{ | |
transaction.commit(); | |
transaction.close(); | |
transaction = session.openTransaction(); | |
resource = transaction.getResource(getResourcePath("/test1")); | |
} | |
// Start test logic | |
a = (NodeD)resource.getContents().get(0); | |
b = a.getChildren().get(0); | |
c = (NodeD)resource.getContents().get(1); | |
a.getChildren().remove(0); | |
Object[] cB = c.getOtherNodes().toArray(); | |
CDORevisionDelta aDelta = transaction.getRevisionDeltas().get(CDOUtil.getCDOObject(a).cdoID()); | |
CDORevisionDelta cDelta = transaction.getRevisionDeltas().get(CDOUtil.getCDOObject(c).cdoID()); | |
session.close(); | |
} | |
@SuppressWarnings("unused") | |
public void testDetachWithXRef_Remove() throws Exception | |
{ | |
CDOSession session = openSession(); | |
CDOTransaction transaction = session.openTransaction(); | |
CDOResource resource = transaction.createResource(getResourcePath("/test1")); | |
NodeD a = getModel3Factory().createNodeD(); | |
NodeD b = getModel3Factory().createNodeD(); | |
NodeD c = getModel3Factory().createNodeD(); | |
a.getChildren().add(b); | |
c.getOtherNodes().add(b); | |
resource.getContents().add(a); | |
resource.getContents().add(c); | |
if (true) | |
{ | |
transaction.commit(); | |
transaction.close(); | |
transaction = session.openTransaction(); | |
resource = transaction.getResource(getResourcePath("/test1")); | |
} | |
// Start test logic | |
a = (NodeD)resource.getContents().get(0); | |
b = a.getChildren().get(0); | |
c = (NodeD)resource.getContents().get(1); | |
a.getChildren().remove(0); | |
c.getOtherNodes().remove(0); | |
Object[] cB = c.getOtherNodes().toArray(); | |
CDORevisionDelta aDelta = transaction.getRevisionDeltas().get(CDOUtil.getCDOObject(a).cdoID()); | |
CDORevisionDelta cDelta = transaction.getRevisionDeltas().get(CDOUtil.getCDOObject(c).cdoID()); | |
CDOListFeatureDelta list = (CDOListFeatureDelta)cDelta.getFeatureDelta(getModel3Package().getNodeD_OtherNodes()); | |
assertEquals(1, list.getListChanges().size()); | |
session.close(); | |
} | |
public void testListRemoveMiddle() | |
{ | |
testStoreDelta(new ListManipulator() | |
{ | |
public void doManipulations(EList<?> list) | |
{ | |
list.remove(5); | |
} | |
}); | |
} | |
public void testListRemoveLast() | |
{ | |
testStoreDelta(new ListManipulator() | |
{ | |
public void doManipulations(EList<?> list) | |
{ | |
list.remove(list.size() - 1); | |
} | |
}); | |
} | |
public void testListRemoveFirst() | |
{ | |
testStoreDelta(new ListManipulator() | |
{ | |
public void doManipulations(EList<?> list) | |
{ | |
list.remove(0); | |
} | |
}); | |
} | |
public void testListSimpleMove() | |
{ | |
testStoreDelta(new ListManipulator() | |
{ | |
public void doManipulations(EList<?> list) | |
{ | |
list.move(2, 7); | |
} | |
}); | |
} | |
public void testListMoveToLast() | |
{ | |
testStoreDelta(new ListManipulator() | |
{ | |
public void doManipulations(EList<?> list) | |
{ | |
list.move(2, list.size() - 1); | |
} | |
}); | |
} | |
public void testListMoveToFirst() | |
{ | |
testStoreDelta(new ListManipulator() | |
{ | |
public void doManipulations(EList<?> list) | |
{ | |
list.move(2, 0); | |
} | |
}); | |
} | |
public void testListTwoIndependentMoves() | |
{ | |
testStoreDelta(new ListManipulator() | |
{ | |
public void doManipulations(EList<?> list) | |
{ | |
list.move(1, 3); | |
list.move(7, 4); | |
} | |
}); | |
} | |
public void testListTwoIntersectingMoves() | |
{ | |
testStoreDelta(new ListManipulator() | |
{ | |
public void doManipulations(EList<?> list) | |
{ | |
list.move(1, 7); | |
list.move(3, 4); | |
} | |
}); | |
} | |
public void testListInsertFirst() | |
{ | |
testStoreDelta(new ListManipulator() | |
{ | |
@SuppressWarnings("unchecked") | |
public void doManipulations(EList<?> list) | |
{ | |
EList<Company> l = (EList<Company>)list; | |
Company company = getModel1Factory().createCompany(); | |
company.setName("NewEntry"); | |
l.add(0, company); | |
} | |
}); | |
} | |
public void testListInsertMiddle() | |
{ | |
testStoreDelta(new ListManipulator() | |
{ | |
@SuppressWarnings("unchecked") | |
public void doManipulations(EList<?> list) | |
{ | |
EList<Company> l = (EList<Company>)list; | |
Company company = getModel1Factory().createCompany(); | |
company.setName("NewEntry"); | |
l.add(5, company); | |
} | |
}); | |
} | |
public void testListInsertLast() | |
{ | |
testStoreDelta(new ListManipulator() | |
{ | |
@SuppressWarnings("unchecked") | |
public void doManipulations(EList<?> list) | |
{ | |
EList<Company> l = (EList<Company>)list; | |
Company company = getModel1Factory().createCompany(); | |
company.setName("NewEntry"); | |
l.add(company); | |
} | |
}); | |
} | |
public void testListMultipleOpsWithClear() | |
{ | |
testStoreDelta(new ListManipulator() | |
{ | |
@SuppressWarnings("unchecked") | |
public void doManipulations(EList<?> list) | |
{ | |
EList<Company> l = (EList<Company>)list; | |
l.remove(4); | |
l.remove(7); | |
Company company = getModel1Factory().createCompany(); | |
company.setName("NewEntry 1"); | |
l.add(5, company); | |
l.move(1, 2); | |
l.move(7, 0); | |
l.clear(); | |
company = getModel1Factory().createCompany(); | |
company.setName("NewEntry 2"); | |
l.add(company); | |
company = getModel1Factory().createCompany(); | |
company.setName("NewEntry 3"); | |
l.add(company); | |
company = getModel1Factory().createCompany(); | |
company.setName("NewEntry 4"); | |
l.add(0, company); | |
l.move(1, 2); | |
} | |
}); | |
} | |
public void testListMultipleOps() | |
{ | |
testStoreDelta(new ListManipulator() | |
{ | |
@SuppressWarnings("unchecked") | |
public void doManipulations(EList<?> list) | |
{ | |
EList<Company> l = (EList<Company>)list; | |
l.remove(7); | |
Company company = getModel1Factory().createCompany(); | |
company.setName("NewEntry 1"); | |
l.add(5, company); | |
l.move(1, 2); | |
company = getModel1Factory().createCompany(); | |
company.setName("NewEntry 2"); | |
l.add(company); | |
l.move(7, 0); | |
company = getModel1Factory().createCompany(); | |
company.setName("NewEntry 3"); | |
l.add(company); | |
l.remove(4); | |
company = getModel1Factory().createCompany(); | |
company.setName("NewEntry 4"); | |
l.add(0, company); | |
l.move(1, 2); | |
} | |
}); | |
} | |
public void testMultipleInserts() | |
{ | |
testStoreDelta(new ListManipulator() | |
{ | |
@SuppressWarnings("unchecked") | |
public void doManipulations(EList<?> list) | |
{ | |
EList<Company> l = (EList<Company>)list; | |
Company company = getModel1Factory().createCompany(); | |
company.setName("NewEntry 1"); | |
l.add(7, company); | |
company = getModel1Factory().createCompany(); | |
company.setName("NewEntry 2"); | |
l.add(12, company); | |
} | |
}); | |
} | |
public void testInsertAndRemove() | |
{ | |
testStoreDelta(new ListManipulator() | |
{ | |
@SuppressWarnings("unchecked") | |
public void doManipulations(EList<?> list) | |
{ | |
EList<Company> l = (EList<Company>)list; | |
Company company = getModel1Factory().createCompany(); | |
company.setName("NewEntry 1"); | |
l.add(7, company); | |
l.remove(12); | |
} | |
}); | |
} | |
public void testInsertAndMove() | |
{ | |
testStoreDelta(new ListManipulator() | |
{ | |
@SuppressWarnings("unchecked") | |
public void doManipulations(EList<?> list) | |
{ | |
EList<Company> l = (EList<Company>)list; | |
Company company = getModel1Factory().createCompany(); | |
company.setName("NewEntry 1"); | |
l.add(7, company); | |
l.move(12, 7); | |
} | |
}); | |
} | |
public void testMoveAndDelete() | |
{ | |
testStoreDelta(new ListManipulator() | |
{ | |
@SuppressWarnings("unchecked") | |
public void doManipulations(EList<?> list) | |
{ | |
EList<Company> l = (EList<Company>)list; | |
l.move(12, 7); | |
l.remove(12); | |
} | |
}); | |
} | |
public void testInsertAndMoveAndRemove() | |
{ | |
testStoreDelta(new ListManipulator() | |
{ | |
@SuppressWarnings("unchecked") | |
public void doManipulations(EList<?> list) | |
{ | |
EList<Company> l = (EList<Company>)list; | |
Company company = getModel1Factory().createCompany(); | |
company.setName("NewEntry 1"); | |
l.add(7, company); | |
l.move(12, 7); | |
l.remove(12); | |
} | |
}); | |
} | |
public void testInsertAndSet() | |
{ | |
testStoreDelta(new ListManipulator() | |
{ | |
@SuppressWarnings("unchecked") | |
public void doManipulations(EList<?> list) | |
{ | |
EList<Company> l = (EList<Company>)list; | |
Company company = getModel1Factory().createCompany(); | |
company.setName("NewEntry 1"); | |
l.add(7, company); | |
Company company2 = getModel1Factory().createCompany(); | |
company2.setName("NewEntry 2"); | |
l.set(7, company2); | |
l.add(19, company); // <- needed because the set operation makes the company a dangling reference | |
} | |
}); | |
} | |
public void testSetAndRemove() | |
{ | |
testStoreDelta(new ListManipulator() | |
{ | |
@SuppressWarnings("unchecked") | |
public void doManipulations(EList<?> list) | |
{ | |
EList<Company> l = (EList<Company>)list; | |
Company company = getModel1Factory().createCompany(); | |
company.setName("NewEntry 1"); | |
Company oldCompany = l.get(7); | |
l.set(7, company); | |
l.add(19, oldCompany); | |
l.remove(7); // <- needed because the set operation makes the company a dangling reference | |
} | |
}); | |
} | |
public void testMultipleRemoves() | |
{ | |
testStoreDelta(new ListManipulator() | |
{ | |
@SuppressWarnings("unchecked") | |
public void doManipulations(EList<?> list) | |
{ | |
EList<Company> l = (EList<Company>)list; | |
l.remove(7); | |
l.remove(12); | |
} | |
}); | |
} | |
private InternalCDORevision getCopyCDORevision(Object object) | |
{ | |
return (InternalCDORevision)CDOUtil.getCDOObject((EObject)object).cdoRevision().copy(); | |
} | |
protected void testStoreDelta(ListManipulator manipulator) | |
{ | |
BasicEList<Company> reference = new BasicEList<Company>(); | |
{ | |
CDOSession session = openSession(); | |
CDOTransaction transaction = session.openTransaction(); | |
CDOResource resource = transaction.createResource(getResourcePath("/test1")); | |
for (int i = 0; i < 20; i++) | |
{ | |
String name = "company " + i; | |
Company company = getModel1Factory().createCompany(); | |
company.setName(name); | |
resource.getContents().add(company); | |
company = getModel1Factory().createCompany(); | |
company.setName(name); | |
reference.add(company); | |
} | |
try | |
{ | |
transaction.commit(); | |
} | |
catch (CommitException ex) | |
{ | |
throw WrappedException.wrap(ex); | |
} | |
transaction.close(); | |
session.close(); | |
} | |
clearCache(getRepository().getRevisionManager()); | |
{ | |
CDOSession session = openSession(); | |
CDOTransaction transaction = session.openTransaction(); | |
CDOResource resource = transaction.getResource(getResourcePath("/test1")); | |
manipulator.doManipulations(resource.getContents()); | |
manipulator.doManipulations(reference); | |
try | |
{ | |
transaction.commit(); | |
} | |
catch (CommitException ex) | |
{ | |
throw WrappedException.wrap(ex); | |
} | |
transaction.close(); | |
session.close(); | |
} | |
clearCache(getRepository().getRevisionManager()); | |
{ | |
CDOSession session = openSession(); | |
CDOView view = session.openView(); | |
CDOResource resource = view.getResource(getResourcePath("/test1")); | |
assertEquals(reference.size(), resource.getContents().size()); | |
for (int i = 0; i < reference.size(); i++) | |
{ | |
assertEquals(reference.get(i).getName(), ((Company)resource.getContents().get(i)).getName()); | |
} | |
view.close(); | |
session.close(); | |
} | |
} | |
/** | |
* @author Simon McDuff | |
*/ | |
protected static interface ListManipulator | |
{ | |
public void doManipulations(EList<?> list); | |
} | |
} |