--- Transformation developed with Eclipse INDIGO --- We have enabled "Inter-model References" in this transformations, since our --- behavior models reference to GCS and ECORE --- The reference to the observer object is not set when there are two rules, --- have a look at that to fix it module WeaveBeh; -- Module Template create OUT : WeaveBeh from INDSLBeh : DSLBeh, INObsBeh : ObsBeh, INWeaveGCS : WeaveGCS, INWeaveMM : WeaveMM, INCorresp : CorrespMM ; -- OUT : WeaveBeh --> Behavior rules resulting of the weave between INDSLBeh:DSLBeh and INObsBeh:ObsBeh. It conforms to the Behavior metamodel -- The Behavior metamodel is taken from SLE12/Metamodels/Behavior.ecore and the resulting model is stored in WeaveModels/WeaveBehavior/OUTWeaveBeh.behavior -- INDSLBeh : DSLBeh --> Behavioral rules of the DSL. It conforms to the Behavior metamodel -- The Behavior metamodel is taken from SLE12/Metamodels/Behavior.ecore and the DSL behavior is taken from PLS/Behavior/DEVSBehavior.behavior -- INObsBeh : ObsBeh --> Behavioral rules of observers. It conforms to the Behavior metamodel -- The Behavior metamodel is taken from SLE12/Metamodels/Behavior.ecore and the observe behavior is taken from SLE/Behaviors/RespTimeBeh.behavior -- INWeaveGCS : WeaveGCS --> GCS model of the weave metamodel result of the WeaveMetamodels.atl transformation. It conforms to the GCS metamodel. -- The GCS metamodel is taken from SLE12/Metamodels/GCS.ecore and the GCS model is taken from WeaveModels/WeaveMetaModels/OUTWeaveGCS.gcs -- INWeaveMM : WeaveMM --> Weave Metamodel result of the WeaveMetamodels.atl transformation. It conforms to Ecore -- The Ecore metamodel is taken from the EMF registry and the woven metamodel is taken from WeaveModels/WeaveMetaModels/OUTWeaveMM.ecore -- INCorresp : CorrespMM --> Model with the correspondences. It conforms to the CorrespondencesMM metamodel -- The Correspondence metamodel is taken from SLE12/Metamodels/CorrespondencesMM and the correspondences model is taken from SLE12/Models/PLSCorrespondences.xmi helper def : slot : WeaveBeh!Slot = OclUndefined; helper def : beh : WeaveBeh!Behavior = OclUndefined; -- Variable for keeping the rules that we create in the weaving model helper def : rules : Set(WeaveBeh!Rule) = Set{}; -- Given a CorrespMM!RuleMatching, a DSLBeh!Pattern (the pattern in a rule) and a -- ObsBeh!Link, which is the link in the pattern (either lhs or rhs) of a rule going -- from an object (which has a correspondence object in the DSLBeh) to another -- object representing a non functional property, this helper returns the -- object that corresponds to the source object of the link helper def: getDSLObjLHS(l : ObsBeh!Link, rm : CorrespMM!RuleMatching, pDSL : DSLBeh!Pattern) : DSLBeh!Object = pDSL.els->select(o|o.oclIsKindOf(DSLBeh!Object))->select(o|o.id = thisModule.getDSLObjIdLHS(rm, l.src))->first() ; -- Given a CorrespondenceMM!RuleMatching and an ObsBeh!Object, this helper -- returns the identifier of the DSLBeh!Object that corresponds -- to the ObsBeh!Object helper def: getDSLObjIdLHS(rm : CorrespMM!RuleMatching, oOb : ObsBeh!Object) : String = rm.lhsObjs->select(om|om.obName = oOb.id)->first().DSLName ; --------------------RULES FOR COPYING THE BEHAVIORAL RULES OF THE DSL---------------------------- entrypoint rule Initialize(){ to b : WeaveBeh!Behavior( denseTime <- false, nonInjectiveness <- false, metamodelGD <- WeaveGCS!MetamodelGD.allInstances() -> first() ) do{ thisModule.beh <- b; -- We keep our woven behavior model in this variable } } rule CopyAtomicRules{ from r : DSLBeh!AtomicRule to outR : WeaveBeh!AtomicRule( name <- r.name, lowerBound <- r.lowerBound, upperBound <- r.upperBound, soft <- r.soft, vbles <- r.vbles, lhs <- r.lhs, rhs <- r.rhs, nacs <- r.nacs, behavior <- thisModule.beh, patterns <- r.patterns, maxDuration <- r.maxDuration, minDuration <- r.minDuration --periodicity <- r.periodicity ) do{ thisModule.rules <- thisModule.rules -> including (outR); } } rule CopyOngoingRules{ from r : DSLBeh!OngoingRule to outR : WeaveBeh!OngoingRule( name <- r.name, lowerBound <- r.lowerBound, upperBound <- r.upperBound, soft <- r.soft, vbles <- r.vbles, lhs <- r.lhs, rhs <- r.rhs, nacs <- r.nacs, behavior <- thisModule.beh, patterns <- r.patterns, maxDuration <- r.maxDuration ) do{ thisModule.rules <- thisModule.rules -> including (outR); } } rule CopyHelpers{ from h : DSLBeh!Helper to outH : WeaveBeh!Helper( oclExpression <- h.oclExpression, behavior <- thisModule.beh ) } rule CopyVariables{ from v : DSLBeh!Variable to outV : WeaveBeh!Variable( name <- v.name, type <- v.type, value <- v.value, "rule" <- v."rule" ) } rule CopyPatterns{ from p : DSLBeh!Pattern to outP : WeaveBeh!Pattern( name <- p.name, "rule" <- p."rule", els <- p.els ) } rule CopyActionExecs{ from a : DSLBeh!ActionExec to outA : WeaveBeh!ActionExec( action <- a.action, participants <- a.participants, id <- a.id, startingTime <- a.startingTime, endingTime <- a.endingTime, status <- a.status, executionTime <- a.executionTime ) } rule CopyObjectRoles{ from o : DSLBeh!ObjectRole to outO : WeaveBeh!ObjectRole( actualObject <- o.actualObject, role <- o.role, actionExec <- o.actionExec ) } rule CopyObjects{ from o : DSLBeh!Object(not o.oclIsKindOf(DSLBeh!Clock)) to outO : WeaveBeh!Object( id <- o.id, sfs <- o.sfs, -- The class of the object has to be that in the WeaveMM and not that in the DSLMM classGD <- WeaveGCS!ClassGD.allInstances()->select(c|c.name=o.classGD.name)->first(), outLinks <- o.outLinks, inLinks <- o.inLinks ) } rule CopyClocks{ from c : DSLBeh!Clock to outC : WeaveBeh!Clock( id <- c.id, sfs <- c.sfs, classGD <- c.classGD, outLinks <- c.outLinks, inLinks <- c.inLinks, pattern <- c.pattern ) } rule CopySlots{ from s : DSLBeh!Slot to outS : WeaveBeh!Slot( --sf <- s.sf, -- sf must point to the EAttribute in the WeaveMM metamodel. In fact, -- in can also be a reference (like in the Collect rule). This is why we -- will with this in the imperative part object <- s.object, oclValue <- s.oclValue ) do{ -- The slot can represent an EAttribute or an EReference, so we have to check it if (s.sf.oclIsKindOf(WeaveMM!EAttribute)){ -- Here, we simply use WeaveMM to refer to the Ecore metamodel outS.sf <- WeaveMM!EAttribute.allInstances()->select(r|r.name=s.sf.name and r.eContainingClass.name=s.sf.eContainingClass.name)->first(); } else { -- If the s.sf is a reference outS.sf <- WeaveMM!EReference.allInstances()->select(r|r.name=s.sf.name and r.eContainingClass.name=s.sf.eContainingClass.name)->first(); } } } rule CopyLinks{ from l : DSLBeh!Link using{ -- Class in the WeaveMM to which the source of the link is type of c : WeaveMM!EClass = WeaveMM!EClass.allInstances()->select(cl|cl.name=l.src.classGD.name)->first(); } to outL : WeaveBeh!Link( src <- l.src, -- This is an Object in Behavior (l.src.classGD is the class and l.src.id is the id) target <- l.target, -- ref.name is the name of the EReference (the link). It has to be a EReference of the input WeaveMM -- We look for that EReference whose name is the same as the name of l.ref and whose -- source class is the same as l.src or a super type of it ref <- WeaveMM!EReference.allInstances()->select(r|r.name=l.ref.name and (c.eStructuralFeatures->exists(r|r.oclIsKindOf(WeaveMM!EReference) and r.name = l.ref.name) or c.eAllSuperTypes->exists(cl|cl.eStructuralFeatures->exists(r|r.oclIsKindOf(WeaveMM!EReference) and r.name=l.ref.name))))->first(), pos <- l.pos ) } rule CopyConditions{ from c : DSLBeh!Condition to outC : WeaveBeh!Condition( oclValue <- c.oclValue ) } -------------------------------------------------------------------------------------------------------------------------- --------------RULES FOR INCLUDING OBSERVER OBJECTS AND LINKS IN THOSE RULES HAVING CORRESPONDENCES------------------ rule CreateObserversLHS { -- This rule aimes to include in the LHS of the DSL rules that correspond with observer rules -- an object and link that are included in the observers -- rule but not in the DSL rule. To achieve it, the rule looks in the CorrespondenceMM -- for two rules that match. The condition to trigger the rule is also to find a link in the LHS of an -- observer rule that does not have a correspondent link, which means that it is pointing to -- an object representing a non functional property. This link, as well as the object representing -- the non functional property, has to be included in the merged behavioral rule. This matched -- rule will create that reference departing from (the class in the WeaveMM model created from) -- the class in the DSL metamodel as well as the class at the other end of the reference. from rm : CorrespMM!RuleMatching, -- Correspondence between an observer and DSL rules om : CorrespMM!ObjectMatching, -- Correspondence between the objects in the rules rObs : ObsBeh!Rule, -- Rule of the observer rDSL : DSLBeh!Rule, -- Rule of the DSL oDSL : DSLBeh!Object, -- Object in the correspondence that belongs to the DSL metamodel lObs : ObsBeh!Link, -- Link departing from an object in the observer rule. This link does not have -- a match in the correspondence model oEndLinkObs : ObsBeh!Object, -- This is the object at the other end of the lObs link, i.e., -- the one representing the non-functional property -- The next one is the object in the correspondence that belongs to the observer rule -- We check that the lObs link does not have a match with any link in the DSL metamodel. -- We check as well that the objects are included in the LHS of the rules doing the matching in the rm. -- (Sometimes, there are errors in the conditions of the line below, simply comment them, save it, uncomment it, -- and then remove the comment and compile it again) oObs : ObsBeh!Object (rObs.lhs.els->includes(oObs) and rDSL.lhs.els->includes(oDSL) and rObs.name=rm.obRuleName and rDSL.name=rm.DSLRuleName and rm.lhsObjs->includes(om) and oObs.id = om.obName and oDSL.id = om.DSLName and oObs.outLinks->includes(lObs) and lObs.src = oObs and lObs.target = oEndLinkObs and rm.lhsLinks -> select (lm|lm.obObjName=oObs.id and lm.obLinkName=lObs.ref.name) -> size() = 0) using{ -- Class in the WeaveMM (class originally belonging to DSL) to which the source of the -- lObs link (class originally belonging to Obs) corresponds to c : WeaveMM!EClass = WeaveMM!EClass.allInstances()->select(cl|cl.name=oDSL.classGD.name)->first(); } to lNonFunc : WeaveBeh!Link( -- The new link pointing the object representing the nonFunctional property -- We look for the appropriate EReference in the WeaveMM metamodel ref <- WeaveMM!EReference.allInstances()->select(r|r.name=lObs.ref.name and (c.name=r.eContainingClass.name or c.eAllSuperTypes->exists(cl|cl.name=r.eContainingClass.name)))->first(), -- The source object of the link has to be the object in the DSL rule, i.e., the object -- created by the "CopyObjects" rule from that object src <- oDSL, target <- oNonFunc, pos <-lObs.pos, pattern <- rDSL.lhs ), oNonFunc : WeaveBeh!Object( id <- oEndLinkObs.id, sfs <- oEndLinkObs.sfs -> collect(s | thisModule.CreateSlot(s, oNonFunc)), -- The class of the object has to be that in the WeaveMM and not that in the ObsMM classGD <- WeaveGCS!ClassGD.allInstances()->select(c|c.name=oEndLinkObs.classGD.name)->first(), inLinks <- Sequence{lNonFunc}, pattern <- rDSL.lhs ) } rule CreateObserversRHS { -- This rule aimes to include in the RHS of the DSL rules that correspond with observer rules -- an object and link that are included in the observers -- rule but not in the DSL rule. To achieve it, the rule looks in the CorrespondenceMM -- for two rules that match. The condition to trigger the rule is also to find a link in the RHS of an -- observer rule that does not have a correspondent link, which means that it is pointing to -- an object representing a non functional property. This link, as well as the object representing -- the non functional property, has to be included in the merged behavioral rule. This matched -- rule will create that reference departing from (the class in the WeaveMM model created from) -- the class in the DSL metamodel as well as the class at the other end of the reference. from rm : CorrespMM!RuleMatching, -- Correspondence between an observer and DSL rules om : CorrespMM!ObjectMatching, -- Correspondence between the objects in the rules rObs : ObsBeh!Rule, -- Rule of the observer rDSL : DSLBeh!Rule, -- Rule of the DSL oDSL : DSLBeh!Object, -- Object in the correspondence that belongs to the DSL metamodel lObs : ObsBeh!Link, -- Link departing from an object in the observer rule. This link does not have -- a match in the correspondence model oEndLinkObs : ObsBeh!Object, -- This is the object at the other end of the lObs link, i.e., -- the one representing the non-functional property -- The next one is the object in the correspondence that belongs to the observer rule -- We check that the lObs link does not have a match with any link in the DSL metamodel. -- We check as well that the objects are included in the RHS of the rules doing the matching in the rm. -- (Sometimes, there are errors in the conditions of the line below, simply comment them, compile it, -- and then remove the comment and compile it again) oObs : ObsBeh!Object (rObs.rhs.els->includes(oObs) and rDSL.rhs.els->includes(oDSL) and rObs.name=rm.obRuleName and rDSL.name=rm.DSLRuleName and rm.rhsObjs->includes(om) and oObs.id = om.obName and oDSL.id = om.DSLName and oObs.outLinks->includes(lObs) and lObs.src = oObs and lObs.target = oEndLinkObs and rm.rhsLinks -> select (lm|lm.obObjName=oObs.id and lm.obLinkName=lObs.ref.name) -> size() = 0) using{ -- Class in the WeaveMM (class originally belonging to DSL) to which the source of the -- lObs link (class originally belonging to Obs) corresponds to c : WeaveMM!EClass = WeaveMM!EClass.allInstances()->select(cl|cl.name=oDSL.classGD.name)->first(); } to lNonFunc : WeaveBeh!Link( -- The new link pointing the object representing the nonFunctional property -- We look for the appropriate EReference in the WeaveMM metamodel ref <- WeaveMM!EReference.allInstances()->select(r|r.name=lObs.ref.name and (c.name=r.eContainingClass.name or c.eAllSuperTypes->exists(cl|cl.name=r.eContainingClass.name)))->first(), -- The source object of the link has to be the object in the DSL rule, i.e., the object -- created by the "CopyObjects" rule from that object src <- oDSL, target <- oNonFunc, pos <-lObs.pos, pattern <- rDSL.rhs ), oNonFunc : WeaveBeh!Object( id <- oEndLinkObs.id, sfs <- oEndLinkObs.sfs -> collect(s | thisModule.CreateSlot(s, oNonFunc)), -- The class of the object has to be that in the WeaveMM and not that in the ObsMM classGD <- WeaveGCS!ClassGD.allInstances()->select(c|c.name=oEndLinkObs.classGD.name)->first(), inLinks <- Sequence{lNonFunc}, pattern <- rDSL.rhs ) } lazy rule CreateSlot{ from s : ObsBeh!Slot, oNonFunc : WeaveBeh!Object to outS : WeaveBeh!Slot( --sf <- s.sf, -- sf must point to the EAttribute in the WeaveMM metamodel. In fact, -- in can also be a reference (like in the Collect rule). That is why we -- will with this in the imperative part object <- oNonFunc, -- If the value of the slot in the observer object is "time", it means that -- it has to access the time elapsed in the DSL, which we identify -- as "clk.time" - the object clock is idenfified as "clk" oclValue <- if s.oclValue='time' then 'clk.time' else s.oclValue endif ) do{ if (s.sf.oclIsKindOf(WeaveMM!EAttribute)){ -- Here, we simple use WeaveMM to refer to the Ecore metamodel outS.sf <- WeaveMM!EAttribute.allInstances()->select(r|r.name=s.sf.name and r.eContainingClass.name=s.sf.eContainingClass.name)->first(); } else { -- If the s.sf is a reference outS.sf <- WeaveMM!EReference.allInstances()->select(r|r.name=s.sf.name and r.eContainingClass.name=s.sf.eContainingClass.name)->first(); } } } --------------RULES FOR INCLUDING CLOCKS IN THE WOVEN RULES------------------ -- Since the majority of the observers require using the time elapsed in the DSL, we add the CLOCK object -- in all those rules where this CLOCK object was not included before rule CreateClock { -- We suppose that the DSL rules are well formed, i.e., if there is an object clock in the -- LHS of the rule, then it is also in the RHS of the rule. If there is not an object clock in -- one pattern, then the object is not in the other pattern either from rm : CorrespMM!RuleMatching, -- Correspondence between an observer and DSL rules rDSL : DSLBeh!Rule -- Rule of the DSL (rDSL.name=rm.DSLRuleName and not rDSL.lhs.els->exists(e|e.oclIsKindOf(DSLBeh!Clock))) to cLHS : WeaveBeh!Clock( id <-'clk', pattern <- rDSL.lhs ), cRHS : WeaveBeh!Clock( id <-'clk', pattern <- rDSL.rhs ) }