FlowLatencyUtil.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.analysis.flows.internal.utils;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.ui.statushandlers.StatusManager;
import org.osate.aadl2.ComponentCategory;
import org.osate.aadl2.ComponentClassifier;
import org.osate.aadl2.ComponentType;
import org.osate.aadl2.VirtualBus;
import org.osate.aadl2.contrib.aadlproject.TimeUnits;
import org.osate.aadl2.contrib.communication.CommunicationProperties;
import org.osate.aadl2.contrib.communication.Timing;
import org.osate.aadl2.contrib.deployment.DeploymentProperties;
import org.osate.aadl2.contrib.timing.TimingProperties;
import org.osate.aadl2.instance.ComponentInstance;
import org.osate.aadl2.instance.ConnectionInstance;
import org.osate.aadl2.instance.ConnectionInstanceEnd;
import org.osate.aadl2.instance.ConnectionKind;
import org.osate.aadl2.instance.EndToEndFlowInstance;
import org.osate.aadl2.instance.FeatureCategory;
import org.osate.aadl2.instance.FeatureInstance;
import org.osate.aadl2.instance.FlowElementInstance;
import org.osate.aadl2.instance.FlowSpecificationInstance;
import org.osate.aadl2.instance.InstanceObject;
import org.osate.aadl2.properties.PropertyLookupException;
import org.osate.contribution.sei.arinc653.Arinc653;
import org.osate.contribution.sei.arinc653.ScheduleWindow;
import org.osate.pluginsupport.properties.PropertyUtils;
import org.osate.result.AnalysisResult;
import org.osate.result.Result;
import org.osate.result.util.ResultUtil;
import org.osate.xtext.aadl2.properties.util.InstanceModelUtil;
public class FlowLatencyUtil {
public static FeatureInstance getIncomingConnectionFeatureInstance(final EndToEndFlowInstance etef,
final FlowElementInstance flowElementInstance) {
ConnectionInstance previousElement = getPreviousConnection(etef, flowElementInstance);
if ((previousElement != null)) {
ConnectionInstanceEnd dst = previousElement.getDestination();
if (dst instanceof FeatureInstance) {
return (FeatureInstance) dst;
}
}
return null;
}
public static boolean isPreviousConnectionImmediate(final EndToEndFlowInstance etef,
final FlowElementInstance flowElementInstance) {
final ConnectionInstance previousElement = getPreviousConnection(etef, flowElementInstance);
//XXX: [Code Coverage] Only called if there is a previous connection.
if (previousElement != null && previousElement.getKind() == ConnectionKind.PORT_CONNECTION) {
return PropertyUtils.propertyEquals(CommunicationProperties::getTiming, previousElement,
Timing.IMMEDIATE);
}
// No previous element, or it's not a port connection (so no TIMING property); either way, it's not immediate
return false;
}
public static boolean isNextConnectionImmediate(final EndToEndFlowInstance etef,
final FlowElementInstance flowElementInstance) {
final ConnectionInstance nextElement = getNextConnection(etef, flowElementInstance);
if (nextElement != null && nextElement.getKind() == ConnectionKind.PORT_CONNECTION) {
return PropertyUtils.propertyEquals(CommunicationProperties::getTiming, nextElement, Timing.IMMEDIATE);
}
// No next element, or it's not a port connection (so no TIMING property); either way, it's not immediate
return false;
}
public static boolean isPreviousConnectionDelayed(final EndToEndFlowInstance etef,
final FlowElementInstance flowElementInstance) {
final ConnectionInstance previousElement = getPreviousConnection(etef, flowElementInstance);
//XXX: [Code Coverage] Only called if there is a previous connection.
if (previousElement != null && previousElement.getKind() == ConnectionKind.PORT_CONNECTION) {
return PropertyUtils.propertyEquals(CommunicationProperties::getTiming, previousElement, Timing.DELAYED);
}
// No previous element, or it's not a port connection (so no TIMING property); either way, it's not delayed
return false;
}
/**
* get the next element in an end to end flow
* @param etef - the end to end flow that contains all the elements
* @param flowElementInstance - the element where we start the search
* @return - a FlowElementInstance that is after flowElementInstance in etef. null if there is nothing after
*/
public static FlowElementInstance getNextFlowElement(final EndToEndFlowInstance etef,
final FlowElementInstance flowElementInstance) {
int n = etef.getFlowElements().indexOf(flowElementInstance);
int size = etef.getFlowElements().size();
if (n + 1 < size) {
return etef.getFlowElements().get(n + 1);
}
return null;
}
/**
* get the previous element in an end to end flow
* @param etef - the end to end flow that contains all the elements
* @param flowElementInstance - the element where we start the search
* @return - a FlowElementInstance that is before flowElementInstance in etef. null if there is nothing before
*/
public static FlowElementInstance getPreviousFlowElement(final EndToEndFlowInstance etef,
final FlowElementInstance flowElementInstance) {
int n = etef.getFlowElements().indexOf(flowElementInstance);
if (n > 0) {
return etef.getFlowElements().get(n - 1);
}
return null;
}
/**
* get previous component instance in flow
* @param etef
* @param flowElementInstance
* @return
*/
public static ComponentInstance getPreviousComponent(final EndToEndFlowInstance etef,
final FlowElementInstance flowElementInstance) {
FlowElementInstance prevConn = getPreviousFlowElement(etef, flowElementInstance);
if (prevConn != null) {
FlowElementInstance prevEl = getPreviousFlowElement(etef, prevConn);
if (prevEl != null) {
if (prevEl instanceof FlowSpecificationInstance) {
return prevEl.getContainingComponentInstance();
}
if (prevEl instanceof ComponentInstance) {
return (ComponentInstance) prevEl;
}
}
}
return null;
}
/**
* find the next connection within an end to end flow
* @param etef - the end to end flow where to search
* @param flowElementInstance - the element from where we start the search
* @return a connectioninstance object that is the next connection in the flow. null otherwise.
*/
public static ConnectionInstance getNextConnection(final EndToEndFlowInstance etef,
final FlowElementInstance flowElementInstance) {
FlowElementInstance fei = getNextFlowElement(etef, flowElementInstance);
if (fei instanceof ConnectionInstance) {
return (ConnectionInstance) fei;
}
return null;
}
/**
* find the previous connection within an end to end flow
* @param etef - the end to end flow where to search
* @param flowElementInstance - the element from where we start the search
* @return a connection instance object that is the previous connection in the flow. null otherwise.
*/
public static ConnectionInstance getPreviousConnection(final EndToEndFlowInstance etef,
final FlowElementInstance flowElementInstance) {
FlowElementInstance fei = getPreviousFlowElement(etef, flowElementInstance);
if (fei instanceof ConnectionInstance) {
return (ConnectionInstance) fei;
}
return null;
}
/**
* Return first virtual processor. Usually processes are only assigned to one VP.
* @param componentInstance system, process, thread or other entity bound to a processor and running inside a partition.
* @return partition
*/
public static ComponentInstance getPartition(ComponentInstance componentInstance) {
Collection<ComponentInstance> vprocessors = InstanceModelUtil.getBoundVirtualProcessors(componentInstance);
if (!vprocessors.isEmpty()) {
return vprocessors.iterator().next();
} else {
return null;
}
}
/**
* get the partition period, either from the virtual processor representing the partition, or from the major frame of the ARINC653 specification of a processor
* @return partition period as latency contributor
*/
public static double getPartitionPeriod(final ComponentInstance part) {
// first look for major frame value on processor
final ComponentInstance module = getModule(part);
final ComponentCategory moduleCategory = module != null ? module.getCategory() : null;
double result = 0.0;
if (moduleCategory == ComponentCategory.PROCESSOR || moduleCategory == ComponentCategory.VIRTUAL_PROCESSOR
|| moduleCategory == ComponentCategory.ABSTRACT) {
result = PropertyUtils.getScaled(Arinc653::getModuleMajorFrame, module, TimeUnits.MS).orElse(0.0);
}
if (result == 0.0) {
// look for period on partition
result = PropertyUtils.getScaled(TimingProperties::getPeriod, part, TimeUnits.MS).orElse(0.0);
if (result == 0.0) {
// look for major frame value on virtual processor (partition)
result = PropertyUtils.getScaled(Arinc653::getModuleMajorFrame, part, TimeUnits.MS).orElse(0.0);
}
}
return result;
}
public static ComponentClassifier getConnectionData(ConnectionInstance connectionInstance) {
ConnectionInstanceEnd cei;
FeatureInstance fi;
cei = connectionInstance.getSource();
if (cei instanceof FeatureInstance) {
fi = (FeatureInstance) cei;
if (fi.getCategory() == FeatureCategory.FEATURE_GROUP) {
return null;
}
return (ComponentClassifier) fi.getFeature().getAllClassifier();
}
return null;
}
public static ComponentInstance getModule(ComponentInstance partition) {
ComponentInstance module;
/**
* The partition must be a virtual processor component.
*/
//XXX: [Code Coverage] partition is always a virtual processor.
if (partition.getCategory() != ComponentCategory.VIRTUAL_PROCESSOR) {
return null;
}
/**
* Try to get the module from the virtual processor partition.
*/
module = (ComponentInstance) DeploymentProperties.getActualProcessorBinding(partition)
.map(list -> list.isEmpty() ? null : list.get(0)).orElse(null);
if (module == null) {
module = partition.getContainingComponentInstance();
}
//XXX: [Code Coverage] module cannot be null.
if ((module != null) && (module.getCategory() != ComponentCategory.VIRTUAL_PROCESSOR)) {
return module;
}
return null;
}
/**
* return the offset of the partition start time relative to the major frame
* utilizes the window schedule of the module for the partition
* @param partition This can be a virtual processor representing a partition or a component instance tagged with SEI properties
* @return offset, no virtual processor as ARINC653 partition, or no processor.
*/
public static double getPartitionFrameOffset(final ComponentInstance partition,
final List<ScheduleWindow> schedule) {
//XXX: [Code Coverage] schedule is never null.
if ((schedule == null) || (schedule.size() == 0)) {
return 0.0;
} else {
double res = 0.0;
for (final ScheduleWindow window : schedule) {
if (PropertyUtils.equals(window.getPartition(), partition, false)) {
return res;
}
res = res + PropertyUtils.scale(window.getDuration(), TimeUnits.MS).orElse(0.0);
}
// XXX: [Code Coverage] partition is always in schedule.
return 0.0;
}
}
public static boolean isInSchedule(ComponentInstance partition, List<ScheduleWindow> schedule) {
if (schedule == null) {
return true;
}
for (ScheduleWindow window : schedule) {
if (PropertyUtils.equals(window.getPartition(), partition, false)) {
return true;
}
}
return false;
}
/**
* return the duration of the partition i.e., its window size.
* utilizes the window schedule of the module for the partition
* If no schedule: interpret WC execution time on partition as duration
* @param partition This is a virtual processor representing a partition
* @param schedule ARINC653 schedule
* @return window size (duration), or 0 if no schedule.
*/
public static double getPartitionDuration(ComponentInstance partition, List<ScheduleWindow> schedule) {
if ((schedule == null) || (schedule.size() == 0)) {
double wcet = PropertyUtils.getScaled(TimingProperties::getExecutionTime, partition, TimeUnits.MS)
.orElse(0.0);
return wcet;
}
for (ScheduleWindow window : schedule) {
if (window.getPartition().orElse(null) == partition) {
return PropertyUtils.scale(window.getDuration(), TimeUnits.MS).orElse(0.0);
}
}
return 0;
}
public static List<ScheduleWindow> getModuleSchedule(final ComponentInstance partition) {
if (partition == null) {
return null;
} else {
final ComponentInstance module = getModule(partition);
if (module == null) {
return null;
} else {
final ComponentCategory moduleCategory = module.getCategory();
if (moduleCategory == ComponentCategory.PROCESSOR
|| moduleCategory == ComponentCategory.VIRTUAL_PROCESSOR
|| moduleCategory == ComponentCategory.ABSTRACT) {
/* Only keep those windows that have a partition specified */
final List<ScheduleWindow> windows = Arinc653.getModuleSchedule(module).orElse(Collections.emptyList());
windows.removeIf(sw -> !sw.getPartition().isPresent());
return windows;
} else {
return Collections.emptyList();
}
}
}
}
/**
* round up to the next sampling frame.
* If processing latency is zero then go to the next frame.
* If processing latency is already a multiple of a frame then use that boundary.
* Otherwise use the next multiple of the samplingLatency
* Parameters are assumed to have the same unit
* @param processingLatency double Can be larger than the sampling latency
* @param samplingLatency double Assumed to be non-zero
* @return double
*/
public static double roundUp(double processingLatency, double samplingLatency) {
int frames = (int) (processingLatency / samplingLatency);
if ((processingLatency % samplingLatency) > 0) {
frames = frames + 1;
} else if (processingLatency == 0) {
frames = 1;
}
return (frames * samplingLatency);
}
/**
* Determine the amount needed to round up to the next frame
* It is the difference been the result of roundUp and processing latency
* @param processingLatency double
* @param samplingLatency double
* @return double
*/
public static double roundUpDiff(double processingLatency, double samplingLatency) {
double diff = processingLatency % samplingLatency;
if ((diff) > 0) {
return samplingLatency - diff;
} else if (processingLatency == 0) {
return samplingLatency;
} else {
return 0;
}
}
/**
* Determine the amount needed to round up to the target latency.
* If processing latency is larger than window then it flows into the next frame
* It is the difference been the result of roundUp and processing latency
* @param processingLatency double
* @param samplingLatency double
* @param targetLatency double
* @return double
*/
public static double roundUpDiff(double processingLatency, double samplingLatency, double targetLatency) {
if (targetLatency == 0 || targetLatency == -1) {
return 0;
}
double diff = targetLatency - (processingLatency % targetLatency);
// deal with overflow into next frame.
int extraslots = targetLatency == 0 ? 0 : (int) (processingLatency / targetLatency);
return diff + (extraslots * samplingLatency);
}
public static String getMinMaxLabel(boolean doMax) {
if (doMax) {
return "Max: ";
} else {
return "Min: ";
}
}
// -------------
// Results
// -------------
@Deprecated
public static AnalysisResult recordAsAnalysisResult(Collection<Result> results, EObject root,
boolean asynchronousSystem, boolean majorFrameDelay, boolean worstCaseDeadline,
boolean bestCaseEmptyQueue) {
return recordAsAnalysisResult(results, root, asynchronousSystem, majorFrameDelay, worstCaseDeadline,
bestCaseEmptyQueue, false);
}
/**
* @since org.osate.analysis.flows 3.0
*/
public static AnalysisResult recordAsAnalysisResult(Collection<Result> results, EObject root,
boolean asynchronousSystem,
boolean majorFrameDelay, boolean worstCaseDeadline, boolean bestCaseEmptyQueue,
boolean disableQueuingLatency) {
AnalysisResult latencyResults = createLatencyAnalysisResult(root, asynchronousSystem, majorFrameDelay,
worstCaseDeadline, bestCaseEmptyQueue, disableQueuingLatency);
if (!results.isEmpty()) {
latencyResults.getResults().addAll(results);
} else {
Result err = ResultUtil.createErrorResult("No latency analysis result", root);
latencyResults.getResults().add(err);
}
return latencyResults;
}
@Deprecated
public static AnalysisResult createLatencyAnalysisResult(EObject root, boolean asynchronousSystem,
boolean majorFrameDelay,
boolean worstCaseDeadline, boolean bestCaseEmptyQueue) {
return createLatencyAnalysisResult(root, asynchronousSystem, majorFrameDelay, worstCaseDeadline,
bestCaseEmptyQueue, false);
}
/**
* @since org.osate.analysis.flows 3.0
*/
public static AnalysisResult createLatencyAnalysisResult(EObject root, boolean asynchronousSystem,
boolean majorFrameDelay, boolean worstCaseDeadline, boolean bestCaseEmptyQueue,
boolean disableQueuingLatency) {
AnalysisResult latencyResults = ResultUtil.createAnalysisResult(FlowLatencyUtil.LatencyAnalysisName, root);
ResultUtil.addParameter(latencyResults, asynchronousSystem);
ResultUtil.addParameter(latencyResults, majorFrameDelay);
ResultUtil.addParameter(latencyResults, worstCaseDeadline);
ResultUtil.addParameter(latencyResults, bestCaseEmptyQueue);
ResultUtil.addParameter(latencyResults, disableQueuingLatency);
latencyResults.setMessage(FlowLatencyUtil.getParametersAsLabels(asynchronousSystem, majorFrameDelay,
worstCaseDeadline, bestCaseEmptyQueue, disableQueuingLatency));
latencyResults.setModelElement(root);
return latencyResults;
}
public static final String LatencyAnalysisName = "latency";
public static URI getLantencyAnalysisResultURI(AnalysisResult results) {
EObject root = results.getModelElement();
URI rootURI = EcoreUtil.getURI(root).trimFragment().trimFileExtension();
String rootname = rootURI.lastSegment();
String postfix = getParametersAsLabels(results);
return rootURI.trimFragment().trimFileExtension().trimSegments(1).appendSegment("reports")
.appendSegment(LatencyAnalysisName).appendSegment(rootname + "__latency_" + postfix)
.appendFileExtension("result");
}
public static void saveAnalysisResult(AnalysisResult results) {
URI latencyURI = getLantencyAnalysisResultURI(results);
Resource res = results.getModelElement().eResource().getResourceSet().createResource(latencyURI);
res.getContents().add(results);
try {
res.save(null);
} catch (IOException e) {
StatusManager.getManager().handle(new Status(IStatus.ERROR, "org.osate.analysis.flows", e.getMessage(), e));
}
}
public static String getParametersAsLabels(AnalysisResult results) {
String labels = results.getMessage();
if (results.getParameters().size() == 4) {
labels = FlowLatencyUtil.getParametersAsLabels((boolean) results.getParameters().get(0).getValue(),
(boolean) results.getParameters().get(1).getValue(),
(boolean) results.getParameters().get(2).getValue(),
(boolean) results.getParameters().get(3).getValue(),
(boolean) results.getParameters().get(4).getValue());
}
return labels;
}
@Deprecated
public static String getParametersAsLabels(boolean asynchronousSystem, boolean majorFrameDelay,
boolean worstCaseDeadline, boolean bestCaseEmptyQueue) {
return getParametersAsLabels(asynchronousSystem, majorFrameDelay, worstCaseDeadline, bestCaseEmptyQueue, false);
}
/**
* @since org.osate.analysis.flows 3.0
*/
public static String getParametersAsLabels(boolean asynchronousSystem, boolean majorFrameDelay,
boolean worstCaseDeadline, boolean bestCaseEmptyQueue, boolean disableQueuingLatency) {
return getAsynchronousSystemLabel(asynchronousSystem) + "-" + getMajorFrameDelayLabel(majorFrameDelay) + "-"
+ getWorstCaseDeadlineLabel(worstCaseDeadline) + "-" + getBestcaseEmptyQueueLabel(bestCaseEmptyQueue)
+ "-" + getDisableQueuingLatencyLabel(disableQueuingLatency);
}
public static String getAsynchronousSystemLabel(boolean isAsynchronous) {
return isAsynchronous ? "AS" : "SS";
}
public static String getMajorFrameDelayLabel(boolean isMajorFrameDelay) {
return isMajorFrameDelay ? "MF" : "PE";
}
public static String getWorstCaseDeadlineLabel(boolean isWorstCaseDeadline) {
return isWorstCaseDeadline ? "DL" : "ET";
}
public static String getBestcaseEmptyQueueLabel(boolean isBestcaseEmptyQueue) {
return isBestcaseEmptyQueue ? "EQ" : "FQ";
}
/**
* @since org.osate.analysis.flows 3.0
*/
public static String getDisableQueuingLatencyLabel(boolean disableQueuingLatency) {
return disableQueuingLatency ? "DQL" : "EQL";
}
public static String getAsynchronousSystemDescription(boolean isAsynchronous) {
return isAsynchronous ? "asynchronous system" : "synchronous system";
}
public static String getMajorFrameDelayDescription(boolean isMajorFrameDelay) {
return isMajorFrameDelay ? "major partition frame" : "partition end";
}
public static String getWorstCaseDeadlineDescription(boolean worstCaseDeadline) {
return worstCaseDeadline ? "worst case as deadline" : "worst case as max compute execution time";
}
public static String getBestcaseEmptyQueueDescription(boolean bestCaseEmptyQueue) {
return bestCaseEmptyQueue ? "best case as empty queue"
: "best case as full queue min compute execution time";
}
/**
* @since org.osate.analysis.flows 3.0
*/
public static String getDisableQueuingLatencyDescription(boolean disableQueuingLatency) {
return disableQueuingLatency ? "queuing latency disabled" : "queuing latency enabled";
}
public static String getParametersAsDescriptions(AnalysisResult results) {
String labels = results.getMessage();
if (results.getParameters().size() == 5) {
labels = FlowLatencyUtil.getParametersAsDescriptions((boolean) results.getParameters().get(0).getValue(),
(boolean) results.getParameters().get(1).getValue(),
(boolean) results.getParameters().get(2).getValue(),
(boolean) results.getParameters().get(3).getValue(),
(boolean) results.getParameters().get(4).getValue());
}
return labels;
}
@Deprecated
public static String getParametersAsDescriptions(boolean asynchronousSystem, boolean majorFrameDelay,
boolean worstCaseDeadline, boolean bestCaseEmptyQueue) {
return getParametersAsDescriptions(asynchronousSystem, majorFrameDelay, worstCaseDeadline, bestCaseEmptyQueue,
false);
}
/**
* @since org.osate.analysis.flows 3.0
*/
public static String getParametersAsDescriptions(boolean asynchronousSystem, boolean majorFrameDelay,
boolean worstCaseDeadline, boolean bestCaseEmptyQueue, boolean disableQueuingLatency) {
return getAsynchronousSystemDescription(asynchronousSystem) + "/"
+ getMajorFrameDelayDescription(majorFrameDelay) + "/"
+ getWorstCaseDeadlineDescription(worstCaseDeadline) + "/"
+ getBestcaseEmptyQueueDescription(bestCaseEmptyQueue) + "/"
+ getDisableQueuingLatencyDescription(disableQueuingLatency);
}
public static String getContributorType(EObject relatedElement) {
if (relatedElement instanceof ComponentInstance) {
ComponentInstance relatedComponentInstance = (ComponentInstance) relatedElement;
if (relatedComponentInstance.getCategory() == ComponentCategory.VIRTUAL_BUS) {
return "protocol";
}
if (relatedComponentInstance.getCategory() == ComponentCategory.VIRTUAL_PROCESSOR) {
return "partition";
}
return relatedComponentInstance.getCategory().getName();
}
if (relatedElement instanceof VirtualBus) {
return "protocol";
}
if (relatedElement instanceof ComponentClassifier) {
ComponentType relatedComponentType = (ComponentType) relatedElement;
return relatedComponentType.getCategory().getName();
}
if (relatedElement instanceof ConnectionInstance) {
final ConnectionKind connectionKind = ((ConnectionInstance) relatedElement)
.getKind();
Timing connectionType;
try {
connectionType = connectionKind == ConnectionKind.PORT_CONNECTION
? CommunicationProperties.getTiming((ConnectionInstance) relatedElement).orElse(Timing.SAMPLED)
: Timing.SAMPLED;
} catch (final PropertyLookupException e) {
// Property association semantics for FEATURE connections are missing
connectionType = Timing.SAMPLED;
}
if (connectionType == Timing.DELAYED) {
return "delayed connection";
}
if (connectionType == Timing.IMMEDIATE) {
return "immediate connection";
}
if (connectionType == Timing.SAMPLED) {
return "connection";
}
return "connection";
}
return "component";
}
// public static ConnectionType getConnectionType(final ConnectionInstance conn) {
// EnumerationLiteral el = GetProperties.getConnectionTiming(conn);
//
// //XXX: [Code Coverage] el cannot be null.
// if ((el != null) && (el.getName().equalsIgnoreCase("immediate"))) {
// return ConnectionType.IMMEDIATE;
// }
// //XXX: [Code Coverage] el cannot be null.
// if ((el != null) && (el.getName().equalsIgnoreCase("delayed"))) {
// return ConnectionType.DELAYED;
// }
// return ConnectionType.SAMPLED;
// }
//
public static String getFullComponentContributorName(EObject relatedElement) {
if (relatedElement instanceof ConnectionInstance) {
return ((ConnectionInstance) relatedElement).getName();
} else if (relatedElement instanceof InstanceObject) {
return ((InstanceObject) relatedElement).getComponentInstancePath();
}
return "";
}
}