blob: e64bea9b67eceed26a94c2984a0d6fb4b41cdbda [file] [log] [blame]
/*
-----------------------------------------------------------------------
-- 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
}