AadlProjectCreator.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.importer.simulink.generator;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.ui.statushandlers.StatusManager;
import org.osate.aadl2.util.OsateDebug;
import org.osate.importer.model.Component;
import org.osate.importer.model.Component.ComponentType;
import org.osate.importer.model.Connection;
import org.osate.importer.model.Model;
import org.osate.importer.model.sm.State;
import org.osate.importer.model.sm.StateMachine;
import org.osate.importer.simulink.FileImport;
import org.osate.importer.simulink.StateFlowInstance;
public class AadlProjectCreator {
/**
* Create all directories required to store the model
* and the necessary files.
* @param outputPath the path that will contain all the model
* and related resources.
*/
public static void createDirectories(String outputPath) {
String outputPathFunctional;
String outputPathRuntime;
File ftmp;
outputPathFunctional = outputPath + File.separatorChar + "functional";
outputPathRuntime = outputPath + File.separatorChar + "runtime";
ftmp = new File(outputPathFunctional);
if (ftmp.exists() && ftmp.isFile()) {
OsateDebug.osateDebug("Error, the following path is a file" + outputPathFunctional);
}
if (!ftmp.exists()) {
ftmp.mkdir();
}
ftmp = new File(outputPathRuntime);
if (ftmp.exists() && ftmp.isFile()) {
OsateDebug.osateDebug("Error, the following path is a file" + outputPathRuntime);
}
if (!ftmp.exists()) {
ftmp.mkdir();
}
}
public static void createAadlFunctions(String outputFile, Model genericModel) {
try (FileWriter fstream = new FileWriter(outputFile); BufferedWriter out = new BufferedWriter(fstream)) {
out.write("package " + genericModel.getName() + "::imported::functions\n");
out.write("public\n");
out.write("with SEI;\n");
out.write("with ARINC653;\n");
for (Component e : genericModel.getComponents()) {
if (e.getType() == Component.ComponentType.BLOCK) {
out.write("abstract " + e.getAadlName() + "\n");
if ((e.getIncomingDependencies().size() > 0) || (e.getOutgoingDependencies().size() > 0)) {
out.write("features\n");
for (Component e2 : e.getIncomingDependencies()) {
out.write(" from_" + e2.getAadlName() + " : in event port;\n");
}
for (Component e2 : e.getOutgoingDependencies()) {
out.write(" to_" + e2.getAadlName() + " : out event port;\n");
}
}
out.write("end " + e.getAadlName() + ";\n");
}
}
out.write("end " + genericModel.getName() + "::imported::functions;\n");
} catch (Exception e) {
OsateDebug.osateDebug("Error: " + e.getMessage());
IStatus status = new Status(IStatus.ERROR, org.osate.importer.simulink.Activator.PLUGIN_ID, e.getMessage(),
e);
StatusManager manager = StatusManager.getManager();
manager.handle(status, StatusManager.LOG);
}
}
public static void createAadlRuntime(String outputFile, Model genericModel) {
boolean connectionPreamble;
boolean subComponentsPreambleWritten;
StateMachine sm;
StateFlowInstance sfi;
connectionPreamble = false;
subComponentsPreambleWritten = false;
try (FileWriter fstream = new FileWriter(outputFile); BufferedWriter out = new BufferedWriter(fstream)) {
out.write("package " + genericModel.getName() + "::imported::runtime\n");
out.write("public\n");
out.write("with " + genericModel.getName() + "::imported::functions;\n");
out.write("with SEI;\n");
out.write("with Data_Model;\n");
List<String> importedPackages = new ArrayList<String>();
/**
* We import all the packages that are used by referenced components
*/
for (Component c : genericModel.getComponents()) {
if (c.getType() == ComponentType.REFERENCE) {
String pkgName = c.getAadlReferencedModel();
boolean found = false;
for (String pkgTmp : importedPackages) {
OsateDebug.osateDebug("AadlProjectCreator", "pkg=" + pkgTmp);
if (pkgTmp.equalsIgnoreCase(pkgName)) {
found = true;
}
}
if (!found) {
out.write("with " + pkgName + "::imported::runtime;\n");
importedPackages.add(pkgName);
}
}
}
out.write("\n\n");
out.write(
"data generictype\nproperties\n Data_Model::Data_Representation => integer;\nend generictype;\n\n\n");
out.write(
"data generictype_boolean\nproperties\n Data_Model::Data_Representation => boolean;\nend generictype_boolean;\n\n\n");
for (Component e : genericModel.getComponents()) {
if (e.getType() != Component.ComponentType.BLOCK) {
continue;
}
/**
* Try to find if we have a corresponding state machine
* for this component.
*/
sm = null;
sfi = FileImport.getStateFlowImport(e.getAadlName());
if (sfi != null) {
OsateDebug.osateDebug("AadlProjectCreator", "machine-id=" + sfi.getMachineId());
sm = genericModel.getStateMachine(sfi.getMachineId());
}
/**
* Let's generate the subprogram for the nested state
* machines of the current component.
*/
if ((sm != null) && (sm.hasNestedStateMachines())) {
for (State s : sm.getStates()) {
if (!s.getInternalStateMachine().isEmpty()) {
out.write("system " + s.getName() + "\n");
if (s.getInternalStateMachine().hasVariables()) {
out.write("features\n");
for (String var : s.getInternalStateMachine().getVariables()) {
out.write(" ");
out.write(var);
out.write(" : requires data access ");
if (s.getInternalStateMachine()
.getVariableType(var) == StateMachine.VARIABLE_TYPE_BOOL) {
out.write("generictype_boolean");
} else {
out.write("generictype");
}
out.write(";\n");
}
}
out.write("end " + s.getName() + ";\n\n\n");
out.write("system implementation " + s.getName() + ".i\n");
Utils.writeBehaviorAnnex(s.getInternalStateMachine(), out);
out.write("end " + s.getName() + ".i;\n\n\n");
}
}
}
/**
* Write the main system component.
*/
out.write("system s_" + e.getAadlName() + "\n");
// if ( (e.getIncomingDependencies().size() > 0 )||
// (e.getOutgoingDependencies().size() > 0 )||
// ((e.getSubEntities().size() > 0) && (((e.getSubEntities().get(0).getIncomingDependencies().size() >
// 0)
// ||
// (e.getSubEntities().get(0).getOutgoingDependencies().size() > 0)))))
if (e.hasInterfaces()) {
out.write("features\n");
}
for (Component e2 : e.getIncomingDependencies()) {
out.write(" from_" + e2.getAadlName() + " : in event data port generictype;\n");
}
for (Component e2 : e.getOutgoingDependencies()) {
out.write(" to_" + e2.getAadlName() + " : out event data port generictype;\n");
}
for (Component e2 : e.getSubcomponents(ComponentType.EXTERNAL_OUTPORT)) {
out.write(" " + e2.getAadlName() + " : out event data port generictype;\n");
}
for (Component e2 : e.getSubcomponents(ComponentType.EXTERNAL_INPORT)) {
out.write(" " + e2.getAadlName() + " : in event data port generictype;\n");
}
out.write("end s_" + e.getAadlName() + ";\n\n");
out.write("system implementation s_" + e.getAadlName() + ".i\n");
/**
* Add all the subcomponents of the current component.
* We consider subcomponents are sub-entities that have
* the type "block".
*/
if (e.hasSubcomponents()) {
out.write("subcomponents\n");
subComponentsPreambleWritten = true;
for (Component c : e.getSubcomponents(ComponentType.BLOCK)) {
out.write(" " + c.getAadlName() + " : system s_" + c.getAadlName() + ".i;\n");
}
for (Component c : e.getSubcomponents(ComponentType.REFERENCE)) {
out.write(" " + c.getAadlName() + " : system " + c.getAadlReferencedModel()
+ "::imported::runtime::s_" + c.getAadlReferencedComponent() + ".i;\n");
}
}
int connectionId = 0;
connectionPreamble = false;
/**
* Here, we try to catch all connections with our external features.
*/
for (Connection conn : genericModel.getConnections()) {
/**
* Case of an IN port connected to a subcomponent.
*/
if ((conn.getSource().getParent() != null) && (conn.getSource().getParent() == e)
&& (conn.getDestination().getParent() != null)
&& (conn.getDestination().getParent().getParent() != null)
&& (conn.getDestination().getParent().getParent() == e)) {
if (!connectionPreamble) {
connectionPreamble = true;
out.write("connections\n");
}
out.write(" cin" + connectionId++ + " : port " + conn.getSource().getAadlName() + "->"
+ conn.getDestination().getParent().getAadlName() + "."
+ conn.getDestination().getAadlName() + ";\n");
}
/**
* Case of an OUT port connected to a subcomponent.
*/
if ((conn.getDestination().getParent() != null) && (conn.getDestination().getParent() == e)
&& (conn.getSource().getParent() != null)
&& (conn.getSource().getParent().getParent() != null)
&& (conn.getSource().getParent().getParent() == e)) {
if (!connectionPreamble) {
connectionPreamble = true;
out.write("connections\n");
}
out.write(" cout" + connectionId++ + " : port " + conn.getSource().getParent().getAadlName()
+ "." + conn.getSource().getAadlName() + "->" + conn.getDestination().getAadlName()
+ ";\n");
}
}
//
// for (Component subco : e.getSubcomponents(ComponentType.EXTERNAL_OUTPORT))
// {
// for (Connection conn : genericModel.getConnections())
// {
// if (conn.getDestination() == subco)
// {
// if (!connectionPreamble)
// {
// connectionPreamble = true;
// out.write("connections\n");
// }
// out.write(" c" + connectionId++ +" : port " + conn.getDestination().getParent().getAadlName() + "." + conn.getDestination().getAadlName() + " -> " + subco.getAadlName() + ";\n");
//
// }
// }
// }
if (sm != null) {
Utils.writeSubprogramSubcomponents(sm, e, out, new ArrayList<String>(),
subComponentsPreambleWritten);
/**
* Let's call the other subprogram that contains
* the sub state machines. Then, if these
* state machines share data, we need to
* add data components and connect them.
*/
if (sm.hasNestedStateMachines()) {
for (State s : sm.getStates()) {
if (!s.getInternalStateMachine().isEmpty()) {
out.write(" call_" + s.getName() + " : system " + s.getName() + ".i;\n");
}
}
}
/**
*
* Connect the data components shared among the different subprograms
* using data access connections.
*/
if (sm.nestedStateMachinehasVariables()) {
out.write("connections\n");
for (State state : sm.getStates()) {
for (String var : state.getInternalStateMachine().getVariables()) {
/**
* Generate the data access if there is a data (in other words,
* if we do not have an existing feature that represent the data).
*/
if (e.getSubEntity(var.toLowerCase()) == null) {
out.write(" c" + connectionId++ + " : data access " + var + "-> call_"
+ state.getName() + "." + var + ";\n");
}
}
}
}
}
if (sm != null) {
Utils.writeBehaviorAnnex(sm, out);
}
out.write("end s_" + e.getAadlName() + ".i;\n\n");
}
/**
* End of generating the main system component.
*/
out.write("system mainsystem\n");
boolean featuresDeclared = false;
for (Component e : genericModel.getComponents()) {
if (e.getParent() != null) {
continue;
}
if (e.getType() == Component.ComponentType.EXTERNAL_INPORT) {
if (!featuresDeclared) {
out.write("features\n");
featuresDeclared = true;
}
out.write(" " + e.getAadlName() + " : in event data port generictype;\n");
}
if (e.getType() == Component.ComponentType.EXTERNAL_OUTPORT) {
if (!featuresDeclared) {
out.write("features\n");
featuresDeclared = true;
}
out.write(" " + e.getAadlName() + " : out event data port generictype;\n");
}
}
out.write("end mainsystem;\n\n\n");
out.write("system implementation mainsystem.i\n");
out.write("subcomponents\n");
for (Component e : genericModel.getComponents()) {
if ((e.getParent() == null) && (e.getType() == Component.ComponentType.BLOCK)) {
out.write(" " + e.getAadlName() + " : system s_" + e.getAadlName() + ".i;\n");
}
}
int connectionId = 0;
connectionPreamble = false;
/**
* Here, we try to catch all connections with our external features.
*/
for (Component e : genericModel.getComponents()) {
if (e.getParent() != null) {
continue;
}
for (Component e2 : e.getOutgoingDependencies()) {
if (!connectionPreamble) {
connectionPreamble = true;
out.write("connections\n");
}
if ((e.getType() == Component.ComponentType.BLOCK)
&& (e2.getType() == Component.ComponentType.BLOCK)) {
out.write(" c" + connectionId++ + " : port " + e.getAadlName() + ".to_" + e2.getAadlName()
+ "->" + e2.getAadlName() + ".from_" + e.getAadlName() + ";\n");
}
if ((e.getType() == Component.ComponentType.EXTERNAL_INPORT)
&& (e2.getType() == Component.ComponentType.BLOCK)) {
out.write(" c" + connectionId++ + " : port " + e.getAadlName() + "->" + e2.getAadlName()
+ ".from_" + e.getAadlName() + ";\n");
}
}
}
/**
* Here, we try to catch all potential connections
* between subcomponents
*/
for (Connection c : genericModel.getConnections()) {
if ((c.getSource().getType() == ComponentType.EXTERNAL_OUTPORT) && (c.getSource().getParent() != null)
&& (c.getSource().getParent().getParent() == null)
&& (c.getDestination().getType() == ComponentType.EXTERNAL_INPORT)
&& (c.getDestination().getParent() != null)
&& (c.getDestination().getParent().getParent() == null)) {
if (!connectionPreamble) {
connectionPreamble = true;
out.write("connections\n");
}
out.write(" c" + connectionId++ + " : port " + c.getSource().getParent().getAadlName() + "."
+ c.getSource().getAadlName() + "->" + c.getDestination().getParent().getAadlName() + "."
+ c.getDestination().getAadlName() + ";\n");
}
}
out.write("end mainsystem.i; \n");
out.write("end " + genericModel.getName() + "::imported::runtime; \n");
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
IStatus status = new Status(IStatus.ERROR, org.osate.importer.simulink.Activator.PLUGIN_ID, e.getMessage(),
e);
StatusManager manager = StatusManager.getManager();
manager.handle(status, StatusManager.LOG);
}
}
public static void createProject(String outputPath, Model genericModel) {
String outputPathFunctional;
String outputPathRuntime;
String outputFileFunctional;
String outputFileRuntime;
outputPathFunctional = outputPath + File.separatorChar + "functional";
outputPathRuntime = outputPath + File.separatorChar + "runtime";
outputFileFunctional = outputPathFunctional + File.separatorChar + "functional.aadl";
outputFileRuntime = outputPathRuntime + File.separatorChar + "runtime.aadl";
createDirectories(outputPath);
// OsateDebug.osateDebug ("Create AADL functional project in " + outputFileFunctional);
createAadlFunctions(outputFileFunctional, genericModel);
// OsateDebug.osateDebug ("Create AADL runtime project in " + outputFileRuntime);
createAadlRuntime(outputFileRuntime, genericModel);
}
}