blob: 1384bea8a1bf5e362ec880f858e61aa6e34a3d8b [file] [log] [blame]
/***************************************************************************
* Copyright (c) 2004 - 2008 Eike Stepper, Germany.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Eike Stepper - initial API and implementation
* Simon McDuff - maintenance
**************************************************************************/
package org.eclipse.emf.internal.cdo.util;
import org.eclipse.emf.cdo.common.id.CDOIDMetaRange;
import org.eclipse.emf.cdo.common.model.CDOClass;
import org.eclipse.emf.cdo.common.model.CDOClassProxy;
import org.eclipse.emf.cdo.common.model.CDOClassRef;
import org.eclipse.emf.cdo.common.model.CDOFeature;
import org.eclipse.emf.cdo.common.model.CDOModelUtil;
import org.eclipse.emf.cdo.common.model.CDOPackage;
import org.eclipse.emf.cdo.common.model.CDOPackageManager;
import org.eclipse.emf.cdo.common.model.CDOType;
import org.eclipse.emf.cdo.common.model.core.CDOCorePackage;
import org.eclipse.emf.cdo.common.model.resource.CDOResourceClass;
import org.eclipse.emf.cdo.common.model.resource.CDOResourceFolderClass;
import org.eclipse.emf.cdo.common.model.resource.CDOResourceNodeClass;
import org.eclipse.emf.cdo.common.model.resource.CDOResourcePackage;
import org.eclipse.emf.cdo.eresource.EresourcePackage;
import org.eclipse.emf.cdo.spi.common.InternalCDOClass;
import org.eclipse.emf.cdo.spi.common.InternalCDOFeature;
import org.eclipse.emf.cdo.spi.common.InternalCDOPackage;
import org.eclipse.emf.cdo.util.CDOEMFUtil;
import org.eclipse.emf.cdo.util.CDOPackageRegistry;
import org.eclipse.emf.internal.cdo.CDOFactoryImpl;
import org.eclipse.emf.internal.cdo.CDOSessionImpl;
import org.eclipse.emf.internal.cdo.CDOSessionPackageManagerImpl;
import org.eclipse.emf.internal.cdo.bundle.OM;
import org.eclipse.net4j.util.ImplementationError;
import org.eclipse.net4j.util.ObjectUtil;
import org.eclipse.net4j.util.om.trace.ContextTracer;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.impl.EPackageImpl;
/**
* @author Eike Stepper
*/
public final class ModelUtil
{
private static final ContextTracer MODEL_TRACER = new ContextTracer(OM.DEBUG_MODEL, ModelUtil.class);
private ModelUtil()
{
}
public static String getParentURI(EPackage ePackage)
{
EPackage superPackage = ePackage.getESuperPackage();
String parentURI = superPackage == null ? null : superPackage.getNsURI();
return parentURI;
}
public static EPackage getTopLevelPackage(EPackage ePackage)
{
EPackage superPackage = ePackage.getESuperPackage();
return superPackage == null ? ePackage : getTopLevelPackage(superPackage);
}
public static CDOType getCDOType(EStructuralFeature eFeature)
{
if (eFeature instanceof EReference)
{
throw new ImplementationError("Should only be called for attributes");
// return CDOTypeImpl.OBJECT;
}
EClassifier classifier = eFeature.getEType();
if (classifier.getEPackage() == EcorePackage.eINSTANCE)
{
int classifierID = classifier.getClassifierID();
switch (classifierID)
{
case EcorePackage.EBOOLEAN:
case EcorePackage.EBOOLEAN_OBJECT:
case EcorePackage.EBYTE:
case EcorePackage.EBYTE_OBJECT:
case EcorePackage.ECHAR:
case EcorePackage.ECHARACTER_OBJECT:
case EcorePackage.EDATE:
case EcorePackage.EDOUBLE:
case EcorePackage.EDOUBLE_OBJECT:
case EcorePackage.EFLOAT:
case EcorePackage.EFLOAT_OBJECT:
case EcorePackage.EINT:
case EcorePackage.EINTEGER_OBJECT:
case EcorePackage.ELONG:
case EcorePackage.ELONG_OBJECT:
case EcorePackage.ESHORT:
case EcorePackage.ESHORT_OBJECT:
CDOType type = CDOModelUtil.getType(classifierID);
if (type == CDOType.OBJECT)
{
throw new ImplementationError("Attributes can not be of type OBJECT");
}
return type;
case EcorePackage.ESTRING:
return CDOType.STRING;
}
}
if (classifier instanceof EDataType)
{
return CDOType.CUSTOM;
}
throw new IllegalArgumentException("Invalid attribute type: " + classifier);
}
public static void initializeCDOPackage(EPackage ePackage, CDOPackage cdoPackage)
{
((InternalCDOPackage)cdoPackage).setClientInfo(ePackage);
for (EClass eClass : CDOEMFUtil.getPersistentClasses(ePackage))
{
CDOClass cdoClass = createCDOClass(eClass, cdoPackage);
((InternalCDOPackage)cdoPackage).addClass(cdoClass);
}
}
public static CDOPackage getCDOPackage(EPackage ePackage, CDOSessionPackageManagerImpl packageManager)
{
String packageURI = ePackage.getNsURI();
CDOPackage cdoPackage = packageManager.lookupPackage(packageURI);
if (cdoPackage == null)
{
EPackage topLevelPackage = getTopLevelPackage(ePackage);
if (topLevelPackage != ePackage)
{
getCDOPackage(topLevelPackage, packageManager);
cdoPackage = packageManager.lookupPackage(packageURI);
}
else
{
cdoPackage = addCDOPackage(topLevelPackage, packageManager);
}
}
return cdoPackage;
}
public static CDOClass getCDOClass(EClass eClass, CDOSessionPackageManagerImpl packageManager)
{
CDOPackage cdoPackage = getCDOPackage(eClass.getEPackage(), packageManager);
return cdoPackage.lookupClass(eClass.getClassifierID());
}
public static CDOFeature getCDOFeature(EStructuralFeature eFeature, CDOSessionPackageManagerImpl packageManager)
{
CDOClass cdoClass = getCDOClass(eFeature.getEContainingClass(), packageManager);
return cdoClass.lookupFeature(eFeature.getFeatureID());
}
private static CDOPackage addCDOPackage(EPackage ePackage, CDOSessionPackageManagerImpl packageManager)
{
CDOPackage cdoPackage = createCDOPackage(ePackage, packageManager);
packageManager.addPackage(cdoPackage);
for (EPackage subPackage : ePackage.getESubpackages())
{
addCDOPackage(subPackage, packageManager);
}
return cdoPackage;
}
/**
* @see CDOEMFUtil#getPersistentFeatures(org.eclipse.emf.common.util.EList)
* @see http://www.eclipse.org/newsportal/article.php?id=26780&group=eclipse.tools.emf#26780
*/
private static CDOPackage createCDOPackage(EPackage ePackage, CDOSessionPackageManagerImpl packageManager)
{
CDOSessionImpl session = packageManager.getSession();
String uri = ePackage.getNsURI();
String parentURI = getParentURI(ePackage);
String name = ePackage.getName();
boolean dynamic = CDOEMFUtil.isDynamicEPackage(ePackage);
String ecore = null;
CDOIDMetaRange idRange = null;
if (parentURI == null)
{
if (!EcorePackage.eINSTANCE.getNsURI().equals(uri))
{
ecore = CDOEMFUtil.ePackageToString(ePackage, session.getPackageRegistry());
}
idRange = session.registerEPackage(ePackage);
}
CDOPackage cdoPackage = CDOModelUtil.createPackage(packageManager, uri, name, ecore, dynamic, idRange, parentURI);
initializeCDOPackage(ePackage, cdoPackage);
return cdoPackage;
}
private static CDOClass createCDOClass(EClass eClass, CDOPackage containingPackage)
{
InternalCDOClass cdoClass = (InternalCDOClass)CDOModelUtil.createClass(containingPackage, eClass.getClassifierID(),
eClass.getName(), eClass.isAbstract());
cdoClass.setClientInfo(eClass);
for (EClass superType : eClass.getESuperTypes())
{
CDOClassRef classRef = createClassRef(superType);
cdoClass.addSuperType(classRef);
}
// Bugs: 247978 Make sure featureIndex are properly set for dynamic classes
eClass.getEAllStructuralFeatures();
for (EStructuralFeature eFeature : CDOEMFUtil.getPersistentFeatures(eClass.getEStructuralFeatures()))
{
CDOFeature cdoFeature = createCDOFeature(eFeature, cdoClass);
cdoClass.addFeature(cdoFeature);
}
return cdoClass;
}
private static CDOFeature createCDOFeature(EStructuralFeature eFeature, CDOClass containingClass)
{
InternalCDOFeature cdoFeature = (InternalCDOFeature)(CDOEMFUtil.isReference(eFeature) ? createCDOReference(
(EReference)eFeature, containingClass) : createCDOAttribute((EAttribute)eFeature, containingClass));
cdoFeature.setClientInfo(eFeature);
return cdoFeature;
}
private static CDOFeature createCDOReference(EReference eFeature, CDOClass containingClass)
{
CDOPackageManager packageManager = containingClass.getPackageManager();
int featureID = eFeature.getFeatureID();
String name = eFeature.getName();
CDOClassRef classRef = createClassRef(eFeature.getEType());
boolean many = eFeature.isMany();
boolean containment = CDOEMFUtil.isContainment(eFeature);
CDOFeature cdoFeature = CDOModelUtil.createReference(containingClass, featureID, name, new CDOClassProxy(classRef,
packageManager), many, containment);
EReference opposite = eFeature.getEOpposite();
if (MODEL_TRACER.isEnabled() && opposite != null)
{
MODEL_TRACER.format("Opposite info: package={0}, class={1}, feature={2}", opposite.getEContainingClass()
.getEPackage().getNsURI(), opposite.getEContainingClass().getName(), opposite.getName());
}
return cdoFeature;
}
private static CDOFeature createCDOAttribute(EAttribute eFeature, CDOClass containingClass)
{
int featureID = eFeature.getFeatureID();
String name = eFeature.getName();
CDOType type = getCDOType(eFeature);
boolean many = CDOEMFUtil.isMany(eFeature);
return CDOModelUtil.createAttribute(containingClass, featureID, name, type, many);
}
public static EPackage getEPackage(CDOPackage cdoPackage, CDOPackageRegistry packageRegistry)
{
EPackage ePackage = (EPackage)cdoPackage.getClientInfo();
if (ePackage == null)
{
String uri = cdoPackage.getPackageURI();
ePackage = packageRegistry.getEPackage(uri);
if (ePackage == null)
{
ePackage = createEPackage(cdoPackage);
packageRegistry.put(uri, ePackage);
}
((InternalCDOPackage)cdoPackage).setClientInfo(ePackage);
}
return ePackage;
}
public static EClass getEClass(CDOClass cdoClass, CDOPackageRegistry packageRegistry)
{
EClass eClass = (EClass)cdoClass.getClientInfo();
if (eClass == null)
{
EPackage ePackage = getEPackage(cdoClass.getContainingPackage(), packageRegistry);
eClass = (EClass)ePackage.getEClassifier(cdoClass.getName());
((InternalCDOClass)cdoClass).setClientInfo(eClass);
}
return eClass;
}
public static EStructuralFeature getEFeature(CDOFeature cdoFeature, CDOPackageRegistry packageRegistry)
{
EStructuralFeature eFeature = (EStructuralFeature)cdoFeature.getClientInfo();
if (eFeature == null)
{
EClass eClass = getEClass(cdoFeature.getContainingClass(), packageRegistry);
eFeature = eClass.getEStructuralFeature(cdoFeature.getFeatureID());
((InternalCDOFeature)cdoFeature).setClientInfo(eFeature);
}
return eFeature;
}
public static EPackage createEPackage(CDOPackage cdoPackage)
{
if (!cdoPackage.isDynamic())
{
EPackage ePackage = createGeneratedEPackage(cdoPackage.getPackageURI());
if (ePackage != null)
{
return ePackage;
}
}
return createDynamicEPackage(cdoPackage);
}
public static EPackage createGeneratedEPackage(String packageURI)
{
if (packageURI.equals(EcorePackage.eINSTANCE.getNsURI()))
{
return EcorePackage.eINSTANCE;
}
return EPackage.Registry.INSTANCE.getEPackage(packageURI);
}
public static EPackageImpl createDynamicEPackage(CDOPackage cdoPackage)
{
CDOPackage topLevelPackage = cdoPackage.getTopLevelPackage();
String ecore = topLevelPackage.getEcore();
EPackageImpl topLevelPackageEPackage = (EPackageImpl)CDOEMFUtil.ePackageFromString(ecore);
EPackageImpl ePackage = prepareDynamicEPackage(topLevelPackageEPackage, cdoPackage.getPackageURI());
return ePackage;
}
private static EPackageImpl prepareDynamicEPackage(EPackageImpl ePackage, String nsURI)
{
prepareDynamicEPackage(ePackage);
EPackageImpl result = ObjectUtil.equals(ePackage.getNsURI(), nsURI) ? ePackage : null;
for (EPackage subPackage : ePackage.getESubpackages())
{
EPackageImpl p = prepareDynamicEPackage((EPackageImpl)subPackage, nsURI);
if (p != null && result == null)
{
result = p;
}
}
return result;
}
public static void prepareDynamicEPackage(EPackageImpl ePackage)
{
ePackage.setEFactoryInstance(new CDOFactoryImpl(ePackage));
}
public static CDOClassRef createClassRef(EClassifier classifier)
{
if (classifier instanceof EClass)
{
String packageURI = classifier.getEPackage().getNsURI();
int classifierID = classifier.getClassifierID();
return CDOModelUtil.createClassRef(packageURI, classifierID);
}
return null;
}
public static void addModelInfos(CDOSessionPackageManagerImpl packageManager)
{
// Ecore
CDOCorePackage corePackage = packageManager.getCDOCorePackage();
((InternalCDOPackage)corePackage).setClientInfo(EcorePackage.eINSTANCE);
((InternalCDOClass)corePackage.getCDOObjectClass()).setClientInfo(EcorePackage.eINSTANCE.getEObject());
// Eresource
if (!ObjectUtil.equals(CDOResourcePackage.PACKAGE_URI, EresourcePackage.eNS_URI))
{
throw new ImplementationError();
}
CDOResourcePackage resourcePackage = packageManager.getCDOResourcePackage();
((InternalCDOPackage)resourcePackage).setClientInfo(EresourcePackage.eINSTANCE);
CDOResourceNodeClass resourceNodeClass = resourcePackage.getCDOResourceNodeClass();
((InternalCDOClass)resourceNodeClass).setClientInfo(EresourcePackage.eINSTANCE.getCDOResourceNode());
((InternalCDOFeature)resourceNodeClass.getCDOFolderFeature()).setClientInfo(EresourcePackage.eINSTANCE
.getCDOResourceNode_Folder());
((InternalCDOFeature)resourceNodeClass.getCDONameFeature()).setClientInfo(EresourcePackage.eINSTANCE
.getCDOResourceNode_Name());
CDOResourceFolderClass resourceFolderClass = resourcePackage.getCDOResourceFolderClass();
((InternalCDOClass)resourceFolderClass).setClientInfo(EresourcePackage.eINSTANCE.getCDOResourceFolder());
((InternalCDOFeature)resourceFolderClass.getCDONodesFeature()).setClientInfo(EresourcePackage.eINSTANCE
.getCDOResourceFolder_Nodes());
CDOResourceClass resourceClass = resourcePackage.getCDOResourceClass();
((InternalCDOClass)resourceClass).setClientInfo(EresourcePackage.eINSTANCE.getCDOResource());
((InternalCDOFeature)resourceClass.getCDOContentsFeature()).setClientInfo(EresourcePackage.eINSTANCE
.getCDOResource_Contents());
}
}