/*
-----------------------------------------------------------------------
--          			CHESS M2M plugin							 --
--                                                                   --
--                    Copyright (C) 2011-2012                        --
--                 University of Padova, ITALY                       --
--                                                                   --
-- Author: Alessandro Zovi         azovi@math.unipd.it 		         --
--                                                                   --
-- 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-v20.html                         --
--																	 --
-- 20150114: SP change in getLifeLineInstance to avoid trouble       -- 
-- in case of an InstanceSpecification whose name is a substring of  --
-- another. 														 --
-----------------------------------------------------------------------
*/

import ProfileUtils_Inst_full;
import UMLUtils_Inst_full;
import chess.lib;
import chess.libJava4QVTutils;
	
modeltype UML uses "http://www.eclipse.org/uml2/5.0.0/UML";
modeltype MARTEP uses "http://www.eclipse.org/papyrus/MARTE/1";
modeltype CHESS uses "http://CHESS";	
modeltype ECORE uses "http://www.eclipse.org/emf/2002/Ecore";
modeltype MARTEGRM uses "http:///MARTE_Library/GRM_BasicTypes.ecore";
	

transformation CHESS_PIM2PSM(inout source:UML);

configuration property analysisType : String;
configuration property deadline : String;
configuration property scenario : String;
configuration property saAnalysis : String;
configuration property saE2EFlow : String;

property model : Model = null;
property psmView : Package = null;
property compView : Package = null;
property depView : Package = null;
property MARTEProfile : Profile = null;
property CHESSProfile : Profile = null;

--property platform : Package = null;
property psmPackage : Package = null;
property hostPackage : Package = null;
property operationPackage : Package = null;
property taskPackage : Package = null;
property partitionPackage : Package = null;
property analysisContextPackage : Package = null;

property assigns : Set(Comment) = null;
property partitionAssigns : Set(Comment) = null;
property specs : Set(Comment) = null;
property partitions :Set(Classifier) = null;
property slots : Set(Slot) = null;
property slotInstances : Set(Slot) = null;
property e2eOperations : Set(Operation) = null;

property instSpecPackage : Package = null;
//property instSpecFullPackage : Package = null;

property currentConcurRes : MARTE::SRM::SW_Concurrency::SwSchedulableResource = null;
property currentSlot : Slot = null;
/*Global variable for partition processing*/
property currentProcessor : InstanceSpecification = null;
property currentCore : String = null;
property currentHost : MARTE::SAM::SaExecHost = null;

property slotinAssigns = false;

property isRUN = false;
//property currentSharedRes : MARTE::SAM::SaSharedResource = null;
	
main() {
	//analysisType:= "Schedulability";
	//saAnalysis := "model::modelAnalysisView::modelRTAnalysisView::SaAnalysisContext1";
	
    log("*** CHESS PIM->PSM transformation   ***");
    log("Performing " + analysisType + " Analysis");
    log("Analysis Context is " + saAnalysis);
	log("End2End Scenario is " + saE2EFlow);
	
	model := source.rootObjects()![Model];
	MARTEProfile := model.getView("ComponentView").getAppliedProfiles()->selectOne(name="GCM").owner.owner.oclAsType(Profile);
	CHESSProfile := model.getAppliedProfiles()->selectOne(name="CHESS").oclAsType(Profile);
	
	initUtils(MARTEProfile, CHESSProfile);
	
	model.map psmModel();
}

mapping inout Model::psmModel() {
	init{
		psmView := self.getView("PSMView");
		
		compView := self.getView("ComponentView");
		depView := self.getView("DeploymentView");
			
		var saAnalysisClass := self.allOwnedElements()[Class]->selectOne(qualifiedName=saAnalysis);
		var saAnalysisCtx := saAnalysisClass.getMetaclass(SaAnalysisContextQN).oclAsType(MARTE::SAM::SaAnalysisContext);
		
		//var platforms := saAnalysisCtx.platform->asSequence();
		//instSpecPackage := platforms->first().oclAsType(CHESS::Core::CHGaResourcePlatform).base_Package;
		instSpecPackage := saAnalysisCtx.getSwSystemInstPackage();
	}
	
	assert fatal (instSpecPackage <> null)
		with log("CHGaResourcesPlatform is not present: there should be one CHGaResourcePlatform in the Analysis Context");
	
	assert fatal (instSpecPackage->size()=1) 
		with log("Ambiguous analysis scenario: there should be only one CHGaResourcePlatform in the Analysis Context");
			
	log("<<CHGaResourcesPlatform>> found.");	
	instSpecPackage.map CHGaResourcePlatform2SaAnalysisContext(saAnalysisCtx);
}

//maps the Package of the SW instances to an AnalysisContext
mapping Package::CHGaResourcePlatform2SaAnalysisContext(saAnalysisCtx : MARTE::SAM::SaAnalysisContext) : Class {
	init{
		log("Generating <<SaAnalysisContext>> and necessary packages.");
		
		psmPackage := object Package {
			name := saAnalysisCtx.base_NamedElement.name + "_PSM";
		};
		hostPackage := object Package {
			name := "Host";
		};   
		operationPackage := object Package {
			name := "Operation";
		};
		taskPackage := object Package {
			name := "Task";
		};
		
		partitionPackage := object Package{
			name := "Partition";
		};
		
		analysisContextPackage := object Package{
			name := "AnalysisContext";
		};
		
		

		psmView.packagedElement += psmPackage;
	    psmPackage.packagedElement += hostPackage;
		psmPackage.packagedElement += operationPackage;
		psmPackage.packagedElement += taskPackage;
		psmPackage.packagedElement += partitionPackage;
		psmPackage.packagedElement += analysisContextPackage;
		
		var psmPkg := psmPackage.applyStereotype(getCHESSStereotype("PSMPackage")).oclAsType(CHESS::Core::PSMPackage);
		psmPkg.AnalysisContext := saAnalysisCtx;
		
	}
	
	// analysisContextPackage
	analysisContextPackage.applyProfile(getMARTEProfile("GQAM"));

	/*
	Creation of the "AnalysisContext" package
	(<<saAnalysisContext>> containing :
	<<saEndToEndFlow>>, Constraint as <<gaLatencyObs>>,
	<<gaWorkloadEvent>>, OpaqueAction as <<saStep>>)
	*/
	
	result.name := model.name + "_analysisContext";
	analysisContextPackage.packagedElement += result;	
	// Apply the stereotype <<saAnalysisContext>>
	var analysisC := result.applyStereotype(getMARTEStereotype("SaAnalysisContext")).oclAsType(MARTE::SAM::SaAnalysisContext);
	analysisC.context += "(tool=mast,options=(invoke=true,recoverResults=true,overwriteResults=true,overwriteOutputModel=true,modeID=''))";
	
	end{
	
	// hostPackage
	
	hostPackage.applyProfile(getMARTEProfile("HwComputing"));
	hostPackage.applyProfile(getMARTEProfile("HwCommunication"));
	hostPackage.applyProfile(getMARTEProfile("GQAM"));
	
	
	// Retrieve all <<Assign>>
	//assumption: Assign are owned by the System component in the DeploymentView
	var systemComp = saAnalysisCtx.getSystem();
	assert fatal (systemComp <> null)
		with log("<<CHGaResourcesPlatform>> System is not present: there should be a CHGaResourcePlatform Package in the AnalysisContext.platform pointing to the System instances");
	assigns := systemComp.allOwnedElements()[Comment]->select(isStereotyped(AssignQN))->asSet();
	
	//retrieve Partitions Assign from the ComponentView
	partitionAssigns := compView.allOwnedElements()[Comment]->select(isStereotyped(AssignQN))->asSet();
	
	assert fatal (assigns <> null)
		with log ("No <<Assign>> found in input model");	
			
	assigns.getTo()->asSet()->select(isProcessor())->HwProcessor2SaExecHostHelper();
	
	//TODO
	//ComputingResource does not contain info about number of cores so the following line should be removed...
	//assigns.getTo()->asSet()->select(isComputingResource())->map HwComputingResource2SaExecHost();
	
	self.ownedMember[InstanceSpecification]->select(isBus())->processBus();
	
	// operationPackage
	
	var comps := compView.allOwnedElements()[Component]->select(isStereotyped(ComponentImplementationQN));
	
	/*Partition support Begin*/
	var functParts := compView.allOwnedElements()[Component]->select(isStereotyped(FunctionalPartitionQN));
	/*Partition support End*/
	
	assert fatal (comps <> null)
		with log ("No <<ComponentImplementation>> found in input model");
	
	// taskPackage
		
	slots := instSpecPackage.allOwnedElements()[Slot]->select(owningInstance.classifier <> null and isCHRtPortSlotCorrect())->asSet();
	
	assert fatal (slots <> null)
		with log ("No <<CHRtPortSlot>> found in input model");
	
	specs := compView.allOwnedElements()[Comment]->select(isStereotyped(CHRtSpecificationQN))->asSet();
	
	assert fatal (specs <> null)
		with log ("No <<CHRtSpecification>> found in input model");	
	
	taskPackage.applyProfile(getMARTEProfile("GRM"));
	
	/*in case of allocation of components to cores, the source of the Assign are slots, i.e. instances of ports
	in case of avionics, functional components appears as source of Assign
	*/
	
	assigns->forEach(ass){
		var asg := ass.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);

		//TODO assumption: one annotatedElement per Assign	
		var list := ass.getInstances(instSpecPackage);
		if(list->size()>0){
			
			slotinAssigns := false;
			list->forEach(e){
				//var id := e.getMetaclass("CHESS::Core::IdentifInstance").oclAsType(CHESS::Core::IdentifInstance);
				slotInstances += e.slot->select(owningInstance.classifier <> null and isCHRtPortSlotCorrect())->asSet();
				if(e.classifier.getMetaclass(FunctionalPartitionQN)->asSequence()->first()<>null){
					partitions += e.classifier;
				/*it is a partition*/				
				};
			}
		} else {
			slotinAssigns := true;
			var slotList := ass.getSlotInstances(instSpecPackage);
			slotInstances += slotList;
		
		}
		
	};
	
	log("Slot list(" + slotInstances->size().toString()+"):");
	slotInstances->forEach(s){
		log("  "+s.definingFeature.name);
	};
	log("Partition list(" + partitions->size().toString()+"):");
	partitions->forEach(s){
		log("  "+s.name);
	};
	
	log("");
	log("*** Proceeds to create SwSchedulableResources and SaSteps ***");
	/*If there are no functional partitions go here; in fact in case of partitions the 'from' field of the Assing has partition instance instead of slot*/
	if(slotInstances->size()<>0){
		slotInstances->forEach(s){
			var specs := s.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot).cH_RtSpecification;
			specs->forEach(spec){
			    log("***Processing Slot" +s.getStringId()+ " defining feature " +s.getStringId()+ s.definingFeature.name+ " for " + s.owningInstance.name + s.owningInstance.getStringId() + " and operation "+ spec.context.name +".");
			    
			    //maps only if the operation is deferred
				s.map CHRtSlot2SwSchedulableResource(spec.base_Comment);  
				//now creates the <<SaStep>> operations
			    spec.base_Comment.CHRTComment2SaStep(s, s.owningInstance);
			}; 
		};
		/*else process functional partitions*/
	} else if (partitions->size()<>0) {
		partitions->forEach(p){
			
			var partitionInst := p.getPartitionInstance();
			var pPSM := partitionInst.map Partition2Package();
			
			currentProcessor := partitionInst.getAssignedProcessor();
			currentCore := partitionInst.getAssignedCore();
			var partition := partitionInst.map Partition2PSM();
			currentHost := partition.getMetaclass(SaExecHostQN).oclAsType(MARTE::SAM::SaExecHost);
			
			partitionInst.getComponentsOfPartition()->forEach(componentInst){
				log("Analysing classifier" + componentInst.classifier![Classifier].name +" mapped on partition " +p.name);
				
				/*
				Assumption:
					1)ARINCFunction operation cannot appear as provided operations
				    2)CHRtSPecification for ARINCFFunctions are associated to the Component Instance through the CHRtPortSlot (where the latter extends InstanceSpecification)
				*/
				
				//checking chrtSpec associated to the componentInstance
				var chrtportslot := componentInst.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot);
				var privateChrtSpecs := chrtportslot.cH_RtSpecification;
				
				
				privateChrtSpecs->forEach(privatechrtspec){
					var arincFuncStereo = privatechrtspec.context.getMetaclass(ARINCFunctionQN).oclAsType(chessmlprofile::ARINCComponentModel::ARINCFunction);
					if (arincFuncStereo <> null) {
						
					    log("Mapping ARINCFunction " + privatechrtspec.context.name);
					    
						//fix any missing information for chrtspec, like period; derive it from the ARINCProcess
						componentInst.getUpdatedArincFunChrtSpec(privatechrtspec.base_Comment.oclAsType(Comment));
						
						//maps only if the operation is deferred
						var schedRes : Class := componentInst.map Instance2SwSchedulableResource(privatechrtspec.base_Comment);
						var temp : Class;
						/*create a class that refere to the schedulabe resource in the right partition package*/
						object temp : Class {
							name := schedRes.name;
							redefinedClassifier+=schedRes;
						};
						pPSM.packagedElement+=temp;  
						//now creates the <<SaStep>> operations
					    
					    //componentInst.map InstanceUnprotected2SaStep(privatechrtspec.base_Comment, componentInst);
					    privatechrtspec.base_Comment.CHRTComment2SaStep(null, componentInst);
						
			
					};
				};

				//checking chrtSpec associated to the componentInstance slots, i.e. provided chrtSpec
				var componentInstSlots := componentInst.slot->select(owningInstance.classifier <> null and isCHRtPortSlotCorrect())->asSet();
				componentInstSlots->forEach(componentInstSlot){
					var specs := componentInstSlot.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot).cH_RtSpecification;	
					specs->forEach(spec){
					    log("***Processing Slot" +componentInstSlot.getStringId()+ " defining feature " +componentInstSlot.getStringId()+ componentInstSlot.definingFeature.name+ " for " + componentInstSlot.owningInstance.name + componentInstSlot.owningInstance.getStringId() + " and operation "+ spec.context.name +".");
					    
					    //ARINC Process must not be mapped
					   var arincFuncStereo = spec.context.getMetaclass(ARINCFunctionQN).oclAsType(chessmlprofile::ARINCComponentModel::ARINCFunction);
					   if (arincFuncStereo <> null){
					    	
					    	//TODO it is allowed to have ARINCFunctions here, i.e. as provided operations?
					    
					    	//TODO fix any missing information for chrtspec, like period; derive it from the ARINCProcess
					    	 log("*********Processing provided ARINC FUNCTION...... !!!!!!!!!!!!!************** ");
					    	componentInst.getUpdatedArincFunChrtSpec(spec.base_Comment.oclAsType(Comment)); 
										  						    
						    //maps only if the operation is deferred
							var schedRes : Class := componentInstSlot.map CHRtSlot2SwSchedulableResource(spec.base_Comment);
							var temp : Class;
							/*create a class that refere to the schedulabe resource in the right partition package*/
							object temp : Class {
								name := schedRes.name;
								redefinedClassifier+=schedRes;
							};
							pPSM.packagedElement+=temp;  
							//now creates the <<SaStep>> operations
						    spec.base_Comment.CHRTComment2SaStep(componentInstSlot, componentInst);
						 }
					}; 
				};
			};		
		};
	} else {
		//TODO error!
	};
	
	if(analysisType.equalsIgnoreCase("Schedulability")) then {
		
	//Proceed to create the EndToEndWorkFlow now since all the necessary resources are generated
		log("");
		log("***Creating the EndToEndWorkFlow ***");
		if(slotInstances->size()<>0){
		slotInstances->forEach(s){
			var specs := s.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot).cH_RtSpecification;
			specs->forEach(spec){
				s.map slot2EndToEndWorkFlow(spec.base_Comment);
			};
		};
		} else if (partitions->size()<>0) {
			partitions->forEach(p){
			/*TODO what happens	 if  an operation calls an operation of a different partition?*/
				var pInst := p.getPartitionInstance();
				var pPSM := pInst.map Partition2PSM();
				currentProcessor := pInst.getAssignedProcessor();
				currentCore := pInst.getAssignedCore();
				
				pInst.getComponentsOfPartition()->forEach(componentInst){
					
					log("Analysing instance " + componentInst.classifier![Classifier].name +" mapped on partition " +p.name);
				
					/*
					Assumption:
						1)ARINCFunction operation cannot appear as provided operations
					    2)CHRtSPecification for ARINCFFunctions are associated to the Component Instance through the CHRtPortSlot (where the latter extends InstanceSpecification)
					*/
					
					//checking chrtSpec associated to the componentInstance
					var chrtportslot := componentInst.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot);
					var privateChrtSpecs := chrtportslot.cH_RtSpecification;
					
					
					privateChrtSpecs->forEach(privatechrtspec){
						var arincFuncStereo = privatechrtspec.context.getMetaclass(ARINCFunctionQN).oclAsType(chessmlprofile::ARINCComponentModel::ARINCFunction);
						if (arincFuncStereo <> null) {
							
						    log("Mapping ARINCFunction " + privatechrtspec.context.name);
						    
							privatechrtspec.base_Comment.map Instance2EndToEndWorkFlow(null, componentInst);
							
						};
					};
					//end 
					

					var instances := componentInst.slot->select(owningInstance.classifier <> null and isCHRtPortSlotCorrect())->asSet();
					instances->forEach(s){
						var specs := s.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot).cH_RtSpecification;
						specs->forEach(spec){
							
							 //ARINC Process must not be mapped
					   		var arincFuncStereo = spec.context.getMetaclass(ARINCFunctionQN).oclAsType(chessmlprofile::ARINCComponentModel::ARINCFunction);	
							if (arincFuncStereo <> null){
								log("*********Processing provided ARINC FUNCTION...... TO BE DONE!!!!!!!!!!!!!************** "); 
						    	s.map slot2EndToEndWorkFlow(spec.base_Comment);
						    }
						}; 
					};
				};		
		};
		} else {
		//TODO error!
		};
	} endif;
	
	
	if(analysisType.equalsIgnoreCase("EndToEnd")) then {
		
		//EndToEndWorkFlow for E2E Scenario
		--2015/02/23 - NP: added a check to avoid null pointers @ c.qualifiedName and @ a.qualifiedName 
		var pimContext : Class = model.allOwnedElements()[Class]->selectOne(c : Class | not c.qualifiedName.oclIsUndefined() and c.qualifiedName.equalsIgnoreCase(saAnalysis));
		var pimActivity : Activity = model.allOwnedElements()[Activity]->selectOne(a : Activity | not a.qualifiedName.oclIsUndefined() and a.qualifiedName.equalsIgnoreCase(saE2EFlow));
		var interactions : Set(Interaction) := model.allOwnedElements()[Interaction];
		interactions->forEach(interaction){
		if(interaction.qualifiedName.equalsIgnoreCase(scenario)) then {
			log(">>>>> Found End-To-End Scenario: " + interaction.name);
			interaction.map Interaction2EndToEndWorkFlow(result, pimContext, pimActivity);
		} endif;
		
		log("e2e operations:");
		e2eOperations->forEach(op){
			log("   "+ op.name)
		};
		
		//Proceeds to create the EndToEndWorkFlow for those tasks not involved in the e2e scenario"
		log("*** Proceeds to create the EndToEndWorkFlow ***");
		slotInstances->forEach(s){
			var specs := s.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot).cH_RtSpecification;
			specs->forEach(spec){
				if(not e2eOperations->exists(op: Operation | op.name.equalsIgnoreCase(spec.context.name))) then {
					log("Operation is: " +  spec.context.name);
				    s.map slot2EndToEndWorkFlow(spec.base_Comment);
				} endif;
			};
		};		
	};

	} endif;
	
		log("*** End of CHESS PIM->PSM transformation ***");
	}

}

//context: the PSM analysisContext - used to read analysis reuslts to backpropagate to PIM
//pimContext, pimActivity: PIM entities to be updated by the backpropagation
//
mapping Interaction::Interaction2EndToEndWorkFlow(context : Class, pimContext : Class, pimActivity: Activity) : Activity{
	init {
		log("Generating <<EndToEndWorkFlow>> from " +  self.name);
		
		//First we get a list of ordered messages 
		//it is based on the assumption that each message starts with a progressive number to keep their order
		var messageSequence : Sequence(Message) := self.message->sortedBy(name)->asSequence();
		log("****** messages sequence");
		messageSequence->forEach(msg){
			log("          " + msg.name)
		};
		//get starting chrts for initializing the <<gaWorkloadEvent>> pattern
		var startMsg := messageSequence->first();
   		var startChrts := startMsg.getMsgChrts();
   	}
   	
   	result.name := self.name;
    // Add the action to the owned behaviors of RTAnalysisContext     
    instSpecPackage.resolveoneIn(Package::CHGaResourcePlatform2SaAnalysisContext, Class).ownedBehavior += result;
    //Apply the stereotype <<SaEndtoEndFlow>> to the activity
	result.applyStereotype(getMARTEStereotype("SaEndtoEndFlow"));
	//Global Timing Requirement
	var actConstraint := new Constraint("Global_Timing_Req");
	result.precondition += actConstraint;
	
	var actInitialNode := result.createInitialNode();
	var controlFlowInit := new ControlFlow("ControlFlowInit");
	actInitialNode.outgoing += controlFlowInit;
	result.edge += controlFlowInit;
	
	//Apply stereotype <<gaLatencyObs>> and specify the deadline for the end to end flow
	var gaLatencyObs := actConstraint.applyStereotype(getMARTEStereotype("GaLatencyObs")).oclAsType(MARTE::GQAM::GaLatencyObs);
	gaLatencyObs.latency += deadline.parseNFPDuration("value");
	
	//Apply stereotype <<gaWorkloadEvent>> and specify the release pattern of the end-to-end flow
	var gaWorkloadEvent := actInitialNode.applyStereotype(getMARTEStereotype("GaWorkloadEvent")).oclAsType(MARTE::GQAM::GaWorkloadEvent);
	gaWorkloadEvent.pattern := startChrts.occKind;
	
	//create end2end action sequence 
	var resultNode := createE2EOpaqueActionsChain(messageSequence, result, actInitialNode);
	
	//create final node
	//var finalNode := new ActivityFinalNode("ActivityFinalNode1");
	var finalNode := result.createFinalNode();
	//result.node += finalNode;
	
	resultNode.outgoing![ControlFlow].target := finalNode;
	
	
	/*Stefano
   	//add entity to store traceability information in the model. This infomation can then be used later in the editor to show analysis results related to the PIM entites.
	*/
    var constr := new Constraint();
    constr.constrainedElement += result;
    constr.constrainedElement += pimActivity;
    instSpecPackage.resolveoneIn(Package::CHGaResourcePlatform2SaAnalysisContext, Class).ownedRule += constr;
   
    //end modification for traceability
}

//Return the nextE2ENode TODO - work in progress!!!
helper createE2EOpaqueActionsChain(in messageSequence : Sequence(Message), inout endToEndWorkFlow : Activity, inout currentNode : ActivityNode) : ActivityNode {
	
	var nextNode := currentNode;	
	messageSequence->forEach(msg){
		//log("operation is: " + msg.signature.name);
		
		var currentChrts := msg.getMsgChrts();
		//log("its context is: " +currentChrts.context.name);
		//log("its partWithPort is: " +currentChrts.partWithPort.name);
		//log("its occKind is: " +currentChrts.occKind.toString());
		//log("its protection is: " +currentChrts.protection.toString());
		//log("its WCET is: " +currentChrts.WCET.toString());
		//log("Slot [createOpaqueActionsChain]: " + currentSlot.definingFeature.name);

		//if operation is sporadic then create a get node before the operation node
		nextNode := createSporadicRelatedNodes(currentChrts, currentSlot, endToEndWorkFlow, nextNode);
		
		//Creates the subsequent OpaqueAction and ControlFlow
		nextNode := createSaStepNode(currentChrts, currentSlot, endToEndWorkFlow, nextNode, currentSlot.owningInstance);
		
		e2eOperations += currentChrts.context->oclAsType(Operation);		
	};
	
	return nextNode;
}


/*
sourceSlot can be null, e.g. in case of ARINCFunction private operation
* IT SEEMS THAT THIS IS DUPLICATED, se helper below
helper createSaStepNode(in sourceCHRtComment: Comment, in sourceSlot : Slot, inout e2eActivity : Activity, inout prevE2ENode : ActivityNode,
	ownerInstance : InstanceSpecification ) : ActivityNode {
		
	
	var chrts := sourceCHRtComment.CHRtSpec();
	var opNode := createOpaqueAction(opaqueActionName(sourceSlot, chrts), e2eActivity, prevE2ENode);
	var opSaStep := opNode.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
	
	// Set the <<SwSchedulableResource>> that executes the <<saStep>>
	
	var concurRes := currentConcurRes;
	if chrts.isDeferred() then
		concurRes := sourceCHRtComment.getConcurRes(sourceSlot)//classResource.getMetaclass(SchedulableResourceQN).oclAsType(MARTE::GRM::SchedulableResource);
	endif;
	
	zzz
	
	opSaStep.concurRes := concurRes;
    // Retrieve the <<SaStep>> to use for the subusage
	var saStep := sourceCHRtComment.resolve2SaStep().getMetaclass(SaStepQN).oclAsType(MARTE::SAM::SaStep);
	//Add the newly created operation as subUsage of the OpaqueAction(<<saStep>>)
	opSaStep.subUsage += saStep;
	
	//opSaStep.sharedRes += currentSharedRes;
	return opNode;
}*/




/*sourceSlot can be null, in case of chrt referring private operation 
*/
helper createSaStepNode(in currentCHRts: chessmlprofile::RTComponentModel::CHRtSpecification, in sourceSlot : Slot, 
		inout EndToEndWorkFlow : Activity, inout currentNode : ActivityNode, in ownerInstance:InstanceSpecification) : ActivityNode {
			
	var actionname : String;
	
	if (sourceSlot<> null) {
		actionname := opaqueActionName(sourceSlot, currentCHRts);
	}else{
		actionname := opaqueActionName(ownerInstance, currentCHRts);
	};
	
	var opNode := createOpaqueAction(actionname, EndToEndWorkFlow, currentNode);
	

	var opSaStep := opNode.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
	//log("Slot [createSaStepNode]: " + currentSlot.definingFeature.name);
	// Set the <<SwSchedulableResource>> that executes the <<saStep>>
	var concurRes := currentConcurRes;
	if currentCHRts.isDeferred() then {
		if (sourceSlot<> null) {
			concurRes := currentCHRts.base_Comment.getConcurRes(sourceSlot);
		}else{
			concurRes := currentCHRts.base_Comment.getConcurRes(ownerInstance);
		}
	}
	endif;
	
	log("********createSaStepNode in endToEnd Activity:  concuRes is " + concurRes.toString());
	
	opSaStep.concurRes := concurRes;
    // Retrieve the <<SaStep>> to use for the subusage
	var saStep := currentCHRts.base_Comment.resolve2SaStep().getMetaclass(SaStepQN).oclAsType(MARTE::SAM::SaStep);
	
	log("********createSaStepNode in endToEnd Activity:  subUsage is " + saStep.toString());
	
	//Add the newly created operation as subUsage of the OpaqueAction(<<saStep>>)
	opSaStep.subUsage += saStep;
	
	//opSaStep.sharedRes += currentSharedRes;
	return opNode;
}

/*
  Creates Bus related entities given an InstanceSpecification of a Bus
*/
helper InstanceSpecification::processBus(){
	log("Bus found for InstanceSpecification '"+self.name+"'."); 
	self.map HwBus2SaCommHost();
	self.map HwBus2OperationClass();
	self.linkedHwInstanceSpecifications()-> map BusProperty2GaCommChannel(self);
	return null;
}

//NOT USED
//mapping Slot::CHRtSlot2SwSchedulableResourceStrict(chrt : Comment) : Class when {chrt.CHRtSpec().isDeferred()} {
//	init{
//		var res := self.owningInstance.resolveoneIn(InstanceSpecification::Instance2SwSchedulableResource, Class);
//		if res = null then
//			res := self.owningInstance.map Instance2SwSchedulableResource(chrt, self)
//		else 
//			log("  Nothing to do")
//		endif;
//		result := res;
//	}
//}


mapping Slot::CHRtSlot2SwSchedulableResource(chrt : Comment) : Class when {chrt.CHRtSpec().isDeferred()} {
	init{
		var res := self.owningInstance.map Slot2SwSchedulableResource(chrt, self);
		result := res;
	}
}

mapping InstanceSpecification::Partition2Package() : Package {
	result.name := self.classifier![Classifier].name;
	partitionPackage.packagedElement += result;
}

mapping InstanceSpecification::Partition2PSM() : Class {
	result.name := self.classifier![Classifier].name;
	var package := self.resolveoneIn(InstanceSpecification::Partition2Package, Package);
	package.packagedElement += result;
	var stHost := result.applyStereotype(getMARTEStereotype("SaExecHost")).oclAsType(MARTE::SAM::SaExecHost);
	stHost.host := currentProcessor.getHost(currentCore);
	stHost.otherSchedPolicy := "IMA";
	var sr := result.applyStereotype(getMARTEStereotype("SwSchedulableResource")).oclAsType(MARTE::SRM::SW_Concurrency::SwSchedulableResource);	
	var par := self.classifier![Classifier].getMetaclass("CHESS::ComponentModel::FunctionalPartition").oclAsType(CHESS::ComponentModel::FunctionalPartition);
	log("MAF");
	log(par.MAF);	
	var schedParamMAF := "MAF=(value=" + par.MAF +")";
	var schedParamSchedTable := "SCHED_TABLE=(value=\""+par.SchedulingTable+"\")";	
	sr.schedParams := "("+schedParamMAF+","+schedParamSchedTable+")";
}

mapping InstanceSpecification::Slot2SwSchedulableResource(chrtComment : Comment, slot : Slot) : Class when {chrtComment.CHRtSpec().isDeferred()} {
	init{
		var chrts := chrtComment.CHRtSpec();
		var chrtportslot := slot.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot);
		var resourceName := chrts.schedulableResourceName(chrtportslot);
		log("  Operation '" + chrts.context.name + "' is deferred. Generating <<SwSchedulableResource>> '" + resourceName + "'.");
    }
	 
	result.name := resourceName;
	
	taskPackage.packagedElement += result;
	
	var sr := result.applyStereotype(getMARTEStereotype("SwSchedulableResource")).oclAsType(MARTE::SRM::SW_Concurrency::SwSchedulableResource);		
	sr.isProtected := false;
	var schedParams := "fp(priority=(" + chrts.relativePriority.normalizeNFPInteger() +", source=meas))";
	
	//TODO assume <<Assign>> 'from' and 'to' typed as InstanceSpecification	
	// Find the deployment node (InstanceSpecification), based on <<Assign>> directives
	
	if(currentHost <> null){
		sr.host := currentHost;//currentProcessor.getHost(currentCore);
	} else {
		
		
	   if(slotinAssigns){
<<<<<<< HEAD
	   	  var hostClassifier := getAssignToFrom_MemoryPartition(slot, chrt);
	   	  if (isRUN){
	   	  	sr.host := hostClassifier.getSupertaskHost(getAssignedSupertaskFrom_MemoryPartition(slot, chrt));
	   	  	schedParams := "edf(deadline=(" + chrts.rlDl +", source=meas))";
	   	  } else {
		  	sr.host := hostClassifier.getHost(getAssignedCoreFrom_MemoryPartition(slot, chrt));
		  };
=======
	   	  var hostClassifier := getAssignToFrom_MemoryPartition(slot, chrtComment);
		  sr.host := hostClassifier.getHost(getAssignedCoreFrom_MemoryPartition(slot, chrtComment));
>>>>>>> origin/develop
	   } else {
		  var hostClassifier := getAssignToFrom_MemoryPartition(slot.owningInstance);
		  sr.host := hostClassifier.getHost(getAssignedCoreFrom_MemoryPartition(slot.owningInstance));
	   }
	};
	assert fatal (sr.host <> null)
		with log("Null Host for SwSchedulableResource '" +result.name+ "'.");
	sr.schedParams := schedParams;
}


//to be used when the CHRTSpecification is attached to a component instance and not to a port slot, e.g. in case of ARINCFUnctions decorating private operations
mapping InstanceSpecification::Instance2SwSchedulableResource(chrtComment : Comment) : Class when {chrtComment.CHRtSpec().isDeferred()} {
	init{
		var chrts := chrtComment.CHRtSpec();
		var chrtportslot := self.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot);
		var resourceName := chrts.schedulableResourceName(chrtportslot);
		log("  Operation '" + chrts.context.name + "' is deferred. Generating <<SwSchedulableResource>> '" + resourceName + "'.");
    }
	 
	result.name := resourceName;
	
	taskPackage.packagedElement += result;
	
	var sr := result.applyStereotype(getMARTEStereotype("SwSchedulableResource")).oclAsType(MARTE::SRM::SW_Concurrency::SwSchedulableResource);		
	sr.isProtected := false;
	var schedParams := "fp(priority=(value=" + chrts.relativePriority.normalizeNFPInteger() +", source=meas))";
	
	//TODO assume <<Assign>> 'from' and 'to' typed as InstanceSpecification	
	// Find the deployment node (InstanceSpecification), based on <<Assign>> directives
	
	if(currentHost <> null){
		sr.host := currentHost;//currentProcessor.getHost(currentCore);
	} else {
		
		 if(slotinAssigns){
		 	log("**************WARNING: Instance2SwSchedulableResource, this flow has not been implemented yet!!!!!");
		 }
		
		else {
		  var hostClassifier := getAssignToFrom_MemoryPartition(self);
		  sr.host := hostClassifier.getHost(getAssignedCoreFrom_MemoryPartition(self));
	   }
	};
	assert fatal (sr.host <> null)
		with log("Null Host for SwSchedulableResource '" +result.name+ "'.");
	sr.schedParams := schedParams;
}





/*
  Given a InstanceSpecification representing a Processor/ComputingResource,
  return the already generated SaExecHost
*/
query InstanceSpecification::getHost(core: String) : MARTE::SAM::SaExecHost {
	if(core<>null) {
			var ress := self.resolveIn(InstanceSpecification::HwProcessor2SaExecHost, Class).getMetaclass(SaExecHostQN).oclAsType(MARTE::SAM::SaExecHost);
			
			if(ress->size() = 1){
				var cpu := ress->selectOne(base_Classifier.name=self.name);
				assert fatal (cpu <> null)
					with log("Host "+self.name+" not found.");
				return cpu;
			};
			var res := ress->selectOne(base_Classifier.name=self.name+"_"+core);
			if(res = null){
				res := ress->selectOne(base_Classifier.name=self.name+"_core"+core);
			};
			if(res <> null){
				return res;
			};
	};
	var res := self.resolveoneIn(InstanceSpecification::HwProcessor2SaExecHost, Class).getMetaclass(SaExecHostQN).oclAsType(MARTE::SAM::SaExecHost);
	
	//TODO the following lines should be removed
	if res.oclIsInvalid() or res = null then
		return self.resolveoneIn(InstanceSpecification::HwComputingResource2SaExecHost, Class).getMetaclass(SaExecHostQN).oclAsType(MARTE::SAM::SaExecHost)
	endif;
	return res;	
}

<<<<<<< HEAD
/*
  Given a InstanceSpecification representing a Processor/ComputingResource,
  return the already generated SaExecHost
*/
query InstanceSpecification::getSupertaskHost(supertask: String) : MARTE::SAM::SaExecHost {
	
			var ress := self.resolveIn(InstanceSpecification::HwProcessor2SaExecHostSupertask, Class).getMetaclass(SaExecHostQN).oclAsType(MARTE::SAM::SaExecHost);

			if(ress->size() = 1){
				var cpu := ress->selectOne(base_Classifier.name=self.name);
				assert fatal (cpu <> null)
					with log("Host "+self.name+" not found.");
				return cpu;
			};
			var res := ress->selectOne(base_Classifier.name=self.name+supertask);
			if(res <> null){
				return res;
			};
	assert fatal (res <> null)
		with log("Unable to find the assigned supertask");
	return null;
}


helper createSaStepNode(in sourceCHRtComment: Comment, in sourceSlot : Slot, inout e2eActivity : Activity, inout prevE2ENode : ActivityNode) : ActivityNode {
	var chrts := sourceCHRtComment.CHRtSpec();
	var opNode := createOpaqueAction(opaqueActionName(sourceSlot, chrts), e2eActivity, prevE2ENode);
	var opSaStep := opNode.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
	
	// Set the <<SwSchedulableResource>> that executes the <<saStep>>
	
	var concurRes := currentConcurRes;
	if chrts.isDeferred() then
		concurRes := sourceCHRtComment.getConcurRes(sourceSlot)//classResource.getMetaclass(SchedulableResourceQN).oclAsType(MARTE::GRM::SchedulableResource);
	endif;
	opSaStep.concurRes := concurRes;
    // Retrieve the <<SaStep>> to use for the subusage
	var saStep := sourceSlot.resolve2SaStep(chrts.base_Comment).getMetaclass(SaStepQN).oclAsType(MARTE::SAM::SaStep);
	//Add the newly created operation as subUsage of the OpaqueAction(<<saStep>>)
	opSaStep.subUsage += saStep;
	
	//opSaStep.sharedRes += currentSharedRes;
	return opNode;
}

=======
>>>>>>> origin/develop
//Stefano: not clear what this method is intended to implement!!!
helper createSubUsage(in sourceCHRtComment: Comment, in sourceSlot : Slot, ownerInstance : InstanceSpecification)  {
	var chrts := sourceCHRtComment.CHRtSpec();
	
	//log(" ***********WARNING 3 : createSubUsage, chrt = " + chrts.toString() + " sourceSlot = "+sourceSlot.owningInstance.toString());
	var owningSaStep := sourceSlot.resolveoneIn(Comment::CHRTCommentProtected2SaStep, Operation).getMetaclass(SaStepQN).oclAsType(MARTE::SAM::SaStep);
	//log("createSubUsage, owningSaStep = " + owningSaStep.toString());
	owningSaStep.subUsage += sourceCHRtComment.resolve2SaStep().getMetaclass(SaStepQN).oclAsType(MARTE::SAM::SaStep); 
	
}

/*
Author: Stefano Puri
Given a CHRtSpecification representing an operation using another operation, 
it sets the dependencies through the subusage field of the SaStep mapped to the requiring operation  

*/

helper createSubUsage(in reqCHRtSpec: chessmlprofile::RTComponentModel::CHRtSpecification, in provCHRtSpec: chessmlprofile::RTComponentModel::CHRtSpecification)  {
	
	//var requiringPSMOperation = requiringSlot.resolve2SaStep(reqCHRtSpec.base_Comment);
	var requiringPSMOperation = reqCHRtSpec.base_Comment.resolve2SaStep();
	
	log("requiringPSMOperation = " + requiringPSMOperation.toString());
	
	//var piPSMOperation = providingSlot.resolve2SaStep();
	var piPSMOperation = provCHRtSpec.base_Comment.resolve2SaStep();
	
	log("usedPSMOperation = " + piPSMOperation.toString());	        			
	var reqSaStep = requiringPSMOperation.getMetaclass(SaStepQN).oclAsType(MARTE::SAM::SaStep); 		
	var provSaStep = piPSMOperation.getMetaclass(SaStepQN).oclAsType(MARTE::SAM::SaStep);  			
	log("usedStep = " + provSaStep.toString());
	reqSaStep.subUsage += provSaStep;
}


/*
  Given a comment related to a CHRtSlot return  the corresponding schedulable resource  
*/
query Comment::getConcurRes(slot : Slot) : MARTE::SRM::SW_Concurrency::SwSchedulableResource {
	
	var chrtportslot := slot.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot);
	var classResource := slot.resolveIn(Slot::CHRtSlot2SwSchedulableResource, Class)->selectOne(
	    name=self.CHRtSpec().schedulableResourceName(chrtportslot));
	return classResource.getMetaclass(SwSchedulableResourceQN).oclAsType(MARTE::SRM::SW_Concurrency::SwSchedulableResource);
}


/*
  Given an instance decorated with a CHRTSPecification returns  the corresponding schedulable resource  
*/
query Comment::getConcurRes(instance : InstanceSpecification) : MARTE::SRM::SW_Concurrency::SwSchedulableResource {
	
	var chrtportslot := instance.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot);
	
	log("");
	log("+++++++++++++++++");
	log("SEARCHING CONCURRES with NAME "+self.CHRtSpec().schedulableResourceName(chrtportslot));
	log("");
	
	var classResource := instance.resolveIn(InstanceSpecification::Instance2SwSchedulableResource, Class)->selectOne(
	    name=self.CHRtSpec().schedulableResourceName(chrtportslot));
	log("FOUND "+classResource.toString());
	log("");    
	    
	return classResource.getMetaclass(SwSchedulableResourceQN).oclAsType(MARTE::SRM::SW_Concurrency::SwSchedulableResource);
}

/*
Given a Comment stereotyped with CHRtSpecification returns the SaStep Operation previously created
*/
query Comment::resolve2SaStep() : Operation {
	var chrts := self.CHRtSpec();
	var ops : Sequence(Operation);
	log("Comment::resolve2SaStep, chrtSpecification = "+chrts.toString() +", context = "+chrts.context.toString());
	
	if (chrts.isSporadic()) then {
		ops := self.resolveIn(Comment::CHRTCommentSporadic2SaStep, Operation);
	}
	else {
		
		if (chrts.isProtected()) then {
			ops := self.resolveIn(Comment::CHRTCommentProtected2SaStep, Operation);
		} else {
			
			log("Comment::resolve2SaStep: resolve in Comment::CHRTCommentUnprotected2SaStep");
			ops := self.resolveIn(Comment::CHRTCommentUnprotected2SaStep, Operation);
		} endif;
	}
	endif;
	
	
	ops->forEach(op) {
		if op.name = chrts.context.name() then
			return op
		endif;
	};
	return null;
}


//"receive" node and "get" node
helper createSporadicRelatedNodes(in currentOp : chessmlprofile::RTComponentModel::CHRtSpecification, in currentSlot : Slot, inout e2eActivity : Activity, inout prevE2ENode : ActivityNode) : ActivityNode {
	if currentOp.isSporadic() then {
		var nextE2ENode := prevE2ENode;
		var riSlot := currentSlot.getCorrespondingSlot();
		//If the current operation responds to a remote call, creates the "receive" node first
		var connectingBus = getConnectingBus(currentSlot.owningInstance, riSlot.owningInstance);
		if connectingBus <> null then
			nextE2ENode := createReceiveOp(connectingBus, currentSlot, e2eActivity, nextE2ENode)
		endif;
		//If the current operation is sporadic, attaches the "get" operation before the operation node 
		//TODO Stefano: the following get operation should be set as subUsage of the sporadic SaStep Operation created in the PSM, it should not appear as activity
		//return createGetOp(currentOp.base_Comment, currentSlot, e2eActivity, nextE2ENode);
		return nextE2ENode;
	} 
	else
		return prevE2ENode
	endif;
	return null;
}

/*
//Return the nextE2ENode 
currentSlot can be null, in case of private operation
*/
helper createOpaqueActionsChainFull(in currentIsGuarded : Boolean, in currentCHRtComment : Comment, in currentSlot : Slot, 
	inout e2eActivity : Activity, inout prevE2ENode : ActivityNode, in owningInstance : InstanceSpecification) : ActivityNode {
	var currentCHRTSpec := currentCHRtComment.CHRtSpec();
	var nextE2ENode := prevE2ENode;
	
	log("CreateOpaqueActionChain: currentIsGuarded = "+currentIsGuarded.toString());
	
	//TODO Assumption: if currentSlot is null, i.e. the current operation is private, then the current chrtspec cannot be sporadic
	//if operation is sporadic then create receive + get nodes before the operation node
	nextE2ENode := createSporadicRelatedNodes(currentCHRTSpec, currentSlot, e2eActivity, nextE2ENode);
	
	//Creates the subsequent OpaqueAction and ControlFlow
	nextE2ENode := createSaStepNode(currentCHRTSpec, currentSlot, e2eActivity, nextE2ENode, owningInstance);
	
	//this does not create sporadic related nodes=>nextE2ENode := createSaStepNode(currentCHRtComment, currentSlot,e2eActivity, prevE2ENode);
	
	//if the operation has a ICB-Activity then parse its CallOperationNodes
	currentCHRTSpec.context.method![Activity].collectCallOperationNodes()->forEach(calledOpNode){
		
		//var riSlot := calledOpNode.onPort.portToSlot(currentSlot.owningInstance);
		var riSlots := calledOpNode.portToSlotFull(owningInstance);
		riSlots->forEach(riSlot){
			log("  Search for piSlot from riSlot '" + riSlot.owningInstance.name + riSlot.owningInstance.getStringId() + riSlot.definingFeature.name + riSlot.getStringId() + "'.");
			var usedPiSlot := riSlot.getCorrespondingSlot();
			log("  Found piSlot '" + usedPiSlot.owningInstance.name+usedPiSlot.owningInstance.getStringId() + usedPiSlot.definingFeature.name + usedPiSlot.getStringId() + "'.");
	        var usedPiCHRtSpec := usedPiSlot.CHRtSpecForOperation(calledOpNode.operation);
	        var bus := getConnectingBus(owningInstance, usedPiSlot.owningInstance);
	        
	        //if it is a remote call, attach a send operation 
	        if bus <> null then{
	        	log("it is a remote call...");
	        	
	        	if (currentSlot = null)
	        		log("*****************WARNING  createOpaqueActionsChainFull: the current slot is null, the operation is private; this path is not currently supported ...");
	        	
	        	if usedPiCHRtSpec.isDeferred() then
	        		return createSendOp(bus, currentSlot, e2eActivity, nextE2ENode)
	        	else 
	        	    //if it is a simple operation, proceeds with the subsequent call
	        		nextE2ENode := createSendOp(bus, currentSlot, e2eActivity, nextE2ENode)
	        	endif
	        }
	        else{
	        	log("it is a local call...");
		        //otherwise it is a local call
		        //if it is a simple operation, simply add it to the endtoendworkflow and proceeds with the subsequent call
				if usedPiCHRtSpec.isDeferred() then {
					// Calls "put" operation
					//TODO Stefano: the following get operation should be set as subUsage of the sporadic SaStep Operation created in the PSM, it should not appear as activity
					//nextE2ENode := createPutOp(usedPiCHRtSpec.base_Comment, usedPiSlot, e2eActivity, nextE2ENode)       
				}
	        	else
	        		//if the node is protected all its CallOperation must be inserted in the subUsage of the SaStep Operation (created in the Operation Package) instead of creating a SaStep node
	        		if usedPiCHRtSpec.isProtected() then {
	        			//Stefano: why should a create a subUsagesChain here?  Just a subusage is enough.
	        			//nextE2ENode := createSubUsagesChain(currentOp.base_Comment, usedPiCHRtSpec.base_Comment, usedPiSlot, e2eActivity, nextE2ENode)
						log("... and protected: create sub usage");
	        			createSubUsage(currentCHRtComment.CHRtSpec(),usedPiCHRtSpec);

	        		}
	        		else{
	        			//TODO Stefano: is this correct?
	        			log("... WARNING 234325: check this oncreateOpaqueActionsChainFull mapping");
	        			nextE2ENode := createOpaqueActionsChainFull(usedPiCHRtSpec.isProtected(),usedPiCHRtSpec.base_Comment, usedPiSlot, e2eActivity, nextE2ENode, usedPiSlot.owningInstance)
	        		}endif
	        						
				endif	
			}	
	        endif;
        }
	};
    return nextE2ENode;
}


//NOT USED
/*
helper createSubUsagesChain(in enclosingCHRTComment : Comment, in currentCHRtComment : Comment, in currentSlot : Slot, inout e2eActivity : Activity, inout prevE2ENode : ActivityNode, 
	ownerInstance:InstanceSpecification) : ActivityNode {
		
	
	var currentOp := currentCHRtComment.CHRtSpec();
	var nextE2ENode := prevE2ENode;
	log("createSubUsagesChain... currentSlot="+currentSlot.owningInstance.toString());
	nextE2ENode := createSporadicRelatedNodes(currentOp, currentSlot, e2eActivity, nextE2ENode);
	//Creates the subsequent OpaqueAction and ControlFlow
	if not currentOp.isDeferred() then
		createSubUsage(currentCHRtComment, currentSlot)
	else
		nextE2ENode := createSaStepNode(currentCHRtComment, currentSlot, e2eActivity, nextE2ENode, ownerInstance)
	endif;	
	//if the operation has a ICB-Activity then parse its CallOperationNodes
	currentOp.context.method![Activity].collectCallOperationNodes()->forEach(calledOpNode){
		
		var riSlots := calledOpNode.portToSlotFull(currentSlot.owningInstance);
		riSlots->forEach(riSlot){
			var piSlot := riSlot.getCorrespondingSlot();
	        var piOp := piSlot.CHRtSpecForOperation(calledOpNode.operation);
	        var bus := getConnectingBus(currentSlot.owningInstance, piSlot.owningInstance);
	        
	        //if it is a remote call, attaches a send operation 
	        if bus <> null then
	        	if piOp.isDeferred() then
	        		return createSendOp(bus, currentSlot, e2eActivity, nextE2ENode)
	        	else 
	        	    //if it is a simple operation, proceeds with the subsequent call
	        		nextE2ENode := createSendOp(bus, currentSlot, e2eActivity, nextE2ENode)
	        	endif
	        else
		        //otherwise it is a local call
		        //if it is a simple operation, simply add it to the endtoendworkflow and proceeds with the subsequent call
				if not piOp.isDeferred() then        
	        		nextE2ENode := createSubUsagesChain(currentOp.base_Comment, piOp.base_Comment, piSlot, e2eActivity, nextE2ENode, ownerInstance)
	        	else
	        		//Calls put operation
					return createPutOp(piOp.base_Comment, piSlot, e2eActivity, nextE2ENode)
				endif		
	        endif;
        }
	};
    return nextE2ENode;
}
*/

helper createPutOp(in sourceCHRtComment : Comment, in sourceSlot : Slot, inout e2eActivity : Activity, inout prevE2ENode : ActivityNode) : ActivityNode {
    var putSpec := sourceCHRtComment.CHRtSpec();
	var putOp := //putSpec.base_Comment.resolveoneIn(Comment::SporadicOperation2SaSharedResource, Class).ownedOperation->selectOne(name="put");
	sourceSlot.owningInstance.resolveoneIn(InstanceSpecification::SporadicOperation2SwMutualExclusionResource, Class).ownedOperation->selectOne(name="put");
	
	var putNode := createOpaqueAction(sourceSlot.owningInstance.name + "_" + putOp.name, e2eActivity, prevE2ENode);
	var opSaStep := putNode.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
	// Set the <<SwSchedulableResource>> that executes the <<saStep>>
	opSaStep.concurRes := currentConcurRes;//sourceCHRtComment.getConcurRes(sourceSlot);
    // Retrieve the <<SaStep>> to use for the subusage
	var saStep := putOp.getMetaclass(SaStepQN).oclAsType(MARTE::SAM::SaStep);
	//Add the newly created operation as subUsage of the OpaqueAction(<<saStep>>)
	opSaStep.subUsage += saStep;
	return putNode;
}

helper createGetOp(in sourceCHRtComment : Comment, in sourceSlot : Slot, inout e2eActivity : Activity, inout prevE2ENode : ActivityNode) : ActivityNode {
    var getSpec := sourceCHRtComment.CHRtSpec();
	var getOp := //getSpec.base_Comment.resolveoneIn(Comment::SporadicOperation2SaSharedResource, Class).ownedOperation->selectOne(name="get");
	sourceSlot.owningInstance.resolveoneIn(InstanceSpecification::SporadicOperation2SwMutualExclusionResource, Class).ownedOperation->selectOne(name="get");
	
	var getNode := createOpaqueAction(sourceSlot.owningInstance.name + "_" + getOp.name, e2eActivity, prevE2ENode);
	var opSaStep := getNode.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
	// Set the <<SchedulableResource>> that executes the <<saStep>>
	//var classResource : Class := currentCHRtComment.resolveIn(Comment::CHRtSlot2SchedulableResource, Class)->selectOne(name=getSpec.genResourceName());
	opSaStep.concurRes := sourceCHRtComment.getConcurRes(sourceSlot);//classResource.getMetaclass(SchedulableResourceQN).oclAsType(MARTE::GRM::SchedulableResource);
    // Retrieve the <<SaStep>> to use for the subusage
	var saStep := getOp.getMetaclass(SaStepQN).oclAsType(MARTE::SAM::SaStep);
	//Add the newly created operation as subUsage of the OpaqueAction(<<saStep>>)
	opSaStep.subUsage += saStep;
	return getNode;
}

helper createSendOp(in connectingBus : InstanceSpecification, in sourceSlot : Slot, inout e2eActivity : Activity, inout prevE2ENode : ActivityNode) : ActivityNode {
	return createBusOp(connectingBus, "send", sourceSlot, e2eActivity, prevE2ENode);
}

helper createReceiveOp(in connectingBus : InstanceSpecification, in sourceSlot : Slot, inout e2eActivity : Activity, inout prevE2ENode : ActivityNode) : ActivityNode {
	return createBusOp(connectingBus, "receive", sourceSlot, e2eActivity, prevE2ENode);
}

//opType must be "receive" or "send"
helper createBusOp(in connectingBus : InstanceSpecification, in opType : String, in sourceSlot : Slot, inout e2eActivity : Activity, inout prevE2ENode : ActivityNode) : ActivityNode {
	log("  Attaching '"+ opType +"' operation for communication channel '" + connectingBus.name + "'.");
	
	var sendNode := createOpaqueAction(connectingBus.name + "_" + opType, e2eActivity, prevE2ENode);
	var sendSaStep := sendNode.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
                       
	//var gaCommChannel := getAssignToFrom(sourceSlot.CHRtSpec().partWithPort.property2InstanceSpec()).resolveoneIn(InstanceSpecification::BusProperty2GaCommChannel, Class).getMetaclass(GaCommChannelQN).oclAsType(MARTE::GQAM::GaCommChannel);                     
	var gaCommChannel := getAssignToFrom_MemoryPartition(sourceSlot.owningInstance).resolveoneIn(InstanceSpecification::BusProperty2GaCommChannel, Class).getMetaclass(GaCommChannelQN).oclAsType(MARTE::GQAM::GaCommChannel);
	sendSaStep.concurRes := gaCommChannel;
	//TODO Assumption: send operation unique for each HwBus
	var sendOp : Operation := connectingBus.resolveoneIn(InstanceSpecification::HwBus2OperationClass, Class).ownedOperation->selectOne(name.endsWith("_" + opType));
	sendSaStep.subUsage += sendOp.getMetaclass(SaStepQN).oclAsType(MARTE::SAM::SaStep);
	return sendNode;
}

helper createOpaqueAction(in name : String , inout e2eActivity : Activity, inout prevE2ENode : ActivityNode) : ActivityNode {
	//var node := new OpaqueAction(name);
	var node := e2eActivity.createOpaqueAction(name);
	var edge := new ControlFlow("ControlFlow_" + node.name);
	e2eActivity.node += node;
	e2eActivity.edge += edge;
	node.outgoing += edge;
	//TODO Assumption: only one outgoing activity edge per node
	prevE2ENode.outgoing![ControlFlow].target := node;
	
	
	return node;
}

mapping Slot::Slot2Class4SaStep() : Class {
	var name := operationClassName(self, "operations");
	log("  <<SaStep>> operation class not found. Generating '" + name + "'.");
	result.name := name;
	operationPackage.packagedElement += result;
}


mapping InstanceSpecification::InstanceSpecification2Class4SaStep() : Class {
	var name := operationClassName(self, "operations");
	log("  <<SaStep>> operation class not found. Generating '" + name + "'.");
	result.name := name;
	operationPackage.packagedElement += result;
}

/*SLot can be null, e.g. in case of private ARINCFunction
*/
helper Comment::CHRTComment2SaStep(slot : Slot, owningInstance : InstanceSpecification) : Operation {
	if self.CHRtSpec().isSporadic() then 
		return self.map CHRTCommentSporadic2SaStep(slot, owningInstance) 
	endif;
	if self.CHRtSpec().isProtected() then
		return self.map CHRTCommentProtected2SaStep(slot, owningInstance)
	else
		return self.map CHRTCommentUnprotected2SaStep(slot, owningInstance)
	endif;	
	return null;
}

/*
//NOT USED
mapping Slot::CHRTCommentUnprotected2SaStepStrict(chrt : Comment) : Operation when {not chrt.CHRtSpec().isProtected()} {
	init{
		var res := self.owningInstance.resolveoneIn(InstanceSpecification::UnprotectedOperation2SaStep, Operation);
		if res = null then {
			log("  Generating <<SaStep>> for operation '" + chrt.CHRtSpec().context.name + "'.");
			res := self.owningInstance.map UnprotectedOperation2SaStep(chrt, self);
		} else 
			log("  Nothing to do")
		endif;
		result := res;
	}
}*/

/*slot can be null, e.g. private ARINCFunction case
*/
mapping Comment::CHRTCommentUnprotected2SaStep(slot : Slot, owningInstance : InstanceSpecification) : Operation when {not self.CHRtSpec().isProtected()} {
	init{
		log("  Generating <<SaStep>> for operation '" + self.CHRtSpec().context.name + "'.");
		var res := owningInstance.map UnprotectedOperation2SaStep(self, slot, owningInstance);
		result := res;
	}
}

mapping InstanceSpecification::UnprotectedOperation2SaStep(chrt : Comment, slot : Slot, owningInstance : InstanceSpecification) : Operation when {not chrt.CHRtSpec().isProtected()} {
	init{	
	
		if chrt.CHRtSpec().isDeferred() then
	    	log("  Operation is cyclic.")
	    else
	    	log("  Operation is unprotected.")
    	endif;
    	
		var chrts := chrt.CHRtSpec();
		var selfOperation := chrts.context.oclAsType(Operation);
		//Create a new Class containing this operation of the PI if it does not exist yet
		var owner : Class;
		
		if(slot<>null){
			owner := slot.Slot2Class4SaStepProxy();
		}else{
			owner := owningInstance.Instance2Class4SaStepProxy();
		};
		
		result := new Operation(selfOperation);
	}

	owner.ownedOperation += result;
	// Convert the newly created operation to a <<saStep>>
	var saStep := result.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
	saStep.execTime += chrt.getWCET();//chrts.localWCET;
	
	//createSubUsageForPSMOperation(selfOperation, result, slot.owningInstance)
}

/*to be used for ARINCFunction mapping

mapping InstanceSpecification::InstanceUnprotected2SaStep(chrt : Comment, instance : InstanceSpecification) : Operation when {not chrt.CHRtSpec().isProtected()} {
	init{	
	
		if chrt.CHRtSpec().isDeferred() then
	    	log("Mapping InstanceUnprotected2SaStep: Operation is cyclic.")
	    else
	    	log("Mapping InstanceUnprotected2SaStep:  Operation is unprotected.")
    	endif;
    	
		var chrts := chrt.CHRtSpec();
		var selfOperation := chrts.context.oclAsType(Operation);
		//Create a new Class containing this operation of the PI if it does not exist yet
		var owner := instance.Instance2Class4SaStepProxy();
		result := new Operation(selfOperation);
	}

	owner.ownedOperation += result;
	// Convert the newly created operation to a <<saStep>>
	var saStep := result.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
	saStep.execTime += chrt.getWCET();//chrts.localWCET;
	
	//createSubUsageForPSMOperation(selfOperation, result, slot.owningInstance)
}*/


mapping Comment::CHRTCommentProtected2SaStepStrict(slot : Slot, ownerInstance:InstanceSpecification) : Operation 
	when {self.CHRtSpec().isProtected()} {
	init{
		//one Slot can have different chrtSpecification associated and so it can be mapped to multiple SaStep...
		//TODO Operation's name can be a problem when used as identifier...
		var res := ownerInstance.resolveIn(InstanceSpecification::InstanceProtected2SaStep, Operation)-> selectOne
				(name=self.CHRtSpec().context.name);
		if res = null then {
			log("  Generating <<SaStep>> for operation '" + self.CHRtSpec().context.name + "'.");
			res := ownerInstance.map InstanceProtected2SaStep(self, slot);
		} else 
			log("  Nothing to do")
		endif;
		result := res;
	}
	
}

/*
@param slot: can be null, e.g. in case of private ARINCFUnction
*/
mapping Comment::CHRTCommentProtected2SaStep(slot : Slot, ownerInstance:InstanceSpecification) : Operation when {self.CHRtSpec().isProtected()} {
	init{
		log("  Generating <<SaStep>> for operation '" + self.CHRtSpec().context.name + "'.");
		var res := ownerInstance.map InstanceProtected2SaStep(self, slot);
		result := res;
	}
}

/*
//NOT USED
mapping InstanceSpecification::InstanceProtected2SaStepStrict(chrt : Comment, slot : Slot) : Operation when {chrt.CHRtSpec().isProtected()} {
    //TODO Assumes 1 state (SwMutualExclusionResource) for each PI with guarded operations
	init{
	    log("  Operation is protected.");
		var chrts := chrt.CHRtSpec();
		var selfOperation := chrts.context.oclAsType(Operation);
		var owner := self.resolveoneIn(InstanceSpecification::ProtectedOperation2SwMutualExclusionResource, Class);
		result := new Operation(selfOperation);
	}
	//Create a new SwMutualExclusionResource containing this operation for each PI port
	
	if owner = null then
		owner := self.map ProtectedOperation2SwMutualExclusionResource(chrt, slot)
	endif;

	var saMutualExRes := owner.getMetaclass("MARTE::MARTE_DesignModel::SRM::SW_Interaction::SwMutualExclusionResource").oclAsType(MARTE::SRM::SW_Interaction::SwMutualExclusionResource);
	//apply also a SaSharedResource in order to add it to sastep.sharedres
	var saSharedRes := owner.getMetaclass("MARTE::MARTE_AnalysisModel::SAM::SaSharedResource").oclAsType(MARTE::SAM::SaSharedResource);

	owner.ownedOperation += result;
	// Convert the newly created operation to a <<saStep>>
	var saStep := result.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
	saStep.execTime += chrt.getWCET();//chrts.localWCET;	
	// The sharedRes will be set on the SaStep of the end to end workflow
	saStep.sharedRes += saSharedRes;
}*/

/*
slot can be null, e.g. in case of private ARINCFunction
*/
mapping InstanceSpecification::InstanceProtected2SaStep(chrt : Comment, slot : Slot) : Operation when {chrt.CHRtSpec().isProtected()} {
    //Assumes 1 state (SwMutualExclusionResource) for each InstanceSpecification with PI with guarded operations
	init{
	    log("  Operation is protected.");
		var chrts := chrt.CHRtSpec();
		var selfOperation := chrts.context.oclAsType(Operation);
		
		log("Check if the protected resource has already been created");
		var owner := self.resolveoneIn(InstanceSpecification::ProtectedOperation2SwMutualExclusionResource, Class);
		if owner = null then
			//Create a new SwMutualExclusionResource containing this operation for each PI port
			owner := self.map ProtectedOperation2SwMutualExclusionResource(chrt)
		else 
			log("<<SwMutualExclusionResource>> found, nothing to do")
		endif;
		
		result := new Operation(selfOperation);
	}
	
	var saMutualExRes := owner.getMetaclass("MARTE::MARTE_DesignModel::SRM::SW_Interaction::SwMutualExclusionResource").oclAsType(MARTE::SRM::SW_Interaction::SwMutualExclusionResource);
	//apply also a SaSharedResource in order to add it to sastep.sharedres
	var saSharedRes := owner.getMetaclass("MARTE::MARTE_AnalysisModel::SAM::SaSharedResource").oclAsType(MARTE::SAM::SaSharedResource);

	owner.ownedOperation += result;
	// Convert the newly created operation to a <<saStep>>
	var saStep := result.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
	saStep.execTime += chrt.getWCET();//chrts.localWCET;
	// The sharedRes will be set on the SaStep of the end to end workflow
	saStep.sharedRes += saSharedRes;
}


mapping InstanceSpecification::ProtectedOperation2SwMutualExclusionResource(annotation : Comment) : Class {
	var name := self.name + "_state";
	log("  <<SwMutualExclusionResource>> class not found. Generating '"+name+"' ");
	
	result.name := name;
	operationPackage.packagedElement += result;
	var mutualExRes := result.applyStereotype(getMARTEStereotype("SwMutualExclusionResource")).oclAsType(MARTE::SRM::SW_Interaction::SwMutualExclusionResource);
	
	var saSharedRes := result.applyStereotype(getMARTEStereotype("SaSharedResource")).oclAsType(MARTE::SAM::SaSharedResource);
	//saSharedRes.ceiling := "(value="+ self.CHRtSpec().ceiling +", source=req)";
	//saSharedRes.ceiling := annotation.CHRtSpec().ceiling;
	result.setCeiling2(annotation.CHRtSpec().ceiling);
	result.setProtectKind2("PriorityCeiling");
}

/*
//NOT USED
mapping Slot::CHRTCommentSporadic2SaStepStrict(chrt : Comment) : Operation when {chrt.CHRtSpec().isSporadic()} {
    //TODO Assumes 1 state (SwMutualExclusionResource) for each sporadic operation
	init{	
		var res := self.owningInstance.resolveoneIn(InstanceSpecification::InstanceSporadic2SaStep, Operation);
		if res = null then {
			log("  Generating <<SaStep>> for operation '" + chrt.CHRtSpec().context.name + "'.");
			res := self.owningInstance.map InstanceSporadic2SaStep(chrt, self);
		} else 
			log("  Nothing to do")
		endif;
		result := res;
	}
}*/

mapping Comment::CHRTCommentSporadic2SaStep(slot : Slot, ownerInstance:InstanceSpecification) : Operation 
	when {self.CHRtSpec().isSporadic()} {
	init{	
		log("  Generating <<SaStep>> for operation '" + self.CHRtSpec().context.name + "'.");
		var res := self.map InstanceSporadic2SaStep(slot, ownerInstance);
		result := res;
	}
}

helper Slot::Slot2Class4SaStepProxy() : Class {
	var owner := self.resolveoneIn(Slot::Slot2Class4SaStep, Class);
	if owner = null then {
		owner := self.map Slot2Class4SaStep();
	} endif;
	return owner;
}



helper InstanceSpecification::Instance2Class4SaStepProxy() : Class {
	var owner := self.resolveoneIn(Slot::Slot2Class4SaStep, Class);
	if owner = null then {
		owner := self.map InstanceSpecification2Class4SaStep();
	} endif;
	return owner;
}

/*
slot can be null, e.g. in case of private ARINCFunction
*/
mapping Comment::InstanceSporadic2SaStep(slot : Slot, ownerInstance:InstanceSpecification): Operation 
	when{self.CHRtSpec().isSporadic()} {
    //TODO Assumes 1 state (SwMutualExclusionResource) for each sporadic operation		
	init{	
		log("  Operation is sporadic.");
		var chrts := self.CHRtSpec();
		var selfOperation := chrts.context.oclAsType(Operation);
		
		var owner : Class;
		
		if (slot <> null){
			owner := slot.Slot2Class4SaStepProxy();
		}else{
			owner := ownerInstance.Instance2Class4SaStepProxy();
		};
		
		//Create a new SwMutualExclusionResource containing the put/get operation associated to this sporadic operation
	    var protectedState := ownerInstance.map SporadicOperation2SwMutualExclusionResource(self, slot);
		result := new Operation(selfOperation);
	}

	owner.ownedOperation += result;
	// Convert the newly created operation to a <<saStep>>
	var localSaStep := result.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
	localSaStep.execTime += self.getWCET();//chrts.localWCET;
	
	//createSubUsageForPSMOperation(selfOperation, result, slot.owningInstance)
	
}

/*
slot can be null, e.g. in case of private ARINCFunction
*/
mapping InstanceSpecification::SporadicOperation2SwMutualExclusionResource(chrt : Comment, slot : Slot) : Class {
	init{
		var name : String;
		
		if (slot <> null){
			name := operationClassName(slot, chrt.CHRtSpec().context.name() + "_state");
		}else{
			name := operationClassName(self, chrt.CHRtSpec().context.name() + "_state");
		};
		
		log("    Generating <<SwMutualExclusionResource>> '" + name + "'.");
		log("    NOTE 'put' and 'get' operations execution times are hardcoded: (worst=0.0,value=0.0,best=0.0,unit=ms)");
		var putOp : Operation := new Operation("put");
		var getOp : Operation := new Operation("get");
	}
	
	result.name := name;
	operationPackage.packagedElement += result;
	
	var swMutualExRes := result.applyStereotype(getMARTEStereotype("SwMutualExclusionResource")).oclAsType(MARTE::SRM::SW_Interaction::SwMutualExclusionResource);	
	//apply also a SaSharedResource in order to add it to sastep.sharedres
	var saSharedRes := result.applyStereotype(getMARTEStereotype("SaSharedResource")).oclAsType(MARTE::SAM::SaSharedResource);
	
	result.setCeiling2(chrt.CHRtSpec().ceiling);
	result.setProtectKind2("PriorityCeiling");
	
	result.ownedOperation += putOp;
	result.ownedOperation += getOp;
		
	var saPutOp  := putOp.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
	saPutOp.sharedRes += saSharedRes;
	var saGetOp := getOp.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
	saGetOp.sharedRes += saSharedRes;
	
	saPutOp.execTime := "(worst=0.0,value=0.0,best=0.0,unit=ms)";
	saGetOp.execTime := "(worst=0.0,value=0.0,best=0.0,unit=ms)";
}

mapping InstanceSpecification::HwBus2OperationClass() : Class {
	init{
		log("  Generating Bus operations. NOTE: 'send' and 'receive' execution times are hardcoded.");
		log("    'send' execution time is (worst=0.0,value=0.0,best=0.0,unit=ms)");
		log("    'receive' execution time is (worst=0.0,value=0.0,best=0.0,unit=ms)");
		var sendOp : Operation := new Operation(self.name + "_send");
		var receiveOp : Operation := new Operation(self.name + "_receive");
	}
	
	result.name := self.name + "_operation";
	operationPackage.packagedElement+=result;
	
	result.ownedOperation += sendOp;
	result.ownedOperation += receiveOp;
		
	var stsendOp  := sendOp.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
	var streceiveOp := receiveOp.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
	
	//TODO for the moment exec time is hardcoded
	stsendOp.execTime := "(worst=0.0,value=0.0,best=0.0,unit=ms)";
	streceiveOp.execTime := "(worst=0.0,value=0.0,best=0.0,unit=ms)";
}

/*
<<HwBus>>
It represents a special resource able to transfer data.
It is characterized by its address and word widths, these are functional values, usually different from the wires number of
its corresponding HW_Channel seeing that buses may be multiplexed or serial.

<<SaCommHost>>
In a communication host (e.g., network and bus), the related schedulable resource element is CommunicationChannel,
which may be characterized by concrete scheduling parameters (like the packet size).
*/
mapping InstanceSpecification::HwBus2SaCommHost() : Class {
	init{
		log ("  Generating <<SaCommHost>>.");
		var hwBus :=  self.getMetaclass(CHHwBusQN).oclAsType(chessmlprofile::HardwareBaseline::CH_HwBus);
	}
    
	result.name := self.name;
	hostPackage.packagedElement += result;
	
	var stHost := result.applyStereotype(getMARTEStereotype("SaCommHost")).oclAsType(MARTE::SAM::SaCommHost);
	stHost.speedFactor := hwBus.speedFactor;//DEF"";
	if stHost.speedFactor = null or stHost.speedFactor = "" then
		stHost.speedFactor := "(value=1.0)"
	endif;
	
	stHost.blockT := hwBus.blockT;//DEF (worst=0.0,unit=ms)
	
	if stHost.blockT->size() = 0 then
		stHost.blockT += "(worst=0.0,unit=ms)"
	endif;
	
	stHost.packetT := hwBus.packetT;
	
	if stHost.packetT->size() = 0 then
		stHost.packetT += "(worst=1.0,unit=ms)"
	endif;	
}

/*
<<GaCommChannel>>
A logical communications layer connecting SchedulableResources.
*/
mapping InstanceSpecification::BusProperty2GaCommChannel(in host : InstanceSpecification) : Class {
	log("  Found connected InstanceSpecification '" + self.name + "'. Generating <<GaCommChannel>>.");
	log("    Scheduling parameters are hardcoded: fp(priority=(value=24,source=meas))");
	result.name := self.name + "_" + host.name + "_server";
	hostPackage.packagedElement += result;
	
	var stCommChannel := result.applyStereotype(getMARTEStereotype("GaCommChannel")).oclAsType(MARTE::GQAM::GaCommChannel);
	
	stCommChannel.host := host.resolveoneIn(InstanceSpecification::HwBus2SaCommHost, Class).getMetaclass(SaCommHostQN).oclAsType(MARTE::SAM::SaCommHost);
	//TODO schedParams?
	stCommChannel.schedParams := "fp(priority=(value=24,source=meas))";
}

/*
<<HwComputingResource>>
It is a high level concept that denotes an active execution resource.
Such resources are often clocked and may support a range of operating frequencies.

<<SaExecHost>>
A CPU or other device which executes functional steps. The SaExecHost stereotype adds schedulability metrics, interrupt
overheads, and utilization of scheduling processing.
*/
mapping InstanceSpecification::HwComputingResource2SaExecHost() : Class {
	log("Generating <<SaExecHost>> from instanceSpecification '"+self.name+"' corresponding to <<CH_HwComputingResource>> '" + self.classifier().name + "'.");
    var hcr := self.getMetaclass(CHHwComputingResourceQN).oclAsType(chessmlprofile::HardwareBaseline::CH_HwComputingResource);
	result.name := self.name;
	hostPackage.packagedElement += result;
	var stHost := result.applyStereotype(getMARTEStereotype("SaExecHost")).oclAsType(MARTE::SAM::SaExecHost);
	
	stHost.schedPriRange := "[1..256]";
	stHost.speedFactor := hcr.speedFactor;//"(value=1.0)";
}

helper InstanceSpecification::HwProcessor2SaExecHostHelper() : OclVoid {
	log("Generating <<SaExecHost>> from instanceSpecification '"+self.name+"' corresponding to <<CH_HwProcessor>> '" + self.classifier().name + "'.");
	var i: Integer := 0;
	var n: Integer := self.getNumberOfCores();
	
	log("number of cores "+n.toString());
	
	//check if it is RUN
	isRUN := self.classifier().isRUN();
	
	var schedPolicy := "partitioned";
	if(isRUN){
		schedPolicy := "global(RUN)";
	};
	
	var p := self.map HwProcessor2SaExecHost(null);
	var pHost := p.getMetaclass("SaExecHost").oclAsType(MARTE::SAM::SaExecHost);
	pHost.otherSchedPolicy := schedPolicy;
	//Generate cores and assign the processor as the host for each core
	while(n>1 and i < n) {
		var c := self.map HwProcessor2SaExecHost("_core"+i.toString());
		//TODO the following lines may be removed
		var cc := object Class {
			redefinedClassifier+=c;
			name := c.name;
		};
		p.nestedClassifier +=cc;
		c.getMetaclass("SaExecHost").oclAsType(MARTE::SAM::SaExecHost).host := pHost;
		i := i + 1;
	};
	
	//Generates the supertasks
	if(isRUN){
		var supertasks := self.classifier().getRUNSupertasks();
		
		supertasks->forEach(supertaskInfo){
			var stname := supertaskInfo->asSequence()->first();
			var stcapacity := supertaskInfo->last();
			self.map HwProcessor2SaExecHostSupertask(stname, stcapacity);
		};
	};
}

mapping InstanceSpecification::HwProcessor2SaExecHostSupertask(supertask : String, capacity : String) : Class {
	var message := "";
	var name := self.name;
	if(supertask<>null){
		message := "'and supertask " + supertask;
		name := name + supertask;
	};
	var host := self.resolveoneIn(InstanceSpecification::HwProcessor2SaExecHost, Class);
	var saHost := host.getMetaclass(SaExecHostQN).oclAsType(MARTE::SAM::SaExecHost);
	log("Generating <<SaExecHost>> from instanceSpecification '"+self.name+"' corresponding to <<CH_HwProcessor>> '" + self.classifier().name + message);
    var hcr := self.getMetaclass(CHHwProcessorQN).oclAsType(chessmlprofile::HardwareBaseline::CH_HwProcessor);
	result.name := name;
	hostPackage.packagedElement += result;
	var stHost := result.applyStereotype(getMARTEStereotype("SaExecHost")).oclAsType(MARTE::SAM::SaExecHost);
	stHost.schedPriRange := "[1..256]";
	stHost.speedFactor := hcr.speedFactor;
	stHost.host := saHost;
	stHost.schedPolicy := GRM_BasicTypes::SchedPolicyKind::EarliestDeadlineFirst;
	stHost.otherSchedPolicy := "RUN";
	var sr := result.applyStereotype(getMARTEStereotype("SwSchedulableResource")).oclAsType(MARTE::SRM::SW_Concurrency::SwSchedulableResource);	
	var schedParam := "capacity=(value=" + capacity +")";	
	sr.schedParams := "("+schedParam+")";
}

mapping InstanceSpecification::HwProcessor2SaExecHost(core : String) : Class {
	var message := "";
	var name := self.name;
	if(core<>null){
		message := "'and Core " + core;
		name := name + core;
	};
	var host := self.resolveoneIn(InstanceSpecification::HwProcessor2SaExecHost, Class);
	var saHost := host.getMetaclass(SaExecHostQN).oclAsType(MARTE::SAM::SaExecHost);
	log("Generating <<SaExecHost>> from instanceSpecification '"+self.name+"' corresponding to <<CH_HwProcessor>> '" + self.classifier().name + message);
    var hcr := self.getMetaclass(CHHwProcessorQN).oclAsType(chessmlprofile::HardwareBaseline::CH_HwProcessor);
	result.name := name;
	hostPackage.packagedElement += result;
	var stHost := result.applyStereotype(getMARTEStereotype("SaExecHost")).oclAsType(MARTE::SAM::SaExecHost);
	stHost.schedPriRange := "[1..256]";
	stHost.speedFactor := hcr.speedFactor;
	stHost.host := saHost;
}

/*
//NOT USED
//Create a new Activity as <<SaEndToEndFlow>>
mapping Slot::slot2EndToEndWorkFlowStrict(chrt : Comment) : Activity when {chrt.CHRtSpec().isDeferred()} {
    init {
    	var res := self.owningInstance.resolveoneIn(InstanceSpecification::Instance2EndToEndWorkFlow, Activity);
    	if res = null then
    		res := self.owningInstance.map Instance2EndToEndWorkFlow(chrt, self)
    	else 
			log("  Nothing to do")
		endif;
    	result := res;
    }
}*/

//Create a new Activity as <<SaEndToEndFlow>>
mapping Slot::slot2EndToEndWorkFlow(chrt : Comment) : Activity when {chrt.CHRtSpec().isDeferred()} {
    init {
    	var res := chrt.map Instance2EndToEndWorkFlow(self, self.owningInstance);
    	result := res;
    }
}

/*
@param slot: can be null, in case chrt refers a private operation, i.e. ARINCFunction operation
*/
mapping Comment::Instance2EndToEndWorkFlow(slot : Slot, inst : InstanceSpecification) : Activity when {self.CHRtSpec().isDeferred()} {
    init {
    	
    	log("Generating <<EndToEndWorkFlow>> from the Instance"+ " for '" + inst.name + inst.getStringId() + "' and operation "+ self.CHRtSpec().context.name +".");
    	
    	var chrts := self.CHRtSpec();
    	var actionName : String;
    	if (slot<>null){
    		actionName := opaqueActionName(slot, chrts);
    		}
    	else{
    		actionName := opaqueActionName(inst, chrts);
    	};
	    // entities for single and distributed communication
	    //var actInitialNode := new InitialNode("InitialNode1");
	   
	    var controlFlowInit := new ControlFlow("ControlFlow1");
		var actConstraint := new Constraint("Global_Timing_Req");
		//setting internal references
		//actInitialNode.outgoing += controlFlowInit;
    }
    
    /*Stefano
   	//add entity to store traceability information in the model. This infomation can then be used later in the editor to show analysis results related to the PIM entites.
   	//I would like to use a Dependency here between the Activity and the originating slot and chrt Comment, but in UML Comment cannot be referenced by dependency.
   	//so here I use Constraint...*/
    var constr := new Constraint();
    constr.constrainedElement += result;
    constr.constrainedElement += slot;
    constr.constrainedElement += self;
    constr.constrainedElement += inst;
    instSpecPackage.resolveoneIn(Package::CHGaResourcePlatform2SaAnalysisContext, Class).ownedRule += constr;
    //end modification for traceability
    
    result.name := actionName;
   
    // Add the action to the owned behaviors of RTAnalysisContext     
    instSpecPackage.resolveoneIn(Package::CHGaResourcePlatform2SaAnalysisContext, Class).ownedBehavior += result;
    //Apply the stereotype <<SaEndtoEndFlow>> to the activity
	result.applyStereotype(getMARTEStereotype("SaEndtoEndFlow"));
	result.precondition += actConstraint;
	//we need to have the original deadline in a field not overritten by the MAST analysis
	var e2estereo : Stereotype := result.getApplicableStereotype("MARTE::MARTE_AnalysisModel::SAM::SaEndtoEndFlow");
	var e2eflow : MARTE::SAM::SaEndtoEndFlow = result.getStereotypeApplication(e2estereo).oclAsType(MARTE::SAM::SaEndtoEndFlow);
	e2eflow.end2EndD += chrts.rlDl;
	
	var actInitialNode := result.createInitialNode();
	actInitialNode.outgoing += controlFlowInit;
	
	result.edge += controlFlowInit;
    //Apply stereotype <<gaLatencyObs>> and specify the deadline for the end to end flow
	var gaLatencyObs := actConstraint.applyStereotype(getMARTEStereotype("GaLatencyObs")).oclAsType(MARTE::GQAM::GaLatencyObs);
	//var relativeDeadline : String := "(value=" + CHRtRlDl + ",unit=ms)";
	gaLatencyObs.latency += chrts.rlDl;
	
	//if the current operation is deferred, it will be the first on the ICB
	if (slot <> null) {
		currentConcurRes := self.getConcurRes(slot);
	}
	else {
		currentConcurRes := self.getConcurRes(inst);
	};
	
	//Apply stereotype <<gaWorkloadEvent>> and specify the release pattern
	//of the end-to-end flow
	var gaWorkloadEvent := actInitialNode.applyStereotype(getMARTEStereotype("GaWorkloadEvent")).oclAsType(MARTE::GQAM::GaWorkloadEvent);
	gaWorkloadEvent.pattern := chrts.occKind;
	
	var resultNode := createOpaqueActionsChainFull(chrts.isProtected(), self, slot, result, actInitialNode, inst);

	//create final node
	//var finalNode := new ActivityFinalNode("ActivityFinalNode1");
	var finalNode := result.createFinalNode();
	//result.node += finalNode;
	
	
    //TODO assumption only one activity edge per node
    resultNode.outgoing![ControlFlow].target := finalNode;
    
}

query chessmlprofile::RTComponentModel::CHRtSpecification::isDeferred() : Boolean {
	var arrivalPattern := self.occKind.getArrivalPatternType();
	//the operation is deferred if the arrival pattern is: periodic, sporadic, bursty
	if  arrivalPattern.oclIsInvalid() then
		return false
	endif;
	return (arrivalPattern <> null and arrivalPattern.length() <> 0);
}

query chessmlprofile::RTComponentModel::CHRtSpecification::isSporadic() : Boolean {
	var arrivalPattern := self.occKind.getArrivalPatternType();
	if (arrivalPattern.oclIsUndefined()) then
		return false
	endif;
	return (arrivalPattern.equalsIgnoreCase("sporadic"));// and self.isGuarded());
}

query chessmlprofile::RTComponentModel::CHRtSpecification::isProtected() : Boolean { 
	return (not self.isDeferred()) and self.protection = MARTE::HLAM::CallConcurrencyKind::guarded;
}

query Port::getCHrtSpecComment() : Comment {
	return specs->selectOne(annotatedElement![Port] = self);
}

query InstanceSpecification::linkedHwInstanceSpecifications() : Set(InstanceSpecification) {
	var res : Set(InstanceSpecification) := Set{};
	var links := self.owner.ownedElement[InstanceSpecification]->select(classifier->size() = 0);
	//var candidates := self.owner.ownedElement[InstanceSpecification] - links;
	var busLinks := links->select(allOwnedElements()[InstanceValue]->selectOne(instance = self) <> null);
	busLinks->forEach(l){
	  var ends := l.allOwnedElements()[InstanceValue]->asOrderedSet();
	  res += l.allOwnedElements()[InstanceValue]->select(instance <> self).instance;
	};
	return res;
}	

/*
  Given a InstanceSpecification representing a Functional Partition
  return the Components assigned to it
*/
query InstanceSpecification::getPartitionComponents() : Set(InstanceSpecification) {
		var res : Set(InstanceSpecification) := Set{};
		return res;
}

query getConnectingBusInstance(senderProcessor: InstanceSpecification, receiverProcessor: InstanceSpecification) : InstanceSpecification {
	// get the hw connections and buses
	//var links : Set(InstanceSpecification):= senderProcessor.owner.ownedElement[InstanceSpecification]->select(isStereotyped("CHESS::Dependability::DependableComponent::Propagation"));
	var links : Set(InstanceSpecification):= senderProcessor.owner.ownedElement[InstanceSpecification]->select(classifier -> size() = 0);
	var buses := senderProcessor.owner.ownedElement[InstanceSpecification]->select(classifier->selectOne(isStereotyped(CHHwBusQN))<>null);
	//for each bus, selects its connectors and check if the two processors are connected by 2 of those
	buses->forEach(bus){
	  	var busLinks := links->select(allOwnedElements()[InstanceValue]->selectOne(instance = bus) <> null);
	  	var sender := busLinks->selectOne(allOwnedElements()[InstanceValue]->selectOne(instance = senderProcessor) <> null) <> null;
	  	var receiver := busLinks->selectOne(allOwnedElements()[InstanceValue]->selectOne(instance = receiverProcessor) <> null) <> null;
	  	if sender and receiver then {
	  		log("  Found a bus interconnection: " + bus.name + ".");
	  		return bus;
	  	} endif;	
	};
	return null;
}

query getConnectingBus(riIns : InstanceSpecification, piIns : InstanceSpecification) : InstanceSpecification {
	var senderHwInstance := getAssignToFrom_MemoryPartition(riIns);					
	var receiverHwInstance := getAssignToFrom_MemoryPartition(piIns); 
	if senderHwInstance <> receiverHwInstance then 
	   return getConnectingBusInstance(senderHwInstance, receiverHwInstance)
	endif;
	return null;
}

//query Port::getConnectedPort() : Port {
//	var bindingConnector := self.getConnector();
//	var myConnectorEnd := (bindingConnector.allOwnedElements()[ConnectorEnd])->	selectOne(role <> self);
//    return myConnectorEnd.role.oclAsType(Port);
//}

//query Port::getConnectedPartWithPort() : Property {
//	var bindingConnector := self.getConnector();
//	var otherEnd := (bindingConnector.allOwnedElements()[ConnectorEnd])->	selectOne(role <> self);
//    return otherEnd.partWithPort;
//}

//query Port::getCorrespondingSlot() : Slot {
//	return slots->selectOne(definingFeature = self);
//}
query Slot::listAll() : Slot {
	var riPiLinks := self.owner.owner.ownedElement[InstanceSpecification]->select(classifier -> size() = 0);
	riPiLinks->forEach(l) {
	    //TODO Assumption: each link has 2 and only 2 ends
		var ends := l.allOwnedElements()[InstanceValue]->asOrderedSet();
		
		log("FIRST");
		log("Instance", ends->first().instance![InstanceSpecification].name + ends->first().instance![InstanceSpecification].getStringId());
		log("Slot", ends->first().owner![Slot].definingFeature![Port].name + ends->first().owner![Slot].getStringId());
	
		log("LAST");
		log("Instance", ends->last().instance![InstanceSpecification].name + ends->last().instance![InstanceSpecification].getStringId());
		log("Slot", ends->last().owner![Slot].definingFeature![Port].name + ends->last().owner![Slot].getStringId());
	};
	return null;	
}

/*Returns the slot connnected to the given slot, if any
*/
query Slot::getCorrespondingSlot() : Slot {
	var riPiLinks := self.owner.owner.ownedElement[InstanceSpecification]->select(classifier -> size() = 0);
	riPiLinks->forEach(l){
	    //TODO Assumption: each link has 2 and only 2 ends
		var ends := l.allOwnedElements()[InstanceValue]->asOrderedSet();
		
		// bug fixed: check also if the instance is the same, not only the slot
		var bFirst := ends->first().instance![InstanceSpecification] = self.owningInstance;
		bFirst := bFirst and 
			ends->first().owner![Slot].definingFeature![Port] = self.definingFeature;
			
		var bLast := ends->last().instance![InstanceSpecification] = self.owningInstance;
		bLast := bLast and 
			ends->last().owner![Slot].definingFeature![Port] = self.definingFeature;
				
			
		if bFirst then {
	  	  var s :=  ends->last();
	  	  return s.instance.slot->selectOne(definingFeature = s.owner![Slot].definingFeature);
	  	} else
	  	 
	    if bLast then {
	  	  var s := ends->first();//res += ends->first().instance//candidates->selectOne(ownedElement[Slot]->selectOne(s | s = ends->first()) <> null)
	  	  return s.instance.slot->selectOne(definingFeature = s.owner![Slot].definingFeature);
	    } endif
		
	    endif;
	    
	};
	return null;
}

/*
query Slot::getCorrespondingSlotFull() : Slot {
	/*if we are not working with instSpecFull, we are on instSpec so use simpler checks to get the corresponding slot*
	if(self.owner.owner![Package].name.endsWith("instSpec")) then {
		return self.getCorrespondingSlot();
	}endif;
	var riPiLinks := self.owner.owner.ownedElement[InstanceSpecification]->select(classifier -> size() = 0);
	riPiLinks->forEach(l){
	    //TODO Assumption: each link has 2 and only 2 ends
		var ends := l.allOwnedElements()[InstanceValue]->asOrderedSet();
		
		// bug fixed: check also if the instance is the same, not only the slot
		var bFirst := ends->first().instance![InstanceSpecification] = self.owningInstance;
		bFirst := bFirst and 
			ends->first().instance![InstanceSpecification].getId() = self.owningInstance.getId();
		bFirst := bFirst and 
			ends->first().owner![Slot].definingFeature![Port] = self.definingFeature;
		bFirst := bFirst and self.getId() = ends->first().owner![Slot].getId();
			
		var bLast := ends->last().instance![InstanceSpecification] = self.owningInstance;
		bLast := bLast and 
			ends->last().instance![InstanceSpecification].getId() = self.owningInstance.getId();
		bLast := bLast and 
			ends->last().owner![Slot].definingFeature![Port] = self.definingFeature;
		bLast := bLast and self.getId() = ends->last().owner![Slot].getId();
				
			
		if bFirst then {
	  	  var s :=  ends->last();
	  	  return s.instance.slot->selectOne(definingFeature = s.owner![Slot].definingFeature);
	  	} else
	  	 
	    if bLast then {
	  	  var s := ends->first();//res += ends->first().instance//candidates->selectOne(ownedElement[Slot]->selectOne(s | s = ends->first()) <> null)
	  	  return s.instance.slot->selectOne(definingFeature = s.owner![Slot].definingFeature);
	    } endif
		
	    endif;
	    
	};
	return null;
}*/

/*
 Return the "to" attribute of a given <Assign>Comment
*/

query Comment::getTo() : InstanceSpecification{
	var asg := self.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
	return 	asg.to![InstanceSpecification];
}

query getAssignForInstance(p : InstanceSpecification) : MARTE::Alloc::Assign {
	return assigns->selectOne(isAssignForInstance(p)).getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
}

query getAssignForInstance(p : Slot, c : Comment) : MARTE::Alloc::Assign {
	return assigns->selectOne(isAssignForInstance(p, c)).getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
}

query InstanceSpecification::getComponentsOfPartition() : Set(InstanceSpecification) {
	return partitionAssigns->select(isAssignForPartition(self)).getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign)._from.oclAsType(InstanceSpecification)->asSet();
}

query Classifier::getPartitionInstance() : InstanceSpecification {
	return partitionAssigns->selectOne(isAssignForPartition(self)).getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign).to![InstanceSpecification].oclAsType(InstanceSpecification);
}

query InstanceSpecification::getAssignedCore() : String {	
	var c  := assigns->selectOne(isAssignFromPartitionInstance(self));
	return c.getCoreFromContraint();
}

query InstanceSpecification::getAssignedProcessor() : InstanceSpecification {	
	var c : MARTE::Alloc::Assign := assigns->selectOne(isAssignFromPartitionInstance(self)).getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
	return c.to![InstanceSpecification];
}

query Comment::isAssignFromPartitionInstance(p : InstanceSpecification) : Boolean {
	var ass := self.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
	return ass._from![InstanceSpecification] = p;
}


query Comment::isAssignForInstance(spec : InstanceSpecification) : Boolean {
	var ass := self.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
	//return ass._from![InstanceSpecification] = spec.getSourceInstanceSpec() and self.isReferringId(spec.getId());
	return ass._from![InstanceSpecification] = spec;
}

query Comment::isAssignForInstance(spec : Slot, chrt : Comment) : Boolean {
	var ass := self.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
	var context := self.getContextFromContraint();
	
	return ass._from![Slot].definingFeature = spec.definingFeature and context = chrt.CHRtSpec().context.name;
}

query Comment::isAssignForPartition(p : InstanceSpecification) : Boolean {
	var ass := self.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
	return ass.to![InstanceSpecification] = p;
}

query Comment::isAssignForPartition(p : Classifier) : Boolean {
	var ass := self.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
	return ass.to![InstanceSpecification].classifier![Classifier] = p;
}

query getAssignToFrom_MemoryPartition(p : Slot, c : Comment) : InstanceSpecification {
	var ass := getAssignForInstance(p, c);
	var toInstance := ass.to![InstanceSpecification];
	var toClass := toInstance.classifier![Classifier];
	if toClass.isStereotyped(MemoryPartitionQN) then {
		var a := assigns -> selectOne(isAssignedFrom(toInstance));
		var asg := a.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
		return 	asg.to![InstanceSpecification];
	} else //it is an hardware component
		return 	ass.to![InstanceSpecification]
	endif;
	
	return null;
}

query getAssignedSupertaskFrom_MemoryPartition(p : Slot, c : Comment) : String {
	
	var ass := getAssignForInstance(p, c);
	var toInstance := ass.to![InstanceSpecification];
	var toClass := toInstance.classifier![Classifier];
	if toClass.isStereotyped(MemoryPartitionQN) then {
		var a := assigns -> selectOne(isAssignedFrom(toInstance));
		var asg := a.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
		return 	asg.base_Comment.getSupertaskFromContraint();
	} else //it is an hardware component
		return 	ass.base_Comment.getSupertaskFromContraint()
	endif;
	
	return null;
}

query getAssignedCoreFrom_MemoryPartition(p : Slot, c : Comment) : String {
	
	//TODO how do we get a core if there is a memory partition? 
	var ass := getAssignForInstance(p, c);
	var toInstance := ass.to![InstanceSpecification];
	var toClass := toInstance.classifier![Classifier];
	if toClass.isStereotyped(MemoryPartitionQN) then {
		var a := assigns -> selectOne(isAssignedFrom(toInstance));
		var asg := a.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
		return 	asg.base_Comment.getCoreFromContraint();
	} else //it is an hardware component
		return 	ass.base_Comment.getCoreFromContraint()
	endif;
	
	return null;
}

query getAssignToFrom_MemoryPartition(p : InstanceSpecification) : InstanceSpecification {
	var ass := getAssignForInstance(p);
	var toInstance := ass.to![InstanceSpecification];
	var toClass := toInstance.classifier![Classifier];
	if toClass.isStereotyped(MemoryPartitionQN) then {
		var a := assigns -> selectOne(isAssignedFrom(toInstance));
		var asg := a.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
		return 	asg.to![InstanceSpecification];
	} else //it is an hardware component
		return 	ass.to![InstanceSpecification]
	endif;
	
	return null;
}


query getAssignedCoreFrom_MemoryPartition(p : InstanceSpecification) : String {
	
	//TODO how do we get a core if there is a memory partition? 
	var ass := getAssignForInstance(p);
	var toInstance := ass.to![InstanceSpecification];
	var toClass := toInstance.classifier![Classifier];
	if toClass.isStereotyped(MemoryPartitionQN) then {
		var a := assigns -> selectOne(isAssignedFrom(toInstance));
		var asg := a.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
		return 	asg.base_Comment.getCoreFromContraint();
	} else //it is an hardware component
		return 	ass.base_Comment.getCoreFromContraint()
	endif;
	
	return null;
}

//query getAssignToFrom(p : InstanceSpecification) : InstanceSpecification {
//	var a := assigns -> selectOne(isAssignedFrom(p));
//	var asg := a.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
//	return 	asg.to![InstanceSpecification];
//}

//query getAssignFromTo(p : InstanceSpecification) : InstanceSpecification {
//	var a := assigns -> selectOne(isAssignedTo(p));
//	var asg := a.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
//	return 	asg._from![InstanceSpecification];
//}

query Comment::isAssignedFrom(p : InstanceSpecification) : Boolean {
    var asg := self.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
    return asg._from![InstanceSpecification] = p;
}

query Comment::isAssignedTo(p : InstanceSpecification) : Boolean {
    var asg := self.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
    return asg.to![InstanceSpecification] = p;
}

//query InstanceSpecification::RIportSize(port : Port): Integer {
//	return self.allOwnedElements()[Slot]->select(isRI())->size();
//}

//query InstanceSpecification::PIportSize(port : Port): Integer {
//	return self.allOwnedElements()[Slot]->select(isPI())->size();
//}

//query InstanceSpecification::getRIportFromIndex(port : Port, i : Integer): Integer {
//	var n := self.RIportSize(port);
//	return i.mod(n);
//}

//query Slot::isRI() : Boolean {
//	var cp := self.definingFeature![Port].getMetaclass(ClientServerPortQN).oclAsType(MARTE::GCM::ClientServerPort);
//	return cp.reqInterface->isEmpty();
//}

//query Slot::isPI() : Boolean {
//	var cp := self.definingFeature![Port].getMetaclass(ClientServerPortQN).oclAsType(MARTE::GCM::ClientServerPort);
//	return cp.provInterface->isEmpty();
//}
query ConnectableElement::getLifeLineInstance(instances : Set(InstanceSpecification)) : InstanceSpecification {
	var nonNullInstances : Set(InstanceSpecification) := instances->select(instance : InstanceSpecification | not instance.name.oclIsUndefined());
	// 20150114: SP corrected next line to avoid trouble in case of an InstanceSpecification whose name is a substring of another 
	//return nonNullInstances->selectOne(instance : InstanceSpecification | instance.name.indexOf(name) > 0);
	return nonNullInstances->selectOne(instance : InstanceSpecification | instance.name.endsWith("."+self.name));
}

helper Message::getMsgChrts() : chessmlprofile::RTComponentModel::CHRtSpecification {
	//log("getMsgChrts... "+self.name);   	
	var chrts : chessmlprofile::RTComponentModel::CHRtSpecification := null;
	//log(self.name);
   	//get the operation
   	var operation : Operation := self.signature.oclAsType(Operation);
   	log("operation =" + operation.name);
   	//assume that Message's receiveEvent is of type MessageOccurrenceSpecification
   	var receiveEvent : MessageOccurrenceSpecification := self.receiveEvent.oclAsType(MessageOccurrenceSpecification);
   	log("receiveEvent= "+receiveEvent.name);
   	//assume that Message's receiveEvent covers only one lifeline
   	var lifeline : Lifeline := receiveEvent.covered->asSequence()->first();
   	log("Lifeline= "+lifeline.name);
   	//get the instance related to Lifeline's' "represents" feature
	log("Found Lifeline for property: " + lifeline.represents.name + " with Type: " + lifeline.represents.type.name);
	//search for instance in the CHGaResourcePlatform
	var instance := lifeline.represents.getLifeLineInstance(instSpecPackage.allOwnedElements()[InstanceSpecification]);
	log("Found Instance " + instance.name);
		
	//get the instance's chrtPortSlots with a ChRtSpecification comment whose context is equal to the inital operation
	var startInstSlots : Set(Slot):= instance.slot->select(isStereotyped(CHRtPortSlotQN));
   	startInstSlots->forEach(s){
   		var chrtSpecs := s.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot).cH_RtSpecification;
   		chrtSpecs->forEach(spec){
   			if(spec.context.qualifiedName.equalsIgnoreCase(operation.qualifiedName)) then {
   				chrts := spec;
   				currentSlot := s;
   				log("Slot [getMsgChrts]: " + s.definingFeature.name);
   			} endif;
   		};
   	};
   	//log("+++++++++++++ context: " + startChrts.context.name);
	return chrts;
}

//assumption: the SaAnalysisContext.platform owns the reference to the package of the HW instances (to be considered for the analysis) available in the DeploymentView.
//returns the component which types the root HW instance stored in the package of the HW instances available in the DeploymentView.
query MARTE::SAM::SaAnalysisContext::getSystem() : Component {
	
	var platforms : Set(MARTE::GQAM::GaResourcesPlatform) := self.platform->asSet();
	platforms->forEach (plat){
		var package : Element := plat.oclAsType(CHESS::Core::CHGaResourcePlatform).base_Package;
		var found : Boolean = false;
		while (not found) {
			var owner : Element = package.owner;
			if (owner.isStereotyped(DeploymentViewQN)){
				found :=true;
				break;
			}else{
				if (owner.oclIsTypeOf(Model)){
					break;
				}
			};
			package := owner;
		};
		if (found) {
			package := plat.oclAsType(CHESS::Core::CHGaResourcePlatform).base_Package;
			//package is in the deploymentView, search the system Component
			var rootInst : InstanceSpecification := package.oclAsType(Package).getRootInstanceInPackage();
			var classifier := rootInst.classifier -> asSequence() -> first();
			log("found system component "+ classifier.name);
			return classifier.oclAsType(Component);
			
		}
	};
	return null;
		
}


//assumption: the SaAnalysisContext.platform owns the reference to the package of the SW instances (to be considered for the analysis) available in the ComponentView.
//returns the packages of the SW instances referred by SaAnalysisContext.platform 
query MARTE::SAM::SaAnalysisContext::getSwSystemInstPackage() : Package {
	
	var platforms : Set(MARTE::GQAM::GaResourcesPlatform) := self.platform->asSet();
	platforms->forEach (plat){
		var package : Element := plat.oclAsType(CHESS::Core::CHGaResourcePlatform).base_Package;
		var found : Boolean = false;
		while (not found) {
			var owner : Element = package.owner;
			if (owner.isStereotyped(ComponentViewQN)){
				found :=true;
				break;
			}else{
				if (owner.oclIsTypeOf(Model)){
					break;
				}
			};
			package := owner;
		};
		if (found) {
			log("found SwSystemInstPackage "+ plat.oclAsType(CHESS::Core::CHGaResourcePlatform).base_Package.oclAsType(Package).name);
			return plat.oclAsType(CHESS::Core::CHGaResourcePlatform).base_Package.oclAsType(Package);
		}
	};
	
	return null;
		
}



