use of org.osate.aadl2.ConnectedElement in project osate2 by osate.
the class ConnectionImpl method createDestination.
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public ConnectedElement createDestination() {
ConnectedElement newDestination = (ConnectedElement) create(Aadl2Package.eINSTANCE.getConnectedElement());
setDestination(newDestination);
return newDestination;
}
use of org.osate.aadl2.ConnectedElement in project osate2 by osate.
the class ConnectionImpl method createSource.
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public ConnectedElement createSource() {
ConnectedElement newSource = (ConnectedElement) create(Aadl2Package.eINSTANCE.getConnectedElement());
setSource(newSource);
return newSource;
}
use of org.osate.aadl2.ConnectedElement in project osate2 by osate.
the class CreateConnectionsSwitch method expandFeatureGroupConnection.
/**
* Expand feature groups as much as possible
*
* @param parentci
* @param connInfo
* @param srcEnd
* @param dstEnd
*/
private void expandFeatureGroupConnection(final ComponentInstance parentci, final ConnectionInfo connInfo, ConnectionInstanceEnd srcEnd, ConnectionInstanceEnd dstEnd, ConnectedElement srcToMatch, ConnectedElement dstToMatch) {
ConnectionInstanceEnd oldSrc = connInfo.src;
if (srcEnd instanceof FeatureInstance && dstEnd instanceof FeatureInstance) {
FeatureInstance srcFi = (FeatureInstance) srcEnd;
FeatureInstance dstFi = (FeatureInstance) dstEnd;
if (srcToMatch != null) {
for (FeatureInstance fi : srcFi.getFeatureInstances()) {
if (srcToMatch.getConnectionEnd() == fi.getFeature()) {
expandFeatureGroupConnection(parentci, connInfo, fi, dstFi, srcToMatch.getNext(), dstToMatch);
break;
}
}
} else if (dstToMatch != null) {
for (FeatureInstance fi : dstFi.getFeatureInstances()) {
if (dstToMatch.getConnectionEnd() == fi.getFeature()) {
expandFeatureGroupConnection(parentci, connInfo, srcFi, fi, srcToMatch, dstToMatch.getNext());
break;
}
}
} else {
/*
* One of three possible situations
* - both ends are feature groups without or with an empty type
* - one end is empty and the other is not
* - both ends are not empty, in this case they have the same internal structure
*/
if (isLeafFeature(srcFi) && isLeafFeature(dstFi)) {
// both ends are empty
if (connInfo.isAcross()) {
if (srcFi.getFlowDirection().outgoing() && dstFi.getFlowDirection().incoming()) {
connInfo.src = srcFi;
addConnectionInstance(parentci.getSystemInstance(), connInfo, dstFi);
}
} else {
boolean upOnly = isUpOnly(connInfo, srcFi, dstFi);
if (upOnly && srcFi.getFlowDirection().outgoing() && dstFi.getFlowDirection().outgoing() || !upOnly && srcFi.getFlowDirection().incoming() && dstFi.getFlowDirection().incoming()) {
connInfo.src = srcFi;
addConnectionInstance(parentci.getSystemInstance(), connInfo, dstFi);
}
}
} else if (isLeafFeature(srcFi)) {
// first find the feature instance as an element of the other end
FeatureInstance dst = findDestinationFeatureInstance(connInfo, dstFi);
// we need to deal with outgoing/incoming only and check the direction correctly
if (dst != null && ((connInfo.isAcross() && dst.getFlowDirection().incoming()) || dst.getFlowDirection().outgoing())) {
expandFeatureGroupConnection(parentci, connInfo, srcFi, dst, srcToMatch, dstToMatch);
} else if (srcFi.getCategory() == FeatureCategory.FEATURE_GROUP) {
// we may have a feature group with no FGT or an empty FGT
boolean upOnly = isUpOnly(connInfo, srcFi, dstFi);
for (FeatureInstance dstelem : dstFi.getFeatureInstances()) {
if (upOnly) {
if (dstelem.getFlowDirection().outgoing()) {
expandFeatureGroupConnection(parentci, connInfo, srcFi, dstelem, srcToMatch, dstToMatch);
}
} else if (dstelem.getFlowDirection().incoming()) {
expandFeatureGroupConnection(parentci, connInfo, srcFi, dstelem, srcToMatch, dstToMatch);
}
}
} else {
// create the unexpanded connection instance
connInfo.src = srcFi;
addConnectionInstance(parentci.getSystemInstance(), connInfo, dstFi);
}
} else if (isLeafFeature(dstFi)) {
FeatureInstance target = findSourceFeatureInstance(connInfo, srcFi);
// we need to deal with outgoing/incoming only and check the direction correctly
if (target != null && ((connInfo.isAcross() && target.getFlowDirection().outgoing()) || target.getFlowDirection().incoming())) {
expandFeatureGroupConnection(parentci, connInfo, target, dstFi, srcToMatch, dstToMatch);
} else if (dstFi.getCategory() == FeatureCategory.FEATURE_GROUP || connInfo.srcToMatch != null) {
// we may have a feature group with no FGT or an empty FGT
boolean downOnly = !connInfo.isAcross() && !isUpOnly(connInfo, srcFi, dstFi);
for (FeatureInstance srcelem : srcFi.getFeatureInstances()) {
if (downOnly) {
if (srcelem.getFlowDirection().incoming()) {
expandFeatureGroupConnection(parentci, connInfo, srcelem, dstFi, srcToMatch, dstToMatch);
}
} else if (srcelem.getFlowDirection().outgoing()) {
expandFeatureGroupConnection(parentci, connInfo, srcelem, dstFi, srcToMatch, dstToMatch);
}
}
} else {
// create the unexpanded connection instance
connInfo.src = srcFi;
addConnectionInstance(parentci.getSystemInstance(), connInfo, dstFi);
}
} else {
boolean isSubset = subsetMatch(connInfo.connections);
if (!isSubset) {
Iterator<FeatureInstance> srcIter = srcFi.getFeatureInstances().iterator();
Iterator<FeatureInstance> dstIter = dstFi.getFeatureInstances().iterator();
while (srcIter.hasNext() && dstIter.hasNext()) {
FeatureInstance src = srcIter.next();
FeatureInstance dst = dstIter.next();
expandFeatureGroupConnection(parentci, connInfo, src, dst, srcToMatch, dstToMatch);
}
Assert.isTrue(!srcIter.hasNext() && !dstIter.hasNext(), "Connected feature groups do not have the same number of features");
} else {
// subset matching features by name
for (FeatureInstance dst : dstFi.getFeatureInstances()) {
if ((connInfo.isAcross() && dst.getFlowDirection().incoming()) || dst.getFlowDirection().outgoing()) {
FeatureInstance src = findFeatureInstance(srcFi, dst.getName());
if (src != null) {
expandFeatureGroupConnection(parentci, connInfo, src, dst, srcToMatch, dstToMatch);
}
}
}
}
}
}
}
connInfo.src = oldSrc;
}
use of org.osate.aadl2.ConnectedElement in project osate2 by osate.
the class CreateEndToEndFlowsSwitch method isValidContinuationConnectionEnd.
private boolean isValidContinuationConnectionEnd(final Context flowCxt, final Feature flowIn, final List<Feature> flowInRefined, final ConnectedElement connElement) {
boolean result = false;
final ConnectionEnd connEnd = connElement.getConnectionEnd();
if (connEnd instanceof Feature) {
final List<Feature> connEndRefined = ((Feature) connEnd).getAllFeatureRefinements();
if (flowCxt instanceof FeatureGroup) {
// src end of the flow is "fg.f"
result = connEndRefined.contains(flowCxt);
// if connDestination.getNext() is null then dest end of connection is "fg"
if (result && connElement.getNext() != null) {
final ConnectionEnd connEnd2 = connElement.getNext().getConnectionEnd();
if (connEnd2 instanceof Feature) {
// check "fg.f" to "fg.f"
final List<Feature> connEndRefined2 = ((Feature) connEnd2).getAllFeatureRefinements();
result = flowInRefined.contains(connEnd2) || connEndRefined2.contains(flowIn);
} else {
// Connection doesn't end in feature, so no match
result = false;
}
}
} else {
// checks "f" to "f" or "fg" to "fg"
result = flowInRefined.contains(connEnd) || connEndRefined.contains(flowIn);
}
}
return result;
}
use of org.osate.aadl2.ConnectedElement in project osate2 by osate.
the class Aadl2Validator method checkFeatureGroupConnectionClassifiers.
/**
* Checks legality rule L3 for section 9.5 (Feature Group Connections) "The
* following rules are supported for feature group connection declarations
* that represent a connection up or down the containment hierarchy:
*
* -Classifier_Match: The source feature group type must be identical to the
* feature group type of the destination. This is the default rule.
*
* -Equivalence: An indication that the two classifiers of a connection are
* considered to match if they are listed in the
* Supported_Classifier_Equivalence_Matches property. Matching feature group
* types are specified by the Supported_Classifier_Equivalence_Matches
* property with pairs of classifier values representing acceptable matches.
* Either element of the pair can be the source or destination classifier.
* Equivalence is intended to be used when the feature group types are
* considered to be identical, i.e., their elements match. The
* Supported_Classifier_Equivalence_Matches property is declared globally as
* a property constant.
*
* -Subset: An indication that the two classifiers of a connection are
* considered to match if the outer feature group has outcoming features
* that are a subset of outgoing features of the inner feature group, and if
* the inner feature group has incoming features that are a subset of
* incoming features of the outer feature group. The pairs of features are
* expected to have the same name."
*
* Checks legality rule L4 for section 9.5 (Feature Group Connections) "The
* following rules are supported for feature group connection declarations
* that represent a connection between two subcomponents, i.e., sibling
* component:
*
* -Classifier_Match: The source feature group type must be the complement
* of the feature group type of the destination. This is the default rule.
*
* -Complement: An indication that the two classifiers of a connection are
* considered to complement if they are listed in the
* Supported_Classifier_Complement_Matches property. Matching feature group
* types are specified by the Supported_Classifier_Complement_Matches
* property with pairs of classifier values representing acceptable matches.
* Either element of the pair can be the source or destination classifier.
* Complement is intended to be used when the feature group types are
* considered to be identical, i.e., their elements match. The
* Supported_Classifier_Complement_Matches property is declared globally as
* a property constant.
*
* -Subset: An indication that the two classifiers of a connection are
* considered to match if each has incoming features that are a subset of
* outgoing features of the other. The pairs of features are expected to
* have the same name."
*/
private void checkFeatureGroupConnectionClassifiers(Connection connection) {
if (!(connection.getAllLastSource() instanceof FeatureGroup) || !(connection.getAllLastDestination() instanceof FeatureGroup)) {
return;
}
FeatureGroup source = (FeatureGroup) connection.getAllLastSource();
FeatureGroup destination = (FeatureGroup) connection.getAllLastDestination();
FeatureGroupType sourceType = source.getAllFeatureGroupType();
FeatureGroupType destinationType = destination.getAllFeatureGroupType();
if (sourceType == null || destinationType == null) {
return;
}
final ClassifierMatchingRule classifierMatchingRuleValue = org.osate.aadl2.contrib.modeling.ModelingProperties.getClassifierMatchingRule(connection).orElse(ClassifierMatchingRule.CLASSIFIER_MATCH);
Context srcContext = connection.getAllSourceContext();
Context dstContext = connection.getAllDestinationContext();
// connection across or through a component
if (srcContext instanceof Subcomponent && dstContext instanceof Subcomponent) {
if (classifierMatchingRuleValue == ClassifierMatchingRule.CLASSIFIER_MATCH) {
if (!testIfFeatureGroupsAreInverses(connection.getRootConnection().getSource(), connection.getRootConnection().getDestination())) {
error(connection, "The feature groups '" + source.getName() + "' and '" + destination.getName() + "' are not inverses of each other.");
}
} else if (classifierMatchingRuleValue == ClassifierMatchingRule.EQUIVALENCE) {
warning(connection, "The classifier matching rule '" + ModelingProperties.EQUIVALENCE + "': trusting user that feature groups are equivalent.");
} else if (classifierMatchingRuleValue == ClassifierMatchingRule.CONVERSION) {
warning(connection, "The classifier matching rule '" + ModelingProperties.CONVERSION + "': 'conversion' not supported.");
} else if (classifierMatchingRuleValue == ClassifierMatchingRule.SUBSET) {
if (!checkIfFeatureGroupTypesAreSiblingSubsets(connection.getRootConnection().getSource(), sourceType, connection.getRootConnection().getDestination(), destinationType, connection.isAllBidirectional())) {
error(connection, "The types of '" + source.getName() + "' and '" + destination.getName() + "' ('" + sourceType.getQualifiedName() + "' and '" + destinationType.getQualifiedName() + "') do not satisfy the Subset rule for classifier matching. In order to satisfy this rule, the incoming features of each feature group must be a" + " subset of the outgoing features in the opposite feature group.");
}
}
} else {
// up or down hierarchy
if (classifierMatchingRuleValue == ClassifierMatchingRule.CLASSIFIER_MATCH || classifierMatchingRuleValue == ClassifierMatchingRule.CONVERSION) // ||
// ModelingProperties.COMPLEMENT.equalsIgnoreCase(classifierMatchingRuleValue.getName())
{
if (classifierMatchingRuleValue == ClassifierMatchingRule.CONVERSION) {
warning(connection, "The classifier matching rule '" + ModelingProperties.CONVERSION + "' is not supported for feature group connections. Using rule '" + ModelingProperties.CLASSIFIER_MATCH + "' instead.");
}
// if (classifierMatchingRuleValue != null &&
// ModelingProperties.COMPLEMENT.equalsIgnoreCase(classifierMatchingRuleValue.getName()))
// {
// warning(connection, "The classifier matching rule '" +
// ModelingProperties.COMPLEMENT +
// "' is not supported for feature group connections that
// connect up or down the containment hierarchy. Using rule '" +
// ModelingProperties.CLASSIFIER_MATCH + "' instead.");
// }
boolean sourceIsInverse = isInvertNeeded(getConnectionChain(connection.getRootConnection().getSource()));
boolean destinationIsInverse = isInvertNeeded(getConnectionChain(connection.getRootConnection().getDestination()));
if (sourceType == destinationType) {
if (sourceIsInverse != destinationIsInverse) {
error(connection, "For connections that connect up or down the containment hierarchy, the feature group types of the source and destination must be identical." + " They cannot be inverses of each other.");
}
} else {
if (isSameInExtends(sourceType, destinationType)) {
if (sourceIsInverse != destinationIsInverse) {
error(connection, "Ancestor feature group types match, but feature group '" + source.getName() + "' and '" + destination.getName() + "' differ in inverse of.");
} else {
warning(connection, "The feature group type of '" + source.getName() + "' and '" + destination.getName() + "' do not match, but their ancestors do.");
}
} else {
error(connection, "The feature group types of the source and destination feature groups must be identical for connections that connect up or down the containment hierarchy.");
}
}
} else if (classifierMatchingRuleValue == ClassifierMatchingRule.EQUIVALENCE) {
if (!classifiersFoundInSupportedClassifierEquivalenceMatchesProperty(connection, sourceType, destinationType)) {
error(connection, "The types of '" + source.getName() + "' and '" + destination.getName() + "' ('" + sourceType.getQualifiedName() + "' and '" + destinationType.getQualifiedName() + "') are not identical and they are not listed as matching classifiers in the property constant '" + AadlProject.SUPPORTED_CLASSIFIER_EQUIVALENCE_MATCHES + "'.");
}
} else if (classifierMatchingRuleValue == ClassifierMatchingRule.SUBSET) {
FeatureGroupType innerFeatureGroupType;
ConnectedElement inner;
FeatureGroupType outerFeatureGroupType;
ConnectedElement outer;
if (connection.getAllSourceContext() instanceof Subcomponent) {
innerFeatureGroupType = sourceType;
inner = connection.getRootConnection().getSource();
outerFeatureGroupType = destinationType;
outer = connection.getRootConnection().getDestination();
} else {
outerFeatureGroupType = sourceType;
outer = connection.getRootConnection().getSource();
innerFeatureGroupType = destinationType;
inner = connection.getRootConnection().getDestination();
}
if (!checkIfFeatureGroupTypesAreUpAndDownSubsets(inner, innerFeatureGroupType, outer, outerFeatureGroupType)) {
error(connection, "The types of '" + source.getName() + "' and '" + destination.getName() + "' ('" + sourceType.getQualifiedName() + "' and '" + destination.getQualifiedName() + "') are not identical and they do not satisfy the Subset rule for classifier matching. In order to satisfy this rule, the incoming features of the inner feature group must be a" + " subset of the incoming features of the outer feature group and the outgoing features of the outer feature group must be a subset of the outgoing features of the inner feature" + " group.");
}
}
}
}
Aggregations