/** * Copyright (c) 2003-2007 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM - Initial API and implementation */ package org.eclipse.emf.ecore.xmi.impl; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.emf.common.notify.Notifier; import org.eclipse.emf.common.util.TreeIterator; 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.EFactory; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EOperation; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EParameter; 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.util.EContentsEList; import org.eclipse.emf.ecore.util.ECrossReferenceEList; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.ecore.util.InternalEList; import org.eclipse.emf.ecore.xmi.XMLResource; public class EMOFHelperImpl extends XMLHelperImpl implements EMOFHandler.Helper { protected EClass propertyClass = null; protected List<EObject> propertyFeatureList = null; protected Set<EObject> objectsWithGenericTypeList = new HashSet<EObject>(); public EMOFHelperImpl(XMLResource resource) { super(resource); packages.put(EcorePackage.eINSTANCE, EMOFExtendedMetaData.EMOF_PACKAGE_NS_PREFIX); } @Override public Object getValue(EObject object, EStructuralFeature feature) { if (feature == EcorePackage.Literals.ESTRUCTURAL_FEATURE__CHANGEABLE) { return ((EStructuralFeature)object).isChangeable() ? Boolean.FALSE : Boolean.TRUE; // EMOF.isReadOnly = !Ecore.changeable } else { return super.getValue(object, feature); } } @Override public void setValue(EObject object, EStructuralFeature feature, Object value, int position) { if (feature == EcorePackage.Literals.ESTRUCTURAL_FEATURE__CHANGEABLE) { ((EStructuralFeature)object).setChangeable(Boolean.FALSE.toString().equals(value)); // Ecore.changeable = !EMOF.isReadOnly } else if (feature == EcorePackage.Literals.ETYPED_ELEMENT__UPPER_BOUND && "*".equals(value)) { ((ETypedElement)object).setUpperBound(-1); } // Don't set the type if it's already set. // else if (feature == EcorePackage.Literals.ETYPED_ELEMENT__ETYPE) { if (((ETypedElement)object).getEType() == null) { super.setValue(object, feature, value, position); } } else if (feature == EcorePackage.Literals.ECLASS__ESUPER_TYPES || feature == EcorePackage.Literals.EOPERATION__EEXCEPTIONS) { // Ignore it if we've already set generic versions of these // if (!objectsWithGenericTypeList.contains(object)) { super.setValue(object, feature, value, position); } } else if (feature == EcorePackage.Literals.ECLASS__EGENERIC_SUPER_TYPES || feature == EcorePackage.Literals.EOPERATION__EGENERIC_EXCEPTIONS) { // Ignore whatever was set before. // if (objectsWithGenericTypeList.add(object)) { ((InternalEList<?>)object.eGet(feature)).clear(); } super.setValue(object, feature, value, position); } else { super.setValue(object, feature, value, position); } } @Override public String getHREF(EObject obj) { String href = super.getHREF(obj); if (href != null && href.startsWith(EMOFExtendedMetaData.ECORE_EDATATYPE_HREF_PREFIX)) { String dataType = href.substring(EMOFExtendedMetaData.ECORE_EDATATYPE_HREF_PREFIX.length()); for (int i = 0; i < EMOFExtendedMetaData.MAPPED_ECORE_EDATATYPES.length; i++) { if (dataType.equals(EMOFExtendedMetaData.MAPPED_ECORE_EDATATYPES[i])) { return EMOFExtendedMetaData.MAPPED_EMOF_EDATATYPE_HREF_PREFIX_2_0 + EMOFExtendedMetaData.MAPPED_EMOF_EDATATYPES[i]; } } return EMOFExtendedMetaData.UNMAPPED_EMOF_EDATATYPE_HREF_PREFIX + dataType; } return href; } @Override public EStructuralFeature getFeature(EClass eClass, String namespaceURI, String name, boolean isElement) { if (eClass == EcorePackage.Literals.EANNOTATION && EMOFExtendedMetaData.EMOF_TAG_ELEMENT.equals(name)) { return EcorePackage.Literals.EANNOTATION__REFERENCES; } else if (EcorePackage.Literals.EMODEL_ELEMENT.isSuperTypeOf(eClass) && EMOFExtendedMetaData.EMOF_OWNED_COMMENT.equals(name)) { return EcorePackage.Literals.EMODEL_ELEMENT__EANNOTATIONS; } for (int i = 0, size = eClass.getFeatureCount(); i < size; ++i) { EStructuralFeature eStructuralFeature = eClass.getEStructuralFeature(i); if (name.equals(extendedMetaData.getName(eStructuralFeature)) && (namespaceURI == null ? extendedMetaData.getNamespace(eStructuralFeature) == null : namespaceURI.equals(extendedMetaData.getNamespace(eStructuralFeature)))) { computeFeatureKind(eStructuralFeature); return eStructuralFeature; } } return null; } @Override public EClassifier getType(EFactory eFactory, String typeName) { EPackage ePackage = eFactory.getEPackage(); if (ePackage == EcorePackage.eINSTANCE) { if (EcorePackage.Literals.ESTRUCTURAL_FEATURE.getName().equals(typeName) || "Property".equals(typeName)) { if (propertyClass == null) { propertyClass = EcoreFactory.eINSTANCE.createEClass(); propertyClass.getESuperTypes().add(EcorePackage.Literals.EREFERENCE); propertyClass.getESuperTypes().add(EcorePackage.Literals.EATTRIBUTE); propertyClass.setName("EMOFProperty"); EPackage propertyPackage = EcoreFactory.eINSTANCE.createEPackage(); propertyPackage.getEClassifiers().add(propertyClass); propertyFeatureList = new ArrayList<EObject>(); } return propertyClass; } else if (EMOFExtendedMetaData.TAG.equals(typeName)) { return EcorePackage.Literals.EANNOTATION; } } return super.getType(eFactory, typeName); } private static final Integer ONE = 1; @Override public EObject createObject(EFactory eFactory, EClassifier type) { if (type == propertyClass && propertyClass != null) { EObject property = propertyClass.getEPackage().getEFactoryInstance().create(propertyClass); property.eSet(EcorePackage.Literals.ETYPED_ELEMENT__LOWER_BOUND, ONE); property.eSet(EcorePackage.Literals.ETYPED_ELEMENT__ORDERED, Boolean.FALSE); propertyFeatureList.add(property); return property; } else if (EcorePackage.Literals.EANNOTATION == type) { EAnnotation annotation = EcoreFactory.eINSTANCE.createEAnnotation(); annotation.setSource(EMOFExtendedMetaData.EMOF_PACKAGE_NS_URI_2_0); return annotation; } else if (EcorePackage.Literals.EOPERATION == type) { EOperation eOperation = EcoreFactory.eINSTANCE.createEOperation(); eOperation.setLowerBound(1); eOperation.setOrdered(false); return eOperation; } else if (EcorePackage.Literals.EPARAMETER == type) { EParameter eParameter = EcoreFactory.eINSTANCE.createEParameter(); eParameter.setLowerBound(1); eParameter.setOrdered(false); return eParameter; } return super.createObject(eFactory, type); } public void convertPropertyFeatures() { if (propertyFeatureList != null) { EcoreUtil.Copier copier = new EcoreUtil.Copier(false) { private static final long serialVersionUID = 1L; @Override protected EObject createCopy(EObject eObject) { EClass eClass = ((EStructuralFeature)eObject).getEType() instanceof EDataType ? EcorePackage.Literals.EATTRIBUTE : EcorePackage.Literals.EREFERENCE; return EcoreUtil.create(eClass); } @Override protected void copyContainment(EReference eReference, EObject eObject, EObject copyEObject) { // The eAnnotations and eGenericType are possible containment references. // We'll move them instead of copying // if (eReference == EcorePackage.Literals.ETYPED_ELEMENT__EGENERIC_TYPE) { ((ETypedElement)copyEObject).setEGenericType(((ETypedElement)eObject).getEGenericType()); } else { ((EStructuralFeature)copyEObject).getEAnnotations().addAll(((EStructuralFeature)eObject).getEAnnotations()); } } @Override protected void copyAttribute(EAttribute eAttribute, EObject eObject, EObject copyEObject) { if (copyEObject.eClass().getEAllStructuralFeatures().contains(eAttribute)) { super.copyAttribute(eAttribute, eObject, copyEObject); } } }; copier.copyAll(propertyFeatureList); copier.copyReferences(); for (Map.Entry<EObject, EObject> entry : copier.entrySet()) { EStructuralFeature emofFeature = (EStructuralFeature)entry.getKey(); EStructuralFeature ecoreFeature = (EStructuralFeature)entry.getValue(); resource.setID(ecoreFeature, resource.getID(emofFeature)); EObject eObject = emofFeature.eContainer(); @SuppressWarnings("unchecked") List<EObject> list = (List<EObject>)eObject.eGet(emofFeature.eContainmentFeature()); list.set(list.indexOf(emofFeature), ecoreFeature); } for (TreeIterator<Notifier> contents = EcoreUtil.getAllContents(resource.getContents(), false); contents.hasNext(); ) { EObject eObject = (EObject)contents.next(); for (EContentsEList.FeatureIterator<EObject> featureIterator = new ECrossReferenceEList.FeatureIteratorImpl<EObject>(eObject) { @Override protected boolean isIncluded(EStructuralFeature eStructuralFeature) { return !eStructuralFeature.isDerived() && super.isIncluded(eStructuralFeature); } }; featureIterator.hasNext(); ) { EObject targetEObject = featureIterator.next(); EObject copyEObject = copier.get(targetEObject); if (copyEObject != null) { EReference eReference = (EReference)featureIterator.feature(); if (eReference.isMany()) { @SuppressWarnings("unchecked") List<EObject> list = (List<EObject>)eObject.eGet(eReference); list.set(list.indexOf(targetEObject), copyEObject); } else { eObject.eSet(eReference, copyEObject); } } } } } } }