Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 178678 Details for
Bug 312535
Partial commits
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read
this important communication.
[patch]
Patch v2 - ready to be committed
clipboard.txt (text/plain), 84.01 KB, created by
Eike Stepper
on 2010-09-11 06:26:59 EDT
(
hide
)
Description:
Patch v2 - ready to be committed
Filename:
MIME Type:
Creator:
Eike Stepper
Created:
2010-09-11 06:26:59 EDT
Size:
84.01 KB
patch
obsolete
>### Eclipse Workspace Patch 1.0 >#P org.eclipse.emf.cdo >Index: src/org/eclipse/emf/cdo/transaction/CDOCommitContext.java >=================================================================== >RCS file: /cvsroot/modeling/org.eclipse.emf/org.eclipse.emf.cdo/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOCommitContext.java,v >retrieving revision 1.7 >diff -u -r1.7 CDOCommitContext.java >--- src/org/eclipse/emf/cdo/transaction/CDOCommitContext.java 25 Feb 2010 10:33:19 -0000 1.7 >+++ src/org/eclipse/emf/cdo/transaction/CDOCommitContext.java 11 Sep 2010 10:26:24 -0000 >@@ -56,4 +56,9 @@ > * Returns a map of the {@link CDORevisionDelta revision deltas} that are to be committed with this commit context. > */ > public Map<CDOID, CDORevisionDelta> getRevisionDeltas(); >+ >+ /** >+ * @since 4.0 >+ */ >+ public boolean isPartialCommit(); > } >Index: src/org/eclipse/emf/cdo/transaction/CDOPushTransaction.java >=================================================================== >RCS file: /cvsroot/modeling/org.eclipse.emf/org.eclipse.emf.cdo/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOPushTransaction.java,v >retrieving revision 1.25 >diff -u -r1.25 CDOPushTransaction.java >--- src/org/eclipse/emf/cdo/transaction/CDOPushTransaction.java 4 Sep 2010 14:07:29 -0000 1.25 >+++ src/org/eclipse/emf/cdo/transaction/CDOPushTransaction.java 11 Sep 2010 10:26:24 -0000 >@@ -597,4 +597,20 @@ > { > delegate.setCommitComment(comment); > } >+ >+ /** >+ * @since 4.0 >+ */ >+ public void setCommittables(Set<EObject> committables) >+ { >+ delegate.setCommittables(committables); >+ } >+ >+ /** >+ * @since 4.0 >+ */ >+ public Set<EObject> getCommittables() >+ { >+ return delegate.getCommittables(); >+ } > } >Index: src/org/eclipse/emf/cdo/transaction/CDOUserTransaction.java >=================================================================== >RCS file: /cvsroot/modeling/org.eclipse.emf/org.eclipse.emf.cdo/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOUserTransaction.java,v >retrieving revision 1.9 >diff -u -r1.9 CDOUserTransaction.java >--- src/org/eclipse/emf/cdo/transaction/CDOUserTransaction.java 26 May 2010 13:25:57 -0000 1.9 >+++ src/org/eclipse/emf/cdo/transaction/CDOUserTransaction.java 11 Sep 2010 10:26:24 -0000 >@@ -14,8 +14,12 @@ > import org.eclipse.emf.cdo.common.commit.CDOCommitInfo; > import org.eclipse.emf.cdo.util.CommitException; > >+import org.eclipse.emf.ecore.EObject; >+ > import org.eclipse.core.runtime.IProgressMonitor; > >+import java.util.Set; >+ > /** > * Only deal with transaction process. > * >@@ -50,4 +54,14 @@ > * @since 3.0 > */ > public CDOUserSavepoint getLastSavepoint(); >+ >+ /** >+ * @since 4.0 >+ */ >+ public void setCommittables(Set<EObject> committables); >+ >+ /** >+ * @since 4.0 >+ */ >+ public Set<EObject> getCommittables(); > } >Index: src/org/eclipse/emf/cdo/util/CommitIntegrityCheck.java >=================================================================== >RCS file: src/org/eclipse/emf/cdo/util/CommitIntegrityCheck.java >diff -N src/org/eclipse/emf/cdo/util/CommitIntegrityCheck.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/emf/cdo/util/CommitIntegrityCheck.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,422 @@ >+/** >+ * Copyright (c) 2004 - 2010 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: >+ * Caspar De Groot - initial API and implementation >+ */ >+package org.eclipse.emf.cdo.util; >+ >+import org.eclipse.emf.cdo.CDOObject; >+import org.eclipse.emf.cdo.common.id.CDOID; >+import org.eclipse.emf.cdo.common.id.CDOID.Type; >+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.CDOContainerFeatureDelta; >+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta; >+import org.eclipse.emf.cdo.common.revision.delta.CDOListFeatureDelta; >+import org.eclipse.emf.cdo.common.revision.delta.CDORemoveFeatureDelta; >+import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; >+import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDeltaUtil; >+import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta; >+import org.eclipse.emf.cdo.common.revision.delta.CDOUnsetFeatureDelta; >+import org.eclipse.emf.cdo.eresource.CDOResource; >+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; >+ >+import org.eclipse.net4j.util.CheckUtil; >+ >+import org.eclipse.emf.common.util.EList; >+import org.eclipse.emf.ecore.EObject; >+import org.eclipse.emf.ecore.EReference; >+import org.eclipse.emf.ecore.EStructuralFeature; >+import org.eclipse.emf.ecore.InternalEObject.EStore; >+import org.eclipse.emf.spi.cdo.InternalCDOObject; >+import org.eclipse.emf.spi.cdo.InternalCDOTransaction; >+import org.eclipse.emf.spi.cdo.InternalCDOTransaction.InternalCDOCommitContext; >+ >+import java.util.HashSet; >+import java.util.Set; >+ >+/** >+ * @author Caspar De Groot >+ * @since 4.0 >+ */ >+public class CommitIntegrityCheck >+{ >+ private InternalCDOTransaction transaction; >+ >+ private Style style; >+ >+ private Set<CDOID> newIDs, dirtyIDs, detachedIDs; >+ >+ private Set<CDOObject> missingObjects = new HashSet<CDOObject>(); >+ >+ private StringBuilder exceptionMessage = new StringBuilder(); >+ >+ public CommitIntegrityCheck(InternalCDOCommitContext commitContext) >+ { >+ this(commitContext, Style.EXCEPTION_FAST); >+ } >+ >+ public CommitIntegrityCheck(InternalCDOCommitContext commitContext, Style style) >+ { >+ transaction = commitContext.getTransaction(); >+ >+ CheckUtil.checkNull(style, "style should not be null"); >+ this.style = style; >+ >+ newIDs = commitContext.getNewObjects().keySet(); >+ dirtyIDs = commitContext.getDirtyObjects().keySet(); >+ detachedIDs = commitContext.getDetachedObjects().keySet(); >+ } >+ >+ public void check() throws CommitIntegrityException >+ { >+ // For new objects: ensure that their container is included, >+ // as well as the targets of the new object's bidi references >+ for (CDOID newID : newIDs) >+ { >+ CDOObject newObject = transaction.getObject(newID); >+ checkContainerIncluded(newObject, "new"); >+ checkCurrentBidiRefTargetsIncluded(newObject, "new"); >+ } >+ >+ // For detached objects: ensure that their former container is included, >+ // as well as the targets of the detached object's bidi references >+ for (CDOID detachedID : detachedIDs) >+ { >+ CDOObject detachedObject = transaction.getObject(detachedID); >+ checkFormerContainerIncluded(detachedObject); >+ checkFormerBidiRefTargetsIncluded(detachedObject, "detached"); >+ } >+ >+ // For dirty objects: if any of the deltas for the object, affect containment (i.e. object was moved) >+ // or a bi-di reference, ensure that for containment, both the old and new containers are included, >+ // (or that the child is included if we are considering the dirty parent), >+ // and that for a bi-di reference, the object holding the other end of the bi-di is included, as >+ // well as possibly the *former* object holding the other end. >+ // >+ for (CDOID dirtyID : dirtyIDs) >+ { >+ CDOObject dirtyObject = transaction.getObject(dirtyID); >+ analyzeRevisionDelta((InternalCDOObject)dirtyObject); >+ } >+ >+ if (!missingObjects.isEmpty() && style == Style.EXCEPTION) >+ { >+ throw createException(); >+ } >+ } >+ >+ public Set<? extends EObject> getMissingObjects() >+ { >+ return missingObjects; >+ } >+ >+ private CDOID getContainerOrResourceID(InternalCDORevision revision) >+ { >+ CDOID containerOrResourceID = null; >+ Object idOrObject = revision.getContainerID(); >+ if (idOrObject != null) >+ { >+ containerOrResourceID = (CDOID)transaction.convertObjectToID(idOrObject); >+ } >+ >+ if (containerOrResourceID == null || containerOrResourceID.getType() == Type.NULL) >+ { >+ idOrObject = revision.getResourceID(); >+ if (idOrObject != null) >+ { >+ containerOrResourceID = (CDOID)transaction.convertObjectToID(idOrObject); >+ } >+ } >+ >+ return containerOrResourceID; >+ } >+ >+ private void analyzeRevisionDelta(InternalCDOObject dirtyObject) throws CommitIntegrityException >+ { >+ // Getting the deltas from the TX is not a good idea... >+ // We better recompute a fresh delta: >+ // >+ InternalCDORevision cleanRev = transaction.getCleanRevisions().get(dirtyObject); >+ CheckUtil.checkNull(cleanRev, "Could not obtain clean revision for dirty object " + dirtyObject); >+ InternalCDORevision dirtyRev = dirtyObject.cdoRevision(); >+ CDORevisionDelta rDelta = CDORevisionDeltaUtil.create(cleanRev, dirtyRev); >+ >+ for (CDOFeatureDelta featureDelta : rDelta.getFeatureDeltas()) >+ { >+ EStructuralFeature feat = featureDelta.getFeature(); >+ if (feat == CDOContainerFeatureDelta.CONTAINER_FEATURE) >+ { >+ // Object is dirty with respect to its container; this means it was moved; >+ // We must ensure that both the old and new containers are included >+ checkContainerIncluded(dirtyObject, "moved"); >+ CDOID containerOrResourceID = getContainerOrResourceID(cleanRev); >+ checkIncluded(containerOrResourceID, "former container (or resource) of moved", dirtyObject); >+ } >+ else if (feat instanceof EReference) >+ { >+ EReference ref = (EReference)feat; >+ if (ref.isContainment() || ref.getEOpposite() != null) >+ { >+ // Object is dirty with respect to a containment feature >+ // We must ensure that any children that were added/removed, are also >+ // included in the commit >+ >+ if (featureDelta instanceof CDOListFeatureDelta) >+ { >+ for (CDOFeatureDelta innerFeatDelta : ((CDOListFeatureDelta)featureDelta).getListChanges()) >+ { >+ checkContainmentDelta(innerFeatDelta, dirtyObject); >+ } >+ } >+ else >+ { >+ checkContainmentDelta(featureDelta, dirtyObject); >+ } >+ } >+ } >+ } >+ } >+ >+ private void checkContainmentDelta(CDOFeatureDelta featureDelta, CDOObject dirtyObject) >+ throws CommitIntegrityException >+ { >+ if (featureDelta instanceof CDORemoveFeatureDelta) >+ { >+ Object idOrObject = ((CDORemoveFeatureDelta)featureDelta).getValue(); >+ CDOID id = (CDOID)transaction.convertObjectToID(idOrObject); >+ checkIncluded(id, "removed child of", dirtyObject); >+ } >+ else if (featureDelta instanceof CDOAddFeatureDelta) >+ { >+ Object idOrObject = ((CDOAddFeatureDelta)featureDelta).getValue(); >+ CDOID id = (CDOID)transaction.convertObjectToID(idOrObject); >+ if (id.getType() != CDOID.Type.NULL) >+ { >+ checkIncluded(id, "added child of", dirtyObject); >+ } >+ } >+ else if (featureDelta instanceof CDOSetFeatureDelta) >+ { >+ Object newIDOrObject = ((CDOSetFeatureDelta)featureDelta).getValue(); >+ Object oldIDOrObject = ((CDOSetFeatureDelta)featureDelta).getOldValue(); >+ CDOID oldID = (CDOID)transaction.convertObjectToID(oldIDOrObject); >+ if (oldIDOrObject != null) >+ { >+ if (newIDOrObject == null) >+ { >+ // Removal: old child must be included >+ checkIncluded(oldID, "removed child of", dirtyObject); >+ } >+ else >+ { >+ // Change: both old and new child must be included >+ checkIncluded(oldID, "former child of", dirtyObject); >+ CDOID newID = (CDOID)transaction.convertObjectToID(newIDOrObject); >+ checkIncluded(newID, "new child of", dirtyObject); >+ } >+ } >+ else >+ { >+ // New child, no old child >+ CDOID newID = (CDOID)transaction.convertObjectToID(newIDOrObject); >+ checkIncluded(newID, "new child of", dirtyObject); >+ } >+ } >+ else if (featureDelta instanceof CDOClearFeatureDelta) >+ { >+ EStructuralFeature feat = ((CDOClearFeatureDelta)featureDelta).getFeature(); >+ InternalCDORevision cleanRev = transaction.getCleanRevisions().get(dirtyObject); >+ int n = cleanRev.size(feat); >+ for (int i = 0; i < n; i++) >+ { >+ Object idOrObject = cleanRev.get(feat, i); >+ CDOID id = (CDOID)transaction.convertObjectToID(idOrObject); >+ checkIncluded(id, "removed child of", dirtyObject); >+ } >+ } >+ else if (featureDelta instanceof CDOUnsetFeatureDelta) >+ { >+ EStructuralFeature feat = ((CDOUnsetFeatureDelta)featureDelta).getFeature(); >+ InternalCDORevision cleanRev = transaction.getCleanRevisions().get(dirtyObject); >+ Object idOrObject = cleanRev.getValue(feat); >+ CDOID id = (CDOID)transaction.convertObjectToID(idOrObject); >+ checkIncluded(id, "removed child of", dirtyObject); >+ } >+ else >+ { >+ throw new RuntimeException("Unexpected delta type: " + featureDelta.getClass().getSimpleName()); >+ } >+ } >+ >+ private void checkIncluded(CDOID id, String msg, CDOObject o) throws CommitIntegrityException >+ { >+ if (id.getType() == Type.NULL) >+ { >+ throw new IllegalArgumentException("CDOID must not be of type NULL"); >+ } >+ >+ if (!dirtyIDs.contains(id) && !detachedIDs.contains(id) && !newIDs.contains(id)) >+ { >+ CDOObject missingObject = transaction.getObject(id); >+ if (missingObject == null) >+ { >+ throw new IllegalStateException("Could not find object for CDOID " + id); >+ } >+ missingObjects.add(missingObject); >+ >+ if (exceptionMessage.length() > 0) >+ { >+ exceptionMessage.append('\n'); >+ } >+ String m = String.format("The %s object %s needs to be included in the commit but isn't", msg, o); >+ exceptionMessage.append(m); >+ >+ if (style == Style.EXCEPTION_FAST) >+ { >+ throw createException(); >+ } >+ } >+ } >+ >+ private CommitIntegrityException createException() >+ { >+ return new CommitIntegrityException(exceptionMessage.toString(), missingObjects); >+ } >+ >+ /** >+ * Checks whether the container of a given object is included in the commit >+ * >+ * @param msgFrag >+ * @throws CommitIntegrityException >+ */ >+ private void checkContainerIncluded(CDOObject object, String msgFrag) throws CommitIntegrityException >+ { >+ EObject eContainer = object.eContainer(); >+ if (eContainer == null) >+ { >+ // It's a top-level object >+ CDOResource resource = object.cdoDirectResource(); >+ checkIncluded(resource.cdoID(), "resource of " + msgFrag, object); >+ } >+ else >+ { >+ CDOObject container = CDOUtil.getCDOObject(eContainer); >+ checkIncluded(container.cdoID(), "container of " + msgFrag, object); >+ } >+ } >+ >+ private void checkCurrentBidiRefTargetsIncluded(CDOObject referencer, String msgFrag) throws CommitIntegrityException >+ { >+ for (EReference eRef : referencer.eClass().getEAllReferences()) >+ { >+ if (eRef.getEOpposite() != null) >+ { >+ if (eRef.isMany()) >+ { >+ EList<?> list = (EList<?>)referencer.eGet(eRef); >+ for (Object element : list) >+ { >+ checkBidiRefTargetIncluded(element, referencer, msgFrag); >+ } >+ } >+ else >+ { >+ Object refTarget = referencer.eGet(eRef); >+ if (refTarget != null) >+ { >+ checkBidiRefTargetIncluded(refTarget, referencer, msgFrag); >+ } >+ } >+ } >+ } >+ } >+ >+ private void checkFormerBidiRefTargetsIncluded(CDOObject referencer, String msgFrag) throws CommitIntegrityException >+ { >+ // The referencer argument should really be a detached object, and so we know >+ // that we can find the pre-detach revision in tx.getFormerRevisions(). However, >+ // the object may have already been dirty prior to detachment, so we check the >+ // clean revisions first. >+ // >+ InternalCDORevision cleanRev = transaction.getCleanRevisions().get(referencer); >+ CheckUtil.checkState(cleanRev, "cleanRev"); >+ >+ for (EReference eRef : referencer.eClass().getEAllReferences()) >+ { >+ if (eRef.getEOpposite() != null) >+ { >+ Object value = cleanRev.get(eRef, EStore.NO_INDEX); >+ if (value != null) >+ { >+ if (eRef.isMany()) >+ { >+ EList<?> list = (EList<?>)value; >+ for (Object element : list) >+ { >+ checkBidiRefTargetIncluded(element, referencer, msgFrag); >+ } >+ } >+ else >+ { >+ checkBidiRefTargetIncluded(value, referencer, msgFrag); >+ } >+ } >+ } >+ } >+ } >+ >+ private void checkBidiRefTargetIncluded(Object refTarget, CDOObject referencer, String msgFrag) >+ throws CommitIntegrityException >+ { >+ CheckUtil.checkArg(refTarget, "refTarget"); >+ CDOID refTargetID = null; >+ if (refTarget instanceof EObject) >+ { >+ refTargetID = CDOUtil.getCDOObject((EObject)refTarget).cdoID(); >+ } >+ else if (refTarget instanceof CDOID) >+ { >+ refTargetID = (CDOID)refTarget; >+ } >+ checkIncluded(refTargetID, "reference target of " + msgFrag, referencer); >+ } >+ >+ private void checkFormerContainerIncluded(CDOObject detachedObject) throws CommitIntegrityException >+ { >+ InternalCDORevision rev = transaction.getCleanRevisions().get(detachedObject); >+ CheckUtil.checkNull(rev, "Could not obtain clean revision for detached object " + detachedObject); >+ CDOID id = getContainerOrResourceID(rev); >+ checkIncluded(id, "former container (or resource) of detached", detachedObject); >+ } >+ >+ /** >+ * Designates an exception style for a {@link CommitIntegrityCheck} >+ * >+ * @author Caspar De Groot >+ */ >+ public enum Style >+ { >+ /** >+ * Throw an exception as soon as this {@link CommitIntegrityCheck} encounters the first problem >+ */ >+ EXCEPTION_FAST, >+ >+ /** >+ * Throw an exception when this {@link CommitIntegrityCheck} finishes performing all possible checks, in case any >+ * problems were found >+ */ >+ EXCEPTION, >+ >+ /** >+ * Do not throw an exception. Caller must invoke {@link CommitIntegrityCheck#getMissingObjects()} to find out if the >+ * check discovered any problems. >+ */ >+ NO_EXCEPTION >+ } >+} >Index: src/org/eclipse/emf/cdo/util/CommitIntegrityException.java >=================================================================== >RCS file: src/org/eclipse/emf/cdo/util/CommitIntegrityException.java >diff -N src/org/eclipse/emf/cdo/util/CommitIntegrityException.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/emf/cdo/util/CommitIntegrityException.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,37 @@ >+/** >+ * Copyright (c) 2004 - 2010 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: >+ * Caspar De Groot - initial API and implementation >+ */ >+package org.eclipse.emf.cdo.util; >+ >+import org.eclipse.emf.ecore.EObject; >+ >+import java.util.Set; >+ >+/** >+ * @author Caspar De Groot >+ * @since 4.0 >+ */ >+public class CommitIntegrityException extends CommitException >+{ >+ private static final long serialVersionUID = 3302652235940254454L; >+ >+ private Set<? extends EObject> missingObjects; >+ >+ public CommitIntegrityException(String msg, Set<? extends EObject> missingObjects) >+ { >+ super(msg); >+ this.missingObjects = missingObjects; >+ } >+ >+ public Set<? extends EObject> getMissingObjects() >+ { >+ return missingObjects; >+ } >+} >Index: src/org/eclipse/emf/internal/cdo/CDOStateMachine.java >=================================================================== >RCS file: /cvsroot/modeling/org.eclipse.emf/org.eclipse.emf.cdo/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOStateMachine.java,v >retrieving revision 1.155 >diff -u -r1.155 CDOStateMachine.java >--- src/org/eclipse/emf/internal/cdo/CDOStateMachine.java 20 Jul 2010 08:39:00 -0000 1.155 >+++ src/org/eclipse/emf/internal/cdo/CDOStateMachine.java 11 Sep 2010 10:26:25 -0000 >@@ -798,6 +798,8 @@ > public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Object featureDelta) > { > InternalCDOTransaction transaction = object.cdoView().toTransaction(); >+ InternalCDORevision cleanRevision = object.cdoRevision(); >+ transaction.getCleanRevisions().put(object, cleanRevision); > > // Copy revision > InternalCDORevision revision = object.cdoRevision().copy(); >Index: src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java >=================================================================== >RCS file: /cvsroot/modeling/org.eclipse.emf/org.eclipse.emf.cdo/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java,v >retrieving revision 1.103 >diff -u -r1.103 CDOTransactionImpl.java >--- src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java 4 Sep 2010 05:28:32 -0000 1.103 >+++ src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java 11 Sep 2010 10:26:27 -0000 >@@ -69,6 +69,7 @@ > import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta; > import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager; > import org.eclipse.emf.cdo.spi.common.revision.PointerCDORevision; >+import org.eclipse.emf.cdo.transaction.CDOCommitContext; > import org.eclipse.emf.cdo.transaction.CDOConflictResolver; > import org.eclipse.emf.cdo.transaction.CDOConflictResolver2; > import org.eclipse.emf.cdo.transaction.CDODefaultTransactionHandler; >@@ -83,6 +84,7 @@ > import org.eclipse.emf.cdo.util.CDOURIUtil; > import org.eclipse.emf.cdo.util.CDOUtil; > import org.eclipse.emf.cdo.util.CommitException; >+import org.eclipse.emf.cdo.util.CommitIntegrityCheck; > import org.eclipse.emf.cdo.util.LegacyModeNotEnabledException; > import org.eclipse.emf.cdo.util.ObjectNotFoundException; > >@@ -191,6 +193,10 @@ > } > }; > >+ private Set<EObject> committables; >+ >+ private Map<InternalCDOObject, InternalCDORevision> cleanRevisions = new HashMap<InternalCDOObject, InternalCDORevision>(); >+ > public CDOTransactionImpl(CDOBranch branch) > { > super(branch, UNSPECIFIED_DATE); >@@ -978,7 +984,7 @@ > { > checkActive(); > rollback(firstSavepoint); >- cleanUp(); >+ cleanUp(null); > } > > private void removeObject(CDOID id, CDOObject object) >@@ -1203,6 +1209,11 @@ > formerRevisionKeys.put(object, revKey); > } > >+ if (!cleanRevisions.containsKey(object)) >+ { >+ cleanRevisions.put(object, object.cdoRevision()); >+ } >+ > // Object may have been reattached previously, in which case it must > // here be removed from the collection of reattached objects > lastSavepoint.getReattachedObjects().remove(id); >@@ -1551,19 +1562,60 @@ > return newPackages; > } > >- private void cleanUp() >+ private void cleanUp(CDOCommitContext commitContext) > { >- lastSavepoint = firstSavepoint; >- firstSavepoint.clear(); >- firstSavepoint.setNextSavepoint(null); >- firstSavepoint.getSharedDetachedObjects().clear(); >- >- // Bug 283985 (Re-attachment) >- formerRevisionKeys.clear(); >- >- dirty = false; >- conflict = 0; >- lastTemporaryID.set(0); >+ if (commitContext == null || !commitContext.isPartialCommit()) >+ { >+ lastSavepoint = firstSavepoint; >+ firstSavepoint.clear(); >+ firstSavepoint.setNextSavepoint(null); >+ firstSavepoint.getSharedDetachedObjects().clear(); >+ >+ // Bug 283985 (Re-attachment) >+ formerRevisionKeys.clear(); >+ >+ cleanRevisions.clear(); >+ dirty = false; >+ conflict = 0; >+ lastTemporaryID.set(0); >+ } >+ else >+ { >+ collapseSavepoints(commitContext); >+ >+ for (CDOObject object : commitContext.getDetachedObjects().values()) >+ { >+ formerRevisionKeys.remove(object); >+ } >+ } >+ >+ // Reset partial-commit filter >+ committables = null; >+ } >+ >+ private void collapseSavepoints(CDOCommitContext commitContext) >+ { >+ InternalCDOSavepoint newSavepoint = createSavepoint(null); >+ copyUncommitted(lastSavepoint.getAllNewObjects(), commitContext.getNewObjects(), newSavepoint.getNewObjects()); >+ copyUncommitted(lastSavepoint.getAllDirtyObjects(), commitContext.getDirtyObjects(), newSavepoint.getDirtyObjects()); >+ copyUncommitted(lastSavepoint.getAllRevisionDeltas(), commitContext.getRevisionDeltas(), >+ newSavepoint.getRevisionDeltas()); >+ copyUncommitted(lastSavepoint.getAllDetachedObjects(), commitContext.getDetachedObjects(), >+ newSavepoint.getDetachedObjects()); >+ lastSavepoint = newSavepoint; >+ firstSavepoint = lastSavepoint; >+ } >+ >+ private <T> void copyUncommitted(Map<CDOID, T> oldSavepointMap, Map<CDOID, T> commitContextMap, >+ Map<CDOID, T> newSavepointMap) >+ { >+ for (Entry<CDOID, T> entry : oldSavepointMap.entrySet()) >+ { >+ if (!commitContextMap.containsKey(entry.getKey())) >+ { >+ newSavepointMap.put(entry.getKey(), entry.getValue()); >+ } >+ } > } > > public CDOSavepoint[] exportChanges(OutputStream stream) throws IOException >@@ -1925,6 +1977,21 @@ > commitComment = comment; > } > >+ public void setCommittables(Set<EObject> committables) >+ { >+ this.committables = committables; >+ } >+ >+ public Set<EObject> getCommittables() >+ { >+ return committables; >+ } >+ >+ public Map<InternalCDOObject, InternalCDORevision> getCleanRevisions() >+ { >+ return cleanRevisions; >+ } >+ > /** > * @author Simon McDuff > */ >@@ -1934,6 +2001,21 @@ > > private CDOCommitData commitData; > >+ private Map<CDOID, CDOObject> newObjects; >+ >+ private Map<CDOID, CDOObject> detachedObjects; >+ >+ private Map<CDOID, CDORevisionDelta> revisionDeltas; >+ >+ private Map<CDOID, CDOObject> dirtyObjects; >+ >+ /** >+ * Tracks whether this commit is *actually* partial or not. (Having tx.committables != null does not in itself mean >+ * that the commit will be partial, because the committables could cover all dirty/new/detached objects. But this >+ * boolean gets set to reflect whether the commit will really commit less than all dirty/new/detached objects.) >+ */ >+ private boolean isPartialCommit; >+ > public CDOCommitContextImpl(InternalCDOTransaction transaction) > { > this.transaction = transaction; >@@ -1943,29 +2025,59 @@ > private void calculateCommitData() > { > List<CDOPackageUnit> newPackageUnits = analyzeNewPackages(); >- List<CDOIDAndVersion> revisions = new ArrayList<CDOIDAndVersion>(getNewObjects().size()); >- for (CDOObject newObject : getNewObjects().values()) >+ newObjects = filterCommittables(transaction.getNewObjects()); >+ List<CDOIDAndVersion> revisions = new ArrayList<CDOIDAndVersion>(newObjects.size()); >+ for (CDOObject newObject : newObjects.values()) > { > revisions.add(newObject.cdoRevision()); > } > >- List<CDORevisionKey> deltas = new ArrayList<CDORevisionKey>(getRevisionDeltas().size()); >- for (CDORevisionDelta delta : getRevisionDeltas().values()) >+ revisionDeltas = filterCommittables(transaction.getRevisionDeltas()); >+ List<CDORevisionKey> deltas = new ArrayList<CDORevisionKey>(revisionDeltas.size()); >+ for (CDORevisionDelta delta : revisionDeltas.values()) > { > deltas.add(delta); > } > >- List<CDOIDAndVersion> detached = new ArrayList<CDOIDAndVersion>(getDetachedObjects().size()); >- for (CDOID id : getDetachedObjects().keySet()) >+ detachedObjects = filterCommittables(transaction.getDetachedObjects()); >+ List<CDOIDAndVersion> detached = new ArrayList<CDOIDAndVersion>(detachedObjects.size()); >+ for (CDOID id : detachedObjects.keySet()) > { > // Add "version-less" key. > // CDOSessionImpl.reviseRevisions() will call reviseLatest() accordingly. > detached.add(CDOIDUtil.createIDAndVersion(id, CDOBranchVersion.UNSPECIFIED_VERSION)); > } > >+ dirtyObjects = filterCommittables(transaction.getDirtyObjects()); >+ > commitData = new CDOCommitDataImpl(newPackageUnits, revisions, deltas, detached); > } > >+ private <T> Map<CDOID, T> filterCommittables(Map<CDOID, T> map) >+ { >+ if (committables == null) >+ { >+ // No partial commit filter -- nothing to do >+ return map; >+ } >+ >+ Map<CDOID, T> newMap = new HashMap<CDOID, T>(); >+ for (CDOID id : map.keySet()) >+ { >+ CDOObject o = getObject(id); >+ if (committables.contains(o)) >+ { >+ newMap.put(id, map.get(id)); >+ } >+ else >+ { >+ isPartialCommit = true; >+ } >+ } >+ >+ return newMap; >+ } >+ > public InternalCDOTransaction getTransaction() > { > return transaction; >@@ -1978,12 +2090,12 @@ > > public Map<CDOID, CDOObject> getDirtyObjects() > { >- return transaction.getDirtyObjects(); >+ return dirtyObjects; > } > > public Map<CDOID, CDOObject> getNewObjects() > { >- return transaction.getNewObjects(); >+ return newObjects; > } > > public List<CDOPackageUnit> getNewPackageUnits() >@@ -1993,12 +2105,12 @@ > > public Map<CDOID, CDOObject> getDetachedObjects() > { >- return transaction.getDetachedObjects(); >+ return detachedObjects; > } > > public Map<CDOID, CDORevisionDelta> getRevisionDeltas() > { >- return transaction.getRevisionDeltas(); >+ return revisionDeltas; > } > > public void preCommit() >@@ -2046,6 +2158,13 @@ > > try > { >+ // TODO (CD) It might be better to always do the checks, >+ // instead of only for partial commits >+ if (isPartialCommit) >+ { >+ new CommitIntegrityCheck(this, CommitIntegrityCheck.Style.EXCEPTION_FAST).check(); >+ } >+ > preCommit(getNewObjects()); > preCommit(getDirtyObjects()); > } >@@ -2110,7 +2229,7 @@ > getChangeSubscriptionManager().committedTransaction(transaction, this); > getAdapterManager().committedTransaction(transaction, this); > >- cleanUp(); >+ cleanUp(this); > Map<CDOID, CDOID> idMappings = result.getIDMappings(); > IListener[] listeners = getListeners(); > if (listeners != null) >@@ -2180,6 +2299,11 @@ > } > } > } >+ >+ public boolean isPartialCommit() >+ { >+ return isPartialCommit; >+ } > } > > /** >Index: src/org/eclipse/emf/internal/cdo/transaction/CDOXACommitContextImpl.java >=================================================================== >RCS file: /cvsroot/modeling/org.eclipse.emf/org.eclipse.emf.cdo/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOXACommitContextImpl.java,v >retrieving revision 1.15 >diff -u -r1.15 CDOXACommitContextImpl.java >--- src/org/eclipse/emf/internal/cdo/transaction/CDOXACommitContextImpl.java 4 Sep 2010 05:28:32 -0000 1.15 >+++ src/org/eclipse/emf/internal/cdo/transaction/CDOXACommitContextImpl.java 11 Sep 2010 10:26:27 -0000 >@@ -134,6 +134,11 @@ > return delegateCommitContext.getCommitData(); > } > >+ public boolean isPartialCommit() >+ { >+ return delegateCommitContext.isPartialCommit(); >+ } >+ > public Object call() throws Exception > { > state.handle(this, progressMonitor); >Index: src/org/eclipse/emf/internal/cdo/transaction/CDOXATransactionImpl.java >=================================================================== >RCS file: /cvsroot/modeling/org.eclipse.emf/org.eclipse.emf.cdo/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOXATransactionImpl.java,v >retrieving revision 1.25 >diff -u -r1.25 CDOXATransactionImpl.java >--- src/org/eclipse/emf/internal/cdo/transaction/CDOXATransactionImpl.java 26 May 2010 13:25:57 -0000 1.25 >+++ src/org/eclipse/emf/internal/cdo/transaction/CDOXATransactionImpl.java 11 Sep 2010 10:26:27 -0000 >@@ -34,6 +34,7 @@ > import org.eclipse.emf.common.notify.Adapter; > import org.eclipse.emf.common.notify.Notification; > import org.eclipse.emf.common.notify.Notifier; >+import org.eclipse.emf.ecore.EObject; > import org.eclipse.emf.spi.cdo.CDOSessionProtocol; > import org.eclipse.emf.spi.cdo.CDOSessionProtocol.CommitTransactionResult; > import org.eclipse.emf.spi.cdo.CDOTransactionStrategy; >@@ -435,6 +436,16 @@ > } > } > >+ public void setCommittables(Set<EObject> committables) >+ { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public Set<EObject> getCommittables() >+ { >+ throw new UnsupportedOperationException(); >+ } >+ > /** > * @author Simon McDuff > */ >Index: src/org/eclipse/emf/spi/cdo/InternalCDOTransaction.java >=================================================================== >RCS file: /cvsroot/modeling/org.eclipse.emf/org.eclipse.emf.cdo/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOTransaction.java,v >retrieving revision 1.21 >diff -u -r1.21 InternalCDOTransaction.java >--- src/org/eclipse/emf/spi/cdo/InternalCDOTransaction.java 9 Aug 2010 15:39:16 -0000 1.21 >+++ src/org/eclipse/emf/spi/cdo/InternalCDOTransaction.java 11 Sep 2010 10:26:27 -0000 >@@ -20,6 +20,7 @@ > import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta; > import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; > import org.eclipse.emf.cdo.eresource.CDOResourceFolder; >+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; > import org.eclipse.emf.cdo.transaction.CDOCommitContext; > import org.eclipse.emf.cdo.transaction.CDOTransaction; > >@@ -92,6 +93,11 @@ > public Map<InternalCDOObject, CDORevisionKey> getFormerRevisionKeys(); > > /** >+ * @since 4.0 >+ */ >+ public Map<InternalCDOObject, InternalCDORevision> getCleanRevisions(); >+ >+ /** > * Provides a context for a commit operation. > * > * @author Simon McDuff >#P org.eclipse.emf.cdo.common >Index: src/org/eclipse/emf/cdo/common/revision/delta/CDOSetFeatureDelta.java >=================================================================== >RCS file: /cvsroot/modeling/org.eclipse.emf/org.eclipse.emf.cdo/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/delta/CDOSetFeatureDelta.java,v >retrieving revision 1.5 >diff -u -r1.5 CDOSetFeatureDelta.java >--- src/org/eclipse/emf/cdo/common/revision/delta/CDOSetFeatureDelta.java 3 Feb 2010 10:19:40 -0000 1.5 >+++ src/org/eclipse/emf/cdo/common/revision/delta/CDOSetFeatureDelta.java 11 Sep 2010 10:26:28 -0000 >@@ -17,7 +17,17 @@ > */ > public interface CDOSetFeatureDelta extends CDOFeatureDelta > { >+ /** >+ * @since 4.0 >+ */ >+ public static final Object UNSPECIFIED = new Object(); >+ > public int getIndex(); > > public Object getValue(); >+ >+ /** >+ * @since 4.0 >+ */ >+ public Object getOldValue(); > } >Index: src/org/eclipse/emf/cdo/internal/common/revision/delta/CDORevisionDeltaImpl.java >=================================================================== >RCS file: /cvsroot/modeling/org.eclipse.emf/org.eclipse.emf.cdo/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/delta/CDORevisionDeltaImpl.java,v >retrieving revision 1.40 >diff -u -r1.40 CDORevisionDeltaImpl.java >--- src/org/eclipse/emf/cdo/internal/common/revision/delta/CDORevisionDeltaImpl.java 8 Aug 2010 07:17:11 -0000 1.40 >+++ src/org/eclipse/emf/cdo/internal/common/revision/delta/CDORevisionDeltaImpl.java 11 Sep 2010 10:26:28 -0000 >@@ -364,7 +364,7 @@ > } > else > { >- addFeatureDelta(new CDOSetFeatureDeltaImpl(feature, 0, dirtyValue)); >+ addFeatureDelta(new CDOSetFeatureDeltaImpl(feature, 0, dirtyValue, originValue)); > } > } > } >Index: src/org/eclipse/emf/cdo/internal/common/revision/delta/CDOSetFeatureDeltaImpl.java >=================================================================== >RCS file: /cvsroot/modeling/org.eclipse.emf/org.eclipse.emf.cdo/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/delta/CDOSetFeatureDeltaImpl.java,v >retrieving revision 1.13 >diff -u -r1.13 CDOSetFeatureDeltaImpl.java >--- src/org/eclipse/emf/cdo/internal/common/revision/delta/CDOSetFeatureDeltaImpl.java 6 Jul 2010 12:11:48 -0000 1.13 >+++ src/org/eclipse/emf/cdo/internal/common/revision/delta/CDOSetFeatureDeltaImpl.java 11 Sep 2010 10:26:28 -0000 >@@ -23,6 +23,7 @@ > import org.eclipse.emf.ecore.EStructuralFeature; > > import java.io.IOException; >+import java.text.MessageFormat; > > /** > * @author Simon McDuff >@@ -30,11 +31,19 @@ > public class CDOSetFeatureDeltaImpl extends CDOSingleValueFeatureDeltaImpl implements CDOSetFeatureDelta, > ListTargetAdding > { >+ private Object oldValue = CDOSetFeatureDelta.UNSPECIFIED; >+ > public CDOSetFeatureDeltaImpl(EStructuralFeature feature, int index, Object value) > { > super(feature, index, value); > } > >+ public CDOSetFeatureDeltaImpl(EStructuralFeature feature, int index, Object value, Object oldValue) >+ { >+ super(feature, index, value); >+ this.oldValue = oldValue; >+ } >+ > public CDOSetFeatureDeltaImpl(CDODataInput in, EClass eClass) throws IOException > { > super(in, eClass); >@@ -47,7 +56,7 @@ > > public CDOFeatureDelta copy() > { >- return new CDOSetFeatureDeltaImpl(getFeature(), getIndex(), getValue()); >+ return new CDOSetFeatureDeltaImpl(getFeature(), getIndex(), getValue(), getOldValue()); > } > > public void apply(CDORevision revision) >@@ -59,4 +68,25 @@ > { > visitor.visit(this); > } >+ >+ public Object getOldValue() >+ { >+ return oldValue; >+ } >+ >+ @Override >+ protected String toStringAdditional() >+ { >+ String oldValueForMessage; >+ if (oldValue != CDOSetFeatureDelta.UNSPECIFIED) >+ { >+ oldValueForMessage = oldValue == null ? "null" : oldValue.toString(); >+ } >+ else >+ { >+ oldValueForMessage = "UNSPECIFIED"; //$NON-NLS-1$ >+ } >+ >+ return super.toStringAdditional() + MessageFormat.format(", oldValue={0}", oldValueForMessage); //$NON-NLS-1$ >+ } > } >#P org.eclipse.emf.cdo.tests >Index: META-INF/MANIFEST.MF >=================================================================== >RCS file: /cvsroot/modeling/org.eclipse.emf/org.eclipse.emf.cdo/plugins/org.eclipse.emf.cdo.tests/META-INF/MANIFEST.MF,v >retrieving revision 1.71 >diff -u -r1.71 MANIFEST.MF >--- META-INF/MANIFEST.MF 6 Aug 2010 17:43:53 -0000 1.71 >+++ META-INF/MANIFEST.MF 11 Sep 2010 10:26:29 -0000 >@@ -15,6 +15,7 @@ > org.eclipse.net4j.db.h2;bundle-version="[4.0.0,5.0.0)";visibility:=reexport, > org.eclipse.emf.ecore.xmi;bundle-version="[2.4.0,3.0.0)";visibility:=reexport, > org.eclipse.emf.edit;bundle-version="[2.4.0,3.0.0)", >+ org.eclipse.emf.transaction;bundle-version="[1.4.0,1.5.0)", > org.eclipse.emf.cdo.common;bundle-version="[4.0.0,5.0.0)";visibility:=reexport, > org.eclipse.emf.cdo.common.db;bundle-version="[3.0.0,4.0.0)";visibility:=reexport, > org.eclipse.emf.cdo;bundle-version="[4.0.0,5.0.0)";visibility:=reexport, >Index: src/org/eclipse/emf/cdo/tests/AllConfigs.java >=================================================================== >RCS file: /cvsroot/modeling/org.eclipse.emf/org.eclipse.emf.cdo/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllConfigs.java,v >retrieving revision 1.32 >diff -u -r1.32 AllConfigs.java >--- src/org/eclipse/emf/cdo/tests/AllConfigs.java 1 Sep 2010 15:56:32 -0000 1.32 >+++ src/org/eclipse/emf/cdo/tests/AllConfigs.java 11 Sep 2010 10:26:29 -0000 >@@ -136,6 +136,7 @@ > testClasses.add(ChunkingTest.class); > testClasses.add(ChunkingWithMEMTest.class); > testClasses.add(PackageRegistryTest.class); >+ testClasses.add(PartialCommitTest.class); > testClasses.add(MetaTest.class); > testClasses.add(RevisionDeltaTest.class); > testClasses.add(RevisionHolderTest.class); >Index: src/org/eclipse/emf/cdo/tests/PartialCommitTest.java >=================================================================== >RCS file: src/org/eclipse/emf/cdo/tests/PartialCommitTest.java >diff -N src/org/eclipse/emf/cdo/tests/PartialCommitTest.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/emf/cdo/tests/PartialCommitTest.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,1257 @@ >+package org.eclipse.emf.cdo.tests; >+ >+import org.eclipse.emf.cdo.CDOObject; >+import org.eclipse.emf.cdo.common.id.CDOID; >+import org.eclipse.emf.cdo.eresource.CDOResource; >+import org.eclipse.emf.cdo.session.CDOSession; >+import org.eclipse.emf.cdo.tests.legacy.model1.Model1Package; >+import org.eclipse.emf.cdo.tests.legacy.model4.model4Package; >+import org.eclipse.emf.cdo.tests.model1.Category; >+import org.eclipse.emf.cdo.tests.model1.Company; >+import org.eclipse.emf.cdo.tests.model1.Model1Factory; >+import org.eclipse.emf.cdo.tests.model1.Product1; >+import org.eclipse.emf.cdo.tests.model1.PurchaseOrder; >+import org.eclipse.emf.cdo.tests.model1.Supplier; >+import org.eclipse.emf.cdo.tests.model4.ContainedElementNoOpposite; >+import org.eclipse.emf.cdo.tests.model4.MultiNonContainedElement; >+import org.eclipse.emf.cdo.tests.model4.RefMultiNonContained; >+import org.eclipse.emf.cdo.tests.model4.RefSingleContainedNPL; >+import org.eclipse.emf.cdo.tests.model4.RefSingleNonContained; >+import org.eclipse.emf.cdo.tests.model4.SingleNonContainedElement; >+import org.eclipse.emf.cdo.tests.model4.model4Factory; >+import org.eclipse.emf.cdo.util.CDOUtil; >+import org.eclipse.emf.cdo.util.CommitException; >+import org.eclipse.emf.cdo.util.CommitIntegrityCheck; >+import org.eclipse.emf.cdo.util.CommitIntegrityCheck.Style; >+import org.eclipse.emf.cdo.util.CommitIntegrityException; >+import org.eclipse.emf.cdo.view.CDOView; >+ >+import org.eclipse.emf.ecore.EObject; >+import org.eclipse.emf.ecore.EReference; >+import org.eclipse.emf.ecore.util.EcoreUtil; >+import org.eclipse.emf.spi.cdo.InternalCDOTransaction; >+import org.eclipse.emf.spi.cdo.InternalCDOTransaction.InternalCDOCommitContext; >+ >+import java.util.HashSet; >+import java.util.Iterator; >+import java.util.Set; >+ >+public class PartialCommitTest extends AbstractCDOTest >+{ >+ private static String RESOURCENAME = "/r1"; >+ >+ private CDOSession session; >+ >+ private InternalCDOTransaction tx; >+ >+ private CDOResource resource1; >+ >+ /* ---- Model 1 stuff ---- */ >+ >+ private Company company1, company2, company3, company99; >+ >+ private PurchaseOrder purchaseOrder; >+ >+ private Supplier supplier1; >+ >+ /* ---- Model 4 stuff ---- */ >+ >+ private RefSingleContainedNPL refSingleContained1, refSingleContained2; >+ >+ private ContainedElementNoOpposite singleContainedElement1; >+ >+ private RefSingleNonContained refSingleNonContained1, refSingleNonContained2; >+ >+ private SingleNonContainedElement singleNonContainedElement1, singleNonContainedElement2; >+ >+ private RefMultiNonContained refMultiNonContained1, refMultiNonContained2; >+ >+ private MultiNonContainedElement multiNonContainedElement1, multiNonContainedElement2; >+ >+ @Override >+ public void setUp() throws Exception >+ { >+ super.setUp(); >+ session = openSession(); >+ session.options().setPassiveUpdateEnabled(false); >+ tx = (InternalCDOTransaction)session.openTransaction(); >+ } >+ >+ @Override >+ public void tearDown() throws Exception >+ { >+ tx.close(); >+ session.close(); >+ super.tearDown(); >+ } >+ >+ public void testNewTopLevelResource() throws CommitException >+ { >+ CDOResource topResource1 = tx.createResource("/top1"); >+ tx.commit(); >+ >+ topResource1.setName("top1_newname"); // Make dirty but don't include; this causes partial commit >+ CDOResource topResource2 = tx.createResource("/top2"); >+ tx.setCommittables(createSet(topResource2, tx.getRootResource())); >+ goodAll(); >+ } >+ >+ public void testNewTopLevelResource_rootResourceNotIncluded() throws CommitException >+ { >+ CDOResource topResource1 = tx.createResource("/top1"); >+ tx.commit(); >+ >+ topResource1.setName("top1_newname"); // Make dirty but don't include; this causes partial commit >+ CDOResource topResource2 = tx.createResource("/top2"); >+ tx.setCommittables(createSet(topResource2)); >+ badAll(createSet(tx.getRootResource())); >+ } >+ >+ public void testNewNestedResource() throws CommitException >+ { >+ CDOResource topResource1 = tx.createResource("/top1"); >+ tx.commit(); >+ >+ topResource1.setName("top1_newname"); // Make dirty but don't include; this causes partial commit >+ CDOResource nestedResource = tx.createResource("/folder/nested"); >+ tx.setCommittables(createSet(nestedResource, nestedResource.getFolder(), tx.getRootResource())); >+ goodAll(); >+ } >+ >+ public void testNewNestedResource_rootResourceNotIncluded() throws CommitException >+ { >+ CDOResource topResource1 = tx.createResource("/top1"); >+ tx.commit(); >+ >+ topResource1.setName("top1_newname"); // Make dirty but don't include; this causes partial commit >+ CDOResource nestedResource = tx.createResource("/folder/nested"); >+ tx.setCommittables(createSet(nestedResource, nestedResource.getFolder())); >+ badAll(createSet(tx.getRootResource())); >+ } >+ >+ public void testNewNestedResource_resourceFolderNotIncluded() throws CommitException >+ { >+ CDOResource topResource1 = tx.createResource("/top1"); >+ tx.commit(); >+ >+ topResource1.setName("top1_newname"); // Make dirty but don't include; this causes partial commit >+ CDOResource nestedResource = tx.createResource("/folder/nested"); >+ tx.setCommittables(createSet(nestedResource, tx.getRootResource())); >+ badAll(createSet(nestedResource.getFolder())); >+ } >+ >+ public void testPartialCleanUp_dirtyObjects() throws CommitException >+ { >+ simpleModel1Setup(); >+ >+ company1.setName("Company1"); >+ company2.setName("Company2"); >+ company3.setName("Company3"); >+ >+ tx.setCommittables(createSet(company1)); >+ tx.commit(); >+ >+ assertClean(company1, tx); >+ assertDirty(company2, tx); >+ assertDirty(company3, tx); >+ assertTrue(tx.isDirty()); >+ >+ tx.setCommittables(createSet(company2)); >+ tx.commit(); >+ >+ assertClean(company1, tx); >+ assertClean(company2, tx); >+ assertDirty(company3, tx); >+ assertTrue(tx.isDirty()); >+ >+ tx.setCommittables(createSet(company3)); >+ tx.commit(); >+ >+ assertClean(company1, tx); >+ assertClean(company2, tx); >+ assertClean(company3, tx); >+ assertFalse(tx.isDirty()); >+ } >+ >+ public void testPartialCleanUp_newObjects() throws CommitException >+ { >+ simpleModel1Setup(); >+ Category cat = Model1Factory.eINSTANCE.createCategory(); >+ resource1.getContents().add(cat); >+ tx.commit(); >+ >+ company1.setName("Zzz"); // Make dirty but don't include; so as to force partial commit >+ >+ // Make some new objects; but with different containers >+ Company company4 = Model1Factory.eINSTANCE.createCompany(); >+ resource1.getContents().add(company4); >+ PurchaseOrder po = Model1Factory.eINSTANCE.createPurchaseOrder(); >+ company2.getPurchaseOrders().add(po); >+ Product1 product = Model1Factory.eINSTANCE.createProduct1(); >+ cat.getProducts().add(product); >+ >+ tx.setCommittables(createSet(company4, resource1)); >+ tx.commit(); >+ >+ assertClean(company4, tx); >+ assertNew(po, tx); >+ assertNew(product, tx); >+ assertTrue(tx.isDirty()); >+ >+ tx.setCommittables(createSet(po, company2)); >+ tx.commit(); >+ >+ assertClean(company4, tx); >+ assertClean(po, tx); >+ assertNew(product, tx); >+ assertTrue(tx.isDirty()); >+ >+ tx.setCommittables(createSet(product, cat)); >+ tx.commit(); >+ >+ assertClean(company4, tx); >+ assertClean(po, tx); >+ assertClean(product, tx); >+ assertTrue(tx.isDirty()); >+ >+ tx.setCommittables(createSet(company1)); >+ tx.commit(); >+ assertFalse(tx.isDirty()); >+ } >+ >+ public void testPartialCleanUp_detachedObjects() throws CommitException >+ { >+ simpleModel1Setup(); >+ Category cat = Model1Factory.eINSTANCE.createCategory(); >+ resource1.getContents().add(cat); >+ >+ // Make some new objects; but with different containers >+ Company company4 = Model1Factory.eINSTANCE.createCompany(); >+ resource1.getContents().add(company4); >+ PurchaseOrder po = Model1Factory.eINSTANCE.createPurchaseOrder(); >+ company2.getPurchaseOrders().add(po); >+ Product1 product = Model1Factory.eINSTANCE.createProduct1(); >+ cat.getProducts().add(product); >+ tx.commit(); >+ >+ company1.setName("Zzz"); // Make dirty but don't include; so as to force partial commit >+ >+ resource1.getContents().remove(company4); >+ company2.getPurchaseOrders().remove(po); >+ cat.getProducts().remove(product); >+ >+ assertTrue(tx.getDetachedObjects().containsValue(company4)); >+ assertTrue(tx.getFormerRevisionKeys().containsKey(company4)); >+ assertTrue(tx.getDetachedObjects().containsValue(po)); >+ assertTrue(tx.getFormerRevisionKeys().containsKey(company4)); >+ assertTrue(tx.getDetachedObjects().containsValue(product)); >+ assertTrue(tx.getFormerRevisionKeys().containsKey(company4)); >+ assertTrue(tx.isDirty()); >+ >+ tx.setCommittables(createSet(company4, resource1)); >+ tx.commit(); >+ >+ assertFalse(tx.getDetachedObjects().containsValue(company4)); >+ assertFalse(tx.getFormerRevisionKeys().containsKey(company4)); >+ assertTrue(tx.getDetachedObjects().containsValue(po)); >+ assertTrue(tx.getFormerRevisionKeys().containsKey(po)); >+ assertTrue(tx.getDetachedObjects().containsValue(product)); >+ assertTrue(tx.getFormerRevisionKeys().containsKey(product)); >+ assertTrue(tx.isDirty()); >+ >+ tx.setCommittables(createSet(po, company2)); >+ tx.commit(); >+ >+ assertFalse(tx.getDetachedObjects().containsValue(company4)); >+ assertFalse(tx.getFormerRevisionKeys().containsKey(company4)); >+ assertFalse(tx.getDetachedObjects().containsValue(po)); >+ assertFalse(tx.getFormerRevisionKeys().containsKey(po)); >+ assertTrue(tx.getDetachedObjects().containsValue(product)); >+ assertTrue(tx.getFormerRevisionKeys().containsKey(product)); >+ assertTrue(tx.isDirty()); >+ >+ tx.setCommittables(createSet(product, cat)); >+ tx.commit(); >+ >+ assertFalse(tx.getDetachedObjects().containsValue(company4)); >+ assertFalse(tx.getFormerRevisionKeys().containsKey(company4)); >+ assertFalse(tx.getDetachedObjects().containsValue(po)); >+ assertFalse(tx.getFormerRevisionKeys().containsKey(po)); >+ assertFalse(tx.getDetachedObjects().containsValue(product)); >+ assertFalse(tx.getFormerRevisionKeys().containsKey(product)); >+ assertTrue(tx.isDirty()); >+ >+ tx.setCommittables(createSet(company1)); >+ tx.commit(); >+ assertFalse(tx.isDirty()); >+ } >+ >+ public void testDirty() throws CommitException >+ { >+ simpleModel1Setup(); >+ supplier1.setName("Supplier"); >+ company1.setName("Company"); >+ >+ tx.setCommittables(createSet(supplier1)); >+ tx.commit(); >+ >+ assertDirty(company1, tx); >+ assertEquals(company1.getName(), "Company"); >+ >+ assertClean(supplier1, tx); >+ assertEquals(supplier1.getName(), "Supplier"); >+ } >+ >+ public void testNew() throws CommitException >+ { >+ simpleModel1Setup(); >+ PurchaseOrder po = Model1Factory.eINSTANCE.createPurchaseOrder(); >+ company2.getPurchaseOrders().add(po); >+ >+ // Include both the new object and its container >+ tx.setCommittables(createSet(company2, po)); >+ goodAll(); >+ } >+ >+ public void testNew_containerOfNewObjectNotIncluded() throws CommitException >+ { >+ simpleModel1Setup(); >+ PurchaseOrder po = Model1Factory.eINSTANCE.createPurchaseOrder(); >+ company2.getPurchaseOrders().add(po); >+ >+ // Include only the new object >+ tx.setCommittables(createSet(po)); >+ badAll(createSet(company2)); >+ } >+ >+ public void testNew_newObjectNotIncluded() throws CommitException >+ { >+ simpleModel1Setup(); >+ PurchaseOrder po = Model1Factory.eINSTANCE.createPurchaseOrder(); >+ company2.getPurchaseOrders().add(po); >+ >+ // Include only the new object's container >+ tx.setCommittables(createSet(company2)); >+ badAll(createSet(po)); >+ } >+ >+ public void testDetach() throws CommitException >+ { >+ simpleModel1Setup(); >+ EcoreUtil.delete(purchaseOrder); >+ >+ // Include the detached object and its old container >+ tx.setCommittables(createSet(company1, purchaseOrder)); >+ goodAll(); >+ } >+ >+ public void testDetach_containerOfDetachedObjectNotIncluded() throws CommitException >+ { >+ simpleModel1Setup(); >+ EcoreUtil.delete(purchaseOrder); >+ >+ // Include only the detached object >+ tx.setCommittables(createSet(purchaseOrder)); >+ badAll(createSet(company1)); >+ } >+ >+ public void testDetach_detachedObjectNotIncluded() throws CommitException >+ { >+ simpleModel1Setup(); >+ EcoreUtil.delete(purchaseOrder); >+ >+ // Include only the detached object's old container >+ tx.setCommittables(createSet(company1)); >+ badAll(createSet(purchaseOrder)); >+ } >+ >+ public void testMove() throws CommitException >+ { >+ simpleModel1Setup(); >+ company2.getPurchaseOrders().add(purchaseOrder); >+ supplier1.setName("Supplier"); >+ >+ // Include the old and new containers as well as the object that was moved >+ tx.setCommittables(createSet(purchaseOrder, company1, company2)); >+ goodAll(); >+ >+ assertClean(company1, tx); >+ assertClean(company2, tx); >+ assertClean(purchaseOrder, tx); >+ assertDirty(supplier1, tx); >+ >+ assertFalse(company1.getPurchaseOrders().contains(purchaseOrder)); >+ assertTrue(company2.getPurchaseOrders().contains(purchaseOrder)); >+ assertEquals("Supplier", supplier1.getName()); >+ assertSame(company2, purchaseOrder.eContainer()); >+ } >+ >+ public void testMove_newContainerNotIncluded() throws CommitException >+ { >+ simpleModel1Setup(); >+ company2.getPurchaseOrders().add(purchaseOrder); >+ >+ // Include only the object that was moved and its old container >+ tx.setCommittables(createSet(purchaseOrder, company1)); >+ badAll(createSet(company2)); >+ } >+ >+ public void testMove_oldContainerNotIncluded() throws CommitException >+ { >+ simpleModel1Setup(); >+ company2.getPurchaseOrders().add(purchaseOrder); >+ >+ // Include only the object that was moved and its new container >+ tx.setCommittables(createSet(purchaseOrder, company2)); >+ badAll(createSet(company1)); >+ } >+ >+ public void testMove_movedObjectNotIncluded() throws CommitException >+ { >+ simpleModel1Setup(); >+ company2.getPurchaseOrders().add(purchaseOrder); >+ >+ // Include only the old and new containers >+ tx.setCommittables(createSet(company1, company2)); >+ badAll(createSet(purchaseOrder)); >+ } >+ >+ public void testMove_onlyOldContainerIncluded() throws CommitException >+ { >+ simpleModel1Setup(); >+ company2.getPurchaseOrders().add(purchaseOrder); >+ >+ // Include only the old container >+ tx.setCommittables(createSet(company1)); >+ badAll(createSet(company2, purchaseOrder)); >+ } >+ >+ public void testMove_onlyNewContainerIncluded() throws CommitException >+ { >+ simpleModel1Setup(); >+ company2.getPurchaseOrders().add(purchaseOrder); >+ >+ // Include only the new container >+ tx.setCommittables(createSet(company2)); >+ badAll(createSet(company1, purchaseOrder)); >+ } >+ >+ public void testMove_onlyMovedObjectIncluded() throws CommitException >+ { >+ simpleModel1Setup(); >+ company2.getPurchaseOrders().add(purchaseOrder); >+ >+ // Include only the moved object >+ tx.setCommittables(createSet(purchaseOrder)); >+ badAll(createSet(company1, company2)); >+ } >+ >+ public void testDoubleMove() throws CommitException >+ { >+ simpleModel1Setup(); >+ company2.getPurchaseOrders().add(purchaseOrder); >+ company3.getPurchaseOrders().add(purchaseOrder); >+ >+ // Include the old and new containers as well as the object that was moved >+ // (The point here is that company2 does NOT have to be included.) >+ tx.setCommittables(createSet(purchaseOrder, company1, company3)); >+ System.out.printf("---> purchaseOrder=%s company1=%s company2=%s company3=%s\n", purchaseOrder, company1, company2, >+ company3); >+ goodAll(); >+ } >+ >+ public void test_noCommittablesAfterCommit() throws CommitException >+ { >+ simpleModel1Setup(); >+ company1.setName("zzz"); >+ tx.setCommittables(createSet(company1)); >+ tx.commit(); >+ >+ assertNull(tx.getCommittables()); >+ } >+ >+ public void testNewSingle() throws CommitException >+ { >+ simpleModel4ContainmentSetup(); >+ ContainedElementNoOpposite singleContainedElement = model4Factory.eINSTANCE.createContainedElementNoOpposite(); >+ refSingleContained2.setElement(singleContainedElement); >+ >+ // Include both the new object and its container >+ tx.setCommittables(createSet(refSingleContained2, singleContainedElement)); >+ goodAll(); >+ } >+ >+ public void testNewSingle_containerOfNewObjectNotIncluded() throws CommitException >+ { >+ simpleModel4ContainmentSetup(); >+ ContainedElementNoOpposite singleContainedElement = model4Factory.eINSTANCE.createContainedElementNoOpposite(); >+ refSingleContained2.setElement(singleContainedElement); >+ >+ // Include only the new object >+ tx.setCommittables(createSet(singleContainedElement)); >+ badAll(createSet(refSingleContained2)); >+ } >+ >+ public void testNewSingle_newObjectNotIncluded() throws CommitException >+ { >+ simpleModel4ContainmentSetup(); >+ ContainedElementNoOpposite singleContainedElement = model4Factory.eINSTANCE.createContainedElementNoOpposite(); >+ refSingleContained2.setElement(singleContainedElement); >+ >+ // Include only the new object's container >+ tx.setCommittables(createSet(refSingleContained2)); >+ badAll(createSet(singleContainedElement)); >+ } >+ >+ public void testDetachSingleRef() throws CommitException >+ { >+ simpleModel4ContainmentSetup(); >+ refSingleContained1.setElement(null); >+ >+ // Include the detached object and its old container >+ tx.setCommittables(createSet(refSingleContained1, singleContainedElement1)); >+ goodAll(); >+ } >+ >+ public void testDetachSingleRef_containerOfDetachedObjectNotIncluded() throws CommitException >+ { >+ simpleModel4ContainmentSetup(); >+ refSingleContained1.setElement(null); >+ >+ // Include only the detached object >+ tx.setCommittables(createSet(singleContainedElement1)); >+ badAll(createSet(refSingleContained1)); >+ } >+ >+ public void testDetachSingleRef_detachedObjectNotIncluded() throws CommitException >+ { >+ simpleModel4ContainmentSetup(); >+ refSingleContained1.setElement(null); >+ >+ // Include only the detached object's old container >+ tx.setCommittables(createSet(refSingleContained1)); >+ badAll(createSet(singleContainedElement1)); >+ } >+ >+ public void testMoveSingleRef() throws CommitException >+ { >+ simpleModel4ContainmentSetup(); >+ refSingleContained2.setElement(singleContainedElement1); >+ >+ // Include the old and new containers as well as the object that was moved >+ tx.setCommittables(createSet(refSingleContained1, refSingleContained2, singleContainedElement1)); >+ goodAll(); >+ } >+ >+ public void testMoveSingleRef_newContainerNotIncluded() throws CommitException >+ { >+ simpleModel4ContainmentSetup(); >+ refSingleContained2.setElement(singleContainedElement1); >+ >+ // Include only the object that was moved and its old container >+ tx.setCommittables(createSet(refSingleContained1, singleContainedElement1)); >+ badAll(createSet(refSingleContained2)); >+ } >+ >+ public void testMoveSingleRef_oldContainerNotIncluded() throws CommitException >+ { >+ simpleModel4ContainmentSetup(); >+ refSingleContained2.setElement(singleContainedElement1); >+ >+ // Include only the object that was moved and its new container >+ tx.setCommittables(createSet(refSingleContained2, singleContainedElement1)); >+ badAll(createSet(refSingleContained1)); >+ } >+ >+ public void testMoveSingleRef_movedObjectNotIncluded() throws CommitException >+ { >+ simpleModel4ContainmentSetup(); >+ refSingleContained2.setElement(singleContainedElement1); >+ >+ // Include only the old and new containers >+ tx.setCommittables(createSet(refSingleContained1, refSingleContained2)); >+ badAll(createSet(singleContainedElement1)); >+ } >+ >+ public void testMoveSingleRef_onlyOldContainerIncluded() throws CommitException >+ { >+ simpleModel4ContainmentSetup(); >+ refSingleContained2.setElement(singleContainedElement1); >+ >+ // Include only the old container >+ tx.setCommittables(createSet(refSingleContained1)); >+ badAll(createSet(singleContainedElement1, refSingleContained2)); >+ } >+ >+ public void testMoveSingleRef_onlyNewContainerIncluded() throws CommitException >+ { >+ simpleModel4ContainmentSetup(); >+ refSingleContained2.setElement(singleContainedElement1); >+ >+ // Include only the new container >+ tx.setCommittables(createSet(refSingleContained2)); >+ badAll(createSet(singleContainedElement1, refSingleContained1)); >+ } >+ >+ public void testMoveSingleRef_onlyMovedObjectIncluded() throws CommitException >+ { >+ simpleModel4ContainmentSetup(); >+ refSingleContained2.setElement(singleContainedElement1); >+ >+ // Include only the moved object >+ tx.setCommittables(createSet(singleContainedElement1)); >+ badAll(createSet(refSingleContained1, refSingleContained2)); >+ } >+ >+ public void testNewTopLevel() throws CommitException >+ { >+ simpleModel1Setup(); >+ Company company = Model1Factory.eINSTANCE.createCompany(); >+ resource1.getContents().add(company); >+ >+ // Include both the resource and the new object >+ tx.setCommittables(createSet(resource1, company)); >+ goodAll(); >+ } >+ >+ public void testNewTopLevel_newObjectNotIncluded() throws CommitException >+ { >+ simpleModel1Setup(); >+ Company company = Model1Factory.eINSTANCE.createCompany(); >+ resource1.getContents().add(company); >+ >+ // Include only the resource >+ tx.setCommittables(createSet(resource1)); >+ badAll(createSet(company)); >+ } >+ >+ public void testNewTopLevel_resourceNotIncluded() throws CommitException >+ { >+ simpleModel1Setup(); >+ Company company = Model1Factory.eINSTANCE.createCompany(); >+ resource1.getContents().add(company); >+ >+ // Include only the new object >+ tx.setCommittables(createSet(company)); >+ badAll(createSet(resource1)); >+ } >+ >+ public void _testNewTopLevel_resourceNotIncluded() throws CommitException >+ { >+ simpleModel1Setup(); >+ >+ CDOID companyID = null; >+ { >+ Company company = Model1Factory.eINSTANCE.createCompany(); >+ resource1.getContents().add(company); >+ >+ // Include only the new object >+ tx.setCommittables(createSet(company)); >+ tx.commit(); >+ >+ companyID = CDOUtil.getCDOObject(company).cdoID(); >+ } >+ >+ System.out.println("---> companyID = " + companyID); >+ System.out.println("---> " + CDOUtil.getCDOObject(resource1).cdoState()); >+ >+ { >+ CDOSession session2 = openSession(); >+ CDOView view = session2.openView(); >+ CDOResource resource = view.getResource(resource1.getPath()); >+ >+ // We want to know if the new company that was committed, is an element >+ // in the getContents() collection of the Resource. We cannot just call >+ // getContents().contains(), because of the odd implementation of >+ // CDOResourceImpl.contains: it actually asks the element, rather than >+ // checking its own collection. So, we have to do this the hard way: >+ // >+ boolean found = false; >+ Iterator<EObject> iter = resource.getContents().iterator(); >+ while (!found && iter.hasNext()) >+ { >+ CDOObject o = CDOUtil.getCDOObject(iter.next()); >+ if (o.cdoID().equals(companyID)) >+ { >+ found = true; >+ } >+ } >+ assertTrue(found); >+ >+ view.close(); >+ session2.close(); >+ } >+ } >+ >+ // -------- Tests concerning bi-di references ---------- >+ // >+ // Cases to test: >+ // Bi-di refs are analogous to containment, the only difference being that >+ // bi-di refs are symmetrical, whereas containment/container is not. >+ // >+ // So: >+ // >+ // For DIRTY objects, the cases are: >+ // 1. Setting a bidi ref to null where it was previously non-null >+ // Must check that object owning opposite feature is included >+ // 2. Setting a bidi ref to non-null where it was previously null >+ // Must check that object owning opposite feature is included >+ // 3. Changing a bidi ref from one non-null value to another >+ // Must check that both the object owning the NEW opposite feature, >+ // as well as the OLD one, are included >+ // >+ // For NEW objects, the >+ // If the detached object had any non-null bidi refs, we must check >+ // whether the bidi target is included. >+ // >+ // For DETACHED objects: >+ // If the detached object had any non-null bidi refs, we must check >+ // whether the bidi target is included. >+ >+ public void testDirtySingleBidiNew() throws CommitException >+ { >+ simpleModel4SingleBidiSetup(); >+ singleNonContainedElement2.setParent(refSingleNonContained2); >+ >+ tx.setCommittables(createSet(singleNonContainedElement2, refSingleNonContained2)); >+ goodAll(); >+ } >+ >+ public void testDirtySingleBidiNew_newtargetNotIncluded() throws CommitException >+ { >+ simpleModel4SingleBidiSetup(); >+ singleNonContainedElement2.setParent(refSingleNonContained2); >+ >+ tx.setCommittables(createSet(singleNonContainedElement2)); >+ badAll(createSet(refSingleNonContained2)); >+ } >+ >+ public void testDirtySingleBidiChanged() throws CommitException >+ { >+ simpleModel4SingleBidiSetup(); >+ // We "reparent" the singleNonContainedElement1 >+ singleNonContainedElement1.setParent(refSingleNonContained2); >+ >+ tx.setCommittables(createSet(singleNonContainedElement1, refSingleNonContained1, refSingleNonContained2)); >+ goodAll(); >+ } >+ >+ public void testDirtySingleBidiChanged_newTargetNotIncluded() throws CommitException >+ { >+ simpleModel4SingleBidiSetup(); >+ // We "reparent" the singleNonContainedElement1 >+ singleNonContainedElement1.setParent(refSingleNonContained2); >+ >+ tx.setCommittables(createSet(singleNonContainedElement1, refSingleNonContained1)); >+ badAll(createSet(refSingleNonContained2)); >+ } >+ >+ public void testDirtySingleBidiChanged_oldTargetNotIncluded() throws CommitException >+ { >+ simpleModel4SingleBidiSetup(); >+ // We "reparent" the singleNonContainedElement1 >+ singleNonContainedElement1.setParent(refSingleNonContained2); >+ >+ tx.setCommittables(createSet(singleNonContainedElement1, refSingleNonContained2)); >+ badAll(createSet(refSingleNonContained1)); >+ } >+ >+ public void testDirtySingleBidiRemoved() throws CommitException >+ { >+ simpleModel4SingleBidiSetup(); >+ singleNonContainedElement1.setParent(null); >+ >+ tx.setCommittables(createSet(singleNonContainedElement1, refSingleNonContained1)); >+ goodAll(); >+ } >+ >+ public void testDirtySingleBidiRemoved_oldTargetNotIncluded() throws CommitException >+ { >+ simpleModel4SingleBidiSetup(); >+ singleNonContainedElement1.setParent(null); >+ >+ tx.setCommittables(createSet(singleNonContainedElement1)); >+ badAll(createSet(refSingleNonContained1)); >+ } >+ >+ public void testSingleBidiOnNewObject() throws CommitException >+ { >+ simpleModel4SingleBidiSetup(); >+ SingleNonContainedElement newNonContainedElement = model4Factory.eINSTANCE.createSingleNonContainedElement(); >+ resource1.getContents().add(newNonContainedElement); >+ newNonContainedElement.setParent(refSingleNonContained2); >+ >+ tx.setCommittables(createSet(newNonContainedElement, resource1, refSingleNonContained2)); >+ goodAll(); >+ } >+ >+ public void testSingleBidiOnNewObject_targetNotIncluded() throws CommitException >+ { >+ simpleModel4SingleBidiSetup(); >+ SingleNonContainedElement newNonContainedElement = model4Factory.eINSTANCE.createSingleNonContainedElement(); >+ resource1.getContents().add(newNonContainedElement); >+ newNonContainedElement.setParent(refSingleNonContained2); >+ >+ tx.setCommittables(createSet(newNonContainedElement, resource1)); >+ badAll(createSet(refSingleNonContained2)); >+ } >+ >+ public void testSingleBidiOnRemovedObject() throws CommitException >+ { >+ simpleModel4SingleBidiSetup(); >+ EcoreUtil.delete(singleNonContainedElement1); >+ >+ tx.setCommittables(createSet(singleNonContainedElement1, resource1, refSingleNonContained1)); >+ goodAll(); >+ } >+ >+ public void testSingleBidiOnRemovedObject_targetNotIncluded() throws CommitException >+ { >+ simpleModel4SingleBidiSetup(); >+ EcoreUtil.delete(singleNonContainedElement1); >+ >+ tx.setCommittables(createSet(singleNonContainedElement1, resource1)); >+ badAll(createSet(refSingleNonContained1)); >+ } >+ >+ public void testDirtyMultiBidiNew() throws CommitException >+ { >+ simpleModel4MultiBidiSetup(); >+ multiNonContainedElement2.setParent(refMultiNonContained2); >+ >+ tx.setCommittables(createSet(multiNonContainedElement2, refMultiNonContained2)); >+ goodAll(); >+ } >+ >+ public void testDirtyMultiBidiNew_newtargetNotIncluded() throws CommitException >+ { >+ simpleModel4MultiBidiSetup(); >+ multiNonContainedElement2.setParent(refMultiNonContained2); >+ >+ tx.setCommittables(createSet(multiNonContainedElement2)); >+ badAll(createSet(refMultiNonContained2)); >+ } >+ >+ public void testDirtyMultiBidiChanged() throws CommitException >+ { >+ simpleModel4MultiBidiSetup(); >+ // We "reparent" the multiNonContainedElement1 >+ multiNonContainedElement1.setParent(refMultiNonContained2); >+ >+ tx.setCommittables(createSet(multiNonContainedElement1, refMultiNonContained1, refMultiNonContained2)); >+ goodAll(); >+ } >+ >+ public void testDirtyMultiBidiChanged_newTargetNotIncluded() throws CommitException >+ { >+ simpleModel4MultiBidiSetup(); >+ // We "reparent" the multiNonContainedElement1 >+ multiNonContainedElement1.setParent(refMultiNonContained2); >+ >+ tx.setCommittables(createSet(multiNonContainedElement1, refMultiNonContained1)); >+ badAll(createSet(refMultiNonContained2)); >+ } >+ >+ public void testDirtyMultiBidiChanged_oldTargetNotIncluded() throws CommitException >+ { >+ simpleModel4MultiBidiSetup(); >+ // We "reparent" the multiNonContainedElement1 >+ multiNonContainedElement1.setParent(refMultiNonContained2); >+ >+ tx.setCommittables(createSet(multiNonContainedElement1, refMultiNonContained2)); >+ badAll(createSet(refMultiNonContained1)); >+ } >+ >+ public void testDirtyMultiBidiRemoved() throws CommitException >+ { >+ simpleModel4MultiBidiSetup(); >+ multiNonContainedElement1.setParent(null); >+ >+ tx.setCommittables(createSet(multiNonContainedElement1, refMultiNonContained1)); >+ goodAll(); >+ } >+ >+ public void testDirtyMultiBidiRemoved_oldTargetNotIncluded() throws CommitException >+ { >+ simpleModel4MultiBidiSetup(); >+ multiNonContainedElement1.setParent(null); >+ >+ tx.setCommittables(createSet(multiNonContainedElement1)); >+ badAll(createSet(refMultiNonContained1)); >+ } >+ >+ public void testMultiBidiOnNewObject() throws CommitException >+ { >+ simpleModel4MultiBidiSetup(); >+ MultiNonContainedElement newNonContainedElement = model4Factory.eINSTANCE.createMultiNonContainedElement(); >+ resource1.getContents().add(newNonContainedElement); >+ newNonContainedElement.setParent(refMultiNonContained2); >+ >+ tx.setCommittables(createSet(newNonContainedElement, resource1, refMultiNonContained2)); >+ goodAll(); >+ } >+ >+ public void testMultiBidiOnNewObject_targetNotIncluded() throws CommitException >+ { >+ simpleModel4MultiBidiSetup(); >+ MultiNonContainedElement newNonContainedElement = model4Factory.eINSTANCE.createMultiNonContainedElement(); >+ resource1.getContents().add(newNonContainedElement); >+ newNonContainedElement.setParent(refMultiNonContained2); >+ >+ tx.setCommittables(createSet(newNonContainedElement, resource1)); >+ badAll(createSet(refMultiNonContained2)); >+ } >+ >+ public void testMultiBidiOnRemovedObject() throws CommitException >+ { >+ simpleModel4MultiBidiSetup(); >+ EcoreUtil.delete(multiNonContainedElement1); >+ >+ tx.setCommittables(createSet(multiNonContainedElement1, resource1, refMultiNonContained1)); >+ goodAll(); >+ } >+ >+ public void testMultiBidiOnRemovedObject_targetNotIncluded() throws CommitException >+ { >+ simpleModel4MultiBidiSetup(); >+ EcoreUtil.delete(multiNonContainedElement1); >+ >+ tx.setCommittables(createSet(multiNonContainedElement1, resource1)); >+ badAll(createSet(refMultiNonContained1)); >+ } >+ >+ public void testCheckWithoutCommit_exceptionFast() throws CommitException >+ { >+ simpleModel1Setup(); >+ PurchaseOrder po = Model1Factory.eINSTANCE.createPurchaseOrder(); >+ company2.getPurchaseOrders().add(po); >+ >+ // Include only the new object >+ tx.setCommittables(createSet(po)); >+ InternalCDOCommitContext ctx = tx.createCommitContext(); >+ try >+ { >+ new CommitIntegrityCheck(ctx, CommitIntegrityCheck.Style.EXCEPTION_FAST).check(); >+ } >+ catch (CommitIntegrityException e) >+ { >+ // Good >+ } >+ } >+ >+ public void testCheckWithoutCommit_exception() throws CommitException >+ { >+ simpleModel1Setup(); >+ PurchaseOrder po = Model1Factory.eINSTANCE.createPurchaseOrder(); >+ company2.getPurchaseOrders().add(po); >+ >+ // Include only the new object >+ tx.setCommittables(createSet(po)); >+ InternalCDOCommitContext ctx = tx.createCommitContext(); >+ try >+ { >+ new CommitIntegrityCheck(ctx, CommitIntegrityCheck.Style.EXCEPTION_FAST).check(); >+ } >+ catch (CommitIntegrityException e) >+ { >+ // Good >+ } >+ } >+ >+ public void testCommittablesContainUncommittableObjects() >+ { >+ // Idea here is to include some objects in the committables, that exist, but >+ // are neither dirty nor detached nor new. >+ // >+ // Actually, one could wonder what the desirable behavior is in this case. >+ // Should there be a failure? Or should the "committables" be considered more like >+ // a filter; i.e. it's ok for the filter to cover more than what can actually be committed. >+ // Hmm... *ponder* *ponder*. >+ // >+ } >+ >+ /** >+ * Test the commit integrity, assuming that it is good, using all possible checking styles. >+ */ >+ private void goodAll() throws CommitException >+ { >+ good(Style.NO_EXCEPTION); >+ good(Style.EXCEPTION_FAST); >+ good(Style.EXCEPTION); >+ good(null); >+ } >+ >+ /** >+ * Test the commit integrity, assuming that it is good. >+ * >+ * @param style >+ * - the checking style to be used; if null, just commit. In that case, the commit logic will choose the >+ * checking style. >+ */ >+ private void good(Style style) throws CommitException >+ { >+ if (style != null) >+ { >+ InternalCDOCommitContext ctx = tx.createCommitContext(); >+ CommitIntegrityCheck check = new CommitIntegrityCheck(ctx, style); >+ >+ try >+ { >+ check.check(); >+ assertTrue("check.getMissingObjects() should have been empty", check.getMissingObjects().isEmpty()); >+ } >+ catch (CommitIntegrityException e) >+ { >+ fail("Should not have thrown " + CommitIntegrityException.class.getName()); >+ } >+ } >+ else >+ { >+ try >+ { >+ // We always make company99 dirty if it's present >+ // (This is just a control object to verify that some stuff does NOT get >+ // committed.) >+ if (company99 != null) >+ { >+ company99.setName("000"); >+ } >+ >+ tx.commit(); >+ >+ // And we verify that it didn't get included in the commit >+ if (company99 != null) >+ { >+ assertDirty(company99, tx); >+ assertTrue("Transaction should still have been dirty", tx.isDirty()); >+ } >+ } >+ catch (CommitException e) >+ { >+ Throwable cause = e.getCause().getCause(); >+ if (cause instanceof CommitIntegrityException) >+ { >+ fail("---> Should not have failed with: " + e.getCause().getMessage()); >+ } >+ else >+ { >+ throw e; >+ } >+ } >+ } >+ } >+ >+ /** >+ * Test the commit integrity, assuming that it is bad, using all possible checking styles. >+ */ >+ private void badAll(Set<EObject> expectedMissingObjects) throws CommitException >+ { >+ bad(Style.NO_EXCEPTION, expectedMissingObjects); >+ bad(Style.EXCEPTION_FAST, expectedMissingObjects); >+ bad(Style.EXCEPTION, expectedMissingObjects); >+ bad(null, expectedMissingObjects); >+ } >+ >+ /** >+ * Test the commit integrity, assuming that it is bad. >+ * >+ * @param style >+ * - the checking style to be used; if null, just commit. In that case, the commit logic will choose the >+ * checking style. >+ */ >+ private void bad(Style style, Set<EObject> expectedMissingObjects) throws CommitException >+ { >+ CommitIntegrityException commitIntegrityEx = null; >+ Set<? extends EObject> missingObjects = null; >+ >+ CommitIntegrityCheck check = null; >+ if (style != null) >+ { >+ InternalCDOCommitContext ctx = tx.createCommitContext(); >+ check = new CommitIntegrityCheck(ctx, style); >+ } >+ >+ if (style == Style.NO_EXCEPTION) >+ { >+ try >+ { >+ check.check(); >+ } >+ catch (CommitIntegrityException e) >+ { >+ fail("Should not have thrown " + CommitIntegrityException.class.getName()); >+ } >+ } >+ else if (style == CommitIntegrityCheck.Style.EXCEPTION || style == CommitIntegrityCheck.Style.EXCEPTION_FAST) >+ { >+ try >+ { >+ check.check(); >+ fail("Should have thrown " + CommitIntegrityException.class.getName()); >+ } >+ catch (CommitIntegrityException e) >+ { >+ commitIntegrityEx = e; >+ } >+ } >+ else if (style == null) >+ { >+ try >+ { >+ tx.commit(); >+ fail("Should have thrown " + CommitException.class.getName()); >+ } >+ catch (CommitException e) >+ { >+ Throwable cause = e.getCause().getCause(); >+ if (cause instanceof CommitIntegrityException) >+ { >+ // Good >+ commitIntegrityEx = (CommitIntegrityException)cause; >+ System.out.println("---> Failed properly: " + e.getCause().getMessage()); >+ } >+ else >+ { >+ throw e; >+ } >+ } >+ } >+ else >+ { >+ fail("Unknown style"); >+ } >+ >+ if (commitIntegrityEx != null) >+ { >+ missingObjects = commitIntegrityEx.getMissingObjects(); >+ } >+ else >+ { >+ missingObjects = check.getMissingObjects(); >+ } >+ >+ if (style == Style.EXCEPTION_FAST) >+ { >+ assertEquals(1, missingObjects.size()); >+ } >+ else >+ { >+ // We cannot use == here, because it isn't (always) possible for the logic to >+ // find all missing objects >+ assertTrue(missingObjects.size() <= expectedMissingObjects.size()); >+ } >+ >+ for (EObject missingObject : missingObjects) >+ { >+ assertTrue(expectedMissingObjects.contains(missingObject)); >+ } >+ } >+ >+ private void simpleModel1Setup() throws CommitException >+ { >+ EReference ref = Model1Package.eINSTANCE.getCompany_PurchaseOrders(); >+ boolean preconditions = ref.isContainment() && ref.getEOpposite() == null && ref.isMany(); >+ if (!preconditions) >+ { >+ throw new RuntimeException("Model1 does not meet prerequirements for this test"); >+ } >+ >+ resource1 = tx.createResource(RESOURCENAME); >+ company1 = Model1Factory.eINSTANCE.createCompany(); >+ company2 = Model1Factory.eINSTANCE.createCompany(); >+ company3 = Model1Factory.eINSTANCE.createCompany(); >+ company99 = Model1Factory.eINSTANCE.createCompany(); >+ supplier1 = Model1Factory.eINSTANCE.createSupplier(); >+ purchaseOrder = Model1Factory.eINSTANCE.createPurchaseOrder(); >+ company1.getPurchaseOrders().add(purchaseOrder); >+ resource1.getContents().add(company1); >+ resource1.getContents().add(company2); >+ resource1.getContents().add(company3); >+ resource1.getContents().add(company99); >+ resource1.getContents().add(supplier1); >+ tx.commit(); >+ } >+ >+ private void simpleModel4ContainmentSetup() throws CommitException >+ { >+ EReference ref = model4Package.eINSTANCE.getRefSingleContainedNPL_Element(); >+ boolean preconditions = ref.isContainment() && ref.getEOpposite() == null && !ref.isMany(); >+ if (!preconditions) >+ { >+ throw new RuntimeException("Model4 does not meet prerequirements for this test"); >+ } >+ >+ resource1 = tx.createResource(RESOURCENAME); >+ >+ refSingleContained1 = model4Factory.eINSTANCE.createRefSingleContainedNPL(); >+ refSingleContained2 = model4Factory.eINSTANCE.createRefSingleContainedNPL(); >+ singleContainedElement1 = model4Factory.eINSTANCE.createContainedElementNoOpposite(); >+ refSingleContained1.setElement(singleContainedElement1); >+ resource1.getContents().add(refSingleContained1); >+ resource1.getContents().add(refSingleContained2); >+ >+ tx.commit(); >+ } >+ >+ private void simpleModel4SingleBidiSetup() throws CommitException >+ { >+ EReference ref = model4Package.eINSTANCE.getRefSingleNonContained_Element(); >+ boolean preconditions = !ref.isContainment() && ref.getEOpposite() != null && !ref.isMany(); >+ if (!preconditions) >+ { >+ throw new RuntimeException("Model4 does not meet prerequirements for this test"); >+ } >+ >+ resource1 = tx.createResource(RESOURCENAME); >+ >+ refSingleNonContained1 = model4Factory.eINSTANCE.createRefSingleNonContained(); >+ refSingleNonContained2 = model4Factory.eINSTANCE.createRefSingleNonContained(); >+ singleNonContainedElement1 = model4Factory.eINSTANCE.createSingleNonContainedElement(); >+ singleNonContainedElement2 = model4Factory.eINSTANCE.createSingleNonContainedElement(); >+ refSingleNonContained1.setElement(singleNonContainedElement1); >+ resource1.getContents().add(refSingleNonContained1); >+ resource1.getContents().add(refSingleNonContained2); >+ resource1.getContents().add(singleNonContainedElement1); >+ resource1.getContents().add(singleNonContainedElement2); >+ >+ tx.commit(); >+ } >+ >+ private void simpleModel4MultiBidiSetup() throws CommitException >+ { >+ EReference ref = model4Package.eINSTANCE.getRefMultiNonContained_Elements(); >+ boolean preconditions = !ref.isContainment() && ref.getEOpposite() != null && ref.isMany(); >+ if (!preconditions) >+ { >+ throw new RuntimeException("Model4 does not meet prerequirements for this test"); >+ } >+ >+ resource1 = tx.createResource(RESOURCENAME); >+ >+ refMultiNonContained1 = model4Factory.eINSTANCE.createRefMultiNonContained(); >+ refMultiNonContained2 = model4Factory.eINSTANCE.createRefMultiNonContained(); >+ multiNonContainedElement1 = model4Factory.eINSTANCE.createMultiNonContainedElement(); >+ multiNonContainedElement2 = model4Factory.eINSTANCE.createMultiNonContainedElement(); >+ refMultiNonContained1.getElements().add(multiNonContainedElement1); >+ resource1.getContents().add(refMultiNonContained1); >+ resource1.getContents().add(refMultiNonContained2); >+ resource1.getContents().add(multiNonContainedElement1); >+ resource1.getContents().add(multiNonContainedElement2); >+ >+ tx.commit(); >+ } >+ >+ private Set<EObject> createSet(EObject... objects) >+ { >+ Set<EObject> committables = new HashSet<EObject>(); >+ for (EObject o : objects) >+ { >+ if (o == null) >+ { >+ throw new NullPointerException(); >+ } >+ committables.add(o); >+ } >+ return committables; >+ } >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 312535
:
178373
|
178678
|
178715