blob: 724ae026532e0344fa6cc74732230eac839413ce [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2013, 2014 CEA LIST.
*
* 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:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
*****************************************************************************/
package org.eclipse.papyrus.interoperability.rsa.blackbox;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.m2m.qvt.oml.blackbox.java.Operation;
import org.eclipse.m2m.qvt.oml.blackbox.java.Operation.Kind;
import org.eclipse.m2m.qvt.oml.util.IContext;
import org.eclipse.uml2.common.util.CacheAdapter;
import org.eclipse.uml2.uml.CallEvent;
import org.eclipse.uml2.uml.Collaboration;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.LiteralString;
import org.eclipse.uml2.uml.OpaqueExpression;
import org.eclipse.uml2.uml.SignalEvent;
import org.eclipse.uml2.uml.UMLFactory;
import org.eclipse.uml2.uml.UMLPackage;
/**
* Implements the Blackbox mappings for RSARTToPapyrusRT
*
* @author Camille Letavernier
*
*/
public class RTMappings {
@Operation(contextual = true, kind = Kind.MAPPING, withExecutionContext = true)
public static org.eclipse.uml2.uml.Class toClass(IContext context, Collaboration collaboration) {
return refactorType(context, collaboration, UMLPackage.eINSTANCE.getClass_(), org.eclipse.uml2.uml.Class.class);
}
@Operation(contextual = true, kind = Kind.MAPPING, withExecutionContext = true)
public static SignalEvent toSignalEvent(IContext context, CallEvent callEvent) {
return refactorType(context, callEvent, UMLPackage.eINSTANCE.getSignalEvent(), SignalEvent.class);
}
@Operation(contextual = true, kind = Kind.MAPPING, withExecutionContext = false)
public static LiteralString toLiteralString(OpaqueExpression expression) {
return refactorType(null, expression, UMLPackage.eINSTANCE.getLiteralString(), LiteralString.class);
}
// Not public to avoid confusing QVTo (Public methods are part of the Blackbox unit API)
private static <T extends Element> T refactorType(IContext context, EObject sourceElement, EClass targetEClass, java.lang.Class<T> resultType) {
// Retrieve the resource at the beginning, because the source element will be removed from its container at some point
// Resource resource = sourceElement.eResource();
// Create a Class and maintain the features (Attributes and References)
T result = resultType.cast(UMLFactory.eINSTANCE.create(targetEClass));
for (EStructuralFeature sourceFeature : sourceElement.eClass().getEAllStructuralFeatures()) {
EStructuralFeature targetFeature = result.eClass().getEStructuralFeature(sourceFeature.getName());
if (targetFeature != null && targetFeature.isChangeable() && sourceElement.eIsSet(sourceFeature)) {
result.eSet(targetFeature, sourceElement.eGet(sourceFeature));
}
}
// Fix incoming references
Collection<EStructuralFeature.Setting> incomingReferences = CacheAdapter.getInstance().getInverseReferences(sourceElement);
for (EStructuralFeature.Setting setting : incomingReferences) {
EStructuralFeature feature = setting.getEStructuralFeature();
if (feature.isChangeable() && feature.getEType().isInstance(result)) {
if (feature.isMany()) {
Object value = setting.get(true);
if (value instanceof Collection<?>) {
List<Object> copy = new LinkedList<Object>((Collection<?>) value);
while (true) {
int index = copy.indexOf(sourceElement);
if (index < 0) {
break;
}
copy.remove(index);
copy.add(index, result);
}
setting.set(copy);
}
} else {
setting.set(result);
}
}
}
// TODO: Keep the same XMI ID
// This algorithm doesn't work here, because the object has been added to a temporary resource (ModelExtent), which doesn't support IDs mapping
// We need to track the mapping somewhere else
// if(resource instanceof XMLResource) {
// XMLResource xmlResource = (XMLResource)resource;
// xmlResource.setID(result, xmlResource.getID(sourceElement));
// }
return result;
}
}