blob: e7a1b84b17eab05f0364aa0aa42b4a709c46a598 [file] [log] [blame]
/*
* Copyright (c) 2007, 2018 IBM Corporation, Embarcadero Technologies, CEA, and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Kenn Hussey (IBM Corporation, Embarcadero Technologies) - initial API and implementation
* Kenn Hussey (Embarcadero Technologies) - 213903
* Kenn Hussey (CEA) - 327039, 41846
* Kenn Hussey - 5353016
*
*/
package org.eclipse.uml2.uml.resource;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.common.util.UniqueEList;
import org.eclipse.emf.ecore.EObject;
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.ecore.util.FeatureMap;
import org.eclipse.emf.ecore.util.InternalEList;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.ecore.xmi.impl.BasicResourceHandler;
import org.eclipse.emf.ecore.xml.type.AnyType;
import org.eclipse.uml2.common.util.UML2Util;
import org.eclipse.uml2.uml.Association;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Enumeration;
import org.eclipse.uml2.uml.Profile;
import org.eclipse.uml2.uml.ProfileApplication;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Stereotype;
import org.eclipse.uml2.uml.UMLPackage;
import org.eclipse.uml2.uml.util.UMLSwitch;
import org.eclipse.uml2.uml.util.UMLUtil;
public class CMOF2UMLResourceHandler
extends BasicResourceHandler {
protected boolean resolveProxies = true;
protected static final boolean DEBUG = false;
protected final XMLResource.ResourceHandler delegate;
public CMOF2UMLResourceHandler() {
this(null);
}
public CMOF2UMLResourceHandler(XMLResource.ResourceHandler delegate) {
super();
this.delegate = delegate;
}
protected AnyType getExtension(XMLResource resource, EObject eObject) {
return resource.getEObjectToExtensionMap().get(eObject);
}
protected AnyType putExtension(XMLResource resource, EObject eObject,
AnyType extension) {
return resource.getEObjectToExtensionMap().put(eObject, extension);
}
protected AnyType removeExtension(XMLResource resource, EObject eObject) {
return resource.getEObjectToExtensionMap().remove(eObject);
}
protected Object getValue(FeatureMap featureMap, String name) {
return getValue(featureMap, name, false);
}
protected Object getValue(FeatureMap featureMap, String name, boolean remove) {
for (Iterator<FeatureMap.Entry> entries = featureMap.iterator(); entries
.hasNext();) {
FeatureMap.Entry entry = entries.next();
if (name.equals(entry.getEStructuralFeature().getName())) {
if (remove) {
entries.remove();
}
return entry.getValue();
}
}
return null;
}
protected EObject getEObject(AnyType extension, Resource resource,
String name, boolean remove) {
if (extension != null) {
Object value = getValue(extension.getAnyAttribute(), name, remove);
if (value == null) {
value = getValue(extension.getMixed(), name, remove);
if (value instanceof EObject) {
EObject eObject = (EObject) value;
if (eObject.eIsProxy() && resolveProxies) {
eObject = EcoreUtil.resolve(eObject, resource);
}
return eObject;
}
} else if (value instanceof String && resource != null) {
return resource.getEObject((String) value);
}
}
return null;
}
protected Collection<Object> getValues(FeatureMap featureMap, String name) {
return getValues(featureMap, name, false);
}
protected Collection<Object> getValues(FeatureMap featureMap, String name,
boolean remove) {
Collection<Object> values = new UniqueEList.FastCompare<Object>();
for (Iterator<FeatureMap.Entry> entries = featureMap.iterator(); entries
.hasNext();) {
FeatureMap.Entry entry = entries.next();
if (name.equals(entry.getEStructuralFeature().getName())) {
if (remove) {
entries.remove();
}
values.add(entry.getValue());
}
}
return values;
}
protected Collection<EObject> getEObjects(AnyType extension,
Resource resource, String name, boolean remove) {
Collection<EObject> eObjects = new UniqueEList.FastCompare<EObject>();
if (extension != null) {
Collection<Object> values = getValues(extension.getAnyAttribute(),
name, remove);
if (values.isEmpty()) {
values = getValues(extension.getMixed(), name, remove);
for (Object value : values) {
if (value instanceof EObject) {
EObject eObject = (EObject) value;
if (eObject.eIsProxy() && resolveProxies) {
eObject = EcoreUtil.resolve(eObject, resource);
}
eObjects.add(eObject);
}
}
} else if (resource != null) {
for (Object value : values) {
if (value instanceof String) {
EObject eObject = resource.getEObject((String) value);
if (eObject != null) {
eObjects.add(eObject);
}
}
}
}
}
return eObjects;
}
protected Profile getEcoreProfile(EObject eObject) {
Resource eResource = eObject.eResource();
if (eResource != null) {
ResourceSet resourceSet = eResource.getResourceSet();
if (resourceSet != null) {
return UML2Util.load(resourceSet, URI
.createURI(UMLResource.ECORE_PROFILE_URI),
UMLPackage.Literals.PROFILE);
}
}
return null;
}
protected Stereotype getEcoreStereotype(EObject eObject, String name) {
Profile ecoreProfile = getEcoreProfile(eObject);
return ecoreProfile != null
? ecoreProfile.getOwnedStereotype(name)
: null;
}
public void preLoad(XMLResource resource, InputStream inputStream,
Map<?, ?> options) {
if (delegate != null) {
delegate.preLoad(resource, inputStream, options);
}
}
@Override
public void postLoad(XMLResource resource, InputStream inputStream,
Map<?, ?> options) {
if (delegate != null) {
delegate.postLoad(resource, inputStream, options);
}
EList<EObject> resourceContents = resource.getContents();
List<AnyType> tagsToRemove = new ArrayList<AnyType>();
final List<ProfileApplication> profileApplicationsToRemove = new ArrayList<ProfileApplication>();
UMLSwitch<Object> umlSwitch = new UMLSwitch<Object>() {
@Override
public Object caseProfileApplication(
ProfileApplication profileApplication) {
Profile appliedProfile = profileApplication.getAppliedProfile();
if (appliedProfile != null) {
org.eclipse.uml2.uml.Package applyingPackage = profileApplication
.getApplyingPackage();
if (applyingPackage != null
&& applyingPackage
.getProfileApplication(appliedProfile) != profileApplication) {
profileApplicationsToRemove.add(profileApplication);
}
}
return super.caseProfileApplication(profileApplication);
}
@Override
public Object defaultCase(EObject eObject) {
Iterator<?> contents = resolveProxies
? eObject.eContents().iterator()
: ((InternalEList<?>) eObject.eContents()).basicIterator();
if (contents != null) {
while (contents.hasNext()) {
doSwitch((EObject) contents.next());
}
}
return eObject;
}
};
for (int i = 0; i < resourceContents.size(); i++) {
EObject content = resourceContents.get(i);
if (content instanceof AnyType
&& CMOF2UMLExtendedMetaData.TAG.equals(content.eClass()
.getName())) {
AnyType tag = (AnyType) content;
Object name = getValue(tag.getAnyAttribute(),
CMOF2UMLExtendedMetaData.CMOF_TAG_NAME);
if (CMOF2UMLExtendedMetaData.EMOF_TAG__OPPOSITE_ROLE_NAME
.equals(name)) {
tagsToRemove.add(tag);
} else if (CMOF2UMLExtendedMetaData.XMI_TAG__XMI_NAME
.equals(name)) {
EObject element = getEObject(tag, resource,
CMOF2UMLExtendedMetaData.CMOF_TAG_ELEMENT, false);
if (element instanceof org.eclipse.uml2.uml.Class
|| element instanceof Association) {
UMLUtil.setTaggedValue(
(Element) element,
getEcoreStereotype(element,
UMLUtil.STEREOTYPE__E_CLASS),
UMLUtil.TAG_DEFINITION__XML_NAME,
getValue(tag.getAnyAttribute(),
CMOF2UMLExtendedMetaData.CMOF_TAG_VALUE));
} else if (element instanceof Property) {
UMLUtil
.setTaggedValue(
(Element) element,
getEcoreStereotype(
element,
UMLUtil.UML2EcoreConverter
.isEDataType((Classifier) ((Property) element)
.getType())
? UMLUtil.STEREOTYPE__E_ATTRIBUTE
: UMLUtil.STEREOTYPE__E_REFERENCE),
UMLUtil.TAG_DEFINITION__XML_NAME,
getValue(tag.getAnyAttribute(),
CMOF2UMLExtendedMetaData.CMOF_TAG_VALUE));
}
tagsToRemove.add(tag);
} else if (CMOF2UMLExtendedMetaData.XMI_TAG__ATTRIBUTE
.equals(name)) {
EObject element = getEObject(tag, resource,
CMOF2UMLExtendedMetaData.CMOF_TAG_ELEMENT, false);
Enumeration featureKindEnumeration = (Enumeration) getEcoreProfile(
element)
.getOwnedType(UMLUtil.ENUMERATION__FEATURE_KIND);
if (featureKindEnumeration != null
&& element instanceof Property
&& Boolean.getBoolean(String.valueOf(getValue(
tag.getAnyAttribute(),
CMOF2UMLExtendedMetaData.CMOF_TAG_VALUE)))) {
UMLUtil
.setTaggedValue(
(Element) element,
getEcoreStereotype(element,
UMLUtil.UML2EcoreConverter
.isEDataType(((Property) element)
.getNamespace())
? UMLUtil.STEREOTYPE__E_ATTRIBUTE
: UMLUtil.STEREOTYPE__E_REFERENCE),
UMLUtil.TAG_DEFINITION__XML_FEATURE_KIND,
featureKindEnumeration
.getOwnedLiteral(UMLUtil.ENUMERATION_LITERAL__ATTRIBUTE));
}
tagsToRemove.add(tag);
} else if (CMOF2UMLExtendedMetaData.XMI_TAG__ELEMENT
.equals(name)) {
EObject element = getEObject(tag, resource,
CMOF2UMLExtendedMetaData.CMOF_TAG_ELEMENT, false);
Enumeration featureKindEnumeration = (Enumeration) getEcoreProfile(
element)
.getOwnedType(UMLUtil.ENUMERATION__FEATURE_KIND);
if (featureKindEnumeration != null
&& element instanceof Property
&& Boolean.getBoolean(String.valueOf(getValue(
tag.getAnyAttribute(),
CMOF2UMLExtendedMetaData.CMOF_TAG_VALUE)))) {
UMLUtil
.setTaggedValue(
(Element) element,
getEcoreStereotype(element,
UMLUtil.UML2EcoreConverter
.isEDataType(((Property) element)
.getNamespace())
? UMLUtil.STEREOTYPE__E_ATTRIBUTE
: UMLUtil.STEREOTYPE__E_REFERENCE),
UMLUtil.TAG_DEFINITION__XML_FEATURE_KIND,
featureKindEnumeration
.getOwnedLiteral(UMLUtil.ENUMERATION_LITERAL__ELEMENT));
}
tagsToRemove.add(tag);
} else if (CMOF2UMLExtendedMetaData.XMI_TAG__SCHEMA_TYPE
.equals(name)) {
tagsToRemove.add(tag);
} else if (CMOF2UMLExtendedMetaData.XMI_TAG__ID_PROPERTY
.equals(name)) {
EObject element = getEObject(tag, resource,
CMOF2UMLExtendedMetaData.CMOF_TAG_ELEMENT, false);
if (element instanceof Property
&& Boolean.getBoolean(String.valueOf(getValue(
tag.getAnyAttribute(),
CMOF2UMLExtendedMetaData.CMOF_TAG_VALUE)))
&& UMLUtil.UML2EcoreConverter
.isEDataType(((Property) element).getNamespace())) {
((Property) element).setIsID(true);
}
tagsToRemove.add(tag);
} else if (CMOF2UMLExtendedMetaData.XMI_TAG__NS_URI
.equals(name)) {
EObject element = getEObject(tag, resource,
CMOF2UMLExtendedMetaData.CMOF_TAG_ELEMENT, false);
if (element instanceof org.eclipse.uml2.uml.Package) {
org.eclipse.uml2.uml.Package package_ = (org.eclipse.uml2.uml.Package) element;
String packageURI = package_.getURI();
String nsURI = (String) getValue(tag.getAnyAttribute(),
CMOF2UMLExtendedMetaData.CMOF_TAG_VALUE);
if (packageURI == null) {
package_.setURI(nsURI);
} else if (!packageURI.equals(nsURI)) {
UMLUtil.setTaggedValue(
package_,
getEcoreStereotype(package_,
UMLUtil.STEREOTYPE__E_PACKAGE),
UMLUtil.TAG_DEFINITION__NS_URI, nsURI);
}
}
tagsToRemove.add(tag);
} else if (CMOF2UMLExtendedMetaData.XMI_TAG__NS_PREFIX
.equals(name)) {
EObject element = getEObject(tag, resource,
CMOF2UMLExtendedMetaData.CMOF_TAG_ELEMENT, false);
if (element instanceof org.eclipse.uml2.uml.Package) {
org.eclipse.uml2.uml.Package package_ = (org.eclipse.uml2.uml.Package) element;
String packageName = package_.getName();
String nsPrefix = (String) getValue(
tag.getAnyAttribute(),
CMOF2UMLExtendedMetaData.CMOF_TAG_VALUE);
if (packageName == null) {
package_.setName(nsPrefix);
} else if (!packageName.equals(nsPrefix)) {
UMLUtil.setTaggedValue(
package_,
getEcoreStereotype(package_,
UMLUtil.STEREOTYPE__E_PACKAGE),
UMLUtil.TAG_DEFINITION__NS_PREFIX, nsPrefix);
}
}
tagsToRemove.add(tag);
} else if (CMOF2UMLExtendedMetaData.XMI_TAG__CONTENT_TYPE
.equals(name)) {
EObject element = getEObject(tag, resource,
CMOF2UMLExtendedMetaData.CMOF_TAG_ELEMENT, false);
Enumeration contentKindEnumeration = (Enumeration) getEcoreProfile(
element)
.getOwnedType(UMLUtil.ENUMERATION__CONTENT_KIND);
if (contentKindEnumeration != null
&& element instanceof org.eclipse.uml2.uml.Class) {
String contentType = (String) getValue(
tag.getAnyAttribute(),
CMOF2UMLExtendedMetaData.CMOF_TAG_VALUE);
Object xmlContentKind = null;
if ("any".equals(contentType)) { //$NON-NLS-1$
xmlContentKind = contentKindEnumeration
.getOwnedLiteral(UMLUtil.ENUMERATION_LITERAL__UNSPECIFIED);
} else if ("complex".equals(contentType)) { //$NON-NLS-1$
xmlContentKind = contentKindEnumeration
.getOwnedLiteral(UMLUtil.ENUMERATION_LITERAL__ELEMENT_ONLY);
} else if ("empty".equals(contentType)) { //$NON-NLS-1$
xmlContentKind = contentKindEnumeration
.getOwnedLiteral(UMLUtil.ENUMERATION_LITERAL__EMPTY);
} else if ("mixed".equals(contentType)) { //$NON-NLS-1$
xmlContentKind = contentKindEnumeration
.getOwnedLiteral(UMLUtil.ENUMERATION_LITERAL__MIXED);
} else if ("simple".equals(contentType)) { //$NON-NLS-1$
xmlContentKind = contentKindEnumeration
.getOwnedLiteral(UMLUtil.ENUMERATION_LITERAL__SIMPLE);
}
if (xmlContentKind != null) {
UMLUtil.setTaggedValue(
(Element) element,
getEcoreStereotype(element,
UMLUtil.STEREOTYPE__E_CLASS),
UMLUtil.TAG_DEFINITION__XML_CONTENT_KIND,
xmlContentKind);
}
}
tagsToRemove.add(tag);
}
} else {
umlSwitch.doSwitch(content);
}
}
for (AnyType tag : tagsToRemove) {
resourceContents.remove(tag);
}
for (ProfileApplication profileApplication : profileApplicationsToRemove) {
profileApplication.getApplyingPackage().getProfileApplications()
.remove(profileApplication);
}
}
public void preSave(XMLResource resource, OutputStream outputStream,
Map<?, ?> options) {
if (delegate != null) {
delegate.preSave(resource, outputStream, options);
}
}
public void postSave(XMLResource resource, OutputStream outputStream,
Map<?, ?> options) {
if (delegate != null) {
delegate.postSave(resource, outputStream, options);
}
}
}