| /* |
| * Copyright (c) 2010-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.spi.common.commit; |
| |
| import org.eclipse.emf.cdo.common.commit.CDOChangeSetData; |
| import org.eclipse.emf.cdo.common.commit.CDOChangeSetDataProvider; |
| import org.eclipse.emf.cdo.common.id.CDOID; |
| import org.eclipse.emf.cdo.common.id.CDOIDUtil; |
| import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion; |
| import org.eclipse.emf.cdo.common.revision.CDORevision; |
| import org.eclipse.emf.cdo.common.revision.CDORevisionKey; |
| import org.eclipse.emf.cdo.common.revision.CDORevisionProvider; |
| import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; |
| import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDeltaProvider; |
| |
| import java.util.Map; |
| |
| /** |
| * If the meaning of this type isn't clear, there really should be more of a description here... |
| * |
| * @author Eike Stepper |
| * @since 4.0 |
| */ |
| public class CDOChangeSetDataRevisionProvider implements CDORevisionProvider, CDOChangeSetDataProvider |
| { |
| private static final CDOIDAndVersion DETACHED = new CDOIDAndVersion() |
| { |
| public CDOID getID() |
| { |
| return CDOID.NULL; |
| } |
| |
| public int getVersion() |
| { |
| return Integer.MIN_VALUE; |
| } |
| |
| @Override |
| public String toString() |
| { |
| return "DETACHED"; |
| } |
| }; |
| |
| private CDORevisionProvider delegate; |
| |
| private CDOChangeSetData changeSetData; |
| |
| private CDORevisionProvider revisionCallback; |
| |
| private CDORevisionDeltaProvider revisionDeltaCallback; |
| |
| private Map<CDOID, CDOIDAndVersion> cachedRevisions; |
| |
| public CDOChangeSetDataRevisionProvider(CDORevisionProvider delegate, CDOChangeSetData changeSetData, |
| CDORevisionProvider revisionCallback, CDORevisionDeltaProvider revisionDeltaCallback) |
| { |
| this.delegate = delegate; |
| this.changeSetData = changeSetData; |
| this.revisionCallback = revisionCallback; |
| this.revisionDeltaCallback = revisionDeltaCallback; |
| } |
| |
| public CDOChangeSetDataRevisionProvider(CDORevisionProvider delegate, CDOChangeSetData changeSetData) |
| { |
| this(delegate, changeSetData, null, null); |
| } |
| |
| public CDOChangeSetData getChangeSetData() |
| { |
| return changeSetData; |
| } |
| |
| public synchronized CDORevision getRevision(CDOID id) |
| { |
| if (cachedRevisions == null) |
| { |
| cachedRevisions = cacheRevisions(); |
| } |
| |
| CDOIDAndVersion key = cachedRevisions.get(id); |
| if (key == DETACHED) |
| { |
| return null; |
| } |
| |
| if (key instanceof CDORevision) // New object (eager) |
| { |
| return (CDORevision)key; |
| } |
| |
| if (key instanceof CDORevisionDelta) // Changed object (eager) |
| { |
| CDORevisionDelta revisionDelta = (CDORevisionDelta)key; |
| return applyDelta(revisionDelta); |
| } |
| |
| if (key instanceof CDORevisionKey) // Changed object (lazy) |
| { |
| CDORevisionDelta revisionDelta = revisionDeltaCallback.getRevisionDelta(id); |
| return applyDelta(revisionDelta); |
| } |
| |
| if (key != null) // New object (lazy) |
| { |
| CDORevision revision = revisionCallback.getRevision(id); |
| cachedRevisions.put(id, revision); |
| return revision; |
| } |
| |
| return delegate.getRevision(id); |
| } |
| |
| private Map<CDOID, CDOIDAndVersion> cacheRevisions() |
| { |
| Map<CDOID, CDOIDAndVersion> cache = CDOIDUtil.createMap(); |
| |
| for (CDOIDAndVersion key : changeSetData.getNewObjects()) |
| { |
| if (revisionCallback == null && !(key instanceof CDORevision)) |
| { |
| throw new IllegalStateException("No callback installed to lazily obtain revision " + key); |
| } |
| |
| cache.put(key.getID(), key); |
| } |
| |
| for (CDORevisionKey key : changeSetData.getChangedObjects()) |
| { |
| if (revisionDeltaCallback == null && !(key instanceof CDORevisionDelta)) |
| { |
| throw new IllegalStateException("No callback installed to lazily obtain revision delta " + key); |
| } |
| |
| cache.put(key.getID(), key); |
| } |
| |
| for (CDOIDAndVersion key : changeSetData.getDetachedObjects()) |
| { |
| cache.put(key.getID(), DETACHED); |
| } |
| |
| return cache; |
| } |
| |
| private CDORevision applyDelta(CDORevisionDelta revisionDelta) |
| { |
| CDOID id = revisionDelta.getID(); |
| CDORevision changedObject = delegate.getRevision(id).copy(); |
| revisionDelta.applyTo(changedObject); |
| cachedRevisions.put(id, changedObject); |
| return changedObject; |
| } |
| } |