Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: 769e52500adf23a7d4a2b85c6fcafee517a7ddb9 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12











                                                                            
                                    
                                   


                                                 
                                                 


                                                          
                                                                
                                                                    

                                                                      
                                                   
                                                                 



                                                             
                                                              




                                                  
                                       
                                    
                                             

                                                  
                                            
                                              
                                                                     
                                                                 
                                                   


                               


                         



                       

                                                                                                                  
 
                                                                                                  
 

                 


                                  


                         

                                         
                                                                
 

                             
                                             
 
                                                                      
   
                 







                                                 
                                                                    
   
                 
                           


                               




                    
                                     
   










                                            






                            
                               
   
                                                 

   

                              
                               


                             
   
                               

   

                                                

                                                                   



                                             

                                                                































                                                                                                  
                                                  



                                                         


                      



                               





                                       
                                                     
   
                                                       

   
                                                         
   





                                                                                              


                               
                                                 









                                                                       
                                                   
   
                                
     
                              

     


                                       
     
                                          





                                       
                                                  
   













                                                                        
 
                           
     
                                                   

     


















                                                             

   
                                              
   
                                                         
                                       
     






                                                                                   
     
 
                                                                                        

   
                                                         
   




                                      


                                                                                                      

                                                       
       
                  

       
                                                                 

                                

                                                     
     
                                                                    
                                   












                                                                
                                                     








                                     
                                                    










                                                                  






































































                                                                            





















                                                                                    
                                                       




                                                               

   




                                                               


                      



                                                            
                                                
     









                           
                               

   


                          

                                                                                                                
















                                                     
                                                           







                                                                
                               











                                                                
                                  




                           
                                                             







                                 




                                

























                                                     
                                                    












                                                                      
                                                                  
                                                  




         

                                                     








                                                                                      
                                                                           







                                                       

   



                                                     
                                                       












                                                                      
                                                                  
                                                     




         


                                                                    
                                                                                      

   



                              


































                                                                            



                         

















                                                                                                          









                                                                                   



                                       















                                                                                                         
 















                                                                                   






                                                        


                                   




                                            
 
/***************************************************************************
 * Copyright (c) 2004-2007 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
 **************************************************************************/
package org.eclipse.emf.internal.cdo;

import org.eclipse.emf.cdo.CDOState;
import org.eclipse.emf.cdo.CDOView;
import org.eclipse.emf.cdo.CDOViewCommittedEvent;
import org.eclipse.emf.cdo.CDOViewDirtyEvent;
import org.eclipse.emf.cdo.CDOViewEvent;
import org.eclipse.emf.cdo.CDOViewResourcesEvent;
import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.eresource.EresourceFactory;
import org.eclipse.emf.cdo.eresource.impl.CDOResourceImpl;
import org.eclipse.emf.cdo.internal.protocol.model.CDOClassImpl;
import org.eclipse.emf.cdo.internal.protocol.revision.CDOIDProvider;
import org.eclipse.emf.cdo.internal.protocol.revision.CDORevisionImpl;
import org.eclipse.emf.cdo.protocol.CDOID;
import org.eclipse.emf.cdo.protocol.model.CDOClass;
import org.eclipse.emf.cdo.protocol.revision.CDORevisionResolver;
import org.eclipse.emf.cdo.protocol.util.ImplementationError;
import org.eclipse.emf.cdo.protocol.util.TransportException;
import org.eclipse.emf.cdo.util.CDOUtil;

import org.eclipse.net4j.internal.util.om.trace.ContextTracer;

import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.internal.cdo.bundle.OM;
import org.eclipse.emf.internal.cdo.protocol.CommitTransactionResult;
import org.eclipse.emf.internal.cdo.protocol.ResourcePathRequest;
import org.eclipse.emf.internal.cdo.util.ModelUtil;

import java.text.MessageFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author Eike Stepper
 */
public class CDOViewImpl extends org.eclipse.net4j.internal.util.event.Notifier implements CDOView, CDOIDProvider,
    Adapter.Internal
{
  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_VIEW, CDOViewImpl.class);

  private int id;

  private CDOSessionImpl session;

  private ResourceSet resourceSet;

  private long timeStamp;

  private CDOTransactionImpl transaction;

  private Map<CDOID, InternalCDOObject> objects = new HashMap();

  private CDOID lastLookupID;

  private InternalCDOObject lastLookupObject;

  public CDOViewImpl(int id, CDOSessionImpl session, boolean readOnly)
  {
    this.id = id;
    this.session = session;
    timeStamp = UNSPECIFIED_DATE;
    if (!readOnly)
    {
      transaction = new CDOTransactionImpl(this);
    }
  }

  public CDOViewImpl(int id, CDOSessionImpl session, long timeStamp)
  {
    this.id = id;
    this.session = session;
    this.timeStamp = timeStamp;
  }

  public int getID()
  {
    return id;
  }

  public ResourceSet getResourceSet()
  {
    return resourceSet;
  }

  public CDOSessionImpl getSession()
  {
    return session;
  }

  public CDOTransactionImpl getTransaction()
  {
    return transaction;
  }

  public long getTimeStamp()
  {
    return timeStamp;
  }

  public boolean isHistorical()
  {
    return timeStamp != CDOView.UNSPECIFIED_DATE;
  }

  public boolean isReadWrite()
  {
    return transaction != null;
  }

  public boolean isReadOnly()
  {
    return transaction == null;
  }

  public CDOResource createResource(String path)
  {
    URI createURI = CDOUtil.createURI(path);
    return (CDOResource)getResourceSet().createResource(createURI);
  }

  public CDOResource getResource(String path)
  {
    URI uri = CDOUtil.createURI(path);
    return (CDOResource)getResourceSet().getResource(uri, true);
  }

  public CDOResourceImpl getResource(CDOID resourceID)
  {
    if (resourceID == null || resourceID == CDOID.NULL)
    {
      throw new ImplementationError("resourceID == null || resourceID == CDOID.NULL");
    }

    ResourceSet resourceSet = getResourceSet();
    EList<Resource> resources = resourceSet.getResources();
    for (Resource resource : resources)
    {
      if (resource instanceof CDOResourceImpl)
      {
        CDOResourceImpl cdoResource = (CDOResourceImpl)resource;
        if (resourceID.equals(cdoResource.cdoID()))
        {
          return cdoResource;
        }
      }
    }

    try
    {
      ResourcePathRequest signal = new ResourcePathRequest(getSession().getChannel(), resourceID);
      String path = signal.send();

      CDOResourceImpl resource = (CDOResourceImpl)EresourceFactory.eINSTANCE.createCDOResource();
      resource.setResourceSet(resourceSet);
      resource.setPath(path);

      InternalCDOObject resourceObject = resource;
      resourceObject.cdoInternalSetID(resourceID);
      resourceObject.cdoInternalSetView(this);
      resourceObject.cdoInternalSetResource(resource);
      resourceObject.cdoInternalSetState(CDOState.PROXY);

      return resource;
    }
    catch (RuntimeException ex)
    {
      throw ex;
    }
    catch (Exception ex)
    {
      throw new TransportException(ex);
    }
  }

  public InternalCDOObject newInstance(EClass eClass)
  {
    return (InternalCDOObject)EcoreUtil.create(eClass);
  }

  public InternalCDOObject newInstance(CDOClass cdoClass)
  {
    EClass eClass = ModelUtil.getEClass((CDOClassImpl)cdoClass, session.getPackageRegistry());
    if (eClass == null)
    {
      throw new IllegalStateException("No EClass for " + cdoClass);
    }

    return newInstance(eClass);
  }

  public CDORevisionImpl lookupRevision(CDOID id)
  {
    CDORevisionResolver revisionManager = session.getRevisionManager();
    if (isReadWrite())
    {
      return (CDORevisionImpl)revisionManager.getRevision(id);
    }

    return (CDORevisionImpl)revisionManager.getRevision(id, timeStamp);
  }

  public InternalCDOObject lookupInstance(CDOID id)
  {
    if (id.equals(lastLookupID))
    {
      return lastLookupObject;
    }

    lastLookupID = id;
    lastLookupObject = objects.get(id);
    if (lastLookupObject == null)
    {
      lastLookupObject = createObject(id);
      registerObject(lastLookupObject);
    }

    return lastLookupObject;
  }

  private InternalCDOObject createObject(CDOID id)
  {
    // if (id.isMeta())
    // {
    // if (TRACER.isEnabled())
    // {
    // TRACER.format("Creating meta: ID={0}", id);
    // }
    //
    // InternalEObject metaInstance = session.lookupMetaInstance(id);
    // if (metaInstance == null)
    // {
    // throw new IllegalArgumentException("No meta instance for " + id);
    // }
    //
    // }

    if (TRACER.isEnabled())
    {
      TRACER.format("Creating object: ID={0}", id);
    }

    CDORevisionImpl revision = lookupRevision(id);
    CDOClassImpl cdoClass = revision.getCDOClass();
    CDOID resourceID = revision.getResourceID();

    InternalCDOObject object = newInstance(cdoClass);
    if (object instanceof CDOResourceImpl)
    {
      object.cdoInternalSetResource((CDOResourceImpl)object);
    }
    else
    {
      CDOResourceImpl resource = getResource(resourceID);
      object.cdoInternalSetResource(resource);
    }

    object.cdoInternalSetRevision(revision);
    object.cdoInternalSetID(revision.getID());
    object.cdoInternalSetState(CDOState.CLEAN);
    return object;
  }

  public CDOID provideCDOID(Object idOrObject)
  {
    Object shouldBeCDOID = convertObjectToID(idOrObject);
    if (shouldBeCDOID instanceof CDOID)
    {
      CDOID id = (CDOID)shouldBeCDOID;
      if (TRACER.isEnabled())
      {
        TRACER.format("Converted dangling reference: {0} --> {1}", idOrObject, id);
      }

      return id;
    }

    throw new ImplementationError("Not a CDOID: " + shouldBeCDOID.getClass().getName());
  }

  public Object convertObjectToID(Object potentialObject)
  {
    if (potentialObject == null)
    {
      throw new ImplementationError();
    }

    if (potentialObject instanceof InternalEObject && !(potentialObject instanceof InternalCDOObject))
    {
      InternalEObject eObject = (InternalEObject)potentialObject;
      CDOID id = session.lookupMetaInstanceID(eObject);
      if (id != null)
      {
        return id;
      }

      InternalCDOObject adapter = CDOStateMachine.adapt(eObject);
      potentialObject = adapter;
    }

    if (potentialObject instanceof InternalCDOObject)
    {
      InternalCDOObject object = (InternalCDOObject)potentialObject;
      if (object.cdoView() == this)
      {
        return object.cdoID();
      }
    }

    if (TRACER.isEnabled())
    {
      TRACER.format("Dangling reference: {0}", potentialObject);
    }

    return potentialObject;
  }

  public Object convertIDToObject(Object potentialID)
  {
    if (potentialID instanceof CDOID)
    {
      if (potentialID == CDOID.NULL)
      {
        return null;
      }

      CDOID id = (CDOID)potentialID;
      InternalCDOObject result = lookupInstance(id);
      if (result == null)
      {
        throw new ImplementationError("ID not registered: " + id);
      }

      return result;
    }

    return potentialID;
  }

  public void registerObject(InternalCDOObject object)
  {
    if (TRACER.isEnabled())
    {
      TRACER.format("Registering object {0}", object);
    }

    InternalCDOObject 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 object {0}", object);
    }

    InternalCDOObject old = objects.remove(object.cdoID());
    if (old == null)
    {
      throw new IllegalStateException("Unknown ID: " + object);
    }
  }

  public void remapObject(CDOID oldID)
  {
    InternalCDOObject object = objects.remove(oldID);
    CDOID newID = object.cdoID();
    objects.put(newID, object);
    if (TRACER.isEnabled())
    {
      TRACER.format("Remapping object: {0} --> {1}", oldID, newID);
    }
  }

  // public final class HistoryEntryImpl implements HistoryEntry, Comparable
  // {
  // private String resourcePath;
  //
  // private HistoryEntryImpl(String resourcePath)
  // {
  // this.resourcePath = resourcePath;
  // }
  //
  // public CDOView getView()
  // {
  // return CDOViewImpl.this;
  // }
  //
  // public String getResourcePath()
  // {
  // return resourcePath;
  // }
  //
  // public int compareTo(Object o)
  // {
  // HistoryEntry that = (HistoryEntry)o;
  // return resourcePath.compareTo(that.getResourcePath());
  // }
  //
  // @Override
  // public String toString()
  // {
  // return resourcePath;
  // }
  // }

  /**
   * 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.
   * 
   * @param timeStamp
   *          The point in time when the newly committed revision have been
   *          created.
   * @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).
   */
  public void notifyInvalidation(long timeStamp, Set<CDOID> dirtyOIDs)
  {
    for (CDOID dirtyOID : dirtyOIDs)
    {
      InternalCDOObject object = objects.get(dirtyOID);
      if (object != null)
      {
        CDOStateMachine.INSTANCE.invalidate(object, timeStamp);
      }
    }
  }

  public boolean isDirty()
  {
    return transaction == null ? false : transaction.isDirty();
  }

  public void commit()
  {
    checkWritable();
    CommitTransactionResult result = transaction.commit();
    if (result != null)
    {
      Map<CDOID, CDOID> idMappings = result.getIdMappings();
      fireEvent(new CommittedEvent(idMappings));
    }
  }

  public void rollback()
  {
    checkWritable();
    transaction.rollback();
  }

  public void close()
  {
    session.viewDetached(this);
  }

  @Override
  public String toString()
  {
    return MessageFormat.format("CDOView({0})", isHistorical() ? new Date(timeStamp) : isReadOnly() ? "readOnly"
        : "readWrite");
  }

  public boolean isAdapterForType(Object type)
  {
    return type instanceof ResourceSet;
  }

  public Notifier getTarget()
  {
    return resourceSet;
  }

  public void setTarget(Notifier newTarget)
  {
    ResourceSet resourceSet = (ResourceSet)newTarget;
    if (TRACER.isEnabled())
    {
      TRACER.trace("Attaching CDO view to " + resourceSet);
    }

    this.resourceSet = resourceSet;
    for (Resource resource : resourceSet.getResources())
    {
      if (resource instanceof CDOResourceImpl)
      {
        CDOResourceImpl cdoResource = (CDOResourceImpl)resource;
        notifyAdd(cdoResource);
      }
    }
  }

  public void unsetTarget(Notifier oldTarget)
  {
    ResourceSet resourceSet = (ResourceSet)oldTarget;
    for (Resource resource : resourceSet.getResources())
    {
      if (resource instanceof CDOResourceImpl)
      {
        CDOResourceImpl cdoResource = (CDOResourceImpl)resource;
        notifyRemove(cdoResource);
      }
    }

    if (TRACER.isEnabled())
    {
      TRACER.trace("Detaching CDO view from " + resourceSet);
    }

    if (resourceSet == oldTarget)
    {
      setTarget(null);
    }
  }

  public void fireDirtyEvent()
  {
    fireEvent(new DirtyEvent());
  }

  public void notifyChanged(Notification msg)
  {
    switch (msg.getEventType())
    {
    case Notification.ADD:
      notifyAdd(msg);
      break;

    case Notification.ADD_MANY:
      notifyAddMany(msg);
      break;

    case Notification.REMOVE:
      notifyRemove(msg);
      break;

    case Notification.REMOVE_MANY:
      notifyRemoveMany(msg);
      break;
    }
  }

  private void notifyAdd(Notification msg)
  {
    if (msg.getNewValue() instanceof CDOResourceImpl)
    {
      notifyAdd((CDOResourceImpl)msg.getNewValue());
    }
  }

  private void notifyAddMany(Notification msg)
  {
    EList<Resource> newResources = (EList<Resource>)msg.getNewValue();
    EList<Resource> oldResources = (EList<Resource>)msg.getOldValue();
    for (Resource newResource : newResources)
    {
      if (newResource instanceof CDOResourceImpl)
      {
        if (!oldResources.contains(newResource))
        {
          // TODO Optimize event notification with IContainerEvent
          notifyAdd((CDOResourceImpl)newResource);
        }
      }
    }
  }

  private void notifyAdd(CDOResourceImpl cdoResource)
  {
    try
    {
      CDOStateMachine.INSTANCE.attach(cdoResource, cdoResource, this);
      fireEvent(new ResourcesEvent(cdoResource.getPath(), ResourcesEvent.Kind.ADDED));
    }
    catch (RuntimeException ex)
    {
      try
      {
        ((InternalCDOObject)cdoResource).cdoInternalSetState(CDOState.NEW);
        resourceSet.getResources().remove(cdoResource);
      }
      catch (RuntimeException ignore)
      {
      }

      throw ex;
    }
  }

  private void notifyRemove(Notification msg)
  {
    if (msg.getOldValue() instanceof CDOResourceImpl)
    {
      notifyRemove((CDOResourceImpl)msg.getOldValue());
    }
  }

  private void notifyRemoveMany(Notification msg)
  {
    EList<Resource> newResources = (EList<Resource>)msg.getNewValue();
    EList<Resource> oldResources = (EList<Resource>)msg.getOldValue();
    for (Resource oldResource : oldResources)
    {
      if (oldResource instanceof CDOResourceImpl)
      {
        if (!newResources.contains(oldResource))
        {
          // TODO Optimize event notification with IContainerEvent
          notifyRemove((CDOResourceImpl)oldResource);
        }
      }
    }
  }

  private void notifyRemove(CDOResourceImpl cdoResource)
  {
    CDOStateMachine.INSTANCE.detach(cdoResource, cdoResource, this);
    fireEvent(new ResourcesEvent(cdoResource.getPath(), ResourcesEvent.Kind.REMOVED));
  }

  private void checkWritable()
  {
    if (isReadOnly())
    {
      throw new IllegalStateException("CDO view is read only");
    }
  }

  // public final class HistoryEntryImpl implements HistoryEntry, Comparable
  // {
  // private String resourcePath;
  //
  // private HistoryEntryImpl(String resourcePath)
  // {
  // this.resourcePath = resourcePath;
  // }
  //
  // public CDOView getView()
  // {
  // return CDOViewImpl.this;
  // }
  //
  // public String getResourcePath()
  // {
  // return resourcePath;
  // }
  //
  // public int compareTo(Object o)
  // {
  // HistoryEntry that = (HistoryEntry)o;
  // return resourcePath.compareTo(that.getResourcePath());
  // }
  //
  // @Override
  // public String toString()
  // {
  // return resourcePath;
  // }
  // }

  /**
   * @author Eike Stepper
   */
  private abstract class Event extends org.eclipse.net4j.internal.util.event.Event implements CDOViewEvent
  {
    private static final long serialVersionUID = 1L;

    public Event()
    {
      super(CDOViewImpl.this);
    }

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

  /**
   * @author Eike Stepper
   */
  private final class ResourcesEvent extends Event implements CDOViewResourcesEvent
  {
    private static final long serialVersionUID = 1L;

    private String resourcePath;

    private Kind kind;

    public ResourcesEvent(String resourcePath, Kind kind)
    {
      this.resourcePath = resourcePath;
      this.kind = kind;
    }

    public String getResourcePath()
    {
      return resourcePath;
    }

    public Kind getKind()
    {
      return kind;
    }

    @Override
    public String toString()
    {
      return MessageFormat.format("CDOViewResourcesEvent[{0}, {1}, {2}]", getView(), resourcePath, kind);
    }
  }

  /**
   * @author Eike Stepper
   */
  private final class DirtyEvent extends Event implements CDOViewDirtyEvent
  {
    private static final long serialVersionUID = 1L;

    private DirtyEvent()
    {
    }
  }

  /**
   * @author Eike Stepper
   */
  private final class CommittedEvent extends Event implements CDOViewCommittedEvent
  {
    private static final long serialVersionUID = 1L;

    private Map<CDOID, CDOID> idMappings;

    private CommittedEvent(Map<CDOID, CDOID> idMappings)
    {
      this.idMappings = idMappings;
    }

    public Map<CDOID, CDOID> getIDMappings()
    {
      return idMappings;
    }
  }
}

Back to the top