blob: b12daccb0883b436511715caba7bd3a6b573cc00 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013, 2019 Willink Transformations 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:
* E.D.Willink - Initial API and implementation
*******************************************************************************/
package org.eclipse.ocl.pivot.uml.internal.resource;
import java.util.List;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EAnnotation;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
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.EcorePackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.Element;
import org.eclipse.ocl.pivot.Model;
import org.eclipse.ocl.pivot.internal.resource.ASResourceFactory;
import org.eclipse.ocl.pivot.internal.resource.AbstractASResourceFactory;
import org.eclipse.ocl.pivot.internal.utilities.EnvironmentFactoryInternal;
import org.eclipse.ocl.pivot.internal.utilities.Technology;
import org.eclipse.ocl.pivot.resource.ASResource;
import org.eclipse.ocl.pivot.uml.UMLStandaloneSetup;
import org.eclipse.ocl.pivot.uml.internal.es2as.UML2AS;
import org.eclipse.ocl.pivot.uml.internal.utilities.UMLEcoreTechnology;
import org.eclipse.ocl.pivot.uml.internal.validation.UMLOCLEValidator;
import org.eclipse.ocl.pivot.utilities.NameUtil;
import org.eclipse.ocl.pivot.utilities.ParserException;
import org.eclipse.uml2.uml.Type;
import org.eclipse.uml2.uml.UMLPackage;
import org.eclipse.uml2.uml.resource.UMLResource;
import org.eclipse.uml2.uml.resource.XMI2UMLResource;
public final class UMLASResourceFactory extends AbstractASResourceFactory
{
private static @Nullable UMLASResourceFactory INSTANCE;
public static synchronized @NonNull UMLASResourceFactory getInstance() {
if (INSTANCE == null) {
// ASResourceFactoryContribution asResourceRegistry = ASResourceFactoryRegistry.INSTANCE.get(ASResource.UML_CONTENT_TYPE);
// if (asResourceRegistry != null) {
// INSTANCE = (UMLASResourceFactory) asResourceRegistry.getASResourceFactory(); // Create the registered singleton
// }
// else {
INSTANCE = new UMLASResourceFactory(); // Create our own singleton
// }
assert INSTANCE != null;
INSTANCE.install("uml", INSTANCE.getResourceClassName());
}
assert INSTANCE != null;
return INSTANCE;
}
public UMLASResourceFactory() {
super(ASResource.UML_CONTENT_TYPE, null);
}
@Override
public void configureResourceSets(@Nullable ResourceSet asResourceSet, @NonNull ResourceSet csResourceSet) {
super.configureResourceSets(asResourceSet, csResourceSet);
if (asResourceSet != null) {
UML2AS.initializeUML(asResourceSet);
}
UML2AS.initializeUML(csResourceSet);
}
@Override
public @NonNull Resource createResource(URI uri) {
assert uri != null;
ASResource asResource = new UMLASResourceImpl(uri, this);
configureResource(asResource);
return asResource;
}
@Override
public @Nullable <T extends Element> T getASElement(@NonNull EnvironmentFactoryInternal environmentFactory,
@NonNull Class<T> pivotClass, @NonNull EObject eObject) throws ParserException {
Resource metamodel = eObject.eResource();
if (metamodel == null) {
return null;
}
UML2AS uml2as = UML2AS.getAdapter(metamodel, environmentFactory);
uml2as.getASModel();
EClass eClass = eObject.eClass();
EPackage ePackage = eClass.getEPackage();
if (ePackage == EcorePackage.eINSTANCE) {
if (eObject instanceof EOperation) {
EOperation eOperation = (EOperation)eObject;
org.eclipse.uml2.uml.Constraint umlConstraint = getConstraintForEOperation(environmentFactory, eOperation);
if (umlConstraint != null) {
eObject = umlConstraint;
}
}
else if (eObject instanceof EClass) {
EClass eStereotype = (EClass)eObject;
org.eclipse.uml2.uml.Stereotype umlStereotype = getStereotypeForEClass(environmentFactory, eStereotype);
if (umlStereotype != null) {
eObject = umlStereotype;
}
}
}
return uml2as.getCreated(pivotClass, eObject);
}
@Override
public @NonNull ASResourceFactory getASResourceFactory() {
return getInstance();
}
protected org.eclipse.uml2.uml.Constraint getConstraintForEOperation(@NonNull EnvironmentFactoryInternal environmentFactory, @NonNull EOperation eOperation) {
if (EcoreUtil.isInvariant(eOperation)) {
EClass eContainingClass = eOperation.getEContainingClass();
EAnnotation eAnnotation = eContainingClass.getEAnnotation("http://www.eclipse.org/uml2/2.0.0/UML"); // UMLUtil.UML2_UML_PACKAGE_2_0_NS_URI
if (eAnnotation != null) {
List<EObject> eReferences = eAnnotation.getReferences();
if ((eReferences != null) && (eReferences.size() > 0)) {
EObject eReference = eReferences.get(0);
if (eReference instanceof org.eclipse.uml2.uml.Type) {
String operationName = environmentFactory.getTechnology().getOriginalName(eOperation);
org.eclipse.uml2.uml.Constraint umlConstraint = ((org.eclipse.uml2.uml.Classifier)eReference).getOwnedRule(operationName);
if (umlConstraint != null) {
return umlConstraint;
}
}
}
}
}
return null;
}
@Override
public @Nullable EOperation getEOperation(@NonNull ASResource asResource, @NonNull EObject eObject) {
UMLASResourceImpl umlResource = (UMLASResourceImpl) asResource;
if (!(eObject instanceof org.eclipse.uml2.uml.Operation)) {
return null;
}
org.eclipse.uml2.uml.Operation umlOperation = (org.eclipse.uml2.uml.Operation)eObject;
org.eclipse.uml2.uml.Class umlClass = umlOperation.getClass_();
if (umlClass == null) {
return null;
}
EClassifier eClassifier = umlResource.getEClassifier(umlClass);
if (eClassifier == null) {
return null;
}
if (!(eClassifier instanceof EClass)) {
return null;
}
String operationName = umlOperation.getName();
if (operationName == null) {
return null;
}
List<org.eclipse.uml2.uml.Parameter> umlParameters = umlOperation.getOwnedParameters();
int umlParameterCount = umlParameters.size();
for (EOperation eOperation : ((EClass)eClassifier).getEOperations()) {
if (operationName.equals(eOperation.getName())) {
List<EParameter> eParameters = eOperation.getEParameters();
int eParameterCount = eParameters.size();
if (umlParameterCount >= eParameterCount) {
boolean parametersMatch = true;
int umlIndex = 0;
int eIndex = 0;
while ((eIndex < eParameterCount) && (umlIndex < umlParameterCount)) {
org.eclipse.uml2.uml.Parameter umlInParameter = null;
while (umlIndex < umlParameterCount) {
org.eclipse.uml2.uml.Parameter umlParameter = umlParameters.get(umlIndex++);
if (umlParameter.getDirection() == org.eclipse.uml2.uml.ParameterDirectionKind.IN_LITERAL) {
umlInParameter = umlParameter;
break;
}
}
if (umlInParameter == null) {
parametersMatch = false;
break;
}
EParameter eParameter = eParameters.get(eIndex++);
Type umlParameterType = umlInParameter.getType();
EClassifier umlEParameterType = umlParameterType != null ? umlResource.getEClassifier(umlParameterType) : null;
EClassifier eParameterType = eParameter.getEType();
if (umlEParameterType != eParameterType) {
parametersMatch = false;
break;
}
}
while (umlIndex < umlParameterCount) {
org.eclipse.uml2.uml.Parameter umlParameter = umlParameters.get(umlIndex++);
if (umlParameter.getDirection() == org.eclipse.uml2.uml.ParameterDirectionKind.IN_LITERAL) {
parametersMatch = false;
break;
}
}
if ((eIndex == eParameterCount) && (umlIndex == umlParameterCount) && parametersMatch) {
return eOperation;
}
}
}
}
return null;
}
@Override
public @Nullable EReference getEReference(@NonNull ASResource asResource, @NonNull EObject eObject) {
UMLASResourceImpl umlResource = (UMLASResourceImpl) asResource;
if (!(eObject instanceof org.eclipse.uml2.uml.Property)) {
return null;
}
org.eclipse.uml2.uml.Property umlProperty = (org.eclipse.uml2.uml.Property)eObject;
org.eclipse.uml2.uml.Class umlClass = umlProperty.getClass_();
if (umlClass == null) {
return null;
}
EClassifier eClassifier = umlResource.getEClassifier(umlClass);
if (eClassifier == null) {
return null;
}
if (!(eClassifier instanceof EClass)) {
return null;
}
String propertyName = umlProperty.getName();
if (propertyName == null) {
return null;
}
for (EReference eReference : ((EClass)eClassifier).getEReferences()) {
if (propertyName.equals(eReference.getName())) {
return eReference;
}
}
return null;
}
@Override
public @NonNull Technology getTechnology() {
UMLStandaloneSetup.assertInitialized();
return UMLEcoreTechnology.INSTANCE;
}
@Override
public @Nullable String getMetamodelNsURI(@NonNull EPackage ePackage) {
if (ePackage instanceof UMLPackage) {
return XMI2UMLResource.UML_METAMODEL_NS_URI;
}
if (ePackage.getClass().getName().startsWith(UMLPackage.class.getPackage().getName())) { // StandardPackage/L2Package/L3Package
return XMI2UMLResource.UML_METAMODEL_NS_URI;
}
return null;
}
@Override
public @Nullable URI getPackageURI(@NonNull EObject eObject) {
if (eObject instanceof org.eclipse.uml2.uml.Package) {
String uri = ((org.eclipse.uml2.uml.Package)eObject).getURI();
if (uri != null) {
return URI.createURI(uri);
}
}
return null;
}
@Override
public @Nullable Integer getPriority() {
return 200;
}
@Override
public @Nullable String getResourceClassName() {
return UMLResource.class.getName();
}
protected org.eclipse.uml2.uml.Stereotype getStereotypeForEClass(@NonNull EnvironmentFactoryInternal environmentFactory, @NonNull EClass eClass) {
EObject eAnnotationParent = null;
for (EObject eObject = eClass; true; eObject = eObject.eContainer()) {
if (eObject == null) {
return null;
}
if (eObject instanceof EAnnotation) {
eAnnotationParent = eObject.eContainer();
break;
}
}
if (!(eAnnotationParent instanceof org.eclipse.uml2.uml.Profile)) {
return null;
}
org.eclipse.uml2.uml.Profile umlProfile = (org.eclipse.uml2.uml.Profile)eAnnotationParent; // FIXME could there be hierarchy ?
org.eclipse.uml2.uml.Stereotype umlStereotype = umlProfile.getOwnedStereotype(NameUtil.getOriginalName(eClass));
return umlStereotype;
}
@Override
public @Nullable Element importFromResource(@NonNull EnvironmentFactoryInternal environmentFactory, @NonNull Resource umlResource, @Nullable URI uri) throws ParserException {
UML2AS conversion = UML2AS.getAdapter(umlResource, environmentFactory);
conversion.setUMLURI(uri != null ? uri.trimFragment() : null);
Model pivotModel = conversion.getASModel();
String uriFragment = uri != null ? uri.fragment() : null;
if (uriFragment == null) {
return pivotModel;
}
else {
EObject eObject = umlResource.getEObject(uriFragment);
if (eObject == null) {
return null;
}
return conversion.getCreated(Element.class, eObject);
}
}
@Override
public void initializeEValidatorRegistry(org.eclipse.emf.ecore.EValidator.@NonNull Registry eValidatorRegistry) {
eValidatorRegistry.put(UMLPackage.eINSTANCE, UMLOCLEValidator.NO_NEW_LINES);
}
}