improved mapping of decomposition

the mapping checks if an internal part has an error model (at any level) 

Signed-off-by: Stefano Puri <stefano.puri@intecs.it>
diff --git a/plugins/mobius/org.polarsys.chess.mobius/transformations/CHESS2SAN.qvto b/plugins/mobius/org.polarsys.chess.mobius/transformations/CHESS2SAN.qvto
index 5a67b38..ab0b744 100644
--- a/plugins/mobius/org.polarsys.chess.mobius/transformations/CHESS2SAN.qvto
+++ b/plugins/mobius/org.polarsys.chess.mobius/transformations/CHESS2SAN.qvto
@@ -303,16 +303,39 @@
 

 	init{

 		//A Join in SAN cannot have one child

-		//TODO actually I should not use getSubInstances() but check  the number of ErrorModelBehaviour instances, indeed the one with no ErrorModel are not mapped to SAN

-		//E.g. in case of A decomposed by B and C, both terminals, if B has ErrorModelBehaviour and C no, then A should be map to Rep 

-		//so the assumption here is that a child has always an error model; it can be the child itself or a part internal to the child

-		if (self.getSubInstances()->size() >1){

-			result:= object SAN::Join{};

+		//check  the number of ErrorModelBehaviour instances, indeed the one with no ErrorModel are not mapped to SAN

+		//E.g. in case of A decomposed by B and C, both terminals, if B has ErrorModelBehaviour and C no, then A must be map to Rep 

+		var subInsts = self.getSubInstances();

+		var createRep : Boolean = false;

+		

+		if (subInsts->size() >1){

+			//check actual error model behaviours owned

+			var numb : Integer := 0;

+			subInsts->forEach(inst){

+				if (inst.hasErrorModel()){

+					numb := numb+1;

+				}else{

+					if (inst.hasInternalErrorModelBehaviour() ){

+						numb := numb+1;

+					}

+				};

+				if (numb>1)

+					break;

+			};

+			if (numb>1){

+				result:= object SAN::Join{};

+			}

+			else {

+				createRep := true;

+			}

 		}

 		else{

+			createRep := true;

+		};

+		if (createRep){

 			result := object SAN::Rep{};

 			result.oclAsType(SAN::Rep).numbOfReps:="1";

-		};

+		}

 	}

 	

 	var node : SAN::Node;

@@ -330,6 +353,8 @@
 			var rep : SAN::Rep;

 			prop := instSlot.definingFeature.oclAsType(UML::Property);

 			subInstance := instSlot.value->first().oclAsType(UML::InstanceValue).instance;

+			if ( subInstance.getErrorModel() = null and not subInstance.hasInternalErrorModelBehaviour())

+				continue;

 			

 			//Multiplicity > 1 is mapped to a Rep

 			//TODO use mapping to create Rep????

@@ -347,6 +372,7 @@
 			

 			//TODO: curently if a component has errorModel attached than it is considered terminal: we should also support internal components with error model

 			if (subInstance.isComposite() and  (subInstance.getErrorModel()->oclIsUndefined() or subInstance.getErrorModel() = null)){

+				//map the subinstance

 				var childComposite : SAN::ComposedNode := subInstance.map UMLInstance2ComposedNode(false, y1+deltay);

 				if (not rep.oclIsUndefined()){

 					rep.child := childComposite;

@@ -362,34 +388,33 @@
 					childComposite.stateVariables -> forEach (stateVariable){

 						var shared := stateVariable.map shared2Shared();				

 						if (not rep.oclIsUndefined()){

-							//TODO if childComposite is kinf of Rep: case RepFather->Rep child composite: if RepChild share a place, then RepFather has to share the place as well	

+							//if childComposite is kinf of Rep: case RepFather->Rep child composite: if RepChild share a place, then RepFather has to share the place as well	

 							//the six lines below should work, I cannot test them now...

-//							if (childComposite.oclIsTypeOf(Rep) and stateVariable.place->notEmpty() ){

-//								shared.place->includesAll(stateVariable.place) ;

-//								shared.sharedStates:=  Sequence {};

-//							};

+							if (childComposite.oclIsTypeOf(Rep) and stateVariable.place->notEmpty() ){

+								shared.place:=stateVariable.place;

+								shared.sharedStates:=  Sequence {};

+							};

 							rep.stateVariables += shared;

 							shared := shared.map shared2Shared(); //this is the shared for the parent of Rep

-							//check case result(Rep)->rep

-//							if (childComposite.oclIsTypeOf(Rep) and stateVariable.place->notEmpty() and result.oclIsTypeOf(Rep)){

-//								shared.place->includesAll(stateVariable.place) ;

-//								shared.sharedStates:=  Sequence {};

-//							};

+							//check case result(kind of Rep)->rep

+							if (childComposite.oclIsTypeOf(Rep) and stateVariable.place->notEmpty() and result.oclIsTypeOf(Rep)){

+								shared.place:=stateVariable.place ;

+								shared.sharedStates:=  Sequence {};

+							};

 							

 						};

 						result.stateVariables += shared;

 					}

-				}else{

+				}else{ //root join

 					if (not rep.oclIsUndefined()){

 						//case of rootJoin->Rep

 						childComposite.stateVariables -> forEach (stateVariable){

 							var shared := stateVariable.map shared2Shared();

-							//TODO if childComposite is kinf of Rep: case RepFather->Rep child composite: if RepChild share a place, then RepFather has to share the place as well	

-							//the three lines below should work, I cannot test them now... 

-//							if (childComposite.oclIsTypeOf(Rep) and stateVariable.place->notEmpty() ){

-//								shared.place->includesAll(stateVariable.place) ;

-//								shared.sharedStates:=  Sequence {};

-//							};

+							//if childComposite is kinf of Rep: case RepFather->Rep child composite: if RepChild share a place, then RepFather has to share the place as well	

+							if (childComposite.oclIsTypeOf(Rep) and stateVariable.place->notEmpty() ){

+								shared.place:= stateVariable.place ;

+								shared.sharedStates:=  Sequence {};

+							};

 							rep.stateVariables += shared;

 						}

 					}

@@ -428,7 +453,7 @@
 							if (not isRootJoin){

 								var newShared := shared.map shared2Shared();

 								result.stateVariables += newShared;

-								//case Rep1->Rep2->Atomiic: if Rep2 share a place, then Rep1 has to share the same place

+								//case Rep1->Rep2->Atomiic: Rep2 share a place, then Rep1 has to share the place as well

 								if (result.oclIsTypeOf(SAN::Rep)){

 									newShared.place += rewardPlace;

 									newShared.sharedStates:=  Sequence {};

@@ -1498,7 +1523,6 @@
 			var children := getAllErrorModelBehaviourInstance();

 			var errorModel : UML::StateMachine;

 			children -> forEach(child){

-				log ("CHECKING instance " + child.name);

 				errorModel := child.getErrorModel();

 				//if (errorModel != null and not errorModel->oclIsInvalid()){ //this is actually guaranteed

 					var vertexes := errorModel.region->asSequence()->first().oclAsType(UML::Region).subvertex;

@@ -1640,7 +1664,8 @@
 }

 

 

-

+helper UML::InstanceSpecification::hasErrorModel() : Boolean =

+	self.getErrorModel() != null;

 

 helper UML::InstanceSpecification::getErrorModel() : UML::StateMachine =

  self.classifier.oclAsType(UML::Class).ownedBehavior->selectOne(sm : UML::StateMachine | sm.isStereotyped(ERRORMODEL_STEREOTYPE)).oclAsType(StateMachine);

@@ -1668,21 +1693,21 @@
  }

 

 

-query UML::InstanceSpecification::hasInternalInstancesWithErroModel() : Boolean {

-	var childs := self.getSubInstances();

-	childs -> forEach(child){

-		if (not child.getErrorModel()->oclIsUndefined())

-			return true;

-		if (child.getSubInstances()->size() >0){

-			var res = child.hasInternalInstancesWithErroModel();

-			if (res){

-				return true;

-			}

-		}

-			

-	};

-	return false;

-}

+//query UML::InstanceSpecification::hasInternalInstancesWithErroModel() : Boolean {

+//	var childs := self.getSubInstances();

+//	childs -> forEach(child){

+//		if (not child.getErrorModel()->oclIsUndefined())

+//			return true;

+//		if (child.getSubInstances()->size() >0){

+//			var res = child.hasInternalInstancesWithErroModel();

+//			if (res){

+//				return true;

+//			}

+//		}

+//			

+//	};

+//	return false;

+//}

 

 --------------------------------------------------------------------

 -- Helpers to get, start from a given InstanceSpecification,

@@ -1705,6 +1730,28 @@
 }

 

 

+query UML::InstanceSpecification::getAllSubInstances() : List(UML::InstanceSpecification) {

+	var res : List(UML::InstanceSpecification);

+	var instances : Set(UML::InstanceSpecification);

+	instances := self.getSubInstances();

+	var sub : Set(UML::InstanceSpecification);

+	instances->forEach(instance){

+		res->add(instance);

+		var sub2 = instance.getAllSubInstances();

+		sub2 -> forEach (instance2) {

+			res->add(instance2);

+		};

+	};

+	return res;

+}

+

+query UML::InstanceSpecification::hasInternalErrorModelBehaviour() : Boolean {

+	var b: Boolean = not self.getAllSubInstances()->select(inst : InstanceSpecification | inst.getErrorModel() != null)->isEmpty();

+	//log("*************"+self.name+" has internal errorModel "+b.toString());

+	return b;

+}

+

+

 

 helper UML::InstanceSpecification::isSubInstanceOf(parent : UML::InstanceSpecification) : Boolean =

 	parent.getSubInstances()->includes(self);