Bug 520516 [codegen] xlia code generation from Sequence Diagrams (via
StateMachines)
 - Adding new component translation: Final transitions from composite
states (for combined fragments) ...

Change-Id: I63bf4de9d7b53b6f07f300289825beb8237709a8
Signed-off-by: Imen Boudhiba <imen.boudhiba@cea.fr>
diff --git a/codegen/org.eclipse.efm.modeling.codegen.xlia/src/org/eclipse/efm/modeling/codegen/xlia/core/InteractionCodeGenerator.java b/codegen/org.eclipse.efm.modeling.codegen.xlia/src/org/eclipse/efm/modeling/codegen/xlia/core/InteractionCodeGenerator.java
index ad427d9..2b02d40 100644
--- a/codegen/org.eclipse.efm.modeling.codegen.xlia/src/org/eclipse/efm/modeling/codegen/xlia/core/InteractionCodeGenerator.java
+++ b/codegen/org.eclipse.efm.modeling.codegen.xlia/src/org/eclipse/efm/modeling/codegen/xlia/core/InteractionCodeGenerator.java
@@ -26,6 +26,7 @@
 import org.eclipse.uml2.uml.Constraint;

 import org.eclipse.uml2.uml.Element;

 import org.eclipse.uml2.uml.ExecutionOccurrenceSpecification;

+import org.eclipse.uml2.uml.Expression;

 import org.eclipse.uml2.uml.Gate;

 import org.eclipse.uml2.uml.Interaction;

 import org.eclipse.uml2.uml.InteractionConstraint;

@@ -37,11 +38,13 @@
 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.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.UMLFactory;

 import org.eclipse.uml2.uml.ValueSpecification;

 import org.eclipse.uml2.uml.internal.impl.BehaviorExecutionSpecificationImpl;

 

@@ -117,9 +120,32 @@
 	            .appendEol(";");

 	    }

 

-		writer.appendTab2Eol("};");

+		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

@@ -148,7 +174,8 @@
 					}

 				}

 				// declare message

-				writer.appendTab2("message ")

+				//writer.appendTab2("message ") // TODO modif until Diversity support

+				writer.appendTab2("signal ")

 					.append(message.getName());

 				

 				if( (signature instanceof Signal)

@@ -170,6 +197,14 @@
 			}

 			writer.appendTabEol("// end message");

 			

+			//function calls vectors

+			writer.appendTab2Eol("// function calls vectors");

+			writer.appendTab2Eol("public var vector globalProgramCallset;");

+			writer.appendTab2Eol("public var vector globalProgramTrace;");

+			writer.appendTab2Eol("public var vector globalTypeParamCalls;");

+			writer.appendTabEol("// end function calls vectors");

+			

+			

 			// Extra element needed to respect model semantic

 		//	for( Lifeline lifeline : element.getLifelines() ) {

 		//		writer.appendTab2("var fifo<integer , 30> " )

@@ -225,18 +260,26 @@
 				.append(lfContext.coveredLifeline.getName())

 				.appendEol(" //////////////////////////////////////////////////////////////////////////////");

 			

-			for( InteractionFragment iFragment : element.getFragments() ) {

-				

-				if( iFragment.getCovereds().contains(lfContext.coveredLifeline)) {

-					// TODO lfContext.isLastFragmentTransformation ???

-					lfContext.isLastFragmentTransformation = false;

-					transformFragment(iFragment, lfContext, writer2);

+			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);

+//			Transition tr_final = lfContext.createTransition(

+//					"tr_final", lfContext.currentState, lfContext.finalState);

 		}

 		

 		

@@ -297,10 +340,10 @@
 					(BehaviorExecutionSpecification)iFragment, lfContext);

 		}

 

-		//else if( iFragment instanceof ExecutionOccurrenceSpecification ) {

-		//	transformExecutionOccurrenceSpecification(

-		//			(ExecutionOccurrenceSpecification)iFragment, lfContext);

-		//}

+		else if( iFragment instanceof ExecutionOccurrenceSpecification ) {

+			transformExecutionOccurrenceSpecification(

+					(ExecutionOccurrenceSpecification)iFragment, lfContext);

+		}

 

 		else {

 			performTransformError(this, iFragment);

@@ -353,31 +396,31 @@
 	private void transformInteractionOperand(InteractionOperand element,

 			StatemachineContext lfContext) {

 		

-		ArrayList<InteractionFragment> fragmentList = new ArrayList<InteractionFragment>();

+		lfContext.initialState.setName("init_" + element.getName());

+		lfContext.finalState.setName("final_" + element.getName());

 		

-		for( InteractionFragment iFragment : element.getFragments() ) {

-			if (iFragment.getCovereds().contains(lfContext.coveredLifeline)) {

-				fragmentList.add(iFragment);

-			}

-		}

-		

-		if( fragmentList.isEmpty() ) {

+		ArrayList<InteractionFragment> coveredFragmentList =

+				coveredFragments(lfContext.coveredLifeline, element.getFragments());

+								

+		if( coveredFragmentList.isEmpty() ) {

 			lfContext.performNoCoveredFragment();

 		}

 		else {

 			lfContext.isLastFragmentTransformation = false;

 			

-			for( InteractionFragment iFragment : fragmentList ){ //element.getFragments() ) {

-				

-				if (fragmentList.indexOf(iFragment) == fragmentList.size()-1 ) {

+			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);

+//			Transition tr_final = lfContext.createTransition(

+//					"tr_final", lfContext.currentState, lfContext.finalState);

 		}

 	}

 

@@ -425,6 +468,7 @@
 	

 	public void transformCombinedFragmentLoop(CombinedFragment element,

 			StatemachineContext lfContext) {

+	

 		

 		lfContext.currentState.setName("LoopFragment#" + element.getName());

 		Constraint loopGuard = element.getOperands().get(0).getGuard();

@@ -433,21 +477,26 @@
 		Transition entryLoop = lfContext.createTransition(

 				"tr_loop_first", lfContext.currentState, loopState);

 		UmlFactory.setGuard(entryLoop, loopGuard);

-		// TODO Add effect behavior

 		

 		entryLoop= lfContext.createTransition(

 				"tr_loop_not_first", lfContext.currentState, loopState);

 		UmlFactory.setGuard(entryLoop, loopGuard);

-		// TODO Add effect behavior

-

+		

+		

 		lfContext.currentState = loopState;

 		

 		// loop boucle with min/max index constraint

-		Transition trLoop = lfContext.createTransition(

+		Transition trLoop = lfContext.createFinalTransition(

 				"tr_loop", loopState, loopState);

+		Property loopIndex = UmlFactory.createVariable(lfContext.statemachine,

+				"loopIndex_" + element.getName(), UmlFactory.integerType());

+		

+		// Add effect behavior

+		//increment loopIndex

+		UmlFactory.addOpaqueBehaviorEffect(trLoop, loopIndex.getName()+" +=1 ;");

+		

+		

 		if( loopGuard instanceof InteractionConstraint ) {

-			Property loopIndex = UmlFactory.createVariable(lfContext.statemachine,

-					"loopIndex_" + element.getName(), UmlFactory.integerType());

 

 			UmlFactory.setGuard(trLoop, (InteractionConstraint) loopGuard, loopIndex);

 		} 

@@ -455,17 +504,22 @@
 			UmlFactory.setGuard(trLoop, loopGuard);

 		}

 		

-		// quit loop transition

-		State quitloopState = lfContext.createTargetState("quit_loop_" + element.getName());

-		Transition quitLoop = lfContext.createElseTransition(

-				"tr_quit_loop", loopState, quitloopState);

-		lfContext.currentState = quitloopState;

+

 		

 		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;

+		

+	

 	}

 

 	

@@ -499,7 +553,7 @@
 		

 		transformInteractionOperand(iFragment, altContext);

 		

-		Transition exitRegionAlt = lfContext.createTransition(

+		Transition exitRegionAlt = lfContext.createFinalTransition(

 				"tr_alt_quit#" + iFragment.getName(), regionAltState, exitAltState);

 	}

 	

@@ -533,7 +587,7 @@
 

 	}

 

-	Transition exitSeq = lfContext.createTransition(

+	Transition exitSeq = lfContext.createFinalTransition(

 			"tr_seq_quit#" + element.getName(), lfContext.currentState, exitSeqState);

 	lfContext.currentState = exitSeqState;

 }

@@ -655,7 +709,6 @@
 	for( InteractionOperand iFragment : element.getOperands()) {

 		transformInteractionOperand(iFragment, optContext);

 	}

-

 }

 

 

@@ -665,10 +718,17 @@
 	 * performTransform a ExecutionOccurrence element to a writer

 	 * @param element

 	 */

-//	public void transformExecutionOccurrenceSpecification(

-//			ExecutionOccurrenceSpecification element, StatemachineContext lfContext) {

-		//

-//	}

+	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;

+	}

 

 	

 	/**

@@ -698,12 +758,22 @@
 		Interaction interaction = element.getInteraction();

 		

 		if( interaction != null ) {

-			for (InteractionFragment itFrag : interaction.getFragments()) {

-				if( itFrag.getCovereds().contains(element) ) {

-					// TODO lfContext.isLastFragmentTransformation ???

-					lfContext.isLastFragmentTransformation = false;

-					transformFragment(itFrag, lfContext);

+			ArrayList<InteractionFragment> coveredFragmentList =

+					coveredFragments(element, interaction.getFragments());

+

+			lfContext.isLastFragmentTransformation = false;

+			int coveredFragmentListCount = coveredFragmentList.size()-1;

+			for (InteractionFragment itFragment : coveredFragmentList) {

+				// TODO lfContext.isLastFragmentTransformation ???

+				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);

 			}

 		}

 	}

@@ -720,17 +790,40 @@
 			BehaviorExecutionSpecification element,

 			StatemachineContext lfContext) {

 		if(element.getStart() instanceof ExecutionOccurrenceSpecification){

-		BehaviorExecutionSpecification act = (BehaviorExecutionSpecification) element;

-		State targetState = lfContext.createTargetState("targetBhExec#" + element.getName());

-		lfContext.currentState.setName("BhExec#" + element.getName());

-		Transition BH_tr= lfContext.createTransition(

-				act.getName(), lfContext.currentState, targetState);

-		lfContext.currentState = targetState;

-		//String effect = act.getBehavior().toString().concat(";");

-		

-		UmlFactory.addOpaqueBehaviorEffect(BH_tr, act.getBehavior());

-		

-		transformElementConstraints(element.getStart(), BH_tr, lfContext);

+			BehaviorExecutionSpecification act = (BehaviorExecutionSpecification) element;

+			

+			//StringBuffer valueBuffer = new StringBuffer(act.getBehavior().toString());

+			

+			State targetState = lfContext.createTargetState("targetBhExec#" + element.getName());

+			lfContext.currentState.setName("BhExec#" + element.getName());

+			Transition BH_tr= lfContext.createTransition(

+					act.getName(), lfContext.currentState, targetState);

+			

+			//String effect = act.getBehavior().toString().concat(";");

+

+			transformElementConstraints(element.getStart(), BH_tr, lfContext);

+

+			UmlFactory.addOpaqueBehaviorEffect(BH_tr, act.getBehavior());

+			

+			//add constraint of finishOccurrence to the transition

+			if(element.getFinish() instanceof ExecutionOccurrenceSpecification ){

+

+				List<Constraint> constraints = lfContext.getElementConstraints(element.getFinish());

+				if( constraints != null ){

+//					State targetState2 = lfContext.createTargetState("targetBhExec2#" + element.getName());

+//					lfContext.currentState.setName("BhExec#2" + element.getName());

+//					Transition BH_tr2= lfContext.createTransition(

+//							act.getName()+"2", lfContext.currentState, targetState2);

+//					lfContext.currentState = targetState2;

+//

+//					transformElementConstraints(element.getFinish(), BH_tr2, lfContext);

+					

+					for (Constraint constraint : constraints) {

+						UmlFactory.addEffectGuard(BH_tr, constraint);

+					}

+				}

+			}

+			lfContext.currentState = targetState;

 		}

 	}

 	

@@ -799,8 +892,7 @@
 				Boolean isStartExecBehavExecution = false;

 				BehaviorExecutionSpecification behavExecSpecOfComAct = null;

 				for (Iterator<InteractionFragment> iterator = fragments.iterator(); iterator.hasNext();) {

-					InteractionFragment interactionFragment = iterator

-							.next();

+					InteractionFragment interactionFragment = iterator.next();

 					if (interactionFragment instanceof BehaviorExecutionSpecification){

 						

 						behavExecSpecOfComAct = (BehaviorExecutionSpecification) interactionFragment;

@@ -811,45 +903,42 @@
 					}	

 				}				

 

+				MsgReceiveAction.append("( ")

+				.append(message.getName()).append( "#params );\n" );

+

 				if (isStartExecBehavExecution){

-					MsgReceiveAction.append("( { ")

-					.append(message.getName() )

-		            .append( "#in" )

-		            .append(".signature, ");

-					

-					

 					Behavior behavior = behavExecSpecOfComAct.getBehavior();

 					if (behavior instanceof OpaqueBehavior){

 						OpaqueBehavior opaqueBehavior = (OpaqueBehavior) behavior;

 						if (opaqueBehavior.getBodies().size() > 0){

-							String strinBehavior = opaqueBehavior.getBodies().get(0);

-							strinBehavior = strinBehavior.replaceAll("\\s","");

-							strinBehavior = strinBehavior.substring(2);

-							MsgReceiveAction.append(strinBehavior);

-							MsgReceiveAction.append(" } );");

+							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(signal.getAllAttributes().get(i).getName())

+									.append(";\n");

+								}

+							}

+							else {

+								//TO DO error message

+							}

 						}

 					}

-					

-					UmlFactory.addOpaqueBehaviorEffect(MsgOcc_tr, MsgReceiveAction.toString());

 				}

 	    	

 		        //ancien

 		        NamedElement signature = message.getSignature();

-		        if( ! isStartExecBehavExecution ) {

 		        if( signature instanceof Signal ) {                    

 		            lfContext.addLocalVariable(message.getName() + "#params", (Signal) signature);

 		        }

 		        

-		        MsgReceiveAction.append("( ")

-		            .append( message.getName() )

-		            .append( "#params" );

-

-				MsgReceiveAction.append(" )");	

-			

-		    

-				MsgReceiveAction.append(";");	

 				UmlFactory.addOpaqueBehaviorEffect(MsgOcc_tr, MsgReceiveAction.toString());

-			    }

 	//	    }

 		}

 		else if( element.isSend() ) {

@@ -858,13 +947,13 @@
 			lfContext.outputMessage.add(message);

 			

 			MsgReceiveAction.append( message.getName() )

-			.append("( ")

+			.append("( { ")

 			.append("\"")

 			.append(message.getSignature().getName())

 			.append("\"");

 			

 			if (! (message.getArguments().isEmpty()) ){

-				MsgReceiveAction.append(", { ");

+				MsgReceiveAction.append(", ");

 

 				boolean isnotFirst = false;

 				

diff --git a/codegen/org.eclipse.efm.modeling.codegen.xlia/src/org/eclipse/efm/modeling/codegen/xlia/core/MainCodeGenerator.java b/codegen/org.eclipse.efm.modeling.codegen.xlia/src/org/eclipse/efm/modeling/codegen/xlia/core/MainCodeGenerator.java
index edb518e..0c38fb7 100644
--- a/codegen/org.eclipse.efm.modeling.codegen.xlia/src/org/eclipse/efm/modeling/codegen/xlia/core/MainCodeGenerator.java
+++ b/codegen/org.eclipse.efm.modeling.codegen.xlia/src/org/eclipse/efm/modeling/codegen/xlia/core/MainCodeGenerator.java
@@ -6,7 +6,8 @@
  * http://www.eclipse.org/legal/epl-v10.html
  *
  * Contributors:
- *     Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr - initial API and implementation
+ * 	Imen Boudhiba (CEA LIST) imen.boudhiba@cea.fr - initial API and implementation
+ *  Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr - initial API and implementation
  *******************************************************************************/
 package org.eclipse.efm.modeling.codegen.xlia.core;
 
@@ -592,19 +593,24 @@
 				}
 			}
 		}
-		writer.append(")");
-
+//old		writer.append(")");
+//new   
+		if(! firstParam ) {
+		writer.append(", ");
+		}
+//		
 		firstParam = true;
 		for( Parameter itParameter : parameters ) {
 			if( itParameter.getDirection() == ParameterDirectionKind.RETURN_LITERAL ) {
 				if( firstParam ) {
-					writer.append(" --> (");
+//old					writer.append(" --> (");
 					firstParam = false;
 				}
 				else {
 					writer.append(", ");
-				}
-				writer.append( fDataTypeFactory.typeName(itParameter) )
+				}//new next line
+				writer.append("return ")
+					.append( fDataTypeFactory.typeName(itParameter) )
 					.append(' ')
 					.append(itParameter.getName());
 
diff --git a/codegen/org.eclipse.efm.modeling.codegen.xlia/src/org/eclipse/efm/modeling/codegen/xlia/core/StatemachineCodeGenerator.java b/codegen/org.eclipse.efm.modeling.codegen.xlia/src/org/eclipse/efm/modeling/codegen/xlia/core/StatemachineCodeGenerator.java
index e2db7bb..0d4e38e 100644
--- a/codegen/org.eclipse.efm.modeling.codegen.xlia/src/org/eclipse/efm/modeling/codegen/xlia/core/StatemachineCodeGenerator.java
+++ b/codegen/org.eclipse.efm.modeling.codegen.xlia/src/org/eclipse/efm/modeling/codegen/xlia/core/StatemachineCodeGenerator.java
@@ -6,7 +6,7 @@
  * http://www.eclipse.org/legal/epl-v10.html
  *
  * Contributors:
- *     Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr - initial API and implementation
+ * 	   Imen Boudhiba (CEA LIST) imen.boudhiba@cea.fr - initial API and implementation
  *******************************************************************************/
 package org.eclipse.efm.modeling.codegen.xlia.core;
 
@@ -40,7 +40,8 @@
 public class StatemachineCodeGenerator extends AbstractCodeGenerator {
 
 	public static final String TRANSITION_GUARD_ELSE = "else";
-
+	
+	public static final String TRANSITION_TRIGGER_FINAL = "final";
 
 	/**
 	 * Constructor
@@ -300,17 +301,24 @@
 			.append(element.getName())
 			.appendEol(" {");
 
-		transformStateActivity(element, writer);
+		if( ! element.isComposite() ) {
+			transformStateActivity(element, writer);
+		}
 
 		transformConnectionPoint(element, writer);
 
 		transformRegion(element.getRegions(), writer);
 
-		if( ! element.getRegions().isEmpty() ) {
-			writer.appendTab2Eol("@transition:");
+		if( element.isComposite() ) {
+			writer.appendTabEol("@transition:");
 		}
 		transformVertexTransition(element, writer);
-
+		
+		if( element.isComposite() ) {
+			writer.appendTabEol("@moe:");
+			transformStateActivity(element, writer);
+		}
+		
 		writer.appendTab("} // end state ")
 			.appendEol2(element.getName());
 	}
@@ -404,16 +412,30 @@
 		TimedTransition timedTransition =
 				StereotypeUtil.getTimedTransition(element);
 		
-		boolean isElseGuard =
-				fSupervisor.isConstraintSymbol(element.getGuard(), TRANSITION_GUARD_ELSE);
+		//completion transition
+		boolean isFinalTrigger = ( element.getTrigger(
+				TRANSITION_TRIGGER_FINAL) != null );
+		
+		boolean isElseGuard = fSupervisor.isConstraintSymbol(
+				element.getGuard(), TRANSITION_GUARD_ELSE);
 
 		boolean isElseTransition = isElseGuard && (timedTransition == null);
 		
 		writer.appendTab("transition");
-		if( isElseTransition ) {
+		if( isFinalTrigger ) {
+			writer.append("< final ");
+			if( isElseTransition ) {
+				writer.append("& else >");
+			}
+			else {
+				writer.append(">");
+			}
+		}
+		else if( isElseTransition ) {
 			writer.append("< else >");
 		}
-		
+			
+
 		if( element.getName() != null ) {
 			writer.append(' ')
 				.append(element.getName());
@@ -506,6 +528,9 @@
 	 * @param writer
 	 */
 	public void transformTrigger(Trigger trigger, PrettyPrintWriter writer) {
+		if( TRANSITION_TRIGGER_FINAL.equals(trigger.getName()) ) {
+			return;
+		}
 
 		writer.appendTab2("input ");
 
diff --git a/codegen/org.eclipse.efm.modeling.codegen.xlia/src/org/eclipse/efm/modeling/codegen/xlia/util/StatemachineContext.java b/codegen/org.eclipse.efm.modeling.codegen.xlia/src/org/eclipse/efm/modeling/codegen/xlia/util/StatemachineContext.java
index 8c8132d..40aa3ff 100644
--- a/codegen/org.eclipse.efm.modeling.codegen.xlia/src/org/eclipse/efm/modeling/codegen/xlia/util/StatemachineContext.java
+++ b/codegen/org.eclipse.efm.modeling.codegen.xlia/src/org/eclipse/efm/modeling/codegen/xlia/util/StatemachineContext.java
@@ -246,6 +246,8 @@
 		return( transition );

 	}

 	

+	

+	

 	public Transition createElseTransition(

 			String name, Vertex source, Vertex target) {		

 		Transition transition = region.createTransition(name);

@@ -262,6 +264,37 @@
 	}

 

 	

+	

+	public Transition createFinalTransition(

+			String name, Vertex source, Vertex target) {		

+		Transition transition = region.createTransition(name);

+		

+		transition.setSource(source);

+		transition.setTarget(target);

+		

+		transition.createTrigger(StatemachineCodeGenerator.TRANSITION_TRIGGER_FINAL);

+		

+		return( transition );

+	}

+	

+	

+	public Transition createFinalElseTransition(

+			String name, Vertex source, Vertex target) {		

+		Transition transition = region.createTransition(name);

+		

+		transition.setSource(source);

+		transition.setTarget(target);

+		

+		transition.createTrigger(StatemachineCodeGenerator.TRANSITION_TRIGGER_FINAL);

+		

+		Constraint constraint = transition.createGuard("ElseGuardConstraint");

+		Expression guardExpression = UMLFactory.eINSTANCE.createExpression();

+		guardExpression.setSymbol(StatemachineCodeGenerator.TRANSITION_GUARD_ELSE);

+		constraint.setSpecification(guardExpression);

+		

+		return( transition );

+	}

+	

 	public void addInputMessage(Message message){

 		if( ! inputMessage.contains(message) ) {

 			inputMessage.add(message);

diff --git a/codegen/org.eclipse.efm.modeling.codegen.xlia/src/org/eclipse/efm/modeling/codegen/xlia/util/UmlFactory.java b/codegen/org.eclipse.efm.modeling.codegen.xlia/src/org/eclipse/efm/modeling/codegen/xlia/util/UmlFactory.java
index fd560b0..cb151b6 100644
--- a/codegen/org.eclipse.efm.modeling.codegen.xlia/src/org/eclipse/efm/modeling/codegen/xlia/util/UmlFactory.java
+++ b/codegen/org.eclipse.efm.modeling.codegen.xlia/src/org/eclipse/efm/modeling/codegen/xlia/util/UmlFactory.java
@@ -10,10 +10,17 @@
  *******************************************************************************/

 package org.eclipse.efm.modeling.codegen.xlia.util;

 

+import java.util.ArrayList;

+import java.util.List;

+

+import org.eclipse.emf.common.util.EList;

 import org.eclipse.uml2.uml.Behavior;

 import org.eclipse.uml2.uml.Constraint;

 import org.eclipse.uml2.uml.Expression;

+import org.eclipse.uml2.uml.Interaction;

 import org.eclipse.uml2.uml.InteractionConstraint;

+import org.eclipse.uml2.uml.InteractionFragment;

+import org.eclipse.uml2.uml.Lifeline;

 import org.eclipse.uml2.uml.LiteralBoolean;

 import org.eclipse.uml2.uml.LiteralInteger;

 import org.eclipse.uml2.uml.LiteralReal;

@@ -33,7 +40,7 @@
 import org.eclipse.uml2.uml.ValueSpecification;

 

 public class UmlFactory {

-	private static final String LANGUAGE_X_LIA = "xLIA";

+	public static final String LANGUAGE_X_LIA = "xLIA";

 	

 

 	///////////////////////////////////////////////////////////////////////////

@@ -176,12 +183,21 @@
 	}

 	

 	public static void addOpaqueBehaviorEffect(Transition transition, String opaqBehavior) {

-		OpaqueBehavior effectBehavior = UMLFactory.eINSTANCE.createOpaqueBehavior();

+		Behavior behavior = transition.getEffect();

+		

+		OpaqueBehavior effectBehavior = null;

+		if(behavior instanceof OpaqueBehavior) {

+			effectBehavior = (OpaqueBehavior) behavior;

+		}

+		

+		if( effectBehavior == null ) {

+			effectBehavior = UMLFactory.eINSTANCE.createOpaqueBehavior();

+			effectBehavior.setName("effect");

+			transition.setEffect(effectBehavior);

+		}

+		

 		effectBehavior.getLanguages().add(LANGUAGE_X_LIA);

 		effectBehavior.getBodies().add(opaqBehavior);

-		effectBehavior.setName("effect");

-

-		transition.setEffect(effectBehavior);

 	}

 

 	public static void setGuard(Transition transition, Constraint guard) {

@@ -220,6 +236,31 @@
 	}

 	

 	

+	public static void addEffectGuard(Transition transition, Constraint guard) {

+		StringBuffer valueBuffer = new StringBuffer("guard( ");

+

+		

+		if( guard != null ) {

+			ValueSpecification valueSpec = guard.getSpecification();

+			if( valueSpec instanceof OpaqueExpression ) {

+				for (String body : ((OpaqueExpression)valueSpec).getBodies()) {

+					valueBuffer.append(body);

+				}

+				valueBuffer.append(" );");

+			}

+			else if( valueSpec instanceof Expression ) {

+				Expression valueExpr = (Expression) valueSpec;

+				valueBuffer.append(valueExpr); //TODO expression to string

+			}

+			else {

+				valueSpecificationToString(valueSpec, valueBuffer);

+			}

+		}

+		

+		addOpaqueBehaviorEffect(transition, valueBuffer.toString());

+	}

+	

+	

 	public static void valueSpecificationToString(

 			ValueSpecification value, StringBuffer stringVar) {

 		if( value instanceof LiteralBoolean ) {

@@ -252,6 +293,12 @@
 

 			stringVar.append(")");

 		}

+		

+		else if( value instanceof OpaqueExpression ) {

+			OpaqueExpression expr = (OpaqueExpression) value;

+			stringVar.append(expr.getBodies().get(0).toString());

+		}

+		

 		else if(  value != null ) {

 			final String name = value.getName();

 			if( name != null ) {

@@ -270,20 +317,8 @@
 			Constraint constraint = transition.createGuard("guardConstraint");

 			ValueSpecification valueSpec = interactionGuard.getSpecification();

 			

-			StringBuffer loopIndexConstraint = new StringBuffer();

-			if( interactionGuard.getMinint() != null ) {

-				loopIndexConstraint.append(indexVar.getName()).append(" >= ");

-				valueSpecificationToString(interactionGuard.getMinint(), loopIndexConstraint);

+			String loopIndexConstraint = toIndexConstraint(interactionGuard, indexVar);

 

-			}

-			if( interactionGuard.getMaxint() != null ) {

-				if( loopIndexConstraint.length() > 0 ) {

-					loopIndexConstraint.append(" && ");

-				}

-				loopIndexConstraint.append(indexVar.getName()).append(" <= ");

-				valueSpecificationToString(interactionGuard.getMaxint(), loopIndexConstraint);

-			}

-			

 			if( valueSpec instanceof OpaqueExpression ) {

 				OpaqueExpression guardSpecification = UMLFactory.eINSTANCE.createOpaqueExpression();

 				guardSpecification.getLanguages().addAll(((OpaqueExpression)valueSpec).getLanguages());

@@ -311,5 +346,26 @@
 		}

 	}

 	

+	public static String toIndexConstraint(InteractionConstraint interactionGuard, Property indexVar) {

+		if( interactionGuard != null ) {

+			StringBuffer loopIndexConstraint = new StringBuffer();

+			if( interactionGuard.getMinint() != null ) {

+				loopIndexConstraint.append(indexVar.getName()).append(" >= ");

+				valueSpecificationToString(interactionGuard.getMinint(), loopIndexConstraint);

+

+			}

+			if( interactionGuard.getMaxint() != null ) {

+				if( loopIndexConstraint.length() > 0 ) {

+					loopIndexConstraint.append(" && ");

+				}

+				loopIndexConstraint.append(indexVar.getName()).append(" <= ");

+				valueSpecificationToString(interactionGuard.getMaxint(), loopIndexConstraint);

+			}

+			

+			return loopIndexConstraint.toString();

+		}

+		

+		return "true";

+	}

 	

 }

diff --git a/gui/org.eclipse.efm.modeling.ui.views.property.tab.xlia/src/org/eclipse/efm/papyrus/view/property/concretesyntax/sheet/EditingPropertyCodeGenerator.java b/gui/org.eclipse.efm.modeling.ui.views.property.tab.xlia/src/org/eclipse/efm/papyrus/view/property/concretesyntax/sheet/EditingPropertyCodeGenerator.java
index 8e73af5..cc55bfe 100644
--- a/gui/org.eclipse.efm.modeling.ui.views.property.tab.xlia/src/org/eclipse/efm/papyrus/view/property/concretesyntax/sheet/EditingPropertyCodeGenerator.java
+++ b/gui/org.eclipse.efm.modeling.ui.views.property.tab.xlia/src/org/eclipse/efm/papyrus/view/property/concretesyntax/sheet/EditingPropertyCodeGenerator.java
@@ -11,6 +11,7 @@
 import java.io.StringWriter;
 
 import org.eclipse.efm.modeling.codegen.xlia.core.MainCodeGenerator;
+import org.eclipse.efm.modeling.codegen.xlia.core.StatemachineCodeGenerator;
 import org.eclipse.efm.modeling.codegen.xlia.util.PrettyPrintWriter;
 import org.eclipse.efm.modeling.formalml.TimedTransition;
 import org.eclipse.efm.modeling.formalml.helpers.StereotypeUtil;
@@ -225,16 +226,29 @@
 		TimedTransition timedTransition =
 				StereotypeUtil.getTimedTransition(element);
 		
-		boolean isElseGuard =
-				super.isConstraintSymbol(element.getGuard(), "else");
+		boolean isFinalTrigger = ( element.getTrigger(
+				StatemachineCodeGenerator.TRANSITION_TRIGGER_FINAL) != null );
+		
+		boolean isElseGuard = fSupervisor.isConstraintSymbol(
+				element.getGuard(), StatemachineCodeGenerator.TRANSITION_GUARD_ELSE);
 
 		boolean isElseTransition = isElseGuard && (timedTransition == null);
 		
 		writer.appendTab("transition");
-		if( isElseTransition ) {
+		if( isFinalTrigger ) {
+			writer.append("< final ");
+			if( isElseTransition ) {
+				writer.append("& else >");
+			}
+			else {
+				writer.append(">");
+			}
+		}
+		else if( isElseTransition ) {
 			writer.append("< else >");
 		}
 		
+		
 		if( element.getName() != null ) {
 			writer.append(" ")
 				.append(element.getName());