blob: 5a5711f97c895bb88c51578b2ca5f7017f36f731 [file] [log] [blame]
/***************************************************************************
* Copyright (c) 2004 - 2008 Eike Stepper, Germany.
* 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
* Simon McDuff - maintenance
* Victor Roldan Betancort - maintenance
**************************************************************************/
package org.eclipse.emf.internal.cdo;
import org.eclipse.emf.cdo.CDOAdapterPolicy;
import org.eclipse.emf.cdo.CDOCommitContext;
import org.eclipse.emf.cdo.CDOFeatureAnalyzer;
import org.eclipse.emf.cdo.CDONotification;
import org.eclipse.emf.cdo.CDOObject;
import org.eclipse.emf.cdo.CDOQuery;
import org.eclipse.emf.cdo.CDORevisionPrefetchingPolicy;
import org.eclipse.emf.cdo.CDOState;
import org.eclipse.emf.cdo.CDOTransaction;
import org.eclipse.emf.cdo.CDOView;
import org.eclipse.emf.cdo.CDOViewEvent;
import org.eclipse.emf.cdo.CDOViewInvalidationEvent;
import org.eclipse.emf.cdo.common.CDOProtocolConstants;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOIDAndVersion;
import org.eclipse.emf.cdo.common.id.CDOIDMeta;
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
import org.eclipse.emf.cdo.common.model.CDOClass;
import org.eclipse.emf.cdo.common.model.CDOFeature;
import org.eclipse.emf.cdo.common.model.resource.CDONameFeature;
import org.eclipse.emf.cdo.common.model.resource.CDOResourceFolderClass;
import org.eclipse.emf.cdo.common.model.resource.CDOResourceNodeClass;
import org.eclipse.emf.cdo.common.model.resource.CDOResourcePackage;
import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.common.revision.CDORevisionResolver;
import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
import org.eclipse.emf.cdo.common.util.CDOException;
import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.eresource.CDOResourceFolder;
import org.eclipse.emf.cdo.eresource.CDOResourceNode;
import org.eclipse.emf.cdo.eresource.impl.CDOResourceImpl;
import org.eclipse.emf.cdo.spi.common.InternalCDORevision;
import org.eclipse.emf.cdo.util.CDOURIUtil;
import org.eclipse.emf.cdo.util.CDOUtil;
import org.eclipse.emf.cdo.util.DanglingReferenceException;
import org.eclipse.emf.cdo.util.InvalidURIException;
import org.eclipse.emf.cdo.util.ReadOnlyException;
import org.eclipse.emf.internal.cdo.bundle.OM;
import org.eclipse.emf.internal.cdo.protocol.CDOClientProtocol;
import org.eclipse.emf.internal.cdo.protocol.ChangeSubscriptionRequest;
import org.eclipse.emf.internal.cdo.protocol.LockObjectsRequest;
import org.eclipse.emf.internal.cdo.protocol.ObjectLockedRequest;
import org.eclipse.emf.internal.cdo.protocol.UnlockObjectsRequest;
import org.eclipse.emf.internal.cdo.protocol.ViewsChangedRequest;
import org.eclipse.emf.internal.cdo.query.CDOQueryImpl;
import org.eclipse.emf.internal.cdo.util.FSMUtil;
import org.eclipse.emf.internal.cdo.util.ModelUtil;
import org.eclipse.net4j.signal.RemoteException;
import org.eclipse.net4j.util.ImplementationError;
import org.eclipse.net4j.util.StringUtil;
import org.eclipse.net4j.util.WrappedException;
import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump;
import org.eclipse.net4j.util.collection.CloseableIterator;
import org.eclipse.net4j.util.collection.HashBag;
import org.eclipse.net4j.util.concurrent.RWLockManager;
import org.eclipse.net4j.util.event.Notifier;
import org.eclipse.net4j.util.lifecycle.Lifecycle;
import org.eclipse.net4j.util.om.trace.ContextTracer;
import org.eclipse.net4j.util.options.OptionsEvent;
import org.eclipse.net4j.util.ref.ReferenceType;
import org.eclipse.net4j.util.ref.ReferenceValueMap;
import org.eclipse.net4j.util.transaction.TransactionException;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.NotificationImpl;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author Eike Stepper
*/
public class CDOViewImpl extends Lifecycle implements InternalCDOView
{
private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_VIEW, CDOViewImpl.class);
private int viewID;
private InternalCDOSession session;
private InternalCDOViewSet viewSet;
private CDOURIHandler uriHandler = new CDOURIHandler(this);
private CDOFeatureAnalyzer featureAnalyzer = CDOFeatureAnalyzer.NOOP;
private ConcurrentMap<CDOID, InternalCDOObject> objects;
private CDOStore store = new CDOStore(this);
private ReentrantLock lock = new ReentrantLock(true);
private CDOResourceImpl rootResource;
private ChangeSubscriptionManager changeSubscriptionManager = createChangeSubscriptionManager();
private AdapterManager adapterPolicyManager = createAdapterManager();
private OptionsImpl options;
@ExcludeFromDump
private transient CDOID lastLookupID;
@ExcludeFromDump
private transient InternalCDOObject lastLookupObject;
/**
* @since 2.0
*/
public CDOViewImpl()
{
options = initOptions();
}
/**
* @since 2.0
*/
public OptionsImpl options()
{
return options;
}
/**
* @since 2.0
*/
protected OptionsImpl initOptions()
{
return new OptionsImpl();
}
public int getViewID()
{
return viewID;
}
/**
* @since 2.0
*/
public void setViewID(int viewId)
{
viewID = viewId;
}
public Type getViewType()
{
return Type.READONLY;
}
public ResourceSet getResourceSet()
{
return viewSet.getResourceSet();
}
/**
* @since 2.0
*/
public InternalCDOViewSet getViewSet()
{
return viewSet;
}
/**
* @since 2.0
*/
public void setViewSet(InternalCDOViewSet viewSet)
{
this.viewSet = viewSet;
if (viewSet != null)
{
viewSet.getResourceSet().getURIConverter().getURIHandlers().add(getURIHandler());
}
}
/**
* @since 2.0
*/
public InternalCDOSession getSession()
{
return session;
}
/**
* @since 2.0
*/
public void setSession(InternalCDOSession session)
{
this.session = session;
}
public CDOStore getStore()
{
checkActive();
return store;
}
/**
* @since 2.0
*/
public synchronized CDOResourceImpl getRootResource()
{
checkActive();
if (rootResource == null)
{
rootResource = createRootResource();
}
return rootResource;
}
/**
* @return
* @since 2.0
*/
protected CDOResourceImpl createRootResource()
{
return (CDOResourceImpl)getResource(CDOResourceNode.ROOT_PATH);
}
/**
* @since 2.0
*/
public CDOURIHandler getURIHandler()
{
return uriHandler;
}
/**
* @since 2.0
*/
public ReentrantLock getLock()
{
return lock;
}
/**
* @throws InterruptedException
* @since 2.0
*/
public void lockObjects(Collection<? extends CDOObject> objects, RWLockManager.LockType lockType, long timeout)
throws InterruptedException
{
checkActive();
InterruptedException interruptedException = null;
RuntimeException runtimeException = null;
try
{
CDOClientProtocol protocol = (CDOClientProtocol)getSession().getProtocol();
new LockObjectsRequest(protocol, this, objects, timeout, lockType).send();
}
catch (RemoteException ex)
{
if (ex.getCause() instanceof RuntimeException)
{
runtimeException = (RuntimeException)ex.getCause();
}
else if (ex.getCause() instanceof InterruptedException)
{
interruptedException = (InterruptedException)ex.getCause();
}
}
catch (Exception ex)
{
throw WrappedException.wrap(ex);
}
if (interruptedException != null)
{
throw interruptedException;
}
if (runtimeException != null)
{
throw runtimeException;
}
}
/**
* @since 2.0
*/
public void unlockObjects(Collection<? extends CDOObject> objects, RWLockManager.LockType lockType)
{
checkActive();
try
{
CDOClientProtocol protocol = (CDOClientProtocol)getSession().getProtocol();
new UnlockObjectsRequest(protocol, this, objects, lockType).send();
}
catch (Exception ex)
{
throw WrappedException.wrap(ex);
}
}
/**
* @since 2.0
*/
public void unlockObjects()
{
unlockObjects(null, null);
}
/**
* @throws InterruptedException
* @since 2.0
*/
public boolean isObjectLocked(CDOObject object, RWLockManager.LockType lockType)
{
checkActive();
try
{
CDOClientProtocol protocol = (CDOClientProtocol)getSession().getProtocol();
return new ObjectLockedRequest(protocol, this, object, lockType).send();
}
catch (Exception ex)
{
throw WrappedException.wrap(ex);
}
}
/**
* @since 2.0
*/
public long getTimeStamp()
{
return UNSPECIFIED_DATE;
}
public boolean isDirty()
{
return false;
}
public boolean hasConflict()
{
return false;
}
/**
* @since 2.0
*/
public CDOFeatureAnalyzer getFeatureAnalyzer()
{
return featureAnalyzer;
}
/**
* @since 2.0
*/
public void setFeatureAnalyzer(CDOFeatureAnalyzer featureAnalyzer)
{
this.featureAnalyzer = featureAnalyzer == null ? CDOFeatureAnalyzer.NOOP : featureAnalyzer;
}
/**
* @since 2.0
*/
public InternalCDOTransaction toTransaction()
{
checkActive();
if (this instanceof InternalCDOTransaction)
{
return (InternalCDOTransaction)this;
}
throw new ReadOnlyException("CDO view is read-only: " + this);
}
public boolean hasResource(String path)
{
checkActive();
try
{
getResourceID(path);
return true;
}
catch (Exception ex)
{
return false;
}
}
/**
* @since 2.0
*/
public CDOQuery createQuery(String language, String queryString)
{
checkActive();
return new CDOQueryImpl(this, language, queryString);
}
/**
* @return never <code>null</code>
* @since 2.0
*/
public CDOID getResourceID(String path)
{
if (StringUtil.isEmpty(path))
{
throw new IllegalArgumentException("path");
}
CDOID folderID = null;
if (CDOURIUtil.SEGMENT_SEPARATOR.equals(path))
{
folderID = getResourceID(null, null);
}
else
{
List<String> names = CDOURIUtil.analyzePath(path);
for (String name : names)
{
folderID = getResourceID(folderID, name);
}
}
return folderID;
}
/**
* @retrn never <code>null</code>
*/
private CDOID getResourceID(CDOID folderID, String name)
{
folderID = getResourceNodeID(folderID, name);
if (folderID == null)
{
throw new CDOException("Can not find " + name);
}
return folderID;
}
/**
* @return never <code>null</code>
* @since 2.0
*/
protected CDOResourceNode getResourceNode(CDOID folderID, String name)
{
try
{
CDOID id = getResourceNodeID(folderID, name);
return (CDOResourceNode)getObject(id);
}
catch (CDOException ex)
{
throw ex;
}
catch (Exception ex)
{
throw new CDOException(ex);
}
}
/**
* @since 2.0
*/
protected CDOID getResourceNodeID(CDOID folderID, String name)
{
if (folderID == null)
{
return getRootOrTopLevelResourceNodeID(name);
}
else if (name == null)
{
throw new IllegalArgumentException("name");
}
InternalCDORevision folderRevision = getLocalRevision(folderID);
CDOResourcePackage resourcePackage = getSession().getPackageManager().getCDOResourcePackage();
CDOResourceFolderClass resourceFolderClass = resourcePackage.getCDOResourceFolderClass();
if (folderRevision.getCDOClass() != resourceFolderClass)
{
throw new CDOException("Expected folder for id = " + folderID);
}
CDOFeature nodesFeature = resourceFolderClass.getCDONodesFeature();
CDOFeature nameFeature = resourcePackage.getCDOResourceNodeClass().getCDONameFeature();
int size = folderRevision.data().size(nodesFeature);
for (int i = 0; i < size; i++)
{
Object value = folderRevision.data().get(nodesFeature, i);
value = getStore().resolveProxy(folderRevision, nodesFeature, i, value);
CDORevision childRevision = getLocalRevision((CDOID)convertObjectToID(value, false));
if (name.equals(childRevision.data().get(nameFeature, 0)))
{
return childRevision.getID();
}
}
throw new CDOException("Node " + name + " not found");
}
/**
* @since 2.0
*/
protected CDOID getRootOrTopLevelResourceNodeID(String name)
{
CDOQuery resourceQuery = createResourcesQuery(null, name, true);
resourceQuery.setMaxResults(1);
List<CDOID> ids = resourceQuery.getResult(CDOID.class);
if (ids.isEmpty())
{
if (name == null)
{
throw new CDOException("No root ResourceNode");
}
else
{
throw new CDOException("No top level ResourceNode with the name " + name);
}
}
if (ids.size() > 1)
{
// TODO is this still needed since the is resourceQuery.setMaxResults(1) ??
throw new ImplementationError("Duplicate top-level ResourceNodes");
}
return ids.get(0);
}
/**
* @since 2.0
*/
protected InternalCDORevision getLocalRevision(CDOID id)
{
InternalCDORevision revision = null;
InternalCDOObject object = getObject(id, false);
if (object != null && object.cdoState() != CDOState.PROXY)
{
revision = object.cdoRevision();
}
if (revision == null)
{
revision = getRevision(id, true);
}
if (revision == null)
{
throw new CDOException("Cannot find revision with ID " + id);
}
return revision;
}
/**
* @since 2.0
*/
public InternalCDOObject[] getObjectsArray()
{
synchronized (objects)
{
return objects.values().toArray(new InternalCDOObject[objects.size()]);
}
}
/**
* TODO Remove me
*
* @since 2.0
*/
@Deprecated
public CDOResourceFolder getResourceFolder(String path)
{
if (path == null)
{
return null;
}
CDOResourceFolder folder = null;
StringTokenizer tokenizer = new StringTokenizer(path, CDOURIUtil.SEGMENT_SEPARATOR);
while (tokenizer.hasMoreTokens())
{
String segment = tokenizer.nextToken();
if (segment != null)
{
if (folder == null)
{
}
else
{
}
}
}
return folder;
}
/**
* @since 2.0
*/
public CDOResource getResource(String path)
{
return getResource(path, true);
}
/**
* @since 2.0
*/
public CDOResource getResource(String path, boolean loadInDemand)
{
checkActive();
URI uri = CDOURIUtil.createResourceURI(this, path);
return (CDOResource)getResourceSet().getResource(uri, loadInDemand);
}
/**
* @since 2.0
*/
public List<CDOResourceNode> queryResources(CDOResourceFolder folder, String name, boolean exactMatch)
{
checkActive();
CDOQuery resourceQuery = createResourcesQuery(folder, name, exactMatch);
return resourceQuery.getResult(CDOResourceNode.class);
}
/**
* @since 2.0
*/
public CloseableIterator<CDOResourceNode> queryResourcesAsync(CDOResourceFolder folder, String name,
boolean exactMatch)
{
checkActive();
CDOQuery resourceQuery = createResourcesQuery(folder, name, exactMatch);
return resourceQuery.getResultAsync(CDOResourceNode.class);
}
private CDOQuery createResourcesQuery(CDOResourceFolder folder, String name, boolean exactMatch)
{
CDOQuery query = createQuery(CDOProtocolConstants.QUERY_LANGUAGE_RESOURCES, name);
query.setParameter(CDOProtocolConstants.QUERY_LANGUAGE_RESOURCES_FOLDER_ID, folder == null ? null : folder.cdoID());
query.setParameter(CDOProtocolConstants.QUERY_LANGUAGE_RESOURCES_EXACT_MATCH, exactMatch);
return query;
}
public CDOResourceImpl getResource(CDOID resourceID)
{
if (CDOIDUtil.isNull(resourceID))
{
throw new IllegalArgumentException("resourceID: " + resourceID);
}
return (CDOResourceImpl)getObject(resourceID);
}
public InternalCDOObject newInstance(CDOClass cdoClass)
{
EClass eClass = ModelUtil.getEClass(cdoClass, session.getPackageRegistry());
if (eClass == null)
{
throw new IllegalStateException("No EClass for " + cdoClass);
}
return newInstance(eClass);
}
public InternalCDOObject newInstance(EClass eClass)
{
EObject eObject = EcoreUtil.create(eClass);
return FSMUtil.adapt(eObject, this);
}
public InternalCDORevision getRevision(CDOID id, boolean loadOnDemand)
{
CDORevisionResolver revisionManager = session.getRevisionManager();
int initialChunkSize = session.options().getCollectionLoadingPolicy().getInitialChunkSize();
return (InternalCDORevision)revisionManager.getRevision(id, initialChunkSize, loadOnDemand);
}
public InternalCDOObject getObject(CDOID id)
{
return getObject(id, true);
}
/**
* Support recursivity and concurrency.
*/
public InternalCDOObject getObject(CDOID id, boolean loadOnDemand)
{
checkActive();
if (CDOIDUtil.isNull(id))
{
return null;
}
synchronized (objects)
{
if (id.equals(lastLookupID))
{
return lastLookupObject;
}
// Needed for recursive call to getObject. (from createObject/cleanObject/getResource/getObject)
InternalCDOObject localLookupObject = objects.get(id);
if (localLookupObject == null)
{
if (id.isMeta())
{
localLookupObject = createMetaObject((CDOIDMeta)id);
}
else
{
if (loadOnDemand)
{
localLookupObject = createObject(id);
}
else
{
return null;
}
}
// CDOResource have a special way to register to the view.
if (!localLookupObject.cdoClass().isResource())
{
registerObject(localLookupObject);
}
}
lastLookupID = id;
lastLookupObject = localLookupObject;
return lastLookupObject;
}
}
/**
* @since 2.0
*/
@SuppressWarnings("unchecked")
public <T extends EObject> T getObject(T objectFromDifferentView)
{
checkActive();
if (objectFromDifferentView instanceof CDOObject)
{
CDOObject object = (CDOObject)objectFromDifferentView;
CDOView view = object.cdoView();
if (view != this)
{
if (view.getSession() != session)
{
throw new IllegalArgumentException("Object is contaiuned in a different session: " + objectFromDifferentView);
}
CDOID id = object.cdoID();
objectFromDifferentView = (T)getObject(id, true);
}
}
return objectFromDifferentView;
}
public boolean isObjectRegistered(CDOID id)
{
checkActive();
if (CDOIDUtil.isNull(id))
{
return false;
}
synchronized (objects)
{
return objects.containsKey(id);
}
}
public InternalCDOObject removeObject(CDOID id)
{
synchronized (objects)
{
if (id.equals(lastLookupID))
{
lastLookupID = null;
lastLookupObject = null;
}
return objects.remove(id);
}
}
/**
* @return Never <code>null</code>
*/
private InternalCDOObject createMetaObject(CDOIDMeta id)
{
if (TRACER.isEnabled())
{
TRACER.trace("Creating meta object for " + id);
}
InternalEObject metaInstance = session.lookupMetaInstance(id);
if (metaInstance == null)
{
throw new ImplementationError("No metaInstance for " + id);
}
return new CDOMetaWrapper(this, metaInstance, id);
}
/**
* @return Never <code>null</code>
*/
private InternalCDOObject createObject(CDOID id)
{
if (TRACER.isEnabled())
{
TRACER.trace("Creating object for " + id);
}
InternalCDORevision revision = getRevision(id, true);
FSMUtil.validate(id, revision);
CDOClass cdoClass = revision.getCDOClass();
InternalCDOObject object;
if (cdoClass.isResource())
{
object = (InternalCDOObject)newResourceInstance(revision);
// object is PROXY
}
else
{
object = newInstance(cdoClass);
// object is TRANSIENT
}
cleanObject(object, revision);
return object;
}
private CDOResource newResourceInstance(InternalCDORevision revision)
{
String path = getResourcePath(revision);
return getResource(path, true);
}
private String getResourcePath(InternalCDORevision revision)
{
CDOResourcePackage resourcePackage = session.getPackageManager().getCDOResourcePackage();
CDOResourceNodeClass resourceNodeClass = resourcePackage.getCDOResourceNodeClass();
CDONameFeature nameFeature = resourceNodeClass.getCDONameFeature();
CDOID folderID = (CDOID)revision.data().getContainerID();
String name = (String)revision.data().get(nameFeature, 0);
if (CDOIDUtil.isNull(folderID))
{
if (name == null)
{
return CDOURIUtil.SEGMENT_SEPARATOR;
}
return name;
}
InternalCDOObject object = getObject(folderID, true);
if (object instanceof CDOResourceFolder)
{
CDOResourceFolder folder = (CDOResourceFolder)object;
String path = folder.getPath();
return path + CDOURIUtil.SEGMENT_SEPARATOR + name;
}
throw new ImplementationError("Not a ResourceFolder: " + object);
}
/**
* @since 2.0
*/
protected void cleanObject(InternalCDOObject object, InternalCDORevision revision)
{
object.cdoInternalCleanup();
object.cdoInternalSetView(this);
object.cdoInternalSetRevision(revision);
object.cdoInternalSetID(revision.getID());
object.cdoInternalSetState(CDOState.CLEAN);
object.cdoInternalPostLoad();
}
public CDOID provideCDOID(Object idOrObject)
{
Object shouldBeCDOID = convertObjectToID(idOrObject);
if (shouldBeCDOID instanceof CDOID)
{
CDOID id = (CDOID)shouldBeCDOID;
if (TRACER.isEnabled() && id != idOrObject)
{
TRACER.format("Converted object to CDOID: {0} --> {1}", idOrObject, id);
}
return id;
}
else if (idOrObject instanceof InternalEObject)
{
InternalEObject eObject = (InternalEObject)idOrObject;
String uri = EcoreUtil.getURI(eObject).toString();
if (eObject instanceof InternalCDOObject)
{
InternalCDOObject object = (InternalCDOObject)idOrObject;
if (object.cdoView() != null && FSMUtil.isNew(object))
{
return CDOIDUtil.createExternalTemp(uri);
}
}
if (eObject.eResource() != null)
{
return CDOIDUtil.createExternal(uri);
}
throw new DanglingReferenceException(eObject);
}
throw new IllegalStateException("Unable to provideCDOID: " + idOrObject.getClass().getName());
}
public Object convertObjectToID(Object potentialObject)
{
return convertObjectToID(potentialObject, false);
}
/**
* @since 2.0
*/
public Object convertObjectToID(Object potentialObject, boolean onlyPersistedID)
{
if (potentialObject instanceof CDOID)
{
return potentialObject;
}
if (potentialObject instanceof InternalEObject && !(potentialObject instanceof InternalCDOObject))
{
// TODO LEGACY
// try
// {
// InternalEObject eObject = (InternalEObject)potentialObject;
// Object legacyListener = FSMUtil.getLegacyWrapper(eObject);
// if (legacyListener != null)
// {
// potentialObject = legacyListener;
// }
// }
// catch (Throwable ex)
// {
// OM.LOG.warn(ex);
// }
}
if (potentialObject instanceof InternalCDOObject)
{
InternalCDOObject object = (InternalCDOObject)potentialObject;
boolean newOrTransient = FSMUtil.isTransient(object) || FSMUtil.isNew(object);
if (object.cdoView() == this && (!onlyPersistedID || !newOrTransient))
{
return object.cdoID();
}
}
return potentialObject;
}
public Object convertIDToObject(Object potentialID)
{
if (potentialID instanceof CDOID)
{
if (potentialID == CDOID.NULL)
{
return null;
}
CDOID id = (CDOID)potentialID;
if (id.isExternal())
{
return getResourceSet().getEObject(URI.createURI(id.toURIFragment()), true);
}
InternalCDOObject result = getObject(id, true);
if (result == null)
{
throw new ImplementationError("ID not registered: " + id);
}
return result.cdoInternalInstance();
}
return potentialID;
}
/**
* @since 2.0
*/
public void attachResource(CDOResourceImpl resource)
{
if (!resource.isExisting())
{
throw new ReadOnlyException("CDO view is read-only: " + this);
}
// ResourceSet.getResource(uri, true) was called!!
resource.cdoInternalSetView(this);
resource.cdoInternalSetState(CDOState.PROXY);
}
/**
* @since 2.0
*/
public void registerProxyResource(CDOResourceImpl resource)
{
URI uri = resource.getURI();
String path = CDOURIUtil.extractResourcePath(uri);
try
{
CDOID id = getResourceID(path);
resource.cdoInternalSetID(id);
registerObject(resource);
}
catch (Exception ex)
{
throw new InvalidURIException(uri, ex);
}
}
public void registerObject(InternalCDOObject object)
{
if (TRACER.isEnabled())
{
TRACER.format("Registering {0}", object);
}
InternalCDOObject old;
synchronized (objects)
{
old = objects.put(object.cdoID(), object);
}
if (old != null)
{
throw new IllegalStateException("Duplicate ID: " + object);
}
}
public void deregisterObject(InternalCDOObject object)
{
if (TRACER.isEnabled())
{
TRACER.format("Deregistering {0}", object);
}
removeObject(object.cdoID());
}
public void remapObject(CDOID oldID)
{
CDOID newID;
synchronized (objects)
{
InternalCDOObject object = objects.remove(oldID);
newID = object.cdoID();
objects.put(newID, object);
}
if (TRACER.isEnabled())
{
TRACER.format("Remapping {0} --> {1}", oldID, newID);
}
}
/**
* Turns registered objects into proxies and synchronously delivers invalidation events to registered event listeners.
* <p>
* <b>Implementation note:</b> This implementation guarantees that exceptions from listener code don't propagate up to
* the caller of this method. Runtime exceptions from the implementation of the {@link CDOStateMachine} are propagated
* to the caller of this method but this should not happen in the absence of implementation errors.
* <p>
* Note that this method can block for an uncertain amount of time on the reentrant view lock!
*
* @param timeStamp
* The time stamp of the server transaction if this event was sent as a result of a successfully committed
* transaction or <code>LOCAL_ROLLBACK</code> if this event was sent due to a local rollback.
* @param dirtyOIDs
* A set of the object IDs to be invalidated. <b>Implementation note:</b> This implementation expects the
* dirtyOIDs set to be unmodifiable. It does not wrap the set (again).
* @since 2.0
*/
public Set<CDOObject> handleInvalidation(long timeStamp, Set<CDOIDAndVersion> dirtyOIDs,
Collection<CDOID> detachedOIDs)
{
Set<CDOObject> conflicts = null;
Set<InternalCDOObject> dirtyObjects = new HashSet<InternalCDOObject>();
Set<InternalCDOObject> detachedObjects = new HashSet<InternalCDOObject>();
lock.lock();
try
{
for (CDOIDAndVersion dirtyOID : dirtyOIDs)
{
InternalCDOObject dirtyObject;
synchronized (objects)
{
dirtyObject = objects.get(dirtyOID.getID());
if (dirtyObject != null)
{
CDOStateMachine.INSTANCE.invalidate(dirtyObject, dirtyOID.getVersion());
dirtyObjects.add(dirtyObject);
if (dirtyObject.cdoConflict())
{
if (conflicts == null)
{
conflicts = new HashSet<CDOObject>();
}
conflicts.add(dirtyObject);
}
}
}
}
for (CDOID id : detachedOIDs)
{
InternalCDOObject detachedObject = removeObject(id);
if (detachedObject != null)
{
CDOStateMachine.INSTANCE.detachRemote(detachedObject);
detachedObjects.add(detachedObject);
if (detachedObject.cdoConflict())
{
if (conflicts == null)
{
conflicts = new HashSet<CDOObject>();
}
conflicts.add(detachedObject);
}
}
}
}
finally
{
lock.unlock();
}
if (options().isInvalidationNotificationEnabled())
{
for (InternalCDOObject dirtyObject : dirtyObjects)
{
if (dirtyObject.eNotificationRequired())
{
CDOInvalidationNotificationImpl notification = new CDOInvalidationNotificationImpl(dirtyObject);
dirtyObject.eNotify(notification);
}
}
for (InternalCDOObject detachedObject : detachedObjects)
{
if (detachedObject.eNotificationRequired())
{
CDOInvalidationNotificationImpl notification = new CDOInvalidationNotificationImpl(detachedObject);
detachedObject.eNotify(notification);
}
}
}
fireInvalidationEvent(timeStamp, Collections.unmodifiableSet(dirtyObjects), Collections
.unmodifiableSet(detachedObjects));
return conflicts;
}
/**
* @since 2.0
*/
public void fireInvalidationEvent(long timeStamp, Set<? extends CDOObject> dirtyObjects,
Set<? extends CDOObject> detachedObjects)
{
if (!dirtyObjects.isEmpty() || !detachedObjects.isEmpty())
{
fireEvent(new InvalidationEvent(timeStamp, dirtyObjects, detachedObjects));
}
}
/**
* @since 2.0
*/
public void handleChangeSubscription(Collection<CDORevisionDelta> deltas, Collection<CDOID> detachedObjects)
{
boolean policiesPresent = options().hasChangeSubscriptionPolicies();
if (!policiesPresent)
{
return;
}
if (deltas != null)
{
CDONotificationBuilder builder = new CDONotificationBuilder(getSession().getPackageRegistry());
for (CDORevisionDelta delta : deltas)
{
InternalCDOObject object = changeSubscriptionManager.getSubcribeObject(delta.getID());
if (object != null && object.eNotificationRequired())
{
NotificationImpl notification = builder.buildNotification(object, delta);
if (notification != null)
{
notification.dispatch();
}
}
}
}
if (detachedObjects != null)
{
for (CDOID id : detachedObjects)
{
InternalCDOObject object = changeSubscriptionManager.getSubcribeObject(id);
if (object != null && object.eNotificationRequired())
{
NotificationImpl notification = new CDODeltaNotificationImpl(object, CDONotification.DETACH_OBJECT,
Notification.NO_FEATURE_ID, null, null);
notification.dispatch();
}
}
getChangeSubscriptionManager().handleDetachedObjects(detachedObjects);
}
}
/**
* @since 2.0
*/
protected ChangeSubscriptionManager createChangeSubscriptionManager()
{
return new ChangeSubscriptionManager();
}
/**
* @since 2.0
*/
public AdapterManager getAdapterManager()
{
return adapterPolicyManager;
}
/**
* @since 2.0
*/
protected AdapterManager createAdapterManager()
{
return new AdapterManager();
}
/**
* @since 2.0
*/
public void handleAddAdapter(InternalCDOObject eObject, Adapter adapter)
{
if (!FSMUtil.isNew(eObject))
{
subscribe(eObject, adapter);
}
adapterPolicyManager.attachAdapter(eObject, adapter);
}
/**
* @since 2.0
*/
public void handleRemoveAdapter(InternalCDOObject eObject, Adapter adapter)
{
if (!FSMUtil.isNew(eObject))
{
unsubscribe(eObject, adapter);
}
adapterPolicyManager.detachAdapter(eObject, adapter);
}
/**
* @since 2.0
*/
public void subscribe(EObject eObject, Adapter adapter)
{
changeSubscriptionManager.subscribe(eObject, adapter);
}
/**
* @since 2.0
*/
public void unsubscribe(EObject eObject, Adapter adapter)
{
changeSubscriptionManager.unsubscribe(eObject, adapter);
}
/**
* @since 2.0
*/
public boolean hasSubscription(CDOID id)
{
return changeSubscriptionManager.getSubcribeObject(id) != null;
}
/**
* @since 2.0
*/
protected ChangeSubscriptionManager getChangeSubscriptionManager()
{
return changeSubscriptionManager;
}
/**
* Needed for {@link CDOAuditImpl#setTimeStamp(long)}.
*
* @since 2.0
*/
protected List<InternalCDOObject> getInvalidObjects(long timeStamp)
{
List<InternalCDOObject> result = new ArrayList<InternalCDOObject>();
synchronized (objects)
{
for (InternalCDOObject object : objects.values())
{
CDORevision revision = object.cdoRevision();
if (revision == null)
{
revision = getRevision(object.cdoID(), false);
}
if (revision == null || !revision.isValid(timeStamp))
{
result.add(object);
}
}
}
return result;
}
public int reload(CDOObject... objects)
{
Collection<InternalCDOObject> internalObjects;
// TODO Should objects.length == 0 reload *all* objects, too?
if (objects != null && objects.length != 0)
{
internalObjects = new ArrayList<InternalCDOObject>(objects.length);
for (CDOObject object : objects)
{
if (object instanceof InternalCDOObject)
{
internalObjects.add((InternalCDOObject)object);
}
}
}
else
{
synchronized (this.objects)
{
internalObjects = new ArrayList<InternalCDOObject>(this.objects.values());
}
}
int result = internalObjects.size();
if (result != 0)
{
CDOStateMachine.INSTANCE.reload(internalObjects.toArray(new InternalCDOObject[result]));
}
return result;
}
public void close()
{
deactivate();
}
/**
* @since 2.0
*/
public boolean isClosed()
{
return !isActive();
}
@Override
public String toString()
{
return MessageFormat.format("CDOView({0})", viewID);
}
public boolean isAdapterForType(Object type)
{
return type instanceof ResourceSet;
}
public org.eclipse.emf.common.notify.Notifier getTarget()
{
return getResourceSet();
}
/**
* @since 2.0
*/
@Override
protected void doBeforeActivate() throws Exception
{
super.doBeforeActivate();
checkState(session, "session");
checkState(viewID > 0, "viewID");
}
/**
* @since 2.0
*/
@Override
protected void doActivate() throws Exception
{
CDOClientProtocol protocol = (CDOClientProtocol)getSession().getProtocol();
new ViewsChangedRequest(protocol, getViewID(), getProtocolViewType(), getTimeStamp()).send();
}
/**
* @since 2.0
*/
@Override
protected void doDeactivate() throws Exception
{
CDOClientProtocol protocol = (CDOClientProtocol)getSession().getProtocol();
new ViewsChangedRequest(protocol, getViewID()).send();
session.viewDetached(this);
session = null;
objects = null;
store = null;
viewSet = null;
changeSubscriptionManager = null;
featureAnalyzer = null;
lastLookupID = null;
lastLookupObject = null;
options = null;
}
private byte getProtocolViewType()
{
Type viewType = getViewType();
switch (viewType)
{
case READONLY:
return CDOProtocolConstants.VIEW_READONLY;
case TRANSACTION:
return CDOProtocolConstants.VIEW_TRANSACTION;
case AUDIT:
return CDOProtocolConstants.VIEW_AUDIT;
default:
throw new IllegalStateException("Invalid view type: " + viewType);
}
}
/**
* @author Eike Stepper
*/
protected abstract class Event extends org.eclipse.net4j.util.event.Event implements CDOViewEvent
{
private static final long serialVersionUID = 1L;
public Event()
{
super(CDOViewImpl.this);
}
public CDOViewImpl getView()
{
return CDOViewImpl.this;
}
}
/**
* @author Simon McDuff
* @since 2.0
*/
protected class AdapterManager
{
private Set<CDOObject> objects = new HashBag<CDOObject>();
public void committedTransaction(CDOTransaction transaction, CDOCommitContext commitContext)
{
if (options().getStrongReferencePolicy() != CDOAdapterPolicy.NONE)
{
for (CDOObject object : commitContext.getNewObjects().values())
{
attachObject(object);
}
for (CDOObject object : commitContext.getNewResources().values())
{
attachObject(object);
}
for (CDOObject object : commitContext.getDetachedObjects().values())
{
detachObject(object);
}
}
}
protected synchronized void attachObject(CDOObject object)
{
CDOAdapterPolicy strongReferencePolicy = options().getStrongReferencePolicy();
int count = 0;
for (Adapter adapter : object.eAdapters())
{
if (strongReferencePolicy.isValid(object, adapter))
{
count++;
}
}
for (int i = 0; i < count; i++)
{
objects.add(object);
}
}
protected synchronized void detachObject(CDOObject object)
{
while (objects.remove(object))
{
// Do nothing
}
}
protected synchronized void attachAdapter(CDOObject object, Adapter adapter)
{
if (options().getStrongReferencePolicy().isValid(object, adapter))
{
objects.add(object);
}
}
protected synchronized void detachAdapter(CDOObject object, Adapter adapter)
{
if (options().getStrongReferencePolicy().isValid(object, adapter))
{
objects.add(object);
}
}
public synchronized void reset()
{
// Keep the object in memory
Set<CDOObject> oldObject = objects;
objects = new HashBag<CDOObject>();
if (options().getStrongReferencePolicy() != CDOAdapterPolicy.NONE)
{
InternalCDOObject objects[] = getObjectsArray();
for (int i = 0; i < objects.length; i++)
{
InternalCDOObject object = objects[i];
attachObject(object);
}
}
oldObject.clear();
}
};
/**
* @author Simon McDuff
* @since 2.0
*/
protected class ChangeSubscriptionManager
{
private Map<CDOID, SubscribeEntry> subscriptions = new HashMap<CDOID, SubscribeEntry>()
{
private static final long serialVersionUID = 1L;
};
public void committedTransaction(CDOTransaction transaction, CDOCommitContext commitContext)
{
handleNewObjects(commitContext.getNewObjects().values());
handleNewObjects(commitContext.getNewObjects().values());
handleDetachedObjects(commitContext.getDetachedObjects().keySet());
}
public void subscribe(EObject eObject, Adapter adapter)
{
subscribe(eObject, adapter, 1);
}
public void unsubscribe(EObject eObject, Adapter adapter)
{
subscribe(eObject, adapter, -1);
}
/**
* Register to the server all objects from the active list
*/
protected void notifyChangeSubcriptionPolicy()
{
boolean policiesPresent = options().hasChangeSubscriptionPolicies();
synchronized (subscriptions)
{
subscriptions.clear();
List<CDOID> cdoIDs = new ArrayList<CDOID>();
if (policiesPresent)
{
for (InternalCDOObject cdoObject : getObjectsArray())
{
int count = getNumberOfValidAdapter(cdoObject);
if (count > 0)
{
cdoIDs.add(cdoObject.cdoID());
addEntry(cdoObject.cdoID(), cdoObject, count);
}
}
}
request(cdoIDs, true, true);
}
}
protected void handleDetachedObjects(Collection<CDOID> detachedObjects)
{
synchronized (subscriptions)
{
for (CDOID id : detachedObjects)
{
SubscribeEntry entry = subscriptions.get(id);
if (entry != null)
{
detachObject(id);
}
}
}
}
protected void handleNewObjects(Collection<? extends CDOObject> newObjects)
{
synchronized (subscriptions)
{
for (CDOObject object : newObjects)
{
InternalCDOObject cdoDetachedObject = (InternalCDOObject)object;
if (cdoDetachedObject != null)
{
int count = getNumberOfValidAdapter(cdoDetachedObject);
if (count > 0)
{
subscribe(cdoDetachedObject.cdoID(), cdoDetachedObject, count);
}
}
}
}
}
protected InternalCDOObject getSubcribeObject(CDOID id)
{
synchronized (subscriptions)
{
SubscribeEntry entry = subscriptions.get(id);
if (entry != null)
{
return entry.getObject();
}
}
return null;
}
protected void request(List<CDOID> cdoIDs, boolean clear, boolean subscribeMode)
{
try
{
CDOClientProtocol protocol = (CDOClientProtocol)getSession().getProtocol();
new ChangeSubscriptionRequest(protocol, getViewID(), cdoIDs, subscribeMode, clear).send();
}
catch (Exception ex)
{
throw new TransactionException(ex);
}
}
protected int getNumberOfValidAdapter(InternalCDOObject object)
{
int count = 0;
if (!FSMUtil.isTransient(object) && !FSMUtil.isNew(object))
{
if (object.eNotificationRequired())
{
for (Adapter adapter : object.eAdapters())
{
if (shouldSubscribe(object, adapter))
{
count++;
}
}
}
}
return count;
}
private void subscribe(EObject eObject, Adapter adapter, int adjust)
{
synchronized (subscriptions)
{
if (shouldSubscribe(eObject, adapter))
{
InternalCDOObject internalCDOObject = FSMUtil.adapt(eObject, CDOViewImpl.this);
if (internalCDOObject.cdoView() != CDOViewImpl.this)
{
throw new CDOException("Object " + internalCDOObject + " doesn`t belong to this view.");
}
subscribe(internalCDOObject.cdoID(), internalCDOObject, adjust);
}
}
}
private boolean shouldSubscribe(EObject eObject, Adapter adapter)
{
for (CDOAdapterPolicy policy : options().getChangeSubscriptionPolicies())
{
if (policy.isValid(eObject, adapter))
{
return true;
}
}
return false;
}
private void subscribe(CDOID id, InternalCDOObject cdoObject, int adjust)
{
boolean policiesPresent = options().hasChangeSubscriptionPolicies();
synchronized (subscriptions)
{
int count = 0;
SubscribeEntry entry = subscriptions.get(id);
if (entry == null)
{
// Cannot adjust negative value
if (adjust < 0)
{
return;
}
// Notification need to be enable to send correct value to the server
if (policiesPresent)
{
request(Collections.singletonList(id), false, true);
}
}
else
{
count = entry.getCount();
}
count += adjust;
// Look if objects need to be unsubscribe
if (count <= 0)
{
subscriptions.remove(id);
// Notification need to be enable to send correct value to the server
if (policiesPresent)
{
request(Collections.singletonList(id), false, false);
}
}
else
{
if (entry == null)
{
addEntry(id, cdoObject, count);
}
else
{
entry.setCount(count);
}
}
}
}
private void detachObject(CDOID id)
{
subscribe(id, null, Integer.MIN_VALUE);
}
private void addEntry(CDOID key, InternalCDOObject object, int count)
{
subscriptions.put(key, new SubscribeEntry(key, object, count));
}
class SubscribeEntry
{
private CDOID id;
private int count = 0;
private InternalCDOObject object;
public SubscribeEntry(CDOID id, InternalCDOObject object, int count)
{
super();
this.id = id;
this.count = count;
this.object = object;
}
public int getCount()
{
return count;
}
public void setCount(int count)
{
this.count = count;
}
public CDOID getId()
{
return id;
}
public InternalCDOObject getObject()
{
return object;
}
}
}
/**
* @author Simon McDuff
*/
private final class InvalidationEvent extends Event implements CDOViewInvalidationEvent
{
private static final long serialVersionUID = 1L;
private long timeStamp;
private Set<? extends CDOObject> dirtyObjects;
private Set<? extends CDOObject> detachedObjects;
public InvalidationEvent(long timeStamp, Set<? extends CDOObject> dirtyOIDs,
Set<? extends CDOObject> detachedObjects)
{
this.timeStamp = timeStamp;
dirtyObjects = dirtyOIDs;
this.detachedObjects = detachedObjects;
}
public long getTimeStamp()
{
return timeStamp;
}
public Set<? extends CDOObject> getDirtyObjects()
{
return dirtyObjects;
}
public Set<? extends CDOObject> getDetachedObjects()
{
return detachedObjects;
}
@Override
public String toString()
{
return "CDOViewInvalidationEvent: " + dirtyObjects;
}
}
/**
* @author Eike Stepper
* @since 2.0
*/
protected class OptionsImpl extends Notifier implements Options
{
private boolean invalidationNotificationEnabled;
private CDORevisionPrefetchingPolicy revisionPrefetchingPolicy;
private HashBag<CDOAdapterPolicy> changeSubscriptionPolicies = new HashBag<CDOAdapterPolicy>();
private CDOAdapterPolicy adapterReferencePolicy = CDOAdapterPolicy.ALL;
public OptionsImpl()
{
setCacheReferenceType(null);
invalidationNotificationEnabled = OM.PREF_ENABLE_INVALIDATION_NOTIFICATION.getValue();
revisionPrefetchingPolicy = CDOUtil.createRevisionPrefetchingPolicy(OM.PREF_REVISION_LOADING_CHUNK_SIZE
.getValue());
}
public CDOViewImpl getContainer()
{
return CDOViewImpl.this;
}
public boolean isInvalidationNotificationEnabled()
{
return invalidationNotificationEnabled;
}
public void setInvalidationNotificationEnabled(boolean enabled)
{
if (invalidationNotificationEnabled != enabled)
{
invalidationNotificationEnabled = enabled;
fireEvent(new InvalidationNotificationEventImpl());
}
}
public boolean hasChangeSubscriptionPolicies()
{
synchronized (changeSubscriptionPolicies)
{
return !changeSubscriptionPolicies.isEmpty();
}
}
public CDOAdapterPolicy[] getChangeSubscriptionPolicies()
{
synchronized (changeSubscriptionPolicies)
{
return changeSubscriptionPolicies.toArray(new CDOAdapterPolicy[changeSubscriptionPolicies.size()]);
}
}
public void addChangeSubscriptionPolicy(CDOAdapterPolicy policy)
{
boolean changed = false;
synchronized (changeSubscriptionPolicies)
{
if (changeSubscriptionPolicies.add(policy))
{
changeSubscriptionManager.notifyChangeSubcriptionPolicy();
changed = true;
}
}
if (changed)
{
fireEvent(new ChangeSubscriptionPoliciesEventImpl());
}
}
public void removeChangeSubscriptionPolicy(CDOAdapterPolicy policy)
{
boolean changed = false;
synchronized (changeSubscriptionPolicies)
{
if (changeSubscriptionPolicies.remove(policy) && !changeSubscriptionPolicies.contains(policy))
{
changeSubscriptionManager.notifyChangeSubcriptionPolicy();
changed = true;
}
}
if (changed)
{
fireEvent(new ChangeSubscriptionPoliciesEventImpl());
}
}
public CDOAdapterPolicy getStrongReferencePolicy()
{
return adapterReferencePolicy;
}
public void setStrongReferencePolicy(CDOAdapterPolicy adapterPolicy)
{
if (adapterPolicy == null)
{
adapterPolicy = CDOAdapterPolicy.ALL;
}
if (adapterReferencePolicy != adapterPolicy)
{
adapterReferencePolicy = adapterPolicy;
adapterPolicyManager.reset();
fireEvent(new ReferencePolicyEventImpl());
}
}
public CDORevisionPrefetchingPolicy getRevisionPrefetchingPolicy()
{
return revisionPrefetchingPolicy;
}
public void setRevisionPrefetchingPolicy(CDORevisionPrefetchingPolicy prefetchingPolicy)
{
if (prefetchingPolicy == null)
{
prefetchingPolicy = CDORevisionPrefetchingPolicy.NO_PREFETCHING;
}
if (revisionPrefetchingPolicy != prefetchingPolicy)
{
revisionPrefetchingPolicy = prefetchingPolicy;
fireEvent(new RevisionPrefetchingPolicyEventImpl());
}
}
public ReferenceType getCacheReferenceType()
{
if (objects instanceof ReferenceValueMap.Strong<?, ?>)
{
return ReferenceType.STRONG;
}
if (objects instanceof ReferenceValueMap.Soft<?, ?>)
{
return ReferenceType.SOFT;
}
if (objects instanceof ReferenceValueMap.Weak<?, ?>)
{
return ReferenceType.WEAK;
}
throw new IllegalStateException("referenceType");
}
public boolean setCacheReferenceType(ReferenceType referenceType)
{
if (referenceType == null)
{
referenceType = ReferenceType.SOFT;
}
ReferenceValueMap<CDOID, InternalCDOObject> newObjects;
switch (referenceType)
{
case STRONG:
if (objects instanceof ReferenceValueMap.Strong<?, ?>)
{
return false;
}
newObjects = new ReferenceValueMap.Strong<CDOID, InternalCDOObject>();
break;
case SOFT:
if (objects instanceof ReferenceValueMap.Soft<?, ?>)
{
return false;
}
newObjects = new ReferenceValueMap.Soft<CDOID, InternalCDOObject>();
break;
case WEAK:
if (objects instanceof ReferenceValueMap.Weak<?, ?>)
{
return false;
}
newObjects = new ReferenceValueMap.Weak<CDOID, InternalCDOObject>();
break;
default:
throw new IllegalArgumentException("referenceType");
}
if (objects == null)
{
objects = newObjects;
fireEvent(new CacheReferenceTypeEventImpl());
return true;
}
for (Entry<CDOID, InternalCDOObject> entry : objects.entrySet())
{
InternalCDOObject object = entry.getValue();
if (object != null)
{
newObjects.put(entry.getKey(), object);
}
}
ConcurrentMap<CDOID, InternalCDOObject> oldObjects = objects;
synchronized (objects)
{
objects = newObjects;
}
oldObjects.clear();
fireEvent(new CacheReferenceTypeEventImpl());
return true;
}
/**
* @author Eike Stepper
*/
private final class CacheReferenceTypeEventImpl extends OptionsEvent implements CacheReferenceTypeEvent
{
private static final long serialVersionUID = 1L;
public CacheReferenceTypeEventImpl()
{
super(OptionsImpl.this);
}
}
/**
* @author Eike Stepper
*/
private final class ChangeSubscriptionPoliciesEventImpl extends OptionsEvent implements
ChangeSubscriptionPoliciesEvent
{
private static final long serialVersionUID = 1L;
public ChangeSubscriptionPoliciesEventImpl()
{
super(OptionsImpl.this);
}
}
/**
* @author Eike Stepper
*/
private final class InvalidationNotificationEventImpl extends OptionsEvent implements InvalidationNotificationEvent
{
private static final long serialVersionUID = 1L;
public InvalidationNotificationEventImpl()
{
super(OptionsImpl.this);
}
}
/**
* @author Eike Stepper
*/
private final class RevisionPrefetchingPolicyEventImpl extends OptionsEvent implements
RevisionPrefetchingPolicyEvent
{
private static final long serialVersionUID = 1L;
public RevisionPrefetchingPolicyEventImpl()
{
super(OptionsImpl.this);
}
}
/**
* @author Eike Stepper
*/
private final class ReferencePolicyEventImpl extends OptionsEvent implements ReferencePolicyEvent
{
private static final long serialVersionUID = 1L;
public ReferencePolicyEventImpl()
{
super(OptionsImpl.this);
}
}
}
}