/*
 * Copyright (c) 2009-2015 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
 *    Simon McDuff - maintenance
 *    Victor Roldan Betancort - maintenance
 */
package org.eclipse.emf.internal.cdo.view;

import org.eclipse.emf.cdo.CDONotification;
import org.eclipse.emf.cdo.CDOObject;
import org.eclipse.emf.cdo.CDOState;
import org.eclipse.emf.cdo.common.CDOCommonView;
import org.eclipse.emf.cdo.common.branch.CDOBranch;
import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo.Operation;
import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.emf.cdo.common.lock.CDOLockUtil;
import org.eclipse.emf.cdo.common.revision.CDOIDAndBranch;
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.CDORevisionManager;
import org.eclipse.emf.cdo.common.revision.CDORevisionsLoadedEvent;
import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
import org.eclipse.emf.cdo.common.util.CDOCommonUtil;
import org.eclipse.emf.cdo.common.util.CDOException;
import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil;
import org.eclipse.emf.cdo.spi.common.lock.InternalCDOLockState;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;
import org.eclipse.emf.cdo.transaction.CDOCommitContext;
import org.eclipse.emf.cdo.transaction.CDOTransaction;
import org.eclipse.emf.cdo.util.CDOUtil;
import org.eclipse.emf.cdo.util.LockTimeoutException;
import org.eclipse.emf.cdo.util.ReadOnlyException;
import org.eclipse.emf.cdo.util.StaleRevisionLockException;
import org.eclipse.emf.cdo.view.CDOAdapterPolicy;
import org.eclipse.emf.cdo.view.CDOFeatureAnalyzer;
import org.eclipse.emf.cdo.view.CDOInvalidationPolicy;
import org.eclipse.emf.cdo.view.CDORevisionPrefetchingPolicy;
import org.eclipse.emf.cdo.view.CDOStaleReferencePolicy;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.cdo.view.CDOViewDurabilityChangedEvent;
import org.eclipse.emf.cdo.view.CDOViewInvalidationEvent;
import org.eclipse.emf.cdo.view.CDOViewLocksChangedEvent;

import org.eclipse.emf.internal.cdo.bundle.OM;
import org.eclipse.emf.internal.cdo.messages.Messages;
import org.eclipse.emf.internal.cdo.object.CDODeltaNotificationImpl;
import org.eclipse.emf.internal.cdo.object.CDOInvalidationNotificationImpl;
import org.eclipse.emf.internal.cdo.object.CDONotificationBuilder;
import org.eclipse.emf.internal.cdo.session.SessionUtil;
import org.eclipse.emf.internal.cdo.util.DefaultLocksChangedEvent;

import org.eclipse.net4j.util.ObjectUtil;
import org.eclipse.net4j.util.WrappedException;
import org.eclipse.net4j.util.collection.HashBag;
import org.eclipse.net4j.util.collection.Pair;
import org.eclipse.net4j.util.concurrent.ConcurrencyUtil;
import org.eclipse.net4j.util.concurrent.ExecutorWorkSerializer;
import org.eclipse.net4j.util.concurrent.IExecutorServiceProvider;
import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
import org.eclipse.net4j.util.concurrent.IWorkSerializer;
import org.eclipse.net4j.util.event.IEvent;
import org.eclipse.net4j.util.event.IListener;
import org.eclipse.net4j.util.event.Notifier;
import org.eclipse.net4j.util.event.ThrowableEvent;
import org.eclipse.net4j.util.lifecycle.LifecycleException;
import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
import org.eclipse.net4j.util.om.log.OMLogger;
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.net4j.util.options.IOptionsEvent;
import org.eclipse.net4j.util.options.OptionsEvent;
import org.eclipse.net4j.util.ref.ReferenceType;
import org.eclipse.net4j.util.ref.ReferenceValueMap;

import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.NotificationChain;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.spi.cdo.CDOSessionProtocol;
import org.eclipse.emf.spi.cdo.CDOSessionProtocol.LockObjectsResult;
import org.eclipse.emf.spi.cdo.CDOSessionProtocol.UnlockObjectsResult;
import org.eclipse.emf.spi.cdo.FSMUtil;
import org.eclipse.emf.spi.cdo.InternalCDOObject;
import org.eclipse.emf.spi.cdo.InternalCDOSession;
import org.eclipse.emf.spi.cdo.InternalCDOTransaction;
import org.eclipse.emf.spi.cdo.InternalCDOView;
import org.eclipse.emf.spi.cdo.InternalCDOViewSet;

import org.eclipse.core.runtime.IProgressMonitor;

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.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.ExecutorService;

/**
 * @author Eike Stepper
 */
public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProvider
{
  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_VIEW, CDOViewImpl.class);

  private int viewID;

  private InternalCDOSession session;

  private String durableLockingID;

  private ChangeSubscriptionManager changeSubscriptionManager = new ChangeSubscriptionManager();

  private AdapterManager adapterManager = new AdapterManager();

  private OptionsImpl options;

  private long lastUpdateTime;

  private CDOLockOwner lockOwner;

  private Map<CDOObject, CDOLockState> lockStates = new WeakHashMap<CDOObject, CDOLockState>();

  private ExecutorWorkSerializer invalidationRunner = createInvalidationRunner();

  private volatile boolean invalidationRunnerActive;

  /**
   * @since 2.0
   */
  public CDOViewImpl(CDOBranch branch, long timeStamp)
  {
    super(branch.getPoint(timeStamp));
    options = createOptions();
  }

  public CDOViewImpl(String durableLockingID)
  {
    this.durableLockingID = durableLockingID;
    options = createOptions();
  }

  /**
   * @since 2.0
   */
  public OptionsImpl options()
  {
    return options;
  }

  public int getViewID()
  {
    return viewID;
  }

  /**
   * @since 2.0
   */
  public void setViewID(int viewId)
  {
    viewID = viewId;
  }

  public ExecutorService getExecutorService()
  {
    return ConcurrencyUtil.getExecutorService(session);
  }

  /**
   * @since 2.0
   */
  public InternalCDOSession getSession()
  {
    return session;
  }

  /**
   * @since 2.0
   */
  public void setSession(InternalCDOSession session)
  {
    this.session = session;
  }

  public int getSessionID()
  {
    return session.getSessionID();
  }

  public synchronized boolean setBranchPoint(CDOBranchPoint branchPoint, IProgressMonitor progressMonitor)
  {
    checkActive();
    branchPoint = adjustBranchPoint(branchPoint);

    long timeStamp = branchPoint.getTimeStamp();
    long creationTimeStamp = session.getRepositoryInfo().getCreationTime();
    if (timeStamp != UNSPECIFIED_DATE && timeStamp < creationTimeStamp)
    {
      throw new IllegalArgumentException(MessageFormat.format("timeStamp ({0}) < repository creation time ({1})", //$NON-NLS-1$
          CDOCommonUtil.formatTimeStamp(timeStamp), CDOCommonUtil.formatTimeStamp(creationTimeStamp)));
    }

    CDOBranchPoint oldBranchPoint = CDOBranchUtil.copyBranchPoint(getBranchPoint());
    if (branchPoint.equals(oldBranchPoint))
    {
      return false;
    }

    if (TRACER.isEnabled())
    {
      TRACER.format("Changing view target to {0}", branchPoint); //$NON-NLS-1$
    }

    Map<CDOID, InternalCDORevision> oldRevisions = CDOIDUtil.createMap();
    List<CDORevisionKey> allChangedObjects = new ArrayList<CDORevisionKey>();
    List<CDOIDAndVersion> allDetachedObjects = new ArrayList<CDOIDAndVersion>();

    List<InternalCDOObject> invalidObjects = getInvalidObjects(branchPoint);
    for (InternalCDOObject object : invalidObjects)
    {
      InternalCDORevision revision = object.cdoRevision();
      if (revision != null)
      {
        oldRevisions.put(object.cdoID(), revision);
      }
    }

    CDOSessionProtocol sessionProtocol = session.getSessionProtocol();
    OMMonitor monitor = progressMonitor != null ? new EclipseMonitor(progressMonitor) : null;
    sessionProtocol.switchTarget(viewID, branchPoint, invalidObjects, allChangedObjects, allDetachedObjects, monitor);

    basicSetBranchPoint(branchPoint);
    CDOBranch branch = branchPoint.getBranch();

    try
    {
      CDOStateMachine.SWITCHING_TARGET.set(Boolean.TRUE);
      doInvalidate(branch, UNSPECIFIED_DATE, allChangedObjects, allDetachedObjects, oldRevisions, true);
    }
    finally
    {
      CDOStateMachine.SWITCHING_TARGET.remove();
    }

    IListener[] listeners = getListeners();
    if (listeners != null)
    {
      fireViewTargetChangedEvent(oldBranchPoint, listeners);
    }

    return true;
  }

  private List<InternalCDOObject> getInvalidObjects(CDOBranchPoint branchPoint)
  {
    List<InternalCDOObject> result = new ArrayList<InternalCDOObject>();
    for (InternalCDOObject object : getModifiableObjects().values())
    {
      CDORevision revision = object.cdoRevision(false);
      if (revision == null || !revision.isValid(branchPoint))
      {
        result.add(object);
      }
    }

    return result;
  }

  private Set<? extends CDOObject> getSet(Collection<? extends CDOObject> objects)
  {
    if (objects instanceof Set)
    {
      return (Set<? extends CDOObject>)objects;
    }

    return new HashSet<CDOObject>(objects);
  }

  /**
   * @throws InterruptedException
   * @since 2.0
   */
  public synchronized void lockObjects(Collection<? extends CDOObject> objects, LockType lockType, long timeout)
      throws InterruptedException
  {
    lockObjects(objects, lockType, timeout, false);
  }

  public synchronized void lockObjects(Collection<? extends CDOObject> objects, LockType lockType, long timeout,
      boolean recursive) throws InterruptedException
  {
    checkActive();
    checkState(getTimeStamp() == UNSPECIFIED_DATE, "Locking not supported for historial views");

    Set<? extends CDOObject> uniqueObjects = getSet(objects);
    int size = uniqueObjects.size();

    List<CDORevisionKey> revisionKeys = new ArrayList<CDORevisionKey>(size);
    List<CDOLockState> locksOnNewObjects = new ArrayList<CDOLockState>(size);

    for (CDOObject object : uniqueObjects)
    {
      if (FSMUtil.isNew(object))
      {
        CDOLockState lockState = createUpdatedLockStateForNewObject(object, lockType, true);
        locksOnNewObjects.add(lockState);
      }
      else
      {
        InternalCDORevision revision = getRevision(object);
        if (revision != null)
        {
          revisionKeys.add(revision);
        }
      }
    }

    LockObjectsResult result = null;
    if (!revisionKeys.isEmpty())
    {
      CDOSessionProtocol sessionProtocol = session.getSessionProtocol();
      result = sessionProtocol.lockObjects2(revisionKeys, viewID, getBranch(), lockType, recursive, timeout);

      if (!result.isSuccessful())
      {
        if (result.isTimedOut())
        {
          throw new LockTimeoutException();
        }

        CDORevisionKey[] staleRevisions = result.getStaleRevisions();
        if (staleRevisions != null)
        {
          throw new StaleRevisionLockException(staleRevisions);
        }

        throw new AssertionError("Unexpected lock result state");
      }

      if (result.isWaitForUpdate())
      {
        if (!session.options().isPassiveUpdateEnabled())
        {
          throw new AssertionError(
              "Lock result requires client to wait, but client does not have passiveUpdates enabled");
        }

        long requiredTimestamp = result.getRequiredTimestamp();
        if (!waitForUpdate(requiredTimestamp, 10000L))
        {
          throw new AssertionError("Lock result requires client to wait for commit " + requiredTimestamp
              + ", but client did not receive invalidations after " + lastUpdateTime);
        }

        InternalCDOSession session = this.session;
        InternalCDORevisionManager revisionManager = session.getRevisionManager();

        for (CDORevisionKey requiredKey : result.getStaleRevisions())
        {
          CDOID id = requiredKey.getID();
          InternalCDOObject object = getObject(id);

          CDORevision revision = object.cdoRevision(true);
          if (!requiredKey.equals(revision))
          {
            InternalCDORevision requiredRevision = revisionManager.getRevisionByVersion(id, requiredKey,
                CDORevision.UNCHUNKED, true);
            InternalCDORevisionDelta revisionDelta = requiredRevision.compare(revision);
            CDOStateMachine.INSTANCE.invalidate(object, revisionDelta);
          }
        }
      }
    }

    CDOLockState[] locksOnNewObjectsArray = locksOnNewObjects.toArray(new CDOLockState[locksOnNewObjects.size()]);
    updateLockStates(locksOnNewObjectsArray);

    if (result != null)
    {
      updateAndNotifyLockStates(Operation.LOCK, lockType, result.getTimestamp(), result.getNewLockStates());
    }
  }

  protected void updateAndNotifyLockStates(Operation op, LockType type, long timestamp, CDOLockState[] newLockStates)
  {
    updateLockStates(newLockStates);
    notifyOtherViewsAboutLockChanges(op, type, timestamp, newLockStates);
  }

  /**
   * Updates the lock states of objects held in this view
   */
  protected void updateLockStates(CDOLockState[] newLockStates)
  {
    for (CDOLockState lockState : newLockStates)
    {
      Object lockedObject = lockState.getLockedObject();
      CDOID id;

      if (lockedObject instanceof CDOID)
      {
        id = (CDOID)lockedObject;
      }
      else if (lockedObject instanceof CDOIDAndBranch)
      {
        id = ((CDOIDAndBranch)lockedObject).getID();
      }
      else if (lockedObject instanceof EObject)
      {
        CDOObject newObj = CDOUtil.getCDOObject((EObject)lockedObject);
        id = newObj.cdoID();
      }
      else
      {
        throw new IllegalStateException("Unexpected: " + lockedObject.getClass().getSimpleName());
      }

      InternalCDOObject object = getObject(id, false);
      if (object != null)
      {
        InternalCDOLockState existingLockState = (InternalCDOLockState)lockStates.get(object);
        if (existingLockState != null)
        {
          Object lockTarget = getLockTarget(object);
          existingLockState.updateFrom(lockTarget, lockState);
        }
        else
        {
          lockStates.put(object, lockState);
        }
      }
    }
  }

  /**
   * Notifies other views of lock changes performed in this view
   */
  private void notifyOtherViewsAboutLockChanges(Operation op, LockType type, long timestamp, CDOLockState[] lockStates)
  {
    if (lockStates.length > 0)
    {
      CDOLockChangeInfo lockChangeInfo = makeLockChangeInfo(op, type, timestamp, lockStates);
      session.handleLockNotification(lockChangeInfo, this);

      if (isActive())
      {
        fireLocksChangedEvent(this, lockChangeInfo);
      }
    }
  }

  private CDOLockChangeInfo makeLockChangeInfo(Operation op, LockType type, long timestamp,
      CDOLockState[] newLockStates)
  {
    return CDOLockUtil.createLockChangeInfo(timestamp, this, getBranch(), op, type, newLockStates);
  }

  public void handleLockNotification(InternalCDOView sender, CDOLockChangeInfo lockChangeInfo)
  {
    CDOLockChangeInfo event = null;

    try
    {
      synchronized (lockStates)
      {
        if (!options().isLockNotificationEnabled())
        {
          return;
        }

        if (lockChangeInfo.isInvalidateAll())
        {
          lockStates.clear();
          event = lockChangeInfo;
          return;
        }

        // If lockChangeInfo pertains to a different view, do nothing.
        CDOBranch lockChangeBranch = lockChangeInfo.getBranch();
        CDOBranch viewBranch = getBranch();
        if (lockChangeBranch != viewBranch)
        {
          return;
        }

        if (lockChangeInfo.getLockOwner().equals(lockOwner))
        {
          return;
        }

        // TODO (CD) I know it is Eike's desideratum that this be done asynchronously.. but beware,
        // this will require the tests to be fixed to listen for the view events instead of the
        // session events.
        updateLockStates(lockChangeInfo.getLockStates());
        event = lockChangeInfo;
      }
    }
    finally
    {
      if (event != null)
      {
        fireLocksChangedEvent(sender, event);
      }
    }
  }

  private void fireLocksChangedEvent(InternalCDOView sender, CDOLockChangeInfo lockChangeInfo)
  {
    IListener[] listeners = getListeners();
    if (listeners != null)
    {
      fireEvent(new LocksChangedEvent(sender, lockChangeInfo), listeners);
    }
  }

  protected InternalCDORevision getRevision(CDOObject object)
  {
    if (object.cdoState() == CDOState.NEW)
    {
      return null;
    }

    InternalCDORevision revision = (InternalCDORevision)object.cdoRevision();
    if (revision == null)
    {
      revision = CDOStateMachine.INSTANCE.read((InternalCDOObject)object);
    }

    return revision;
  }

  /**
   * @since 2.0
   */
  public synchronized void unlockObjects(Collection<? extends CDOObject> objects, LockType lockType)
  {
    unlockObjects(objects, lockType, false);
  }

  /**
   * Note: This may get called with objects == null, and lockType == null, which is a request to remove all locks on all
   * objects in this view.
   */
  public synchronized void unlockObjects(Collection<? extends CDOObject> objects, LockType lockType, boolean recursive)
  {
    checkActive();

    List<CDOID> objectIDs = null;
    List<CDOLockState> locksOnNewObjects = new LinkedList<CDOLockState>();

    if (objects != null)
    {
      objectIDs = new ArrayList<CDOID>();

      for (CDOObject object : getSet(objects))
      {
        if (FSMUtil.isNew(object))
        {
          CDOLockState lockState = createUpdatedLockStateForNewObject(object, lockType, false);
          locksOnNewObjects.add(lockState);
        }
        else
        {
          objectIDs.add(object.cdoID());
        }
      }
    }
    else
    {
      locksOnNewObjects.addAll(createUnlockedLockStatesForAllNewObjects());
    }

    UnlockObjectsResult result = null;
    if (objectIDs == null || !objectIDs.isEmpty())
    {
      CDOSessionProtocol sessionProtocol = session.getSessionProtocol();
      result = sessionProtocol.unlockObjects2(this, objectIDs, lockType, recursive);
    }

    CDOLockState[] locksOnNewObjectsArray = locksOnNewObjects.toArray(new CDOLockState[locksOnNewObjects.size()]);
    updateLockStates(locksOnNewObjectsArray);

    if (result != null)
    {
      updateAndNotifyLockStates(Operation.UNLOCK, lockType, result.getTimestamp(), result.getNewLockStates());
    }
  }

  protected InternalCDOLockState createUpdatedLockStateForNewObject(CDOObject object, LockType lockType, boolean on)
  {
    throw new ReadOnlyException();
  }

  protected Collection<CDOLockState> createUnlockedLockStatesForAllNewObjects()
  {
    return Collections.emptyList();
  }

  /**
   * @since 2.0
   */
  public synchronized void unlockObjects()
  {
    unlockObjects(null, null);
  }

  /**
   * @since 2.0
   */
  public synchronized boolean isObjectLocked(CDOObject object, LockType lockType, boolean byOthers)
  {
    checkActive();
    CDOSessionProtocol sessionProtocol = session.getSessionProtocol();
    return sessionProtocol.isObjectLocked(this, object, lockType, byOthers);
  }

  public boolean isDurableView()
  {
    return durableLockingID != null;
  }

  public synchronized String getDurableLockingID()
  {
    return durableLockingID;
  }

  @Deprecated
  public String enableDurableLocking(boolean enable)
  {
    if (enable)
    {
      return enableDurableLocking();
    }

    disableDurableLocking(false);
    return null;
  }

  public String enableDurableLocking()
  {
    final String oldID = durableLockingID;

    try
    {
      synchronized (this)
      {
        CDOSessionProtocol sessionProtocol = session.getSessionProtocol();
        if (durableLockingID == null)
        {
          durableLockingID = sessionProtocol.changeLockArea(this, true);
        }

        return durableLockingID;
      }
    }
    finally
    {
      fireDurabilityChangedEvent(oldID);
    }
  }

  public void disableDurableLocking(boolean releaseLocks)
  {
    final String oldID = durableLockingID;

    try
    {
      synchronized (this)
      {
        CDOSessionProtocol sessionProtocol = session.getSessionProtocol();
        if (durableLockingID != null)
        {
          sessionProtocol.changeLockArea(this, false);
          durableLockingID = null;

          if (releaseLocks)
          {
            unlockObjects();
          }
        }
      }
    }
    finally
    {
      fireDurabilityChangedEvent(oldID);
    }
  }

  private void fireDurabilityChangedEvent(final String oldID)
  {
    if (!ObjectUtil.equals(oldID, durableLockingID))
    {
      fireEvent(new CDOViewDurabilityChangedEvent()
      {
        public CDOView getSource()
        {
          return CDOViewImpl.this;
        }

        public String getOldDurableLockingID()
        {
          return oldID;
        }

        public String getNewDurableLockingID()
        {
          return durableLockingID;
        }
      });
    }
  }

  /**
   * @since 2.0
   */
  @Deprecated
  public synchronized CDOFeatureAnalyzer getFeatureAnalyzer()
  {
    return options().getFeatureAnalyzer();
  }

  /**
   * @since 2.0
   */
  @Deprecated
  public synchronized void setFeatureAnalyzer(CDOFeatureAnalyzer featureAnalyzer)
  {
    options.setFeatureAnalyzer(featureAnalyzer);
  }

  /**
   * @since 2.0
   */
  public InternalCDOTransaction toTransaction()
  {
    checkActive();
    if (this instanceof InternalCDOTransaction)
    {
      return (InternalCDOTransaction)this;
    }

    throw new ReadOnlyException(MessageFormat.format(Messages.getString("CDOViewImpl.0"), this)); //$NON-NLS-1$
  }

  public synchronized InternalCDORevision getRevision(CDOID id, boolean loadOnDemand)
  {
    InternalCDORevisionManager revisionManager = session.getRevisionManager();
    int initialChunkSize = session.options().getCollectionLoadingPolicy().getInitialChunkSize();
    CDOBranchPoint branchPoint = getBranchPointForID(id);
    return revisionManager.getRevision(id, branchPoint, initialChunkSize, CDORevision.DEPTH_NONE, loadOnDemand);
  }

  @Override
  public synchronized void remapObject(CDOID oldID)
  {
    InternalCDOObject object = getObject(oldID, false);
    InternalCDOLockState oldLockState = (InternalCDOLockState)lockStates.get(object);
    if (oldLockState != null)
    {
      oldLockState.updateFrom(getLockTarget(object), oldLockState);
    }
    super.remapObject(oldID);
  }

  @Override
  public synchronized InternalCDOObject removeObject(CDOID id)
  {
    InternalCDOObject removedObject = super.removeObject(id);
    removeLockState(removedObject);
    return removedObject;
  }

  public synchronized CDOLockState[] getLockStates(Collection<CDOID> ids)
  {
    return getLockStates(ids, true);
  }

  protected synchronized CDOLockState[] getLockStates(Collection<CDOID> ids, boolean loadOnDemand)
  {
    List<CDOID> missing = new LinkedList<CDOID>();
    List<CDOLockState> lockStates = new LinkedList<CDOLockState>();
    List<CDOLockState> locksOnNewObjects = new ArrayList<CDOLockState>(ids.size());

    for (CDOID id : ids)
    {
      CDOLockState lockState = null;
      InternalCDOObject obj = getObject(id, false);
      if (obj != null)
      {
        lockState = this.lockStates.get(obj);
      }

      if (lockState != null)
      {
        lockStates.add(lockState);
      }
      else if (loadOnDemand && obj != null && FSMUtil.isNew(obj))
      {
        CDOLockState defaultLockState = CDOLockUtil.createLockState(getLockTarget(obj));
        locksOnNewObjects.add(defaultLockState);
        lockStates.add(defaultLockState);
      }
      else
      {
        missing.add(id);
      }
    }

    if (loadOnDemand && (missing.size() > 0 || ids.isEmpty()))
    {
      CDOSessionProtocol sessionProtocol = session.getSessionProtocol();
      CDOLockState[] loadedLockStates = sessionProtocol.getLockStates(viewID, missing, CDOLockState.DEPTH_NONE);
      List<CDOLockState> newLockStateForCache = new ArrayList<CDOLockState>(loadedLockStates.length + missing.size());
      for (CDOLockState loadedLockState : loadedLockStates)
      {
        lockStates.add(loadedLockState);
        newLockStateForCache.add(loadedLockState);

        CDOID cdoID = CDOIDUtil.getCDOID(loadedLockState.getLockedObject());
        if (cdoID != null)
        {
          missing.remove(cdoID);
        }
      }

      for (CDOID missingLockStateForCDOID : missing)
      {
        Object target;

        InternalCDOObject obj = getObject(missingLockStateForCDOID, false);
        if (obj != null)
        {
          target = getLockTarget(obj);
        }
        else
        {
          target = missingLockStateForCDOID;
        }

        CDOLockState defaultLockState = CDOLockUtil.createLockState(target);
        lockStates.add(defaultLockState);
        newLockStateForCache.add(defaultLockState);
      }

      if (options().isLockNotificationEnabled())
      {
        updateLockStates(newLockStateForCache.toArray(new CDOLockState[newLockStateForCache.size()]));
      }
    }

    CDOLockState[] locksOnNewObjectsArray = locksOnNewObjects.toArray(new CDOLockState[locksOnNewObjects.size()]);
    updateLockStates(locksOnNewObjectsArray);

    return lockStates.toArray(new CDOLockState[lockStates.size()]);
  }

  protected CDOLockState removeLockState(CDOObject object)
  {
    return lockStates.remove(object);
  }

  protected CDOLockState getLockState(CDOObject object)
  {
    return lockStates.get(object);
  }

  private CDOBranchPoint getBranchPointForID(CDOID id)
  {
    // If this view's timestamp is something other than UNSPECIFIED_DATE,
    // then this is an 'audit' view, and so this timestamp must always be
    // used without any concern for possible sticky-view behavior
    CDOBranchPoint branchPoint = getNormalizedBranchPoint();
    if (branchPoint.getTimeStamp() != UNSPECIFIED_DATE)
    {
      return branchPoint;
    }

    if (session.isSticky())
    {
      branchPoint = session.getCommittedSinceLastRefresh(id);
      if (branchPoint == null)
      {
        branchPoint = getBranch().getPoint(session.getLastUpdateTime());
      }

      return branchPoint;
    }

    return this;
  }

  public synchronized void prefetchRevisions(CDOID id, int depth)
  {
    checkArg(depth != CDORevision.DEPTH_NONE, "Prefetch depth must not be zero"); //$NON-NLS-1$
    int initialChunkSize = session.options().getCollectionLoadingPolicy().getInitialChunkSize();
    prefetchRevisions(id, depth, initialChunkSize);
  }

  protected void prefetchRevisions(CDOID id, int depth, int initialChunkSize)
  {
    CDORevisionManager revisionManager = session.getRevisionManager();
    revisionManager.getRevision(id, this, initialChunkSize, depth, true);
  }

  /*
   * Must not by synchronized on the view!
   */
  @Deprecated
  public/* synchronized */void invalidate(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects,
      List<CDOIDAndVersion> allDetachedObjects, Map<CDOID, InternalCDORevision> oldRevisions, boolean async)
  {
    invalidate(branch, lastUpdateTime, allChangedObjects, allDetachedObjects, oldRevisions, async, true);
  }

  /*
   * Must not by synchronized on the view!
   */
  public/* synchronized */void invalidate(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects,
      List<CDOIDAndVersion> allDetachedObjects, Map<CDOID, InternalCDORevision> oldRevisions, boolean async,
      boolean clearResourcePathCache)
  {
    if (async)
    {
      IWorkSerializer serializer = getInvalidationRunner();
      serializer.addWork(new InvalidationRunnable(branch, lastUpdateTime, allChangedObjects, allDetachedObjects,
          oldRevisions, clearResourcePathCache));
    }
    else
    {
      doInvalidate(branch, lastUpdateTime, allChangedObjects, allDetachedObjects, oldRevisions, clearResourcePathCache);
    }
  }

  protected synchronized void doInvalidate(CDOBranch branch, long lastUpdateTime,
      List<CDORevisionKey> allChangedObjects, List<CDOIDAndVersion> allDetachedObjects,
      Map<CDOID, InternalCDORevision> oldRevisions, boolean clearResourcePathCache)
  {
    if (getTimeStamp() != UNSPECIFIED_DATE && CDOStateMachine.SWITCHING_TARGET.get() != Boolean.TRUE)
    {
      // Don't invalidate historical views unless during a branch point switch.
      return;
    }

    try
    {
      // Also false for FailureCommitInfos (because of branch==null). Only setLastUpdateTime() is called below.
      if (branch == getBranch())
      {
        if (clearResourcePathCache)
        {
          clearResourcePathCacheIfNecessary(null);
        }

        List<CDORevisionDelta> deltas = new ArrayList<CDORevisionDelta>();
        Map<CDOObject, CDORevisionDelta> revisionDeltas = new HashMap<CDOObject, CDORevisionDelta>();
        Set<CDOObject> detachedObjects = new HashSet<CDOObject>();

        Map<CDOObject, Pair<CDORevision, CDORevisionDelta>> conflicts = invalidate(allChangedObjects,
            allDetachedObjects, deltas, revisionDeltas, detachedObjects);
        handleConflicts(lastUpdateTime, conflicts, deltas);

        sendInvalidationNotifications(revisionDeltas.keySet(), detachedObjects);
        fireInvalidationEvent(lastUpdateTime, Collections.unmodifiableMap(revisionDeltas),
            Collections.unmodifiableSet(detachedObjects));

        // Then send the notifications. The deltas could have been modified by the conflict resolvers.
        if (!deltas.isEmpty() || !detachedObjects.isEmpty())
        {
          sendDeltaNotifications(deltas, detachedObjects, oldRevisions);
        }

        fireAdaptersNotifiedEvent(lastUpdateTime);
      }
    }
    catch (RuntimeException ex)
    {
      if (isActive())
      {
        fireEvent(new ThrowableEvent(this, ex));
        throw ex;
      }
    }
    finally
    {
      setLastUpdateTime(lastUpdateTime);
    }
  }

  public ExecutorWorkSerializer getInvalidationRunner()
  {
    return invalidationRunner;
  }

  private ExecutorWorkSerializer createInvalidationRunner()
  {
    return new ExecutorWorkSerializer()
    {
      @Override
      protected void noWork()
      {
        if (isClosed())
        {
          dispose();
        }
      }
    };
  }

  public boolean isInvalidationRunnerActive()
  {
    return invalidationRunnerActive;
  }

  private void sendInvalidationNotifications(Set<CDOObject> dirtyObjects, Set<CDOObject> detachedObjects)
  {
    if (options().isInvalidationNotificationEnabled())
    {
      for (CDOObject dirtyObject : dirtyObjects)
      {
        if (((InternalCDOObject)dirtyObject).eNotificationRequired())
        {
          CDOInvalidationNotificationImpl notification = new CDOInvalidationNotificationImpl(dirtyObject);
          dirtyObject.eNotify(notification);
        }
      }

      for (CDOObject detachedObject : detachedObjects)
      {
        if (((InternalCDOObject)detachedObject).eNotificationRequired())
        {
          CDOInvalidationNotificationImpl notification = new CDOInvalidationNotificationImpl(detachedObject);
          detachedObject.eNotify(notification);
        }
      }
    }
  }

  /**
   * @since 2.0
   */
  private void fireInvalidationEvent(long timeStamp, Map<CDOObject, CDORevisionDelta> revisionDeltas,
      Set<CDOObject> detachedObjects)
  {
    if (!revisionDeltas.isEmpty() || !detachedObjects.isEmpty())
    {
      IListener[] listeners = getListeners();
      if (listeners != null)
      {
        fireEvent(new InvalidationEvent(timeStamp, revisionDeltas, detachedObjects), listeners);
      }
    }
  }

  /**
   * @since 2.0
   */
  public synchronized void sendDeltaNotifications(Collection<CDORevisionDelta> deltas, Set<CDOObject> detachedObjects,
      Map<CDOID, InternalCDORevision> oldRevisions)
  {
    if (deltas != null)
    {
      CDONotificationBuilder builder = new CDONotificationBuilder(this);
      Map<CDOID, InternalCDOObject> objects = getModifiableObjects();
      for (CDORevisionDelta delta : deltas)
      {
        CDOID id = delta.getID();
        InternalCDOObject object = objects.get(id);
        if (object != null && object.eNotificationRequired())
        {
          // if (!isLocked(object))
          {
            InternalCDORevision oldRevision = null;
            if (oldRevisions != null)
            {
              oldRevision = oldRevisions.get(id);
            }

            NotificationChain notification = builder.buildNotification(object, oldRevision, delta, detachedObjects);
            if (notification != null)
            {
              notification.dispatch();
            }
          }
        }
      }
    }

    if (detachedObjects != null && !detachedObjects.isEmpty())
    {
      if (options().isDetachmentNotificationEnabled())
      {
        for (CDOObject detachedObject : detachedObjects)
        {
          InternalCDOObject object = (InternalCDOObject)detachedObject;
          if (object.eNotificationRequired())
          {
            // if (!isLocked(object))
            {
              new CDODeltaNotificationImpl(object, CDONotification.DETACH_OBJECT, null, null, null).dispatch();
            }
          }
        }
      }

      getChangeSubscriptionManager().handleDetachedObjects(detachedObjects);
    }
  }

  /**
   * TODO For this method to be useable locks must be cached locally!
   */
  @SuppressWarnings("unused")
  private boolean isLocked(InternalCDOObject object)
  {
    if (object.cdoWriteLock().isLocked())
    {
      return true;
    }

    if (object.cdoReadLock().isLocked())
    {
      return true;
    }

    return false;
  }

  /**
   * @since 2.0
   */
  protected final AdapterManager getAdapterManager()
  {
    return adapterManager;
  }

  /**
   * @since 2.0
   */
  public synchronized void handleAddAdapter(InternalCDOObject eObject, Adapter adapter)
  {
    if (!FSMUtil.isNew(eObject))
    {
      subscribe(eObject, adapter);
    }

    adapterManager.attachAdapter(eObject, adapter);
  }

  /**
   * @since 2.0
   */
  public synchronized void handleRemoveAdapter(InternalCDOObject eObject, Adapter adapter)
  {
    if (!FSMUtil.isNew(eObject))
    {
      unsubscribe(eObject, adapter);
    }

    adapterManager.detachAdapter(eObject, adapter);
  }

  /**
   * @since 2.0
   */
  public synchronized void subscribe(EObject eObject, Adapter adapter)
  {
    if (changeSubscriptionManager != null)
    {
      changeSubscriptionManager.subscribe(eObject, adapter);
    }
  }

  /**
   * @since 2.0
   */
  public synchronized void unsubscribe(EObject eObject, Adapter adapter)
  {
    if (changeSubscriptionManager != null)
    {
      changeSubscriptionManager.unsubscribe(eObject, adapter);
    }
  }

  /**
   * @since 2.0
   */
  public synchronized boolean hasSubscription(CDOID id)
  {
    if (changeSubscriptionManager != null)
    {
      return changeSubscriptionManager.getSubcribeObject(id) != null;
    }

    return false;
  }

  /**
   * @since 2.0
   */
  protected final ChangeSubscriptionManager getChangeSubscriptionManager()
  {
    return changeSubscriptionManager;
  }

  /**
   * @since 2.0
   */
  protected OptionsImpl createOptions()
  {
    return new OptionsImpl();
  }

  /**
   * @since 2.0
   */
  @Override
  protected void doBeforeActivate() throws Exception
  {
    super.doBeforeActivate();
    checkState(session, "session"); //$NON-NLS-1$
    checkState(viewID > 0, "viewID"); //$NON-NLS-1$
  }

  /**
   * @since 2.0
   */
  @Override
  protected void doActivate() throws Exception
  {
    super.doActivate();

    CDOSessionProtocol sessionProtocol = session.getSessionProtocol();
    if (durableLockingID != null)
    {
      CDOBranchPoint branchPoint = sessionProtocol.openView(viewID, isReadOnly(), durableLockingID);
      basicSetBranchPoint(branchPoint);
    }
    else
    {
      sessionProtocol.openView(viewID, isReadOnly(), this);
    }

    CDOViewRegistryImpl.INSTANCE.register(this);

    Runnable runnable = SessionUtil.getTestDelayInViewActivation();
    if (runnable != null)
    {
      runnable.run();
    }

    lockOwner = CDOLockUtil.createLockOwner(this);
  }

  @Override
  protected void doAfterActivate() throws Exception
  {
    super.doAfterActivate();

    ExecutorService executorService = ConcurrencyUtil.getExecutorService(session);
    invalidationRunner.setExecutor(executorService);

    try
    {
      LifecycleUtil.activate(invalidationRunner);
    }
    catch (LifecycleException ex)
    {
      // Don't pollute the log if the worker thread is interrupted due to asynchronous view.close()
      if (!(ex.getCause() instanceof InterruptedException))
      {
        throw ex;
      }
    }
  }

  @Override
  protected void doBeforeDeactivate() throws Exception
  {
    // Detach viewset from the view
    InternalCDOViewSet viewSet = getViewSet();
    viewSet.remove(this);

    super.doBeforeDeactivate();
  }

  /**
   * @since 2.0
   */
  @Override
  protected void doDeactivate() throws Exception
  {
    CDOViewRegistryImpl.INSTANCE.deregister(this);
    LifecycleUtil.deactivate(invalidationRunner, OMLogger.Level.WARN);

    try
    {
      CDOSessionProtocol sessionProtocol = session.getSessionProtocol();
      if (LifecycleUtil.isActive(sessionProtocol))
      {
        sessionProtocol.closeView(viewID);
      }
    }
    catch (Exception ex)
    {
      OM.LOG.error(ex);
    }
    finally
    {
      synchronized (lockStates)
      {
        if (options.lockStatePrefetcher != null)
        {
          options.lockStatePrefetcher.dispose();
          options.lockStatePrefetcher = null;
        }

        if (session.isActive() && !lockStates.isEmpty())
        {
          List<CDOLockState> result = new ArrayList<CDOLockState>();
          for (CDOLockState lockState : lockStates.values())
          {
            if (((InternalCDOLockState)lockState).removeOwner(lockOwner))
            {
              result.add(lockState);
            }
          }

          if (!result.isEmpty())
          {
            CDOLockState[] deactivateLockStates = result.toArray(new CDOLockState[result.size()]);
            long timeStamp = session.getLastUpdateTime();
            notifyOtherViewsAboutLockChanges(Operation.UNLOCK, null, timeStamp, deactivateLockStates);
          }

          lockStates.clear();
          lockOwner = null;
        }
      }
    }

    try
    {
      session.viewDetached(this);
    }
    catch (Exception ex)
    {
      OM.LOG.error(ex);
    }

    changeSubscriptionManager = null;
    super.doDeactivate();
  }

  public synchronized long getLastUpdateTime()
  {
    return lastUpdateTime;
  }

  public synchronized void setLastUpdateTime(long lastUpdateTime)
  {
    if (this.lastUpdateTime < lastUpdateTime)
    {
      this.lastUpdateTime = lastUpdateTime;
    }

    notifyAll();
  }

  public boolean waitForUpdate(long updateTime, long timeoutMillis)
  {
    long end = timeoutMillis == NO_TIMEOUT ? Long.MAX_VALUE : System.currentTimeMillis() + timeoutMillis;
    synchronized (this)
    {
      for (;;)
      {
        if (lastUpdateTime >= updateTime)
        {
          return true;
        }

        long now = System.currentTimeMillis();
        if (now >= end)
        {
          return false;
        }

        try
        {
          long waitMillis = end - now;
          wait(waitMillis);
        }
        catch (InterruptedException ex)
        {
          throw WrappedException.wrap(ex);
        }
      }
    }
  }

  public boolean runAfterUpdate(final long updateTime, final Runnable runnable)
  {
    synchronized (this)
    {
      long lastUpdateTime = getLastUpdateTime();
      if (lastUpdateTime < updateTime)
      {
        addListener(new IListener()
        {
          public void notifyEvent(IEvent event)
          {
            if (event instanceof CDOViewInvalidationEvent)
            {
              CDOViewInvalidationEvent e = (CDOViewInvalidationEvent)event;
              if (e.getTimeStamp() >= updateTime)
              {
                removeListener(this);
                runnable.run();
              }
            }
          }
        });

        return false;
      }
    }

    runnable.run();
    return true;
  }

  protected static Object getLockTarget(CDOObject object)
  {
    CDOView view = object.cdoView();
    if (view == null)
    {
      return null;
    }

    CDOID id = object.cdoID();
    boolean branching = view.getSession().getRepositoryInfo().isSupportingBranches();
    if (branching)
    {
      return CDOIDUtil.createIDAndBranch(id, view.getBranch());
    }

    return id;
  }

  /**
   * @author Simon McDuff
   * @since 2.0
   */
  protected final class AdapterManager
  {
    private Set<CDOObject> objects = new HashBag<CDOObject>();

    public AdapterManager()
    {
    }

    public void committedTransaction(CDOTransaction transaction, CDOCommitContext commitContext)
    {
      if (options().getStrongReferencePolicy() != CDOAdapterPolicy.NONE)
      {
        for (CDOObject object : commitContext.getNewObjects().values())
        {
          attachObject(object);
        }

        for (CDOObject object : commitContext.getDetachedObjects().values())
        {
          detachObject(object);
        }
      }
    }

    private void attachObject(CDOObject object)
    {
      if (((InternalEObject)object).eNotificationRequired())
      {
        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);
        }
      }
    }

    private void detachObject(CDOObject object)
    {
      while (objects.remove(object))
      {
        // Do nothing
      }
    }

    private void attachAdapter(CDOObject object, Adapter adapter)
    {
      if (options().getStrongReferencePolicy().isValid(object, adapter))
      {
        objects.add(object);
      }
    }

    private void detachAdapter(CDOObject object, Adapter adapter)
    {
      if (options().getStrongReferencePolicy().isValid(object, adapter))
      {
        objects.remove(object);
      }
    }

    private void reset()
    {
      // Keep the objects in memory
      Set<CDOObject> oldObjects = objects;
      objects = new HashBag<CDOObject>();
      if (options().getStrongReferencePolicy() != CDOAdapterPolicy.NONE)
      {
        for (InternalCDOObject object : getObjectsList())
        {
          attachObject(object);
        }
      }

      oldObjects.clear();
    }
  }

  /**
   * @author Simon McDuff
   * @since 2.0
   */
  protected final class ChangeSubscriptionManager
  {
    private Map<CDOID, SubscribeEntry> subscriptions = CDOIDUtil.createMap();

    public ChangeSubscriptionManager()
    {
    }

    public void committedTransaction(CDOTransaction transaction, CDOCommitContext commitContext)
    {
      handleNewObjects(commitContext.getNewObjects().values());
      handleDetachedObjects(commitContext.getDetachedObjects().values());
    }

    private void subscribe(EObject eObject, Adapter adapter)
    {
      subscribe(eObject, adapter, 1);
    }

    private void unsubscribe(EObject eObject, Adapter adapter)
    {
      subscribe(eObject, adapter, -1);
    }

    /**
     * Register to the server all objects from the active list
     */
    private void notifyChangeSubcriptionPolicy()
    {
      boolean policiesPresent = options().hasChangeSubscriptionPolicies();
      subscriptions.clear();
      List<CDOID> ids = new ArrayList<CDOID>();
      if (policiesPresent)
      {
        for (InternalCDOObject object : getObjectsList())
        {
          int count = getNumberOfValidAdapters(object);
          if (count > 0)
          {
            ids.add(object.cdoID());
            addEntry(object.cdoID(), object, count);
          }
        }
      }

      request(ids, true, true);
    }

    private void handleDetachedObjects(Collection<CDOObject> detachedObjects)
    {
      for (CDOObject detachedObject : detachedObjects)
      {
        CDOID id = detachedObject.cdoID();
        SubscribeEntry entry = subscriptions.get(id);
        if (entry != null)
        {
          detachObject(id);
        }
      }
    }

    private void handleNewObjects(Collection<? extends CDOObject> newObjects)
    {
      for (CDOObject object : newObjects)
      {
        InternalCDOObject cdoDetachedObject = (InternalCDOObject)object;
        if (cdoDetachedObject != null)
        {
          int count = getNumberOfValidAdapters(cdoDetachedObject);
          if (count > 0)
          {
            subscribe(cdoDetachedObject.cdoID(), cdoDetachedObject, count);
          }
        }
      }
    }

    private InternalCDOObject getSubcribeObject(CDOID id)
    {
      SubscribeEntry entry = subscriptions.get(id);
      if (entry != null)
      {
        return entry.getObject();
      }

      return null;
    }

    private void request(List<CDOID> ids, boolean clear, boolean subscribeMode)
    {
      CDOSessionProtocol sessionProtocol = session.getSessionProtocol();
      sessionProtocol.changeSubscription(getViewID(), ids, subscribeMode, clear);
    }

    private int getNumberOfValidAdapters(InternalCDOObject object)
    {
      int count = 0;
      if (!FSMUtil.isTransient(object) && !FSMUtil.isNew(object))
      {
        if (object.eNotificationRequired())
        {
          EObject instance = CDOUtil.getEObject(object);
          for (Adapter adapter : instance.eAdapters())
          {
            if (shouldSubscribe(object, adapter))
            {
              ++count;
            }
          }
        }
      }

      return count;
    }

    private void subscribe(EObject eObject, Adapter adapter, int adjust)
    {
      if (shouldSubscribe(eObject, adapter))
      {
        CDOView view = CDOViewImpl.this;
        InternalCDOObject internalCDOObject = FSMUtil.adapt(eObject, view);
        if (internalCDOObject.cdoView() != view)
        {
          throw new CDOException(MessageFormat.format(Messages.getString("CDOViewImpl.27"), internalCDOObject)); //$NON-NLS-1$
        }

        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();

      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(object, count));
    }
  }

  /**
   * @author Eike Stepper
   */
  private static final class SubscribeEntry
  {
    private InternalCDOObject object;

    private int count;

    public SubscribeEntry(InternalCDOObject object, int count)
    {
      this.object = object;
      this.count = count;
    }

    public InternalCDOObject getObject()
    {
      return object;
    }

    public int getCount()
    {
      return count;
    }

    public void setCount(int count)
    {
      this.count = count;
    }
  }

  /**
   * A {@link IListener} to prefetch {@link CDOLockState lockstates} when {@link CDORevision revisions} are loaded, according to {@link Options#setLockStatePrefetchEnabled(boolean)} option.
   *
   * @author Esteban Dugueperoux
   */
  private final class LockStatePrefetcher implements IListener
  {
    public LockStatePrefetcher()
    {
      session.getRevisionManager().addListener(this);
    }

    public void notifyEvent(IEvent event)
    {
      if (event instanceof CDORevisionsLoadedEvent)
      {
        CDORevisionsLoadedEvent revisionsLoadedEvent = (CDORevisionsLoadedEvent)event;
        updateCDOViewObjectsCache(revisionsLoadedEvent);
      }
    }

    private void updateCDOViewObjectsCache(CDORevisionsLoadedEvent revisionsLoadedEvent)
    {
      Set<CDOID> ids = new HashSet<CDOID>();
      CDOLockStateLoadingPolicy lockStateLoadingPolicy = options().getLockStateLoadingPolicy();
      for (CDORevision revision : revisionsLoadedEvent.getPrimaryLoadedRevisions())
      {
        // Bug 466721 : Check null if it is a about a DetachedRevision
        if (revision != null)
        {
          CDOID id = revision.getID();
          if (id != null && lockStateLoadingPolicy.loadLockState(id))
          {
            // - Don't ask to create an object for CDOResource as the caller of ResourceSet.getResource()
            // can have created it but not yet registered in CDOView.
            // - Don't ask others CDOResourceNode either as it will create some load revisions request
            // in addition to mode without lock state prefetch
            boolean isResourceNode = revision.isResourceNode();
            InternalCDOObject object = getObject(id, !isResourceNode);
            if (object != null)
            {
              ids.add(id);
            }
          }
        }
      }

      if (!ids.isEmpty())
      {
        // direct call the session protocol
        CDOSessionProtocol sessionProtocol = session.getSessionProtocol();
        CDOLockState[] lockStates = sessionProtocol.getLockStates(viewID, ids, revisionsLoadedEvent.getPrefetchDepth());

        updateLockStatesForAllViews(lockStates);

        // add missing lock states
        List<CDOLockState> missingLockStates = new ArrayList<CDOLockState>();
        for (CDOID id : ids)
        {
          InternalCDOObject obj = getObject(id, false);

          if (obj != null && CDOViewImpl.this.lockStates.get(obj) == null)
          {
            missingLockStates.add(CDOLockUtil.createLockState(getLockTarget(obj)));
          }
        }

        for (CDORevision revision : revisionsLoadedEvent.getAdditionalLoadedRevisions())
        {
          CDOID id = revision.getID();
          if (id != null && lockStateLoadingPolicy.loadLockState(id))
          {
            boolean isResourceNode = revision.isResourceNode();
            InternalCDOObject obj = getObject(id, !isResourceNode);
            if (obj != null && CDOViewImpl.this.lockStates.get(obj) == null)
            {
              missingLockStates.add(CDOLockUtil.createLockState(getLockTarget(obj)));
            }
          }
        }

        updateLockStatesForAllViews(missingLockStates.toArray(new CDOLockState[missingLockStates.size()]));
      }
    }

    private void updateLockStatesForAllViews(CDOLockState[] lockStates)
    {
      updateLockStates(lockStates);

      for (CDOCommonView view : getSession().getViews())
      {
        if (view != CDOViewImpl.this && view.getBranch() == getBranch())
        {
          updateLockStates(lockStates);
        }
      }
    }

    public void dispose()
    {
      session.getRevisionManager().removeListener(this);
    }
  }

  /**
   * @author Eike Stepper
   */
  private final class InvalidationRunnable implements Runnable
  {
    private final CDOBranch branch;

    private final long lastUpdateTime;

    private final List<CDORevisionKey> allChangedObjects;

    private final List<CDOIDAndVersion> allDetachedObjects;

    private final Map<CDOID, InternalCDORevision> oldRevisions;

    private boolean clearResourcePathCache;

    private InvalidationRunnable(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects,
        List<CDOIDAndVersion> allDetachedObjects, Map<CDOID, InternalCDORevision> oldRevisions,
        boolean clearResourcePathCache)
    {
      this.branch = branch;
      this.lastUpdateTime = lastUpdateTime;
      this.allChangedObjects = allChangedObjects;
      this.allDetachedObjects = allDetachedObjects;
      this.oldRevisions = oldRevisions;
      this.clearResourcePathCache = clearResourcePathCache;
    }

    public void run()
    {
      try
      {
        invalidationRunnerActive = true;
        doInvalidate(branch, lastUpdateTime, allChangedObjects, allDetachedObjects, oldRevisions,
            clearResourcePathCache);
      }
      catch (Exception ex)
      {
        if (isActive())
        {
          OM.LOG.error(ex);
        }
      }
      finally
      {
        invalidationRunnerActive = false;
      }
    }
  }

  /**
   * @author Simon McDuff
   */
  private final class InvalidationEvent extends Event implements CDOViewInvalidationEvent
  {
    private static final long serialVersionUID = 1L;

    private long timeStamp;

    private Map<CDOObject, CDORevisionDelta> revisionDeltas;

    private Set<CDOObject> detachedObjects;

    public InvalidationEvent(long timeStamp, Map<CDOObject, CDORevisionDelta> revisionDeltas,
        Set<CDOObject> detachedObjects)
    {
      this.timeStamp = timeStamp;
      this.revisionDeltas = revisionDeltas;
      this.detachedObjects = detachedObjects;
    }

    public long getTimeStamp()
    {
      return timeStamp;
    }

    public Set<CDOObject> getDirtyObjects()
    {
      return revisionDeltas.keySet();
    }

    public Map<CDOObject, CDORevisionDelta> getRevisionDeltas()
    {
      return revisionDeltas;
    }

    public Set<CDOObject> getDetachedObjects()
    {
      return detachedObjects;
    }

    @Override
    public String toString()
    {
      return "CDOViewInvalidationEvent: " + revisionDeltas; //$NON-NLS-1$
    }
  }

  /**
   * @author Caspar De Groot
   * @since 4.1
   */
  private final class LocksChangedEvent extends DefaultLocksChangedEvent implements CDOViewLocksChangedEvent
  {
    private static final long serialVersionUID = 1L;

    public LocksChangedEvent(InternalCDOView sender, CDOLockChangeInfo lockChangeInfo)
    {
      super(CDOViewImpl.this, sender, lockChangeInfo);
    }

    @Override
    public InternalCDOView getSource()
    {
      return (InternalCDOView)super.getSource();
    }

    public EObject[] getAffectedObjects()
    {
      List<EObject> objects = new ArrayList<EObject>();
      CDOView view = getSource();

      CDOLockState[] lockStates = getLockStates();
      for (int i = 0; i < lockStates.length; i++)
      {
        CDOLockState lockState = lockStates[i];
        Object lockedObject = lockState.getLockedObject();

        CDOID id = null;
        if (lockedObject instanceof CDOIDAndBranch)
        {
          CDOIDAndBranch idAndBranch = (CDOIDAndBranch)lockedObject;
          if (idAndBranch.getBranch().getID() == view.getBranch().getID())
          {
            id = idAndBranch.getID();
          }
        }
        else if (lockedObject instanceof CDOID)
        {
          id = (CDOID)lockedObject;
        }

        if (id != null)
        {
          CDOObject object = view.getObject(id, false);
          if (object != null)
          {
            objects.add(CDOUtil.getEObject(object));
          }
        }
      }

      return objects.toArray(new EObject[objects.size()]);
    }
  }

  /**
   * @author Eike Stepper
   * @since 2.0
   */
  public class OptionsImpl extends Notifier implements Options
  {
    private boolean loadNotificationEnabled;

    private boolean detachmentNotificationEnabled;

    private boolean invalidationNotificationEnabled;

    private CDOInvalidationPolicy invalidationPolicy = CDOInvalidationPolicy.DEFAULT;

    private boolean lockNotificationsEnabled;

    private boolean lockStatePrefetchEnabled;

    private CDOLockStateLoadingPolicy lockStateLoadingPolicy = new CDODefaultLockStateLoadingPolicy();

    private LockStatePrefetcher lockStatePrefetcher;

    private CDORevisionPrefetchingPolicy revisionPrefetchingPolicy = CDOUtil
        .createRevisionPrefetchingPolicy(NO_REVISION_PREFETCHING);

    private CDOFeatureAnalyzer featureAnalyzer = CDOFeatureAnalyzer.NOOP;

    private CDOStaleReferencePolicy staleReferencePolicy = CDOStaleReferencePolicy.DEFAULT;

    private HashBag<CDOAdapterPolicy> changeSubscriptionPolicies = new HashBag<CDOAdapterPolicy>();

    private CDOAdapterPolicy strongReferencePolicy = CDOAdapterPolicy.ALL;

    public OptionsImpl()
    {
    }

    public CDOViewImpl getContainer()
    {
      return CDOViewImpl.this;
    }

    public boolean isLoadNotificationEnabled()
    {
      synchronized (CDOViewImpl.this)
      {
        return loadNotificationEnabled;
      }
    }

    public void setLoadNotificationEnabled(boolean enabled)
    {
      checkActive();

      IEvent event = null;
      synchronized (CDOViewImpl.this)
      {
        if (loadNotificationEnabled != enabled)
        {
          loadNotificationEnabled = enabled;
          event = new LoadNotificationEventImpl();
        }
      }

      fireEvent(event);
    }

    public boolean isDetachmentNotificationEnabled()
    {
      synchronized (CDOViewImpl.this)
      {
        return detachmentNotificationEnabled;
      }
    }

    public void setDetachmentNotificationEnabled(boolean enabled)
    {
      checkActive();

      IEvent event = null;
      synchronized (CDOViewImpl.this)
      {
        if (detachmentNotificationEnabled != enabled)
        {
          detachmentNotificationEnabled = enabled;
          event = new DetachmentNotificationEventImpl();
        }
      }

      fireEvent(event);
    }

    public boolean isInvalidationNotificationEnabled()
    {
      synchronized (CDOViewImpl.this)
      {
        return invalidationNotificationEnabled;
      }
    }

    public void setInvalidationNotificationEnabled(boolean enabled)
    {
      checkActive();

      IEvent event = null;
      synchronized (CDOViewImpl.this)
      {
        if (invalidationNotificationEnabled != enabled)
        {
          invalidationNotificationEnabled = enabled;
          event = new InvalidationNotificationEventImpl();
        }
      }

      fireEvent(event);
    }

    public CDOInvalidationPolicy getInvalidationPolicy()
    {
      synchronized (CDOViewImpl.this)
      {
        return invalidationPolicy;
      }
    }

    public void setInvalidationPolicy(CDOInvalidationPolicy policy)
    {
      checkActive();

      IEvent event = null;
      synchronized (CDOViewImpl.this)
      {
        if (invalidationPolicy != policy)
        {
          invalidationPolicy = policy;
          event = new InvalidationPolicyEventImpl();
        }
      }

      fireEvent(event);
    }

    public boolean isLockNotificationEnabled()
    {
      return lockNotificationsEnabled;
    }

    public void setLockNotificationEnabled(boolean enabled)
    {
      checkActive();

      IEvent event = null;
      synchronized (CDOViewImpl.this)
      {
        if (enabled != lockNotificationsEnabled)
        {
          CDOSessionProtocol protocol = session.getSessionProtocol();
          protocol.enableLockNotifications(viewID, enabled);
          lockNotificationsEnabled = enabled;
          event = new LockNotificationEventImpl(enabled);
        }
      }

      fireEvent(event);
    }

    public boolean isLockStatePrefetchEnabled()
    {
      return lockStatePrefetchEnabled;
    }

    public void setLockStatePrefetchEnabled(boolean enabled)
    {
      checkActive();

      IEvent event = null;
      synchronized (CDOViewImpl.this)
      {
        if (enabled != lockStatePrefetchEnabled)
        {
          lockStatePrefetchEnabled = enabled;
          if (enabled)
          {
            lockStatePrefetcher = new LockStatePrefetcher();
          }
          else
          {
            lockStatePrefetcher.dispose();
            lockStatePrefetcher = null;
          }

          event = new LockStatePrefetchEventImpl();
        }
      }

      fireEvent(event);
    }

    public CDOLockStateLoadingPolicy getLockStateLoadingPolicy()
    {
      synchronized (CDOViewImpl.this)
      {
        return lockStateLoadingPolicy;
      }
    }

    public void setLockStateLoadingPolicy(CDOLockStateLoadingPolicy lockStateLoadingPolicy)
    {
      checkActive();

      synchronized (CDOViewImpl.this)
      {
        this.lockStateLoadingPolicy = lockStateLoadingPolicy;
      }
    }

    public boolean hasChangeSubscriptionPolicies()
    {
      synchronized (CDOViewImpl.this)
      {
        return !changeSubscriptionPolicies.isEmpty();
      }
    }

    public CDOAdapterPolicy[] getChangeSubscriptionPolicies()
    {
      synchronized (CDOViewImpl.this)
      {
        return changeSubscriptionPolicies.toArray(new CDOAdapterPolicy[changeSubscriptionPolicies.size()]);
      }
    }

    public void addChangeSubscriptionPolicy(CDOAdapterPolicy policy)
    {
      checkActive();

      IEvent event = null;
      synchronized (CDOViewImpl.this)
      {
        if (changeSubscriptionPolicies.add(policy))
        {
          changeSubscriptionManager.notifyChangeSubcriptionPolicy();
          event = new ChangeSubscriptionPoliciesEventImpl();
        }
      }

      fireEvent(event);
    }

    public void removeChangeSubscriptionPolicy(CDOAdapterPolicy policy)
    {
      checkActive();

      IEvent event = null;
      synchronized (CDOViewImpl.this)
      {
        if (changeSubscriptionPolicies.remove(policy) && !changeSubscriptionPolicies.contains(policy))
        {
          changeSubscriptionManager.notifyChangeSubcriptionPolicy();
          event = new ChangeSubscriptionPoliciesEventImpl();
        }
      }

      fireEvent(event);
    }

    public CDOAdapterPolicy getStrongReferencePolicy()
    {
      synchronized (CDOViewImpl.this)
      {
        return strongReferencePolicy;
      }
    }

    public void setStrongReferencePolicy(CDOAdapterPolicy adapterPolicy)
    {
      checkActive();

      if (adapterPolicy == null)
      {
        adapterPolicy = CDOAdapterPolicy.ALL;
      }

      IEvent event = null;
      synchronized (CDOViewImpl.this)
      {
        if (strongReferencePolicy != adapterPolicy)
        {
          strongReferencePolicy = adapterPolicy;
          adapterManager.reset();
          event = new ReferencePolicyEventImpl();
        }
      }

      fireEvent(event);
    }

    public CDORevisionPrefetchingPolicy getRevisionPrefetchingPolicy()
    {
      synchronized (CDOViewImpl.this)
      {
        return revisionPrefetchingPolicy;
      }
    }

    public void setRevisionPrefetchingPolicy(CDORevisionPrefetchingPolicy prefetchingPolicy)
    {
      checkActive();

      if (prefetchingPolicy == null)
      {
        prefetchingPolicy = CDORevisionPrefetchingPolicy.NO_PREFETCHING;
      }

      IEvent event = null;
      synchronized (CDOViewImpl.this)
      {
        if (revisionPrefetchingPolicy != prefetchingPolicy)
        {
          revisionPrefetchingPolicy = prefetchingPolicy;
          event = new RevisionPrefetchingPolicyEventImpl();
        }
      }

      fireEvent(event);
    }

    public CDOFeatureAnalyzer getFeatureAnalyzer()
    {
      synchronized (CDOViewImpl.this)
      {
        return featureAnalyzer;
      }
    }

    public void setFeatureAnalyzer(CDOFeatureAnalyzer featureAnalyzer)
    {
      checkActive();

      if (featureAnalyzer == null)
      {
        featureAnalyzer = CDOFeatureAnalyzer.NOOP;
      }

      IEvent event = null;
      synchronized (CDOViewImpl.this)
      {
        if (this.featureAnalyzer != featureAnalyzer)
        {
          this.featureAnalyzer = featureAnalyzer;
          event = new FeatureAnalyzerEventImpl();
        }
      }

      fireEvent(event);
    }

    @Deprecated
    public CDOStaleReferencePolicy getStaleReferenceBehaviour()
    {
      return getStaleReferencePolicy();
    }

    @Deprecated
    public void setStaleReferenceBehaviour(CDOStaleReferencePolicy policy)
    {
      setStaleReferencePolicy(policy);
    }

    public CDOStaleReferencePolicy getStaleReferencePolicy()
    {
      synchronized (CDOViewImpl.this)
      {
        return staleReferencePolicy;
      }
    }

    public void setStaleReferencePolicy(CDOStaleReferencePolicy policy)
    {
      checkActive();

      if (policy == null)
      {
        policy = CDOStaleReferencePolicy.DEFAULT;
      }

      IEvent event = null;
      synchronized (CDOViewImpl.this)
      {
        if (staleReferencePolicy != policy)
        {
          staleReferencePolicy = policy;
          event = new StaleReferencePolicyEventImpl();
        }
      }

      fireEvent(event);
    }

    public ReferenceType getCacheReferenceType()
    {
      synchronized (CDOViewImpl.this)
      {
        Map<CDOID, InternalCDOObject> objects = getModifiableObjects();
        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(Messages.getString("CDOViewImpl.29")); //$NON-NLS-1$
      }
    }

    public boolean setCacheReferenceType(ReferenceType referenceType)
    {
      checkActive();

      if (referenceType == null)
      {
        referenceType = ReferenceType.SOFT;
      }

      synchronized (CDOViewImpl.this)
      {
        if (!initObjectsMap(referenceType))
        {
          return false;
        }
      }

      IListener[] listeners = getListeners();
      if (listeners != null)
      {
        fireEvent(new CacheReferenceTypeEventImpl(), listeners);
      }

      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 LoadNotificationEventImpl extends OptionsEvent implements LoadNotificationEvent
    {
      private static final long serialVersionUID = 1L;

      public LoadNotificationEventImpl()
      {
        super(OptionsImpl.this);
      }
    }

    /**
     * @author Eike Stepper
     */
    private final class DetachmentNotificationEventImpl extends OptionsEvent implements DetachmentNotificationEvent
    {
      private static final long serialVersionUID = 1L;

      public DetachmentNotificationEventImpl()
      {
        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 InvalidationPolicyEventImpl extends OptionsEvent implements InvalidationPolicyEvent
    {
      private static final long serialVersionUID = 1L;

      public InvalidationPolicyEventImpl()
      {
        super(OptionsImpl.this);
      }
    }

    /**
     * @author Caspar De Groot
     */
    private final class LockNotificationEventImpl extends OptionsEvent implements LockNotificationEvent
    {
      private static final long serialVersionUID = 1L;

      private boolean enabled;

      public LockNotificationEventImpl(boolean enabled)
      {
        super(OptionsImpl.this);
        this.enabled = enabled;
      }

      public boolean getEnabled()
      {
        return enabled;
      }
    }

    /**
     * An {@link IOptionsEvent options event} fired from common view {@link CDOCommonView#options() options} when the
     * {@link OptionsImpl#setLockStatePrefetchEnabled(boolean) lock state prefetch enabled} option has changed.
     *
     * @author Esteban Dugueperoux
     * @noextend This interface is not intended to be extended by clients.
     * @noimplement This interface is not intended to be implemented by clients.
     * @since 4.4
     */
    private final class LockStatePrefetchEventImpl extends OptionsEvent
    {
      private static final long serialVersionUID = 1L;

      public LockStatePrefetchEventImpl()
      {
        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 FeatureAnalyzerEventImpl extends OptionsEvent implements FeatureAnalyzerEvent
    {
      private static final long serialVersionUID = 1L;

      public FeatureAnalyzerEventImpl()
      {
        super(OptionsImpl.this);
      }
    }

    /**
     * @author Eike Stepper
     */
    @SuppressWarnings("deprecation")
    private final class ReferencePolicyEventImpl extends OptionsEvent implements ReferencePolicyEvent
    {
      private static final long serialVersionUID = 1L;

      public ReferencePolicyEventImpl()
      {
        super(OptionsImpl.this);
      }
    }

    /**
     * @author Simon McDuff
     */
    private final class StaleReferencePolicyEventImpl extends OptionsEvent implements StaleReferencePolicyEvent
    {
      private static final long serialVersionUID = 1L;

      public StaleReferencePolicyEventImpl()
      {
        super(OptionsImpl.this);
      }
    }
  }
}
