use of org.osate.xtext.aadl2.errormodel.util.ErrorModelState in project osate2 by osate.
the class PropagationGraphBackwardTraversal method traverseIncomingErrorPropagation.
/**
* traverse backwards according to propagation paths
* if preProcessing result is non-null return it instead of result of actual traversal (used for shared subtrees)
* handle external incoming propagations as origin by calling on processIncomingErrorPropagation
* handle source outgoing propagation
* collection of those results are post processed postProcessIncomingPropagation.
* If empty incoming propagation itself is processed as "leaf" by processIncomingErrorPropagation
* @param component component instance with incoming propagation
* @param errorPropagation incoming propagation
* @param type error type
* @return EObject (can be null)
*/
private EObject traverseIncomingErrorPropagation(ComponentInstance component, ErrorPropagation errorPropagation, TypeToken proptype, BigDecimal scale) {
List<EObject> results = new LinkedList<EObject>();
Collection<TypeToken> filteredtypes = filterTokenThroughConstraint(errorPropagation.getTypeSet(), proptype);
if (filteredtypes.isEmpty()) {
return null;
}
boolean traversed = false;
boolean hasCycle = false;
List<EObject> subResults = new LinkedList<EObject>();
for (TypeToken type : filteredtypes) {
boolean didProp = false;
// we want to track cycles.
// we do that by tagging the feature instance of the error propagation with the error type (as token)
ErrorModelState st = null;
FeatureInstance fi = EMV2Util.findFeatureInstance(errorPropagation, component);
if (fi != null) {
st = (ErrorModelState) ErrorModelStateAdapterFactory.INSTANCE.adapt(fi, ErrorModelState.class);
} else {
st = (ErrorModelState) ErrorModelStateAdapterFactory.INSTANCE.adapt(component, ErrorModelState.class);
}
if (st.visited(errorPropagation, type)) {
// we were there before.
hasCycle = true;
continue;
} else {
st.setVisitToken(errorPropagation, type);
}
EObject preResult = preProcessIncomingErrorPropagation(component, errorPropagation, type, scale);
if (preResult != null) {
// found common event
addSubresult(results, preResult);
continue;
}
for (PropagationGraphPath ppr : Util.getAllReversePropagationPaths(currentAnalysisModel, component, errorPropagation)) {
// traverse incoming
if (ppr.getConnection() != null) {
ErrorSource ces = EMV2Util.findConnectionErrorSourceForConnection(ppr.getConnection());
// the type constraint has to come from the error source as the connection does not have one
if (ces != null && contains(ces.getTypeTokenConstraint(), type)) {
// XXX filter type
EObject result = processConnectionErrorSource(ppr.getConnection(), ces, type, scale);
addSubresult(subResults, result);
didProp = true;
}
ComponentInstance contextCI = ppr.getConnection().getComponentInstance();
TypeTransformationSet tts = EMV2Util.getAllTypeTransformationSet(contextCI);
for (PropagationPathEnd ppe : Util.getAllPropagationSourceEnds(currentAnalysisModel, ppr.getConnection())) {
ComponentInstance componentSource = ppe.getComponentInstance();
ErrorPropagation propagationSource = ppe.getErrorPropagation();
TypeSet newtype = reverseMapTypeTokenToContributor(type, tts);
if (newtype != null) {
EList<TypeToken> ttlist = flattenTypesetElements(newtype);
for (TypeToken typeToken : ttlist) {
TypeToken ntype = EMV2TypeSetUtil.contains(typeToken, type) ? type : typeToken;
EObject result = traverseOutgoingErrorPropagation(componentSource, propagationSource, ntype, scale);
addSubresult(subResults, result);
didProp = true;
}
} else {
EObject result = traverseOutgoingErrorPropagation(componentSource, propagationSource, type, scale);
addSubresult(subResults, result);
didProp = true;
}
// source of connection
newtype = reverseMapTypeTokenToSource(type, tts);
if (newtype != null) {
EList<TypeToken> ttlist = flattenTypesetElements(newtype);
for (TypeToken typeToken : ttlist) {
TypeToken ntype = EMV2TypeSetUtil.contains(typeToken, type) ? type : typeToken;
EObject result = traverseOutgoingErrorPropagation(componentSource, propagationSource, ntype, scale);
addSubresult(subResults, result);
didProp = true;
}
} else {
EObject result = traverseOutgoingErrorPropagation(componentSource, propagationSource, type, scale);
if (!addSubresult(subResults, result)) {
didProp = true;
}
}
}
}
PropagationPathEnd ppe = ppr.getPathSrc();
ComponentInstance componentSource = ppe.getComponentInstance();
ErrorPropagation propagationSource = ppe.getErrorPropagation();
if (propagationSource.getDirection() == DirectionType.IN) {
// we have an external incoming propagation
EObject result = processIncomingErrorPropagation(componentSource, propagationSource, type, scale);
addSubresult(subResults, result);
didProp = true;
} else {
EObject result = traverseOutgoingErrorPropagation(componentSource, propagationSource, type, scale);
addSubresult(subResults, result);
didProp = true;
}
}
st.removeVisitedToken(errorPropagation, type);
if (didProp) {
traversed = true;
}
}
if (!subResults.isEmpty()) {
return postProcessIncomingErrorPropagation(component, errorPropagation, proptype, subResults, scale);
}
if (traversed || hasCycle) {
return null;
}
// we have no subresults and did not prune. Allow handling of incoming propagation as endpoint of traversal
return processIncomingErrorPropagation(component, errorPropagation, proptype, scale);
}
use of org.osate.xtext.aadl2.errormodel.util.ErrorModelState in project osate2 by osate.
the class PropagationGraphBackwardTraversal method traverseOutgoingErrorPropagation.
/**
* process an Outgoing Error Propagation by going backwards in the propagation graph
* if preProcessOutgoingerrorPropagation returns non-null return its value as traverse result.
* First we attempt to go backwards according to the component error behavior, i.e., the OutgoingPropagationCondition.
* If subresults is non-null then return value of postProcessingErrorPropagationCOndition.
* If not present we do it according to error flow specifications.
*
* @param component ComponentInstance
* @param errorPropagation outgoing ErrorPropagation
* @param type ErrorTypes
* @return EObject (can be null)
*/
public EObject traverseOutgoingErrorPropagation(final ComponentInstance component, final ErrorPropagation errorPropagation, TypeToken proptype, BigDecimal scale) {
List<EObject> subResults = new LinkedList<EObject>();
Collection<TypeToken> filteredTypes = filterTokenThroughConstraint(errorPropagation.getTypeSet(), proptype);
if (filteredTypes.isEmpty()) {
return null;
}
HashMultimap<ErrorPropagation, String> handledEOPs = HashMultimap.create();
boolean traverse = false;
boolean hasCycle = false;
for (TypeToken type : filteredTypes) {
// we did follow an OPC.
boolean didProp = false;
EObject found = preProcessOutgoingErrorPropagation(component, errorPropagation, type, scale);
if (found != null) {
addSubresult(subResults, found);
// found common event
continue;
}
// we want to track cycles.
// we do that by tagging the feature instance of the error propagation with the error type (as token)
ErrorModelState st = null;
FeatureInstance fi = EMV2Util.findFeatureInstance(errorPropagation, component);
if (fi != null) {
st = (ErrorModelState) ErrorModelStateAdapterFactory.INSTANCE.adapt(fi, ErrorModelState.class);
} else {
st = (ErrorModelState) ErrorModelStateAdapterFactory.INSTANCE.adapt(component, ErrorModelState.class);
}
if (st.visited(errorPropagation, type)) {
// we were there before.
hasCycle = true;
continue;
} else {
st.setVisitToken(errorPropagation, type);
}
// processing call has to be after the preproccessing call so it is not found and we proceed in processing.
// On the other hand it needs to be called here so the event exists in ftamodel and is found the next time around.
// Originally we were creating the events bottom up thus the loop did not find the event.
// EObject myEvent = processOutgoingErrorPropagation(component, errorPropagation, type, scale);
Collection<ErrorFlow> errorFlows = EMV2Util.getAllErrorFlows(component);
Collection<OutgoingPropagationCondition> opcs = EMV2Util.getAllOutgoingPropagationConditions(component);
for (OutgoingPropagationCondition opc : opcs) {
if ((opc.getTypeToken() != null && !isNoError(opc.getTypeToken())) || opc.getTypeToken() == null) {
if (opc.isAllPropagations() || (EMV2Util.isSame(opc.getOutgoing(), errorPropagation))) {
// opc token if OPC token is subtype or same type
Collection<TypeToken> opcFilteredTypes = filterTokenThroughConstraint(opc.getTypeToken(), type);
for (TypeToken opctype : opcFilteredTypes) {
if (contains(opc.getTypeToken(), opctype)) {
EObject res = handleOutgoingErrorPropagationCondition(component, opc, opctype, handledEOPs, scale);
addSubresult(subResults, res);
didProp = true;
}
}
}
}
}
// try to find a path from an outer to an inner out error propagation
EList<PropagationPathEnd> propagationSources = Util.getAllPropagationSourceEnds(currentAnalysisModel, component, errorPropagation);
for (PropagationPathEnd ppe : propagationSources) {
ComponentInstance componentSource = ppe.getComponentInstance();
ErrorPropagation propagationSource = ppe.getErrorPropagation();
if (propagationSource.getDirection() == DirectionType.OUT) {
Set<ErrorPropagation> eops = handledEOPs.keySet();
if (!containsEOP(eops, propagationSource)) {
// if not already handled by a opc
EObject res = traverseOutgoingErrorPropagation(componentSource, propagationSource, type, scale);
addSubresult(subResults, res);
didProp = true;
}
}
}
for (ErrorFlow ef : errorFlows) {
if (ef instanceof ErrorPath) {
ErrorPath ep = (ErrorPath) ef;
if (handledEOPs.containsEntry(ep.getIncoming(), EMV2Util.getPrintName(type))) {
// already handled by a opc
continue;
}
if (Util.conditionHolds(ef, component)) {
/**
* Make sure that the error type we are looking for is contained
* in the error types for the out propagation.
* This is a fix for the JMR/SAVI WBS model.
*/
if (ep.isAllOutgoing() || EMV2Util.isSame(ep.getOutgoing(), errorPropagation)) {
BigDecimal newscale = scale;
double pathprobability = EMV2Properties.getProbability(component, ep, type);
if (pathprobability > 0) {
newscale = scale.multiply(BigDecimal.valueOf((pathprobability)));
}
if (ep.getTargetToken() != null) {
Collection<TypeToken> mappedTypes = filterTokenThroughConstraint(ep.getTargetToken(), type);
for (TypeToken mappedtype : mappedTypes) {
// we have a type mapping
EList<TypeToken> result;
if (ep.getTypeTokenConstraint() != null) {
// get type from path constraint
result = mapTokenThroughConstraint(ep.getTypeTokenConstraint(), mappedtype);
} else {
// get incoming type from propagation
result = mapTokenThroughConstraint(ep.getIncoming().getTypeSet(), mappedtype);
}
for (TypeToken newToken : result) {
if (ep.isAllIncoming()) {
Collection<ErrorPropagation> inprops = EMV2Util.getAllIncomingErrorPropagations(component);
for (ErrorPropagation eprop : inprops) {
handledEOPs.put(eprop, EMV2Util.getPrintName(newToken));
EObject newEvent = traverseIncomingErrorPropagation(component, eprop, newToken, newscale);
addSubresult(subResults, newEvent);
didProp = true;
}
} else {
handledEOPs.put(ep.getIncoming(), EMV2Util.getPrintName(newToken));
EObject newEvent = traverseIncomingErrorPropagation(component, ep.getIncoming(), newToken, newscale);
addSubresult(subResults, newEvent);
didProp = true;
}
}
}
} else {
// no type mapping
if (ep.isAllIncoming()) {
Collection<ErrorPropagation> inprops = EMV2Util.getAllIncomingErrorPropagations(component);
for (ErrorPropagation eprop : inprops) {
TypeSet matchtype = ep.getTypeTokenConstraint();
if (matchtype == null) {
matchtype = eprop.getTypeSet();
}
EList<TypeToken> filteredtypes = filterTokenThroughConstraint(matchtype, type);
for (TypeToken subtype : filteredtypes) {
handledEOPs.put(eprop, EMV2Util.getPrintName(subtype));
EObject newEvent = traverseIncomingErrorPropagation(component, eprop, subtype, newscale);
addSubresult(subResults, newEvent);
didProp = true;
}
}
} else {
ErrorPropagation inep = ep.getIncoming();
TypeSet matchtype = ep.getTypeTokenConstraint();
if (matchtype == null) {
matchtype = inep.getTypeSet();
}
Collection<TypeToken> mappedtypes = filterTokenThroughConstraint(matchtype, type);
for (TypeToken subtype : mappedtypes) {
handledEOPs.put(inep, EMV2Util.getPrintName(subtype));
EObject newEvent = traverseIncomingErrorPropagation(component, inep, subtype, newscale);
addSubresult(subResults, newEvent);
didProp = true;
}
}
}
}
}
} else if (ef instanceof ErrorSource) {
ErrorSource errorSource = (ErrorSource) ef;
NamedElement src = errorSource.getSourceModelElement();
if (src instanceof ErrorPropagation) {
// check if error source was already handled by opc
ErrorPropagation srcep = (ErrorPropagation) src;
if (targetsEOP(opcs, srcep, type)) {
// already handled by a opc with the same target
continue;
}
}
if (Util.conditionHolds(ef, component)) {
if (errorSource.isAll() || EMV2Util.isSame(errorSource.getSourceModelElement(), errorPropagation)) {
Collection<TypeToken> mappedTypes = filterTokenThroughConstraint(errorSource.getTypeTokenConstraint(), type);
for (TypeToken mappedType : mappedTypes) {
if (src instanceof ErrorPropagation) {
handledEOPs.put((ErrorPropagation) src, EMV2Util.getPrintName(mappedType));
}
if (errorSource.getFailureModeReference() != null) {
List<EObject> stResults = new LinkedList<EObject>();
ErrorBehaviorState ebs = errorSource.getFailureModeReference();
EObject sEvent = traverseErrorBehaviorState(component, ebs, mappedType, scale);
addSubresult(stResults, sEvent);
EObject newEvent = postProcessErrorSource(component, errorSource, proptype, stResults, scale);
addSubresult(subResults, newEvent);
didProp = true;
} else {
EObject newEvent = processErrorSource(component, errorSource, mappedType, scale);
addSubresult(subResults, newEvent);
didProp = true;
}
}
}
}
}
}
st.removeVisitedToken(errorPropagation, type);
if (didProp) {
traverse = true;
}
}
if (!subResults.isEmpty()) {
// out propagation with sub elements
return postProcessOutgoingErrorPropagation(component, errorPropagation, proptype, subResults, scale);
}
if (hasCycle) {
return null;
}
if (traverse && !handledEOPs.isEmpty()) {
// we handled error out propagations
return null;
}
// out propagation as end point
return processOutgoingErrorPropagation(component, errorPropagation, proptype, scale);
}
use of org.osate.xtext.aadl2.errormodel.util.ErrorModelState in project osate2 by osate.
the class PropagateErrorSources method traceErrorPaths.
/**
* traverse to the destination of the propagation path
* @param conni
*/
protected void traceErrorPaths(ComponentInstance ci, ErrorPropagation ep, TypeToken tt, int depth, String entryText) {
ErrorModelState st = null;
FeatureInstance fi = EMV2Util.findFeatureInstance(ep, ci);
if (fi != null) {
st = (ErrorModelState) ErrorModelStateAdapterFactory.INSTANCE.adapt(fi, ErrorModelState.class);
} else {
st = (ErrorModelState) ErrorModelStateAdapterFactory.INSTANCE.adapt(ci, ErrorModelState.class);
}
if (st.visited(ep, tt)) {
// we were there before.
String effectText = "," + generateTypeTokenErrorPropText(ep, tt);
reportEntry(entryText + effectText + " -> [Propagation Cycle],,", depth);
return;
} else {
st.setVisitToken(ep, tt);
}
EList<PropagationGraphPath> paths = Util.getAllPropagationPaths(faultModel, ci, ep);
String effectText = "," + generateTypeTokenErrorPropText(ep, tt);
if (paths.isEmpty()) {
if (fi != null) {
EList<ConnectionInstance> conns = fi.getSrcConnectionInstances();
if (conns.isEmpty()) {
reportEntry(entryText + effectText + " -> [No Outgoing Connection],,", depth);
} else {
for (ConnectionInstance connectionInstance : conns) {
reportEntry(entryText + "," + (tt != null ? EMV2Util.getPrintName(tt) + " " : "") + connectionInstance.getName() + "[No In Propagation],,", depth);
}
}
} else if (EMV2Util.getPropagationPoint(ep) != null) {
reportEntry(entryText + effectText + " -> [No Propagation Point Connection],,", depth);
} else if (ep.getKind() != null) {
reportEntry(entryText + effectText + " -> [No Binding],,", depth);
} else {
reportEntry(entryText + effectText + " -> [Could not find propagation feature],,", depth);
}
} else {
for (PropagationGraphPath path : paths) {
ConnectionInstance pathConni = path.getConnection();
TypeMappingSet typeEquivalence = EMV2Util.getAllTypeEquivalenceMapping(ci.getContainingComponentInstance());
TypeToken mappedtt = tt;
TypeToken resulttt = tt;
TypeToken xformedtt = tt;
if (typeEquivalence != null) {
mappedtt = EMV2TypeSetUtil.mapTypeToken(tt, typeEquivalence);
if (mappedtt != null) {
resulttt = mappedtt;
}
}
if (pathConni != null) {
// find the connection transformation rules if we have a connection path
ComponentInstance contextCI = pathConni.getComponentInstance();
TypeTransformationSet tts = EMV2Util.getAllTypeTransformationSet(contextCI);
// TODO find contributor type token by looking for the state/out prop type.
if (tts != null) {
xformedtt = EMV2TypeSetUtil.mapTypeToken(tt, null, tts);
if (xformedtt == null && mappedtt != null) {
xformedtt = EMV2TypeSetUtil.mapTypeToken(mappedtt, null, tts);
}
if (xformedtt != null) {
resulttt = xformedtt;
}
}
}
EList<PropagationPathEnd> dstEnds;
ConnectionInstance dstConni = path.getPathDst().getConnectionInstance();
String connSymbol = " -> ";
if (dstConni != null) {
// we have a connection binding path with a connection instance as target
dstEnds = Util.getAllPropagationDestinationEnds(faultModel, dstConni);
connSymbol = " -Conn-> ";
// find the connection transformation rules
ComponentInstance contextCI = dstConni.getComponentInstance();
TypeTransformationSet tts = EMV2Util.getAllTypeTransformationSet(contextCI);
// TODO find source type token by looking for the state/out prop type.
if (tts != null) {
xformedtt = EMV2TypeSetUtil.mapTypeToken(null, tt, tts);
if (xformedtt == null && mappedtt != null) {
xformedtt = EMV2TypeSetUtil.mapTypeToken(null, mappedtt, tts);
}
if (xformedtt != null) {
resulttt = xformedtt;
}
}
} else {
dstEnds = new BasicEList<PropagationPathEnd>();
dstEnds.add(path.getPathDst());
}
for (PropagationPathEnd propagationPathEnd : dstEnds) {
ComponentInstance destci = propagationPathEnd.getComponentInstance();
ErrorPropagation destEP = propagationPathEnd.getErrorPropagation();
if (destEP != null) {
TypeSet dstTS = destEP.getTypeSet();
TypeToken targettt = null;
if (tt != null && EMV2TypeSetUtil.contains(dstTS, tt)) {
targettt = tt;
} else if (mappedtt != null && EMV2TypeSetUtil.contains(dstTS, mappedtt)) {
targettt = mappedtt;
} else if (xformedtt != null && EMV2TypeSetUtil.contains(dstTS, xformedtt)) {
targettt = xformedtt;
}
if (targettt == null) {
// type token or mapped/xformed type token is not contained in incoming EP
String connText = connSymbol + generateComponentPropagationPointTypeTokenText(destci, destEP, resulttt) + " [Unhandled Type]";
reportEntry(entryText + effectText + connText, depth);
} else if (destci instanceof SystemInstance) {
// we have an external propagation (out only connection)
String connText = connSymbol + generateComponentPropagationPointText(destci, destEP) + " [External Effect]";
reportEntry(entryText + effectText + connText, depth);
} else if (pathConni != null && Aadl2InstanceUtil.outOnly(pathConni) && !pathConni.isComplete()) {
// outgoing only, but not ending at root
String connText = connSymbol + generateComponentPropagationPointText(destci, destEP) + " [External Effect]";
reportEntry(entryText + effectText + connText, depth);
} else if (destci != null) {
String connText = connSymbol + generateComponentPropagationPointText(destci, destEP);
traceErrorFlows(destci, destEP, targettt, depth, entryText + effectText + connText);
}
}
}
}
}
st.removeVisitedToken(ep, tt);
}
Aggregations