/******************************************************************************* | |
* Copyright (c) 2017 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: | |
* Imen BOUDHIBA (CEA LIST) imen.boudhiba@cea.fr - initial API and implementation | |
*******************************************************************************/ | |
package org.eclipse.efm.modeling.codegen.xlia.core; | |
import java.util.ArrayList; | |
import java.util.Arrays; | |
import java.util.Collection; | |
import java.util.HashMap; | |
import java.util.Iterator; | |
import java.util.List; | |
import java.util.Map; | |
//import org.eclipse.efm.modeling.codegen.xlia.datatype.DataTypeCodeGenerator; | |
import org.eclipse.efm.modeling.codegen.xlia.util.PrettyPrintWriter; | |
import org.eclipse.efm.modeling.codegen.xlia.util.StatemachineContext; | |
import org.eclipse.efm.modeling.codegen.xlia.util.StatemachineContext.CONTEXT; | |
import org.eclipse.efm.modeling.codegen.xlia.util.UmlFactory; | |
import org.eclipse.emf.common.util.EList; | |
import org.eclipse.uml2.uml.Behavior; | |
import org.eclipse.uml2.uml.BehaviorExecutionSpecification; | |
import org.eclipse.uml2.uml.Class; | |
import org.eclipse.uml2.uml.CombinedFragment; | |
import org.eclipse.uml2.uml.ConnectableElement; | |
import org.eclipse.uml2.uml.Constraint; | |
import org.eclipse.uml2.uml.DataType; | |
import org.eclipse.uml2.uml.Element; | |
import org.eclipse.uml2.uml.ExecutionOccurrenceSpecification; | |
import org.eclipse.uml2.uml.FunctionBehavior; | |
import org.eclipse.uml2.uml.Gate; | |
import org.eclipse.uml2.uml.Interaction; | |
import org.eclipse.uml2.uml.InteractionConstraint; | |
import org.eclipse.uml2.uml.InteractionFragment; | |
import org.eclipse.uml2.uml.InteractionOperand; | |
import org.eclipse.uml2.uml.Lifeline; | |
import org.eclipse.uml2.uml.Message; | |
import org.eclipse.uml2.uml.MessageOccurrenceSpecification; | |
import org.eclipse.uml2.uml.NamedElement; | |
import org.eclipse.uml2.uml.OpaqueBehavior; | |
import org.eclipse.uml2.uml.OpaqueExpression; | |
import org.eclipse.uml2.uml.Operation; | |
import org.eclipse.uml2.uml.Parameter; | |
import org.eclipse.uml2.uml.Property; | |
import org.eclipse.uml2.uml.Signal; | |
import org.eclipse.uml2.uml.State; | |
import org.eclipse.uml2.uml.TimeObservation; | |
import org.eclipse.uml2.uml.Transition; | |
import org.eclipse.uml2.uml.ValueSpecification; | |
//import com.cea.aide.core.factory.Creator; | |
//import com.cea.aide.core.form.Verbatim; | |
public class InteractionCodeGenerator extends AbstractCodeGenerator { | |
/** | |
* Constructor | |
*/ | |
public InteractionCodeGenerator(MainCodeGenerator supervisor) { | |
super(supervisor); | |
} | |
/** | |
* performTransform dispatcher for any element to a writer | |
* @param element | |
* @param writer | |
*/ | |
public void performTransformImpl(Element element, PrettyPrintWriter writer) { | |
if( element instanceof Interaction ) { | |
transformInteraction((Interaction)element, writer); | |
} | |
else if( element instanceof Lifeline ) { | |
transformLifeline((Lifeline)element, writer); | |
} | |
else if( element instanceof InteractionFragment ) | |
{ | |
if( element instanceof InteractionOperand ) { | |
transformFragment((InteractionOperand)element, writer); | |
} | |
else if( element instanceof CombinedFragment ) { | |
transformFragment((CombinedFragment)element, writer); | |
} | |
// else if( element instanceof ExecutionSpecification ) | |
// { | |
if( element instanceof BehaviorExecutionSpecification ) { | |
transformFragment( | |
(BehaviorExecutionSpecification)element, writer); | |
} | |
// } | |
// else if( element instanceof OccurrenceSpecification ) | |
// { | |
if( element instanceof MessageOccurrenceSpecification ) { | |
transformFragment( | |
(MessageOccurrenceSpecification)element, writer); | |
} | |
// } | |
} | |
else if( element instanceof Message ) { | |
transformMessage((Message)element, null, writer); | |
} | |
else { | |
performTransformError(this, element); | |
} | |
} | |
public void declareSignalMessageType(Signal signal, PrettyPrintWriter writer) { | |
writer.appendTab2("type ") | |
.append(signal.getName()) | |
.appendEol(" struct {"); | |
writer.appendTab3("var ") | |
.appendEol( "string signature;" ); | |
for (Property property : signal.getAllAttributes()) { | |
writer.appendTab3("var ") | |
.append( fSupervisor.fDataTypeFactory.typeName(property) ) | |
.append(" ") | |
.append(property.getName()) | |
.appendEol(";"); | |
} | |
writer.appendTab2Eol("}"); | |
} | |
/** | |
* Lifeline Projection of dedicated Fragment Util | |
* @param lifeline | |
* @param fragments | |
* @return | |
*/ | |
private ArrayList<InteractionFragment> coveredFragments( | |
Lifeline lifeline, List<InteractionFragment> fragments) { | |
ArrayList<InteractionFragment> coveredFragmentList = new ArrayList<InteractionFragment>(); | |
for( InteractionFragment iFragment : fragments ) { | |
if (iFragment.getCovereds().contains(lifeline)) { | |
if( !( iFragment instanceof ExecutionOccurrenceSpecification) ) { | |
coveredFragmentList.add(iFragment); | |
} | |
} | |
} | |
return coveredFragmentList; | |
} | |
/** | |
* performTransform an Interaction element to a writer | |
* @param element | |
* @param writer | |
*/ | |
public void transformInteraction(Interaction element, Collection<Lifeline> lifelines, | |
StatemachineContext lfContext, PrettyPrintWriter writer) { | |
writer.appendTabEol2(ClassCodeGenerator.XLIA_SYSTEM_1_0); | |
writer.appendTab("system< and > ") | |
.append(element.getName()) | |
.appendEol(" {"); | |
ArrayList<DataType> datatypes = new ArrayList<DataType>(); | |
ArrayList<Signal> signals = new ArrayList<Signal>(); | |
fSupervisor.fClassFactory.collectGlobalElement(element, datatypes, signals); | |
PrettyPrintWriter writer2 = writer.itab2(); | |
Map<NamedElement, Boolean> declaredSignatures = new HashMap<NamedElement, Boolean>(); | |
writer.appendEol("@property: "); | |
writer.appendTabEol("// GLOBAL DATA TYPES"); | |
for (DataType datatype : datatypes) { | |
fSupervisor.fDataTypeFactory.performTransformImpl(datatype, writer2); | |
} | |
// for( Lifeline lifeline : lifelines ) { | |
// ConnectableElement representedClass = lifeline.getRepresents(); | |
// if( representedClass instanceof Property ) { | |
// Class clazz = (Class) (((Property)representedClass).getType()); | |
// | |
// for( Classifier classifier : clazz.getNestedClassifiers() ) { | |
// if( classifier instanceof DataType ) { | |
// if( ! classifier.getRedefinedClassifiers().isEmpty() ) { | |
// writer.appendTab("type ").append(classifier.getName()).append(' '); | |
// | |
// for (Classifier redefClassifier : classifier.getRedefinedClassifiers()) { | |
// if( redefClassifier instanceof Type ) { | |
// writer.append(typeName((Type)redefClassifier)); | |
// break; | |
// } | |
// } | |
// writer.appendEol(";"); | |
// } | |
// } | |
// } | |
// } | |
// } | |
writer.appendTabEol("// message"); | |
for( Message message : element.getMessages() ) { | |
//declare signal structure | |
NamedElement signature = message.getSignature(); | |
if( (signature instanceof Signal) && (declaredSignatures.get(signature) == null) ) { | |
declaredSignatures.put(signature, Boolean.TRUE); | |
if( ! ((Signal) signature).getAllAttributes().isEmpty() ) { | |
declareSignalMessageType((Signal) signature, writer); | |
} | |
} | |
// declare message | |
//writer.appendTab2("message ") // TODO modif until Diversity support | |
writer.appendTab2("signal ") | |
.append(message.getName()); | |
if( (signature instanceof Signal) | |
&& (! ((Signal) signature).getAllAttributes().isEmpty()) ) { | |
writer.append("( " ) | |
.append(signature.getName()) | |
.append(" )"); | |
} | |
writer.appendEol(";"); | |
} | |
writer.appendTabEol("// end message"); | |
//function signatures vector | |
writer.appendTabEol("// function signatures vector"); | |
// writer.appendTab2Eol("type FontionSignature struct {"); | |
// writer.appendTab3Eol("var string name;"); | |
// writer.appendTab3Eol("var string signature;"); | |
// writer.appendTab2Eol("}"); | |
writer.appendTab2Eol("public var vector<FonctionSignature> AllSignatures = {"); | |
for( Lifeline lifeline : lifelines ) { | |
ConnectableElement representedClass = lifeline.getRepresents(); | |
if( representedClass instanceof Property ) { | |
Class clazz = (Class) (((Property)representedClass).getType()); | |
for (int j = 0; j < clazz.getOperations().size(); j++ ) { | |
Operation operation = clazz.getOperations().get(j); | |
writer.appendTab3("{ \"").append(operation.getName()).append("\" , \"") | |
.append(fSupervisor.fDataTypeFactory.typeName( operation.getReturnResult().getType())) | |
.append(" ").append(operation.getName()).append("("); | |
for(int i = 0; i < operation.getOwnedParameters().size()-1; i++){ | |
Parameter param = operation.getOwnedParameters().get(i); | |
writer.append( fSupervisor.fDataTypeFactory.typeName(param.getType()) //param.getType().getName() // | |
).append(" ").append(param.getName()); | |
if(i < operation.getOwnedParameters().size()-2 ){ | |
writer.append(", "); | |
} | |
} | |
writer.append(")\" }"); | |
if(j < clazz.getOperations().size()-1 ){ | |
writer.appendEol(", "); | |
} | |
} | |
// clazz.getOperations(); | |
// for (Operation operation : clazz.getOperations()) { | |
// writer.appendTab3("{ \"").append(operation.getName()).append("\" , \"") | |
// .append(operation.getReturnResult().getType().getName()) | |
// .append(" ").append(operation.getName()).append("("); | |
// //int i=0; | |
// | |
// for(int i = 0; i < operation.getOwnedParameters().size()-1; i++){ | |
// Parameter param = operation.getOwnedParameters().get(i); | |
// writer.append(param.getType().getName()).append(" ").append(param.getName()); | |
// if(i < operation.getOwnedParameters().size()-2 ){ | |
// writer.append(", "); | |
// } | |
// } | |
// writer.appendEol(")\" }"); | |
// } | |
} | |
} | |
writer.appendTab2Eol("};"); | |
//function calls vectors | |
writer.appendTabEol("// function calls vectors"); | |
// writer.appendTab2Eol("type CallStack struct {"); | |
// writer.appendTab3Eol("var string ID;"); | |
// writer.appendTab3Eol("var string PRE;"); | |
// writer.appendTab3Eol("var vector CALL;"); | |
// writer.appendTab3Eol("var string POST;"); | |
// writer.appendTab3Eol("var string INV;"); | |
// writer.appendTab2Eol("}"); | |
writer.appendTab2Eol("var integer callIndex = -1;"); | |
writer.appendTab2Eol("public var vector<CallData> AllCallsStack;"); | |
writer.appendTab2Eol("public var CallData currentCall;"); | |
writer.appendTab2Eol("public var vector EMPTY_VECTOR;"); | |
writer.appendTab2Eol("public const CallData EMPTY_CALL = { \"\" , \"\" , EMPTY_VECTOR , \"\" , \"\" };"); | |
// writer.appendTab2Eol("public var vector globalProgramCallset;"); | |
// writer.appendTab2Eol("public var vector globalProgramTrace;"); | |
// writer.appendTab2Eol("public var vector globalTypeParamCalls;"); | |
// writer.appendTab2Eol("public var vector globalAssertion;"); | |
writer.appendTabEol("// end function calls vectors"); | |
writer.appendEol("@composite: "); | |
for( Lifeline alifeline : lifelines ) { | |
transformWriteLifeline(alifeline, lfContext, writer2); | |
} | |
// Section moe | |
// | |
writer.appendEolTab_Eol("@moe:"); | |
// Section irun | |
writer.appendTab2Eol("@irun{"); | |
writer.appendTab3Eol("currentCall = EMPTY_CALL;"); | |
writer.appendTab2Eol2("}"); | |
//route fifo | env messages | |
String routeProtocol = (lifelines.size() < 2) ? "env" : "fifo"; | |
writer.appendEol("@com: "); | |
writer.appendTabEol("// route: message fifo"); | |
for( Message message : element.getMessages() ) { | |
//declare message fifo | |
if(message.getSendEvent() instanceof Gate){ | |
writer.appendTab2("route<") | |
.append("env"); | |
} | |
else | |
{ | |
writer.appendTab2("route<") | |
.append(routeProtocol); | |
} | |
writer.append("> [ ") | |
.append(message.getName()); | |
writer.appendEol("];"); | |
} | |
writer.appendTabEol("// end route"); | |
writer.appendTab("} // end Interaction ") | |
.appendEol2(element.getName()); | |
//!@?DERADCODE: TO DELETE | |
// if( lfContext == null ) { | |
// } | |
// else { | |
// lfContext.initializeConstraintMap(element); | |
// | |
// // A writer indenting with TAB + iTAB -> TAB2 | |
// PrettyPrintWriter writer2 = writer.itab2(); | |
// | |
// writer2.appendTab("////////////////////////////////////////////////////////////////////////////// Lifeline ") | |
// .append(lfContext.coveredLifeline.getName()) | |
// .appendEol(" //////////////////////////////////////////////////////////////////////////////"); | |
// | |
// ArrayList<InteractionFragment> coveredFragmentList = | |
// coveredFragments(lfContext.coveredLifeline, element.getFragments()); | |
// | |
// lfContext.isLastFragmentTransformation = false; | |
// int coveredFragmentListCount = coveredFragmentList.size()-1; | |
// for( InteractionFragment iFragment : coveredFragmentList ) { | |
// if(coveredFragmentList.indexOf(iFragment) == coveredFragmentListCount){ | |
// //Transition tr_final = lfContext.createTransition( | |
// //"tr_final", lfContext.currentState, lfContext.finalState); | |
// lfContext.isLastFragmentTransformation = true; | |
// | |
//// lfContext.currentState = lfContext.finalState; | |
// } | |
// | |
// transformFragment(iFragment, lfContext, writer2); | |
// } | |
// | |
// //TODO DELETE Transition tr_final | |
//// Transition tr_final = lfContext.createTransition( | |
//// "tr_final", lfContext.currentState, lfContext.finalState); | |
// } | |
} | |
// public String typeName(Type element) { | |
// String typeString = element.getName(); | |
// | |
// if( element instanceof PrimitiveType ) { | |
// typeString = typeString.toLowerCase(); | |
// } | |
// else if( element instanceof Class ){ | |
// typeString = "machine" + "/*< " + typeString + " >*/"; | |
// } | |
// | |
// return typeString; | |
// } | |
// | |
public void transformInteraction(Interaction element, PrettyPrintWriter writer) | |
{ | |
final StatemachineContext lfContext = new StatemachineContext(element, CONTEXT.INTERACTION); | |
transformInteraction(element, element.getLifelines(), lfContext, writer); | |
} | |
/** | |
* performTransform a Fragment element to a writer | |
* @param element | |
* @param writer | |
*/ | |
private void transformFragment(InteractionFragment element, PrettyPrintWriter writer) | |
{ | |
for (Lifeline lifeline : element.getCovereds()) { | |
StatemachineContext lfContext = new StatemachineContext(lifeline); | |
transformFragment(element, lfContext); | |
lfContext.toWriter(fSupervisor.fStatemachineFactory, writer); | |
} | |
} | |
private void transformFragment(InteractionFragment iFragment, | |
StatemachineContext lfContext) { | |
if( iFragment instanceof CombinedFragment ) { | |
transformCombinedFragment( | |
(CombinedFragment)iFragment, lfContext); | |
} | |
else if( iFragment instanceof InteractionOperand ) { | |
transformInteractionOperand( | |
(InteractionOperand)iFragment, lfContext); | |
} | |
else if( iFragment instanceof MessageOccurrenceSpecification ) { | |
transformMessageOccurrenceSpecification( | |
(MessageOccurrenceSpecification)iFragment, lfContext); | |
} | |
else if( iFragment instanceof BehaviorExecutionSpecification ) { | |
transformBehaviorExecutionSpecification( | |
(BehaviorExecutionSpecification)iFragment, lfContext); | |
} | |
else if( iFragment instanceof ExecutionOccurrenceSpecification ) { | |
transformExecutionOccurrenceSpecification( | |
(ExecutionOccurrenceSpecification)iFragment, lfContext); | |
} | |
else { | |
performTransformError(this, iFragment); | |
} | |
} | |
// transform data constraint | |
public void transformElementConstraints( | |
Element element, Transition transition, StatemachineContext lfContext) { | |
List<Constraint> constraints = lfContext.getElementConstraints(element); | |
if( constraints != null ) { | |
for (Constraint constraint : constraints) { | |
UmlFactory.addEffectGuard(lfContext, | |
element ,transition, constraint); | |
}; | |
} | |
} | |
// transform timed constraint | |
public void transformElementTimedConstraints( | |
Element element, Transition transition, StatemachineContext lfContext) { | |
List<Constraint> constraints = lfContext.getElementConstraints(element); | |
if( constraints != null ) { | |
for (Constraint constraint : constraints) { | |
UmlFactory.setGuard(transition, constraint); | |
}; | |
} | |
} | |
// transform TimeObservation | |
public void transformElementTimeObservation( | |
NamedElement element, Transition transition, StatemachineContext lfContext) { | |
List<TimeObservation> timeObservations = lfContext.getTimeObservation(element); | |
if( timeObservations != null ) { | |
for (TimeObservation tObs : timeObservations) { | |
// UmlFactory.setGuard(transition, tObs); | |
}; | |
} | |
} | |
/** | |
* performTransform a InteractionOperand element | |
* @param element | |
* @param writer | |
*/ | |
private void transformInteractionOperand(InteractionOperand element, | |
StatemachineContext lfContext) { | |
lfContext.initialState.setName("init_" + element.getName()); | |
lfContext.finalState.setName("final_" + element.getName()); | |
ArrayList<InteractionFragment> coveredFragmentList = | |
coveredFragments(lfContext.coveredLifeline, element.getFragments()); | |
if( coveredFragmentList.isEmpty() ) { | |
lfContext.performNoCoveredFragment(); | |
} | |
else { | |
lfContext.isLastFragmentTransformation = false; | |
int coveredFragmentListCount = coveredFragmentList.size()-1; | |
for( InteractionFragment iFragment : coveredFragmentList ) { | |
if (coveredFragmentList.indexOf(iFragment) == coveredFragmentListCount ) { | |
// lfContext.isLastFragmentTransformation | |
lfContext.isLastFragmentTransformation = true; | |
// lfContext.currentState = lfContext.finalState; | |
} | |
transformFragment(iFragment, lfContext); | |
} | |
// Transition tr_final = lfContext.createTransition( | |
// "tr_final", lfContext.currentState, lfContext.finalState); | |
} | |
} | |
/** | |
* performTransform a CombinedFragment element | |
* @param element | |
* @param writer | |
*/ | |
public void transformCombinedFragment(CombinedFragment element, | |
StatemachineContext lfContext) { | |
switch (element.getInteractionOperator()) { | |
case LOOP_LITERAL: | |
transformCombinedFragmentLoop(element, lfContext); | |
break; | |
case ALT_LITERAL: | |
transformCombinedFragmentAlt(element, lfContext); | |
break; | |
case OPT_LITERAL: | |
transformCombinedFragmentOpt(element, lfContext); | |
break; | |
case SEQ_LITERAL: | |
transformCombinedFragmentSequence(element, lfContext); | |
break; | |
case STRICT_LITERAL: | |
transformCombinedFragmentStrict(element, lfContext); | |
break; | |
case PAR_LITERAL: | |
transformCombinedFragmentParallel(element, lfContext); | |
break; | |
default: | |
break; | |
} | |
} | |
////////////////////////////////////// Transform Loop Fragment ////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////////////////// | |
public void transformCombinedFragmentLoop(CombinedFragment element, | |
StatemachineContext lfContext) { | |
lfContext.currentState.setName("LoopFragment#" + element.getName()); | |
Constraint loopGuard = element.getOperands().get(0).getGuard(); | |
State loopState = lfContext.createTargetState("loop_" + element.getName()); | |
if( element.getCovereds().size() < 2 || lfContext.transfoCtx == CONTEXT.LIFELINE ) { | |
Transition entryLoop = lfContext.createTransition( | |
"tr_loop_entry", lfContext.currentState, loopState); | |
UmlFactory.setGuard(entryLoop, loopGuard); | |
} | |
else { | |
Transition entryLoop = lfContext.createTransition( | |
"tr_loop_first", lfContext.currentState, loopState); | |
UmlFactory.setGuard(entryLoop, loopGuard); | |
entryLoop= lfContext.createTransition( | |
"tr_loop_not_first", lfContext.currentState, loopState); | |
UmlFactory.setGuard(entryLoop, loopGuard); | |
} | |
lfContext.currentState = loopState; | |
// loop boucle with min/max index constraint | |
Transition trLoop = lfContext.createFinalTransition( | |
"tr_loop", loopState, loopState); | |
Property loopIndex = UmlFactory.createVariable(lfContext.statemachine, | |
//"loopIndex_" | |
"count_"+ element.getName(), UmlFactory.integerType()); | |
// Add effect behavior | |
//increment loopIndex | |
UmlFactory.addOpaqueBehaviorEffect(trLoop, loopIndex.getName()+" +=1 ;"); | |
if( loopGuard instanceof InteractionConstraint ) { | |
UmlFactory.setGuard(trLoop, (InteractionConstraint) loopGuard, loopIndex); | |
} | |
else { | |
UmlFactory.setGuard(trLoop, loopGuard); | |
} | |
StatemachineContext loopContext = new StatemachineContext(lfContext, element); | |
for( InteractionOperand iFragment : element.getOperands()) { | |
transformInteractionOperand(iFragment, loopContext); | |
} | |
// quit loop transition | |
State quitloopState = lfContext.createTargetState("quit_loop_" + element.getName()); | |
Transition quitLoop = lfContext.createFinalElseTransition( | |
"final#tr_quit_loop", loopState, quitloopState); | |
lfContext.currentState = quitloopState; | |
} | |
////////////////////////////////////// Transform Alt Fragment ////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////////////////// | |
public void transformCombinedFragmentAlt(CombinedFragment element, | |
StatemachineContext lfContext) { | |
State exitAltState = lfContext.createTargetState("exit_alt#" + element.getName()); | |
State sourceAltStates = lfContext.currentState; | |
for( InteractionOperand iFragment : element.getOperands()) { | |
State regionAltState = lfContext.createTargetState("region_alt#" + iFragment.getName()); | |
Constraint regionGuard = iFragment.getGuard(); | |
if( element.getCovereds().size() < 2 || lfContext.transfoCtx == CONTEXT.LIFELINE ) { | |
Transition entryAltFirst = lfContext.createTransition( | |
"tr_alt_entry#" + iFragment.getName(), sourceAltStates, regionAltState); | |
UmlFactory.setGuard(entryAltFirst, regionGuard); | |
} | |
else { | |
Transition entryAltFirst = lfContext.createTransition( | |
"tr_alt_first#" + iFragment.getName(), sourceAltStates, regionAltState); | |
UmlFactory.setGuard(entryAltFirst, regionGuard); | |
Transition entryAltNotFirst = lfContext.createTransition( | |
"tr_alt_not_first#" + iFragment.getName(), sourceAltStates, regionAltState); | |
UmlFactory.setGuard(entryAltNotFirst, regionGuard); | |
} | |
lfContext.currentState = regionAltState; | |
StatemachineContext altContext = new StatemachineContext(lfContext, element); | |
transformInteractionOperand(iFragment, altContext); | |
Transition exitRegionAlt = lfContext.createFinalTransition( | |
"tr_alt_quit#" + iFragment.getName(), regionAltState, exitAltState); | |
} | |
lfContext.currentState = exitAltState; | |
} | |
//////////////////////////////////////Transform Sequence Fragment ////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////////////////// | |
// TODO | |
public void transformCombinedFragmentSequence( | |
CombinedFragment element, StatemachineContext lfContext) { | |
lfContext.currentState.setName("SeqFragment#" + element.getName()); | |
State exitSeqState = lfContext.createTargetState("exit_seq#" + element.getName()); | |
State regionSeqState = lfContext.createTargetState("target_seq#" + element.getName()); | |
for( InteractionOperand iFragment : element.getOperands()) { | |
Constraint regionGuard = iFragment.getGuard(); | |
Transition entrySeq = lfContext.createTransition( | |
"tr_seq_region#" + iFragment.getName(), lfContext.currentState, regionSeqState); | |
// UmlFactory.setGuard(entryStrict, regionGuard); | |
StatemachineContext seqContext = new StatemachineContext(lfContext, iFragment); | |
transformInteractionOperand(iFragment, seqContext); | |
} | |
Transition exitSeq = lfContext.createFinalTransition( | |
"tr_seq_quit#" + element.getName(), lfContext.currentState, exitSeqState); | |
lfContext.currentState = exitSeqState; | |
} | |
//////////////////////////////////////Transform Strict Fragment ////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////////////////// | |
public void transformCombinedFragmentStrict( | |
CombinedFragment element, StatemachineContext lfContext) { | |
lfContext.currentState.setName("StrictFragment#" + element.getName()); | |
State elseStrictState = null; | |
Transition elseStrictTransition = null; | |
State operandStrictState = null; | |
for( InteractionOperand iFragment : element.getOperands()) { | |
if( elseStrictState != null ) { | |
elseStrictState.setName("strict#" + iFragment.getName()); | |
operandStrictState = elseStrictState; | |
elseStrictState = null; | |
} | |
else { | |
operandStrictState = lfContext.createNewState("strict#" + iFragment.getName()); | |
} | |
Transition operandStrictTransition = lfContext.createTransition( | |
"tr_strict_region#" + iFragment.getName(), lfContext.currentState, operandStrictState); | |
Constraint regionGuard = iFragment.getGuard(); | |
if( regionGuard != null ) { | |
UmlFactory.setGuard(operandStrictTransition, regionGuard); | |
// previous else transition | |
if( elseStrictTransition != null ) { | |
UmlFactory.setGuard(elseStrictTransition, regionGuard); | |
} | |
elseStrictState = lfContext.createNewState("else_strict#" + iFragment.getName()); | |
elseStrictTransition = lfContext.createTransition( | |
"tr_else_strict_region#" + iFragment.getName(), lfContext.currentState, elseStrictState); | |
} | |
lfContext.currentState = operandStrictState; | |
StatemachineContext strictContext = new StatemachineContext(lfContext, iFragment); | |
transformInteractionOperand(iFragment, strictContext); | |
} | |
if( elseStrictState != null ) { | |
elseStrictState.setName("exit_strict#" + element.getName()); | |
} | |
else { | |
elseStrictState = lfContext.createTargetState("exit_strict#" + element.getName()); | |
} | |
Transition exitStrict = lfContext.createTransition( | |
"tr_strict_quit#" + element.getName(), lfContext.currentState, elseStrictState); | |
lfContext.currentState = elseStrictState; | |
} | |
//////////////////////////////////////Transform Parallel Fragment ////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////////////////// | |
//TODO | |
public void transformCombinedFragmentParallel( | |
CombinedFragment element, StatemachineContext lfContext) { | |
lfContext.currentState.setName("ParFragment#" + element.getName()); | |
State exitParState = lfContext.createTargetState("exit_par#" + element.getName()); | |
State regionStrictState = lfContext.createTargetState("target_par#" + element.getName()); | |
for( InteractionOperand iFragment : element.getOperands()) { | |
Constraint regionGuard = iFragment.getGuard(); | |
// Transition entryStrict = lfContext.createTransition( | |
// "tr_strict_region#" + iFragment.getName(), lfContext.currentState, regionStrictState); | |
// UmlFactory.setGuard(entryStrict, regionGuard); | |
StatemachineContext parContext = new StatemachineContext(lfContext, iFragment); | |
transformInteractionOperand(iFragment, parContext); | |
} | |
Transition exitPar = lfContext.createTransition( | |
"tr_par_quit#" + element.getName(), lfContext.currentState, exitParState); | |
lfContext.currentState = exitParState; | |
} | |
//////////////////////////////////////Transform Opt Fragment ////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////////////////// | |
public void transformCombinedFragmentOpt(CombinedFragment element, | |
StatemachineContext lfContext) { | |
State optState = lfContext.createTargetState("opt#" + element.getName()); | |
Transition entryOpt = lfContext.createTransition( | |
"tr_opt_first", lfContext.currentState, optState); | |
////TODO Add effect behavior | |
entryOpt= lfContext.createTransition( | |
"tr_opt_not_first", lfContext.currentState, optState); | |
////TODO Add effect behavior | |
lfContext.currentState = optState; | |
// | |
// | |
StatemachineContext optContext = new StatemachineContext(lfContext, element); | |
for( InteractionOperand iFragment : element.getOperands()) { | |
transformInteractionOperand(iFragment, optContext); | |
} | |
} | |
/** | |
* performTransform a ExecutionOccurrence element to a writer | |
* @param element | |
*/ | |
public void transformExecutionOccurrenceSpecification( | |
ExecutionOccurrenceSpecification element, StatemachineContext lfContext) { | |
State execOccState = lfContext.createTargetState("execOcc#" + element.getName()); | |
Transition execOccTrqns = lfContext.createTransition( | |
"tr_execOcc", lfContext.currentState, execOccState); | |
lfContext.currentState = execOccState; | |
} | |
/** | |
* performTransform a Lifeline element to a writer | |
* @param element | |
* @param writer | |
*/ | |
public void transformLifeline(Lifeline element, PrettyPrintWriter writer) | |
{ | |
final StatemachineContext lfContext = | |
new StatemachineContext(element.getInteraction(), CONTEXT.LIFELINE); | |
transformInteraction(element.getInteraction(), | |
Arrays.asList( element ), lfContext, writer); | |
} | |
public void transformWriteLifeline(Lifeline element, | |
StatemachineContext lfContext, PrettyPrintWriter writer) { | |
Interaction interaction = element.getInteraction(); | |
if( interaction != null ) { | |
lfContext = new StatemachineContext(lfContext, element); | |
ArrayList<InteractionFragment> coveredFragmentList = | |
coveredFragments(element, interaction.getFragments()); | |
lfContext.isLastFragmentTransformation = false; | |
int coveredFragmentListCount = coveredFragmentList.size()-1; | |
for (InteractionFragment itFragment : coveredFragmentList) { | |
if(coveredFragmentList.indexOf(itFragment) == coveredFragmentListCount){ | |
//Transition tr_final = lfContext.createTransition( | |
//"tr_final", lfContext.currentState, lfContext.finalState); | |
lfContext.isLastFragmentTransformation = true; | |
// lfContext.currentState = lfContext.finalState; | |
} | |
transformFragment(itFragment, lfContext); | |
} | |
lfContext.toWriter(fSupervisor, writer); | |
} | |
} | |
/** | |
* performTransform a BehaviorExecutionSpecification element to a writer | |
* @param element | |
* @param writer | |
*/ | |
public void transformBehaviorExecutionSpecification( | |
BehaviorExecutionSpecification element, | |
StatemachineContext lfContext) { | |
if(element.getStart() instanceof ExecutionOccurrenceSpecification){ | |
BehaviorExecutionSpecification act = element; | |
State targetState = needIntermediateState(element, lfContext) | |
? lfContext.createIntermediateState("targetBhExec#" + element.getName()) | |
: lfContext.createTargetState("targetBhExec#" + element.getName()); | |
lfContext.currentState.setName("BhExec#" + element.getName()); | |
Transition BH_tr= lfContext.createTransition( | |
act.getName(), lfContext.currentState, targetState); | |
transformElementConstraints(element.getStart(), BH_tr, lfContext); | |
UmlFactory.addOpaqueBehaviorEffect(BH_tr, act.getBehavior()); | |
lfContext.currentState = targetState; | |
//add constraint of finishOccurrence to the transition | |
if(element.getFinish() instanceof ExecutionOccurrenceSpecification ){ | |
List<Constraint> constraints = lfContext.getElementConstraints(element.getFinish()); | |
if( constraints != null ){ | |
lfContext.intermediateTransition = null; | |
for (Constraint constraint : constraints) { | |
UmlFactory.addEffectGuard(lfContext, element, BH_tr, constraint); | |
} | |
if(lfContext.intermediateTransition != null){ | |
lfContext.currentState = (State) lfContext.intermediateTransition.getTarget(); | |
lfContext.intermediateTransition = null; | |
} | |
if(element.getBehavior() instanceof FunctionBehavior){ | |
UmlFactory.addOpaqueBehaviorEffect(BH_tr, "AllCallsStack <=< currentCall;"); | |
} | |
} | |
else { | |
if(element.getBehavior() instanceof FunctionBehavior){ | |
UmlFactory.addOpaqueBehaviorEffect(BH_tr, "AllCallsStack <=< currentCall;"); | |
} | |
} | |
} | |
//lfContext.currentState = targetState; | |
} | |
} | |
private boolean needIntermediateState( | |
BehaviorExecutionSpecification element, | |
StatemachineContext lfContext) { | |
if( lfContext.isLastFragmentTransformation | |
&& (element.getFinish() instanceof ExecutionOccurrenceSpecification) ){ | |
List<Constraint> constraints = lfContext.getElementConstraints(element.getFinish()); | |
if( constraints != null ){ | |
for (Constraint constraint : constraints) | |
{ | |
ValueSpecification valueSpec = constraint.getSpecification(); | |
if( valueSpec instanceof OpaqueExpression ) { | |
OpaqueExpression opaqExpr = (OpaqueExpression)valueSpec; | |
for (String language : opaqExpr.getLanguages()) { | |
if(language.contains("xLIA")){ | |
{ | |
return true; | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
return false; | |
} | |
/** | |
* performTransform a MessageOccurrenceSpecification element to a writer | |
* @param element | |
* @param writer | |
*/ | |
public void transformMessageOccurrenceSpecification( | |
MessageOccurrenceSpecification element, | |
StatemachineContext lfContext) { | |
lfContext.currentState.setName("MsgOcc#" + element.getName()); | |
State targetState = lfContext.createTargetState("targetMsgOcc#" + element.getName()); | |
Transition MsgOcc_tr= lfContext.createTransition( | |
"tr_" + element.getName(), lfContext.currentState, targetState); | |
// Message message = element.getMessage(); | |
// if( element.isReceive() ){ | |
// | |
// StringBuilder MsgReceiveAction = new StringBuilder("input "); | |
// lfContext.inputMessage.add(message); | |
// | |
// MsgReceiveAction.append( message.getName() );//.getSignature().getLabel() ) | |
//// if (! (message.getArguments().isEmpty()) ){ | |
// boolean isnotFirst = false; | |
// | |
// MsgReceiveAction.append("( { "); | |
// | |
// if( message.getSignature() instanceof Signal ) { | |
// Signal signal = (Signal) message.getSignature(); | |
// | |
// final String paramPrefix = message.getName() + "#in."; | |
// | |
// for (Property property : signal.getAllAttributes()) { | |
// | |
// if( isnotFirst ) { | |
// MsgReceiveAction.append(" , "); | |
// } | |
// else { | |
// isnotFirst = true; | |
// } | |
// MsgReceiveAction.append( paramPrefix) | |
// .append(property.getName()); | |
// } | |
// | |
// } | |
Message message = element.getMessage(); | |
if( element.isReceive() ){ | |
StringBuilder MsgReceiveAction = new StringBuilder("input "); | |
lfContext.inputMessage.add(message); | |
MsgReceiveAction.append( message.getName() ); | |
// if (! (message.getArguments().isEmpty()) ){ | |
// check if there is a behaviorExecution that specifies the variables on which we receive the message | |
EList<InteractionFragment> fragments = lfContext.coveredLifeline.getCoveredBys(); | |
Boolean isStartExecBehavExecution = false; | |
BehaviorExecutionSpecification behavExecSpecOfComAct = null; | |
for (Iterator<InteractionFragment> iterator = fragments.iterator(); iterator.hasNext();) { | |
InteractionFragment interactionFragment = iterator.next(); | |
if (interactionFragment instanceof BehaviorExecutionSpecification){ | |
behavExecSpecOfComAct = (BehaviorExecutionSpecification) interactionFragment; | |
if (behavExecSpecOfComAct.getStart() == element){ | |
isStartExecBehavExecution = true; | |
break; | |
} | |
} | |
} | |
MsgReceiveAction.append("( ") | |
.append(message.getName()).append( "#params );\n" );//append("#").append(message.getSignature().getName()).append(");\n"); | |
if (isStartExecBehavExecution){ | |
Behavior behavior = behavExecSpecOfComAct.getBehavior(); | |
if (behavior instanceof OpaqueBehavior){ | |
OpaqueBehavior opaqueBehavior = (OpaqueBehavior) behavior; | |
if (opaqueBehavior.getBodies().size() > 0){ | |
String strinBehavior = opaqueBehavior.getBodies().get(0).trim(); | |
if( strinBehavior.startsWith("in ") ) { | |
strinBehavior = strinBehavior.substring(3, strinBehavior.length()-1); | |
String[] inVars = strinBehavior.split(" *, *"); | |
Signal signal = (Signal) message.getSignature(); | |
for (int i = 0; i < inVars.length; i++) { | |
MsgReceiveAction.append(inVars[i]) | |
.append(" = ") | |
.append(message.getName()).append( "#params.")//append("#").append(message.getSignature().getName()).append(".") | |
.append(signal.getAllAttributes().get(i).getName()) | |
.append(";\n"); | |
} | |
} | |
else { | |
//TO DO error message | |
} | |
} | |
} | |
} | |
//ancien | |
NamedElement signature = message.getSignature(); | |
if( signature instanceof Signal ) { | |
lfContext.addLocalVariable(message.getName() + "#params"//"#" + message.getSignature().getName() | |
, (Signal) signature); | |
} | |
UmlFactory.addOpaqueBehaviorEffect(MsgOcc_tr, MsgReceiveAction.toString()); | |
// } | |
} | |
else if( element.isSend() ) { | |
//translate constraints | |
transformElementConstraints(element, MsgOcc_tr, lfContext); | |
//translate output action | |
StringBuilder MsgReceiveAction = new StringBuilder("output "); | |
lfContext.outputMessage.add(message); | |
MsgReceiveAction.append( message.getName() ) | |
.append("( { ") | |
.append("\"") | |
.append(message.getSignature().getName()) | |
.append("\""); | |
if (! (message.getArguments().isEmpty()) ){ | |
MsgReceiveAction.append(", "); | |
boolean isnotFirst = false; | |
for (ValueSpecification itArg : message.getArguments()) { | |
if( isnotFirst ) { | |
MsgReceiveAction.append(" , "); | |
} | |
else { | |
isnotFirst = true; | |
} | |
MsgReceiveAction.append(itArg.stringValue()); | |
} | |
MsgReceiveAction.append(" } )"); | |
} | |
MsgReceiveAction.append(" --> "); | |
if (message.getReceiveEvent() instanceof MessageOccurrenceSpecification){ | |
if( lfContext.transfoCtx == CONTEXT.INTERACTION ) | |
{ | |
MessageOccurrenceSpecification target = (MessageOccurrenceSpecification) message.getReceiveEvent(); | |
MsgReceiveAction.append(target.getCovered().getRepresents().getType().getName()) | |
.append('#').append(target.getCovered().getName()); | |
} | |
else { | |
MsgReceiveAction.append("$env"); | |
} | |
} | |
if (message.getReceiveEvent() instanceof Gate){ | |
//Gate target = (Gate) message.getReceiveEvent(); | |
MsgReceiveAction.append("$env"); | |
} | |
MsgReceiveAction.append(";"); | |
UmlFactory.addOpaqueBehaviorEffect(MsgOcc_tr, MsgReceiveAction.toString()); | |
} | |
lfContext.currentState = targetState; | |
} | |
/** | |
* performTransform a Message element to a writer | |
* @param element | |
* @param writer | |
*/ | |
public void transformMessage(Message element, | |
StatemachineContext lfContext, PrettyPrintWriter writer) { | |
writer.appendTab("Message ") | |
.appendEol(" {"); | |
writer.appendTab("} // end Message ") | |
.appendEol2(element.getName()); | |
} | |
// /** | |
// * performTransform a Region List element to a writer | |
// * @param listOfRegion | |
// * @param writer | |
// */ | |
// private void transformGate(Gate element, | |
// StatemachineContext lfContext, PrettyPrintWriter writer) { | |
// | |
// writer.appendTab("Gate ") | |
// .append(element.getName()) | |
// .appendEol(" {"); | |
// | |
// writer.appendTab("} // end Gate ") | |
// .appendEol2(element.getName()); | |
// } | |
// private void transformPartDecomposition(PartDecomposition element, | |
// StatemachineContext lfContext, PrettyPrintWriter writer) { | |
// writer.appendTab("PartDecomposition ") | |
// .append(element.getName()) | |
// .appendEol(" {"); | |
// | |
// writer.appendTab("} // end PartDecomposition ") | |
// .appendEol2(element.getName()); | |
// } | |
} |