blob: ea977f8880c24489e711827ad027eacb7e741b0a [file] [log] [blame]
/*******************************************************************************
* CHESS core plugin
*
* Copyright (C) 2011-2015
* Mälardalen University, Sweden
*
*
* 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-v10.html
*******************************************************************************/
import org.polarsys.chess.fla.transformations.utilities.blackboxlibrary;
import PortUtilities;
import CommonUtilities;
modeltype Chess uses chessmlprofile('http://CHESS');
modeltype ChessFailurePropagation uses 'http://CHESS/Dependability/FailurePropagation';
modeltype ChessFailureTypes uses 'http:///CHESS/Dependability/FailurePropagation/FailurePropagationDataTypes.ecore';
modeltype ChessCore uses 'http://CHESS/Core';
modeltype FLA uses flamm('http://www.polarsys.org/chess/fla/flamm');
modeltype UML uses 'http://www.eclipse.org/uml2/5.0.0/UML';
modeltype MARTE uses "http://www.eclipse.org/papyrus/GCM/1";
modeltype SySML uses "http://www.eclipse.org/papyrus/0.7.0/SysML/PortAndFlows";
transformation Chess2FlaMM(in source : Chess, out target : FLA);
// Qualified names of stereotypes
property FAILURE_PROPAGATION_STEREOTYPE = "CHESS::Dependability::FailurePropagation::FailurePropagationAnalysis";
property FPTC_SPECIFICATION_STEREOTYPE = "CHESS::Dependability::FailurePropagation::FPTCSpecification";
property FPTC_RULE_STEREOTYPE = "CHESS::Dependability::FailurePropagation::FPTC";
property FLA_BEHAVIOUR_SPECIFICATION = "CHESS::Dependability::FailurePropagation::FLABehavior";
// Platform selected by user
configuration property selectedPlatformQName : String;
property model : Model;
property rootComponent : Class;
main() {
this.model := source.rootObjects()![Model];
var selectedInstSpec : Package = model.findElementByQualifiedName(selectedPlatformQName).oclAsType(Package);
this.rootComponent := selectedInstSpec.ownedElement[InstanceSpecification]->
selectOne(name = selectedInstSpec.name.substringBefore("_instSpec")).classifier![Class];
//this.rootComponent.ownedComment += object Comment {body := "hello chess"; annotatedElement += rootComponent;};
this.rootComponent.UmlComponent2FlaComponent();
}
query UML::Class::UmlComponent2FlaComponent() : FLA::Component {
var flaComponent : FLA::Component;
if (self.isComposite()) {
flaComponent := self.UmlComponent2CompositeComponent();
} else {
flaComponent := self.UmlComponent2SimpleComponent();
};
flaComponent.name := self.name;
flaComponent.id := self.getTransformationId();
flaComponent.inputPorts := self.ownedPort->select(port : UML::Port | port.isInputPort()).umlInputPort2flaPort(flaComponent);
flaComponent.outputPorts := self.ownedPort->select(port : UML::Port | port.isOutputPort()).umlOutputPort2flaPort(flaComponent);
if (flaComponent.oclIsTypeOf(SimpleComponent)) {
setRulesInComponent(flaComponent.oclAsType(SimpleComponent), self.getRuleStrings());
} else if (flaComponent.oclIsTypeOf(CompositeComponent)) {
flaComponent.oclAsType(CompositeComponent).connectPorts(self.ownedMember[Connector]);
};
return flaComponent;
}
// Return a Fla component based on a property
// Component data wil be overridden by property data where available
query Property::asFlaComponent() : FLA::Component {
if (not self.hasPorts()) {
return null;
};
var component := self.type.oclAsType(Class).UmlComponent2FlaComponent();
// Override component name and id with property identity
component.name := self.name;
component.id := self.getTransformationId();
// Override rules in component with property rules, if present
if (component.oclIsTypeOf(SimpleComponent)) {
setRulesInComponent(component.oclAsType(SimpleComponent), self.getRuleStrings());
};
return component;
}
query UML::Class::UmlComponent2CompositeComponent() : FLA::CompositeComponent {
var flaComponent = object FLA::CompositeComponent {};
flaComponent.components += self.ownedMember->select(oclIsTypeOf(Property)).oclAsType(Property).asFlaComponent();
//connections += self.ownedMember[Connector]->reject(_end->exists(role = null))->map umlConnector2flaConnection();
return flaComponent;
}
query UML::Class::UmlComponent2SimpleComponent() : FLA::SimpleComponent {
var flaComponent = object FLA::SimpleComponent {};
return flaComponent;
}
query FLA::Component::getPorts() : Set(FLA::Port) {
return self.inputPorts->union(self.outputPorts);
}
query UML::Port::umlOutputPort2flaPort(owner : FLA::Component) : FLA::Port {
var resultPort = object FLA::Port {id := self.getTransformationId(); name := self.name};
resultPort.owner := owner;
return resultPort;
}
query UML::Port::umlInputPort2flaPort(owner : FLA::Component) : FLA::Port {
var resultPort = object FLA::Port {id := self.getTransformationId(); name := self.name};
resultPort.owner := owner;
if (self.owner = this.rootComponent) {
resultPort.failures := self.getInputFailures();
};
return resultPort;
}
query UML::Port::getInputFailures() : Bag(FLA::Failure) {
if (self.owner <> this.rootComponent) {
return null;
};
var comment := this.rootComponent.ownedComment->selectOne(hasAnnotatedElement(self) and isStereotyped(FPTC_SPECIFICATION_STEREOTYPE));
var failures = comment.getStereotypeValue(FPTC_SPECIFICATION_STEREOTYPE, "failure");
var resultVar := failures.oclAsType(Collection(FailureType))->ChessFailureType2FlaFailure();
return resultVar;
}
query CompositeComponent::connectPorts(connections : Set(UML::Connector)) {
var ports = self.getPorts()->union(self.components.getPorts()->asSet());
connections.connectFlaPorts(ports, self);
}
query UML::Connector::connectFlaPorts(ports : Set(FLA::Port), component : CompositeComponent) {
var connectorEnds = self._end;
var connectedPorts = ports->select(port : FLA::Port | port.matches(connectorEnds->at(1), component) or port.matches(connectorEnds->at(2), component) )->asOrderedSet();
connectedPorts->at(1).connectedPorts += connectedPorts->at(2);
connectedPorts->at(2).connectedPorts += connectedPorts->at(1);
}
query FLA::Port::matches(connectorEnd : UML::ConnectorEnd, component : CompositeComponent) : Boolean {
return ((connectorEnd.role.getTransformationId() = self.id) and
(((connectorEnd.partWithPort <> null) and (connectorEnd.partWithPort.getTransformationId() = self.owner.id))
or (connectorEnd.partWithPort = null and self.owner = component))) ;
}
query setRulesInComponent(inout component : FLA::SimpleComponent, ruleStrings : Collection(String)) {
if ((ruleStrings <> null) and (not ruleStrings->oclIsInvalid())) {
component.rules := ruleStrings.getRuleFromRulestring(component);
}
}
query UML::Element::getRuleStrings() : Collection(String) {
// Use FLABehavior if present
if (self.isStereotyped(FLA_BEHAVIOUR_SPECIFICATION)) {
var flaStereotype := self.getStereotypeApplication(FLA_BEHAVIOUR_SPECIFICATION).oclAsType(FLABehavior);
return flaStereotype.fptc.trim().tokenize(";").trim();
} else {
return null;
};
}
query UML::Component::getSelectedPlatform() : CHGaResourcePlatform {
var stereotype = self.getAppliedStereotype(FAILURE_PROPAGATION_STEREOTYPE);
if (stereotype = null) {
return null;
};
var selectedPackage = self.getValue(stereotype, "platform").oclAsType(CHGaResourcePlatform);
return selectedPackage;
}
query UML::NamedElement::getTransformationId() : String {
//return self.getXmiId();
return self.getQualifiedName();
}
query ChessFailureTypes::FailureType::ChessFailureType2FlaFailure() : FLA::Failure {
var failure = object Failure {};
switch {
case (self = FailureType::noFailure) {
failure.type := FLA::FailureTypes::FailureType::noFailure;
failure.id := "noFailure";
}
case (self = FailureType::wildcard) {
failure.type := FLA::FailureTypes::FailureType::wildcard;
failure.id := "wildcard";
}
case (self = FailureType::variable) {
failure.type := FLA::FailureTypes::FailureType::variable;
failure.id := "notSet";
//TODO: not supported
}
else {
failure.type := FLA::FailureTypes::FailureType::failure;
failure.id := self.toString();
}
};
return failure;
}