blob: ff7a63d8b7db1348f91d255475792b01d2947beb [file] [log] [blame]
/*
* 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;
}
}