AnalysisModel.java
/**
* Copyright (c) 2004-2025 Carnegie Mellon University and others. (see Contributors file).
* All Rights Reserved.
*
* NO WARRANTY. ALL MATERIAL IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY
* KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE
* OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT
* MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
*
* This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
* SPDX-License-Identifier: EPL-2.0
*
* Created, in part, with funding and support from the United States Government. (see Acknowledgments file).
*
* This program includes and/or can make use of certain third party source code, object code, documentation and other
* files ("Third Party Software"). The Third Party Software that is used by this program is dependent upon your system
* configuration. By using this program, You agree to comply with any and all relevant Third Party Software terms and
* conditions contained in any such Third Party Software or separate license file distributed with such Third Party
* Software. The parties who own the Third Party Software ("Third Party Licensors") are intended third party benefici-
* aries to this license with respect to the terms applicable to their Third Party Software. Third Party Software li-
* censes only apply to the Third Party Software and not any other portion of this program or this program as a whole.
*/
package org.osate.xtext.aadl2.errormodel.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.xtext.EcoreUtil2;
import org.osate.aadl2.ComponentClassifier;
import org.osate.aadl2.DirectionType;
import org.osate.aadl2.Feature;
import org.osate.aadl2.NamedElement;
import org.osate.aadl2.VirtualBus;
import org.osate.aadl2.VirtualProcessor;
import org.osate.aadl2.instance.ComponentInstance;
import org.osate.aadl2.instance.ConnectionInstance;
import org.osate.aadl2.instance.ConnectionInstanceEnd;
import org.osate.aadl2.instance.ConnectionReference;
import org.osate.aadl2.instance.FeatureInstance;
import org.osate.aadl2.instance.InstanceObject;
import org.osate.aadl2.instance.SystemOperationMode;
import org.osate.aadl2.util.Aadl2InstanceUtil;
import org.osate.aadl2.util.OsateDebug;
import org.osate.xtext.aadl2.errormodel.errorModel.ErrorPropagation;
import org.osate.xtext.aadl2.errormodel.errorModel.PropagationPath;
import org.osate.xtext.aadl2.errormodel.errorModel.SubcomponentElement;
import org.osate.xtext.aadl2.errormodel.errorModel.TypeSet;
import org.osate.xtext.aadl2.properties.util.InstanceModelUtil;
/**
* The purpose of this class is to keep track of model elements involved in a
* particular EM analysis.
*
* @author phf
*
* @deprecated use {@link org.osate.aadl2.errormodel.propagationgraph.PropgationGraph} instead. Will be removed in 2.7.
* This is used by the AltaRica plugin. Possibly looking to move to AltaRica.
*/
@Deprecated
public class AnalysisModel {
protected ComponentInstance root; // component instance that is the root of
// the analysis
// propagation paths
protected Collection<PropagationPathRecord> propagationPaths = new ArrayList<PropagationPathRecord>();
// component instances that are involved in propagation paths
protected Collection<ComponentInstance> subcomponents = new LinkedHashSet<ComponentInstance>();
// connection instances as source or taraget of a propagation path
protected Collection<ConnectionInstance> connections = new ArrayList<ConnectionInstance>();
public static AnalysisModel createAnalysisModel(ComponentInstance root) {
AnalysisModel am = new AnalysisModel(root);
return am;
}
public AnalysisModel(ComponentInstance root) {
this(root, PropagationPathLevel.LEAF, true);
}
public AnalysisModel(ComponentInstance root, boolean complete) {
this(root, PropagationPathLevel.LEAF, complete);
}
/**
* build up a propagation path graph of propagations within a system as well
* as external ones.
*
* @param root
* ComponentInstance that is the root of the system
* @param level
* LEAF: propagations between leaf (lowest level)components with
* error propagations only TOP: propagations between highest
* level components with error propagations only ALL: between all
* leaf and enclosing components at the source and at the
* destination
* @param completeConnectionsOnly
* Only for connections within a system. Otherwise outgoing only
* and incoming only connections will be included.
*/
public AnalysisModel(ComponentInstance root, PropagationPathLevel level, boolean completeConnectionsOnly) {
this.root = root;
List<ConnectionInstance> cilist = EcoreUtil2.getAllContentsOfType(root, ConnectionInstance.class);
for (ConnectionInstance connectionInstance : cilist) {
if (!(completeConnectionsOnly && !connectionInstance.isComplete())) {
populateConnectionPropagationPaths(connectionInstance, level);
populateBindingPaths(connectionInstance);
}
}
/**
* We also browse the list of all component instances and add user declared propagation paths.
* We also add binding related propagation paths.
*/
List<ComponentInstance> complist = EcoreUtil2.getAllContentsOfType(root, ComponentInstance.class);
for (ComponentInstance ci : complist) {
if (!EMV2Util.hasEMV2Subclause(ci)) {
continue;
}
populateUserDeclaredPropagationPaths(ci);
// if (ci.getCategory() == ComponentCategory.PROCESS || ci.getCategory() == ComponentCategory.ABSTRACT
// || ci.getCategory() == ComponentCategory.SYSTEM || ci.getCategory() == ComponentCategory.PROCESSOR
// || ci.getCategory() == ComponentCategory.THREAD || ci.getCategory() == ComponentCategory.VIRTUAL_BUS
// || ci.getCategory() == ComponentCategory.THREAD_GROUP
// || ci.getCategory() == ComponentCategory.VIRTUAL_PROCESSOR) {
populateBindingPaths(ci);
// }
}
}
public boolean impact(PropagationPathEnd src, PropagationPathEnd dst) {
for (PropagationPathRecord ppr : propagationPaths) {
if ((ppr.getPathSrc().getComponentInstance() == src.getComponentInstance())
&& (ppr.getPathSrc().getErrorPropagation() == src.getErrorPropagation())
&& (ppr.getPathDst().getComponentInstance() == dst.getComponentInstance())
&& (ppr.getPathDst().getErrorPropagation() == dst.getErrorPropagation())) {
return true;
}
if ((ppr.getPathSrc().getComponentInstance() == src.getComponentInstance())
&& (ppr.getPathSrc().getErrorPropagation() == src.getErrorPropagation())) {
ComponentInstance dstCI = ppr.getDstCI();
List<ErrorPropagation> eps = new ArrayList<ErrorPropagation>();
ComponentClassifier classifier = dstCI.getComponentClassifier();
eps.addAll(EMV2Util.getAllOutgoingErrorPropagations(classifier));
for (ErrorPropagation ep : eps) {
if (impact(new PropagationPathEnd(dstCI, ep), dst)) {
return true;
}
}
}
}
return false;
}
public Collection<PropagationPathRecord> getPropagationPaths() {
return propagationPaths;
}
public Collection<ComponentInstance> getSubcomponents() {
return subcomponents;
}
public Collection<ConnectionInstance> getConnections() {
return connections;
}
public InstanceObject getRoot() {
return root;
}
public void setRoot(ComponentInstance root) {
this.root = root;
}
public void printPropagationPaths() {
Collection<PropagationPathRecord> pl = getPropagationPaths();
for (PropagationPathRecord propagationPath : pl) {
OsateDebug.osateDebug("PP src " + propagationPath.getSrcCI().getComponentInstancePath() + ":"
+ generateErrorPropTypeSetText(propagationPath.getPathSrc().getErrorPropagation()) + " dst "
+ propagationPath.getDstCI().getComponentInstancePath() + ":"
+ generateErrorPropTypeSetText(propagationPath.getPathDst().getErrorPropagation())
+ (propagationPath.getConnectionInstance() != null
? " conni " + propagationPath.getConnectionInstance().getName() : ""));
}
}
public String generateErrorPropTypeSetText(ErrorPropagation ep) {
if (ep == null) {
return "";
}
TypeSet ts = ep.getTypeSet();
return ((EMV2Util.getPrintName(ep)) + (ts != null ? " " + EMV2Util.getPrintName(ts) : ""));
}
/**
* find the propagation paths between component instances with error propagations.
* This method handles different levels.
* It also handles both complete and incomplete connection instances (the latter are out only and in only connections
* @param connectionInstance
* @param level LEAF (lowest), TOP (highest), ALL (all combinations)
*/
protected void populateConnectionPropagationPaths(ConnectionInstance connectionInstance,
PropagationPathLevel level) {
SystemOperationMode som = connectionInstance.getSystemInstance().getCurrentSystemOperationMode();
if (!connectionInstance.isActive(som)) {
return;
}
EList<ConnectionReference> connrefs = connectionInstance.getConnectionReferences();
if (connrefs.isEmpty()) {
return;
}
ErrorPropagation srcprop = null;
ComponentInstance srcCI = null;
ErrorPropagation dstprop = null;
ComponentInstance dstCI = null;
ConnectionReference first = connrefs.get(0);
// inonly is an incomplete connection instance that is only incoming,
// i.e., we only have incoming propagations.
boolean inonly = (first.getSource().getComponentInstance() == first.getContext());
ConnectionReference last = connrefs.get(connrefs.size() - 1);
// outonly is an incomplete connection instance that is only outgoing,
// i.e., we only have outgoing propagations.
boolean outonly = (last.getDestination().getComponentInstance() == last.getContext());
// list of additional source error propagations (i.e., those of
// enclosing components.
List<ComponentInstance> addlSrcCI = new ArrayList<ComponentInstance>();
List<ErrorPropagation> addlSrcEP = new ArrayList<ErrorPropagation>();
List<ComponentInstance> addlDstCI = new ArrayList<ComponentInstance>();
List<ErrorPropagation> addlDstEP = new ArrayList<ErrorPropagation>();
for (ConnectionReference connectionReference : connrefs) {
if (!connectionReference.isActive(som)) {
continue;
}
ConnectionInstanceEnd src = connectionReference.getSource();
ConnectionInstanceEnd dst = connectionReference.getDestination();
// remember the first (lowest in the hierarchy) src component
// instance with Error propagation
// srcprop is null until we found the source error propagation
ErrorPropagation foundEP = null;
if (src instanceof FeatureInstance) {
if (inonly) {
foundEP = EMV2Util.getIncomingErrorPropagation((FeatureInstance) src);
} else {
foundEP = EMV2Util.getOutgoingErrorPropagation((FeatureInstance) src);
}
} else if (src instanceof ComponentInstance) {
// deal with an access connection pointing to a component
// instance instead of a feature instance
if (inonly) {
foundEP = EMV2Util.getIncomingAccessErrorPropagation((ComponentInstance) src);
} else {
foundEP = EMV2Util.getOutgoingAccessErrorPropagation((ComponentInstance) src);
}
}
if (foundEP != null) {
switch (level) {
case TOP:
srcprop = foundEP;
srcCI = src.getComponentInstance();
break;
case LEAF:
if (srcprop == null) {
srcprop = foundEP;
srcCI = src.getComponentInstance();
}
break;
case ALL:
addlSrcEP.add(foundEP);
addlSrcCI.add(src.getComponentInstance());
break;
}
}
// We look for destination error propagations
// it should be incoming except when outonly
ErrorPropagation founddst = null;
if (dst instanceof FeatureInstance) {
if (outonly) {
founddst = EMV2Util.getOutgoingErrorPropagation((FeatureInstance) dst);
} else {
founddst = EMV2Util.getIncomingErrorPropagation((FeatureInstance) dst);
}
} else if (dst instanceof ComponentInstance) {
// a shared model element
if (outonly) {
founddst = EMV2Util.getOutgoingAccessErrorPropagation((ComponentInstance) dst);
} else {
founddst = EMV2Util.getIncomingAccessErrorPropagation((ComponentInstance) dst);
}
}
if (founddst != null) {
switch (level) {
case TOP:
if (dstprop == null) {
dstprop = founddst;
dstCI = dst.getComponentInstance();
}
break;
case LEAF:
dstprop = founddst;
dstCI = dst.getComponentInstance();
break;
case ALL:
addlDstEP.add(foundEP);
addlDstCI.add(src.getComponentInstance());
break;
}
}
}
// done with all connection references
// record the results
switch (level) {
case TOP:
case LEAF:
if (srcprop != null && dstprop != null) {
// we found a source and destination. Add it if not already
// there.
addPropagationpathRecord(srcCI, srcprop, dstCI, dstprop, connectionInstance);
} else {
if (srcprop != null && addlSrcEP.size() > 1) {
dstprop = addlSrcEP.get(addlSrcEP.size() - 1);
dstCI = addlSrcCI.get(addlSrcCI.size() - 1);
}
}
break;
case ALL:
// add all combinations
// FIXME: this is obviously wrong
for (int i = 0; i < addlSrcCI.size(); i++) {
for (int j = 0; i < addlDstCI.size(); i++) {
srcCI = addlSrcCI.get(i);
srcprop = addlSrcEP.get(i);
dstCI = addlDstCI.get(i);
dstprop = addlDstEP.get(i);
addPropagationpathRecord(srcCI, srcprop, dstCI, dstprop, connectionInstance);
}
}
break;
}
if (connectionInstance.isBidirectional()) {
// now work in the inverse direction since the conneciton is
// bi-directional
srcprop = null;
srcCI = null;
dstprop = null;
dstCI = null;
addlSrcCI.clear();
addlSrcEP.clear();
addlDstCI.clear();
addlDstEP.clear();
for (int i = connrefs.size() - 1; i >= 0; i--) {
ConnectionReference connectionReference = connrefs.get(i);
if (!connectionReference.isActive(som)) {
continue;
}
ConnectionInstanceEnd dst = connectionReference.getSource();
ConnectionInstanceEnd src = connectionReference.getDestination();
ErrorPropagation foundEP = null;
if (src instanceof FeatureInstance) {
if (inonly) {
foundEP = EMV2Util.getIncomingErrorPropagation((FeatureInstance) src);
} else {
foundEP = EMV2Util.getOutgoingErrorPropagation((FeatureInstance) src);
}
} else if (src instanceof ComponentInstance) {
// deal with an access connection pointing to a component
// instance instead of a feature instance
if (inonly) {
foundEP = EMV2Util.getIncomingAccessErrorPropagation((ComponentInstance) src);
} else {
foundEP = EMV2Util.getOutgoingAccessErrorPropagation((ComponentInstance) src);
}
}
if (foundEP != null) {
switch (level) {
case TOP:
srcprop = foundEP;
srcCI = src.getComponentInstance();
break;
case LEAF:
if (srcprop == null) {
srcprop = foundEP;
srcCI = src.getComponentInstance();
}
break;
case ALL:
addlSrcEP.add(foundEP);
addlSrcCI.add(src.getComponentInstance());
break;
}
}
// We look for destination error propagations
// it should be incoming except when outonly
ErrorPropagation founddst = null;
if (dst instanceof FeatureInstance) {
if (outonly) {
founddst = EMV2Util.getOutgoingErrorPropagation((FeatureInstance) dst);
} else {
founddst = EMV2Util.getIncomingErrorPropagation((FeatureInstance) dst);
}
} else if (dst instanceof ComponentInstance) {
// a shared model element
if (outonly) {
founddst = EMV2Util.getOutgoingAccessErrorPropagation((ComponentInstance) dst);
} else {
founddst = EMV2Util.getIncomingAccessErrorPropagation((ComponentInstance) dst);
}
}
if (founddst != null) {
switch (level) {
case TOP:
if (dstprop == null) {
dstprop = founddst;
dstCI = dst.getComponentInstance();
}
break;
case LEAF:
dstprop = founddst;
dstCI = dst.getComponentInstance();
break;
case ALL:
addlDstEP.add(foundEP);
addlDstCI.add(src.getComponentInstance());
break;
}
}
}
// done with all connection references
// record the results
switch (level) {
case TOP:
case LEAF:
if (srcprop != null && dstprop != null) {
// we found a source and destination. Add it if not already
// there.
addPropagationpathRecord(srcCI, srcprop, dstCI, dstprop, connectionInstance);
} else {
if (srcprop != null && addlSrcEP.size() > 1) {
dstprop = addlSrcEP.get(addlSrcEP.size() - 1);
dstCI = addlSrcCI.get(addlSrcCI.size() - 1);
}
}
break;
case ALL:
// add all combinations
// FIXME: this is obviously wrong
for (int i = 0; i < addlSrcCI.size(); i++) {
for (int j = 0; i < addlDstCI.size(); i++) {
srcCI = addlSrcCI.get(i);
srcprop = addlSrcEP.get(i);
dstCI = addlDstCI.get(i);
dstprop = addlDstEP.get(i);
addPropagationpathRecord(srcCI, srcprop, dstCI, dstprop, connectionInstance);
}
}
break;
}
}
}
/**
* add a propagation path record only if it does not exist already.
* It also updates the list of "saubcomponent" i.e., component instances involved in propagation paths
* @param srcCI
* @param srcprop
* @param dstCI
* @param dstprop
* @param connectionInstance
*/
private void addPropagationpathRecord(ComponentInstance srcCI, ErrorPropagation srcprop, ComponentInstance dstCI,
ErrorPropagation dstprop, ConnectionInstance connectionInstance) {
if (!existsPropagationPath(srcCI, srcprop, dstCI, dstprop, connectionInstance)) {
PropagationPathRecord path = new PropagationPathRecord(srcCI, srcprop, dstCI, dstprop, connectionInstance);
propagationPaths.add(path);
subcomponents.add(srcCI);
subcomponents.add(dstCI);
}
}
/**
* populate direct bindings from the specified component to its resources
*
* @param ci
*/
protected void populateBindingPaths(InstanceObject obj) {
if (obj instanceof ComponentInstance) {
ComponentInstance ci = (ComponentInstance) obj;
List<ComponentInstance> cpus = InstanceModelUtil.getProcessorBinding(ci);
for (ComponentInstance cpu : cpus) {
populateBindingPropagationPaths(ci, cpu, "processor");
}
if (!(ci instanceof VirtualProcessor)) {
// do memory bindings
List<ComponentInstance> mems = InstanceModelUtil.getMemoryBinding(ci);
for (ComponentInstance mem : mems) {
populateBindingPropagationPaths(ci, mem, "memory");
}
}
if (ci instanceof VirtualBus) {
// do connection bindings
List<InstanceObject> boundresources = InstanceModelUtil.getConnectionBindings(ci);
for (InstanceObject bres : boundresources) {
populateBindingPropagationPaths(ci, (ComponentInstance) bres, "connection");
}
}
List<ComponentInstance> systems = InstanceModelUtil.getFunctionBinding(ci);
for (ComponentInstance system : systems) {
populateBindingPropagationPaths(ci, system, "binding");
}
} else if (obj instanceof ConnectionInstance) {
// do connection bindings
List<? extends InstanceObject> boundresources = InstanceModelUtil.getConnectionBindings(obj);
if (boundresources.isEmpty()) {
boundresources = InstanceModelUtil.deriveBoundBuses((ConnectionInstance) obj);
}
for (InstanceObject bres : boundresources) {
populateBindingPropagationPaths((ConnectionInstance) obj, (ComponentInstance) bres, "connection");
}
}
}
/**
* Add a binding as propagation path.
* The first argument is the component bound to a resource (e.g. a process) and the
* boundResource argument the associated resources (e.g. a processor).
* We will add the propagation path in each direction if declared in the EMV2 annex.
* @param comp
* @param boundResource
*/
protected void populateBindingPropagationPaths(ComponentInstance comp, ComponentInstance boundResource,
String resourcebindingKind) {
// source prop kind determined by destination and vice versa (BR = bound
// resource, BC bound component
ErrorPropagation BRsrcprop = EMV2Util.findOutgoingErrorPropagation(boundResource.getComponentClassifier(),
"bindings");
ErrorPropagation BCdstprop = EMV2Util.findIncomingErrorPropagation(comp.getComponentClassifier(),
resourcebindingKind);
if (BRsrcprop != null && BCdstprop != null) {
addPropagationpathRecord(boundResource, BRsrcprop, comp, BCdstprop, null);
}
ErrorPropagation BCsrcprop = EMV2Util.findOutgoingErrorPropagation(comp.getComponentClassifier(),
resourcebindingKind);
ErrorPropagation BRdstprop = EMV2Util.findIncomingErrorPropagation(boundResource.getComponentClassifier(),
"bindings");
if (BCsrcprop != null && BRdstprop != null) {
addPropagationpathRecord(comp, BCsrcprop, boundResource, BRdstprop, null);
}
}
/**
* This is made to support the binding between connection and components.
* Here, the first argument is the connection bound to a resource and the
* boundResource argument the associated resources (e.g. a bus).
*
* @param conn
* @param boundResource
*/
protected void populateBindingPropagationPaths(ConnectionInstance conn, ComponentInstance boundResource,
String bindingKind) {
boolean added = false;
// source prop kind determined by destination and vice versa (BR = bound
// resource, BC bound component
ErrorPropagation BRsrcprop = EMV2Util.findOutgoingErrorPropagation(boundResource.getComponentClassifier(),
"bindings");
if (BRsrcprop != null) {
propagationPaths.add(new PropagationPathRecord(boundResource, BRsrcprop, conn));
added = true;
}
ErrorPropagation BRdstprop = EMV2Util.findIncomingErrorPropagation(boundResource.getComponentClassifier(),
"bindings");
if (BRdstprop != null) {
propagationPaths.add(new PropagationPathRecord(conn, boundResource, BRdstprop));
added = true;
}
if (added) {
connections.add(conn);
subcomponents.add(boundResource);
}
}
/**
* populate with user declared propagation paths declared in this component
* instance the paths are between subcomponents
*
* @param ci
* ComponentInstance
*/
protected void populateUserDeclaredPropagationPaths(InstanceObject obj) {
if (obj instanceof ComponentInstance) {
ComponentInstance ci = (ComponentInstance) obj;
Collection<PropagationPath> pplist = EMV2Util.getAllPropagationPaths(ci.getComponentClassifier());
for (PropagationPath propagationPath : pplist) {
addUserDeclaredPropagationPath(ci, propagationPath);
}
}
}
protected void addUserDeclaredPropagationPath(ComponentInstance ci, PropagationPath pp) {
ErrorPropagation srcEP = null;
ErrorPropagation dstEP = null;
ComponentInstance srcCI = getComponentInstance(ci, EMV2Util.getSubcomponents(pp.getSource()));
ComponentInstance dstCI = getComponentInstance(ci, EMV2Util.getSubcomponents(pp.getTarget()));
if (srcCI != null) {
srcEP = EMV2Util.findErrorPropagation(srcCI.getComponentClassifier(),
pp.getSource().getPropagationPoint().getName(), DirectionType.OUT);
}
if (dstCI != null) {
dstEP = EMV2Util.findErrorPropagation(srcCI.getComponentClassifier(),
pp.getTarget().getPropagationPoint().getName(), DirectionType.IN);
}
addPropagationpathRecord(srcCI, srcEP, dstCI, dstEP, null);
}
protected ComponentInstance getComponentInstance(ComponentInstance ci, EList<SubcomponentElement> sublist) {
ComponentInstance result = ci;
for (SubcomponentElement subcomponentElement : sublist) {
result = result.findSubcomponentInstance(subcomponentElement.getSubcomponent());
if (result == null) {
return null;
}
}
return result;
}
public EList<PropagationPathEnd> getAllPropagationDestinationEnds(ComponentInstance ci, ErrorPropagation outEP) {
EList<PropagationPathEnd> result = new BasicEList<PropagationPathEnd>();
for (PropagationPathRecord propagationPathRecord : propagationPaths) {
PropagationPathEnd src = propagationPathRecord.getPathSrc();
if (src.getComponentInstance() == ci && src.getErrorPropagation() == outEP) {
result.add(propagationPathRecord.getPathDst());
}
}
return result;
}
public EList<PropagationPathEnd> getAllPropagationDestinationEnds(ConnectionInstance ci) {
EList<PropagationPathEnd> result = new BasicEList<PropagationPathEnd>();
for (PropagationPathRecord propagationPathRecord : propagationPaths) {
if (propagationPathRecord.getConnectionInstance() == ci) {
result.add(propagationPathRecord.getPathDst());
}
}
return result;
}
/**
* return all propagation paths out of the outgoing error propagation we
* assume that any type token to be propagated meets the ep type constraint
*
* @param ci
* @param outEP
* @return
*/
public EList<PropagationPathRecord> getAllPropagationPaths(ComponentInstance ci, ErrorPropagation outEP) {
EList<PropagationPathRecord> result = new BasicEList<PropagationPathRecord>();
for (PropagationPathRecord propagationPathRecord : propagationPaths) {
PropagationPathEnd src = propagationPathRecord.getPathSrc();
if (src.getComponentInstance() == ci) {
if (src.getErrorPropagation() == outEP) {
result.add(propagationPathRecord);
} else {
// check if one EP is in an ancestor feature instance
FeatureInstance outepfi = EMV2Util.findFeatureInstance(outEP, ci);
FeatureInstance srcfi = EMV2Util.findFeatureInstance(src.getErrorPropagation(), ci);
if (Aadl2InstanceUtil.containedIn(outepfi, srcfi)
|| Aadl2InstanceUtil.containedIn(srcfi, outepfi)) {
result.add(propagationPathRecord);
}
}
}
}
return result;
}
public EList<PropagationPathRecord> getAllPropagationPaths(ConnectionInstance ci) {
EList<PropagationPathRecord> result = new BasicEList<PropagationPathRecord>();
for (PropagationPathRecord propagationPathRecord : propagationPaths) {
PropagationPathEnd src = propagationPathRecord.getPathSrc();
if (src.getConnectionInstance() == ci) {
result.add(propagationPathRecord);
}
}
return result;
}
public EList<PropagationPathEnd> getAllPropagationSourceEnds(ComponentInstance ci, ErrorPropagation inEP) {
EList<PropagationPathEnd> result = new BasicEList<PropagationPathEnd>();
for (PropagationPathRecord propagationPathRecord : propagationPaths) {
PropagationPathEnd dst = propagationPathRecord.getPathDst();
if (dst.getComponentInstance() == ci && dst.getErrorPropagation() == inEP) {
result.add(propagationPathRecord.getPathSrc());
}
}
return result;
}
public EList<PropagationPathEnd> getAllPropagationSourceEnds(ConnectionInstance ci) {
EList<PropagationPathEnd> result = new BasicEList<PropagationPathEnd>();
for (PropagationPathRecord propagationPathRecord : propagationPaths) {
PropagationPathEnd dst = propagationPathRecord.getPathDst();
if (dst.getConnectionInstance() == ci) {
result.add(propagationPathRecord.getPathSrc());
}
}
return result;
}
public EList<PropagationPathRecord> getAllReversePropagationPaths(ComponentInstance ci, ErrorPropagation inEP) {
EList<PropagationPathRecord> result = new BasicEList<PropagationPathRecord>();
for (PropagationPathRecord propagationPathRecord : propagationPaths) {
PropagationPathEnd src = propagationPathRecord.getPathDst();
if (src.getComponentInstance() == ci && src.getErrorPropagation() == inEP) {
result.add(propagationPathRecord);
}
}
return result;
}
public EList<PropagationPathRecord> getAllReversePropagationPaths(ConnectionInstance ci) {
EList<PropagationPathRecord> result = new BasicEList<PropagationPathRecord>();
for (PropagationPathRecord propagationPathRecord : propagationPaths) {
PropagationPathEnd src = propagationPathRecord.getPathDst();
if (src.getConnectionInstance() == ci) {
result.add(propagationPathRecord);
}
}
return result;
}
/**
* return all feature (or for access component) instances that are the
* connection destination of the given feature instance The source and
* destinations are assumed to be components with error models
*
* @param fi
* @return list of ConnectionInstanceEnd
*/
public EList<ConnectionInstanceEnd> getAllPropagationDestinationEnds(ConnectionInstanceEnd fi) {
EList<ConnectionInstanceEnd> result = new BasicEList<ConnectionInstanceEnd>();
NamedElement f = null;
if (fi instanceof FeatureInstance) {
f = ((FeatureInstance) fi).getFeature();
} else {
f = ((ComponentInstance) fi).getSubcomponent();
}
for (PropagationPathRecord propagationPathRecord : propagationPaths) {
PropagationPathEnd src = propagationPathRecord.getPathSrc();
ErrorPropagation ep = src.getErrorPropagation();
Feature srcf = EMV2Util.getFeature(ep);
if (srcf != null && srcf == f) {
PropagationPathEnd dst = propagationPathRecord.pathDst;
ErrorPropagation dstep = dst.getErrorPropagation();
if (dstep != null) {
Feature dstf = EMV2Util.getFeature(dstep);
ComponentInstance dstCI = dst.getComponentInstance();
if (dstf != null) {
FeatureInstance dstfi = dstCI.findFeatureInstance(dstf);
result.add(dstfi);
} else if (EMV2Util.isAccess(dstep)) {
result.add(dstCI);
}
}
}
}
return result;
}
private boolean existsPropagationPath(ComponentInstance srcCI, ErrorPropagation srcEP, ComponentInstance dstCI,
ErrorPropagation dstEP, ConnectionInstance conni) {
for (PropagationPathRecord pp : propagationPaths) {
if (pp.getConnectionInstance() == conni && pp.getSrcCI() == srcCI && pp.getDstCI() == dstCI
&& pp.getPathSrc().getErrorPropagation() == srcEP
&& pp.getPathDst().getErrorPropagation() == dstEP) {
return true;
}
}
return false;
}
}