| /* |
| ----------------------------------------------------------------------- |
| -- CHESS M2M plugin -- |
| -- -- |
| -- Copyright (C) 2011-2012 -- |
| -- University of Padova, ITALY -- |
| -- -- |
| -- Author: Stefano Puri stefano.puri@intecs.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 -- |
| ----------------------------------------------------------------------- |
| */ |
| |
| |
| modeltype CHESS uses "http://CHESS"; |
| modeltype UML uses "http://www.eclipse.org/uml2/3.0.0/UML"; |
| modeltype MARTE uses "http://www.eclipse.org/papyrus/MARTE/1"; |
| |
| transformation BuildMultiInstance(inout chessModel : CHESS); |
| |
| property CHESSProfile : Profile = null; |
| property model : Model = null; |
| property newMultiInstPackage : Package = null; |
| property CHGaResourcePlatformQN = "CHESS::Core::CHGaResourcePlatform"; |
| |
| |
| configuration property rootComp : String; |
| |
| property rootInstance : InstanceSpecification = null; |
| |
| main() { |
| |
| log("*** Build Multi Instances Transformation ***"); |
| model := chessModel.rootObjects()![Model]; |
| |
| CHESSProfile := model.getAppliedProfiles()->selectOne(name="CHESS").oclAsType(Profile); |
| |
| var compViewPack : Package := model.getView("ComponentView"); |
| compViewPack->map buildMultipleInstancePackage(); |
| |
| } |
| |
| /** |
| Takes the package owning the instances created by the BuildInstance trasformation and explodes |
| all the instanceSpecification and Slot deriving from Properties/Ports with mult>1 |
| */ |
| mapping UML::Package::buildMultipleInstancePackage() { |
| |
| var platforms := self.allOwnedElements()[Package]->select(isStereotyped(CHGaResourcePlatformQN))->asSequence(); |
| log("CHGaResourcesPlatforms in the model: " + platforms->size().repr()); |
| assert fatal (platforms->size()=1) with log("CHGaResourcesPlatform not found"); |
| |
| var instPackage := platforms->first(); |
| |
| var parentPackage : UML::Package := instPackage.owner.oclAsType(UML::Package); |
| |
| newMultiInstPackage := object UML::Package{}; |
| |
| newMultiInstPackage.name := instPackage.name+"_full"; |
| |
| parentPackage.packagedElement += newMultiInstPackage; |
| instPackage.map createFullInstances(); |
| |
| instPackage.map createLinks(); |
| |
| } |
| |
| mapping UML::Package::createFullInstances() { |
| |
| self.packagedElement->forEach(a){ |
| if(a.oclIsTypeOf(UML::InstanceSpecification))then{ |
| var inst := a.oclAsType(UML::InstanceSpecification); |
| if (not inst.classifier -> isEmpty()) then { |
| //this is a Component instance |
| var multiInstanceStereo := inst.getStereotypeApplications()-> |
| select(metaClassName()="MultiInstance")->asOrderedSet()->first().oclAsType(CHESS::Core::MultiInstance); |
| if (not multiInstanceStereo.oclIsInvalid()) then { |
| var i : Integer := 1; |
| while(i<=multiInstanceStereo.upperBound){ |
| inst.map cloneInst(i); |
| i:=i+1; |
| } |
| }else{ |
| inst.map cloneInst(0); |
| } |
| endif; |
| |
| }else{ |
| |
| }endif; |
| }endif; |
| } |
| } |
| |
| |
| mapping UML::Package::createLinks() { |
| |
| self.packagedElement->forEach(a){ |
| if(a.oclIsTypeOf(UML::InstanceSpecification))then{ |
| var inst := a.oclAsType(UML::InstanceSpecification); |
| if (not inst.classifier -> isEmpty()) then { |
| |
| }else{ |
| //this is an instance of Connector |
| var reqInstanceOrig : InstanceSpecification := getRequiringInstance(inst); |
| var reqPort : Port := getRequiredPort(inst); |
| var provPort : Port := getProvidedPort(inst); |
| var provInstanceOrig : InstanceSpecification := getProvidingInstance(inst); |
| var reqInstMult : Integer := 0; |
| var reqPortMult : Integer := reqPort.upperBound(); |
| var provInstMult : Integer := 0; |
| var provPortMult : Integer := provPort.upperBound(); |
| |
| var multiInstanceStereo := reqInstanceOrig.getStereotypeApplications()-> |
| select(metaClassName()="MultiInstance")->asOrderedSet()->first().oclAsType(CHESS::Core::MultiInstance); |
| if (not multiInstanceStereo.oclIsInvalid()) then { |
| reqInstMult :=multiInstanceStereo.upperBound; |
| }else{ |
| reqInstMult :=1; |
| |
| }endif; |
| multiInstanceStereo := provInstanceOrig.getStereotypeApplications()-> |
| select(metaClassName()="MultiInstance")->asOrderedSet()->first().oclAsType(CHESS::Core::MultiInstance); |
| if (not multiInstanceStereo.oclIsInvalid()) then { |
| provInstMult :=multiInstanceStereo.upperBound; |
| } |
| else{ |
| provInstMult :=1; |
| }endif; |
| |
| newMultiInstPackage.ownedElement -> forEach(newInst){ |
| var identInstStereo : CHESS::Core::IdentifInstance := newInst.getStereotypeApplications()->select(metaClassName()="IdentifInstance")-> |
| asOrderedSet()->first().oclAsType(CHESS::Core::IdentifInstance); |
| if (identInstStereo.sourceInstanceSpec = reqInstanceOrig) then { |
| |
| |
| newInst.oclAsType(UML::InstanceSpecification).map setRequired(reqPort, provPort, provInstanceOrig, provInstMult, reqInstMult, reqPortMult); |
| |
| }endif; |
| |
| }; |
| |
| }endif; |
| }endif; |
| } |
| } |
| |
| |
| mapping UML::InstanceSpecification::cloneInst (in id : Integer):UML::InstanceSpecification { |
| name := self.name; |
| classifier := self.classifier; |
| |
| newMultiInstPackage.packagedElement += result; |
| |
| self.slot->forEach(slot){ |
| var multiSlotStereo := slot.getStereotypeApplications()-> |
| select(metaClassName()="MultiSlot")->asOrderedSet()->first().oclAsType(CHESS::Core::MultiSlot); |
| if (not multiSlotStereo.oclIsInvalid()) then { |
| var i : Integer := 1; |
| while(i<=multiSlotStereo.upperBound){ |
| slot.map cloneSlot(i, result); |
| i:=i+1; |
| } |
| }else{ |
| slot.map cloneSlot(0, result); |
| }endif; |
| |
| }; |
| |
| var identifInstance := result.applyStereotype(getCHESSStereotype("IdentifInstance")).oclAsType(CHESS::Core::IdentifInstance); |
| identifInstance.id := id; |
| identifInstance.sourceInstanceSpec :=self; |
| |
| |
| } |
| |
| mapping UML::Slot::cloneSlot (in id : Integer, inout inst : InstanceSpecification):UML::Slot { |
| definingFeature := self.definingFeature; |
| inst.slot += result; |
| if (id > 0) then{ |
| var identifSlot := result.applyStereotype(getCHESSStereotype("IdentifSlot")).oclAsType(CHESS::Core::IdentifSlot); |
| identifSlot.id := id; |
| }endif; |
| |
| var chRtSlotStereo : CHESS::RTComponentModel::CHRtPortSlot := self.getStereotypeApplications()-> |
| select(metaClassName()="CHRtPortSlot")->asOrderedSet()->first().oclAsType(CHESS::RTComponentModel::CHRtPortSlot); |
| if (not chRtSlotStereo.oclIsInvalid()) then { |
| var chrtslot := result.applyStereotype(getCHESSStereotype("CHRtPortSlot")).oclAsType(CHESS::RTComponentModel::CHRtPortSlot); |
| chrtslot.cH_RtSpecification := chRtSlotStereo.cH_RtSpecification; |
| }endif; |
| |
| |
| |
| } |
| |
| |
| query getRequiringInstance(connInst : UML::InstanceSpecification) : UML::InstanceSpecification { |
| connInst.slot->forEach(sl){ |
| if (sl.oclAsType(UML::Slot).definingFeature.oclIsKindOf(UML::Port)) then{ |
| var port : UML::Port := sl.oclAsType(UML::Slot).definingFeature.oclAsType(UML::Port); |
| |
| port.getStereotypeApplications()->select(metaClassName()="ClientServerPort")->forEach(csp){ |
| var p := csp.oclAsType(MARTE::GCM::ClientServerPort); |
| if(p.kind = MARTE::GCM::ClientServerKind::required)then{ |
| return sl.value->select(name="partWithPort")->asOrderedSet()->first().oclAsType(UML::InstanceValue).instance; |
| }endif; |
| } |
| |
| }endif; |
| }; |
| return null; |
| } |
| |
| query getRequiredPort(connInst : UML::InstanceSpecification) : UML::Port { |
| connInst.slot->forEach(sl){ |
| if (sl.oclAsType(UML::Slot).definingFeature.oclIsKindOf(UML::Port)) then{ |
| var port : UML::Port := sl.oclAsType(UML::Slot).definingFeature.oclAsType(UML::Port); |
| |
| port.getStereotypeApplications()->select(metaClassName()="ClientServerPort")->forEach(csp){ |
| var p := csp.oclAsType(MARTE::GCM::ClientServerPort); |
| if(p.kind = MARTE::GCM::ClientServerKind::required)then{ |
| return sl.definingFeature.oclAsType(UML::Port); |
| }endif; |
| } |
| |
| }endif; |
| }; |
| return null; |
| } |
| |
| query getProvidingInstance(connInst : UML::InstanceSpecification) : UML::InstanceSpecification { |
| connInst.slot->forEach(sl){ |
| if (sl.oclAsType(UML::Slot).definingFeature.oclIsKindOf(UML::Port)) then{ |
| var port : UML::Port := sl.oclAsType(UML::Slot).definingFeature.oclAsType(UML::Port); |
| |
| port.getStereotypeApplications()->select(metaClassName()="ClientServerPort")->forEach(csp){ |
| var p := csp.oclAsType(MARTE::GCM::ClientServerPort); |
| if(p.kind = MARTE::GCM::ClientServerKind::provided)then{ |
| return sl.value->select(name="partWithPort")->asOrderedSet()->first().oclAsType(UML::InstanceValue).instance; |
| }endif; |
| } |
| |
| }endif; |
| }; |
| return null; |
| } |
| |
| query getProvidedPort(connInst : UML::InstanceSpecification) : UML::Port { |
| connInst.slot->forEach(sl){ |
| if (sl.oclAsType(UML::Slot).definingFeature.oclIsKindOf(UML::Port)) then{ |
| var port : UML::Port := sl.oclAsType(UML::Slot).definingFeature.oclAsType(UML::Port); |
| |
| port.getStereotypeApplications()->select(metaClassName()="ClientServerPort")->forEach(csp){ |
| var p := csp.oclAsType(MARTE::GCM::ClientServerPort); |
| if(p.kind = MARTE::GCM::ClientServerKind::provided)then{ |
| return sl.definingFeature.oclAsType(UML::Port); |
| }endif; |
| } |
| |
| }endif; |
| }; |
| return null; |
| } |
| |
| |
| |
| |
| |
| //set links between required ports and provided ports |
| mapping UML::InstanceSpecification::setRequired(in reqPort : UML::Port, in provPort : UML::Port, |
| in destInst : UML::InstanceSpecification, in provCompMult: Integer, in reqCompMult: Integer, in reqPortMult: Integer){ |
| //var chessComp := sm.objectsOfType(UML::Component)->select(name = self.name)->asOrderedSet()->first(); |
| var instId : Integer :=0; |
| var identifInstStereo : CHESS::Core::IdentifInstance := self.getStereotypeApplications()-> |
| select(metaClassName()="IdentifInstance")->asOrderedSet()->first().oclAsType(CHESS::Core::IdentifInstance); |
| instId := identifInstStereo.id; |
| |
| self.slot->select(definingFeature.oclIsKindOf(UML::Port))->forEach(slot){ |
| var p : UML::Port := slot.definingFeature.oclAsType(UML::Port); |
| if (p=reqPort) then { |
| var reqPortId : Integer := 0; |
| var identifSlotStereo : CHESS::Core::IdentifSlot := slot.getStereotypeApplications()-> |
| select(metaClassName()="IdentifSlot")->asOrderedSet()->first().oclAsType(CHESS::Core::IdentifSlot); |
| reqPortId := identifSlotStereo.id; |
| |
| //create new InstanceSpecification for connector |
| var connInst : UML::InstanceSpecification := new InstanceSpecification (); |
| //set Slot for requiredPort |
| var reqSlot : UML::Slot := new Slot(); |
| newMultiInstPackage.packagedElement += connInst; |
| connInst.slot += reqSlot; |
| reqSlot.definingFeature := reqPort; |
| var instValue : UML::InstanceValue := new InstanceValue(); |
| reqSlot.value += instValue; |
| instValue.instance := self; |
| var identifSlot := reqSlot.applyStereotype(getCHESSStereotype("IdentifSlot")).oclAsType(CHESS::Core::IdentifSlot); |
| identifSlot.id := reqPortId; |
| |
| //now set Slot for provided port |
| |
| var portID := 0; //0 is the value in case of provPort.upperBound()=1 |
| var destCompID := 0; //0 is the value in case of provCompMult=1 |
| //if reqP.mult = comp.mult*provP.mult then same as for setEmptyLinks() |
| if(p.upperBound()=provPort.upperBound()*provCompMult)then{ |
| |
| if (provPort.upperBound()>1)then{ |
| if(reqPortId.mod(provPort.upperBound())<>0)then{ |
| portID := reqPortId.mod(provPort.upperBound()); |
| }else{ |
| portID :=provPort.upperBound(); |
| }endif; |
| }endif; |
| |
| if (provCompMult > 1) then { |
| if(reqPortId.mod(provPort.upperBound())<>0)then{ |
| destCompID := (reqPortId/provPort.upperBound()).floor()+1; |
| }else{ |
| destCompID := (reqPortId/provPort.upperBound()).floor(); |
| }endif; |
| }endif; |
| }else{ |
| //case reqP.mult=1, comp.mult=provP.mult*destComp.mult |
| if(p.upperBound()=1 and reqCompMult=provPort.upperBound()*provCompMult)then{ |
| |
| if (provPort.upperBound()>1)then{ |
| |
| if(instId.mod(provPort.upperBound())<>0)then{ |
| portID := instId.mod(provPort.upperBound()); |
| }else{ |
| portID := provPort.upperBound(); |
| }endif; |
| }endif; |
| if (provCompMult > 1) then { |
| if(instId.mod(provPort.upperBound())<>0)then{ |
| destCompID := (instId/provPort.upperBound()).floor()+1; |
| }else{ |
| destCompID := (instId/provPort.upperBound()).floor(); |
| }endif; |
| }endif; |
| }else{ |
| //case reqP.mult=provP.mult |
| if(p.upperBound() = provPort.upperBound())then{ |
| |
| if (provPort.upperBound()>1)then{ |
| if(instId.mod(provPort.upperBound())<>0)then{ |
| portID := instId.mod(provPort.upperBound()); |
| }else{ |
| portID := provPort.upperBound(); |
| }endif; |
| }endif; |
| if (provCompMult >1) then { |
| if(instId.mod(provPort.upperBound())<>0)then{ |
| destCompID := (instId/provPort.upperBound()).floor()+1; |
| }else{ |
| destCompID := (instId/provPort.upperBound()).floor(); |
| }endif; |
| }endif; |
| }else{ |
| //case reqP.mult*comp.mult=provP.mult (compDest.mult = 1) |
| if(p.upperBound()*reqCompMult = provPort.upperBound())then{ |
| if (provPort.upperBound()>1)then{ |
| portID := p.upperBound()*reqCompMult; |
| }endif; |
| if (provCompMult > 1) then { |
| destCompID := 1; |
| }endif; |
| }else{ |
| //case reqP.mult*comp.mult=destComp.mult (provP.mult = 1) ---> (self.relId*reqP.mult)-(reqP.mult-reqP.relId) |
| if(p.upperBound()*reqCompMult=provCompMult)then{ |
| if (provPort.upperBound()>1)then{ |
| portID := 1; |
| }endif; |
| if (provCompMult > 1) then { |
| destCompID := (instId*p.upperBound())-(p.upperBound()-reqPortId); |
| }endif; |
| log("MISSING CASE"+" comp:"+instId.toString()+" reqP:"+reqPortId.toString()+" destC:"+destCompID.toString()); |
| }endif; |
| }endif; |
| }endif; |
| }endif; |
| }endif; |
| |
| var provIdentifInstance : UML::InstanceSpecification := getIdentifInstance(destCompID, destInst); |
| |
| //set Slot for providedPort |
| var provSlot : UML::Slot := new Slot(); |
| connInst.slot += provSlot; |
| provSlot.definingFeature := provPort; |
| instValue := new InstanceValue(); |
| provSlot.value += instValue; |
| instValue.instance := provIdentifInstance; |
| identifSlot := provSlot.applyStereotype(getCHESSStereotype("IdentifSlot")).oclAsType(CHESS::Core::IdentifSlot); |
| identifSlot.id := portID; |
| |
| }endif; |
| |
| }; |
| } |
| |
| query getIdentifInstance(in id : Integer, in origInstance : UML::InstanceSpecification):UML::InstanceSpecification{ |
| newMultiInstPackage.ownedElement->forEach(elem){ |
| var identifInstStereo : CHESS::Core::IdentifInstance := elem.getStereotypeApplications()-> |
| select(metaClassName()="IdentifInstance")->asOrderedSet()->first().oclAsType(CHESS::Core::IdentifInstance); |
| if (not identifInstStereo.oclIsInvalid()) then{ |
| if (identifInstStereo.id = id and identifInstStereo.sourceInstanceSpec = origInstance) then { |
| return elem.oclAsType(UML::InstanceSpecification); |
| }endif; |
| }endif; |
| }; |
| return null; |
| } |
| |
| |
| |
| //find the provided port for the required port in input among the connectors in input |
| query Set(UML::Connector)::findOtherEndReq(in pin : String, in cin : String) : UML::ConnectorEnd{ |
| self->forEach(c){ |
| var en := c._end->select(role.name = pin and partWithPort.name=cin)->asOrderedSet()->first(); |
| if((not en.oclIsInvalid()))then{ |
| var target := c._end->select(partWithPort.name <> cin and role.oclAsType(UML::Port).getStereotypeApplications()-> |
| select(metaClassName()="ClientServerPort")->asOrderedSet()->first().oclAsType(MARTE::GCM::ClientServerPort).kind=MARTE::GCM::ClientServerKind::provided)-> |
| asOrderedSet()->first(); |
| return target; |
| }endif; |
| }; |
| return null; |
| } |
| |
| |
| query getCHESSStereotype(stereoName : String) : Stereotype { |
| return CHESSProfile.allOwnedElements()[Stereotype]->selectOne(name=stereoName); |
| } |
| |
| query getCHRtSpecification(port : UML::Port, partWithPort : UML::Property, setComm : Set(UML::Comment)) : chessmlprofile::RTComponentModel::CHRtSpecification { |
| |
| setComm->forEach(comm){ |
| var c := comm.getStereotypeApplications()-> |
| select(metaClassName()="CHRtSpecification")->asOrderedSet()->first().oclAsType(chessmlprofile::RTComponentModel::CHRtSpecification); |
| |
| if (c != null)then{ |
| if (partWithPort != null) then{ |
| |
| if (c.partWithPort = partWithPort and c.base_Comment.annotatedElement->includes(port)) then{ |
| return c; |
| }endif; |
| }else{ |
| if (c.base_Comment.annotatedElement->includes(port)) then{ |
| return c; |
| }endif; |
| |
| }endif; |
| }endif; |
| }; |
| return null; |
| } |
| |
| query getRequiredPort(conn : UML::Connector) : UML::Port { |
| conn._end->forEach(conEnd){ |
| var martePort := conEnd.role.oclAsType(UML::Port).getStereotypeApplications()-> |
| select(metaClassName()="ClientServerPort")->asOrderedSet()->first().oclAsType(MARTE::GCM::ClientServerPort); |
| if(conEnd.partWithPort <> null and martePort.kind=MARTE::GCM::ClientServerKind::required)then{ |
| return conEnd.role.oclAsType(UML::Port); |
| }endif; |
| }; |
| return null; |
| } |
| |
| query getRequiredProperty(conn : UML::Connector) : UML::Property { |
| conn._end->forEach(conEnd){ |
| var martePort := conEnd.role.oclAsType(UML::Port).getStereotypeApplications()-> |
| select(metaClassName()="ClientServerPort")->asOrderedSet()->first().oclAsType(MARTE::GCM::ClientServerPort); |
| if(conEnd.partWithPort <> null and martePort.kind=MARTE::GCM::ClientServerKind::required)then{ |
| return conEnd.partWithPort.oclAsType(UML::Property); |
| }endif; |
| }; |
| return null; |
| } |
| |
| query getProvidedProperty(conn : UML::Connector) : UML::Property { |
| conn._end->forEach(conEnd){ |
| var martePort := conEnd.role.oclAsType(UML::Port).getStereotypeApplications()-> |
| select(metaClassName()="ClientServerPort")->asOrderedSet()->first().oclAsType(MARTE::GCM::ClientServerPort); |
| if(conEnd.partWithPort <> null and martePort.kind=MARTE::GCM::ClientServerKind::provided)then{ |
| return conEnd.partWithPort.oclAsType(UML::Property); |
| }endif; |
| }; |
| return null; |
| } |
| |
| query Model::getView(viewName : String) : Package { |
| var seq := self.packagedElement[Package]-> union(self.packagedElement[Package].packagedElement[Package]); |
| return seq -> selectOne(isStereotyped("CHESS::Core::CHESSViews::" + viewName)); |
| } |
| |
| query Element::isStereotyped(stereoName : String) : Boolean { |
| return self.getAppliedStereotype(stereoName) <> null |
| } |