| /******************************************************************************* |
| * Copyright (c) 2011, 2012, 2013, 2014 Red Hat, Inc. |
| * All rights reserved. |
| * This program is 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: |
| * Red Hat, Inc. - initial API and implementation |
| * |
| * @author Bob Brodt |
| ******************************************************************************/ |
| |
| package org.eclipse.bpmn2.modeler.core.model; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.bpmn2.BaseElement; |
| import org.eclipse.bpmn2.Bpmn2Package; |
| import org.eclipse.bpmn2.Collaboration; |
| import org.eclipse.bpmn2.Definitions; |
| import org.eclipse.bpmn2.ExtensionAttributeValue; |
| import org.eclipse.bpmn2.Participant; |
| import org.eclipse.bpmn2.Process; |
| import org.eclipse.bpmn2.di.BPMNDiagram; |
| import org.eclipse.bpmn2.di.BpmnDiPackage; |
| import org.eclipse.bpmn2.modeler.core.Activator; |
| import org.eclipse.bpmn2.modeler.core.EDataTypeConversionFactory; |
| import org.eclipse.bpmn2.modeler.core.adapters.AdapterRegistry; |
| import org.eclipse.bpmn2.modeler.core.adapters.AdapterUtil; |
| import org.eclipse.bpmn2.modeler.core.adapters.ExtendedPropertiesAdapter; |
| import org.eclipse.bpmn2.modeler.core.adapters.FeatureDescriptor; |
| import org.eclipse.bpmn2.modeler.core.adapters.InsertionAdapter; |
| import org.eclipse.bpmn2.modeler.core.utils.Messages; |
| import org.eclipse.bpmn2.modeler.core.utils.ModelUtil; |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.dd.dc.DcPackage; |
| import org.eclipse.dd.di.DiPackage; |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.emf.ecore.EAnnotation; |
| 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.EDataType.Internal.ConversionDelegate; |
| import org.eclipse.emf.ecore.EEnum; |
| import org.eclipse.emf.ecore.EEnumLiteral; |
| import org.eclipse.emf.ecore.EModelElement; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EPackage; |
| import org.eclipse.emf.ecore.EReference; |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| import org.eclipse.emf.ecore.ETypedElement; |
| import org.eclipse.emf.ecore.EcoreFactory; |
| import org.eclipse.emf.ecore.EcorePackage; |
| import org.eclipse.emf.ecore.impl.EAttributeImpl; |
| import org.eclipse.emf.ecore.resource.ResourceSet; |
| import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; |
| import org.eclipse.emf.ecore.util.BasicFeatureMap; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.emf.ecore.util.ExtendedMetaData; |
| import org.eclipse.emf.ecore.util.FeatureMap; |
| import org.eclipse.emf.ecore.util.FeatureMap.Entry; |
| import org.eclipse.emf.ecore.util.FeatureMapUtil; |
| import org.eclipse.emf.ecore.xmi.impl.XMLResourceFactoryImpl; |
| import org.eclipse.emf.ecore.xml.type.AnyType; |
| import org.eclipse.emf.ecore.xml.type.XMLTypePackage; |
| import org.eclipse.emf.transaction.RecordingCommand; |
| import org.eclipse.emf.transaction.TransactionalEditingDomain; |
| import org.eclipse.emf.transaction.util.TransactionUtil; |
| import org.eclipse.osgi.util.NLS; |
| |
| /** |
| * This class wraps an EPackage and provides methods for dynamic EMF. |
| */ |
| /** |
| * |
| */ |
| public class ModelDecorator { |
| final static EcoreFactory theCoreFactory = EcoreFactory.eINSTANCE; |
| public final static String DECORATOR_URI = "http://org.eclipse.bpmn2.modeler.core.decorator"; //$NON-NLS-1$ |
| |
| protected EPackage ePackage; |
| protected static ResourceSet resourceSet; |
| protected List<EPackage> relatedEPackages; |
| |
| /** |
| * Construct a new EPackage for extension classes and features, and add the given |
| * EPackage to our list of related packages. The new EPackage will have the same |
| * namespace URI and prefix, but will be contained in a private ResourceSet, |
| * so there's no danger of contaminating the original EPackage. |
| * |
| * This allows extension plugins to define their own EMF models the traditional |
| * way (by generating Java implementations classes from an ecore file) but still |
| * supports dynamic extensions to those models. |
| * |
| * @param pkg |
| */ |
| public ModelDecorator(EPackage pkg) { |
| Assert.isTrue( isValid(pkg) ); |
| String name = pkg.getName()+" Dynamic Extensions"; //$NON-NLS-1$ |
| String nsPrefix = pkg.getNsPrefix(); |
| String nsURI = pkg.getNsURI(); |
| |
| addRelatedEPackage(pkg); |
| // AdapterRegistry.INSTANCE.registerFactory(pkg, AnyTypeAdaptorFactory.INSTANCE); |
| |
| getResourceSet(); |
| ePackage = (EPackage) resourceSet.getPackageRegistry().get(nsURI); |
| if (ePackage==null) { |
| ePackage = createEPackage(name,nsPrefix,nsURI); |
| initPackage(); |
| } |
| } |
| |
| /** |
| * Construct a new EPackage for extension classes and features that will be |
| * defined dynamically. |
| * |
| * @param name |
| * @param nsPrefix |
| * @param nsURI |
| */ |
| public ModelDecorator(String name, String nsPrefix, String nsURI) { |
| ePackage = (EPackage) getResourceSet().getPackageRegistry().get(nsURI); |
| if (ePackage==null) { |
| ePackage = createEPackage(name,nsPrefix,nsURI); |
| } |
| initPackage(); |
| } |
| |
| /** |
| * Dispose of our dynamic EPackage and all of its contained classes and features. |
| */ |
| public void dispose() { |
| if (resourceSet!=null) { |
| if (ePackage!=null) { |
| ModelDecoratorAdapter mda = ModelDecoratorAdapter.getAdapter(ePackage); |
| if (mda!=null) |
| mda.dispose(); |
| resourceSet.getPackageRegistry().remove(ePackage.getNsURI()); |
| EcoreUtil.delete(ePackage); |
| } |
| } |
| } |
| |
| /** |
| * Construct a private ResourceSet that will contain our dynamic EPackage. |
| * |
| * @return |
| */ |
| private static ResourceSet getResourceSet() { |
| if (resourceSet==null) |
| resourceSet = new ResourceSetImpl(); |
| return resourceSet; |
| } |
| |
| /** |
| * Initialize our dynamic EPackage: |
| * - set our object factory to create adapted AnyType objects |
| * - add a ModelDecorator adapter to the EPackage so that clients can find us |
| * - add our DataTypeConversion factory for user-defined EDataTypes |
| */ |
| private void initPackage() { |
| ePackage.setEFactoryInstance(new AnyTypeObjectFactory(this)); |
| ModelDecoratorAdapter.adapt(this); |
| List<String> delegates = new ArrayList<String>(); |
| delegates.add(EDataTypeConversionFactory.DATATYPE_CONVERSION_FACTORY_URI); |
| EcoreUtil.setConversionDelegates(ePackage, delegates); |
| AdapterRegistry.INSTANCE.registerFactory(ePackage, AnyTypeAdaptorFactory.INSTANCE); |
| } |
| |
| /** |
| * Return our dynamic EPackage. |
| * |
| * @return |
| */ |
| public EPackage getEPackage() { |
| Assert.isNotNull(ePackage); |
| return ePackage; |
| } |
| |
| /** |
| * Return the dynamic EPackage for the given namespace URI. |
| * |
| * @param nsURI |
| * @return the dynamic EPackage or null if not found. |
| */ |
| public static EPackage getEPackage(String nsURI) { |
| EPackage pkg = (EPackage) getResourceSet().getPackageRegistry().get(nsURI); |
| if (pkg!=null) |
| return pkg; |
| |
| // check all related packages in all ModelDecorators in our ResourceSet |
| for (Map.Entry<String, Object> entry : getResourceSet().getPackageRegistry().entrySet()) { |
| ModelDecorator md = ModelDecoratorAdapter.getModelDecorator((EPackage) entry.getValue()); |
| for (EPackage p : md.getRelatedEPackages()) { |
| if (p.getNsURI().equals(nsURI)) |
| return p; |
| } |
| } |
| |
| return null; |
| } |
| |
| public static ModelDecorator getModelDecorator(String nsURI) { |
| EPackage pkg = getEPackage(nsURI); |
| if (pkg!=null) { |
| ModelDecoratorAdapter mda = AdapterUtil.adapt(pkg, ModelDecoratorAdapter.class); |
| if (mda!=null) |
| return mda.getModelDecorator(); |
| } |
| return null; |
| } |
| |
| /** |
| * Look up the ModelDecorator from the given feature by using that feature's namespace. |
| * |
| * @param feature |
| * @return the ModelDecorator that contains the given feature or null if the feature |
| * is not defined. |
| */ |
| public static ModelDecorator getModelDecorator(EStructuralFeature feature) { |
| String nsURI = ExtendedMetaData.INSTANCE.getNamespace(feature); |
| return getModelDecorator(nsURI); |
| } |
| |
| /** |
| * Add the given EPackage to the list of related packages. |
| * See the ModelDecorator(EPackage) constructor |
| * |
| * @param pkg |
| */ |
| public void addRelatedEPackage(EPackage pkg) { |
| if (pkg!=ePackage && !getRelatedEPackages().contains(pkg)) |
| getRelatedEPackages().add(pkg); |
| } |
| |
| /** |
| * Return the list of related EPackages. |
| * See the ModelDecorator(EPackage) constructor |
| * |
| * @return a list of EPackage objects. The list may be empty. |
| */ |
| public List<EPackage> getRelatedEPackages() { |
| if (relatedEPackages==null) { |
| relatedEPackages = new ArrayList<EPackage>(); |
| } |
| return relatedEPackages; |
| } |
| |
| /** |
| * Create our dynamic EPackage and add it to our private ResourceSet. |
| * |
| * @param name |
| * @param nsPrefix |
| * @param nsURI |
| * @return the newly created dynamic EPackage |
| */ |
| private EPackage createEPackage(String name, String nsPrefix, String nsURI) { |
| ePackage = theCoreFactory.createEPackage(); |
| ePackage.setName(name); |
| ePackage.setNsPrefix(nsPrefix); |
| ePackage.setNsURI(nsURI); |
| |
| getResourceSet(); |
| resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("*", new XMLResourceFactoryImpl()); //$NON-NLS-1$ |
| resourceSet.getPackageRegistry().put(nsURI, ePackage); |
| |
| return ePackage; |
| } |
| |
| /** |
| * Parse a type string to return the list of supertypes. The type string is in |
| * the form |
| * |
| * "classname:supertype1,supertype2,..." |
| * |
| * this method returns the list of strings containing "supertype1", "supertype2", etc. |
| * |
| * @param type |
| * @return a list of strings or an empty list of no supertypes found. |
| */ |
| private List<String> getSuperTypes(String type) { |
| List<String> supertypes = new ArrayList<String>(); |
| if (type!=null && type.contains(":")) { //$NON-NLS-1$ |
| String a[] = type.split(":"); //$NON-NLS-1$ |
| if (a.length>1) { |
| a = a[1].split(","); //$NON-NLS-1$ |
| } |
| else { |
| a = a[0].split(","); //$NON-NLS-1$ |
| } |
| for (int i=0; i<a.length; ++i) { |
| supertypes.add(a[i]); |
| } |
| } |
| return supertypes; |
| } |
| |
| /** |
| * Parse a type string to return the subclass name. The type string is in |
| * the form |
| * |
| * "classname:supertype1,supertype2,..." |
| * |
| * this method returns the "classname" portion. |
| * |
| * @param type |
| * @return a string containing only the type name |
| */ |
| private String getType(String type) { |
| if (type!=null && type.contains(":")) { //$NON-NLS-1$ |
| return type.split(":")[0]; //$NON-NLS-1$ |
| } |
| return type; |
| } |
| |
| /** |
| * Search for the EClassifier whose name is the type string. |
| * |
| * @param type - a type name string that may contain additional supertype names. |
| * @see getType(String) |
| * @return the EClassifier or null if not found. |
| */ |
| public EClassifier getEClassifier(String type) { |
| type = getType(type); |
| EClassifier eClassifier = ePackage.getEClassifier(type); |
| if (eClassifier != null) { |
| return eClassifier; |
| } |
| for (EPackage p : getRelatedEPackages()) { |
| eClassifier = p.getEClassifier(getType(type)); |
| if (eClassifier != null) { |
| return eClassifier; |
| } |
| } |
| Assert.isTrue(eClassifier==null); |
| return null; |
| } |
| |
| /** |
| * Create a dynamic EClassifier from a type string. This will create a new |
| * EEnum if the supertype is an EEnum, or a new EDataType if the supertype |
| * is an EDataType. If no supertype is given, an EClass is created instead. |
| * |
| * @param type - a type name string that may contain additional supertype names. |
| * @see getType(String) |
| * @return the EClassifier. |
| */ |
| public EClassifier createEClassifier(String type) { |
| EClassifier eClassifier = getEClassifier(type); |
| if (eClassifier!=null) |
| return eClassifier; |
| |
| EClassifier eDataType = null; |
| for (String st : getSuperTypes(type)) { |
| EClassifier ec = findEClassifier(st); |
| if (EDataType.class.isAssignableFrom( ec.getInstanceClass() )) { |
| eDataType = ec; |
| break; |
| } |
| } |
| |
| if (eDataType==null) { |
| if (EDataTypeConversionFactory.isFactoryFor(getType(type))) |
| return createEDataType(type); |
| return createEClass(type); |
| } |
| |
| if (EEnum.class.isAssignableFrom(eDataType.getInstanceClass())) |
| eClassifier = theCoreFactory.createEEnum(); |
| else |
| eClassifier = theCoreFactory.createEDataType(); |
| |
| eClassifier.setName(getType(type)); |
| ePackage.getEClassifiers().add(eClassifier); |
| |
| return eClassifier; |
| } |
| |
| /** |
| * Create a dynamic EEnum literal value for an EEnum type name. |
| * |
| * @param name - name of the enum literal |
| * @param owningtype - the EEnum type name that owns the newly created literal. |
| * @return a new EEnum literal. |
| */ |
| public EEnumLiteral createEEnumLiteral(String name, String owningtype) { |
| |
| EClassifier eClassifier = getEClassifier(owningtype); |
| if (eClassifier==null) { |
| eClassifier = createEClassifier(owningtype + ":EEnum"); //$NON-NLS-1$ |
| } |
| if (!(eClassifier instanceof EEnum)) |
| return null; |
| |
| return createEEnumLiteral(name, (EEnum)eClassifier); |
| } |
| |
| /** |
| * Create a dynamic EEnum literal value for an EEnum type. |
| * |
| * @param name - name of the enum literal |
| * @param eEnum - the EEnum type that owns the newly created literal. |
| * @return a new EEnum literal |
| */ |
| public EEnumLiteral createEEnumLiteral(String name, EEnum eEnum) { |
| |
| EEnumLiteral literal = theCoreFactory.createEEnumLiteral(); |
| literal.setLiteral(name); |
| literal.setName(name.toUpperCase()); |
| literal.setValue(eEnum.getELiterals().size()); |
| |
| eEnum.getELiterals().add(literal); |
| |
| return literal; |
| } |
| |
| /** |
| * Search for the EDataType whose name is the type string. |
| * |
| * @param type - name of an EDataType |
| * @return the EDatatype or null if not found |
| */ |
| public EDataType getEDataType(String type) { |
| EClassifier eClassifier = getEClassifier(type); |
| if (eClassifier instanceof EDataType) { |
| return (EDataType) eClassifier; |
| } |
| Assert.isTrue(eClassifier==null); |
| return null; |
| } |
| |
| /** |
| * Create a dynamic EDataType from a type string. |
| * |
| * @param type - name of the EDataType to create. |
| * @return a new EDataType. |
| */ |
| public EDataType createEDataType(String type) { |
| type = getType(type); |
| EDataType eDataType = getEDataType(type); |
| if (eDataType!=null) |
| return eDataType; |
| |
| eDataType = theCoreFactory.createEDataType(); |
| eDataType.setName(type); |
| |
| ePackage.getEClassifiers().add(eDataType); |
| // make this look like a DocumentRoot so that it can be added |
| // to the containing object's "anyType" feature. |
| ExtendedMetaData.INSTANCE.setName(eDataType, ""); //$NON-NLS-1$ |
| EAnnotation ea = theCoreFactory.createEAnnotation(); |
| ea.setEModelElement(eDataType); |
| ea.setSource(EDataTypeConversionFactory.DATATYPE_CONVERSION_FACTORY_URI); |
| ConversionDelegate cd = EDataTypeConversionFactory.INSTANCE.createConversionDelegate(eDataType); |
| if (cd!=null) { |
| Object value = cd.createFromString(""); //$NON-NLS-1$ |
| eDataType.setInstanceClass(value.getClass()); |
| } |
| eDataType.getEAnnotations().add(ea); |
| |
| return eDataType; |
| } |
| |
| /** |
| * Search for the EClass whose name is the type string. |
| * |
| * @param type - name of an EClass |
| * @return the EClass or null if not found |
| */ |
| public EClass getEClass(String type) { |
| EClassifier eClassifier = getEClassifier(type); |
| if (eClassifier instanceof EClass) { |
| return (EClass) eClassifier; |
| } |
| Assert.isTrue(eClassifier==null); |
| return null; |
| } |
| |
| /** |
| * Create a dynamic EClass from a type string. |
| * |
| * @param type - a type name string that may contain additional supertype names. |
| * @see getType(String) |
| * @return the EClass. |
| */ |
| public EClass createEClass(String type) { |
| EClass eClass = getEClass(type); |
| if (eClass!=null) |
| return eClass; |
| |
| eClass = theCoreFactory.createEClass(); |
| eClass.setName(getType(type)); |
| eClass.getESuperTypes().add(XMLTypePackage.eINSTANCE.getAnyType()); |
| |
| ePackage.getEClassifiers().add(eClass); |
| for (String st : getSuperTypes(type)) { |
| EClassifier eClassifier = findEClassifier(st); |
| if (eClassifier instanceof EClass) |
| eClass.getESuperTypes().add((EClass) eClassifier); |
| } |
| |
| // make this class look like a DocumentRoot so that it can be added |
| // to the containing object's "anyType" feature. |
| ExtendedMetaData.INSTANCE.setName(eClass, ""); //$NON-NLS-1$ |
| eClass.setInstanceClass(AnyType.class); |
| |
| return eClass; |
| } |
| |
| public EStructuralFeature getEStructuralFeature(EObject object, String name) { |
| // first check the object's EClass for the feature name |
| EClass eClass = object.eClass(); |
| if (eClass!=null) { |
| EStructuralFeature feature = eClass.getEStructuralFeature(name); |
| if (feature!=null) |
| return feature; |
| } |
| // if not found, search our dynamic EPackages for a class with the same name |
| // and look for the feature name in there |
| if (object instanceof ExtensionAttributeValue) { |
| object = object.eContainer(); |
| } |
| String type = object.eClass().getName(); |
| eClass = getEClass(type); |
| if (eClass!=null) { |
| for (EStructuralFeature feature : eClass.getEAllStructuralFeatures()) { |
| if (name.equals(feature.getName())) |
| return feature; |
| if (name.equals(ExtendedMetaData.INSTANCE.getName(feature))) |
| return feature; |
| } |
| } |
| return findEStructuralFeatureInDocumentRoot(name); |
| } |
| |
| /** |
| * Search for an EAttribute with the given name in the specified EClass. |
| * |
| * @param name - name of the attribute to search for. |
| * @param type - the data type of the attribute. |
| * @param owningtype - name of the EClass that contains the attribute. |
| * @return the EAttribute or null if not found. |
| */ |
| public EAttribute getEAttribute(String name, String type, String owningtype) { |
| EStructuralFeature feature = findEStructuralFeatureInDocumentRoot(name); |
| if (feature instanceof EAttribute) { |
| // if (type!=null) |
| // Assert.isTrue(type.equals(((EAttribute) feature).getEType().getName()) ); |
| return (EAttribute) feature; |
| } |
| |
| EClass eClass = getEClass(owningtype); |
| if (eClass!=null) { |
| // the EClass already exists in our EPackage: check if the named feature was already created |
| feature = eClass.getEStructuralFeature(name); |
| if (feature instanceof EAttribute) { |
| if (type!=null) { |
| Assert.isTrue(type.equals(((EAttribute) feature).getEType().getName()) ); |
| } |
| return (EAttribute) feature; |
| } |
| Assert.isTrue(feature==null); |
| return null; |
| } |
| else { |
| // if not, check other related packages including the Bpmn2Package |
| EClassifier ec = findEClassifier(owningtype); |
| if ( !isValid(ec) && ec instanceof EClass ) { |
| // the EClass does not belong to us, but if the feature exists in that EClass, use it. |
| feature = ((EClass)ec).getEStructuralFeature(name); |
| if (feature instanceof EAttribute) { |
| return (EAttribute) feature; |
| } |
| } |
| } |
| Assert.isTrue(eClass==null); |
| return null; |
| } |
| |
| /** |
| * Create a dynamic EAttribute of a given type, and add it the specified EClass. |
| * If the specified EClass does not exist, it will be created. |
| * |
| * @param name - name of the dynamic attribute. |
| * @param type - type of the attribute. |
| * @param owningtype - the name of the EClass that owns this attribute. |
| * @param defaultValue - initial default value for the attribute. |
| * @return a new EAttribute |
| */ |
| public EAttribute createEAttribute(String name, String type, String owningtype, String defaultValue) { |
| EAttribute eAttribute = getEAttribute(name,type,owningtype); |
| if (eAttribute!=null) |
| return eAttribute; |
| |
| if (type==null) |
| type = "EString"; //$NON-NLS-1$ |
| |
| // if the class type does not exist, create it in this package |
| EClassifier eClassifier = findEClassifier(type); |
| if (eClassifier==null) { |
| eClassifier = createEClassifier(type); |
| } |
| |
| // check if owning class is in this package |
| EClass eClass = getEClass(owningtype); |
| if (eClass==null) { |
| // if not, check other related packages including the Bpmn2Package |
| EClassifier ec = findEClassifier(owningtype); |
| if ( !isValid(ec) ) { |
| ec = createEClass(owningtype); |
| } |
| if (ec instanceof EClass) |
| eClass = (EClass) ec; |
| } |
| Assert.isNotNull(eClass); |
| |
| eAttribute = theCoreFactory.createEAttribute(); |
| eAttribute.setName(name); |
| eAttribute.setChangeable(true); |
| eAttribute.setUnsettable(true); |
| eAttribute.setEType(eClassifier); |
| |
| eClass.getEStructuralFeatures().add(eAttribute); |
| |
| ExtendedMetaData.INSTANCE.setNamespace(eAttribute, ePackage.getNsURI()); |
| ExtendedMetaData.INSTANCE.setFeatureKind(eAttribute, ExtendedMetaData.ATTRIBUTE_FEATURE); |
| ExtendedMetaData.INSTANCE.setName(eAttribute, name); |
| |
| if (eClassifier instanceof EEnum) { |
| if (defaultValue!=null) { |
| boolean setDefault = true; |
| String values[]; |
| if (defaultValue.contains(",")) //$NON-NLS-1$ |
| values = defaultValue.split(","); //$NON-NLS-1$ |
| else |
| values = defaultValue.split(" "); //$NON-NLS-1$ |
| for (String v : values) { |
| if (setDefault) { |
| eAttribute.setDefaultValue(v); |
| setDefault = false; |
| } |
| createEEnumLiteral(v, (EEnum)eClassifier); |
| } |
| } |
| } |
| else if (eClassifier instanceof EDataType) { |
| if (defaultValue!=null) { |
| eAttribute.setDefaultValue(defaultValue); |
| } |
| } |
| |
| return eAttribute; |
| } |
| |
| /** |
| * Search for an EReference with the given name in the specified EClass. |
| * |
| * @param name - name of the reference to search for. |
| * @param type - the data type of the reference. |
| * @param owningtype - name of the EClass that contains the reference. |
| * @param containment - if true, the EReference is a containment feature; if false, it is a reference. |
| * @param many - if true, the EReference is a list; if false, it is a single value. |
| * @return the EReference or null if not found. |
| */ |
| public EReference getEReference(String name, String type, String owningtype, boolean containment, boolean many) { |
| EStructuralFeature feature = findEStructuralFeatureInDocumentRoot(name); |
| if (feature instanceof EReference) { |
| if (type!=null) |
| Assert.isTrue(type.equals(((EReference) feature).getEType().getName()) ); |
| Assert.isTrue(containment == ((EReference) feature).isContainment()); |
| Assert.isTrue(many == ((EReference) feature).isMany()); |
| return (EReference) feature; |
| } |
| EClass eClass = getEClass(owningtype); |
| if (eClass != null) { |
| // the EClass already exists in our EPackage: check if the named feature was already created |
| feature = eClass.getEStructuralFeature(name); |
| if (feature instanceof EReference) { |
| EClassifier eClassifier = findEClassifier(type); |
| Assert.isTrue(eClassifier == feature.getEType()); |
| Assert.isTrue(containment == ((EReference) feature) |
| .isContainment()); |
| Assert.isTrue(many ? ((EReference) feature).getUpperBound() == EStructuralFeature.UNBOUNDED_MULTIPLICITY |
| : true); |
| return (EReference) feature; |
| } |
| Assert.isTrue(feature == null); |
| return null; |
| } |
| else { |
| // if not, check other related packages including the Bpmn2Package |
| EClassifier ec = findEClassifier(owningtype); |
| if ( !isValid(ec) && ec instanceof EClass ) { |
| // the EClass does not belong to us, but if the feature exists in that EClass, use it. |
| feature = ((EClass)ec).getEStructuralFeature(name); |
| if (feature instanceof EReference) { |
| return (EReference) feature; |
| } |
| } |
| } |
| Assert.isTrue(eClass==null); |
| return null; |
| } |
| |
| /** |
| * Create a new EReference with the given name in the specified EClass. |
| * If the specified EClass does not exist, it will be created. |
| * |
| * @param name - name of the reference to create. |
| * @param type - the data type of the reference. |
| * @param owningtype - name of the EClass that contains the reference. |
| * @param containment - if true, the EReference is a containment feature; if false, it is a reference. |
| * @param many - if true, the EReference is a list; if false, it is a single value. |
| * @return a new EReference. |
| */ |
| public EReference createEReference(String name, String type, String owningtype, boolean containment, boolean many) { |
| EReference eReference = getEReference(name,type,owningtype,containment,many); |
| if (eReference!=null) |
| return eReference; |
| |
| // if the class type does not exist, create it in this package |
| EClassifier eClassifier = findEClassifier(type); |
| if (eClassifier==null) { |
| eClassifier = createEClass(type); |
| } |
| |
| eReference = theCoreFactory.createEReference(); |
| eReference.setName(name); |
| eReference.setChangeable(true); |
| eReference.setUnsettable(true); |
| eReference.setUnique(true); |
| eReference.setContainment(containment); |
| if (many) |
| eReference.setUpperBound(EStructuralFeature.UNBOUNDED_MULTIPLICITY); |
| eReference.setEType(eClassifier); |
| |
| // check if owning class is in this package |
| EClass eClass = getEClass(owningtype); |
| if (eClass==null) { |
| // if not, check other related packages |
| EClassifier ec = findEClassifier(owningtype); |
| if ( !isValid(ec) ) { |
| ec = createEClass(owningtype); |
| } |
| if (ec instanceof EClass) |
| eClass = (EClass) ec; |
| } |
| Assert.isNotNull(eClass); |
| eClass.getEStructuralFeatures().add(eReference); |
| |
| ExtendedMetaData.INSTANCE.setNamespace(eReference, ePackage.getNsURI()); |
| ExtendedMetaData.INSTANCE.setFeatureKind(eReference, ExtendedMetaData.ELEMENT_FEATURE); |
| ExtendedMetaData.INSTANCE.setName(eReference, name); |
| |
| return eReference; |
| } |
| |
| /** |
| * Set an EAnnotation that represents a human readable label for the given named model element. |
| * |
| * @param element - the named element to be decorated |
| * @param label - the label string |
| */ |
| public static void setLabel(EModelElement element, String label) { |
| // FIXME: we can only decorate dynamic EClass objects. |
| // Figure out how to do this for EClasses that are defined in other models. |
| if (element instanceof EReference) { |
| EReference ref = (EReference) element; |
| EClassifier ec = ref.getEType(); |
| if (isValid(ec.getEPackage())) |
| element = ec; |
| } |
| EAnnotation ea = element.getEAnnotation(DECORATOR_URI); |
| if (label!=null && !label.isEmpty()) { |
| if (ea==null) { |
| ea = theCoreFactory.createEAnnotation(); |
| ea.setEModelElement(element); |
| ea.setSource(DECORATOR_URI); |
| } |
| ea.getDetails().put("label", label); //$NON-NLS-1$ |
| } |
| else { |
| if (ea!=null) { |
| element.getEAnnotations().remove(ea); |
| EcoreUtil.delete(ea); |
| } |
| } |
| } |
| |
| /** |
| * Return the label string for the given named model element. |
| * |
| * @param element - the named element. |
| * @return a text string or null if not set. |
| */ |
| public static String getLabel(EModelElement element) { |
| EAnnotation ea = element.getEAnnotation(DECORATOR_URI); |
| if (ea!=null) { |
| String label = ea.getDetails().get("label"); //$NON-NLS-1$ |
| return label; |
| } |
| return null; |
| } |
| |
| /** |
| * Check if the given EClassifier is owned by this ModelDecorator. |
| * The requested element can be either in our dynamic EPackage or in a related package. |
| * |
| * @param eClassifier - the requested element. |
| * @return true if the EClassifier is managed by us, false if not. |
| */ |
| public boolean isValid(EClassifier eClassifier) { |
| EPackage p = eClassifier==null ? null : eClassifier.getEPackage(); |
| return eClassifier!=null && |
| (p == ePackage || getRelatedEPackages().contains(p)); |
| } |
| |
| public static boolean isValid(EPackage pkg) { |
| return pkg!=null && |
| pkg != EcorePackage.eINSTANCE && |
| pkg != Bpmn2Package.eINSTANCE && |
| pkg != BpmnDiPackage.eINSTANCE && |
| pkg != DcPackage.eINSTANCE && |
| pkg != DiPackage.eINSTANCE; |
| } |
| |
| /** |
| * Search for an EClassifier with the given name. The search order is as follows: |
| * 1. our own dynamic EPackage |
| * 2. any related packages |
| * 3. the EcorePackage |
| * 4. the BPMN2 packages, including BPMNDI, DI and DC |
| * |
| * @param type - name of the EClassifier to search for. |
| * @return - an EClassifier if found or null if not found. |
| */ |
| public EClassifier findEClassifier(String type) { |
| // parse out just the class type, excluding super types |
| if (type==null) |
| return null; |
| |
| type = getType(type); |
| EClassifier eClassifier = null; |
| |
| if (ePackage!=null) { |
| eClassifier = ePackage.getEClassifier(type); |
| if (eClassifier!=null) |
| return eClassifier; |
| eClassifier = findEClassifierInDocumentRoot(ePackage,type); |
| if (eClassifier!=null) |
| return eClassifier; |
| } |
| for (EPackage pkg : getRelatedEPackages()) { |
| eClassifier = pkg.getEClassifier(type); |
| if (eClassifier!=null) |
| return eClassifier; |
| eClassifier = findEClassifierInDocumentRoot(pkg,type); |
| if (eClassifier!=null) |
| return eClassifier; |
| } |
| |
| return findEClassifier(null,type); |
| } |
| |
| public EStructuralFeature findEStructuralFeatureInDocumentRoot(String name) { |
| if (name==null) |
| return null; |
| |
| EStructuralFeature feature = null; |
| |
| if (ePackage!=null) { |
| feature = findEStructuralFeatureInDocumentRoot(ePackage,name); |
| if (feature!=null) |
| return feature; |
| } |
| for (EPackage pkg : getRelatedEPackages()) { |
| feature = findEStructuralFeatureInDocumentRoot(pkg,name); |
| if (feature!=null) |
| return feature; |
| } |
| |
| feature = findEStructuralFeatureInDocumentRoot(Bpmn2Package.eINSTANCE, name); |
| if (feature!=null) |
| return feature; |
| |
| return null; |
| } |
| |
| /** |
| * Search for an EClassifier with the given name. The search order is as follows: |
| * 1. the specified EPackage, if not null |
| * 2. the EcorePackage |
| * 3. the BPMN2 packages, including BPMNDI, DI and DC |
| * |
| * @param pkg - an optional EPackage to search. |
| * @param type - name of the EClassifier to search for. |
| * @return - an EClassifier if found or null if not found. |
| */ |
| public static EClassifier findEClassifier(EPackage pkg, String type) { |
| if (type==null) { |
| return null; |
| } |
| |
| EClassifier eClassifier = null; |
| if (pkg!=null) { |
| eClassifier = pkg.getEClassifier(type); |
| if (eClassifier!=null) |
| return eClassifier; |
| eClassifier = findEClassifierInDocumentRoot(pkg,type); |
| if (eClassifier!=null) |
| return eClassifier; |
| } |
| |
| eClassifier = EcorePackage.eINSTANCE.getEClassifier(type); |
| if (eClassifier!=null) |
| return eClassifier; |
| |
| eClassifier = Bpmn2Package.eINSTANCE.getEClassifier(type); |
| if (eClassifier!=null) |
| return eClassifier; |
| eClassifier = findEClassifierInDocumentRoot(Bpmn2Package.eINSTANCE,type); |
| if (eClassifier!=null) |
| return eClassifier; |
| |
| eClassifier = BpmnDiPackage.eINSTANCE.getEClassifier(type); |
| if (eClassifier!=null) |
| return eClassifier; |
| eClassifier = findEClassifierInDocumentRoot(BpmnDiPackage.eINSTANCE,type); |
| if (eClassifier!=null) |
| return eClassifier; |
| |
| eClassifier = DiPackage.eINSTANCE.getEClassifier(type); |
| if (eClassifier!=null) |
| return eClassifier; |
| |
| eClassifier = DcPackage.eINSTANCE.getEClassifier(type); |
| if (eClassifier!=null) |
| return eClassifier; |
| |
| return null; |
| } |
| |
| /** |
| * Search for an EClassifier with the given name as an element in the DocumentRoot of |
| * the given EPackage. |
| * |
| * @param pkg - the EPackage to search. |
| * @param name - name of the EClassifier to search for. |
| * @return - an EClassifier if found or null if not found. |
| */ |
| private static EClassifier findEClassifierInDocumentRoot(EPackage pkg, String name) { |
| EStructuralFeature feature = findEStructuralFeatureInDocumentRoot(pkg, name); |
| if (feature!=null) |
| return feature.getEType(); |
| return null; |
| } |
| |
| private static EStructuralFeature findEStructuralFeatureInDocumentRoot(EPackage pkg, String name) { |
| try { |
| EClass docRoot = (EClass)pkg.getEClassifier("DocumentRoot"); //$NON-NLS-1$ |
| if (docRoot==null) { |
| docRoot = ExtendedMetaData.INSTANCE.getDocumentRoot(pkg); |
| } |
| if (docRoot!=null) { |
| for (EStructuralFeature feature : docRoot.getEAllStructuralFeatures()) { |
| if (feature.getEContainingClass().getEPackage()==pkg) { |
| if (name.equals(feature.getName())) |
| return feature; |
| if (name.equals(ExtendedMetaData.INSTANCE.getName(feature))) |
| return feature; |
| } |
| } |
| } |
| } |
| catch (Exception e) { |
| } |
| return null; |
| } |
| |
| private static EStructuralFeature getAnyAttributeFeature(EObject object) { |
| EStructuralFeature anyAttribute = null; |
| if (object!=null) { |
| EClass eclass = null; |
| if (object instanceof EClass) |
| eclass = (EClass)object; |
| else |
| eclass = object.eClass(); |
| anyAttribute = eclass.getEStructuralFeature("anyAttribute"); //$NON-NLS-1$ |
| } |
| return anyAttribute; |
| } |
| |
| /** |
| * Return the feature with the given name in the specified object's "anyAttribute" feature map. |
| * |
| * @param object - the EObject to search. |
| * @param name - name of the feature to search for. |
| * @return an EStructuralFeature if found or null if not found. |
| */ |
| public static EStructuralFeature getAnyAttribute(EObject object, String name) { |
| EStructuralFeature anyAttribute = getAnyAttributeFeature(object); |
| if (anyAttribute!=null && object.eGet(anyAttribute) instanceof BasicFeatureMap) { |
| BasicFeatureMap map = (BasicFeatureMap)object.eGet(anyAttribute); |
| for (Entry entry : map) { |
| EStructuralFeature feature = entry.getEStructuralFeature(); |
| if (feature.getName().equals(name)) |
| return feature; |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Return all of the features in the specified object's "anyAttribute" feature map. |
| * |
| * @param object - the EObject to search. |
| * @return a list of EStructuralFeatures if found or an empty list if not found. |
| */ |
| public static List<EStructuralFeature> getAnyAttributes(EObject object) { |
| List<EStructuralFeature> list = new ArrayList<EStructuralFeature>(); |
| EStructuralFeature anyAttribute = getAnyAttributeFeature(object); |
| if (anyAttribute!=null && object.eGet(anyAttribute) instanceof BasicFeatureMap) { |
| BasicFeatureMap map = (BasicFeatureMap)object.eGet(anyAttribute); |
| for (Entry entry : map) { |
| EStructuralFeature feature = entry.getEStructuralFeature(); |
| list.add(feature); |
| } |
| } |
| return list; |
| } |
| |
| /** |
| * Create a new attribute in the specified object's "anyAttribute" feature map. |
| * The attribute will be assigned the given namespace, name, type and initial value. |
| * |
| * @param object - the EObject to be decorated. |
| * @param namespace - namespace of the new attribute. |
| * @param name - name of the new extension attribute. |
| * @param type - data type of the attribute. |
| * @param value - initial value of the attribute. |
| * @return a new EAttribute |
| */ |
| @SuppressWarnings("unchecked") |
| public EStructuralFeature addAnyAttribute(EObject object, String namespace, String name, String type, Object value) { |
| EStructuralFeature attr = null; |
| EClass eclass; |
| if (object instanceof EClass) { |
| eclass = (EClass)object; |
| object = ExtendedPropertiesAdapter.getDummyObject(eclass); |
| } |
| else |
| eclass = object.eClass(); |
| EStructuralFeature anyAttribute = getAnyAttributeFeature(object); |
| List<BasicFeatureMap.Entry> anyMap = (List<BasicFeatureMap.Entry>)object.eGet(anyAttribute); |
| if (anyMap==null) |
| return null; |
| for (BasicFeatureMap.Entry fe : anyMap) { |
| if (fe.getEStructuralFeature() instanceof EAttributeImpl) { |
| EAttributeImpl a = (EAttributeImpl) fe.getEStructuralFeature(); |
| if (namespace.equals(a.getExtendedMetaData().getNamespace()) && name.equals(a.getName())) { |
| attr = a; |
| break; |
| } |
| } |
| } |
| |
| // this featuremap can only hold attributes, not elements |
| if (type==null) |
| type = "E" + value.getClass().getSimpleName(); //$NON-NLS-1$ |
| EPackage pkg = ModelDecorator.getEPackage(namespace); |
| EDataType eDataType = (EDataType)ModelDecorator.findEClassifier(pkg, type);//(EDataType)EcorePackage.eINSTANCE.getEClassifier(type); |
| if (eDataType!=null) { |
| // value can not be null - use the default value instead |
| if (value==null) { |
| try { |
| value = eDataType.getEPackage().getEFactoryInstance().createFromString(eDataType,""); //$NON-NLS-1$ |
| } |
| catch (Exception e) { |
| // data type converter can't handle empty strings, |
| // try creating an empty object using default constructor |
| try { |
| value = eDataType.getInstanceClass().newInstance(); |
| } catch (Exception e1) { |
| e1.printStackTrace(); |
| } |
| } |
| } |
| if (attr==null) { |
| attr = createEAttribute(name, type, eclass.getName(), null); |
| anyMap.add( FeatureMapUtil.createEntry(attr, value) ); |
| } |
| else { |
| EClassifier dt = attr.getEType(); |
| if (dt==null || !eDataType.getInstanceClass().isAssignableFrom(dt.getInstanceClass())) |
| throw new IllegalArgumentException( |
| NLS.bind( |
| Messages.ModelUtil_Illegal_Value, |
| new Object[] { |
| object.eClass().getName(), |
| attr.getName(), |
| attr.getEType().getName(), |
| value.toString() |
| } |
| ) |
| ); |
| anyMap.add( FeatureMapUtil.createEntry(attr, value) ); |
| } |
| } |
| else { |
| if (attr==null) { |
| attr = createEAttribute(name, type, eclass.getName(), null); |
| } |
| if (value==null) { |
| if (attr.getEType() instanceof EDataType) { |
| eDataType = (EDataType) attr.getEType(); |
| value = eDataType.getEPackage().getEFactoryInstance().createFromString(eDataType,""); //$NON-NLS-1$ |
| } |
| } |
| anyMap.add( FeatureMapUtil.createEntry(attr, value) ); |
| } |
| return attr; |
| } |
| |
| /** |
| * Create a new attribute in the specified object's "anyAttribute" feature map. |
| * The attribute will be assigned the namespace from our dynamic EPackage. |
| * |
| * @param object - the EObject to be decorated. This SHOULD be a BaseElement. |
| * @param name - name of the new extension attribute. |
| * @param type - data type of the attribute. |
| * @param value - initial value of the attribute. |
| * @return a new EAttribute |
| */ |
| public EStructuralFeature addAnyAttribute(EObject object, String name, String type, Object value) { |
| EPackage pkg = object.eClass().getEPackage(); |
| String nsURI = pkg.getNsURI(); |
| return addAnyAttribute(object, nsURI, name, type, value); |
| } |
| |
| /** |
| * Create a new extension element in the specified BaseElement's extension values container. |
| * |
| * @param object - the EObject to be decorated. This SHOULD be a BaseElement. |
| * @param feature - name of the new extension element. |
| * @param value - value assigned to the new element. |
| */ |
| public static void addExtensionAttributeValue(EObject object, EStructuralFeature feature, Object value) { |
| addExtensionAttributeValue(object, feature, value, -1, false); |
| } |
| |
| /** |
| * Create a new extension element in the specified BaseElement's extension values container. |
| * |
| * @param object - the EObject to be decorated. This SHOULD be a BaseElement. |
| * @param feature - name of the new extension element. |
| * @param value - value assigned to the new element. |
| * @param delay - if true, use an InsertionAdapter to set the feature value, otherwise set it immediately. |
| */ |
| public static void addExtensionAttributeValue(EObject object, EStructuralFeature feature, Object value, boolean delay) { |
| addExtensionAttributeValue(object, feature, value, -1, delay); |
| } |
| |
| /** |
| * Create a new extension element in the specified BaseElement's extension values container. |
| * |
| * @param object - the EObject to be decorated. This SHOULD be a BaseElement. |
| * @param feature - name of the new extension element. |
| * @param value - value assigned to the new element. |
| * @param index - if the element is a list, the list index for the value. |
| * @param delay - if true, use an InsertionAdapter to set the feature value, otherwise set it immediately. |
| */ |
| @SuppressWarnings("unchecked") |
| public static void addExtensionAttributeValue(EObject object, EStructuralFeature feature, Object value, int index, boolean delay) { |
| if (object instanceof ExtensionAttributeValue) |
| object = object.eContainer(); |
| EStructuralFeature evf = object.eClass().getEStructuralFeature("extensionValues"); //$NON-NLS-1$ |
| if (evf==null) { |
| Activator.logError(new Exception("Object type "+object.eClass().getName()+" is not a BaseElement")); |
| return; |
| } |
| EList<EObject> list = (EList<EObject>)object.eGet(evf); |
| |
| if (list.size()==0) { |
| ExtensionAttributeValue newItem = Bpmn2ModelerFactory.create(ExtensionAttributeValue.class); |
| ModelUtil.setID(newItem); |
| FeatureMap map = newItem.getValue(); |
| map.add(feature, value); |
| if (delay) { |
| InsertionAdapter.add(object, feature, (EObject)value); |
| } |
| else { |
| list.add(newItem); |
| } |
| } |
| else { |
| ExtensionAttributeValue oldItem = (ExtensionAttributeValue) list.get(0); |
| if (delay) { |
| InsertionAdapter.add(object, feature, (EObject)value); |
| } |
| else { |
| FeatureMap map = oldItem.getValue(); |
| // treat unspecified multiplicity as unbounded |
| // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=448073 |
| if (!(feature.isMany() || feature.getUpperBound()==ETypedElement.UNSPECIFIED_MULTIPLICITY)) { |
| // only one of these features is allowed: remove existing one(s) |
| for (int i=0; i<map.size(); ++i) { |
| Entry entry = map.get(i); |
| if (entry.getEStructuralFeature().getName().equals(feature.getName())) { |
| map.remove(i--); |
| } |
| } |
| map.add(feature, value); |
| } |
| else if (index>=0){ |
| } |
| else { |
| map.add(feature, value); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Return a list of all extension elements in the BaseElement's extension values container. |
| * |
| * @param be - the EObject to search. This SHOULD be a BaseElement. |
| * @return a list of all extension elements or an empty list if none found. |
| */ |
| public static List<ExtensionAttributeValue> getExtensionAttributeValues(EObject be) { |
| if (be instanceof Participant) { |
| final Participant participant = (Participant) be; |
| if (participant.getProcessRef() == null) { |
| if (participant.eContainer() instanceof Collaboration) { |
| Collaboration collab = (Collaboration) participant.eContainer(); |
| if (collab.eContainer() instanceof Definitions) { |
| final Definitions definitions = ModelUtil.getDefinitions(collab); |
| |
| TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(definitions.eResource()); |
| |
| domain.getCommandStack().execute(new RecordingCommand(domain) { |
| @Override |
| protected void doExecute() { |
| Process process = Bpmn2ModelerFactory.create(Process.class); |
| participant.setProcessRef(process); |
| definitions.getRootElements().add(process); |
| ModelUtil.setID(process); |
| } |
| |
| }); |
| |
| } |
| } |
| } |
| return participant.getProcessRef().getExtensionValues(); |
| } |
| if (be instanceof BPMNDiagram) { |
| BPMNDiagram diagram = (BPMNDiagram) be; |
| BaseElement bpmnElement = diagram.getPlane().getBpmnElement(); |
| if (bpmnElement instanceof org.eclipse.bpmn2.Process) { |
| return bpmnElement.getExtensionValues(); |
| } |
| } |
| if (be instanceof BaseElement) { |
| return ((BaseElement) be).getExtensionValues(); |
| } |
| |
| return new ArrayList<ExtensionAttributeValue>(); |
| } |
| |
| /** |
| * Return a list of all extension elements in the BaseElement's extension values container |
| * that have the specified java type. |
| * |
| * @param be - the EObject to search. This SHOULD be a BaseElement. |
| * @param clazz - the type of elements to search for. |
| * @return a list of all extension elements or an empty list if none found. |
| */ |
| @SuppressWarnings("unchecked") |
| public static <T> List<T> getAllExtensionAttributeValues(EObject object, Class<T> clazz) { |
| List<T> results = new ArrayList<T>(); |
| |
| if (object!=null) { |
| EStructuralFeature evf = object.eClass().getEStructuralFeature("extensionValues"); //$NON-NLS-1$ |
| EList<ExtensionAttributeValue> list = (EList<ExtensionAttributeValue>)object.eGet(evf); |
| for (ExtensionAttributeValue eav : list) { |
| FeatureMap fm = eav.getValue(); |
| for (Entry e : fm) { |
| if (clazz.isInstance(e.getValue())) { |
| results.add((T)e.getValue()); |
| } |
| } |
| } |
| } |
| return results; |
| } |
| |
| /** |
| * Return a list of Objects that are the values of all extension elements specified by the given feature. |
| * |
| * @param object - the EObject to be searched. This SHOULD be a BaseElement. |
| * @param feature - the EStructuralFeature to search for. |
| * @return a list of Object values for the extension elements. |
| */ |
| public static List<Object> getAllExtensionAttributeValues(EObject object, EStructuralFeature feature) { |
| List<Object> results = new ArrayList<Object>(); |
| |
| if (object!=null) { |
| String name = feature.getName(); |
| EStructuralFeature evf = object.eClass().getEStructuralFeature("extensionValues"); //$NON-NLS-1$ |
| EList<ExtensionAttributeValue> list = (EList<ExtensionAttributeValue>)object.eGet(evf); |
| for (ExtensionAttributeValue eav : list) { |
| FeatureMap fm = eav.getValue(); |
| for (Entry e : fm) { |
| if (e.getEStructuralFeature().getName().equals(name)) { |
| results.add(e.getValue()); |
| } |
| } |
| } |
| } |
| return results; |
| } |
| |
| /** |
| * Search the given object for an extension element by name. |
| * |
| * @param object - the EObject to be searched. This SHOULD be a BaseElement. |
| * @param name - name of the feature to search for. |
| * @return an EStructuralFeature if found, or null if not found. |
| */ |
| @SuppressWarnings("unchecked") |
| public static EStructuralFeature getExtensionAttribute(EObject object, String name) { |
| if (object!=null) { |
| EStructuralFeature evf = object.eClass().getEStructuralFeature("extensionValues"); //$NON-NLS-1$ |
| EList<ExtensionAttributeValue> list = (EList<ExtensionAttributeValue>)object.eGet(evf); |
| for (ExtensionAttributeValue eav : list) { |
| FeatureMap fm = eav.getValue(); |
| for (Entry e : fm) { |
| if (e.getEStructuralFeature().getName().equals(name)) { |
| return e.getEStructuralFeature(); |
| } |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Look up a dynamic feature associated with the given EObject by name. |
| * |
| * @param object - the EObject to check. |
| * @param prefix - a namespace prefix passed in by the XMLHandler - not used here. |
| * @param name - name of the dynamic feature. |
| * @param isElement - true if the feature is an element, false if attribute. |
| * @return an EStructuralFeature if the feature was found, or null if not found. |
| */ |
| public EStructuralFeature getFeature(EObject object, String prefix, String name, boolean isElement) { |
| // search for the object's type in our own package |
| EClass eClass = getEClass(object.eClass().getName()); |
| if (eClass!=null) { |
| // found it! check if it has the requested feature |
| EStructuralFeature feature = eClass.getEStructuralFeature(name); |
| if (feature!=null) { |
| if (isElement) { |
| if (feature instanceof EReference) |
| return feature; |
| } |
| else { |
| if (feature instanceof EAttribute) |
| return feature; |
| } |
| } |
| } |
| object = object.eContainer(); |
| return null; |
| } |
| |
| public EStructuralFeature getFeature(EObject object, String name) { |
| EStructuralFeature feature = getAnyAttribute(object, name); |
| if (feature!=null) |
| return feature; |
| feature = getExtensionAttribute(object, name); |
| if (feature!=null) |
| return feature; |
| |
| return null; |
| } |
| } |