use of org.osate.aadl2.instance.ConnectionInstanceEnd in project osate2 by osate.
the class CreateConnectionsSwitch method balanceFeatureGroupEnds.
/**
* Handle the case where one of the ends (or both) is a feature group.
* Create multiple connection instances.
*
* @param parentci
* @param connInfo
* @param srcEnd
* @param dstEnd
*/
private void balanceFeatureGroupEnds(final ComponentInstance parentci, final ConnectionInfo connInfo, ConnectionInstanceEnd srcEnd, ConnectionInstanceEnd dstEnd) {
if (!upFeature.isEmpty()) {
// we need to match from latest to the oldest in stack going down into the FG nesting hierarchy
for (int count = upFeature.size() - 1; count >= 0; count--) {
FeatureInstance upFi = upFeature.get(count);
EList<FeatureInstance> flist = ((FeatureInstance) dstEnd).getFeatureInstances();
if (connInfo.dstToMatch != null) {
String name = connInfo.dstToMatch.getConnectionEnd().getName();
dstEnd = (FeatureInstance) AadlUtil.findNamedElementInList(flist, name);
connInfo.dstToMatch = connInfo.dstToMatch.getNext();
} else {
FeatureGroup upfg = (FeatureGroup) ((FeatureInstance) upFi.getOwner()).getFeature();
FeatureGroup downfg = (FeatureGroup) ((FeatureInstance) dstEnd).getFeature();
FeatureGroupType upfgt = upfg.getAllFeatureGroupType();
FeatureGroupType downfgt = downfg.getAllFeatureGroupType();
if (upfgt != null && downfgt != null && upfg.isInverseOf(downfg) && !upfgt.getAllFeatures().isEmpty() && !downfgt.getAllFeatures().isEmpty()) {
dstEnd = flist.get(Aadl2InstanceUtil.getFeatureIndex(upFi));
} else {
String name = upFi.getName();
srcEnd = (FeatureInstance) AadlUtil.findNamedElementInList(flist, name);
}
}
}
} else if (!downFeature.isEmpty()) {
// This is a down stack, i.e., the highest element got pushed first and is the oldest.
for (int count = 0; count < downFeature.size(); count++) {
FeatureInstance downFi = downFeature.get(count);
EList<FeatureInstance> flist = ((FeatureInstance) srcEnd).getFeatureInstances();
if (connInfo.srcToMatch != null) {
String name = connInfo.srcToMatch.getConnectionEnd().getName();
srcEnd = (FeatureInstance) AadlUtil.findNamedElementInList(flist, name);
connInfo.srcToMatch = connInfo.srcToMatch.getNext();
} else {
FeatureGroup downfg = ((FeatureGroup) ((FeatureInstance) downFi.getOwner()).getFeature());
FeatureGroupType downfgt = downfg.getFeatureGroupType();
FeatureGroup upfg = ((FeatureGroup) ((FeatureInstance) srcEnd).getFeature());
FeatureGroupType upfgt = upfg.getFeatureGroupType();
if (upfgt != null && downfgt != null && upfg.isInverseOf(downfg) && !upfgt.getAllFeatures().isEmpty() && !downfgt.getAllFeatures().isEmpty()) {
srcEnd = flist.get(Aadl2InstanceUtil.getFeatureIndex(downFi));
} else {
String name = downFi.getName();
srcEnd = (FeatureInstance) AadlUtil.findNamedElementInList(flist, name);
}
}
}
connInfo.src = srcEnd;
}
if (srcEnd instanceof ComponentInstance && dstEnd instanceof ComponentInstance) {
// TODO-LW: error
} else if (srcEnd instanceof ComponentInstance || dstEnd instanceof ComponentInstance) {
addConnectionInstance(parentci.getSystemInstance(), connInfo, dstEnd);
} else {
expandFeatureGroupConnection(parentci, connInfo, srcEnd, dstEnd, connInfo.srcToMatch, connInfo.dstToMatch);
}
}
use of org.osate.aadl2.instance.ConnectionInstanceEnd 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.instance.ConnectionInstanceEnd in project osate2 by osate.
the class ConnectionInfo method addSegment.
/**
* @param newSeg the connection to be appended
* @param srcFi the feature instance at the source of the new segment
* @param dstFi the feature instance at the destination of the new
* segment
* @param ci the component containing the new segment
* @param opposite if we traverse a bidirectional segment opposite to
* the declaration order
* @return if the new segment is a valid continuation of the connection
* instance
*/
public boolean addSegment(final Connection newSeg, final ConnectionInstanceEnd srcFi, final ConnectionInstanceEnd dstFi, final ComponentInstance ci, boolean opposite, boolean[] keep) {
boolean valid = true;
final Context srcCtx = opposite ? newSeg.getAllDestinationContext() : newSeg.getAllSourceContext();
final Context dstCtx = opposite ? newSeg.getAllSourceContext() : newSeg.getAllDestinationContext();
final ConnectionEnd source = opposite ? newSeg.getAllDestination() : newSeg.getAllSource();
final ConnectionEnd dest = opposite ? newSeg.getAllSource() : newSeg.getAllDestination();
final boolean goingUp = !(dstCtx instanceof Subcomponent) && (source instanceof Subcomponent || srcCtx instanceof Subcomponent);
final boolean goingDown = !(srcCtx instanceof Subcomponent) && (dest instanceof Subcomponent || dstCtx instanceof Subcomponent);
// TODO can we do these checks on the instance information
keep[0] = true;
if (srcFi != null) {
sources.add(srcFi);
if (srcFi instanceof FeatureInstance) {
DirectionType dir = ((FeatureInstance) srcFi).getFlowDirection();
bidirectional &= (dir == DirectionType.IN_OUT);
if (goingUp) {
valid &= dir.outgoing();
} else if (goingDown) {
valid &= dir.incoming();
} else {
valid &= dir.outgoing();
}
}
}
bidirectional &= newSeg.isAllBidirectional();
if (dstFi != null) {
destinations.add(dstFi);
if (dstFi instanceof FeatureInstance) {
DirectionType dir = ((FeatureInstance) dstFi).getFlowDirection();
bidirectional &= (dir == DirectionType.IN_OUT);
if (goingUp) {
valid &= dir.outgoing();
} else if (goingDown) {
valid &= dir.incoming();
} else {
valid &= dir.incoming();
}
}
}
/*
* Issue 582 -- This does not catch all the bad things that can happen. NOT testing for
* subcomponents being connected to requires (goingup) or provides (goingdon).
*/
// XXX: the argument below, "this.src", may not be correct, but I'm not really sure what is the correct thing
final ConnectionInstanceEnd resolvedSrc = resolveFeatureInstance(this.src, srcFi);
// XXX: the argument below, "this.src", may not be correct, but I'm not really sure what is the correct thing
final ConnectionInstanceEnd resolvedDst = resolveFeatureInstance(this.src, dstFi);
if (resolvedSrc instanceof FeatureInstance) {
if (resolvedDst instanceof FeatureInstance) {
final FeatureInstance resolvedSrcFI = (FeatureInstance) resolvedSrc;
final FeatureInstance resolvedDstFI = (FeatureInstance) resolvedDst;
if (resolvedSrcFI.getCategory() == FeatureCategory.DATA_ACCESS && resolvedDstFI.getCategory() == FeatureCategory.DATA_ACCESS) {
if (goingUp || goingDown) {
valid &= resolvedSrcFI.getDirection() == resolvedDstFI.getDirection();
} else {
valid &= resolvedSrcFI.getDirection().getInverseDirection() == resolvedDstFI.getDirection();
}
}
}
} else {
// TODO ComponentInstance -- Should check connections between components and access features here
}
if (valid) {
// handle reaching into feature groups in across connection
if (newSeg.isAcross()) {
// segment goes across
int i = connections.size();
Connection root = newSeg.getRootConnection();
srcToMatch = opposite ? root.getDestination() : root.getSource();
srcToMatch = srcToMatch.getNext();
while (keep[0] && i > 0 && srcToMatch != null) {
i -= 1;
Connection c = connections.get(i);
// skip connections that don't go into a feature group
if (!connectsSameFeatureGroup(c)) {
ConnectionEnd e = opposites.get(i) ? c.getAllSource() : c.getAllDestination();
ConnectionEnd cce = srcToMatch.getConnectionEnd();
srcToMatch = srcToMatch.getNext();
keep[0] = cce == e;
}
}
across = true;
acrossConnection = newSeg;
dstToMatch = opposite ? root.getSource() : root.getDestination();
dstToMatch = dstToMatch.getNext();
container = ci;
} else if (across && dstToMatch != null) {
if (!connectsSameFeatureGroup(newSeg)) {
ConnectionEnd e = opposite ? newSeg.getAllDestination() : newSeg.getAllSource();
ConnectionEnd cce = dstToMatch.getConnectionEnd();
dstToMatch = dstToMatch.getNext();
keep[0] = cce == e;
}
}
}
connections.add(newSeg);
opposites.add(opposite);
contexts.add(ci);
return valid;
}
use of org.osate.aadl2.instance.ConnectionInstanceEnd in project osate2 by osate.
the class ConnectionInfo method createConnectionInstance.
public ConnectionInstance createConnectionInstance(final String name, final ConnectionInstanceEnd dst) {
ConnectionInstance conni = InstanceFactory.eINSTANCE.createConnectionInstance();
conni.setName(name);
Iterator<Connection> connIter = connections.iterator();
Iterator<ComponentInstance> ctxIter = contexts.iterator();
// Iterator<ConnectionInstanceEnd> srcIter = sources.iterator();
Iterator<ConnectionInstanceEnd> dstIter = destinations.iterator();
Iterator<Boolean> oppIter = opposites.iterator();
ConnectionInstanceEnd dosrc = src;
ConnectionInstanceEnd dodst = null;
while (connIter.hasNext() && dstIter.hasNext()) {
ConnectionReference connRef = conni.createConnectionReference();
connRef.setConnection(connIter.next());
connRef.setContext(ctxIter.next());
connRef.setSource(dosrc);
dodst = resolveFeatureInstance(dosrc, dstIter.next());
connRef.setDestination(dodst);
dosrc = dodst;
connRef.setReverse(oppIter.next());
}
conni.setSource(src);
conni.setDestination(dst);
conni.setComplete(across);
kind = getKind(dst);
conni.setKind(kind);
return conni;
}
use of org.osate.aadl2.instance.ConnectionInstanceEnd in project osate2 by osate.
the class InstantiateModel method createNewConnection.
/**
* create a copy of the connection instance with the specified indices for the source and the destination
* @param conni
* @param srcIndices
* @param dstIndices
*/
private void createNewConnection(ConnectionInstance conni, List<Long> srcIndices, List<Long> dstIndices) {
LinkedList<String> names = new LinkedList<String>();
LinkedList<Integer> dims = new LinkedList<Integer>();
LinkedList<Integer> sizes = new LinkedList<Integer>();
ConnectionInstance newConn = EcoreUtil.copy(conni);
conni.getContainingComponentInstance().getConnectionInstances().add(newConn);
ConnectionReference topConnRef = Aadl2InstanceUtil.getTopConnectionReference(newConn);
analyzePath(conni.getContainingComponentInstance(), conni.getSource(), names, dims, sizes);
if (srcIndices.size() != sizes.size() && // filter out one side being an element without index (array of 1) (many to one mapping)
!(sizes.size() == 0 && dstIndices.size() == 1)) {
errManager.error(newConn, "Source indices " + srcIndices + " do not match source dimension " + sizes.size());
}
InstanceObject src = resolveConnectionInstancePath(newConn, topConnRef, names, dims, sizes, srcIndices, true);
names.clear();
dims.clear();
sizes.clear();
analyzePath(conni.getContainingComponentInstance(), conni.getDestination(), names, dims, sizes);
if (dstIndices.size() != sizes.size() && // filter out one side being an element without index (array of 1) (many to one mapping)
!(sizes.size() == 0 && dstIndices.size() == 1)) {
errManager.error(newConn, "For " + newConn.getConnectionReferences().get(0).getFullName() + " : " + newConn.getFullName() + ", destination indices " + dstIndices + " do not match destination dimension " + sizes.size());
}
InstanceObject dst = resolveConnectionInstancePath(newConn, topConnRef, names, dims, sizes, dstIndices, false);
if (src == null) {
errManager.error(newConn, "Connection source not found");
}
if (dst == null) {
errManager.error(newConn, "Connection destination not found");
}
String containerPath = conni.getContainingComponentInstance().getInstanceObjectPath();
int len = containerPath.length() + 1;
String srcPath = (src != null) ? src.getInstanceObjectPath() : "Source end not found";
StringBuffer sb = new StringBuffer();
int i = (srcPath.startsWith(containerPath)) ? len : 0;
sb.append(srcPath.substring(i));
sb.append(" --> ");
String dstPath = (dst != null) ? dst.getInstanceObjectPath() : "Destination end not found";
i = (dstPath.startsWith(containerPath)) ? len : 0;
sb.append(dstPath.substring(i));
ConnectionInstance duplicate = (ConnectionInstance) AadlUtil.findNamedElementInList(conni.getContainingComponentInstance().getConnectionInstances(), sb.toString());
if (duplicate != null && duplicate != conni) {
// conni will be removed later
errManager.warning(newConn, "There is already another connection between the same endpoints");
}
newConn.setSource((ConnectionInstanceEnd) src);
newConn.setDestination((ConnectionInstanceEnd) dst);
newConn.setName(sb.toString());
}
Aggregations