From bf1c533eb3b25c5014f41e197e74fd402e7d9a35 Mon Sep 17 00:00:00 2001 From: Simon McDuff Date: Fri, 23 May 2008 17:20:50 +0000 Subject: [233277] Automatic link persistence objects together https://bugs.eclipse.org/bugs/show_bug.cgi?id=233277 --- .../eclipse/emf/cdo/tests/AutoAttacherTest.java | 103 ++++++++++++ .../emf/cdo/eresource/impl/CDOResourceImpl.java | 6 +- .../eclipse/emf/internal/cdo/CDOObjectImpl.java | 5 + .../eclipse/emf/internal/cdo/CDOStateMachine.java | 9 +- .../emf/internal/cdo/CDOTransactionImpl.java | 41 ++++- .../emf/internal/cdo/util/CDOAutoAttacher.java | 176 +++++++++++++++++++++ 6 files changed, 322 insertions(+), 18 deletions(-) create mode 100644 plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AutoAttacherTest.java create mode 100644 plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/CDOAutoAttacher.java diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AutoAttacherTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AutoAttacherTest.java new file mode 100644 index 0000000000..8633fb469a --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AutoAttacherTest.java @@ -0,0 +1,103 @@ +/*************************************************************************** + * Copyright (c) 2004 - 2008 Simon McDuff, Canada. + * 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 + **************************************************************************/ +package org.eclipse.emf.cdo.tests; + +import org.eclipse.emf.cdo.CDOSession; +import org.eclipse.emf.cdo.eresource.CDOResource; +import org.eclipse.emf.cdo.tests.model1.Model1Factory; +import org.eclipse.emf.cdo.tests.model1.Order; +import org.eclipse.emf.cdo.tests.model1.OrderDetail; +import org.eclipse.emf.cdo.tests.model1.Product; +import org.eclipse.emf.cdo.tests.model1.PurchaseOrder; +import org.eclipse.emf.cdo.tests.model1.Supplier; + +import org.eclipse.emf.internal.cdo.CDOTransactionImpl; +import org.eclipse.emf.internal.cdo.util.CDOAutoAttacher; + + +/** + * @author Simon McDuff + */ +public class AutoAttacherTest extends AbstractCDOTest +{ + + + public void testBasic() throws Exception + { + CDOSession session = openModel1Session(); + + CDOTransactionImpl transaction = (CDOTransactionImpl)session.openTransaction(); + + new CDOAutoAttacher(transaction); + + CDOResource resource1 = transaction.getOrCreateResource("/test1"); + + Product product = Model1Factory.eINSTANCE.createProduct(); + { + assertTransient(product); + + resource1.getContents().add(product); + assertEquals(resource1, product.eResource()); + //assertEquals(resource1, ((EObjectImpl)product).eDirectResource()); + + assertNew(product, transaction); + + } + + OrderDetail orderDetail = Model1Factory.eINSTANCE.createOrderDetail(); + { + assertTransient(orderDetail); + product.getOrderDetails().add(orderDetail); + assertNew(orderDetail, transaction); + } + + Order order = Model1Factory.eINSTANCE.createOrder(); + { + // Bidirectionnel/containment relationship + assertTransient(order); + // Fail for now. Need to be able to handle that case! + //order.getOrderDetails().add(orderDetail); + + //assertTransient(order); + } + + transaction.close(); + session.close(); + } + + public void testBasic2() throws Exception + { + CDOSession session = openModel1Session(); + + CDOTransactionImpl transaction = (CDOTransactionImpl)session.openTransaction(); + + new CDOAutoAttacher(transaction); + + CDOResource resource1 = transaction.getOrCreateResource("/test1"); + + Supplier supplier = Model1Factory.eINSTANCE.createSupplier(); + PurchaseOrder purchaseOrder = Model1Factory.eINSTANCE.createPurchaseOrder(); + + supplier.getPurchaseOrders().add(purchaseOrder); + + assertTransient(supplier); + + resource1.getContents().add(supplier); + + assertNew(supplier, transaction); + assertNew(purchaseOrder, transaction); + + + transaction.close(); + session.close(); + } + +} diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/eresource/impl/CDOResourceImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/eresource/impl/CDOResourceImpl.java index aef3dd435c..7544edbf78 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/eresource/impl/CDOResourceImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/eresource/impl/CDOResourceImpl.java @@ -434,7 +434,7 @@ public class CDOResourceImpl extends CDOObjectImpl implements CDOResource */ public void attached(EObject object) { - InternalCDOObject legacy = getLegacyWrapper(object); + /*InternalCDOObject legacy = getLegacyWrapper(object); if (legacy.cdoState() != CDOState.CLEAN) { CDOStateMachine.INSTANCE.attach(legacy, this, view); @@ -443,7 +443,7 @@ public class CDOResourceImpl extends CDOObjectImpl implements CDOResource // legacy.eBasicSetContainer(null, 0, null); // legacy.eSetResource(this, null); // } - } + }*/ } /** @@ -451,8 +451,10 @@ public class CDOResourceImpl extends CDOObjectImpl implements CDOResource */ public void detached(EObject object) { + /* InternalCDOObject legacy = getLegacyWrapper(object); CDOStateMachine.INSTANCE.detach(legacy); + */ } /** diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectImpl.java index 6bda90a614..a1d06f9673 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectImpl.java @@ -569,6 +569,11 @@ public class CDOObjectImpl extends EStoreEObjectImpl implements InternalCDOObjec { // Delegate to CDOStore getStore().setContainer(this, newContainer, newContainerFeatureID); + + if (newContainer instanceof Resource.Internal) + { + eSetDirectResource((Resource.Internal)newContainer); + } } } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOStateMachine.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOStateMachine.java index c7e6acd864..de9aa6013b 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOStateMachine.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOStateMachine.java @@ -504,14 +504,7 @@ public final class CDOStateMachine extends FiniteStateMachine map = object instanceof CDOResource ? transaction.getLastSavePoint() - .getNewResources() : transaction.getLastSavePoint().getNewObjects(); - - if (!map.containsKey(object.cdoID())) transaction.registerFeatureDelta(object, (CDOFeatureDelta)featureDelta); + transaction.registerFeatureDelta(object, (CDOFeatureDelta)featureDelta); } } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOTransactionImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOTransactionImpl.java index f8e45022de..7e0652a79c 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOTransactionImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOTransactionImpl.java @@ -495,21 +495,46 @@ public class CDOTransactionImpl extends CDOViewImpl implements CDOTransaction public void registerFeatureDelta(InternalCDOObject object, CDOFeatureDelta featureDelta) { - CDORevisionDelta revisionDelta = (CDORevisionDelta)lastSavePoint.getRevisionDeltas().get(object.cdoID()); - - if (revisionDelta == null) + boolean needToSaveFeatureDelta = true; + + if (object.cdoState() == CDOState.NEW) { - revisionDelta = (CDORevisionDelta)CDORevisionDeltaUtil.create(object.cdoRevision()); - lastSavePoint.getRevisionDeltas().put(object.cdoID(), revisionDelta); + // Register Delta for new objects only if objectA doesn't belong to this savepoint + if (this.getLastSavePoint().getPreviousSavePoint() == null || featureDelta == null) + { + needToSaveFeatureDelta = false; + } + else + { + Map map = object instanceof CDOResource ? this.getLastSavePoint() + .getNewResources() : this.getLastSavePoint().getNewObjects(); + + needToSaveFeatureDelta = !map.containsKey(object.cdoID()); + } } - - ((InternalCDORevisionDelta)revisionDelta).addFeatureDelta(featureDelta); + + if (needToSaveFeatureDelta) + { + CDORevisionDelta revisionDelta = (CDORevisionDelta)lastSavePoint.getRevisionDeltas().get(object.cdoID()); + + if (revisionDelta == null) + { + revisionDelta = (CDORevisionDelta)CDORevisionDeltaUtil.create(object.cdoRevision()); + lastSavePoint.getRevisionDeltas().put(object.cdoID(), revisionDelta); + } + + ((InternalCDORevisionDelta)revisionDelta).addFeatureDelta(featureDelta); + } + for (CDOTransactionHandler handler : getHandlers()) { handler.modifyingObject(this, object, featureDelta); } } - + + protected void fireEventRegisterDelta(InternalCDOObject object, CDOFeatureDelta featureDelta) + { + } public void registerRevisionDelta(CDORevisionDelta revisionDelta) { lastSavePoint.getRevisionDeltas().putIfAbsent(revisionDelta.getID(), revisionDelta); diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/CDOAutoAttacher.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/CDOAutoAttacher.java new file mode 100644 index 0000000000..20175c28ee --- /dev/null +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/CDOAutoAttacher.java @@ -0,0 +1,176 @@ +/*************************************************************************** + * Copyright (c) 2004 - 2008 Simon McDuff, Canada. + * 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 + **************************************************************************/package org.eclipse.emf.internal.cdo.util; + +import org.eclipse.emf.cdo.CDOObject; +import org.eclipse.emf.cdo.CDOTransaction; +import org.eclipse.emf.cdo.CDOTransactionHandler; +import org.eclipse.emf.cdo.eresource.CDOResource; +import org.eclipse.emf.cdo.protocol.revision.delta.CDOAddFeatureDelta; +import org.eclipse.emf.cdo.protocol.revision.delta.CDOClearFeatureDelta; +import org.eclipse.emf.cdo.protocol.revision.delta.CDOContainerFeatureDelta; +import org.eclipse.emf.cdo.protocol.revision.delta.CDOFeatureDelta; +import org.eclipse.emf.cdo.protocol.revision.delta.CDOFeatureDeltaVisitor; +import org.eclipse.emf.cdo.protocol.revision.delta.CDOListFeatureDelta; +import org.eclipse.emf.cdo.protocol.revision.delta.CDOMoveFeatureDelta; +import org.eclipse.emf.cdo.protocol.revision.delta.CDORemoveFeatureDelta; +import org.eclipse.emf.cdo.protocol.revision.delta.CDOSetFeatureDelta; +import org.eclipse.emf.cdo.protocol.revision.delta.CDOUnsetFeatureDelta; + +import org.eclipse.emf.internal.cdo.InternalCDOObject; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.resource.Resource; + +import java.util.List; +/** + * @author Simon McDuff + */ +public class CDOAutoAttacher implements CDOTransactionHandler +{ + CDOTransaction cdoTransaction; + + + + class CDOFeatureDeltaVisitorAutoAttach implements CDOFeatureDeltaVisitor + { + + Resource resource; + CDOFeatureDeltaVisitorAutoAttach(Resource resource) + { + this.resource = resource; + } + public void visit(CDOAddFeatureDelta featureChange) + { + persist(resource, featureChange.getValue()); + } + + public void visit(CDOClearFeatureDelta featureChange) + { + + } + + public void visit(CDOListFeatureDelta featureChange) + { + + } + + public void visit(CDOMoveFeatureDelta featureChange) + { + + } + + public void visit(CDORemoveFeatureDelta featureChange) + { + } + + public void visit(CDOSetFeatureDelta featureChange) + { + persist(resource, featureChange.getValue()); + } + + public void visit(CDOUnsetFeatureDelta featureChange) + { + } + + public void visit(CDOContainerFeatureDelta delta) + { + } + + }; + + public CDOAutoAttacher(CDOTransaction transaction) + { + this.cdoTransaction = transaction; + transaction.addHandler(this); + } + + protected void persist(Resource res, Object object) + { + if (object instanceof CDOResource) + return; + + if (!(object instanceof InternalCDOObject)) + return; + + res.getContents().add((InternalCDOObject)object); + } + + /** + * @param eObject + */ + private void handle(Resource resource, EObject eObject) + { + for (EReference reference : eObject.eClass().getEAllReferences()) + { + if (reference.isMany()) + { + List list = (List)eObject.eGet(reference); + for (EObject element : list) + { + if (element.eResource() == null) + { + if (reference.isContainment()) + handle(resource, element); + else + persist(resource, element); + } + } + } + else + { + EObject element = (EObject)eObject.eGet(reference); + + if (element != null && element.eResource() == null) + { + // objectsAdded.add(element); + if (reference.isContainment()) + handle(resource, element); + else + persist(resource, element); + } + } + } + + } + + public void addingObject(CDOTransaction transaction, CDOObject object) + { + if (object instanceof CDOResource) + return; + + // Persist the graph as well. + handle(object.eResource(), object); + } + + public void committingTransaction(CDOTransaction transaction) + { + + } + + public void modifyingObject(CDOTransaction transaction, CDOObject object, CDOFeatureDelta featureChange) + { + if (object instanceof CDOResource) + return; + + if (featureChange != null) + { + CDOFeatureDeltaVisitorAutoAttach featureChangeVisitor = new CDOFeatureDeltaVisitorAutoAttach( object.cdoResource()); + featureChange.accept(featureChangeVisitor); + } + + } + + public void rollingbackTransaction(CDOTransaction transaction) + { + } + +} -- cgit v1.2.3