blob: 6047687e4e1a1792ddec0600caba6b107aa3a404 [file] [log] [blame]
/***************************************************************************
* Copyright (c) 2004 - 2008 Eike Stepper, Germany.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Eike Stepper - initial API and implementation
* Eike Stepper - maintenance
**************************************************************************/
package org.eclipse.emf.internal.cdo.util;
import org.eclipse.emf.cdo.CDOCommitContext;
import org.eclipse.emf.cdo.CDOObject;
import org.eclipse.emf.cdo.CDOSession;
import org.eclipse.emf.cdo.CDOTransaction;
import org.eclipse.emf.cdo.CDOTransactionHandler;
import org.eclipse.emf.cdo.CDOView;
import org.eclipse.emf.cdo.common.id.CDOIDMetaRange;
import org.eclipse.emf.cdo.common.model.CDOPackage;
import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackage;
import org.eclipse.emf.cdo.util.CDOPackageRegistry;
import org.eclipse.emf.cdo.util.CDOPackageType;
import org.eclipse.emf.cdo.util.CDOPackageTypeRegistry;
import org.eclipse.emf.cdo.util.EMFUtil;
import org.eclipse.emf.internal.cdo.CDOSessionPackageManagerImpl;
import org.eclipse.emf.internal.cdo.InternalCDOSession;
import org.eclipse.emf.internal.cdo.bundle.OM;
import org.eclipse.net4j.util.container.ContainerEventAdapter;
import org.eclipse.net4j.util.container.IContainer;
import org.eclipse.net4j.util.event.IListener;
import org.eclipse.net4j.util.lifecycle.ILifecycle;
import org.eclipse.net4j.util.lifecycle.LifecycleEventAdapter;
import org.eclipse.net4j.util.om.trace.ContextTracer;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EFactory;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.impl.EPackageRegistryImpl;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author Eike Stepper
*/
public class CDOPackageRegistryImpl extends EPackageRegistryImpl implements CDOPackageRegistry
{
private static final long serialVersionUID = 1L;
private final ContextTracer tracer = new ContextTracer(OM.DEBUG_MODEL, CDOPackageRegistryImpl.class);
private InternalCDOSession session;
public CDOPackageRegistryImpl()
{
}
public InternalCDOSession getSession()
{
return session;
}
public void setSession(CDOSession session)
{
this.session = (InternalCDOSession)session;
}
public void putPackageDescriptor(CDOPackage cdoPackage)
{
checkSession();
EPackage.Descriptor descriptor = new RemotePackageDescriptor(cdoPackage);
String uri = cdoPackage.getPackageURI();
if (tracer.isEnabled())
{
tracer.format("Registering package descriptor for {0}", uri);
}
put(uri, descriptor);
}
/**
* Insert the topPackage and its sub-packages by their URI
*/
public EPackage putEPackage(EPackage ePackage) throws IllegalArgumentException
{
checkSession();
String uri = ePackage.getNsURI();
if (ePackage.getESuperPackage() != null)
{
throw new IllegalArgumentException("Not a top level package: " + uri);
}
putEPackage(uri, ePackage);
return getEPackage(uri);
}
private void putEPackage(String uri, EPackage ePackage)
{
if (uri != null)
{
put(uri, ePackage);
}
for (EPackage subPackage : ePackage.getESubpackages())
{
putEPackage(subPackage.getNsURI(), subPackage);
}
}
@Override
public Object put(String key, Object value)
{
checkSession();
if (value instanceof EPackage)
{
if (tracer.isEnabled())
{
tracer.format("Registering package for {0}", key);
}
EPackage ePackage = (EPackage)value;
EMFUtil.prepareDynamicEPackage(ePackage);
CDOSessionPackageManagerImpl packageManager = (CDOSessionPackageManagerImpl)session.getPackageManager();
CDOPackage cdoPackage = ModelUtil.getCDOPackage(ePackage, packageManager);
CDOIDMetaRange metaIDRange = cdoPackage.getTopLevelPackage().getMetaIDRange();
((InternalCDOPackage)cdoPackage).setPersistent(metaIDRange != null && !metaIDRange.isTemporary());
}
return super.put(key, value);
}
@Override
public void putAll(Map<? extends String, ? extends Object> m)
{
throw new UnsupportedOperationException();
}
private void checkSession()
{
if (session == null)
{
throw new IllegalStateException("session == null");
}
}
/**
* @author Eike Stepper
*/
private final class RemotePackageDescriptor implements EPackage.Descriptor
{
private CDOPackage cdoPackage;
private RemotePackageDescriptor(CDOPackage cdoPackage)
{
this.cdoPackage = cdoPackage;
}
public CDOPackage getCDOPackage()
{
return cdoPackage;
}
public EFactory getEFactory()
{
// TODO Implement method RemotePackageDescriptor.getEFactory()
throw new UnsupportedOperationException("Not yet implemented");
}
public EPackage getEPackage()
{
EPackage ePackage = ModelUtil.createEPackage(cdoPackage);
CDOIDMetaRange idRange = cdoPackage.getMetaIDRange();
if (idRange != null)
{
session.registerEPackage(ePackage, idRange);
}
return ePackage;
}
@Override
public String toString()
{
return MessageFormat.format("RemotePackageDescriptor[{0}]", cdoPackage.getPackageURI());
}
}
/**
* @author Eike Stepper
*/
public static abstract class SessionBound extends CDOPackageRegistryImpl
{
private static final long serialVersionUID = 1L;
private IListener sessionLifecycleListener = new LifecycleEventAdapter()
{
@Override
protected void onActivated(ILifecycle lifecycle)
{
sessionActivated();
}
@Override
protected void onAboutToDeactivate(ILifecycle lifecycle)
{
getSession().removeListener(this);
sessionAboutToDeactivate();
}
};
public SessionBound()
{
}
@Override
public void setSession(CDOSession session)
{
super.setSession(session);
session.addListener(sessionLifecycleListener);
}
protected abstract void sessionActivated();
protected abstract void sessionAboutToDeactivate();
}
/**
* @author Eike Stepper
*/
public static class Eager extends SessionBound
{
private static final long serialVersionUID = 1L;
private IListener typeListener = new ContainerEventAdapter<Map.Entry<String, CDOPackageType>>()
{
@Override
protected void onAdded(IContainer<java.util.Map.Entry<String, CDOPackageType>> container,
java.util.Map.Entry<String, CDOPackageType> entry)
{
addEntry(entry);
}
};
public Eager()
{
}
@Override
protected void sessionActivated()
{
for (Map.Entry<String, CDOPackageType> entry : CDOPackageTypeRegistry.INSTANCE.entrySet())
{
addEntry(entry);
}
CDOPackageTypeRegistry.INSTANCE.addListener(typeListener);
}
@Override
protected void sessionAboutToDeactivate()
{
CDOPackageTypeRegistry.INSTANCE.removeListener(typeListener);
}
protected void addEntry(Map.Entry<String, CDOPackageType> entry)
{
CDOPackageType packageType = entry.getValue();
// TODO LEGACY
if (packageType != CDOPackageType.LEGACY)
{
String uri = entry.getKey();
if (!containsKey(uri))
{
try
{
EPackage ePackage = EPackage.Registry.INSTANCE.getEPackage(uri);
if (ePackage.getESuperPackage() == null)
{
putEPackage(ePackage);
}
}
catch (RuntimeException ex)
{
OM.LOG.error(ex);
}
}
}
}
}
/**
* @author Eike Stepper
*/
public static class TransactionBound extends SessionBound implements CDOTransactionHandler
{
private static final long serialVersionUID = 1L;
private List<CDOTransaction> transactions = new ArrayList<CDOTransaction>();
private IListener sessionContainerListener = new ContainerEventAdapter<CDOView>()
{
@Override
protected void onAdded(IContainer<CDOView> session, CDOView view)
{
if (view instanceof CDOTransaction)
{
CDOTransaction transaction = (CDOTransaction)view;
transaction.addHandler(TransactionBound.this);
synchronized (transactions)
{
transactions.add(transaction);
}
}
}
@Override
protected void onRemoved(IContainer<CDOView> session, CDOView view)
{
if (view instanceof CDOTransaction)
{
CDOTransaction transaction = (CDOTransaction)view;
transaction.removeHandler(TransactionBound.this);
synchronized (transactions)
{
transactions.remove(transaction);
}
}
}
};
public TransactionBound()
{
}
@Override
protected void sessionActivated()
{
getSession().addListener(sessionContainerListener);
}
@Override
protected void sessionAboutToDeactivate()
{
getSession().removeListener(sessionContainerListener);
synchronized (transactions)
{
for (CDOTransaction transaction : transactions)
{
transaction.removeHandler(this);
}
transactions.clear();
}
}
public void attachingObject(CDOTransaction transaction, CDOObject object)
{
}
public void modifyingObject(CDOTransaction transaction, CDOObject object, CDOFeatureDelta featureDelta)
{
}
public void committingTransaction(CDOTransaction transaction, CDOCommitContext commitContext)
{
}
public void rolledBackTransaction(CDOTransaction transaction)
{
}
public void detachingObject(CDOTransaction transaction, CDOObject object)
{
}
public void committedTransaction(CDOTransaction transaction, CDOCommitContext commitContext)
{
}
}
/**
* @author Eike Stepper
*/
public static class Lazy extends TransactionBound
{
private static final long serialVersionUID = 1L;
private Set<EClass> usedClasses = new HashSet<EClass>();
public Lazy()
{
}
@Override
public void attachingObject(CDOTransaction transaction, CDOObject object)
{
EClass usedClass = object.eClass();
addAllEPackages(usedClass);
}
private void addAllEPackages(EClass eClass)
{
if (usedClasses.add(eClass))
{
addPackage(eClass.getEPackage());
for (EClass superType : eClass.getEAllSuperTypes())
{
addAllEPackages(superType);
}
for (EReference eReference : eClass.getEAllReferences())
{
addAllEPackages(eReference.getEReferenceType());
}
}
}
@Override
protected void sessionAboutToDeactivate()
{
usedClasses.clear();
super.sessionAboutToDeactivate();
}
private void addPackage(EPackage ePackage)
{
if (!containsKey(ePackage.getNsURI()))
{
EPackage topLevelPackage = ModelUtil.getTopLevelPackage(ePackage);
// PutEPackage
putEPackage(topLevelPackage);
}
}
}
}