diff options
Diffstat (limited to 'plugins/org.eclipse.emf.cdo/src/org/eclipse')
19 files changed, 918 insertions, 388 deletions
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 6d1da1d676..3b36ffbcc0 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 @@ -744,7 +744,6 @@ public class CDOResourceImpl extends CDOResourceLeafImpl implements InternalCDOR return uriFragmentPath; } - private EObject getEObject(List<String> uriFragmentPath) { int size = uriFragmentPath.size(); diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOPushTransaction.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOPushTransaction.java index 4600a68f9d..37c51936df 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOPushTransaction.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOPushTransaction.java @@ -196,11 +196,17 @@ public class CDOPushTransaction extends Notifier implements CDOTransaction return CDOPushTransaction.this; } + @Deprecated public Type getType() { return Type.COMMITTED; } + public Cause getCause() + { + return Cause.COMMITTED; + } + public Map<CDOID, CDOID> getIDMappings() { return Collections.emptyMap(); @@ -655,15 +661,15 @@ public class CDOPushTransaction extends Notifier implements CDOTransaction public void lockObjects(Collection<? extends CDOObject> objects, LockType lockType, long timeout) throws InterruptedException - { + { delegate.lockObjects(objects, lockType, timeout); - } + } public void lockObjects(Collection<? extends CDOObject> objects, LockType lockType, long timeout, boolean recursive) throws InterruptedException - { + { delegate.lockObjects(objects, lockType, timeout, recursive); - } + } public Options options() { @@ -677,9 +683,9 @@ public class CDOPushTransaction extends Notifier implements CDOTransaction public CloseableIterator<CDOResourceNode> queryResourcesAsync(CDOResourceFolder folder, String name, boolean exactMatch) - { + { return delegate.queryResourcesAsync(folder, name, exactMatch); - } + } /** * @since 4.3 @@ -712,9 +718,9 @@ public class CDOPushTransaction extends Notifier implements CDOTransaction public CloseableIterator<CDOObjectReference> queryXRefsAsync(Set<CDOObject> targetObjects, EReference... sourceReferences) - { + { return delegate.queryXRefsAsync(targetObjects, sourceReferences); - } + } @Deprecated public int reload(CDOObject... objects) diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOTransaction.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOTransaction.java index d7afe27671..13afc46c5b 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOTransaction.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOTransaction.java @@ -225,6 +225,11 @@ public interface CDOTransaction extends CDOView, CDOCommonTransaction, CDOUserTr public interface Options extends CDOView.Options { /** + * @since 4.3 + */ + public static final CDOUndoDetector DEFAULT_UNDO_DETECTOR = CDOUndoDetector.ALL_FEATURES; + + /** * Returns the {@link CDOTransaction transaction} of this options object. * * @since 4.0 @@ -232,6 +237,20 @@ public interface CDOTransaction extends CDOView, CDOCommonTransaction, CDOUserTr public CDOTransaction getContainer(); /** + * Returns the undo detector of this transaction. + * + * @since 4.3 + */ + public CDOUndoDetector getUndoDetector(); + + /** + * Sets the undo detector of this transaction. + * + * @since 4.3 + */ + public void setUndoDetector(CDOUndoDetector undoDetector); + + /** * Returns a copy of the conflict resolver list of this transaction. */ public CDOConflictResolver[] getConflictResolvers(); @@ -271,6 +290,19 @@ public interface CDOTransaction extends CDOView, CDOCommonTransaction, CDOUserTr /** * An {@link IOptionsEvent options event} fired from transaction {@link CDOTransaction#options() options} when the + * {@link Options#setUndoDetector(CDOUndoDetector) undo detector} option has changed. + * + * @author Eike Stepper + * @since 4.3 + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ + public interface UndoDetectorEvent extends IOptionsEvent + { + } + + /** + * An {@link IOptionsEvent options event} fired from transaction {@link CDOTransaction#options() options} when the * {@link Options#addConflictResolver(CDOConflictResolver) conflict resolvers} option has changed. * * @author Eike Stepper diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOTransactionFinishedEvent.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOTransactionFinishedEvent.java index b2d4fb3fb2..9cf0da679f 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOTransactionFinishedEvent.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOTransactionFinishedEvent.java @@ -19,7 +19,7 @@ import java.util.Map; * A {@link CDOViewEvent view event} fired from a {@link CDOTransaction transaction} when it becomes * {@link CDOTransaction#isDirty() clean} after a sucessful {@link CDOTransaction#commit() commit} or * {@link CDOTransaction#rollback() rollback}. - * + * * @author Eike Stepper * @since 2.0 * @noextend This interface is not intended to be extended by clients. @@ -27,18 +27,41 @@ import java.util.Map; */ public interface CDOTransactionFinishedEvent extends CDOViewEvent { + /** + * @deprecated As of 4.3 use {@link #getCause()}. + */ + @Deprecated public Type getType(); + /** + * @since 4.3 + */ + public Cause getCause(); + public Map<CDOID, CDOID> getIDMappings(); /** * Enumerates the possible {@link CDOTransactionFinishedEvent#getType() causes} for a {@link CDOTransaction * transaction} to become finished. - * + * * @author Eike Stepper + * @deprecated As of 4.3 use {@link Cause}. */ + @Deprecated public enum Type { COMMITTED, ROLLED_BACK } + + /** + * Enumerates the possible {@link CDOTransactionFinishedEvent#getCause() causes} for a {@link CDOTransaction + * transaction} to become finished. + * + * @author Eike Stepper + * @since 4.3 + */ + public enum Cause + { + COMMITTED, ROLLED_BACK, UNDONE + } } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOUndoDetector.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOUndoDetector.java new file mode 100644 index 0000000000..93ce378265 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOUndoDetector.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014 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: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.emf.cdo.transaction; + +import org.eclipse.emf.cdo.common.revision.CDORevision; +import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta; + +import org.eclipse.emf.internal.cdo.transaction.CDOUndoDetectorImpl; + +import org.eclipse.emf.ecore.EObject; + +/** + * A strategy used to detect whether the feature of an {@link EObject object} has the original (clean) value after a number of modifications. + * + * @see CDOTransaction.Options#setUndoDetector(CDOUndoDetector) + * @author Eike Stepper + * @since 4.3 + */ +public interface CDOUndoDetector +{ + public static final CDOUndoDetector NO_FEATURES = new CDOUndoDetectorImpl.NoFeatures(); + + public static final CDOUndoDetector SINGLE_VALUED_FEATURES = new CDOUndoDetectorImpl.SingleValuedFeatures(); + + public static final CDOUndoDetector ALL_FEATURES = new CDOUndoDetectorImpl(); + + public boolean detectUndo(CDOTransaction transaction, CDORevision cleanRevision, CDORevision revision, + CDOFeatureDelta featureDelta); +} diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CDOUtil.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CDOUtil.java index 5d6006878d..9ebed60f0e 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CDOUtil.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CDOUtil.java @@ -54,6 +54,7 @@ import org.eclipse.emf.internal.cdo.transaction.CDOXATransactionImpl; import org.eclipse.emf.internal.cdo.transaction.CDOXATransactionImpl.CDOXAInternalAdapter; import org.eclipse.emf.internal.cdo.view.CDORevisionPrefetchingPolicyImpl; import org.eclipse.emf.internal.cdo.view.CDOStateMachine; +import org.eclipse.emf.internal.cdo.view.CDOStoreImpl; import org.eclipse.net4j.util.AdapterUtil; import org.eclipse.net4j.util.container.IPluginContainer; @@ -427,8 +428,7 @@ public final class CDOUtil try { - EStore eStore = cdoObject.eStore(); - eStore.remove(cdoObject, eFeature, index); + CDOStoreImpl.removeElement(cdoObject, eFeature, index); } catch (ObjectNotFoundException ex) { 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 d349ba52f4..04ede44ba9 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 @@ -417,7 +417,7 @@ public class CDOObjectImpl extends MinimalEStoreEObjectImpl implements InternalC */ public final void cdoInternalPostInvalidate() { - // Do nothing + cdoInternalSetRevision(null); } public final void cdoInternalPostAttach() @@ -1217,38 +1217,38 @@ public class CDOObjectImpl extends MinimalEStoreEObjectImpl implements InternalC * Adjust the reference ONLY if the opposite reference used CDOID. This is true ONLY if the state of <cdo>this</code> * was not {@link CDOState#NEW}. */ - private static void adjustOppositeReference(InternalCDOObject instance, InternalEObject object, EReference feature) + private static void adjustOppositeReference(InternalCDOObject instance, InternalEObject opposite, + EReference oppositeReference) { - if (object != null) + if (opposite != null) { - InternalCDOObject cdoObject = (InternalCDOObject)CDOUtil.getCDOObject(object); + InternalCDOObject cdoObject = (InternalCDOObject)CDOUtil.getCDOObject(opposite); if (cdoObject != null && !FSMUtil.isTransient(cdoObject)) { - if (feature.isMany()) + if (oppositeReference.isMany()) { EStore eStore = cdoObject.eStore(); - int index = eStore.indexOf(cdoObject, feature, instance.cdoID()); - + int index = eStore.indexOf(cdoObject, oppositeReference, instance.cdoID()); if (index != -1) { - eStore.set(cdoObject, feature, index, instance); + eStore.set(cdoObject, oppositeReference, index, instance); } } else { EStore eStore = cdoObject.eStore(); - eStore.set(cdoObject, feature, 0, instance); + eStore.set(cdoObject, oppositeReference, 0, instance); } } else { - if (feature.isResolveProxies()) + if (oppositeReference.isResolveProxies()) { // We should not trigger events. But we have no choice :-(. - if (feature.isMany()) + if (oppositeReference.isMany()) { @SuppressWarnings("unchecked") - List<Object> list = (List<Object>)object.eGet(feature); + List<Object> list = (List<Object>)opposite.eGet(oppositeReference); int index = list.indexOf(instance); if (index != -1) { @@ -1257,7 +1257,7 @@ public class CDOObjectImpl extends MinimalEStoreEObjectImpl implements InternalC } else { - object.eSet(feature, instance); + opposite.eSet(oppositeReference, instance); } } } @@ -1283,6 +1283,7 @@ public class CDOObjectImpl extends MinimalEStoreEObjectImpl implements InternalC { TRACER.format("Filtering value of feature {0}", feature); //$NON-NLS-1$ } + setting = filter.getPersistableValue(object, setting); } @@ -1298,15 +1299,15 @@ public class CDOObjectImpl extends MinimalEStoreEObjectImpl implements InternalC EList<Object> list = (EList<Object>)setting; for (Object value : list) { - value = cdoStore.convertToCDO(object, feature, value); - revision.add(feature, index++, value); + Object cdoValue = cdoStore.convertToCDO(object, feature, value); + revision.add(feature, index++, cdoValue); } } } else { - setting = cdoStore.convertToCDO(object, feature, setting); - revision.set(feature, 0, setting); + Object cdoValue = cdoStore.convertToCDO(object, feature, setting); + revision.set(feature, 0, cdoValue); } } @@ -1335,21 +1336,21 @@ public class CDOObjectImpl extends MinimalEStoreEObjectImpl implements InternalC { // Do not trigger events // Do not trigger inverse updates - Object object = cdoStore.get(instance, eFeature, index); - eStore.add(instance, eFeature, index, object); + Object opposite = cdoStore.get(instance, eFeature, index); + eStore.add(instance, eFeature, index, opposite); if (oppositeReference != null) { - adjustOppositeReference(instance, (InternalEObject)object, oppositeReference); + adjustOppositeReference(instance, (InternalEObject)opposite, oppositeReference); } } } else { - Object object = cdoStore.get(instance, eFeature, EStore.NO_INDEX); - eStore.set(instance, eFeature, EStore.NO_INDEX, object); + Object opposite = cdoStore.get(instance, eFeature, EStore.NO_INDEX); + eStore.set(instance, eFeature, EStore.NO_INDEX, opposite); if (oppositeReference != null) { - adjustOppositeReference(instance, (InternalEObject)object, oppositeReference); + adjustOppositeReference(instance, (InternalEObject)opposite, oppositeReference); } } } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDOLegacyListener.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDOLegacyListener.java index 81b5f7c254..5bff08aba4 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDOLegacyListener.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDOLegacyListener.java @@ -95,7 +95,7 @@ public final class CDOLegacyListener extends CDOLegacyWrapper try { handlingCallback = true; - CDOStateMachine.INSTANCE.write(this); + CDOStateMachine.INSTANCE.write(this, null); // TODO Optimize this when the list position index is added to the new callbacks resolveAllProxies(); diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDOLegacyWrapper.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDOLegacyWrapper.java index 374194b7f7..62ec57d5dd 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDOLegacyWrapper.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDOLegacyWrapper.java @@ -369,14 +369,22 @@ public abstract class CDOLegacyWrapper extends CDOObjectWrapper public void cdoInternalPostInvalidate() { - if (cdoState() != CDOState.CLEAN) + if (cdoState() != CDOState.PROXY) { - InternalCDORevision revision = cdoView().getRevision(cdoID(), true); - cdoInternalSetRevision(revision); + throw new IllegalStateException(); } - revisionToInstance(); - cdoInternalSetState(CDOState.CLEAN); + InternalCDORevision revision = cdoView().getRevision(cdoID(), true); + if (revision == null) + { + cdoInternalPostDetach(true); + } + else + { + cdoInternalSetRevision(revision); + revisionToInstance(); + cdoInternalSetState(CDOState.CLEAN); + } } protected void instanceToRevision() diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java index 4aa88a6780..efcdb2010e 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java @@ -2022,7 +2022,7 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl impleme try { - revisionDelta.apply(newRevision); + revisionDelta.applyTo(newRevision); } finally { diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOSingleTransactionStrategyImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOSingleTransactionStrategyImpl.java index 199247be0b..1fd7a2a228 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOSingleTransactionStrategyImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOSingleTransactionStrategyImpl.java @@ -23,11 +23,8 @@ import org.eclipse.emf.cdo.util.OptimisticLockingException; import org.eclipse.emf.cdo.util.ReferentialIntegrityException; import org.eclipse.emf.cdo.util.ValidationException; -import org.eclipse.emf.internal.cdo.bundle.OM; - import org.eclipse.net4j.util.om.monitor.EclipseMonitor; import org.eclipse.net4j.util.om.monitor.OMMonitor; -import org.eclipse.net4j.util.om.trace.ContextTracer; import org.eclipse.emf.spi.cdo.CDOSessionProtocol; import org.eclipse.emf.spi.cdo.CDOSessionProtocol.CommitTransactionResult; @@ -48,29 +45,21 @@ public class CDOSingleTransactionStrategyImpl implements CDOTransactionStrategy { public static final CDOSingleTransactionStrategyImpl INSTANCE = new CDOSingleTransactionStrategyImpl(); - private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_TRANSACTION, - CDOSingleTransactionStrategyImpl.class); - public CDOSingleTransactionStrategyImpl() { } public CDOCommitInfo commit(InternalCDOTransaction transaction, IProgressMonitor progressMonitor) throws Exception { - String comment = transaction.getCommitComment(); InternalCDOCommitContext commitContext = transaction.createCommitContext(); - if (TRACER.isEnabled()) - { - TRACER.format("CDOCommitContext.preCommit"); //$NON-NLS-1$ - } + CDOCommitData commitData = commitContext.getCommitData(); commitContext.preCommit(); - CDOCommitData commitData = commitContext.getCommitData(); InternalCDOSession session = transaction.getSession(); + CDOSessionProtocol sessionProtocol = session.getSessionProtocol(); OMMonitor monitor = new EclipseMonitor(progressMonitor); - CDOSessionProtocol sessionProtocol = session.getSessionProtocol(); CommitTransactionResult result = sessionProtocol.commitTransaction(commitContext, monitor); commitContext.postCommit(result); @@ -104,6 +93,7 @@ public class CDOSingleTransactionStrategyImpl implements CDOTransactionStrategy } } + String comment = transaction.getCommitComment(); transaction.setCommitComment(null); long previousTimeStamp = result.getPreviousTimeStamp(); diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java index 2c1a99e7cf..4706d4ba6c 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java @@ -102,6 +102,7 @@ import org.eclipse.emf.cdo.transaction.CDOTransactionHandler2; import org.eclipse.emf.cdo.transaction.CDOTransactionHandler3; import org.eclipse.emf.cdo.transaction.CDOTransactionHandlerBase; import org.eclipse.emf.cdo.transaction.CDOTransactionStartedEvent; +import org.eclipse.emf.cdo.transaction.CDOUndoDetector; import org.eclipse.emf.cdo.transaction.CDOUserSavepoint; import org.eclipse.emf.cdo.util.CDOURIUtil; import org.eclipse.emf.cdo.util.CDOUtil; @@ -248,7 +249,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa /** * A map to hold a clean (i.e. unmodified) revision for objects that have been modified or detached. */ - private Map<InternalCDOObject, InternalCDORevision> cleanRevisions = new ResolvingRevisionMap(); + private Map<InternalCDOObject, InternalCDORevision> cleanRevisions = new CleanRevisionsMap(); public CDOTransactionImpl(CDOBranch branch) { @@ -394,7 +395,17 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa public void setDirty(boolean dirty) { - this.dirty = dirty; + if (this.dirty != dirty) + { + this.dirty = dirty; + + IListener[] listeners = getListeners(); + if (listeners != null) + { + IEvent event = dirty ? new StartedEvent() : new FinishedEvent(false); + fireEvent(event, listeners); + } + } } @Override @@ -601,7 +612,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa registerObject(object); registerAttached(object, true); result.add(revision); - dirty = true; + setDirty(true); } } } @@ -618,7 +629,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa result.add(CDOIDUtil.createIDAndVersion(id, CDOBranchVersion.UNSPECIFIED_VERSION)); CDOStateMachine.INSTANCE.detach(object); detachedSet.add(object); - dirty = true; + setDirty(true); } } @@ -663,7 +674,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa } goalRevision.setRevised(CDOBranchPoint.UNSPECIFIED_DATE); - ancestorGoalDelta.apply(goalRevision); + ancestorGoalDelta.applyTo(goalRevision); InternalCDORevisionDelta targetGoalDelta = goalRevision.compare(targetRevision); targetGoalDelta.setTarget(null); @@ -689,7 +700,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa revisionChanged = true; dirtyObjects.put(id, object); - dirty = true; + setDirty(true); } if (revisionChanged) @@ -1532,16 +1543,6 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa // here be removed from the collection of reattached objects lastSavepoint.getReattachedObjects().remove(id); } - - if (!dirty) - { - dirty = true; - IListener[] listeners = getListeners(); - if (listeners != null) - { - fireEvent(new StartedEvent(), listeners); - } - } } /** @@ -1638,11 +1639,10 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa } } - Map<CDOID, CDOID> idMappings = Collections.emptyMap(); IListener[] listeners = getListeners(); if (listeners != null) { - fireEvent(new FinishedEvent(CDOTransactionFinishedEvent.Type.ROLLED_BACK, idMappings), listeners); + fireEvent(new FinishedEvent(true), listeners); } CDOTransactionHandler2[] handlers = getTransactionHandlers2(); @@ -1694,6 +1694,11 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa return (InternalCDOSavepoint)getTransactionStrategy().setSavepoint(this); } + public boolean hasMultipleSavepoints() + { + return lastSavepoint != firstSavepoint; + } + private void addToBase(Map<CDOID, CDOObject> objects) { for (CDOObject object : objects.values()) @@ -1744,18 +1749,53 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa } } + private CDOOriginSizeProvider getOriginSizeProvider(InternalCDOObject object, CDOFeatureDelta featureDelta, + InternalCDORevision cleanRevision) + { + EStructuralFeature feature = featureDelta.getFeature(); + if (feature.isMany()) + { + if (cleanRevision == null) + { + cleanRevision = cleanRevisions.get(object); + if (cleanRevision == null) + { + cleanRevision = object.cdoRevision(); + } + } + + CDOList list = cleanRevision.getList(feature); + final int originSize = list.size(); + + return new CDOOriginSizeProvider() + { + public int getOriginSize() + { + return originSize; + } + }; + } + + return null; + } + /** * Receives notification for new and dirty objects */ - public synchronized void registerFeatureDelta(final InternalCDOObject object, final CDOFeatureDelta featureDelta) + public synchronized void registerFeatureDelta(InternalCDOObject object, CDOFeatureDelta featureDelta) + { + registerFeatureDelta(object, featureDelta, null); + } + + public synchronized void registerFeatureDelta(InternalCDOObject object, CDOFeatureDelta featureDelta, + InternalCDORevision cleanRevision) { CDOID id = object.cdoID(); boolean needToSaveFeatureDelta = true; if (object.cdoState() == CDOState.NEW) { - // Register Delta for new objects only if objectA doesn't belong to - // this savepoint + // Register Delta for new objects only if objectA doesn't belong to this savepoint if (getLastSavepoint().getPreviousSavepoint() == null || featureDelta == null) { needToSaveFeatureDelta = false; @@ -1769,31 +1809,18 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa if (needToSaveFeatureDelta) { - final InternalCDORevision revision = object.cdoRevision(); - - CDORevisionDelta revisionDelta = lastSavepoint.getRevisionDeltas2().get(id); + Map<CDOID, CDORevisionDelta> revisionDeltas = lastSavepoint.getRevisionDeltas2(); + InternalCDORevisionDelta revisionDelta = (InternalCDORevisionDelta)revisionDeltas.get(id); if (revisionDelta == null) { - revisionDelta = CDORevisionUtil.createDelta(revision); - lastSavepoint.getRevisionDeltas2().put(id, revisionDelta); - } + InternalCDORevision revision = object.cdoRevision(); - ((InternalCDORevisionDelta)revisionDelta).addFeatureDelta(featureDelta, new CDOOriginSizeProvider() - { - public int getOriginSize() - { - EStructuralFeature feature = featureDelta.getFeature(); - InternalCDORevision cleanRevision = cleanRevisions.get(object); - if (cleanRevision == null) - { - // Clean revision has *not yet* been registered, in this case the object revision *is still clean* - cleanRevision = revision; - } + revisionDelta = (InternalCDORevisionDelta)CDORevisionUtil.createDelta(revision); + revisionDeltas.put(id, revisionDelta); + } - CDOList list = cleanRevision.getList(feature); - return list.size(); - } - }); + CDOOriginSizeProvider originSizeProvider = getOriginSizeProvider(object, featureDelta, cleanRevision); + revisionDelta.addFeatureDelta(featureDelta, originSizeProvider); } CDOTransactionHandler1[] handlers = getTransactionHandlers1(); @@ -1814,7 +1841,12 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa } } - public synchronized void registerDirty(InternalCDOObject object, CDOFeatureDelta featureDelta) + public void registerDirty(InternalCDOObject object, CDOFeatureDelta featureDelta) + { + registerDirty(object, featureDelta, null); + } + + public void registerDirty(InternalCDOObject object, CDOFeatureDelta featureDelta, InternalCDORevision cleanRevision) { if (TRACER.isEnabled()) { @@ -1823,7 +1855,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa if (featureDelta != null) { - registerFeatureDelta(object, featureDelta); + registerFeatureDelta(object, featureDelta, cleanRevision); } registerNew(lastSavepoint.getDirtyObjects(), object); @@ -1841,15 +1873,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa throw new IllegalStateException(MessageFormat.format(Messages.getString("CDOTransactionImpl.10"), object)); //$NON-NLS-1$ } - if (!dirty) - { - dirty = true; - IListener[] listeners = getListeners(); - if (listeners != null) - { - fireEvent(new StartedEvent(), listeners); - } - } + setDirty(true); } public synchronized List<CDOPackageUnit> analyzeNewPackages() @@ -2726,24 +2750,60 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa /** * @author Eike Stepper */ - private final class ResolvingRevisionMap extends HashMap<InternalCDOObject, InternalCDORevision> + private final class CleanRevisionsMap extends HashMap<InternalCDOObject, InternalCDORevision> { private static final long serialVersionUID = 1L; - public ResolvingRevisionMap() + public CleanRevisionsMap() { } @Override - public InternalCDORevision get(Object cdoObject) + public InternalCDORevision get(Object key) { - InternalCDORevision revision = super.get(cdoObject); - if (revision != null) + if (key instanceof EObject) { - getSession().resolveAllElementProxies(revision); + CDOObject cdoObject = CDOUtil.getCDOObject((EObject)key); + InternalCDORevision revision = super.get(cdoObject); + if (revision != null) + { + getSession().resolveAllElementProxies(revision); + } + + return revision; } - return revision; + return null; + } + + @Override + public InternalCDORevision remove(Object key) + { + if (key instanceof EObject) + { + CDOObject cdoObject = CDOUtil.getCDOObject((EObject)key); + return super.remove(cdoObject); + } + + return null; + } + + @Override + public boolean containsKey(Object key) + { + if (key instanceof EObject) + { + CDOObject cdoObject = CDOUtil.getCDOObject((EObject)key); + return super.containsKey(cdoObject); + } + + return false; + } + + @Override + public Set<InternalCDOObject> keySet() + { + throw new UnsupportedOperationException(); } } @@ -3084,8 +3144,9 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa if (session.isSticky()) { CDOBranchPoint commitBranchPoint = CDOBranchUtil.copyBranchPoint(result); - for (CDOObject object : getNewObjects().values()) // Note: keyset() does not work because ID mappings are - // not applied there! + + // Note: keyset() does not work because ID mappings are not applied there! + for (CDOObject object : getNewObjects().values()) { session.setCommittedSinceLastRefresh(object.cdoID(), commitBranchPoint); } @@ -3130,7 +3191,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa } Map<CDOID, CDOID> idMappings = result.getIDMappings(); - fireEvent(new FinishedEvent(CDOTransactionFinishedEvent.Type.COMMITTED, idMappings), listeners); + fireEvent(new FinishedEvent(idMappings), listeners); } CDOLockState[] newLockStates = result.getNewLockStates(); @@ -3226,19 +3287,42 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa { private static final long serialVersionUID = 1L; - private Type type; + private final Cause cause; - private Map<CDOID, CDOID> idMappings; + private final Map<CDOID, CDOID> idMappings; - private FinishedEvent(Type type, Map<CDOID, CDOID> idMappings) + private FinishedEvent(Map<CDOID, CDOID> idMappings) { - this.type = type; + cause = Cause.COMMITTED; this.idMappings = idMappings; } + private FinishedEvent(boolean rolledBack) + { + cause = rolledBack ? Cause.ROLLED_BACK : Cause.UNDONE; + idMappings = Collections.emptyMap(); + } + + @Deprecated public Type getType() { - return type; + switch (cause) + { + case COMMITTED: + return Type.COMMITTED; + + case ROLLED_BACK: + case UNDONE: + return Type.ROLLED_BACK; + + default: + throw new IllegalStateException("Illegal cause: " + cause); + } + } + + public Cause getCause() + { + return cause; } public Map<CDOID, CDOID> getIDMappings() @@ -3249,8 +3333,8 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa @Override public String toString() { - return MessageFormat.format("CDOTransactionFinishedEvent[source={0}, type={1}, idMappings={2}]", getSource(), //$NON-NLS-1$ - getType(), idMappings == null ? 0 : idMappings.size()); + return MessageFormat.format("CDOTransactionFinishedEvent[source={0}, cause={1}, idMappings={2}]", getSource(), //$NON-NLS-1$ + getCause(), idMappings == null ? 0 : idMappings.size()); } } @@ -3295,6 +3379,8 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa */ protected final class OptionsImpl extends CDOViewImpl.OptionsImpl implements CDOTransaction.Options { + private CDOUndoDetector undoDetector = DEFAULT_UNDO_DETECTOR; + private List<CDOConflictResolver> conflictResolvers = new ArrayList<CDOConflictResolver>(); private boolean autoReleaseLocksEnabled = true; @@ -3303,6 +3389,33 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa { } + public CDOUndoDetector getUndoDetector() + { + return undoDetector; + } + + public void setUndoDetector(CDOUndoDetector undoDetector) + { + checkActive(); + + if (undoDetector == null) + { + undoDetector = DEFAULT_UNDO_DETECTOR; + } + + IEvent event = null; + synchronized (CDOTransactionImpl.this) + { + if (this.undoDetector != undoDetector) + { + this.undoDetector = undoDetector; + event = new UndoDetectorEventImpl(); + } + } + + fireEvent(event); + } + @Override public CDOTransactionImpl getContainer() { @@ -3429,6 +3542,19 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa /** * @author Eike Stepper */ + private final class UndoDetectorEventImpl extends OptionsEvent implements UndoDetectorEvent + { + private static final long serialVersionUID = 1L; + + public UndoDetectorEventImpl() + { + super(OptionsImpl.this); + } + } + + /** + * @author Eike Stepper + */ private final class ConflictResolversEventImpl extends OptionsEvent implements ConflictResolversEvent { private static final long serialVersionUID = 1L; diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOUndoDetectorImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOUndoDetectorImpl.java new file mode 100644 index 0000000000..68947b213b --- /dev/null +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOUndoDetectorImpl.java @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2014 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: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.emf.internal.cdo.transaction; + +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.revision.CDORevision; +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.CDOFeatureDelta.Type; +import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; +import org.eclipse.emf.cdo.transaction.CDOTransaction; +import org.eclipse.emf.cdo.transaction.CDOUndoDetector; + +import org.eclipse.net4j.util.ObjectUtil; + +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EStructuralFeature; + +import java.util.Iterator; +import java.util.List; + +/** + * @author Eike Stepper + * @since 4.3 + */ +public class CDOUndoDetectorImpl implements CDOUndoDetector +{ + public boolean detectUndo(CDOTransaction transaction, CDORevision cleanRevision, CDORevision revision, + CDOFeatureDelta featureDelta) + { + EStructuralFeature feature = featureDelta.getFeature(); + if (ignore(feature)) + { + return false; + } + + if (ignore(cleanRevision)) + { + return false; + } + + if (ignore(revision)) + { + return false; + } + + InternalCDORevision rev1 = (InternalCDORevision)cleanRevision; + InternalCDORevision rev2 = (InternalCDORevision)revision; + + if (featureDelta.getType() == Type.CONTAINER) + { + // return false; + return detectUndoContainer(transaction, rev1, rev2, (CDOContainerFeatureDelta)featureDelta); + } + + Object value1 = rev1.getValue(feature); + Object value2 = rev2.getValue(feature); + + if (feature instanceof EReference) + { + if (feature.isMany()) + { + List<?> list1 = (List<?>)value1; + List<?> list2 = (List<?>)value2; + + int size1 = size(list1); + int size2 = size(list2); + + if (size1 != size2) + { + return false; + } + + if (size1 != 0) + { + for (Iterator<?> it1 = list1.iterator(), it2 = list2.iterator(); it1.hasNext();) + { + Object id1 = getID(it1.next()); + Object id2 = getID(it2.next()); + if (id1 != id2) + { + return false; + } + } + } + + return true; + } + + value1 = getID(value1); + value2 = getID(value2); + return value1 == value2; + } + + return ObjectUtil.equals(value1, value2); + } + + protected boolean detectUndoContainer(CDOTransaction transaction, InternalCDORevision cleanRevision, + InternalCDORevision revision, CDOContainerFeatureDelta featureDelta) + { + CDOID resourceID1 = cleanRevision.getResourceID(); + CDOID resourceID2 = revision.getResourceID(); + if (resourceID1 != resourceID2) + { + return false; + } + + int containingFeatureID1 = cleanRevision.getContainingFeatureID(); + int containingFeatureID2 = revision.getContainingFeatureID(); + if (containingFeatureID1 != containingFeatureID2) + { + return false; + } + + Object c1 = cleanRevision.getContainerID(); + Object c2 = revision.getContainerID(); + + // Potentially most expensive check because of EObject/ID conversion + Object containerID1 = getID(c1); + Object containerID2 = getID(c2); + if (containerID1 != containerID2) + { + return false; + } + + return true; + } + + protected boolean ignore(EStructuralFeature feature) + { + return false; + } + + protected boolean ignore(CDORevision revision) + { + return !((InternalCDORevision)revision).isUnchunked(); + } + + private static Object getID(Object value) + { + // TODO Write tests to see if EObject instead of CDOID instances need special handling + // CDOID id = CDOIDUtil.getCDOID(value); + // if (id != null) + // { + // return id; + // } + + return value; + } + + private static int size(List<?> list) + { + if (list == null) + { + return 0; + } + + return list.size(); + } + + /** + * @author Eike Stepper + */ + public static final class NoFeatures extends CDOUndoDetectorImpl + { + @Override + protected boolean ignore(EStructuralFeature feature) + { + return true; + } + } + + /** + * @author Eike Stepper + */ + public static final class SingleValuedFeatures extends CDOUndoDetectorImpl + { + @Override + protected boolean ignore(EStructuralFeature feature) + { + return feature.isMany(); + } + } +} diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/AbstractCDOView.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/AbstractCDOView.java index e7eb49eaf3..1f265f9142 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/AbstractCDOView.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/AbstractCDOView.java @@ -1291,8 +1291,7 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb throw new DanglingReferenceException(eObject); } - throw new IllegalStateException(MessageFormat.format( - Messages.getString("CDOViewImpl.16"), idOrObject.getClass().getName())); //$NON-NLS-1$ + throw new IllegalStateException(MessageFormat.format(Messages.getString("CDOViewImpl.16"), idOrObject)); //$NON-NLS-1$ } public synchronized Object convertObjectToID(Object potentialObject) diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStateMachine.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStateMachine.java index e09c8f12c7..5ec19fdc48 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStateMachine.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStateMachine.java @@ -31,6 +31,8 @@ import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionCache; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager; import org.eclipse.emf.cdo.transaction.CDOTransaction; +import org.eclipse.emf.cdo.transaction.CDOUndoDetector; +import org.eclipse.emf.cdo.util.CDOUtil; import org.eclipse.emf.cdo.view.CDOInvalidationPolicy; import org.eclipse.emf.cdo.view.CDOView; @@ -128,7 +130,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent init(CDOState.CLEAN, CDOEvent.DETACH, new DetachTransition()); init(CDOState.CLEAN, CDOEvent.REATTACH, FAIL); init(CDOState.CLEAN, CDOEvent.READ, IGNORE); - init(CDOState.CLEAN, CDOEvent.WRITE, new WriteTransition()); + init(CDOState.CLEAN, CDOEvent.WRITE, new WriteTransition(false)); init(CDOState.CLEAN, CDOEvent.INVALIDATE, new InvalidateTransition()); init(CDOState.CLEAN, CDOEvent.DETACH_REMOTE, DetachRemoteTransition.INSTANCE); init(CDOState.CLEAN, CDOEvent.COMMIT, FAIL); @@ -149,8 +151,8 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent init(CDOState.PROXY, CDOEvent.ATTACH, FAIL); init(CDOState.PROXY, CDOEvent.DETACH, new DetachTransition()); init(CDOState.PROXY, CDOEvent.REATTACH, FAIL); - init(CDOState.PROXY, CDOEvent.READ, new LoadTransition(false)); - init(CDOState.PROXY, CDOEvent.WRITE, new LoadTransition(true)); + init(CDOState.PROXY, CDOEvent.READ, new LoadTransition()); + init(CDOState.PROXY, CDOEvent.WRITE, new WriteTransition(true)); init(CDOState.PROXY, CDOEvent.INVALIDATE, IGNORE); init(CDOState.PROXY, CDOEvent.DETACH_REMOTE, DetachRemoteTransition.INSTANCE); init(CDOState.PROXY, CDOEvent.COMMIT, FAIL); @@ -191,10 +193,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent } /** - * The object is already attached in EMF world. It contains all the information needed to know where it will be - * connected. - * - * @since 2.0 + * The object is already attached in EMF world. It contains all the information needed to know where it will be connected. */ public void attach(InternalCDOObject object, InternalCDOTransaction transaction) { @@ -263,9 +262,6 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent process(object, CDOEvent.REATTACH, transaction); } - /** - * @since 2.0 - */ public void detach(InternalCDOObject object) { synchronized (getMonitor(object)) @@ -302,9 +298,6 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent } } - /** - * @since 2.0 - */ public InternalCDORevision read(InternalCDOObject object) { synchronized (getMonitor(object)) @@ -315,14 +308,10 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent } process(object, CDOEvent.READ, null); - return object.cdoRevision(); } } - /** - * @since 2.0 - */ public InternalCDORevision readNoLoad(InternalCDOObject object) { synchronized (getMonitor(object)) @@ -343,38 +332,28 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent } } - /** - * @since 2.0 - */ - public void write(InternalCDOObject object) - { - write(object, null); - } - - /** - * @since 2.0 - */ - public void write(InternalCDOObject object, CDOFeatureDelta featureDelta) + public Object write(InternalCDOObject object, CDOFeatureDelta featureDelta) { synchronized (getMonitor(object)) { - writeWithoutViewLock(object, featureDelta); + return writeWithoutViewLock(object, featureDelta); } } - private void writeWithoutViewLock(InternalCDOObject object, CDOFeatureDelta featureDelta) + private Object writeWithoutViewLock(InternalCDOObject object, CDOFeatureDelta featureDelta) { if (TRACER.isEnabled()) { trace(object, CDOEvent.WRITE); } - process(object, CDOEvent.WRITE, featureDelta); + // TODO: Make FeatureDeltaAndResult constant + FeatureDeltaAndResult featureDeltaAndResult = new FeatureDeltaAndResult(featureDelta); + + process(object, CDOEvent.WRITE, featureDeltaAndResult); + return featureDeltaAndResult.getResult(); } - /** - * @since 2.0 - */ public void reload(InternalCDOObject... objects) { if (objects == null || objects.length == 0) @@ -397,9 +376,6 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent } } - /** - * @since 3.0 - */ public void invalidate(InternalCDOObject object, CDORevisionKey key) { synchronized (getMonitor(object)) @@ -413,9 +389,6 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent } } - /** - * @since 2.0 - */ public void detachRemote(InternalCDOObject object) { synchronized (getMonitor(object)) @@ -429,9 +402,6 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent } } - /** - * @since 2.0 - */ public void commit(InternalCDOObject object, CommitTransactionResult result) { synchronized (getMonitor(object)) @@ -445,9 +415,6 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent } } - /** - * @since 2.0 - */ public void rollback(InternalCDOObject object) { synchronized (getMonitor(object)) @@ -519,7 +486,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent CDORevisionDelta delta = savepoint.getRevisionDeltas2().get(id); if (delta != null) { - delta.apply(cleanRevision); + delta.applyTo(cleanRevision); } savepoint = savepoint.getNextSavepoint(); @@ -582,6 +549,60 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent } } + private void internalLoad(InternalCDOObject object, boolean forWrite) + { + object.cdoInternalPreLoad(); + + InternalCDOView view = object.cdoView(); + InternalCDORevision revision = view.getRevision(object.cdoID(), true); + if (revision == null) + { + INSTANCE.detachRemote(object); + CDOInvalidationPolicy policy = view.options().getInvalidationPolicy(); + policy.handleInvalidObject(object); + } + + if (forWrite && !revision.isWritable()) + { + throw new NoPermissionException(revision); + } + + object.cdoInternalSetRevision(revision); + changeState(object, CDOState.CLEAN); + object.cdoInternalPostLoad(); + dispatchLoadNotification(object); + } + + /** + * @author Eike Stepper + */ + public static final class FeatureDeltaAndResult + { + private final CDOFeatureDelta featureDelta; + + private Object result; + + public FeatureDeltaAndResult(CDOFeatureDelta featureDelta) + { + this.featureDelta = featureDelta; + } + + public CDOFeatureDelta getFeatureDelta() + { + return featureDelta; + } + + public Object getResult() + { + return result; + } + + public void setResult(Object result) + { + this.result = result; + } + } + /** * Prepares a tree of transient objects to be subsequently {@link AttachTransition attached} to a CDOView. * <p> @@ -719,11 +740,11 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent internalReattach(object, transaction); // Bug 385268 - InternalEObject reattachedObject = object.cdoInternalInstance(); + CDOID reattachedObject = object.cdoID(); processRevisionDeltas(reattachedObject, transaction); } - private void processRevisionDeltas(InternalEObject reattachedObject, InternalCDOTransaction transaction) + private void processRevisionDeltas(CDOID reattachedObject, InternalCDOTransaction transaction) { InternalCDOSavepoint lastSavepoint = transaction.getLastSavepoint(); Map<CDOID, CDORevisionDelta> revisionDeltas = lastSavepoint.getRevisionDeltas2(); @@ -741,7 +762,10 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent CDOID id = revisionDelta.getID(); InternalCDOObject cleanObject = (InternalCDOObject)lastSavepoint.getDirtyObjects().remove(id); - cleanObject.cdoInternalSetState(CDOState.CLEAN); + if (cleanObject != null) + { + cleanObject.cdoInternalSetState(CDOState.CLEAN); + } } } @@ -751,7 +775,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent } } - private void processFeatureDeltas(InternalEObject reattachedObject, Map<EStructuralFeature, CDOFeatureDelta> map) + private void processFeatureDeltas(CDOID reattachedObject, Map<EStructuralFeature, CDOFeatureDelta> map) { for (Iterator<Entry<EStructuralFeature, CDOFeatureDelta>> it = map.entrySet().iterator(); it.hasNext();) { @@ -761,22 +785,22 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent } } - private void processFeatureDelta(InternalEObject reattachedObject, Iterator<?> it, CDOFeatureDelta featureDelta) + private void processFeatureDelta(CDOID reattachedObject, Iterator<?> it, CDOFeatureDelta featureDelta) { switch (featureDelta.getType()) { case SET: CDOSetFeatureDelta setFeatureDelta = (CDOSetFeatureDelta)featureDelta; Object oldValue = setFeatureDelta.getOldValue(); - if (oldValue instanceof InternalCDOObject) + if (oldValue instanceof EObject) { - oldValue = ((InternalCDOObject)oldValue).cdoInternalInstance(); + oldValue = CDOUtil.getCDOObject((EObject)oldValue).cdoID(); } Object newValue = setFeatureDelta.getValue(); - if (newValue instanceof InternalCDOObject) + if (newValue instanceof EObject) { - newValue = ((InternalCDOObject)newValue).cdoInternalInstance(); + newValue = CDOUtil.getCDOObject((EObject)newValue).cdoID(); } if (reattachedObject == oldValue && reattachedObject == newValue) @@ -898,61 +922,157 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent /** * @author Eike Stepper */ - private final class WriteTransition implements ITransition<CDOState, CDOEvent, InternalCDOObject, Object> + private static abstract class AbstractWriteTransition implements + ITransition<CDOState, CDOEvent, InternalCDOObject, FeatureDeltaAndResult> { - public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Object featureDelta) + public void execute(InternalCDOObject object, CDOState state, CDOEvent event, + FeatureDeltaAndResult featureDeltaAndResult) { - InternalCDORevision cleanRevision = object.cdoRevision(); - if (!cleanRevision.isWritable()) + InternalCDORevision revision = object.cdoRevision(); + if (!revision.isWritable()) { - throw new NoPermissionException(cleanRevision); + throw new NoPermissionException(revision); } InternalCDOTransaction transaction = object.cdoView().toTransaction(); - transaction.getCleanRevisions().put(object, cleanRevision); + CDOFeatureDelta featureDelta = featureDeltaAndResult.getFeatureDelta(); + Object result = execute(object, transaction, featureDelta, revision); + featureDeltaAndResult.setResult(result); + } - // Copy revision - InternalCDORevision revision = object.cdoRevision().copy(); - object.cdoInternalSetRevision(revision); + protected abstract Object execute(InternalCDOObject object, InternalCDOTransaction transaction, + CDOFeatureDelta featureDelta, InternalCDORevision revision); + } - transaction.registerDirty(object, (CDOFeatureDelta)featureDelta); - changeState(object, CDOState.DIRTY); + /** + * @author Simon McDuff + */ + private final class WriteNewTransition extends AbstractWriteTransition + { + @Override + protected Object execute(InternalCDOObject object, InternalCDOTransaction transaction, + CDOFeatureDelta featureDelta, InternalCDORevision revision) + { + Object result = null; + if (featureDelta != null) + { + result = featureDelta.applyTo(revision); + } + + transaction.registerFeatureDelta(object, featureDelta); + return result; } } /** - * @author Simon McDuff + * @author Eike Stepper */ - private static final class WriteNewTransition implements ITransition<CDOState, CDOEvent, InternalCDOObject, Object> + private final class WriteTransition extends AbstractWriteTransition { - public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Object featureDelta) + private boolean load; + + public WriteTransition(boolean load) { - InternalCDORevision revision = object.cdoRevision(); - if (!revision.isWritable()) + this.load = load; + } + + @Override + public void execute(InternalCDOObject object, CDOState state, CDOEvent event, + FeatureDeltaAndResult featureDeltaAndResult) + { + if (load) { - throw new NoPermissionException(revision); + internalLoad(object, true); } - InternalCDOTransaction transaction = object.cdoView().toTransaction(); - transaction.registerFeatureDelta(object, (CDOFeatureDelta)featureDelta); + super.execute(object, state, event, featureDeltaAndResult); + } + + @Override + protected Object execute(InternalCDOObject object, InternalCDOTransaction transaction, + CDOFeatureDelta featureDelta, InternalCDORevision cleanRevision) + { + InternalCDORevision revision = cleanRevision.copy(); + + Object result = null; + if (featureDelta != null) + { + result = featureDelta.applyTo(revision); + + if (!transaction.hasMultipleSavepoints()) + { + CDOUndoDetector undoDetector = transaction.options().getUndoDetector(); + if (undoDetector.detectUndo(transaction, cleanRevision, revision, featureDelta)) + { + return null; + } + } + } + + transaction.getCleanRevisions().put(object, cleanRevision); + object.cdoInternalSetRevision(revision); + + transaction.registerDirty(object, featureDelta, cleanRevision); + changeState(object, CDOState.DIRTY); + return result; } } /** * @author Simon McDuff */ - private static final class RewriteTransition implements ITransition<CDOState, CDOEvent, InternalCDOObject, Object> + private final class RewriteTransition extends AbstractWriteTransition { - public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Object featureDelta) + @Override + protected Object execute(InternalCDOObject object, InternalCDOTransaction transaction, + CDOFeatureDelta featureDelta, InternalCDORevision revision) { - InternalCDORevision revision = object.cdoRevision(); - if (!revision.isWritable()) + Map<InternalCDOObject, InternalCDORevision> cleanRevisions = transaction.getCleanRevisions(); + InternalCDORevision cleanRevision = cleanRevisions.get(object); + + Object result = null; + if (featureDelta != null) { - throw new NoPermissionException(revision); + result = featureDelta.applyTo(revision); + + if (!transaction.hasMultipleSavepoints()) + { + CDOUndoDetector undoDetector = transaction.options().getUndoDetector(); + if (undoDetector.detectUndo(transaction, cleanRevision, revision, featureDelta)) + { + CDOID id = revision.getID(); + + InternalCDOSavepoint lastSavepoint = transaction.getLastSavepoint(); + Map<CDOID, CDORevisionDelta> revisionDeltas = lastSavepoint.getRevisionDeltas2(); + InternalCDORevisionDelta revisionDelta = (InternalCDORevisionDelta)revisionDeltas.get(id); + if (revisionDelta != null) + { + Map<EStructuralFeature, CDOFeatureDelta> featureDeltas = revisionDelta.getFeatureDeltaMap(); + featureDeltas.remove(featureDelta.getFeature()); + + if (featureDeltas.isEmpty()) + { + cleanRevisions.remove(object); + revisionDeltas.remove(id); + lastSavepoint.getDirtyObjects().remove(id); + + object.cdoInternalSetRevision(cleanRevision); + changeState(object, CDOState.CLEAN); + } + } + + if (revisionDeltas.isEmpty()) + { + transaction.setDirty(false); + } + + return result; + } + } } - InternalCDOTransaction transaction = object.cdoView().toTransaction(); - transaction.registerFeatureDelta(object, (CDOFeatureDelta)featureDelta); + transaction.registerFeatureDelta(object, featureDelta, cleanRevision); + return result; } } @@ -995,7 +1115,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent { newRevision = oldRevision.copy(); view.getSession().resolveAllElementProxies(newRevision); - delta.apply(newRevision); + delta.applyTo(newRevision); newRevision.setBranchPoint(target); cache.addRevision(newRevision); } @@ -1020,9 +1140,9 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent newRevision = (InternalCDORevision)cache.getRevisionByVersion(newKey.getID(), newKey); } - object.cdoInternalSetRevision(newRevision); if (newRevision != null) { + object.cdoInternalSetRevision(newRevision); changeState(object, CDOState.CLEAN); object.cdoInternalPostLoad(); } @@ -1056,7 +1176,6 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent /** * @author Eike Stepper - * @since 2.0 */ private class ConflictTransition extends InvalidateTransition { @@ -1093,40 +1212,9 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent */ private final class LoadTransition implements ITransition<CDOState, CDOEvent, InternalCDOObject, Object> { - private boolean forWrite; - - public LoadTransition(boolean forWrite) + public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Object UNUSED) { - this.forWrite = forWrite; - } - - public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Object delta) - { - object.cdoInternalPreLoad(); - - InternalCDOView view = object.cdoView(); - InternalCDORevision revision = view.getRevision(object.cdoID(), true); - if (revision == null) - { - INSTANCE.detachRemote(object); - CDOInvalidationPolicy policy = view.options().getInvalidationPolicy(); - policy.handleInvalidObject(object); - } - - if (forWrite && !revision.isWritable()) - { - throw new NoPermissionException(revision); - } - - object.cdoInternalSetRevision(revision); - changeState(object, CDOState.CLEAN); - object.cdoInternalPostLoad(); - dispatchLoadNotification(object); - - if (forWrite) - { - INSTANCE.writeWithoutViewLock(object, (CDOFeatureDelta)delta); - } + internalLoad(object, false); } } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStoreImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStoreImpl.java index 9b9cabd551..018ad73d4e 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStoreImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStoreImpl.java @@ -36,6 +36,7 @@ import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager; import org.eclipse.emf.cdo.util.ObjectNotFoundException; import org.eclipse.emf.cdo.view.CDOFeatureAnalyzer; import org.eclipse.emf.cdo.view.CDORevisionPrefetchingPolicy; +import org.eclipse.emf.cdo.view.CDOStaleReferencePolicy; import org.eclipse.emf.internal.cdo.bundle.OM; @@ -75,48 +76,19 @@ public final class CDOStoreImpl implements CDOStore private InternalCDOView view; - /** - * @since 2.0 - */ public CDOStoreImpl(InternalCDOView view) { this.view = view; } - /** - * @since 2.0 - */ public InternalCDOView getView() { return view; } /** - * @since 2.0 + * @category READ */ - public void setContainer(InternalEObject eObject, CDOResource newResource, InternalEObject newEContainer, - int newContainerFeatureID) - { - synchronized (view) - { - InternalCDOObject cdoObject = getCDOObject(eObject); - if (TRACER.isEnabled()) - { - TRACER.format("setContainer({0}, {1}, {2}, {3})", cdoObject, newResource, newEContainer, newContainerFeatureID); //$NON-NLS-1$ - } - - Object newContainerID = newEContainer == null ? CDOID.NULL : cdoObject.cdoView().convertObjectToID(newEContainer, - true); - CDOID newResourceID = newResource == null ? CDOID.NULL : newResource.cdoID(); - - CDOFeatureDelta delta = new CDOContainerFeatureDeltaImpl(newResourceID, newContainerID, newContainerFeatureID); - InternalCDORevision revision = getRevisionForWriting(cdoObject, delta); - revision.setResourceID(newResourceID); - revision.setContainerID(newContainerID); - revision.setContainingFeatureID(newContainerFeatureID); - } - } - public InternalEObject getContainer(InternalEObject eObject) { synchronized (view) @@ -127,12 +99,15 @@ public final class CDOStoreImpl implements CDOStore TRACER.format("getContainer({0})", cdoObject); //$NON-NLS-1$ } - InternalCDORevision revision = getRevisionForReading(cdoObject); - return (InternalEObject)convertIDToObject(cdoObject.cdoView(), cdoObject, - EcorePackage.eINSTANCE.eContainingFeature(), -1, revision.getContainerID()); + InternalCDORevision revision = readRevision(cdoObject); + return (InternalEObject)convertIDToObject(view, cdoObject, EcorePackage.eINSTANCE.eContainingFeature(), -1, + revision.getContainerID()); } } + /** + * @category READ + */ public int getContainingFeatureID(InternalEObject eObject) { synchronized (view) @@ -143,13 +118,13 @@ public final class CDOStoreImpl implements CDOStore TRACER.format("getContainingFeatureID({0})", cdoObject); //$NON-NLS-1$ } - InternalCDORevision revision = getRevisionForReading(cdoObject); + InternalCDORevision revision = readRevision(cdoObject); return revision.getContainingFeatureID(); } } /** - * @since 2.0 + * @category READ */ public InternalEObject getResource(InternalEObject eObject) { @@ -161,17 +136,23 @@ public final class CDOStoreImpl implements CDOStore TRACER.format("getResource({0})", cdoObject); //$NON-NLS-1$ } - InternalCDORevision revision = getRevisionForReading(cdoObject); - return (InternalEObject)convertIDToObject(cdoObject.cdoView(), cdoObject, - EcorePackage.eINSTANCE.eContainingFeature(), -1, revision.getResourceID()); + InternalCDORevision revision = readRevision(cdoObject); + return (InternalEObject)convertIDToObject(view, cdoObject, EcorePackage.eINSTANCE.eContainingFeature(), -1, + revision.getResourceID()); } } + /** + * @category READ + */ public EStructuralFeature getContainingFeature(InternalEObject eObject) { throw new UnsupportedOperationException("Use getContainingFeatureID() instead"); //$NON-NLS-1$ } + /** + * @category READ + */ public Object get(InternalEObject eObject, EStructuralFeature feature, int index) { synchronized (view) @@ -185,7 +166,7 @@ public final class CDOStoreImpl implements CDOStore CDOFeatureAnalyzer featureAnalyzer = view.options().getFeatureAnalyzer(); featureAnalyzer.preTraverseFeature(cdoObject, feature, index); - InternalCDORevision revision = getRevisionForReading(cdoObject); + InternalCDORevision revision = readRevision(cdoObject); Object value = revision.get(feature, index); value = convertToEMF(eObject, revision, feature, index, value); @@ -195,6 +176,9 @@ public final class CDOStoreImpl implements CDOStore } } + /** + * @category READ + */ public boolean isSet(InternalEObject eObject, EStructuralFeature feature) { synchronized (view) @@ -205,7 +189,7 @@ public final class CDOStoreImpl implements CDOStore TRACER.format("isSet({0}, {1})", cdoObject, feature); //$NON-NLS-1$ } - InternalCDORevision revision = getRevisionForReading(cdoObject); + InternalCDORevision revision = readRevision(cdoObject); if (feature.isMany()) { CDOList list = revision.getList(feature); @@ -229,6 +213,9 @@ public final class CDOStoreImpl implements CDOStore } } + /** + * @category READ + */ public int size(InternalEObject eObject, EStructuralFeature feature) { synchronized (view) @@ -239,11 +226,14 @@ public final class CDOStoreImpl implements CDOStore TRACER.format("size({0}, {1})", cdoObject, feature); //$NON-NLS-1$ } - InternalCDORevision revision = getRevisionForReading(cdoObject); + InternalCDORevision revision = readRevision(cdoObject); return revision.size(feature); } } + /** + * @category READ + */ public boolean isEmpty(InternalEObject eObject, EStructuralFeature feature) { synchronized (view) @@ -254,11 +244,14 @@ public final class CDOStoreImpl implements CDOStore TRACER.format("isEmpty({0}, {1})", cdoObject, feature); //$NON-NLS-1$ } - InternalCDORevision revision = getRevisionForReading(cdoObject); + InternalCDORevision revision = readRevision(cdoObject); return revision.isEmpty(feature); } } + /** + * @category READ + */ public boolean contains(InternalEObject eObject, EStructuralFeature feature, Object value) { synchronized (view) @@ -271,7 +264,7 @@ public final class CDOStoreImpl implements CDOStore Object convertedValue = convertToCDO(cdoObject, feature, value); - InternalCDORevision revision = getRevisionForReading(cdoObject); + InternalCDORevision revision = readRevision(cdoObject); boolean result = revision.contains(feature, convertedValue); // Special handling of detached (TRANSIENT) objects, see bug 354395 @@ -284,6 +277,9 @@ public final class CDOStoreImpl implements CDOStore } } + /** + * @category READ + */ public int indexOf(InternalEObject eObject, EStructuralFeature feature, Object value) { synchronized (view) @@ -296,11 +292,14 @@ public final class CDOStoreImpl implements CDOStore value = convertToCDO(cdoObject, feature, value); - InternalCDORevision revision = getRevisionForReading(cdoObject); + InternalCDORevision revision = readRevision(cdoObject); return revision.indexOf(feature, value); } } + /** + * @category READ + */ public int lastIndexOf(InternalEObject eObject, EStructuralFeature feature, Object value) { synchronized (view) @@ -313,11 +312,14 @@ public final class CDOStoreImpl implements CDOStore value = convertToCDO(cdoObject, feature, value); - InternalCDORevision revision = getRevisionForReading(cdoObject); + InternalCDORevision revision = readRevision(cdoObject); return revision.lastIndexOf(feature, value); } } + /** + * @category READ + */ public int hashCode(InternalEObject eObject, EStructuralFeature feature) { synchronized (view) @@ -328,11 +330,14 @@ public final class CDOStoreImpl implements CDOStore TRACER.format("hashCode({0}, {1})", cdoObject, feature); //$NON-NLS-1$ } - InternalCDORevision revision = getRevisionForReading(cdoObject); + InternalCDORevision revision = readRevision(cdoObject); return revision.hashCode(feature); } } + /** + * @category READ + */ public Object[] toArray(InternalEObject eObject, EStructuralFeature feature) { synchronized (view) @@ -343,7 +348,7 @@ public final class CDOStoreImpl implements CDOStore TRACER.format("toArray({0}, {1})", cdoObject, feature); //$NON-NLS-1$ } - InternalCDORevision revision = getRevisionForReading(cdoObject); + InternalCDORevision revision = readRevision(cdoObject); Object[] result = revision.toArray(feature); for (int i = 0; i < result.length; i++) { @@ -364,6 +369,9 @@ public final class CDOStoreImpl implements CDOStore } } + /** + * @category READ + */ @SuppressWarnings("unchecked") public <T> T[] toArray(InternalEObject eObject, EStructuralFeature feature, T[] a) { @@ -387,6 +395,31 @@ public final class CDOStoreImpl implements CDOStore } } + /** + * @category WRITE + */ + public void setContainer(InternalEObject eObject, CDOResource newResource, InternalEObject newEContainer, + int newContainerFeatureID) + { + synchronized (view) + { + InternalCDOObject cdoObject = getCDOObject(eObject); + if (TRACER.isEnabled()) + { + TRACER.format("setContainer({0}, {1}, {2}, {3})", cdoObject, newResource, newEContainer, newContainerFeatureID); //$NON-NLS-1$ + } + + Object newContainerID = newEContainer == null ? CDOID.NULL : view.convertObjectToID(newEContainer, true); + CDOID newResourceID = newResource == null ? CDOID.NULL : newResource.cdoID(); + + CDOFeatureDelta delta = new CDOContainerFeatureDeltaImpl(newResourceID, newContainerID, newContainerFeatureID); + writeRevision(cdoObject, delta); + } + } + + /** + * @category WRITE RESULT + */ public Object set(InternalEObject eObject, EStructuralFeature feature, int index, Object value) { synchronized (view) @@ -399,18 +432,21 @@ public final class CDOStoreImpl implements CDOStore value = convertToCDO(cdoObject, feature, value); - InternalCDORevision oldRevision = getRevisionForReading(cdoObject); + // TODO: Use writeRevision() result!! + InternalCDORevision oldRevision = readRevision(cdoObject); Object oldValue = oldRevision.get(feature, index); oldValue = convertToEMF(eObject, oldRevision, feature, index, oldValue); CDOFeatureDelta delta = new CDOSetFeatureDeltaImpl(feature, index, value, oldValue); - InternalCDORevision revision = getRevisionForWriting(cdoObject, delta); - revision.set(feature, index, value); + writeRevision(cdoObject, delta); return oldValue; } } + /** + * @category WRITE + */ public void unset(InternalEObject eObject, EStructuralFeature feature) { synchronized (view) @@ -422,31 +458,13 @@ public final class CDOStoreImpl implements CDOStore } CDOFeatureDelta delta = new CDOUnsetFeatureDeltaImpl(feature); - InternalCDORevision revision = getRevisionForWriting(cdoObject, delta); - - if (feature.isUnsettable()) - { - revision.unset(feature); - } - else - { - if (feature.isMany()) - { - Object value = revision.getValue(feature); - - @SuppressWarnings("unchecked") - List<Object> list = (List<Object>)value; - list.clear(); - } - else - { - Object defaultValue = convertToCDO(cdoObject, feature, feature.getDefaultValue()); - revision.set(feature, NO_INDEX, defaultValue); - } - } + writeRevision(cdoObject, delta); } } + /** + * @category WRITE + */ public void add(InternalEObject eObject, EStructuralFeature feature, int index, Object value) { synchronized (view) @@ -457,21 +475,16 @@ public final class CDOStoreImpl implements CDOStore TRACER.format("add({0}, {1}, {2}, {3})", cdoObject, feature, index, value); //$NON-NLS-1$ } - if (feature.isMany()) - { - value = convertToCDO(cdoObject, feature, value); - } - else - { - throw new UnsupportedOperationException("ADD is not supported for single-valued features"); - } + value = convertToCDO(cdoObject, feature, value); CDOFeatureDelta delta = new CDOAddFeatureDeltaImpl(feature, index, value); - InternalCDORevision revision = getRevisionForWriting(cdoObject, delta); - revision.add(feature, index, value); + writeRevision(cdoObject, delta); } } + /** + * @category WRITE RESULT + */ public Object remove(InternalEObject eObject, EStructuralFeature feature, int index) { synchronized (view) @@ -482,75 +495,50 @@ public final class CDOStoreImpl implements CDOStore TRACER.format("remove({0}, {1}, {2})", cdoObject, feature, index); //$NON-NLS-1$ } - Object oldValue = null; - - // Bug 293283 / Bug 314387 - if (feature.isMany()) - { - InternalCDORevision readLockedRevision = getRevisionForReading(cdoObject); - CDOList list = readLockedRevision.getList(feature); - int size = list.size(); - if (index < 0 || size <= index) - { - throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size); - } - } - else - { - throw new UnsupportedOperationException("REMOVE is not supported for single-valued features"); - } - - CDOFeatureDelta delta = new CDORemoveFeatureDeltaImpl(feature, index); - InternalCDORevision revision = getRevisionForWriting(cdoObject, delta); - - oldValue = revision.get(feature, index); - - try - { - oldValue = convertToEMF(eObject, revision, feature, index, oldValue); - } - finally - { - revision.remove(feature, index); - } + Object oldValue = getOldListValue(eObject, cdoObject, feature, index); + removeElement(cdoObject, feature, index); return oldValue; } } - public void clear(InternalEObject eObject, EStructuralFeature feature) + /** + * @category WRITE RESULT + */ + public Object move(InternalEObject eObject, EStructuralFeature feature, int target, int source) { synchronized (view) { InternalCDOObject cdoObject = getCDOObject(eObject); if (TRACER.isEnabled()) { - TRACER.format("clear({0}, {1})", cdoObject, feature); //$NON-NLS-1$ + TRACER.format("move({0}, {1}, {2}, {3})", cdoObject, feature, target, source); //$NON-NLS-1$ } - CDOFeatureDelta delta = new CDOClearFeatureDeltaImpl(feature); - InternalCDORevision revision = getRevisionForWriting(cdoObject, delta); - // TODO Handle containment remove!!! - revision.clear(feature); + Object oldValue = getOldListValue(eObject, cdoObject, feature, source); + + CDOFeatureDelta delta = new CDOMoveFeatureDeltaImpl(feature, target, source); + writeRevision(cdoObject, delta); + + return oldValue; } } - public Object move(InternalEObject eObject, EStructuralFeature feature, int target, int source) + /** + * @category WRITE + */ + public void clear(InternalEObject eObject, EStructuralFeature feature) { synchronized (view) { InternalCDOObject cdoObject = getCDOObject(eObject); if (TRACER.isEnabled()) { - TRACER.format("move({0}, {1}, {2}, {3})", cdoObject, feature, target, source); //$NON-NLS-1$ + TRACER.format("clear({0}, {1})", cdoObject, feature); //$NON-NLS-1$ } - CDOFeatureDelta delta = new CDOMoveFeatureDeltaImpl(feature, target, source); - InternalCDORevision revision = getRevisionForWriting(cdoObject, delta); - Object result = revision.move(feature, target, source); - - result = convertToEMF(eObject, revision, feature, target, result); - return result; + CDOFeatureDelta delta = new CDOClearFeatureDeltaImpl(feature); + writeRevision(cdoObject, delta); } } @@ -694,7 +682,8 @@ public final class CDOStoreImpl implements CDOStore { if (value instanceof CDOID) { - value = view.options().getStaleReferencePolicy().processStaleReference(eObject, feature, index, ex.getID()); + CDOStaleReferencePolicy staleReferencePolicy = view.options().getStaleReferencePolicy(); + value = staleReferencePolicy.processStaleReference(eObject, feature, index, ex.getID()); } } @@ -716,21 +705,31 @@ public final class CDOStoreImpl implements CDOStore return object; } - private static InternalCDORevision getRevisionForReading(InternalCDOObject cdoObject) + private Object getOldListValue(InternalEObject eObject, InternalCDOObject cdoObject, EStructuralFeature feature, + int index) { - CDOStateMachine.INSTANCE.read(cdoObject); - return getRevision(cdoObject); - } + if (!feature.isMany()) + { + throw new UnsupportedOperationException("Not supported for single-valued features"); + } - private static InternalCDORevision getRevisionForWriting(InternalCDOObject cdoObject, CDOFeatureDelta delta) - { - CDOStateMachine.INSTANCE.write(cdoObject, delta); - return getRevision(cdoObject); + // Bug 293283 / Bug 314387 + InternalCDORevision revision = readRevision(cdoObject); + CDOList list = revision.getList(feature); + int size = list.size(); + if (index < 0 || size <= index) + { + throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size); + } + + Object oldValue = revision.get(feature, index); + oldValue = convertToEMF(eObject, revision, feature, index, oldValue); + return oldValue; } - private static InternalCDORevision getRevision(InternalCDOObject cdoObject) + private static InternalCDORevision readRevision(InternalCDOObject cdoObject) { - InternalCDORevision revision = cdoObject.cdoRevision(); + InternalCDORevision revision = CDOStateMachine.INSTANCE.read(cdoObject); if (revision == null) { throw new IllegalStateException("revision == null"); @@ -738,4 +737,15 @@ public final class CDOStoreImpl implements CDOStore return revision; } + + private static Object writeRevision(InternalCDOObject cdoObject, CDOFeatureDelta delta) + { + return CDOStateMachine.INSTANCE.write(cdoObject, delta); + } + + public static void removeElement(InternalCDOObject cdoObject, EStructuralFeature feature, int index) + { + CDOFeatureDelta delta = new CDORemoveFeatureDeltaImpl(feature, index); + writeRevision(cdoObject, delta); + } } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java index 2dff05fd54..ac55e7fc60 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java @@ -1712,7 +1712,10 @@ public class CDOViewImpl extends AbstractCDOView } catch (Exception ex) { - OM.LOG.error(ex); + if (isActive()) + { + OM.LOG.error(ex); + } } finally { diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOMergingConflictResolver.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOMergingConflictResolver.java index 0814783223..75c3cb898b 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOMergingConflictResolver.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOMergingConflictResolver.java @@ -168,7 +168,7 @@ public class CDOMergingConflictResolver extends AbstractChangeSetsConflictResolv { InternalCDORevision newLocalRevision = cleanRevision.copy(); newLocalRevision.setVersion(newVersion); - resultDelta.apply(newLocalRevision); + resultDelta.applyTo(newLocalRevision); return newLocalRevision; } @@ -180,7 +180,7 @@ public class CDOMergingConflictResolver extends AbstractChangeSetsConflictResolv { InternalCDORevision newCleanRevision = cleanRevision.copy(); newCleanRevision.setVersion(newVersion); - remoteDelta.apply(newCleanRevision); + remoteDelta.applyTo(newCleanRevision); return newCleanRevision; } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOTransaction.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOTransaction.java index d8aceb5b95..eda49dcb33 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOTransaction.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOTransaction.java @@ -48,6 +48,11 @@ public interface InternalCDOTransaction extends CDOTransaction, InternalCDOUserT public InternalCDOCommitContext createCommitContext(); /** + * @since 4.3 + */ + public boolean hasMultipleSavepoints(); + + /** * @since 3.0 */ public InternalCDOSavepoint setSavepoint(); @@ -101,8 +106,19 @@ public interface InternalCDOTransaction extends CDOTransaction, InternalCDOUserT public void registerDirty(InternalCDOObject object, CDOFeatureDelta featureDelta); + /** + * @since 4.3 + */ + public void registerDirty(InternalCDOObject object, CDOFeatureDelta featureDelta, InternalCDORevision cleanRevision); + public void registerFeatureDelta(InternalCDOObject object, CDOFeatureDelta featureDelta); + /** + * @since 4.3 + */ + public void registerFeatureDelta(InternalCDOObject object, CDOFeatureDelta featureDelta, + InternalCDORevision cleanRevision); + public void registerRevisionDelta(CDORevisionDelta revisionDelta); /** |