use of org.osate.aadl2.Abstract in project osate2 by osate.
the class Aadl2Util method findOwnedNamedElement.
/**
* Find owned named elements. In the case of a thread implementation, subprogram implementation,
* or abstract implementation also look up subprogram calls.
* @param owner Classifier in which the lookup is performed
* @param name name of Element to be found
* @return NamedElement or null
*/
public static NamedElement findOwnedNamedElement(Classifier owner, String name) {
for (Element e : owner.getOwnedElements()) {
if (!(e instanceof NamedElement)) {
continue;
}
NamedElement ne = (NamedElement) e;
String neName = Aadl2Util.getName(ne);
if (neName != null && neName.equalsIgnoreCase(name)) {
return ne;
}
}
if (owner instanceof BehavioredImplementation) {
BehavioredImplementation bi = (BehavioredImplementation) owner;
for (SubprogramCall sc : bi.getSubprogramCalls()) {
if (sc.getName() != null && sc.getName().equalsIgnoreCase(name)) {
return sc;
}
}
}
return null;
}
use of org.osate.aadl2.Abstract in project osate2 by osate.
the class AbstractFeaturePrototypeModel method getCommonContainingClassifier.
/**
* Return the containing classifier which is shared between the selected abstract features.
* @return the containing classifier which is shared between the selected abstract features. Returns null if the containing classifier does not match.
*/
private Classifier getCommonContainingClassifier() {
final Iterator<Classifier> it = bos.boStream(AbstractFeature.class).map(f -> f.getContainingClassifier()).iterator();
if (!it.hasNext()) {
return null;
}
final Classifier classifier = it.next();
while (it.hasNext()) {
if (classifier != it.next()) {
return null;
}
}
return classifier;
}
use of org.osate.aadl2.Abstract in project osate2 by osate.
the class CreateConnectionsSwitch method appendSegment.
/**
* appendSegment Append a segment to a connection instance.
*
* @param newSegment
* the declarative connection to be added to the connection
* instance
* @param ci
* the component that contains the new segment
* @param goOpposite
* the current declarative connection is bidirectional and we are
* following it toward its source
* @param conni
* the connection instance representing the semantic connection
*/
// TODO-LW: set 'complete' in conn info
private void appendSegment(ConnectionInfo connInfo, final Connection newSegment, final ComponentInstance ci, final boolean goOpposite) {
final boolean didModeTransitionConnection = doModeTransitionConnections(ci, connInfo, newSegment);
final ConnectionEnd fromEnd = goOpposite ? newSegment.getAllDestination() : newSegment.getAllSource();
final Context fromCtx = goOpposite ? newSegment.getAllDestinationContext() : newSegment.getAllSourceContext();
ConnectionEnd toEnd = goOpposite ? newSegment.getAllSource() : newSegment.getAllDestination();
final Context toCtx = goOpposite ? newSegment.getAllSourceContext() : newSegment.getAllDestinationContext();
final ComponentInstance toCi = (toCtx instanceof Subcomponent) ? ci.findSubcomponentInstance((Subcomponent) toCtx) : null;
final boolean finalComponent = isConnectionEndingComponent(toCtx);
final boolean dstEmpty = toCtx instanceof Subcomponent && toCi.getComponentInstances().isEmpty();
ConnectionInstanceEnd fromFi = null;
ConnectionInstanceEnd toFi = null;
FeatureInstance pushedFeature = null;
FeatureInstance poppedFeature = null;
FeatureInstance downedFeature = null;
/*
* FIX JD If we have a data component directly connected to a subprogram
* parameter, we do not handle it because we do not deal with parameter
* connection within the instance model. See bug #220
*/
if ((toEnd instanceof ParameterImpl) && ((fromEnd instanceof DataSubcomponent) || (fromEnd instanceof DataAccess))) {
return;
}
/*
* Fix JD bug #222.
* Tweaked again for Issue #2162: changed to check if the context is a subprogram call
* rather than just checking if the feature is contained in a subprogram.
*/
if ((toEnd instanceof DataAccess) && (toCtx instanceof SubprogramCall)) {
return;
}
if (toCtx instanceof Subcomponent && toCi == null) {
if (!(toCtx instanceof SubprogramSubcomponent)) {
error(ci, "Instantiation error: no component instance for subcomponent " + toCtx.getName());
}
return;
}
if (!(fromEnd instanceof Subcomponent)) {
// fromEnd is a feature
final ComponentInstance fromCi = (fromCtx instanceof Subcomponent) ? ci.findSubcomponentInstance((Subcomponent) fromCtx) : null;
if (fromCtx instanceof Subcomponent && fromCi == null) {
if (!(fromCtx instanceof SubprogramSubcomponent)) {
error(ci, "Instantiation error: no component instance for subcomponent " + fromCtx.getName());
}
return;
}
List<FeatureInstance> fiList = null;
if (fromCtx instanceof FeatureGroup) {
// TODO phf: find index and compare with stack
FeatureInstance fgi = (FeatureInstance) AadlUtil.findNamedElementInList(ci.getFeatureInstances(), fromCtx.getName());
if (fgi != null) {
fiList = fgi.getFeatureInstances();
fromFi = (FeatureInstance) AadlUtil.findNamedElementInList(fiList, fromEnd.getName());
}
if (fromFi != null) {
if (!upFeature.empty()) {
FeatureInstance popfi = upFeature.peek();
// match against stack only if we don't reach deeper into feature group
if (connInfo.dstToMatch == null && !Aadl2InstanceUtil.isSame(popfi, (FeatureInstance) fromFi)) {
// did not match
return;
} else {
poppedFeature = upFeature.pop();
}
} else {
downFeature.push((FeatureInstance) fromFi);
downedFeature = (FeatureInstance) fromFi;
}
}
} else {
fiList = (fromCi != null ? fromCi : ci).getFeatureInstances();
fromFi = (FeatureInstance) AadlUtil.findNamedElementInList(fiList, fromEnd.getName());
}
} else {
fromFi = ci.findSubcomponentInstance((Subcomponent) fromEnd);
}
if (!(toEnd instanceof Subcomponent)) {
List<FeatureInstance> fiList = null;
if (toCtx instanceof FeatureGroup) {
FeatureInstance fgi = (FeatureInstance) AadlUtil.findNamedElementInList(ci.getFeatureInstances(), toCtx.getName());
if (fgi != null) {
fiList = fgi.getFeatureInstances();
toFi = (FeatureInstance) AadlUtil.findNamedElementInList(fiList, toEnd.getName());
}
if (toFi != null) {
upFeature.push((FeatureInstance) toFi);
pushedFeature = (FeatureInstance) toFi;
}
} else {
fiList = (toCi != null ? toCi : ci).getFeatureInstances();
toFi = (FeatureInstance) AadlUtil.findNamedElementInList(fiList, toEnd.getName());
}
} else {
toFi = ci.findSubcomponentInstance((Subcomponent) toEnd);
}
/*
* Issue 2032: We do not want connections that go from abstract subcomponent to the ports of
* their containing components if the containing component is final. We specifically are
* checking that the connection starts at a port feature and ends at a feature that is a feature
* of the containing component and the containing component is a connection ending component. We don't
* have to check that the end feature is a port because AADL semantics guarantee that it will be.
*/
if (fromFi instanceof FeatureInstance && ((FeatureInstance) fromFi).getFeature() instanceof Port && toFi.eContainer().equals(ci) && isConnectionEndingCategory(ci.getCategory())) {
return;
}
try {
boolean[] keep = { false };
boolean valid = connInfo.addSegment(newSegment, fromFi, toFi, ci, goOpposite, keep);
if (!keep[0]) {
return;
}
if (!valid) {
if (toFi == null) {
error(ci, "Connection from " + connInfo.src.getInstanceObjectPath() + " via " + newSegment.getQualifiedName() + " has no valid direction. Connection instance not created.");
} else {
error(ci, "Connection from " + connInfo.src.getInstanceObjectPath() + " to " + toFi.getInstanceObjectPath() + " has no valid direction. Connection instance not created.");
}
return;
}
// first check if the connection must end with the new segment
if (toEnd instanceof Subcomponent) {
ComponentInstance toInstance = ci.findSubcomponentInstance((Subcomponent) toEnd);
if (toInstance == null) {
// happens if conn leaves system to aggregate data port
warning(ci, "Connection to " + toEnd.getQualifiedName() + " could not be instantiated.");
} else {
// connection ends at a shared data, bus, or subprogram (group)
connInfo.complete = true;
finalizeConnectionInstance(ci.getSystemInstance(), connInfo, toInstance);
}
} else if (toEnd instanceof InternalFeature || toEnd instanceof ProcessorFeature) {
// can't handle these
// FIXME: What if a connection from outside goes to one of these?
warning(ci, "Connection to " + toEnd.getQualifiedName() + " could not be instantiated.");
} else {
Feature toFeature = (Feature) toEnd;
if (toEnd instanceof Parameter) {
// connection ends at a parameter
FeatureInstance dstFi = toCi.findFeatureInstance(toFeature);
if (dstFi == null) {
error(toCi, "Destination feature " + toFeature.getName() + " not found. No connection created.");
} else {
connInfo.complete = true;
finalizeConnectionInstance(ci, connInfo, dstFi);
}
} else if (dstEmpty) {
// connection ends because the destination component does not
// contain any subcomponents
FeatureInstance dstFi = toCi.findFeatureInstance(toFeature);
if (dstFi == null) {
error(toCi, "Destination feature " + toFeature.getName() + " not found. No connection created.");
} else {
connInfo.complete = true;
finalizeConnectionInstance(ci, connInfo, dstFi);
}
} else if (!(toCtx instanceof Subcomponent)) {
// implementation
if (ci instanceof SystemInstance) {
if (toCtx instanceof FeatureGroup) {
// XXX: PHF: going up into an element of a feature group
// should we go to the FG or to the feature?
finalizeConnectionInstance(ci, connInfo, ci.findFeatureInstance((FeatureGroup) toCtx));
} else {
finalizeConnectionInstance(ci, connInfo, ci.findFeatureInstance(toFeature));
}
} else {
if (toCtx instanceof FeatureGroup) {
toFeature = (FeatureGroup) toCtx;
// toFeature now points to the enclosing feature group
// this should be the starting feature for the next
// connection
}
ComponentInstance nextCi = ci.getContainingComponentInstance();
List<Connection> parentConns = InstanceUtil.getComponentImplementation(nextCi, 0, classifierCache).getAllConnections();
FeatureInstance dstFi = ci.findFeatureInstance(toFeature);
List<Connection> conns = filterOutgoingConnections(parentConns, dstFi.getFeature(), ci.getSubcomponent());
if (conns.isEmpty()) {
if (!didModeTransitionConnection) {
if (ci instanceof SystemInstance) {
finalizeConnectionInstance(ci, connInfo, ci.findFeatureInstance(toFeature));
} else {
warning(toFi, "Could not continue connection from " + connInfo.src.getInstanceObjectPath() + " through " + toFi.getInstanceObjectPath() + ". No connection instance created.");
}
}
} else {
for (Connection nextConn : conns) {
// note: nextConn goes either up or across
final ConnectionInfo clone = connInfo.cloneInfo();
boolean opposite = false;
if (nextConn.isAllBidirectional()) {
/*
* The next connection is bidirectional, but we need to figure out if we are
* traveling from its src to dest or from its dest to src.
*
* Put another way, we traverse the next connection in the opposite direction
* only if the destination feature instance of the next connection is equal to
* the destination feature instance of the current connection (based on "toFeature" which
* already takes it's own opposite direction into account via "goOpposite" at
* the start of the method).
*/
final ConnectionEnd nextConnDest = nextConn.getAllDestination();
if (nextConnDest instanceof Feature) {
final Feature nextConnDstFeature = (Feature) nextConnDest;
FeatureInstance nextConnDstFi = nextCi.findFeatureInstance(nextConnDstFeature);
/*
* If we find the connection destination in the containing component instance, then
* the connection is a normal (not reversed) traversal of the connection. The
* value of `opposite` will stay `false`.
*/
if (nextConnDstFi == null) {
/*
* Didn't find the next destination in the containing component, so the question
* still is, is the destination in a sibling subcomponent or is it a reversed
* traversal from the containing component, or even a reversed traversal from
* a sibling subcomponent?
*/
// next goes across, maybe?
Context nextConnDstCtx = nextConn.getAllDestinationContext();
if (nextConnDstCtx instanceof Subcomponent) {
final ComponentInstance nextConnDstSubi = nextCi.findSubcomponentInstance((Subcomponent) nextConnDstCtx);
nextConnDstFi = nextConnDstSubi.findFeatureInstance(nextConnDstFeature);
}
if (nextConnDstFi != null) {
/*
* Opposite is true if the dest of the next connection the same feature instance as the
* dest of the current connection.
*/
opposite = ci.findFeatureInstance(toFeature) == nextConnDstFi;
}
}
}
} else {
/*
* not bidirectional, so the src of nextConn is a feature of 'ci', and the dest
* is a feature of either 'nextCi` or a sibling subcomponent. We are following
* the connection in its natural direction, so `opposite` is `false`.
*/
}
appendSegment(clone, nextConn, nextCi, opposite);
}
}
}
} else {
if (toCtx instanceof Subcomponent && toCi == null) {
if (!(toCtx instanceof SubprogramSubcomponent)) {
error(ci, "Instantiation error: no component instance for subcomponent " + toCtx.getName());
}
return;
}
toFi = toCi.findFeatureInstance(toFeature);
if (toFi == null) {
error(ci, "Could not find instance object for feature " + toEnd.getName() + " of subcomponent " + ((Subcomponent) toCtx).getName() + ". No connection instance created.");
return;
}
ComponentImplementation toImpl = InstanceUtil.getComponentImplementation(toCi, 0, classifierCache);
if (toImpl == null) {
connInfo.complete = true;
finalizeConnectionInstance(ci, connInfo, toFi);
} else {
// there is a toImpl
/*
* Issue 2032: Get the connections internal to the destination component that connect
* to the feature. Two cases here. (1) If the component is final (thread/device/processor),
* we only follow access features inside, (2) otherwise we follow all the internal connections
* except for the parameter connections. We keep track of whether any internal connections were
* ignored so we know if we should create a connection instance that stops at the component itself.
*/
final AtomicBoolean hasIgnoredConnection = new AtomicBoolean(false);
List<Connection> conns = AadlUtil.getIngoingConnections(toImpl, toFeature, c -> {
if (c instanceof AccessConnection) {
// never ignore access connections
return true;
} else if (c instanceof ParameterConnection) {
// always ignore parameter connections
hasIgnoredConnection.set(true);
return false;
} else {
// Ignore other connections only if the component is connection ending
if (finalComponent) {
hasIgnoredConnection.set(true);
return false;
} else {
return true;
}
}
});
if (conns.isEmpty()) {
// No internal connections, or they are all parameter connections, so we stop here
List<Subcomponent> subs = toImpl.getAllSubcomponents();
if (!subs.isEmpty()) {
if (!finalComponent) {
warning(ci, "No connection declaration from feature " + toEnd.getName() + " of component " + ((Subcomponent) toCtx).getName() + " to subcomponents. Connection instance ends at " + ((Subcomponent) toCtx).getName());
}
connInfo.complete = true;
finalizeConnectionInstance(ci, connInfo, toFi);
}
} else {
/*
* Issue 2032: If we get here then destination component has internal connections,
* not all of which are parameter connections. We definitely are going to proceed
* inside the component with the connection. However, if there are internal
* connections that were ignored, we also need to create a connection instance that
* ends at the component.
*
* NB. Not possible to have an ignored parameter connection from a feature and have a
* another not ignored connection from that feature because the only place a
* parameter connection can exist is in a subprogram or a thread, and it's
* not possible to have a regular port connections internal to
* either one of those (with the exception of abstract components, but those
* should probably be illegal anyway and we ignore those too).
*/
if (hasIgnoredConnection.get()) {
final ConnectionInfo clone = connInfo.cloneInfo();
clone.complete = true;
finalizeConnectionInstance(ci, clone, toFi);
}
// as End or as Cxt
for (Connection nextConn : conns) {
final ConnectionInfo clone = connInfo.cloneInfo();
EList<Feature> toflist = toFeature.getAllFeatureRefinements();
Context dstCtx = nextConn.getAllDestinationContext();
// dstCtx is null if we're going down and in opposite direction
final boolean opposite = toflist.contains(nextConn.getAllDestination()) && (dstCtx == null || toCtx == dstCtx) || toflist.contains(dstCtx);
appendSegment(clone, nextConn, toCi, opposite);
}
}
}
}
}
} finally {
if (pushedFeature != null) {
if (!upFeature.empty()) {
upFeature.pop();
} else {
warning(ci, "Popping from empty upindex");
}
}
if (poppedFeature != null) {
if (downFeature.empty()) {
upFeature.push(poppedFeature);
} else {
// remove from downIndex
warning(ci, "Trying to push back on while downIndex is not empty");
}
}
if (downedFeature != null) {
// remove from downIndex
FeatureInstance popfeature = downFeature.pop();
if (!Aadl2InstanceUtil.isSame(popfeature, downedFeature)) {
// should be the same
warning(ci, "Did not match popped downIndex");
}
}
}
}
use of org.osate.aadl2.Abstract in project osate2 by osate.
the class CreateConnectionsSwitch method instantiateConnections.
/**
* Create all connection instances that start at a component instance.
*
* @param ci
* The component that is the ultimate source; this should be a
* thread, processor or device
* @throws InstantiationException
*/
// TODO-LW: handle access to subprograms and subprogram groups
// TODO-LW: connections inside threads (mode conn, access)
// TODO-LW: warning if connection incomplete
private void instantiateConnections(final ComponentInstance ci) throws UnsupportedOperationException {
ComponentCategory cat = ci.getCategory();
Subcomponent sub = ci.getSubcomponent();
ComponentInstance parentci = ci.getContainingComponentInstance();
List<Connection> parentConns = InstanceUtil.getComponentImplementation(parentci, 0, classifierCache).getAllConnections();
if (parentci instanceof SystemInstance) {
monitor.subTask("Creating connections in " + ci.getName());
}
if (cat == DATA || cat == BUS || cat == VIRTUAL_BUS || cat == SUBPROGRAM || cat == SUBPROGRAM_GROUP) {
// connection instance may start at a shared component
for (Connection conn : filterStartingConnections(parentConns, sub)) {
boolean opposite = sub.getAllSubcomponentRefinements().contains(conn.getAllDestination());
appendSegment(ConnectionInfo.newConnectionInfo(ci), conn, parentci, opposite);
if (monitor.isCanceled()) {
return;
}
}
}
// connection instance may start at a feature
List<Connection> outsideSubConns = filterOutgoingConnections(parentConns, sub);
ComponentImplementation cimpl = InstanceUtil.getComponentImplementation(ci, 0, classifierCache);
@SuppressWarnings("unchecked") List<Connection> insideSubConns = cimpl != null ? cimpl.getAllConnections() : Collections.EMPTY_LIST;
boolean hasOutgoingFeatureSubcomponents = AadlUtil.hasOutgoingFeatureSubcomponents(ci.getComponentInstances());
// prevFi is used to skip all but the first element in a feature array
// TODO inspect index, instead
FeatureInstance prevFi = null;
for (FeatureInstance featurei : ci.getFeatureInstances()) {
if (prevFi == null || !prevFi.getName().equalsIgnoreCase(featurei.getName())) {
Feature feature = featurei.getFeature();
// exist
if (AadlUtil.hasOutgoingFeatures(featurei)) {
List<Connection> outgoingConns = filterOutgoingConnections(outsideSubConns, feature, sub);
/*
* We only care about internal connections if (1) they exist and (2) the component is either not connection ending or it is connection
* ending but the feature has an access feature. (Here we are deliberately ignoring any connections between a port on thread
* and feature of a abstract subcomponent. Such connections are currently legal but seem wrong.)
*/
final FeatureInfo fInfo = FeatureInfo.init(featurei);
final boolean isConnectionEndingCategory = isConnectionEndingCategory(cat);
final boolean lookInside = hasOutgoingFeatureSubcomponents && (!isConnectionEndingCategory || fInfo.hasAccess());
final boolean connectedInside = lookInside && isConnectionEnd(insideSubConns, feature);
final boolean destinationFromInside = lookInside && isDestination(insideSubConns, feature);
for (final Connection conn : outgoingConns) {
/*
* We start from inside the component in the following cases
* - The feature is a destination from inside (we have already dealt with the connection ending component case above)
* - The outside connection is bidirectional and the the feature is connected inside (again, we have already filtered out the connection
* ending component case)
*
* So, we start AT THE Component in the following cases
* - The disjunction of the above is false
* - The component is connection ending and the feature has ports or feature groups. (This case is only relevant when
* the feature is a feature group.)
*/
if ((!destinationFromInside && !(conn.isAllBidirectional() && connectedInside)) || (isConnectionEndingCategory && (fInfo.hasFeatureGroup() || fInfo.hasPort()))) {
prevFi = featurei;
boolean opposite = isOpposite(feature, sub, conn);
appendSegment(ConnectionInfo.newConnectionInfo(featurei), conn, parentci, opposite);
if (monitor.isCanceled()) {
return;
}
}
}
}
}
}
}
use of org.osate.aadl2.Abstract in project osate2 by osate.
the class InstantiateModel method instantiateSubcomponent.
protected void instantiateSubcomponent(final ComponentInstance parent, final ModalElement mm, final Subcomponent sub, Stack<Long> indexStack, int index) throws InterruptedException {
final ComponentInstance newInstance = InstanceFactory.eINSTANCE.createComponentInstance();
final ComponentClassifier cc;
final InstantiatedClassifier ic;
newInstance.setSubcomponent(sub);
// Issue 961: Set the category for real later (below); set it here now in case something goes wrong
newInstance.setCategory(sub.getCategory());
newInstance.setName(sub.getName());
newInstance.getIndices().addAll(indexStack);
newInstance.getIndices().add(Long.valueOf(index));
parent.getComponentInstances().add(newInstance);
ic = getInstantiatedClassifier(newInstance);
if (ic == null) {
cc = null;
} else {
cc = (ComponentClassifier) ic.getClassifier();
}
if (cc == null) {
errManager.warning(newInstance, "Instantiated subcomponent doesn't have a component classifier");
} else {
// if (cc instanceof ComponentType) {
// if (sub instanceof SystemSubcomponent || sub instanceof ProcessSubcomponent
// || sub instanceof ThreadGroupSubcomponent) {
// errManager.warning(newInstance, "Instantiated subcomponent has a component type only");
// }
// }
newInstance.setClassifier(cc);
/*
* From Issue 961:
*
* I think the category can be determined as follows:
*
* If the classifier is not abstract then use its category (and maybe check that the subcomponent either has the same category or is abstract).
* If the classifier is abstract then use the category from the subcomponent.
*
* Only if both are abstract the component instance should be abstract.
* If both are not abstract then they must have the same category. If the categories are different, validation should already have reported an
* error, and we don't instantiate models with errors. It can't hurt if the instantiator checks again, though.
*/
final ComponentCategory classifierCategory = cc.getCategory();
final ComponentCategory subcomponentCategory = sub.getCategory();
if (classifierCategory != ComponentCategory.ABSTRACT) {
newInstance.setCategory(cc.getCategory());
if (subcomponentCategory != ComponentCategory.ABSTRACT && subcomponentCategory != classifierCategory) {
errManager.warning(newInstance, "Subcomponent's category and its classifier's category do not match");
}
} else {
newInstance.setCategory(subcomponentCategory);
}
}
for (Mode mode : mm.getAllInModes()) {
if (monitor.isCanceled()) {
throw new InterruptedException();
}
ModeInstance mi = parent.findModeInstance(mode);
if (mi != null) {
newInstance.getInModes().add(mi);
}
}
populateComponentInstance(newInstance, index);
}
Aggregations