AadlBaVisitors.java
/**
* AADL-BA-FrontEnd
*
* Copyright (c) 2011-2021 TELECOM ParisTech and CNRS
*
* TELECOM ParisTech/LTCI
*
* Authors: see AUTHORS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Eclipse Public License as published by Eclipse,
* either version 2.0 of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Eclipse Public License for more details.
* You should have received a copy of the Eclipse Public License
* along with this program. If not, see
* https://www.eclipse.org/legal/epl-2.0/
*/
package org.osate.ba.utils;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.osate.aadl2.AadlPackage;
import org.osate.aadl2.ComponentClassifier;
import org.osate.aadl2.PackageSection;
import org.osate.aadl2.Port;
import org.osate.aadl2.PrivatePackageSection;
import org.osate.ba.aadlba.AadlBaFactory;
import org.osate.ba.aadlba.BasicAction;
import org.osate.ba.aadlba.BehaviorAction;
import org.osate.ba.aadlba.BehaviorActionCollection;
import org.osate.ba.aadlba.BehaviorActions;
import org.osate.ba.aadlba.BehaviorAnnex;
import org.osate.ba.aadlba.BehaviorState;
import org.osate.ba.aadlba.BehaviorTransition;
import org.osate.ba.aadlba.BehaviorVariable;
import org.osate.ba.aadlba.DispatchConjunction;
import org.osate.ba.aadlba.DispatchTrigger;
import org.osate.ba.aadlba.DispatchTriggerLogicalExpression;
import org.osate.ba.aadlba.ElseStatement;
import org.osate.ba.aadlba.IfStatement;
import org.osate.ba.aadlba.LoopStatement;
import org.osate.utils.internal.Aadl2Visitors;
/**
* A collection of behavior annex visitors.
*/
public class AadlBaVisitors {
// Some names.
public static final String INITIALIZE_ENTRYPOINT_PROPERTYSET = "Programming_Properties";
public static final String INITIALIZE_ENTRYPOINT_PROPERTY_NAME = "Initialize_Entrypoint";
public static final String DISPATCH_PROTOCOL_PROPERTY_NAME = "Dispatch_Protocol";
public static final String SEI_AADL2_PACKAGE_NAME = "org.osate.aadl2";
public static final String SEI_AADL2_CLASSIFIER_SUFFIX = "Classifier";
public static final long DEFAULT_TRANSITION_PRIORITY;
static {
DEFAULT_TRANSITION_PRIORITY = AadlBaFactory.eINSTANCE.createBehaviorTransition().getPriority();
}
/**
* Returns a list of basic action contained in the given behavior
* action (recursively).
*
* @param BehAction the given behavior action
* @return a list of basic action contained in the given behavior
* action
*/
public static EList<BasicAction> getBasicActions(BehaviorAction BehAction) {
EList<BasicAction> result = null;
if (BehAction instanceof BasicAction) {
result = new BasicEList<BasicAction>();
result.add((BasicAction) BehAction);
} else {
// Case of an loop statements (excepted if statement).
if (BehAction instanceof LoopStatement) {
result = getBasicActions(((LoopStatement) BehAction).getBehaviorActions());
} else if (BehAction instanceof IfStatement) {
IfStatement stat = (IfStatement) BehAction;
result = getBasicActions(stat.getBehaviorActions());
if (stat.getElseStatement() != null) {
result.addAll(getBasicActions(stat.getElseStatement().getBehaviorActions()));
}
} else // ElseStatement case.
{
ElseStatement elseStat = (ElseStatement) BehAction;
result = getBasicActions(elseStat.getBehaviorActions());
}
}
return result;
}
/**
* Return a list of the BasicAction objects contained in a given BehaviorActions
* object (recursively). If the given BehaviorActions object is {@code null},
* the returned list is empty.
*
* @param BehActions the given BehaviorActions object or {@code null} (for
* batch processing purpose)
* @return the list of BasicAction contained in the given BehaviorActions
* object. May be empty.
*/
public static EList<BasicAction> getBasicActions(BehaviorActions BehActions) {
EList<BasicAction> result = new BasicEList<BasicAction>();
// A behavior transition may have no behavior actions.
if (BehActions != null) {
// Case of single behavior action.
if (BehActions instanceof BehaviorAction) {
result.addAll(getBasicActions((BehaviorAction) BehActions));
} else // Case of BehaviorActionCollection.
{
for (BehaviorAction BehAct : ((BehaviorActionCollection) BehActions).getActions()) {
result.addAll(getBasicActions(BehAct));
}
}
}
return result;
}
/**
* Return the package sections related to a given BehaviorAnnex. As
* "Classifier declarations in public sections are accessible to other
* packages, while classifiers in private sections can only be referenced
* within the private section of the same package".<br><br>
* table[0] always refers to public section.
* If the given BehaviorAnnex is declared in a private section, table's
* length equals to 2 and table[1] refers to the private section.
*
* @param ba The given BehaviorAnnex
* @return the package sections related to the given BehaviorAnnex.
*/
public static PackageSection[] getBaPackageSections(BehaviorAnnex ba) {
PackageSection result[];
PackageSection container = Aadl2Visitors.getContainingPackageSection(ba);
// Init contexts tab with current package's sections.
// Private section is also investigated only if ba is declared in
// package's private section.
if (container instanceof PrivatePackageSection) {
result = new PackageSection[2];
result[1] = container;
result[0] = ((AadlPackage) container.eContainer()).getPublicSection();
} else {
result = new PackageSection[1];
result[0] = container;
}
return result;
}
/**
* Find the first occurrence of an BehaviorVariable within a given
* BehaviorAnnex which name equals to the given name. Return {@code null}
* if no BehaviorVariable is found.
*
* @param ba the given BehaviorAnnex
* @param variableName the given name
* @return the first occurrence of an BehaviorVariable related to the given
* name or {@code null}.
*/
public static BehaviorVariable findBehaviorVariable(BehaviorAnnex ba, String variableName) {
for (BehaviorVariable v : ba.getVariables()) {
if (v.getName().equalsIgnoreCase(variableName)) {
return v;
}
}
return null;
}
/**
* Find the first occurrence of an BehaviorState within a given BehaviorAnnex
* which name equals to a given name. Return {@code null} if no
* BehaviorState is found.
*
* @param ba the given BehaviorAnnex
* @param stateName the given name
* @return the first occurrence of an BehaviorState related to the given name
* or {@code null}
*/
public static BehaviorState findBehaviorState(BehaviorAnnex ba, String stateName) {
for (BehaviorState s : ba.getStates()) {
if (stateName.equalsIgnoreCase(s.getName())) {
return s;
}
}
return null;
}
/**
* Return a list of DispatchTrigger objects contained in the given
* DispatchTriggerLogicelExpression object. The list may be empty but not
* {@code null}.
*
* @param dtle the given DispatchTriggerLogicelExpression object
* @return a list of DispatchTrigger objects, eventually empty.
*/
public static EList<DispatchTrigger> getDispatchTriggers(DispatchTriggerLogicalExpression dtle) {
EList<DispatchTrigger> result = new BasicEList<DispatchTrigger>();
for (DispatchConjunction dc : dtle.getDispatchConjunctions()) {
result.addAll(dc.getDispatchTriggers());
}
return result;
}
/**
* Returns the behavior annex's parent component.
*
* @param ba the behavior annex
* @return the behavior annex's parent component
*/
public static ComponentClassifier getParentComponent(BehaviorAnnex ba) {
return (ComponentClassifier) ba.getContainingClassifier();
}
protected static final Map<BehaviorAnnex, Set<Port>> _IS_FRESH = new WeakHashMap<BehaviorAnnex, Set<Port>>();
/**
* Return {@code true} if the given port which is contained in the given
* BehaviorAnnex object is used as a fresh port value. Otherwise return
* {@code false}.
*
* @param ba the given BehaviorAnnex object which contains the given port
* @param port the given port
* @return {@code true} if the given is used as a fresh port value.
* Otherwise {@code false}
*/
public static boolean isFresh(BehaviorAnnex ba, Port port) {
Set<Port> ports = _IS_FRESH.get(ba);
if (ports != null) {
return ports.contains(port);
} else {
return false;
}
}
/**
* Tag the given port as a port used as a fresh port value.
*
* @param ba the BehaviorAnnex object which contains the given port
* @param port the given port
*/
public static void putFreshPort(BehaviorAnnex ba, Port port) {
Set<Port> ports = _IS_FRESH.get(ba);
if (ports == null) {
ports = new HashSet<Port>();
_IS_FRESH.put(ba, ports);
}
ports.add(port);
}
/**
* Return a list of behavior transitions where the given behavior state is
* the source state. May return empty list.<br><br>
*
* The list of behavior transitions is sorted according to:<br><br>
* _ the behavior priority (highest to the lowest).<br>
* _ the behavior transitions which have "otherwise" execution condition are
* set at the end of the list.<br>
* _ in case of equality, the order of behavior transition appearance in the
* aadl code is applied.<br><br>
*
* @param state the given behavior state
* @return the list of behavior transitions where the given behavior state is
* the source state or an empty list
*/
public static List<BehaviorTransition> getTransitionWhereSrc(BehaviorState state) {
List<BehaviorTransition> result = new BasicEList<BehaviorTransition>(state.getOutgoingTransitions());
sort(result);
return result;
}
/**
* Specify that the given behavior state is the source state of the given
* behavior transition.
*
* @param state the given behavior state
* @param bt the given behavior transition where the the given behavior state
* is source
*/
@Deprecated
public static void putTransitionWhereSrc(BehaviorState state, BehaviorTransition bt) {
List<BehaviorTransition> list = state.getOutgoingTransitions();
if (list == null) {
return;
}
if (false == list.contains(bt)) {
addAndSort(list, bt);
}
}
// Add the given behavior transition to the given list and sort the list.
protected static void addAndSort(List<BehaviorTransition> btl, BehaviorTransition bt) {
// TODO to be optimized.
btl.add(bt);
sort(btl);
}
// Sort (insertion) behavior transitions list
// according to their priority (highest to the lowest).
// In case of equality, the order of transition appearance in the aadl
// code is applied.
// Behavior transition which have execution condition set to "otherwise"
// will be set at the end of the list.
/**
* @since 4.0
*/
protected static void sort(List<BehaviorTransition> btl) {
BehaviorTransition tmp = null;
int i;
int j;
for (i = btl.size() - 2; i >= 0; i--) {
tmp = btl.get(i);
j = i;
while (j < btl.size() - 1 && AadlBaUtils.compareBehaviorTransitionPriority(btl.get(j + 1), tmp)) {
btl.set(j, btl.get(j + 1));
j++;
}
btl.set(j, tmp);
}
}
}