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