blob: 8e72f32596c63caf05f06a26aa23a98fd2fdfd1e [file] [log] [blame]
/**
* Copyright (c) 2004 - 2011 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 - bug 233490
*/
package org.eclipse.emf.cdo.internal.server;
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.revision.CDORevision;
import org.eclipse.emf.cdo.common.revision.CDORevisionManager;
import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
import org.eclipse.emf.cdo.spi.server.InternalRepository;
import org.eclipse.emf.cdo.spi.server.InternalSession;
import org.eclipse.emf.cdo.spi.server.InternalView;
import org.eclipse.net4j.util.ObjectUtil;
import org.eclipse.net4j.util.lifecycle.Lifecycle;
import org.eclipse.net4j.util.options.IOptionsContainer;
import java.text.MessageFormat;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
* @author Eike Stepper
*/
public class View extends Lifecycle implements InternalView, CDOCommonView.Options
{
private InternalSession session;
private final int viewID;
private final int sessionID; // Needed here so we can compute the hashCode even after session becomes null due to
// deactivation!
private CDOBranchPoint branchPoint;
private String durableLockingID;
private InternalRepository repository;
private Set<CDOID> changeSubscriptionIDs = new HashSet<CDOID>();
private boolean lockNotificationsEnabled;
/**
* @since 2.0
*/
public View(InternalSession session, int viewID, CDOBranchPoint branchPoint)
{
this.session = session;
this.viewID = viewID;
sessionID = session.getSessionID();
repository = session.getManager().getRepository();
setBranchPoint(branchPoint);
}
public InternalSession getSession()
{
return session;
}
public int getViewID()
{
return viewID;
}
public CDOBranch getBranch()
{
return branchPoint.getBranch();
}
public long getTimeStamp()
{
return branchPoint.getTimeStamp();
}
public boolean isReadOnly()
{
return true;
}
public String getDurableLockingID()
{
return durableLockingID;
}
/**
* @since 2.0
*/
public InternalRepository getRepository()
{
checkOpen();
return repository;
}
public InternalCDORevision getRevision(CDOID id)
{
CDORevisionManager revisionManager = repository.getRevisionManager();
return (InternalCDORevision)revisionManager.getRevision(id, this, CDORevision.UNCHUNKED, CDORevision.DEPTH_NONE,
true);
}
public void changeTarget(CDOBranchPoint branchPoint, List<CDOID> invalidObjects,
List<CDORevisionDelta> allChangedObjects, List<CDOID> allDetachedObjects)
{
List<CDORevision> oldRevisions = getRevisions(invalidObjects);
setBranchPoint(branchPoint);
List<CDORevision> newRevisions = getRevisions(invalidObjects);
Iterator<CDORevision> it = newRevisions.iterator();
for (CDORevision oldRevision : oldRevisions)
{
CDORevision newRevision = it.next();
if (newRevision == null)
{
allDetachedObjects.add(oldRevision.getID());
}
else if (newRevision != oldRevision)
{
CDORevisionDelta delta = newRevision.compare(oldRevision);
allChangedObjects.add(delta);
}
}
}
private List<CDORevision> getRevisions(List<CDOID> ids)
{
return repository.getRevisionManager().getRevisions(ids, branchPoint, CDORevision.UNCHUNKED,
CDORevision.DEPTH_NONE, true);
}
public void setBranchPoint(CDOBranchPoint branchPoint)
{
checkOpen();
long timeStamp = branchPoint.getTimeStamp();
branchPoint = branchPoint.getBranch().getPoint(timeStamp);
validateTimeStamp(timeStamp);
this.branchPoint = branchPoint;
}
protected void validateTimeStamp(long timeStamp) throws IllegalArgumentException
{
if (timeStamp != UNSPECIFIED_DATE)
{
repository.validateTimeStamp(timeStamp);
}
}
public void setDurableLockingID(String durableLockingID)
{
this.durableLockingID = durableLockingID;
}
/**
* @since 2.0
*/
public synchronized void subscribe(CDOID id)
{
checkOpen();
changeSubscriptionIDs.add(id);
}
/**
* @since 2.0
*/
public synchronized void unsubscribe(CDOID id)
{
checkOpen();
changeSubscriptionIDs.remove(id);
}
/**
* @since 2.0
*/
public synchronized boolean hasSubscription(CDOID id)
{
checkOpen();
return changeSubscriptionIDs.contains(id);
}
/**
* @since 2.0
*/
public synchronized void clearChangeSubscription()
{
checkOpen();
changeSubscriptionIDs.clear();
}
@Override
public int hashCode()
{
return ObjectUtil.hashCode(sessionID, viewID);
}
@Override
public String toString()
{
int sessionID = session == null ? 0 : session.getSessionID();
return MessageFormat.format("{0}[{1}:{2}]", getClassName(), sessionID, viewID); //$NON-NLS-1$
}
protected String getClassName()
{
return "View"; //$NON-NLS-1$
}
/**
* @since 2.0
*/
public void close()
{
deactivate();
}
@Override
protected void doDeactivate() throws Exception
{
if (!isClosed())
{
session.viewClosed(this);
}
super.doDeactivate();
}
/**
* @since 2.0
*/
public void doClose()
{
clearChangeSubscription();
changeSubscriptionIDs = null;
session = null;
repository = null;
}
/**
* @since 2.0
*/
public boolean isClosed()
{
return repository == null;
}
private void checkOpen()
{
if (isClosed())
{
throw new IllegalStateException("View closed"); //$NON-NLS-1$
}
}
public IOptionsContainer getContainer()
{
return this;
}
public Options options()
{
return this;
}
public boolean isLockNotificationEnabled()
{
return lockNotificationsEnabled;
}
public void setLockNotificationEnabled(boolean enable)
{
lockNotificationsEnabled = enable;
}
}