blob: 8305a6c0984d6f545831590c005fe1e342bd337b [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2019 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:
* David Lopez david.lopez@cea.fr(CEA LIST)
*
*****************************************************************************/
package org.eclipse.papyrus.moka.engine.suml.opaquebehaviors;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.papyrus.moka.engine.suml.accessor.AccessAdapterRegistry;
import org.eclipse.papyrus.moka.engine.suml.accessor.ComponentAccessor;
import org.eclipse.papyrus.moka.engine.suml.accessor.ValueTypeWrapper;
import org.eclipse.papyrus.moka.engine.suml.accessor.locus.IValueConverter;
import org.eclipse.papyrus.moka.engine.suml.accessor.structures.ListAccess;
import org.eclipse.papyrus.moka.fuml.commonbehavior.IExecution;
import org.eclipse.papyrus.moka.fuml.commonbehavior.IParameterValue;
import org.eclipse.papyrus.moka.fuml.commonbehavior.ParameterValue;
import org.eclipse.papyrus.moka.fuml.commonbehavior.SignalEventOccurrence;
import org.eclipse.papyrus.moka.fuml.loci.ILocus;
import org.eclipse.papyrus.moka.fuml.simpleclassifiers.EnumerationValue;
import org.eclipse.papyrus.moka.fuml.simpleclassifiers.IEnumerationValue;
import org.eclipse.papyrus.moka.fuml.simpleclassifiers.IValue;
import org.eclipse.papyrus.moka.fuml.simpleclassifiers.SignalInstance;
import org.eclipse.papyrus.moka.fuml.structuredclassifiers.IObject_;
import org.eclipse.papyrus.moka.fuml.structuredclassifiers.IReference;
import org.eclipse.papyrus.moka.fuml.structuredclassifiers.Reference;
import org.eclipse.uml2.uml.Behavior;
import org.eclipse.uml2.uml.Class;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.Enumeration;
import org.eclipse.uml2.uml.EnumerationLiteral;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.Operation;
import org.eclipse.uml2.uml.Parameter;
import org.eclipse.uml2.uml.ParameterDirectionKind;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Signal;
public class LocusAdapter {
private IObject_ ctxInstance;
public void setExecutionInstance(IObject_ context) {
this.ctxInstance = context;
}
private ILocus getLocus() {
return ctxInstance.getLocus();
}
private Classifier getContextType() {
return ctxInstance.getTypes().get(0);
}
private NamedElement findNamedElement(String qualifiedName) {
Classifier context = getContextType();
if( qualifiedName.startsWith("::") ) {
String parent = context.getPackage().getQualifiedName();
qualifiedName = parent + qualifiedName;
}
if ( !(context instanceof EObject) || (((EObject)context).eResource() == null) )
throw new RuntimeException("Failed to find a contextual resource for object");
ResourceSet resSet = ((EObject)context).eResource().getResourceSet();
Collection<NamedElement> elems = org.eclipse.uml2.uml.util.UMLUtil.findNamedElements(resSet, qualifiedName);
if (!elems.isEmpty()) {
return elems.iterator().next();
}else {
throw new RuntimeException("Failed to find a NamedElement with qualified name: "+ qualifiedName);
}
}
public Object importEnumeration(String qualifiedName) {
NamedElement elm = findNamedElement(qualifiedName);
if( !(elm instanceof Enumeration) )
throw new RuntimeException("The NamedElement is not an Enumeration: "+ qualifiedName);
Enumeration enumeration = (Enumeration) elm;
//Map with IEnumValues
HashMap<String, IEnumerationValue> enumObject = new HashMap<String, IEnumerationValue>();
for(EnumerationLiteral lit : enumeration.getOwnedLiterals()) {
EnumerationValue eValue = new EnumerationValue();
eValue.literal = lit;
eValue.type = enumeration;
enumObject.put(lit.getName(), eValue );
}
return enumObject;
}
public Object instantiate(String qualifiedName) {
NamedElement elm = findNamedElement(qualifiedName);
if( !(elm instanceof org.eclipse.uml2.uml.Class) )
throw new RuntimeException("The NamedElement is not a class: "+ qualifiedName);
ILocus locus = getLocus();
//Wrap it
Reference reference = new Reference();
reference.referent = locus.instantiate((Class) elm);
Class type = (Class)reference.referent.getTypes().get(0);
//Start behavior if it's not null
if( type.getClassifierBehavior() != null )
reference.referent.startBehavior(type, new ArrayList<IParameterValue>());
return AccessAdapterRegistry.getInstance().getComponentAccessor().valueToScript( reference );
}
public Object callBehavior( String qualifiedName ) {
return callBehavior(qualifiedName, ctxInstance);
}
public Object callBehavior(String qualifiedName, Object context) {
return callBehavior(qualifiedName, context, null);
}
private IObject_ getRightContext(Object context) {
if( context == null )
return ctxInstance;
if( context instanceof IObject_ )
return (IObject_) context;
if( !(context instanceof ValueTypeWrapper) )
throw new RuntimeException("The object "+ context + " is not a valid Reference, and can't be the context of a behavior call");
ValueTypeWrapper<IValue> target = (ValueTypeWrapper<IValue>)context;
return ((IReference)target.unwrap()).getReferent();
}
public Object toLocusList(List<Object> params) {
if( params == null )
return null;
ArrayList locusList = new ArrayList<IValue>();
for(Object o : params)
locusList.add(o);
return locusList;
}
public Object callBehavior( String qualifiedName , Object context, List<Object> params ) {
NamedElement element = findNamedElement(qualifiedName);
if( !(element instanceof Behavior ) )
throw new RuntimeException("The class "+ qualifiedName + " is not a behavior");
Behavior behavior = (Behavior)element;
IExecution execution = getLocus().getFactory().createExecution(behavior, getRightContext(context));
IValueConverter conv = AccessAdapterRegistry.getInstance().getConverterForClass(IValue.class);
ComponentAccessor accesor = AccessAdapterRegistry.getInstance().getComponentAccessor();
if( params != null ) {
for( int i = 0; i < params.size(); i++ ) {
Parameter p = behavior.getOwnedParameters().get(i);
ParameterValue pv = new ParameterValue();
pv.parameter = p;
pv.values = new ArrayList<IValue>();
pv.values.add( conv.newValue(params.get(i)) );
execution.setParameterValue(pv);
}
}
execution.execute();
Object returnObject = Void.TYPE;
for( IParameterValue pv : execution.getOutputParameterValues() )
if( pv.getParameter().getDirection() == ParameterDirectionKind.RETURN_LITERAL ) {
returnObject = accesor.valueListToScript( pv.getValues() );
break;
}
execution.destroy();
return returnObject;
}
public Object callOperation(Operation operation, IReference reference, List<Object> params) {
IExecution callExecution = reference.dispatch(operation);
if( params != null ) {
IValueConverter conv = AccessAdapterRegistry.getInstance().getConverterForClass(IValue.class);
List<Parameter> parameters = callExecution.getBehavior().getOwnedParameters();
for( int i = 0; i < parameters.size(); i++ ) {
Parameter parameter = parameters.get(i);
ParameterValue parameterValue = new ParameterValue();
parameterValue.parameter = parameter;
parameterValue.values = new ArrayList<IValue>();
callExecution.setParameterValue(parameterValue);
if( parameter.getDirection() == ParameterDirectionKind.RETURN_LITERAL ||
parameter.getDirection() == ParameterDirectionKind.OUT_LITERAL)
continue;
parameterValue.values.add( conv.newValue(params.get(i)));
}
}
callExecution.execute();
ComponentAccessor accesor = AccessAdapterRegistry.getInstance().getComponentAccessor();
Object returnObject = Void.TYPE;
for( IParameterValue pv : callExecution.getOutputParameterValues() )
if( pv.getParameter().getDirection() == ParameterDirectionKind.RETURN_LITERAL ) {
returnObject = accesor.valueListToScript( pv.getValues() );
break;
}
callExecution.destroy();
return returnObject;
}
public Object callOperation( String opName, Object obj, List<Object> params) {
if( !(obj instanceof ValueTypeWrapper) )
throw new RuntimeException("The object "+ obj + " is not a valid Reference, and can't be targeted by a signal");
ValueTypeWrapper<IValue> target = (ValueTypeWrapper<IValue>)obj;
IReference ref = (IReference) target.unwrap();
Classifier c = ref.getTypes().get(0);
Operation operation = null;
for( Operation op : c.getOperations() ) {
if( op.getName().equals(opName) ) {
operation = op;
break;
}
}
if( operation == null )
throw new RuntimeException("The operation "+ opName + " doesn't exist in the object " + obj);
return callOperation(operation, ref, params);
}
public void sendSignal(String qualifiedName, Object obj, List<Object> params ) {
if( !(obj instanceof ValueTypeWrapper) )
throw new RuntimeException("The object "+ obj + " is not a valid Reference, and can't be targeted by a signal");
ValueTypeWrapper<IValue> target = (ValueTypeWrapper<IValue>)obj;
NamedElement element = findNamedElement(qualifiedName);
if( !(element instanceof Signal ) )
throw new RuntimeException("The signal "+ qualifiedName + " does not exist");
Signal signal = (Signal)element;
SignalInstance signalInstance = new SignalInstance();
signalInstance.type = signal;
IValueConverter conv = AccessAdapterRegistry.getInstance().getConverterForClass(IValue.class);
if( params != null ) {
List<Property> attributes = signal.getOwnedAttributes();
for (int i = 0; i < attributes.size(); i++) {
Property attribute = attributes.get(i);
List<IValue> values = new ArrayList<IValue>();
values.add( conv.newValue(params.get(i)) );
signalInstance.setFeatureValue(attribute, values, 0);
}
}
SignalEventOccurrence signalEventOccurrence = new SignalEventOccurrence();
signalEventOccurrence.signalInstance = (SignalInstance) signalInstance.copy();
signalEventOccurrence.sendTo((IReference) target.unwrap());
}
}