mirror of
http://172.16.200.102/INGEQUIP/Capella2AADL.git
synced 2025-12-04 18:47:58 +01:00
Initial commit.
This commit is contained in:
7
plugins/com.irtsaintexupery.capella2aadl/.classpath
Normal file
7
plugins/com.irtsaintexupery.capella2aadl/.classpath
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" output="bin" path="src"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
3
plugins/com.irtsaintexupery.capella2aadl/.gitignore
vendored
Normal file
3
plugins/com.irtsaintexupery.capella2aadl/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/tasks
|
||||
/bin
|
||||
/target/
|
||||
50
plugins/com.irtsaintexupery.capella2aadl/.project
Normal file
50
plugins/com.irtsaintexupery.capella2aadl/.project
Normal file
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>com.irtsaintexupery.capella2aadl</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.acceleo.ide.ui.acceleoBuilder</name>
|
||||
<arguments>
|
||||
<dictionary>
|
||||
<key>compilation.kind</key>
|
||||
<value>compilation.platform.resource</value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>compliance</key>
|
||||
<value>pragmatic</value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>resource.kind</key>
|
||||
<value>xmi</value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>trim-position</key>
|
||||
<value>false</value>
|
||||
</dictionary>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.acceleo.ide.ui.acceleoNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,26 @@
|
||||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: %pluginName
|
||||
Bundle-SymbolicName: com.irtsaintexupery.capella2aadl
|
||||
Bundle-Version: 1.2.2.qualifier
|
||||
Bundle-Activator: com.irtsaintexupery.capella2aadl.Activator
|
||||
Bundle-Vendor: %providerName
|
||||
Bundle-Localization: plugin
|
||||
Require-Bundle: org.eclipse.core.runtime,
|
||||
org.polarsys.capella.core.data.gen;bundle-version="1.1.0",
|
||||
org.eclipse.emf.ecore,
|
||||
org.eclipse.emf.ecore.xmi,
|
||||
org.eclipse.ocl,
|
||||
org.eclipse.ocl.ecore,
|
||||
org.eclipse.acceleo.common;bundle-version="3.3.0",
|
||||
org.eclipse.acceleo.model;bundle-version="3.3.0",
|
||||
org.eclipse.acceleo.profiler;bundle-version="3.3.0",
|
||||
org.eclipse.acceleo.engine;bundle-version="3.3.0",
|
||||
com.google.guava,
|
||||
org.polarsys.capella.common.libraries.gen;bundle-version="1.1.0"
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Eclipse-LazyStart: true
|
||||
Export-Package: com.irtsaintexupery.capella2aadl.main,
|
||||
com.irtsaintexupery.capella2aadl.requests
|
||||
|
||||
17
plugins/com.irtsaintexupery.capella2aadl/build.properties
Normal file
17
plugins/com.irtsaintexupery.capella2aadl/build.properties
Normal file
@@ -0,0 +1,17 @@
|
||||
###############################################################################
|
||||
# Copyright (c) 2015 IRT AESE (IRT Saint Exupery).
|
||||
# All rights reserved. This program and the accompanying materials
|
||||
# are made available under the terms of the Eclipse Public License v1.0
|
||||
# which accompanies this distribution, and is available at
|
||||
# http://www.eclipse.org/legal/epl-v10.html
|
||||
#
|
||||
# Contributors:
|
||||
# Bassem Ouni and Pierre Gaufillet (IRT Saint Exup<75>ry) - initial API and implementation
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = plugin.properties, META-INF/,\
|
||||
.
|
||||
jre.compilation.profile = JavaSE-1.7
|
||||
14
plugins/com.irtsaintexupery.capella2aadl/plugin.properties
Normal file
14
plugins/com.irtsaintexupery.capella2aadl/plugin.properties
Normal file
@@ -0,0 +1,14 @@
|
||||
###############################################################################
|
||||
# Copyright (c) 2015, 2016 IRT AESE (IRT Saint Exupery).
|
||||
# All rights reserved. This program and the accompanying materials
|
||||
# are made available under the terms of the Eclipse Public License v1.0
|
||||
# which accompanies this distribution, and is available at
|
||||
# http://www.eclipse.org/legal/epl-v10.html
|
||||
#
|
||||
# Contributors:
|
||||
# Bassem Ouni and Pierre Gaufillet (IRT Saint Exup<75>ry) - initial API and implementation
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
pluginName = Capella2AADL
|
||||
providerName = IRT AESE (IRT Saint Exup<75>ry)
|
||||
60
plugins/com.irtsaintexupery.capella2aadl/pom.xml
Normal file
60
plugins/com.irtsaintexupery.capella2aadl/pom.xml
Normal file
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (c) 2015, 2017 IRT AESE (IRT Saint Exupery).
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
which accompanies this distribution, and is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
|
||||
Contributors:
|
||||
Bassem Ouni and Pierre Gaufillet (IRT Saint Exupéry) - initial API and implementation
|
||||
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.irtsaintexupery</groupId>
|
||||
<artifactId>parent</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<relativePath>../../releng/com.irtsaintexupery.parent</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>com.irtsaintexupery.capella2aadl</artifactId>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
<version>1.2.2-SNAPSHOT</version>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.acceleo</groupId>
|
||||
<artifactId>org.eclipse.acceleo.maven</artifactId>
|
||||
<configuration>
|
||||
<useBinaryResources>false</useBinaryResources>
|
||||
<usePlatformResourcePath>true</usePlatformResourcePath>
|
||||
<acceleoProject>
|
||||
<root>${project.basedir}</root>
|
||||
<entries>
|
||||
<entry>
|
||||
<input>src</input>
|
||||
<output>target/classes</output>
|
||||
</entry>
|
||||
</entries>
|
||||
</acceleoProject>
|
||||
<packagesToRegister>
|
||||
<packageToRegister>org.eclipse.emf.ecore.EcorePackage</packageToRegister>
|
||||
<packageToRegister>org.polarsys.capella.core.data.pa.PaPackage</packageToRegister>
|
||||
<packageToRegister>org.polarsys.capella.core.data.cs.CsPackage</packageToRegister>
|
||||
<packageToRegister>org.polarsys.capella.core.data.capellacore.CapellacorePackage</packageToRegister>
|
||||
<packageToRegister>org.polarsys.capella.core.data.capellamodeller.CapellamodellerPackage</packageToRegister>
|
||||
<packageToRegister>org.polarsys.capella.common.libraries.LibrariesPackage</packageToRegister>
|
||||
<packageToRegister>org.polarsys.capella.core.data.capellacommon.CapellacommonPackage</packageToRegister>
|
||||
<packageToRegister>org.polarsys.capella.core.data.capellacore.CapellacorePackage</packageToRegister>
|
||||
</packagesToRegister>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,69 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2015, 2017 IRT AESE (IRT Saint Exupery).
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Bassem Ouni and Pierre Gaufillet (IRT Saint Exupéry) - initial API and implementation
|
||||
*
|
||||
*******************************************************************************/
|
||||
package com.irtsaintexupery.capella2aadl;
|
||||
|
||||
import org.eclipse.core.runtime.Plugin;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
/**
|
||||
* The activator class controls the plug-in life cycle.
|
||||
*/
|
||||
public class Activator extends Plugin {
|
||||
|
||||
/**
|
||||
* The plug-in ID.
|
||||
*/
|
||||
public static final String PLUGIN_ID = "com.irtsaintexupery.capella2aadl";
|
||||
|
||||
/**
|
||||
* The shared instance.
|
||||
*/
|
||||
private static Activator plugin;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*/
|
||||
public Activator() {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see org.eclipse.core.runtime.Plugin#start(org.osgi.framework.BundleContext)
|
||||
*/
|
||||
@Override
|
||||
public void start(BundleContext context) throws Exception {
|
||||
super.start(context);
|
||||
plugin = this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext)
|
||||
*/
|
||||
@Override
|
||||
public void stop(BundleContext context) throws Exception {
|
||||
plugin = null;
|
||||
super.stop(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the shared instance.
|
||||
*
|
||||
* @return the shared instance
|
||||
*/
|
||||
public static Activator getDefault() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,407 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2015, 2017 IRT AESE (IRT Saint Exupery).
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Bassem Ouni and Pierre Gaufillet (IRT Saint Exupéry) - initial API and implementation
|
||||
*
|
||||
*******************************************************************************/
|
||||
package com.irtsaintexupery.capella2aadl.main;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.acceleo.engine.event.IAcceleoTextGenerationListener;
|
||||
import org.eclipse.acceleo.engine.generation.strategy.IAcceleoGenerationStrategy;
|
||||
import org.eclipse.acceleo.engine.service.AbstractAcceleoGenerator;
|
||||
import org.eclipse.emf.common.util.BasicMonitor;
|
||||
import org.eclipse.emf.common.util.Monitor;
|
||||
import org.eclipse.emf.common.util.URI;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.emf.ecore.resource.ResourceSet;
|
||||
|
||||
/**
|
||||
* Entry point of the 'Capella2aadl' generation module.
|
||||
*
|
||||
* @generated
|
||||
*/
|
||||
public class Capella2aadl extends AbstractAcceleoGenerator {
|
||||
/**
|
||||
* The name of the module.
|
||||
*
|
||||
* @generated
|
||||
*/
|
||||
public static final String MODULE_FILE_NAME = "/com/irtsaintexupery/capella2aadl/main/capella2aadl";
|
||||
|
||||
/**
|
||||
* The name of the templates that are to be generated.
|
||||
*
|
||||
* @generated
|
||||
*/
|
||||
public static final String[] TEMPLATE_NAMES = { "generateProject" };
|
||||
|
||||
/**
|
||||
* The list of properties files from the launch parameters (Launch configuration).
|
||||
*
|
||||
* @generated
|
||||
*/
|
||||
private List<String> propertiesFiles = new ArrayList<String>();
|
||||
|
||||
/**
|
||||
* Allows the public constructor to be used. Note that a generator created
|
||||
* this way cannot be used to launch generations before one of
|
||||
* {@link #initialize(EObject, File, List)} or
|
||||
* {@link #initialize(URI, File, List)} is called.
|
||||
* <p>
|
||||
* The main reason for this constructor is to allow clients of this
|
||||
* generation to call it from another Java file, as it allows for the
|
||||
* retrieval of {@link #getProperties()} and
|
||||
* {@link #getGenerationListeners()}.
|
||||
* </p>
|
||||
*
|
||||
* @generated
|
||||
*/
|
||||
public Capella2aadl() {
|
||||
// Empty implementation
|
||||
}
|
||||
|
||||
/**
|
||||
* This allows clients to instantiates a generator with all required information.
|
||||
*
|
||||
* @param modelURI
|
||||
* URI where the model on which this generator will be used is located.
|
||||
* @param targetFolder
|
||||
* This will be used as the output folder for this generation : it will be the base path
|
||||
* against which all file block URLs will be resolved.
|
||||
* @param arguments
|
||||
* If the template which will be called requires more than one argument taken from the model,
|
||||
* pass them here.
|
||||
* @throws IOException
|
||||
* This can be thrown in three scenarios : the module cannot be found, it cannot be loaded, or
|
||||
* the model cannot be loaded.
|
||||
* @generated
|
||||
*/
|
||||
public Capella2aadl(URI modelURI, File targetFolder,
|
||||
List<? extends Object> arguments) throws IOException {
|
||||
initialize(modelURI, targetFolder, arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* This allows clients to instantiates a generator with all required information.
|
||||
*
|
||||
* @param model
|
||||
* We'll iterate over the content of this element to find Objects matching the first parameter
|
||||
* of the template we need to call.
|
||||
* @param targetFolder
|
||||
* This will be used as the output folder for this generation : it will be the base path
|
||||
* against which all file block URLs will be resolved.
|
||||
* @param arguments
|
||||
* If the template which will be called requires more than one argument taken from the model,
|
||||
* pass them here.
|
||||
* @throws IOException
|
||||
* This can be thrown in two scenarios : the module cannot be found, or it cannot be loaded.
|
||||
* @generated
|
||||
*/
|
||||
public Capella2aadl(EObject model, File targetFolder,
|
||||
List<? extends Object> arguments) throws IOException {
|
||||
initialize(model, targetFolder, arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* This can be used to launch the generation from a standalone application.
|
||||
*
|
||||
* @param args
|
||||
* Arguments of the generation.
|
||||
* @generated
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
if (args.length < 2) {
|
||||
System.out.println("Arguments not valid : {model, folder}.");
|
||||
} else {
|
||||
URI modelURI = URI.createFileURI(args[0]);
|
||||
File folder = new File(args[1]);
|
||||
|
||||
List<String> arguments = new ArrayList<String>();
|
||||
|
||||
/*
|
||||
* If you want to change the content of this method, do NOT forget to change the "@generated"
|
||||
* tag in the Javadoc of this method to "@generated NOT". Without this new tag, any compilation
|
||||
* of the Acceleo module with the main template that has caused the creation of this class will
|
||||
* revert your modifications.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Add in this list all the arguments used by the starting point of the generation
|
||||
* If your main template is called on an element of your model and a String, you can
|
||||
* add in "arguments" this "String" attribute.
|
||||
*/
|
||||
|
||||
Capella2aadl generator = new Capella2aadl(modelURI, folder, arguments);
|
||||
|
||||
/*
|
||||
* Add the properties from the launch arguments.
|
||||
* If you want to programmatically add new properties, add them in "propertiesFiles"
|
||||
* You can add the absolute path of a properties files, or even a project relative path.
|
||||
* If you want to add another "protocol" for your properties files, please override
|
||||
* "getPropertiesLoaderService(AcceleoService)" in order to return a new property loader.
|
||||
* The behavior of the properties loader service is explained in the Acceleo documentation
|
||||
* (Help -> Help Contents).
|
||||
*/
|
||||
|
||||
for (int i = 2; i < args.length; i++) {
|
||||
generator.addPropertiesFile(args[i]);
|
||||
}
|
||||
|
||||
generator.doGenerate(new BasicMonitor());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Launches the generation described by this instance.
|
||||
*
|
||||
* @param monitor
|
||||
* This will be used to display progress information to the user.
|
||||
* @throws IOException
|
||||
* This will be thrown if any of the output files cannot be saved to disk.
|
||||
* @generated
|
||||
*/
|
||||
@Override
|
||||
public void doGenerate(Monitor monitor) throws IOException {
|
||||
/*
|
||||
* TODO if you wish to change the generation as a whole, override this. The default behavior should
|
||||
* be sufficient in most cases. If you want to change the content of this method, do NOT forget to
|
||||
* change the "@generated" tag in the Javadoc of this method to "@generated NOT". Without this new tag,
|
||||
* any compilation of the Acceleo module with the main template that has caused the creation of this
|
||||
* class will revert your modifications. If you encounter a problem with an unresolved proxy during the
|
||||
* generation, you can remove the comments in the following instructions to check for problems. Please
|
||||
* note that those instructions may have a significant impact on the performances.
|
||||
*/
|
||||
|
||||
//org.eclipse.emf.ecore.util.EcoreUtil.resolveAll(model);
|
||||
|
||||
/*
|
||||
* If you want to check for potential errors in your models before the launch of the generation, you
|
||||
* use the code below.
|
||||
*/
|
||||
|
||||
//if (model != null && model.eResource() != null) {
|
||||
// List<org.eclipse.emf.ecore.resource.Resource.Diagnostic> errors = model.eResource().getErrors();
|
||||
// for (org.eclipse.emf.ecore.resource.Resource.Diagnostic diagnostic : errors) {
|
||||
// System.err.println(diagnostic.toString());
|
||||
// }
|
||||
//}
|
||||
|
||||
super.doGenerate(monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* If this generator needs to listen to text generation events, listeners can be returned from here.
|
||||
*
|
||||
* @return List of listeners that are to be notified when text is generated through this launch.
|
||||
* @generated
|
||||
*/
|
||||
@Override
|
||||
public List<IAcceleoTextGenerationListener> getGenerationListeners() {
|
||||
List<IAcceleoTextGenerationListener> listeners = super.getGenerationListeners();
|
||||
/*
|
||||
* TODO if you need to listen to generation event, add listeners to the list here. If you want to change
|
||||
* the content of this method, do NOT forget to change the "@generated" tag in the Javadoc of this method
|
||||
* to "@generated NOT". Without this new tag, any compilation of the Acceleo module with the main template
|
||||
* that has caused the creation of this class will revert your modifications.
|
||||
*/
|
||||
return listeners;
|
||||
}
|
||||
|
||||
/**
|
||||
* If you need to change the way files are generated, this is your entry point.
|
||||
* <p>
|
||||
* The default is {@link org.eclipse.acceleo.engine.generation.strategy.DefaultStrategy}; it generates
|
||||
* files on the fly. If you only need to preview the results, return a new
|
||||
* {@link org.eclipse.acceleo.engine.generation.strategy.PreviewStrategy}. Both of these aren't aware of
|
||||
* the running Eclipse and can be used standalone.
|
||||
* </p>
|
||||
* <p>
|
||||
* If you need the file generation to be aware of the workspace (A typical example is when you wanna
|
||||
* override files that are under clear case or any other VCS that could forbid the overriding), then
|
||||
* return a new {@link org.eclipse.acceleo.engine.generation.strategy.WorkspaceAwareStrategy}.
|
||||
* <b>Note</b>, however, that this <b>cannot</b> be used standalone.
|
||||
* </p>
|
||||
* <p>
|
||||
* All three of these default strategies support merging through JMerge.
|
||||
* </p>
|
||||
*
|
||||
* @return The generation strategy that is to be used for generations launched through this launcher.
|
||||
* @generated
|
||||
*/
|
||||
@Override
|
||||
public IAcceleoGenerationStrategy getGenerationStrategy() {
|
||||
return super.getGenerationStrategy();
|
||||
}
|
||||
|
||||
/**
|
||||
* This will be called in order to find and load the module that will be launched through this launcher.
|
||||
* We expect this name not to contain file extension, and the module to be located beside the launcher.
|
||||
*
|
||||
* @return The name of the module that is to be launched.
|
||||
* @generated
|
||||
*/
|
||||
@Override
|
||||
public String getModuleName() {
|
||||
return MODULE_FILE_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the module(s) called by this launcher require properties files, return their qualified path from
|
||||
* here.Take note that the first added properties files will take precedence over subsequent ones if they
|
||||
* contain conflicting keys.
|
||||
*
|
||||
* @return The list of properties file we need to add to the generation context.
|
||||
* @see java.util.ResourceBundle#getBundle(String)
|
||||
* @generated
|
||||
*/
|
||||
@Override
|
||||
public List<String> getProperties() {
|
||||
/*
|
||||
* If you want to change the content of this method, do NOT forget to change the "@generated"
|
||||
* tag in the Javadoc of this method to "@generated NOT". Without this new tag, any compilation
|
||||
* of the Acceleo module with the main template that has caused the creation of this class will
|
||||
* revert your modifications.
|
||||
*/
|
||||
|
||||
/*
|
||||
* TODO if your generation module requires access to properties files, add their qualified path to the list here.
|
||||
*
|
||||
* Properties files can be located in an Eclipse plug-in or in the file system (all Acceleo projects are Eclipse
|
||||
* plug-in). In order to use properties files located in an Eclipse plugin, you need to add the path of the properties
|
||||
* files to the "propertiesFiles" list:
|
||||
*
|
||||
* final String prefix = "platform:/plugin/";
|
||||
* final String pluginName = "org.eclipse.acceleo.module.sample";
|
||||
* final String packagePath = "/org/eclipse/acceleo/module/sample/properties/";
|
||||
* final String fileName = "default.properties";
|
||||
* propertiesFiles.add(prefix + pluginName + packagePath + fileName);
|
||||
*
|
||||
* With this mechanism, you can load properties files from your plugin or from another plugin.
|
||||
*
|
||||
* You may want to load properties files from the file system, for that you need to add the absolute path of the file:
|
||||
*
|
||||
* propertiesFiles.add("C:\Users\MyName\MyFile.properties");
|
||||
*
|
||||
* If you want to let your users add properties files located in the same folder as the model:
|
||||
*
|
||||
* if (EMFPlugin.IS_ECLIPSE_RUNNING && model != null && model.eResource() != null) {
|
||||
* propertiesFiles.addAll(AcceleoEngineUtils.getPropertiesFilesNearModel(model.eResource()));
|
||||
* }
|
||||
*
|
||||
* To learn more about Properties Files, have a look at the Acceleo documentation (Help -> Help Contents).
|
||||
*/
|
||||
return propertiesFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a properties file in the list of properties files.
|
||||
*
|
||||
* @param propertiesFile
|
||||
* The properties file to add.
|
||||
* @generated
|
||||
* @since 3.1
|
||||
*/
|
||||
@Override
|
||||
public void addPropertiesFile(String propertiesFile) {
|
||||
this.propertiesFiles.add(propertiesFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will be used to get the list of templates that are to be launched by this launcher.
|
||||
*
|
||||
* @return The list of templates to call on the module {@link #getModuleName()}.
|
||||
* @generated
|
||||
*/
|
||||
@Override
|
||||
public String[] getTemplateNames() {
|
||||
return TEMPLATE_NAMES;
|
||||
}
|
||||
|
||||
/**
|
||||
* This can be used to update the resource set's package registry with all needed EPackages.
|
||||
*
|
||||
* @param resourceSet
|
||||
* The resource set which registry has to be updated.
|
||||
* @generated
|
||||
*/
|
||||
@Override
|
||||
public void registerPackages(ResourceSet resourceSet) {
|
||||
super.registerPackages(resourceSet);
|
||||
|
||||
/*
|
||||
* If you want to change the content of this method, do NOT forget to change the "@generated"
|
||||
* tag in the Javadoc of this method to "@generated NOT". Without this new tag, any compilation
|
||||
* of the Acceleo module with the main template that has caused the creation of this class will
|
||||
* revert your modifications.
|
||||
*/
|
||||
|
||||
/*
|
||||
* If you need additional package registrations, you can register them here. The following line
|
||||
* (in comment) is an example of the package registration for UML.
|
||||
*
|
||||
* You can use the method "isInWorkspace(Class c)" to check if the package that you are about to
|
||||
* register is in the workspace.
|
||||
*
|
||||
* To register a package properly, please follow the following conventions:
|
||||
*
|
||||
* If the package is located in another plug-in, already installed in Eclipse. The following content should
|
||||
* have been generated at the beginning of this method. Do not register the package using this mechanism if
|
||||
* the metamodel is located in the workspace.
|
||||
*
|
||||
* if (!isInWorkspace(UMLPackage.class)) {
|
||||
* // The normal package registration if your metamodel is in a plugin.
|
||||
* resourceSet.getPackageRegistry().put(UMLPackage.eNS_URI, UMLPackage.eINSTANCE);
|
||||
* }
|
||||
*
|
||||
* If the package is located in another project in your workspace, the plugin containing the package has not
|
||||
* been register by EMF and Acceleo should register it automatically. If you want to use the generator in
|
||||
* stand alone, the regular registration (seen a couple lines before) is needed.
|
||||
*
|
||||
* To learn more about Package Registration, have a look at the Acceleo documentation (Help -> Help Contents).
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* This can be used to update the resource set's resource factory registry with all needed factories.
|
||||
*
|
||||
* @param resourceSet
|
||||
* The resource set which registry has to be updated.
|
||||
* @generated
|
||||
*/
|
||||
@Override
|
||||
public void registerResourceFactories(ResourceSet resourceSet) {
|
||||
super.registerResourceFactories(resourceSet);
|
||||
/*
|
||||
* If you want to change the content of this method, do NOT forget to change the "@generated"
|
||||
* tag in the Javadoc of this method to "@generated NOT". Without this new tag, any compilation
|
||||
* of the Acceleo module with the main template that has caused the creation of this class will
|
||||
* revert your modifications.
|
||||
*/
|
||||
|
||||
/*
|
||||
* TODO If you need additional resource factories registrations, you can register them here. the following line
|
||||
* (in comment) is an example of the resource factory registration for UML.
|
||||
*
|
||||
* If you want to use the generator in stand alone, the resource factory registration will be required.
|
||||
*
|
||||
* To learn more about the registration of Resource Factories, have a look at the Acceleo documentation (Help -> Help Contents).
|
||||
*/
|
||||
|
||||
// resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(UMLResource.FILE_EXTENSION, UMLResource.Factory.INSTANCE);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,234 @@
|
||||
[comment encoding = UTF-8 /]
|
||||
[**
|
||||
* Copyright (c) 2015, 2017 IRT AESE (IRT Saint Exupery).
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Bassem Ouni and Pierre Gaufillet (IRT Saint Exupéry) - initial API and implementation
|
||||
*
|
||||
*/]
|
||||
[module capella2aadl('http://www.polarsys.org/capella/core/pa/1.1.0','http://www.polarsys.org/capella/core/core/1.1.0','http://www.polarsys.org/capella/core/modeller/1.1.0','http://www.polarsys.org/capella/common/libraries/1.1.0','http://www.polarsys.org/capella/common/core/1.1.0','http://www.polarsys.org/capella/core/common/1.1.0', 'http://www.polarsys.org/capella/core/cs/1.1.0', 'http://www.polarsys.org/capella/core/fa/1.1.0')]
|
||||
|
||||
[import com::irtsaintexupery::capella2aadl::requests::capella2aadl_queries /]
|
||||
|
||||
[template public generateProject(aProject: Project)]
|
||||
[comment @main/]
|
||||
[transformCapellaPhysicalLinksIntoAADLBusTopology(aProject)/]
|
||||
[transformCapellaComponentExchangeIntoAADLConnections(aProject)/]
|
||||
[for(cat: String | getBusNames(aProject))][generateBus(cat)/][/for]
|
||||
[for(component: PhysicalComponent | PhysicalComponent.allInstances())][generatePhysicalComponent(component)/][/for]
|
||||
[/template]
|
||||
|
||||
[**
|
||||
* The documentation of the template generatePhysicalComponent.
|
||||
* @param aPhysicalComponent
|
||||
*/]
|
||||
[template public generatePhysicalComponent(aPhysicalComponent : PhysicalComponent)]
|
||||
[let PcName : String = aPhysicalComponent.name.replaceAll(' ', '_') ]
|
||||
[if(not aPhysicalComponent.hasPropertyValue('isBus'))]
|
||||
[file ((PcName + '.aadl').toLower(), false, 'UTF-8')]
|
||||
package [PcName/]
|
||||
|
||||
public
|
||||
[for(name: String | aPhysicalComponent.ownedPhysicalComponents->select(nature = PhysicalComponentNature::NODE).name->asSet()->union(getSyntheticPorts(aPhysicalComponent).getBusTypeForPort()->asSet())->sortedBy(s: String | s))]
|
||||
with [name.replaceAll(' ', '_')/]; renames [name.replaceAll(' ', '_')/]::all;
|
||||
[/for]
|
||||
[for(processor: PhysicalComponent | aPhysicalComponent.ownedPhysicalComponents->select(kind=PhysicalComponentKind::SOFTWARE_EXECUTION_UNIT))]
|
||||
[let processorPart: Part = Part.allInstances()->select(abstractType=processor)->any(eContainer()=aPhysicalComponent and name=processor.name)]
|
||||
[let deployedParts: Sequence(Part) = processorPart.ownedDeploymentLinks.deployedElement]
|
||||
[for(part: Part | deployedParts->sortedBy(name))]
|
||||
with [part.abstractType.name.replaceAll(' ', '_')/]; renames [part.abstractType.name.replaceAll(' ', '_')/]::all;
|
||||
[/for]
|
||||
[/let][/let]
|
||||
[/for]
|
||||
|
||||
[if(aPhysicalComponent.nature = PhysicalComponentNature::BEHAVIOR)]
|
||||
[generateBehavior(aPhysicalComponent)/]
|
||||
[else]
|
||||
[generateNode(aPhysicalComponent)/]
|
||||
[/if]
|
||||
end [PcName/];
|
||||
[/file]
|
||||
[/if][/let][/template]
|
||||
|
||||
[template public generateBehavior(aPhysicalComponent : PhysicalComponent)]
|
||||
[let PcName : String = aPhysicalComponent.name.replaceAll(' ', '_') ]
|
||||
process [PcName/]
|
||||
[if(aPhysicalComponent.ownedFeatures->filter(ComponentPort)->notEmpty())]
|
||||
features
|
||||
[for(port1: ComponentPort | aPhysicalComponent.ownedFeatures->filter(ComponentPort)->sortedBy(name))]
|
||||
[if(port1.kind=ComponentPortKind::FLOW)] [port1.name.replaceAll(' ', '_')/]: [port1.orientation.getPortDirection()/] feature;[/if]
|
||||
[/for][/if]
|
||||
|
||||
end [PcName/];
|
||||
|
||||
process implementation [PcName/].impl
|
||||
end [PcName/].impl;
|
||||
|
||||
[/let]
|
||||
[/template]
|
||||
|
||||
[template public generateNode(aPhysicalComponent : PhysicalComponent)]
|
||||
[if(aPhysicalComponent.kind=PhysicalComponentKind::SOFTWARE_EXECUTION_UNIT)]
|
||||
[generateProcessor(aPhysicalComponent)/]
|
||||
[elseif(aPhysicalComponent.kind=PhysicalComponentKind::HARDWARE)]
|
||||
[generateDevice(aPhysicalComponent)/]
|
||||
[else]
|
||||
[generateSystem(aPhysicalComponent)/]
|
||||
[/if][/template]
|
||||
|
||||
[template public generateProcessor(aPhysicalComponent : PhysicalComponent)]
|
||||
[let PcName : String = aPhysicalComponent.name.replaceAll(' ', '_') ]
|
||||
processor [PcName/]
|
||||
[if(getSyntheticPorts(aPhysicalComponent)->notEmpty())]
|
||||
features
|
||||
[for(pport: PhysicalPort | getSyntheticPorts(aPhysicalComponent)->sortedBy(name))]
|
||||
[pport.name.toLowerCase().replaceAll(' ', '_')/]: requires bus access [getBusTypeForPort(pport).replaceAll(' ', '_')/].impl;
|
||||
[/for][/if]
|
||||
end [PcName/];
|
||||
|
||||
processor implementation [PcName/].impl
|
||||
end [PcName/].impl;
|
||||
|
||||
[/let]
|
||||
[/template]
|
||||
|
||||
[template public generateDevice(aPhysicalComponent : PhysicalComponent)]
|
||||
[let PcName : String = aPhysicalComponent.name.replaceAll(' ', '_') ]
|
||||
device [PcName/]
|
||||
[if(getSyntheticPorts(aPhysicalComponent)->union(getComponentVirtualBehaviorPort(aPhysicalComponent))->notEmpty())]
|
||||
features
|
||||
[for(pport: PhysicalPort | getSyntheticPorts(aPhysicalComponent)->sortedBy(name))]
|
||||
[pport.name.toLowerCase().replaceAll(' ', '_')/]: requires bus access [getBusTypeForPort(pport).replaceAll(' ', '_')/].impl;
|
||||
[/for]
|
||||
[for(pport: PhysicalPort | getComponentVirtualBehaviorPort(aPhysicalComponent)->sortedBy(name))]
|
||||
[pport.name.toLowerCase().replaceAll(' ', '_')/]: [pport.getStringPropertyValue('orientation')/] feature;
|
||||
[/for]
|
||||
[/if]
|
||||
end [PcName/];
|
||||
|
||||
device implementation [PcName/].impl
|
||||
end [PcName/].impl;
|
||||
|
||||
[/let]
|
||||
[/template]
|
||||
|
||||
[template public generateBus(name : String)]
|
||||
[let busName: String = name.replaceAll(' ', '_')]
|
||||
[file ((busName + '.aadl').toLower(), false, 'UTF-8')]
|
||||
package [busName/]
|
||||
|
||||
public
|
||||
|
||||
bus [busName/]
|
||||
end [busName/];
|
||||
|
||||
bus implementation [busName/].impl
|
||||
end [busName/].impl;
|
||||
|
||||
end [busName/];
|
||||
[/file][/let]
|
||||
[/template]
|
||||
|
||||
[template public generateSystem(aPhysicalComponent : PhysicalComponent)]
|
||||
[let PcName : String = aPhysicalComponent.name.replaceAll(' ', '_') ]
|
||||
system [PcName/]
|
||||
[if(getSyntheticPorts(aPhysicalComponent)->union(getComponentVirtualBehaviorPort(aPhysicalComponent))->notEmpty())]
|
||||
features
|
||||
[for(pport: PhysicalPort | getSyntheticPorts(aPhysicalComponent)->sortedBy(name))]
|
||||
[pport.name.toLowerCase().replaceAll(' ', '_')/]: requires bus access [getBusTypeForPort(pport).replaceAll(' ', '_')/].impl;
|
||||
[/for]
|
||||
[for(pport: PhysicalPort | getComponentVirtualBehaviorPort(aPhysicalComponent)->sortedBy(name))]
|
||||
[pport.name.toLowerCase().replaceAll(' ', '_')/]: [pport.getStringPropertyValue('orientation')/] feature;
|
||||
[/for]
|
||||
[/if]
|
||||
|
||||
end [PcName/];
|
||||
|
||||
system implementation [PcName/].impl
|
||||
[if(aPhysicalComponent.ownedPhysicalComponents->select(nature = PhysicalComponentNature::NODE)->notEmpty())]
|
||||
subcomponents
|
||||
[for(bus: PhysicalComponent | aPhysicalComponent.ownedPhysicalComponents->select(nature = PhysicalComponentNature::NODE)->sortedBy(name))]
|
||||
[if(not bus.hasPropertyValue('isBus'))]
|
||||
[bus.name.toLower().replaceAll(' ', '_')/]_part: [getAADLNature(bus)/] [bus.name.replaceAll(' ', '_')/].impl;
|
||||
[else]
|
||||
[bus.getStringPropertyValue('busName').toLower().replaceAll(' ', '_')/]: [getAADLNature(bus)/] [bus.name.replaceAll(' ', '_')/].impl;
|
||||
[/if]
|
||||
[/for]
|
||||
[for(processor: PhysicalComponent | aPhysicalComponent.ownedPhysicalComponents->select(kind=PhysicalComponentKind::SOFTWARE_EXECUTION_UNIT)->sortedBy(name))]
|
||||
[let processorPart: Part = Part.allInstances()->select(abstractType=processor)->any(eContainer()=aPhysicalComponent and name=processor.name)]
|
||||
[let deployedParts: Sequence(Part) = processorPart.ownedDeploymentLinks.deployedElement]
|
||||
[for(part: Part | deployedParts->sortedBy(name))]
|
||||
[part.name.toLower().replaceAll(' ', '_')/]_part: process [part.abstractType.name.replaceAll(' ', '_')/].impl;
|
||||
[/for]
|
||||
[/let][/let]
|
||||
[/for]
|
||||
[/if]
|
||||
[if(getSyntheticLinks(aPhysicalComponent)->union(getComponentVirtualBehaviorLink(aPhysicalComponent))->notEmpty())]
|
||||
|
||||
connections
|
||||
-- Bus accesses
|
||||
[for(link: PhysicalLink | getSyntheticLinks(aPhysicalComponent)->sortedBy(name))]
|
||||
[let pp1: PhysicalPort = link.linkEnds->at(1).oclAsType(PhysicalPort)]
|
||||
[let pp2: PhysicalPort = link.linkEnds->at(2).oclAsType(PhysicalPort)]
|
||||
[let linkEnd_1_container: String = if(pp1.eContainer() <> aPhysicalComponent) then pp1.eContainer().oclAsType(PhysicalComponent).name.toLower().replaceAll(' ', '_') else '' endif]
|
||||
[let linkEnd_2_container: String = if(pp2.eContainer() <> aPhysicalComponent) then pp2.eContainer().oclAsType(PhysicalComponent).name.toLower().replaceAll(' ', '_') else '' endif]
|
||||
[if(not pp2.eContainer().oclAsType(PhysicalComponent).hasPropertyValue('isBus'))]
|
||||
[link.name.toLower().replaceAll(' ', '_')/]_connection: bus access [if(linkEnd_1_container<>'')][linkEnd_1_container/]_part.[/if][pp1.name.toLower().replaceAll(' ', '_')/] -> [if(linkEnd_2_container<>'')][linkEnd_2_container/]_part.[/if][pp2.name.toLower().replaceAll(' ', '_')/];
|
||||
[else]
|
||||
[link.name.toLower().replaceAll(' ', '_')/]_connection: bus access [if(linkEnd_1_container<>'')][linkEnd_1_container/]_part.[/if][pp1.name.toLower().replaceAll(' ', '_')/] -> [pp2.eContainer().oclAsType(PhysicalComponent).getStringPropertyValue('busName').toLower().replaceAll(' ', '_')/];
|
||||
[/if]
|
||||
[/let][/let][/let][/let]
|
||||
[/for]
|
||||
|
||||
-- Logical connections
|
||||
[for(link: PhysicalLink | getComponentVirtualBehaviorLink(aPhysicalComponent)->sortedBy(name))]
|
||||
[let pp1: PhysicalPort = link.linkEnds->at(1).oclAsType(PhysicalPort)]
|
||||
[let pp2: PhysicalPort = link.linkEnds->at(2).oclAsType(PhysicalPort)]
|
||||
[let linkEnd_1_container: String = if(pp1.eContainer() <> aPhysicalComponent) then pp1.eContainer().oclAsType(PhysicalComponent).name.toLower().replaceAll(' ', '_') else '' endif]
|
||||
[let linkEnd_2_container: String = if(pp2.eContainer() <> aPhysicalComponent) then pp2.eContainer().oclAsType(PhysicalComponent).name.toLower().replaceAll(' ', '_') else '' endif]
|
||||
[link.name.toLower().replaceAll(' ', '_')/]_connection: feature [if(linkEnd_1_container<>'')][linkEnd_1_container/]_part.[/if][pp1.name.toLower().replaceAll(' ', '_')/] -> [if(linkEnd_2_container<>'')][linkEnd_2_container/]_part.[/if][pp2.name.toLower().replaceAll(' ', '_')/];
|
||||
[/let][/let]
|
||||
[/let][/let]
|
||||
[/for]
|
||||
[/if]
|
||||
[let processors: OrderedSet(PhysicalComponent) = aPhysicalComponent.ownedPhysicalComponents->select(kind=PhysicalComponentKind::SOFTWARE_EXECUTION_UNIT)]
|
||||
[let parts: Bag(DeployableElement) = Part.allInstances()->select(processors->includes(abstractType) and eContainer()=aPhysicalComponent).ownedDeploymentLinks.deployedElement]
|
||||
[let buses: OrderedSet(PhysicalComponent) = aPhysicalComponent.ownedPhysicalComponents->select(nature = PhysicalComponentNature::NODE and hasPropertyValue('isBus'))->sortedBy(name)]
|
||||
[let links: Sequence(PhysicalLink) = getAllocatedVirtualBehaviorLink(aPhysicalComponent)->select(l: PhysicalLink | buses->select(b: PhysicalComponent | b.getStringPropertyValue('busName') = l.getStringPropertyValue('allocatedToBus'))->notEmpty())]
|
||||
[comment]
|
||||
-- processors: [processors.name->sep(', ')/]
|
||||
|
||||
-- parts: [parts.name->sep(', ')/]
|
||||
|
||||
-- buses: [buses.getStringPropertyValue('busName')->sep(', ')/]
|
||||
|
||||
-- links: [links.name->sep(', ')/]
|
||||
|
||||
-- links allocatedToBus: [links.getStringPropertyValue('allocatedToBus')->sep(', ')/]
|
||||
[/comment]
|
||||
[if(parts->notEmpty() or links->notEmpty())]
|
||||
|
||||
properties
|
||||
[for(processor: PhysicalComponent | processors->sortedBy(name))]
|
||||
[for(processorPart: Part | Part.allInstances()->select(abstractType=processor and eContainer()=aPhysicalComponent)->sortedBy(name))]
|
||||
[let deployedParts: Sequence(Part) = processorPart.ownedDeploymentLinks.deployedElement]
|
||||
[for(part: Part | deployedParts->sortedBy(name))]
|
||||
Actual_Processor_Binding => (reference ([processorPart.name.toLower().replaceAll(' ', '_')/]_part)) applies to [part.name.toLower().replaceAll(' ', '_')/]_part;
|
||||
[/for]
|
||||
[/let]
|
||||
[/for]
|
||||
[/for]
|
||||
[for(bus: PhysicalComponent | buses)]
|
||||
[for(link: PhysicalLink | links->select(l: PhysicalLink | bus.getStringPropertyValue('busName') = l.getStringPropertyValue('allocatedToBus')))]
|
||||
Actual_Connection_Binding => (reference ([bus.getStringPropertyValue('busName').toLower().replaceAll(' ', '_')/])) applies to [getVirtualBehaviorLinkRelativeInstancePath(link, aPhysicalComponent)/]_connection;
|
||||
[/for]
|
||||
[/for]
|
||||
[/if]
|
||||
[/let][/let][/let][/let]
|
||||
|
||||
end [PcName/].impl;
|
||||
[/let][/template]
|
||||
@@ -0,0 +1,73 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2015, 2017 IRT AESE (IRT Saint Exupery).
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Bassem Ouni and Pierre Gaufillet (IRT Saint Exupéry) - initial API and implementation
|
||||
*
|
||||
*******************************************************************************/
|
||||
package com.irtsaintexupery.capella2aadl.requests;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.polarsys.capella.core.data.capellamodeller.Project;
|
||||
|
||||
public class Bus {
|
||||
private String name;
|
||||
|
||||
private String type;
|
||||
|
||||
private static Map<String, int[]> busCounters = null;
|
||||
|
||||
public static Set<String> getBusNames(Project project) {
|
||||
return busCounters.keySet();
|
||||
}
|
||||
|
||||
public static Bus createIncrementedNameFromCategory(String type) {
|
||||
if(busCounters == null) {
|
||||
init();
|
||||
}
|
||||
|
||||
if (!busCounters.containsKey(type)) {
|
||||
busCounters.put(type, new int[] { 1 });
|
||||
} else {
|
||||
busCounters.get(type)[0]++;
|
||||
}
|
||||
return new Bus(type + "_" + busCounters.get(type)[0], type);
|
||||
}
|
||||
|
||||
private Bus(String aName) {
|
||||
name = aName;
|
||||
}
|
||||
|
||||
private Bus(String aName, String aType) {
|
||||
name = aName;
|
||||
type = aType;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
busCounters = new HashMap<String, int[]>();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2015, 2017 IRT AESE (IRT Saint Exupery).
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Bassem Ouni and Pierre Gaufillet (IRT Saint Exupéry) - initial API and implementation
|
||||
*
|
||||
*******************************************************************************/
|
||||
package com.irtsaintexupery.capella2aadl.requests;
|
||||
|
||||
public class Capella2AADLException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1089748525850510492L;
|
||||
|
||||
public Capella2AADLException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,493 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2015, 2017 IRT AESE (IRT Saint Exupery).
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Bassem Ouni and Pierre Gaufillet (IRT Saint Exupéry) - initial API and implementation
|
||||
*
|
||||
*******************************************************************************/
|
||||
package com.irtsaintexupery.capella2aadl.requests;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.emf.ecore.util.EcoreUtil;
|
||||
import org.polarsys.capella.common.data.modellingcore.AbstractType;
|
||||
import org.polarsys.capella.common.helpers.EcoreUtil2;
|
||||
import org.polarsys.capella.core.data.capellacore.CapellacoreFactory;
|
||||
import org.polarsys.capella.core.data.capellacore.ModellingArchitecture;
|
||||
import org.polarsys.capella.core.data.capellacore.StringPropertyValue;
|
||||
import org.polarsys.capella.core.data.capellamodeller.Project;
|
||||
import org.polarsys.capella.core.data.capellamodeller.SystemEngineering;
|
||||
import org.polarsys.capella.core.data.cs.AbstractDeploymentLink;
|
||||
import org.polarsys.capella.core.data.cs.CsFactory;
|
||||
import org.polarsys.capella.core.data.cs.DeployableElement;
|
||||
import org.polarsys.capella.core.data.cs.Part;
|
||||
import org.polarsys.capella.core.data.cs.PhysicalLink;
|
||||
import org.polarsys.capella.core.data.cs.PhysicalPort;
|
||||
import org.polarsys.capella.core.data.fa.ComponentExchange;
|
||||
import org.polarsys.capella.core.data.fa.ComponentPort;
|
||||
import org.polarsys.capella.core.data.fa.ComponentPortAllocation;
|
||||
import org.polarsys.capella.core.data.fa.OrientationPortKind;
|
||||
import org.polarsys.capella.core.data.pa.PaFactory;
|
||||
import org.polarsys.capella.core.data.pa.PhysicalArchitecture;
|
||||
import org.polarsys.capella.core.data.pa.PhysicalComponent;
|
||||
import org.polarsys.capella.core.data.pa.PhysicalComponentKind;
|
||||
import org.polarsys.capella.core.data.pa.PhysicalComponentNature;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Multimaps;
|
||||
|
||||
/**
|
||||
* This class provides various static methods for transforming Capella physical
|
||||
* architecture into a preliminary but yet complete AADL model. The main
|
||||
* transformation consists in moving from the 1 to 1 communication model used by
|
||||
* {@link ComponentExchange} to a bus oriented topology closer to AADL bus
|
||||
* accesses
|
||||
*
|
||||
*/
|
||||
public class ComponentExchangeUtils {
|
||||
|
||||
/**
|
||||
* This map provides the list of dummy {@link PhysicalComponent}
|
||||
* representing deployed bahevior nodes for each {@link PhysicalComponent}
|
||||
*/
|
||||
private static ArrayListMultimap<PhysicalComponent, PhysicalComponent> componentVirtualBehaviorNode;
|
||||
|
||||
private static ArrayListMultimap<PhysicalComponent, PhysicalPort> componentVirtualBehaviorPort;
|
||||
|
||||
private static ArrayListMultimap<PhysicalComponent, PhysicalLink> componentVirtualBehaviorLink;
|
||||
private static Multimap<PhysicalLink, PhysicalComponent> virtualBehaviorLinkComponent = null;
|
||||
|
||||
private static ArrayListMultimap<String, PhysicalLink> allocationOfVirtualLinkToPhysicalComponent;
|
||||
|
||||
private static Map<ComponentPort, PhysicalPort> allocationOfComponentPortToPhysicalPort;
|
||||
|
||||
private static List<PhysicalLink> allocatedVirtualBehaviorLink;
|
||||
|
||||
/**
|
||||
* @param pc
|
||||
* @return
|
||||
*/
|
||||
public static List<PhysicalComponent> getComponentVirtualBehaviorNode(PhysicalComponent pc) {
|
||||
return componentVirtualBehaviorNode.get(pc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pc
|
||||
* @return
|
||||
*/
|
||||
public static List<PhysicalPort> getComponentVirtualBehaviorPort(PhysicalComponent pc) {
|
||||
return componentVirtualBehaviorPort.get(pc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pc
|
||||
* @return
|
||||
*/
|
||||
public static List<PhysicalLink> getComponentVirtualBehaviorLink(PhysicalComponent pc) {
|
||||
return componentVirtualBehaviorLink.get(pc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param link
|
||||
* @return
|
||||
*/
|
||||
public static Collection<PhysicalComponent> getVirtualBehaviorLinkComponent(PhysicalLink link) {
|
||||
if(virtualBehaviorLinkComponent == null) {
|
||||
virtualBehaviorLinkComponent = Multimaps.invertFrom(componentVirtualBehaviorLink, ArrayListMultimap.<PhysicalLink, PhysicalComponent>create());
|
||||
// System.out.println("Reversing component/link map...");
|
||||
// for(PhysicalLink l: virtualBehaviorLinkComponent.keySet()) {
|
||||
// System.out.println(l.getName() + ":");
|
||||
// for(PhysicalComponent c: virtualBehaviorLinkComponent.get(l)) {
|
||||
// System.out.println("\t" + c.getName());
|
||||
// }
|
||||
// }
|
||||
}
|
||||
return virtualBehaviorLinkComponent.get(link);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pc
|
||||
* @return
|
||||
*/
|
||||
public static List<PhysicalLink> getAllocatedVirtualBehaviorLink() {
|
||||
return allocatedVirtualBehaviorLink;
|
||||
}
|
||||
|
||||
public static void transformCapellaComponentExchangeIntoAADLConnections(Project project) throws Capella2AADLException {
|
||||
// Get the physical architecture from Project in Capella model
|
||||
List<ModellingArchitecture> architectures = ((SystemEngineering) (project.getOwnedModelRoots().get(0))).getOwnedArchitectures();
|
||||
PhysicalArchitecture physicalArchitecture = null;
|
||||
|
||||
for (ModellingArchitecture architecture : architectures) {
|
||||
if (architecture instanceof PhysicalArchitecture) {
|
||||
physicalArchitecture = (PhysicalArchitecture) architecture;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no physical architecture has been found, the transformation
|
||||
// doesn't apply
|
||||
if (physicalArchitecture == null) {
|
||||
throw new Capella2AADLException("Physical Architecture not found.");
|
||||
}
|
||||
|
||||
PhysicalComponent physicalSystem = physicalArchitecture.getOwnedPhysicalComponent();
|
||||
|
||||
// Index the PhysicalComponent parts (nature NODE, kind
|
||||
// SOFTWARE_EXECUTION_UNIT)
|
||||
|
||||
System.out.println("CPU/Device parts:");
|
||||
List<Part> hardwareParts = new ArrayList<>();
|
||||
|
||||
allocationOfComponentPortToPhysicalPort = new HashMap<>();
|
||||
|
||||
for (Iterator<EObject> it = physicalSystem.eAllContents(); it.hasNext();) {
|
||||
EObject eo = it.next();
|
||||
if (eo instanceof Part) {
|
||||
Part part = (Part) eo;
|
||||
AbstractType abstractType = part.getAbstractType();
|
||||
if (abstractType instanceof PhysicalComponent) {
|
||||
PhysicalComponent typeComponent = (PhysicalComponent) abstractType;
|
||||
if ((typeComponent.getKind().equals(PhysicalComponentKind.SOFTWARE_EXECUTION_UNIT) || typeComponent.getKind().equals(
|
||||
PhysicalComponentKind.HARDWARE))
|
||||
&& typeComponent.getNature().equals(PhysicalComponentNature.NODE)) {
|
||||
hardwareParts.add(part);
|
||||
System.out.println("\t" + PhysicalLinkUtils.getFullQualifiedName(part) + " (" + part.getAbstractType().getName() + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
if(eo instanceof ComponentPortAllocation) {
|
||||
ComponentPortAllocation cpa = (ComponentPortAllocation) eo;
|
||||
allocationOfComponentPortToPhysicalPort.put((ComponentPort) cpa.getTargetElement(), (PhysicalPort) cpa.getSourceElement());
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Deployed components:");
|
||||
// Build a Behavioral node to CPU/device part map
|
||||
Map<PhysicalComponent, Part> behaviourNode2Part = new HashMap<>();
|
||||
for (Part part : hardwareParts) {
|
||||
for (AbstractDeploymentLink deployableLink : part.getOwnedDeploymentLinks()) {
|
||||
DeployableElement deployableElement = deployableLink.getDeployedElement();
|
||||
if (deployableElement instanceof Part) {
|
||||
Part deployedPart = (Part) deployableElement;
|
||||
AbstractType deployedPartType = deployedPart.getAbstractType();
|
||||
if (deployedPartType instanceof PhysicalComponent) {
|
||||
PhysicalComponent deployedPhysicalComponent = (PhysicalComponent) deployedPartType;
|
||||
behaviourNode2Part.put(deployedPhysicalComponent, part);
|
||||
System.out.println("\t" + deployedPhysicalComponent.getName() + " is deployed on " + PhysicalLinkUtils.getFullQualifiedName(part));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
componentVirtualBehaviorNode = ArrayListMultimap.create();
|
||||
componentVirtualBehaviorPort = ArrayListMultimap.create();
|
||||
componentVirtualBehaviorLink = ArrayListMultimap.create();
|
||||
allocationOfVirtualLinkToPhysicalComponent = ArrayListMultimap.create();
|
||||
allocatedVirtualBehaviorLink = new ArrayList<>();
|
||||
virtualBehaviorLinkComponent = null;
|
||||
|
||||
// Fow now let's consider ComponentExchanges are all in the root
|
||||
// physical system
|
||||
for (ComponentExchange ce : physicalSystem.getOwnedComponentExchanges()) {
|
||||
// First determine which PhysicalComponent is the virtual parent of
|
||||
// the ports' containers
|
||||
ComponentPort sourcePort = (ComponentPort) ce.getSource();
|
||||
ComponentPort targetPort = (ComponentPort) ce.getTarget();
|
||||
|
||||
// Re-orient the link if needed. The sourcePort must really be the sender
|
||||
if(sourcePort.getOrientation().equals(OrientationPortKind.IN)) {
|
||||
ComponentPort tmpPort = targetPort;
|
||||
targetPort = sourcePort;
|
||||
sourcePort = tmpPort;
|
||||
}
|
||||
|
||||
boolean physicalComponentCleanUpNeeded = false;
|
||||
|
||||
System.out.println("Processing ComponentExchange " + PhysicalLinkUtils.getFullQualifiedName(sourcePort) + " <-> "
|
||||
+ PhysicalLinkUtils.getFullQualifiedName(targetPort));
|
||||
|
||||
PhysicalComponent sourcePortContainer = (PhysicalComponent) sourcePort.eContainer();
|
||||
PhysicalComponent targetPortContainer = (PhysicalComponent) targetPort.eContainer();
|
||||
|
||||
System.out.println("\tsourcePortContainer: " + PhysicalLinkUtils.getFullQualifiedName(sourcePortContainer));
|
||||
System.out.println("\ttargetPortContainer: " + PhysicalLinkUtils.getFullQualifiedName(targetPortContainer));
|
||||
// Search now the PhysicalComponent part (nature NODE, kind
|
||||
// SOFTWARE_EXECUTION_UNIT) referencing these containers
|
||||
|
||||
// The parent of this part/type is the virtual parent of the
|
||||
// ports' containers
|
||||
Part virtualSourcePortParentPart = behaviourNode2Part.get(sourcePortContainer);
|
||||
Part virtualTargetPortParentPart = behaviourNode2Part.get(targetPortContainer);
|
||||
PhysicalComponent virtualSourcePortGrandParent = null;
|
||||
PhysicalComponent virtualTargetPortGrandParent = null;
|
||||
if (virtualSourcePortParentPart != null) {
|
||||
switch (((PhysicalComponent) behaviourNode2Part.get(sourcePortContainer).getAbstractType()).getKind()) {
|
||||
case SOFTWARE_EXECUTION_UNIT: {
|
||||
virtualSourcePortGrandParent = (PhysicalComponent) behaviourNode2Part.get(sourcePortContainer).eContainer();
|
||||
break;
|
||||
}
|
||||
case HARDWARE: {
|
||||
virtualSourcePortGrandParent = (PhysicalComponent) behaviourNode2Part.get(sourcePortContainer).getAbstractType();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new Capella2AADLException("Unknown PhysicalComponent kind");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (virtualTargetPortParentPart != null) {
|
||||
switch (((PhysicalComponent) behaviourNode2Part.get(targetPortContainer).getAbstractType()).getKind()) {
|
||||
case SOFTWARE_EXECUTION_UNIT: {
|
||||
virtualTargetPortGrandParent = (PhysicalComponent) behaviourNode2Part.get(targetPortContainer).eContainer();
|
||||
break;
|
||||
}
|
||||
case HARDWARE: {
|
||||
virtualTargetPortGrandParent = (PhysicalComponent) behaviourNode2Part.get(targetPortContainer).getAbstractType();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new Capella2AADLException("Unknown PhysicalComponent kind");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (virtualSourcePortGrandParent != null && virtualTargetPortGrandParent != null) {
|
||||
|
||||
System.out.println("\tvirtualSourcePortGrandParent: " + PhysicalLinkUtils.getFullQualifiedName(virtualSourcePortGrandParent));
|
||||
System.out.println("\tvirtualTargetPortGrandParent: " + PhysicalLinkUtils.getFullQualifiedName(virtualTargetPortGrandParent));
|
||||
|
||||
PhysicalComponent virtualSourcePortParent = null;
|
||||
PhysicalComponent virtualTargetPortParent = null;
|
||||
switch (((PhysicalComponent) behaviourNode2Part.get(sourcePortContainer).getAbstractType()).getKind()) {
|
||||
case SOFTWARE_EXECUTION_UNIT: {
|
||||
virtualSourcePortParent = PaFactory.eINSTANCE.createPhysicalComponent(sourcePortContainer.getName());
|
||||
componentVirtualBehaviorNode.put(virtualSourcePortGrandParent, virtualSourcePortParent);
|
||||
virtualSourcePortGrandParent.getOwnedPhysicalComponents().add(virtualSourcePortParent);
|
||||
physicalComponentCleanUpNeeded = true;
|
||||
break;
|
||||
}
|
||||
case HARDWARE: {
|
||||
// Connect directly to the device
|
||||
virtualSourcePortParent = virtualSourcePortGrandParent;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new Capella2AADLException("Unknown PhysicalComponent kind");
|
||||
}
|
||||
}
|
||||
|
||||
switch (((PhysicalComponent) behaviourNode2Part.get(targetPortContainer).getAbstractType()).getKind()) {
|
||||
case SOFTWARE_EXECUTION_UNIT: {
|
||||
virtualTargetPortParent = PaFactory.eINSTANCE.createPhysicalComponent(targetPortContainer.getName());
|
||||
componentVirtualBehaviorNode.put(virtualTargetPortGrandParent, virtualTargetPortParent);
|
||||
virtualTargetPortGrandParent.getOwnedPhysicalComponents().add(virtualTargetPortParent);
|
||||
physicalComponentCleanUpNeeded = true;
|
||||
break;
|
||||
}
|
||||
case HARDWARE: {
|
||||
// Connect directly to the device
|
||||
virtualTargetPortParent = virtualTargetPortGrandParent;
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
throw new Capella2AADLException("Unknown PhysicalComponent kind");
|
||||
}
|
||||
}
|
||||
|
||||
// Add tip ports
|
||||
// And the property "orientation" provides the orientation of
|
||||
// the port
|
||||
StringPropertyValue outOrientationProperty = CapellacoreFactory.eINSTANCE.createStringPropertyValue("orientation");
|
||||
outOrientationProperty.setValue("out");
|
||||
StringPropertyValue inOrientationProperty = CapellacoreFactory.eINSTANCE.createStringPropertyValue("orientation");
|
||||
inOrientationProperty.setValue("in");
|
||||
|
||||
PhysicalPort virtualSourcePort = CsFactory.eINSTANCE.createPhysicalPort(sourcePort.getName());
|
||||
PhysicalPort virtualTargetPort = CsFactory.eINSTANCE.createPhysicalPort(targetPort.getName());
|
||||
virtualSourcePort.getOwnedPropertyValues().add(outOrientationProperty);
|
||||
virtualTargetPort.getOwnedPropertyValues().add(inOrientationProperty);
|
||||
|
||||
componentVirtualBehaviorPort.put(virtualSourcePortParent, virtualSourcePort);
|
||||
componentVirtualBehaviorPort.put(virtualTargetPortParent, virtualTargetPort);
|
||||
|
||||
// BEWARE: here the orginal PhysicalComponent representing a
|
||||
// device is directly modified.
|
||||
// This strategy would impact the bus topology transformation.
|
||||
// Therefore, the ComponentExchange processing
|
||||
// shall be done AFTER the bus topology.
|
||||
virtualSourcePortParent.getOwnedFeatures().add(virtualSourcePort);
|
||||
virtualTargetPortParent.getOwnedFeatures().add(virtualTargetPort);
|
||||
|
||||
// Create virtualLink
|
||||
PhysicalLink link = CsFactory.eINSTANCE.createPhysicalLink(ce.getName());
|
||||
link.getLinkEnds().add(virtualSourcePort);
|
||||
link.getLinkEnds().add(virtualTargetPort);
|
||||
|
||||
// Extracting allocation to bus
|
||||
Set<Bus> allocatingBuses = new HashSet<Bus>();
|
||||
Bus lastAllocatingBus = null;
|
||||
Bus tmpBus = PhysicalLinkUtils.getBusForPort(allocationOfComponentPortToPhysicalPort.get(sourcePort));
|
||||
if (tmpBus != null) {
|
||||
lastAllocatingBus = tmpBus;
|
||||
allocatingBuses.add(lastAllocatingBus);
|
||||
}
|
||||
tmpBus = PhysicalLinkUtils.getBusForPort(allocationOfComponentPortToPhysicalPort.get(targetPort));
|
||||
if (tmpBus != null) {
|
||||
lastAllocatingBus = tmpBus;
|
||||
allocatingBuses.add(lastAllocatingBus);
|
||||
}
|
||||
|
||||
if(allocatingBuses.size() > 1)
|
||||
{
|
||||
// Error : a link cannot be allocated to several buses
|
||||
throw new Capella2AADLException("Ports " + PhysicalLinkUtils.getFullQualifiedName(sourcePort) + " and " + PhysicalLinkUtils.getFullQualifiedName(targetPort) + " shall be allocated to the same bus");
|
||||
}
|
||||
|
||||
if(allocatingBuses.isEmpty())
|
||||
{
|
||||
// Error : a link shall be allocated to one bus
|
||||
throw new Capella2AADLException("Ports " + PhysicalLinkUtils.getFullQualifiedName(sourcePort) + " or " + PhysicalLinkUtils.getFullQualifiedName(targetPort) + " shall be allocated to a bus");
|
||||
}
|
||||
|
||||
synthesizePortsAndLinks(link, lastAllocatingBus);
|
||||
|
||||
if (physicalComponentCleanUpNeeded) {
|
||||
virtualTargetPortGrandParent.getOwnedPhysicalComponents().remove(virtualTargetPortParent);
|
||||
virtualSourcePortGrandParent.getOwnedPhysicalComponents().remove(virtualSourcePortParent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void synthesizePortsAndLinks(PhysicalLink link, Bus bus) throws Capella2AADLException {
|
||||
|
||||
// This algorithm only works if link is between a tip port and the bus
|
||||
// port.
|
||||
// In this situation, the bus is always contained in the closest common
|
||||
// ancestor of all tip ports and links are always exclusively ascending
|
||||
// in the hierarchy.
|
||||
|
||||
// Note: in Capella models, the grand parent of a PhysicalPort cannot be
|
||||
// null
|
||||
PhysicalPort sourcePort, targetPort;
|
||||
|
||||
// Origin and destination ports (links are not oriented)
|
||||
sourcePort = (PhysicalPort) link.getLinkEnds().get(0);
|
||||
targetPort = (PhysicalPort) link.getLinkEnds().get(1);
|
||||
|
||||
System.out.println(PhysicalLinkUtils.getFullQualifiedName(sourcePort) + " <-> " + PhysicalLinkUtils.getFullQualifiedName(targetPort));
|
||||
|
||||
PhysicalPort lastPort1 = createBottomUpLinks(sourcePort, targetPort, link.getName(), OrientationPortKind.OUT);
|
||||
PhysicalPort lastPort2 = createBottomUpLinks(targetPort, sourcePort, link.getName(), OrientationPortKind.IN);
|
||||
|
||||
// Now take care of the final case where ancestor = busPortGrandParent.
|
||||
// Here ports have already been created and it may only be needed to
|
||||
// connect ports. The algorithm is exactly the same as above.
|
||||
|
||||
createSyntheticLink(link.getName(), lastPort1, lastPort2, (PhysicalComponent) EcoreUtil2.getCommonAncestor(sourcePort, targetPort), bus);
|
||||
}
|
||||
|
||||
public static PhysicalPort createBottomUpLinks(PhysicalPort sourcePort, PhysicalPort targetport, String name, OrientationPortKind orientation) throws Capella2AADLException {
|
||||
PhysicalComponent ancestor = (PhysicalComponent) sourcePort.eContainer().eContainer();
|
||||
PhysicalComponent targetPortGrandParent = (PhysicalComponent) targetport.eContainer().eContainer();
|
||||
PhysicalPort origin = sourcePort;
|
||||
PhysicalPort syntheticPhysicalPort;
|
||||
|
||||
while (!EcoreUtil.isAncestor(ancestor, targetPortGrandParent)) {
|
||||
syntheticPhysicalPort = CsFactory.eINSTANCE.createPhysicalPort(name);
|
||||
componentVirtualBehaviorPort.put(ancestor, syntheticPhysicalPort);
|
||||
ancestor.getOwnedFeatures().add(syntheticPhysicalPort);
|
||||
// And the property "orientation" provides the orientation of the
|
||||
// port
|
||||
StringPropertyValue orientationProperty = CapellacoreFactory.eINSTANCE.createStringPropertyValue("orientation");
|
||||
switch(orientation) {
|
||||
case IN:
|
||||
orientationProperty.setValue("in");
|
||||
createSyntheticLink(name, syntheticPhysicalPort, origin, ancestor);
|
||||
break;
|
||||
case OUT:
|
||||
orientationProperty.setValue("out");
|
||||
createSyntheticLink(name, origin, syntheticPhysicalPort, ancestor);
|
||||
break;
|
||||
default:
|
||||
throw new Capella2AADLException("Unknown orientation");
|
||||
}
|
||||
syntheticPhysicalPort.getOwnedPropertyValues().add(orientationProperty);
|
||||
|
||||
System.out.println("Create port " + PhysicalLinkUtils.getFullQualifiedName(syntheticPhysicalPort));
|
||||
|
||||
// Move the origin to the syntheticPort, reset syntheticPort and
|
||||
// move ancestor one step upward in the hierarchy
|
||||
origin = syntheticPhysicalPort;
|
||||
ancestor = (PhysicalComponent) ancestor.eContainer();
|
||||
}
|
||||
return origin;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates a {@link PhysicalLink} between {@link PhysicalPort}
|
||||
* <code>origin</code> and <code>destination</code> and stores it in
|
||||
* {@link PhysicalComponent} <code>ancestor</code> only if no such link
|
||||
* already exists.
|
||||
*
|
||||
* @param prefix
|
||||
* Name of the new link
|
||||
* @param origin
|
||||
* Port of origin
|
||||
* @param destination
|
||||
* Port of destination
|
||||
* @param ancestor
|
||||
* Container of the new link
|
||||
*/
|
||||
private static void createSyntheticLink(String prefix, PhysicalPort origin, PhysicalPort destination, PhysicalComponent ancestor) {
|
||||
createSyntheticLink(prefix, origin, destination, ancestor, null);
|
||||
}
|
||||
|
||||
private static void createSyntheticLink(String prefix, PhysicalPort origin, PhysicalPort destination, PhysicalComponent ancestor, Bus allocatedTo) {
|
||||
boolean needToCreateNewLink = true;
|
||||
for (PhysicalLink l : componentVirtualBehaviorLink.get(ancestor)) {
|
||||
if ((l.getLinkEnds().get(0).equals(destination) && l.getLinkEnds().get(1).equals(origin))
|
||||
|| (l.getLinkEnds().get(0).equals(origin) && l.getLinkEnds().get(1).equals(destination))) {
|
||||
needToCreateNewLink = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (needToCreateNewLink) {
|
||||
PhysicalLink syntheticPhysicalLink = CsFactory.eINSTANCE.createPhysicalLink(prefix + "_" + (componentVirtualBehaviorLink.get(ancestor).size() + 1));
|
||||
syntheticPhysicalLink.getLinkEnds().add(origin);
|
||||
syntheticPhysicalLink.getLinkEnds().add(destination);
|
||||
componentVirtualBehaviorLink.put(ancestor, syntheticPhysicalLink);
|
||||
|
||||
if(allocatedTo != null) {
|
||||
// The property "allocatedToBus" provides the name of the bus instance the link is allocated to
|
||||
StringPropertyValue busName = CapellacoreFactory.eINSTANCE.createStringPropertyValue("allocatedToBus");
|
||||
busName.setValue(allocatedTo.getName());
|
||||
syntheticPhysicalLink.getOwnedPropertyValues().add(busName);
|
||||
allocationOfVirtualLinkToPhysicalComponent.put(allocatedTo.getName(), syntheticPhysicalLink);
|
||||
allocatedVirtualBehaviorLink.add(syntheticPhysicalLink);
|
||||
}
|
||||
|
||||
System.out.println("Create synthetic link: " + PhysicalLinkUtils.getFullQualifiedName(origin) + " <-> "
|
||||
+ PhysicalLinkUtils.getFullQualifiedName(destination));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,637 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2015, 2017 IRT AESE (IRT Saint Exupery).
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Bassem Ouni and Pierre Gaufillet (IRT Saint Exupéry) - initial API and implementation
|
||||
*
|
||||
*******************************************************************************/
|
||||
package com.irtsaintexupery.capella2aadl.requests;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.emf.ecore.util.EcoreUtil;
|
||||
import org.polarsys.capella.common.helpers.EcoreUtil2;
|
||||
import org.polarsys.capella.core.data.capellacore.AbstractPropertyValue;
|
||||
import org.polarsys.capella.core.data.capellacore.BooleanPropertyValue;
|
||||
import org.polarsys.capella.core.data.capellacore.CapellaElement;
|
||||
import org.polarsys.capella.core.data.capellacore.CapellacoreFactory;
|
||||
import org.polarsys.capella.core.data.capellacore.Feature;
|
||||
import org.polarsys.capella.core.data.capellacore.ModellingArchitecture;
|
||||
import org.polarsys.capella.core.data.capellacore.NamedElement;
|
||||
import org.polarsys.capella.core.data.capellacore.StringPropertyValue;
|
||||
import org.polarsys.capella.core.data.capellamodeller.Project;
|
||||
import org.polarsys.capella.core.data.capellamodeller.SystemEngineering;
|
||||
import org.polarsys.capella.core.data.cs.AbstractPhysicalLinkEnd;
|
||||
import org.polarsys.capella.core.data.cs.CsFactory;
|
||||
import org.polarsys.capella.core.data.cs.PhysicalLink;
|
||||
import org.polarsys.capella.core.data.cs.PhysicalPort;
|
||||
import org.polarsys.capella.core.data.pa.PaFactory;
|
||||
import org.polarsys.capella.core.data.pa.PhysicalArchitecture;
|
||||
import org.polarsys.capella.core.data.pa.PhysicalComponent;
|
||||
import org.polarsys.capella.core.data.pa.PhysicalComponentNature;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
|
||||
/**
|
||||
* This class provides various static methods for transforming Capella physical
|
||||
* architecture into a preliminary but yet complete AADL model. The main
|
||||
* transformation consists in moving from the 1 to 1 communication model used by
|
||||
* {@link PhysicalLink} to a bus oriented topology closer to AADL bus accesses
|
||||
*
|
||||
*/
|
||||
public class PhysicalLinkUtils {
|
||||
|
||||
/**
|
||||
* Reversible map between deduced buses and origin/destination
|
||||
* {@link PhysicalPort}
|
||||
*/
|
||||
private static BiMap<Bus, Set<PhysicalPort>> bus2TipPorts = null;
|
||||
|
||||
/**
|
||||
* Cross-reference from {@link PhysicalPort} to {@link PhysicalLink}
|
||||
* connected to these ports
|
||||
*/
|
||||
private static ArrayListMultimap<PhysicalPort, PhysicalLink> port2link = null;
|
||||
|
||||
/**
|
||||
* All {@link PhysicalLink} in the model
|
||||
*/
|
||||
private static List<PhysicalLink> physicalLinks = null;
|
||||
|
||||
/**
|
||||
* List of {@link PhysicalPort} to synthesize for each
|
||||
* {@link PhysicalComponent}
|
||||
*/
|
||||
private static ArrayListMultimap<PhysicalComponent, PhysicalPort> componentSyntheticPorts = null;
|
||||
|
||||
/**
|
||||
* Cross-reference from {@link PhysicalPort} to the bus they are connected
|
||||
* to
|
||||
*/
|
||||
private static Map<PhysicalPort, Bus> componentSyntheticPorts2Bus = null;
|
||||
|
||||
/**
|
||||
* List of {@link PhysicalLink} to synthesize for each
|
||||
* {@link PhysicalComponent}
|
||||
*/
|
||||
private static ArrayListMultimap<PhysicalComponent, PhysicalLink> componentSyntheticLinks = null;
|
||||
|
||||
/**
|
||||
* Numbering counter for default bus types
|
||||
*/
|
||||
private static int defaultBusTypeCounter;
|
||||
|
||||
/**
|
||||
* @param pc
|
||||
* target {@link PhysicalComponent}
|
||||
* @return the list of synthetic ports for component <code>pc</code>
|
||||
*/
|
||||
public static List<PhysicalPort> getSyntheticPorts(PhysicalComponent pc) {
|
||||
return componentSyntheticPorts.get(pc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pc
|
||||
* target {@link PhysicalComponent}
|
||||
* @return the list of synthetic links for component <code>pc</code>
|
||||
*/
|
||||
public static List<PhysicalLink> getSyntheticLinks(PhysicalComponent pc) {
|
||||
return componentSyntheticLinks.get(pc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param port
|
||||
* target {@link PhysicalPort}
|
||||
* @return the type name of the bus connected to <code>port</code>
|
||||
*/
|
||||
public static String getBusTypeForPort(PhysicalPort port) {
|
||||
return componentSyntheticPorts2Bus.get(port).getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param port
|
||||
* target {@link PhysicalPort}
|
||||
* @return the bus connected to <code>port</code>
|
||||
*/
|
||||
public static Bus getBusForPort(PhysicalPort port) {
|
||||
return componentSyntheticPorts2Bus.get(port);
|
||||
}
|
||||
|
||||
/**
|
||||
* This methode analyses the data flows and hierarchy of
|
||||
* {@link PhysicalComponent} of the physical architecture and synthesizes a
|
||||
* corresponding bus topology.
|
||||
*
|
||||
* @param project
|
||||
* Capella {@link Project} that is analyzed
|
||||
* @throws Capella2AADLException
|
||||
*/
|
||||
public static void transformCapellaPhysicalLinksIntoAADLBusTopology(Project project) throws Capella2AADLException {
|
||||
|
||||
// (Re-)init Bus class attributes and bus type counter
|
||||
Bus.init();
|
||||
defaultBusTypeCounter = 1;
|
||||
|
||||
// Get the physical architecture from Project in Capella model
|
||||
List<ModellingArchitecture> architectures = ((SystemEngineering) (project.getOwnedModelRoots().get(0))).getOwnedArchitectures();
|
||||
PhysicalArchitecture physicalArchitecture = null;
|
||||
|
||||
for (ModellingArchitecture architecture : architectures) {
|
||||
if (architecture instanceof PhysicalArchitecture) {
|
||||
physicalArchitecture = (PhysicalArchitecture) architecture;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no physical architecture has been found, the transformation
|
||||
// doesn't apply
|
||||
if (physicalArchitecture == null) {
|
||||
throw new Capella2AADLException("Physical Architecture not found.");
|
||||
}
|
||||
|
||||
PhysicalComponent physicalSystem = physicalArchitecture.getOwnedPhysicalComponent();
|
||||
|
||||
// Visit the model and connect internally PhysicalPorts of PhysicalComponents
|
||||
// when they share the same virtualConnection string property value
|
||||
// Thanks to the preprocessing, it is possible to consider low level
|
||||
// communication device like transceivers, routers, switch, etc. as physically connecting
|
||||
// some of their ports.
|
||||
|
||||
for (Iterator<EObject> it = physicalSystem.eAllContents(); it.hasNext();) {
|
||||
EObject eo = it.next();
|
||||
if (eo instanceof PhysicalComponent) {
|
||||
PhysicalComponent pc = (PhysicalComponent) eo;
|
||||
ArrayListMultimap<String, PhysicalPort> map = ArrayListMultimap.create();
|
||||
for(Feature feature: pc.getOwnedFeatures()) {
|
||||
if (feature instanceof PhysicalPort) {
|
||||
PhysicalPort pp = (PhysicalPort) feature;
|
||||
for(AbstractPropertyValue pv: pp.getAppliedPropertyValues()) {
|
||||
if(pv.getName().equals("virtualConnection")) {
|
||||
map.put(((StringPropertyValue) pv).getValue(), pp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Now that the list of ports is known, create a chain with all ports of each virtualConnection
|
||||
for(String virtualConnection: map.keySet()) {
|
||||
int counter = 1;
|
||||
Iterator<PhysicalPort> pp_it = map.get(virtualConnection).iterator();
|
||||
PhysicalPort origin = pp_it.next();
|
||||
PhysicalPort dest = null;
|
||||
PhysicalLink link = null;
|
||||
while(pp_it.hasNext()) {
|
||||
dest = pp_it.next();
|
||||
link = CsFactory.eINSTANCE.createPhysicalLink(virtualConnection + "_" + counter);
|
||||
link.getLinkEnds().add(origin);
|
||||
link.getLinkEnds().add(dest);
|
||||
PhysicalComponent parentComponent = (PhysicalComponent) origin.eContainer();
|
||||
parentComponent.getOwnedPhysicalLinks().add(link);
|
||||
System.out.println("Creating virtual connection "
|
||||
+ virtualConnection + "_" + counter + " in "
|
||||
+ getFullQualifiedName(parentComponent) + ": "
|
||||
+ origin.getName() + " <-> " + dest.getName());
|
||||
if(pp_it.hasNext()) {
|
||||
origin = dest;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extract the list of physical ports, physical links and a cross
|
||||
// reference between
|
||||
// physical ports and physical links
|
||||
|
||||
physicalLinks = new ArrayList<PhysicalLink>();
|
||||
port2link = ArrayListMultimap.create();
|
||||
|
||||
for (Iterator<EObject> it = physicalSystem.eAllContents(); it.hasNext();) {
|
||||
EObject eo = it.next();
|
||||
if (eo instanceof PhysicalLink) {
|
||||
PhysicalLink link = (PhysicalLink) eo;
|
||||
physicalLinks.add(link);
|
||||
port2link.put((PhysicalPort) link.getLinkEnds().get(0), link);
|
||||
port2link.put((PhysicalPort) link.getLinkEnds().get(1), link);
|
||||
}
|
||||
}
|
||||
|
||||
// Now extract the origin and destination ports (aka tipPorts) for each
|
||||
// set of links (PhysicalLink) connected through ports (PhysicalPort)
|
||||
|
||||
bus2TipPorts = HashBiMap.create();
|
||||
|
||||
// Each PhysicalLink shall be visited once. Initialize the list of links
|
||||
// to visit
|
||||
List<PhysicalLink> linksToVisit = new ArrayList<PhysicalLink>(physicalLinks);
|
||||
|
||||
// allConnectedLinks is a list of sets of PhysicalLink connected by
|
||||
// PhysicalPorts. Sets of links are never connected. Each set will lead
|
||||
// to an AADL bus instance
|
||||
ArrayDeque<Set<PhysicalLink>> allConnectedLinks = new ArrayDeque<Set<PhysicalLink>>();
|
||||
|
||||
Set<PhysicalPort> ports;
|
||||
while (!linksToVisit.isEmpty()) {
|
||||
ports = new HashSet<>();
|
||||
allConnectedLinks.add(extractConnectedPhysicalLinks(linksToVisit.get(0), ports));
|
||||
|
||||
// Now that connected links and ports have been discovered, identify
|
||||
// the type of the bus. By convention, this type is hold by a
|
||||
// PhysicalLinkCategory associated with at least one connected link
|
||||
String categoryName = null;
|
||||
for (PhysicalLink l : allConnectedLinks.peekLast()) {
|
||||
if (!l.getCategories().isEmpty()) {
|
||||
categoryName = l.getCategories().get(0).getName();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no category has been found, use a default name
|
||||
if (categoryName == null) {
|
||||
categoryName = "BusType_" + defaultBusTypeCounter;
|
||||
defaultBusTypeCounter++;
|
||||
}
|
||||
|
||||
// Gather all these information together
|
||||
// the bus instance is named by its category + an increment
|
||||
Bus bus = Bus.createIncrementedNameFromCategory(categoryName);
|
||||
|
||||
// Associate the bus with its tip ports
|
||||
bus2TipPorts.put(bus, ports);
|
||||
|
||||
// all the connected links has been visited in the process. They can
|
||||
// be removed at once from the list of links that still need to be
|
||||
// visited.
|
||||
linksToVisit.removeAll(allConnectedLinks.peekLast());
|
||||
}
|
||||
|
||||
printTipPorts2Bus();
|
||||
|
||||
// Now that the original topology of PhysicalLinks is known, synthesize
|
||||
// a new one compatible with AADL. By convention, a new
|
||||
// PhysicalComponent with specific key/values will be created in the
|
||||
// lowest ancestor of all tip ports.
|
||||
|
||||
componentSyntheticPorts = ArrayListMultimap.create();
|
||||
componentSyntheticLinks = ArrayListMultimap.create();
|
||||
|
||||
// Initialize the list of synthetic ports with the tip ports
|
||||
// Only one port / component / bus should be kept
|
||||
componentSyntheticPorts2Bus = new HashMap<>();
|
||||
for (Set<PhysicalPort> sp : bus2TipPorts.inverse().keySet()) {
|
||||
for (PhysicalPort p : sp) {
|
||||
if (!componentSyntheticPorts.containsValue(p)) {
|
||||
componentSyntheticPorts2Bus.put(p, bus2TipPorts.inverse().get(sp));
|
||||
componentSyntheticPorts.put((PhysicalComponent) p.eContainer(), p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Bus bus : bus2TipPorts.keySet()) {
|
||||
// First discover the closest common ancestor of all tipPorts
|
||||
PhysicalComponent commonAncestor = (PhysicalComponent) EcoreUtil2.getCommonAncestor(bus2TipPorts.get(bus));
|
||||
|
||||
// Create the PhysicalComponent that will play the role of bus
|
||||
// instance
|
||||
PhysicalComponent busPhysicalComponent = PaFactory.eINSTANCE.createPhysicalComponent(bus.getType());
|
||||
busPhysicalComponent.setNature(PhysicalComponentNature.NODE);
|
||||
|
||||
// The property "isBus" acts as a marker to process differently this
|
||||
// PhysicalComponent in Acceleo
|
||||
BooleanPropertyValue isBus = CapellacoreFactory.eINSTANCE.createBooleanPropertyValue("isBus");
|
||||
isBus.setValue(true);
|
||||
busPhysicalComponent.getOwnedPropertyValues().add(isBus);
|
||||
|
||||
// And the property "busName" provides the name of the bus instance
|
||||
StringPropertyValue busName = CapellacoreFactory.eINSTANCE.createStringPropertyValue("busName");
|
||||
busName.setValue(bus.getName());
|
||||
busPhysicalComponent.getOwnedPropertyValues().add(busName);
|
||||
|
||||
// Add a port to the bus instance to connect synthetic links to it
|
||||
PhysicalPort port = CsFactory.eINSTANCE.createPhysicalPort("bus_port");
|
||||
busPhysicalComponent.getOwnedFeatures().add(port);
|
||||
|
||||
// And finally add the bus instance to the common ancestor
|
||||
commonAncestor.getOwnedPhysicalComponents().add(busPhysicalComponent);
|
||||
|
||||
// Synthesize now the new PhysicalLinks. It is done in 2 steps:
|
||||
// 1- Create a link from tip port to bus_port
|
||||
// 2- Split this link into segments that don't cross
|
||||
// PhysicalComponent boundaries
|
||||
// The second step involves synthesize intermediate PhysicalPorts on
|
||||
// intermediate PhysicalComponents
|
||||
for (PhysicalPort p : bus2TipPorts.get(bus)) {
|
||||
PhysicalLink l = CsFactory.eINSTANCE.createPhysicalLink(bus.getName());
|
||||
l.getLinkEnds().add(p);
|
||||
l.getLinkEnds().add(port);
|
||||
synthesizePortsAndLinks(l, bus);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
printSyntheticPorts();
|
||||
printSyntheticLinks();
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print synthetic links by {@link PhysicalComponent} on stdout for
|
||||
* debugging purpose
|
||||
*/
|
||||
private static void printSyntheticLinks() {
|
||||
System.out.println("\nSynthetic Links:");
|
||||
for (PhysicalComponent c : componentSyntheticLinks.keySet()) {
|
||||
System.out.println(getFullQualifiedName(c) + ":");
|
||||
for (PhysicalLink l : componentSyntheticLinks.get(c)) {
|
||||
System.out.println("\t" + getFullQualifiedName(l.getLinkEnds().get(0)) + " <-> " + getFullQualifiedName(l.getLinkEnds().get(1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print synthetic ports by {@link PhysicalComponent} on stdout for
|
||||
* debugging purpose
|
||||
*/
|
||||
private static void printSyntheticPorts() {
|
||||
System.out.println("Synthetic Ports:");
|
||||
for (PhysicalComponent c : componentSyntheticPorts.keySet()) {
|
||||
System.out.println(getFullQualifiedName(c) + ":");
|
||||
for (PhysicalPort p : componentSyntheticPorts.get(c)) {
|
||||
System.out.println("\t" + getFullQualifiedName(p));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method analyzes the {@link PhysicalLink} link and if required splits
|
||||
* it into several links connected by new intermediate ports that don't
|
||||
* violate the encapsulation principle of AADL.
|
||||
*
|
||||
* @param link
|
||||
* the link that will be analyzed
|
||||
* @param bus
|
||||
* the bus <code>link</code> connects to
|
||||
*/
|
||||
private static void synthesizePortsAndLinks(PhysicalLink link, Bus bus) {
|
||||
|
||||
// This algorithm only works if link is between a tip port and the bus
|
||||
// port.
|
||||
// In this situation, the bus is always contained in the closest common
|
||||
// ancestor of all tip ports and links are always exclusively ascending
|
||||
// in the hierarchy.
|
||||
|
||||
// Note: in Capella models, the grand parent of a PhysicalPort cannot be
|
||||
// null
|
||||
PhysicalPort tipPort, bus_port;
|
||||
|
||||
// Origin and destination ports (links are not oriented)
|
||||
tipPort = (PhysicalPort) link.getLinkEnds().get(0);
|
||||
bus_port = (PhysicalPort) link.getLinkEnds().get(1);
|
||||
|
||||
System.out.println(getFullQualifiedName(tipPort) + " <-> " + getFullQualifiedName(bus_port));
|
||||
|
||||
PhysicalComponent ancestor = (PhysicalComponent) tipPort.eContainer().eContainer();
|
||||
PhysicalComponent busPortGrandParent = (PhysicalComponent) bus_port.eContainer().eContainer();
|
||||
PhysicalPort origin = tipPort;
|
||||
PhysicalPort syntheticPhysicalPort = null;
|
||||
|
||||
while (!ancestor.equals(busPortGrandParent)) {
|
||||
|
||||
// Ancestor needs one and only one Physical port to connect to the
|
||||
// bus. If a such port already exists, use it rather than create a
|
||||
// new one.
|
||||
for (PhysicalPort p : componentSyntheticPorts.get(ancestor)) {
|
||||
if (componentSyntheticPorts2Bus.containsKey(p)) {
|
||||
if (componentSyntheticPorts2Bus.get(p).equals(bus)) {
|
||||
syntheticPhysicalPort = p;
|
||||
System.out.println("Component " + getFullQualifiedName(ancestor) + " already contains the synthetic port " + getFullQualifiedName(p)
|
||||
+ " for bus " + bus.getName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No port connected to the bus has been found. Create a new one.
|
||||
if (syntheticPhysicalPort == null) {
|
||||
syntheticPhysicalPort = CsFactory.eINSTANCE.createPhysicalPort(link.getName());
|
||||
componentSyntheticPorts.put(ancestor, syntheticPhysicalPort);
|
||||
componentSyntheticPorts2Bus.put(syntheticPhysicalPort, bus);
|
||||
ancestor.getOwnedFeatures().add(syntheticPhysicalPort);
|
||||
System.out.println("Component " + getFullQualifiedName(ancestor) + " doesn't contain a synthetic port for bus " + bus.getName()
|
||||
+ ": create port " + getFullQualifiedName(syntheticPhysicalPort));
|
||||
}
|
||||
|
||||
createSyntheticLink(link.getName(), origin, syntheticPhysicalPort, ancestor);
|
||||
|
||||
// Move the origin to the syntheticPort, reset syntheticPort and
|
||||
// move ancestor one step upward in the hierarchy
|
||||
origin = syntheticPhysicalPort;
|
||||
syntheticPhysicalPort = null;
|
||||
ancestor = (PhysicalComponent) ancestor.eContainer();
|
||||
}
|
||||
|
||||
// Now take care of the final case where ancestor = busPortGrandParent.
|
||||
// Here ports have already been created and it may only be needed to
|
||||
// connect ports. The algorithm is exactly the same as above.
|
||||
createSyntheticLink(link.getName(), origin, bus_port, ancestor);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates a {@link PhysicalLink} between {@link PhysicalPort}
|
||||
* <code>origin</code> and <code>destination</code> and stores it in
|
||||
* {@link PhysicalComponent} <code>ancestor</code> only if no such link
|
||||
* already exists.
|
||||
*
|
||||
* @param prefix
|
||||
* Name of the new link
|
||||
* @param origin
|
||||
* Port of origin
|
||||
* @param destination
|
||||
* Port of destination
|
||||
* @param ancestor
|
||||
* Container of the new link
|
||||
*/
|
||||
private static void createSyntheticLink(String prefix, PhysicalPort origin, PhysicalPort destination, PhysicalComponent ancestor) {
|
||||
boolean needToCreateNewLink = true;
|
||||
for (PhysicalLink l : componentSyntheticLinks.get(ancestor)) {
|
||||
if ((l.getLinkEnds().get(0).equals(destination) && l.getLinkEnds().get(1).equals(origin))
|
||||
|| (l.getLinkEnds().get(0).equals(origin) && l.getLinkEnds().get(1).equals(destination))) {
|
||||
needToCreateNewLink = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (needToCreateNewLink) {
|
||||
PhysicalLink syntheticPhysicalLink = CsFactory.eINSTANCE.createPhysicalLink(prefix + "_" + (componentSyntheticLinks.get(ancestor).size() + 1));
|
||||
syntheticPhysicalLink.getLinkEnds().add(origin);
|
||||
syntheticPhysicalLink.getLinkEnds().add(destination);
|
||||
componentSyntheticLinks.put(ancestor, syntheticPhysicalLink);
|
||||
System.out.println("Create synthetic link: " + getFullQualifiedName(origin) + " <-> " + getFullQualifiedName(destination));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print origin/destination ports by bus on stdout for debugging purpose
|
||||
*/
|
||||
private static void printTipPorts2Bus() {
|
||||
for (Bus b : bus2TipPorts.keySet()) {
|
||||
System.out.println(b.getName() + ": " + b.getType());
|
||||
for (PhysicalPort p : bus2TipPorts.get(b))
|
||||
System.out.println("\t" + getFullQualifiedName(p));
|
||||
System.out.println("");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the list of {@link PhysicalLink} connected by
|
||||
* {@link PhysicalPort} from <code>link</code> along with the list of
|
||||
* origin/destination ports.
|
||||
*
|
||||
* @param link
|
||||
* the link that is analyzed
|
||||
* @param tipPorts
|
||||
* the list of origin/destination ports
|
||||
* @return
|
||||
*/
|
||||
private static Set<PhysicalLink> extractConnectedPhysicalLinks(PhysicalLink link, Set<PhysicalPort> tipPorts) {
|
||||
|
||||
Set<PhysicalLink> connectedLinks = new HashSet<PhysicalLink>();
|
||||
extractConnectedPhysicalLinks(link, connectedLinks, tipPorts);
|
||||
return connectedLinks;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the list of {@link PhysicalLink} connected by
|
||||
* {@link PhysicalPort} from <code>link</code> and updates the list of
|
||||
* origin/destination ports + the list of visited links.
|
||||
*
|
||||
* @param link
|
||||
* the link that is analyzed
|
||||
* @param visitedLinks
|
||||
* the list of links already analyzed.
|
||||
* <em>This list is updated by the method.</em>
|
||||
* @param tipPorts
|
||||
* the list of origin/destination ports.
|
||||
* <em>This list is updated by the method.</em>
|
||||
*/
|
||||
private static void extractConnectedPhysicalLinks(PhysicalLink link, Set<PhysicalLink> visitedLinks, Set<PhysicalPort> tipPorts) {
|
||||
// link is about to be analyzed. Add it to the list of visited links
|
||||
visitedLinks.add(link);
|
||||
|
||||
// The principle of this method is to explore recursively each link
|
||||
// connected to the origin or destination port of link
|
||||
List<PhysicalLink> linksToVisit = new ArrayList<>();
|
||||
|
||||
// First, determine for each port connected to link if it is a tip.
|
||||
// A port is a tip if its container either contains all containers of
|
||||
// the
|
||||
// other ports or none of them.
|
||||
for (AbstractPhysicalLinkEnd le : link.getLinkEnds()) {
|
||||
PhysicalPort p = (PhysicalPort) le;
|
||||
linksToVisit.addAll(port2link.get(p));
|
||||
|
||||
Set<PhysicalComponent> portsParents = new HashSet<>();
|
||||
for (PhysicalLink l : port2link.get(p)) {
|
||||
PhysicalPort oppositePort;
|
||||
|
||||
// Consider only the opposite port of p on link l
|
||||
if (l.getLinkEnds().get(0).equals(le)) {
|
||||
oppositePort = (PhysicalPort) l.getLinkEnds().get(1);
|
||||
} else {
|
||||
oppositePort = (PhysicalPort) l.getLinkEnds().get(0);
|
||||
}
|
||||
|
||||
portsParents.add((PhysicalComponent) oppositePort.eContainer());
|
||||
}
|
||||
|
||||
PhysicalComponent pParent = (PhysicalComponent) p.eContainer();
|
||||
boolean allParentsAreInsidePContainer = true;
|
||||
boolean allParentsAreOutsidePContainer = true;
|
||||
for (PhysicalComponent c : portsParents) {
|
||||
if (!EcoreUtil.isAncestor(pParent, c))
|
||||
allParentsAreInsidePContainer = false;
|
||||
else
|
||||
allParentsAreOutsidePContainer = false;
|
||||
}
|
||||
|
||||
if (allParentsAreInsidePContainer || allParentsAreOutsidePContainer)
|
||||
tipPorts.add(p);
|
||||
}
|
||||
|
||||
// Remove already visited links and continue exploration with neighbor
|
||||
// links
|
||||
linksToVisit.removeAll(visitedLinks);
|
||||
|
||||
for (PhysicalLink l : linksToVisit) {
|
||||
extractConnectedPhysicalLinks(l, visitedLinks, tipPorts);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the path from root {@link PhysicalComponent} using '::' separator
|
||||
* as the fully qualified name of <code>object</code>.
|
||||
* <p>
|
||||
* eg: <code>getFullQualifiedName(subsubsystem_3)</code> returns
|
||||
* <code>Root::system_1::subsystem_2::subsubsystem_3</code>
|
||||
*
|
||||
* @param object
|
||||
* the targeted object
|
||||
* @return the fully qualified name of <code>object</code>
|
||||
*/
|
||||
public static String getFullQualifiedName(EObject object) {
|
||||
EObject parent = object.eContainer();
|
||||
if (!(parent instanceof PhysicalComponent))
|
||||
return ((NamedElement) object).getName();
|
||||
else
|
||||
return getFullQualifiedName((PhysicalComponent) parent) + "::" + ((NamedElement) object).getName();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the instance path of <code>target</code> from origin {@link PhysicalComponent} using '.' separator.
|
||||
* <p>
|
||||
* eg: <code>getVirtualBehaviorLinkRelativeInstancePath(subsubsystem_3, root_system)</code> returns
|
||||
* <code>system_1_part.subsystem_2_part.subsubsystem_3</code>
|
||||
*
|
||||
* Used for <code>Actual_Connection_Binding</code> when the bus instance is not in the same container.
|
||||
*
|
||||
* @param target
|
||||
* @param origin
|
||||
* @return
|
||||
*/
|
||||
public static String getVirtualBehaviorLinkRelativeInstancePath(CapellaElement target, PhysicalComponent origin) {
|
||||
EObject parent = null;
|
||||
if(target instanceof PhysicalLink) {
|
||||
Collection<PhysicalComponent> parents = ComponentExchangeUtils.getVirtualBehaviorLinkComponent((PhysicalLink) target);
|
||||
if(parents.size() == 1) {
|
||||
parent = (CapellaElement) parents.toArray() [0];
|
||||
}
|
||||
} else {
|
||||
parent = target.eContainer();
|
||||
}
|
||||
if (parent.equals(origin)) {
|
||||
return ((NamedElement) target).getName().toLowerCase().replace(' ', '_');
|
||||
} else {
|
||||
if (!(parent instanceof PhysicalComponent))
|
||||
return null; // TODO Improve error handling
|
||||
else
|
||||
return getVirtualBehaviorLinkRelativeInstancePath((PhysicalComponent) parent,
|
||||
origin) + "_part." + ((NamedElement) target).getName().toLowerCase().replace(' ', '_');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
[comment encoding = UTF-8 /]
|
||||
[**
|
||||
* Copyright (c) 2015, 2017 IRT AESE (IRT Saint Exupery).
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Bassem Ouni and Pierre Gaufillet (IRT Saint Exupéry) - initial API and implementation
|
||||
*
|
||||
*/]
|
||||
[module capella2aadl_queries('http://www.polarsys.org/capella/core/pa/1.1.0','http://www.polarsys.org/capella/core/core/1.1.0','http://www.polarsys.org/capella/core/modeller/1.1.0','http://www.polarsys.org/capella/common/libraries/1.1.0','http://www.polarsys.org/capella/common/core/1.1.0','http://www.polarsys.org/capella/core/common/1.1.0', 'http://www.polarsys.org/capella/core/cs/1.1.0', 'http://www.polarsys.org/capella/core/fa/1.1.0')]
|
||||
|
||||
|
||||
[**
|
||||
* The documentation of the query getPortDirection.
|
||||
* @param anOrientationPortKind
|
||||
*/]
|
||||
[query public getPortDirection(o : OrientationPortKind) : String = if(o=OrientationPortKind::IN) then 'in' else if(o=OrientationPortKind::OUT) then 'out' else '' endif endif/]
|
||||
|
||||
[query public getAADLNature(sc: PhysicalComponent) : String = if(sc.ownedPropertyValues->select(name='isBus')->notEmpty()) then 'bus' else if(sc.kind=PhysicalComponentKind::SOFTWARE_EXECUTION_UNIT) then 'processor' else if (sc.kind=PhysicalComponentKind::HARDWARE) then 'device' else if(sc.nature = PhysicalComponentNature::BEHAVIOR) then 'process' else 'system' endif endif endif endif/]
|
||||
|
||||
[query public getStringPropertyValue(ce: CapellaElement, key: String) : String = ce.ownedPropertyValues->select(name=key)->at(1).oclAsType(StringPropertyValue).value/]
|
||||
|
||||
[query public hasPropertyValue(ce: CapellaElement, key: String) : Boolean = ce.ownedPropertyValues->select(name=key)->notEmpty()/]
|
||||
|
||||
[query public transformCapellaPhysicalLinksIntoAADLBusTopology(project: Project) : OclVoid =
|
||||
invoke('com.irtsaintexupery.capella2aadl.requests.PhysicalLinkUtils', 'transformCapellaPhysicalLinksIntoAADLBusTopology(org.polarsys.capella.core.data.capellamodeller.Project)', Sequence{project})
|
||||
/]
|
||||
|
||||
[query public transformCapellaComponentExchangeIntoAADLConnections(project: Project) : OclVoid =
|
||||
invoke('com.irtsaintexupery.capella2aadl.requests.ComponentExchangeUtils', 'transformCapellaComponentExchangeIntoAADLConnections(org.polarsys.capella.core.data.capellamodeller.Project)', Sequence{project})
|
||||
/]
|
||||
|
||||
[query public getFullQualifiedName(elt: NamedElement) : String =
|
||||
invoke('com.irtsaintexupery.capella2aadl.requests.PhysicalLinkUtils', 'getFullQualifiedName(org.polarsys.capella.core.data.capellacore.NamedElement)', Sequence{elt})
|
||||
/]
|
||||
|
||||
[query public getVirtualBehaviorLinkRelativeInstancePath(target: CapellaElement, origin: PhysicalComponent) : String =
|
||||
invoke('com.irtsaintexupery.capella2aadl.requests.PhysicalLinkUtils', 'getVirtualBehaviorLinkRelativeInstancePath(org.polarsys.capella.core.data.capellacore.CapellaElement, org.polarsys.capella.core.data.pa.PhysicalComponent)', Sequence{target, origin})
|
||||
/]
|
||||
|
||||
[query public getBusNames(project: Project) : Set(String) =
|
||||
invoke('com.irtsaintexupery.capella2aadl.requests.Bus', 'getBusNames(org.polarsys.capella.core.data.capellamodeller.Project)', Sequence{project})
|
||||
/]
|
||||
|
||||
[query public getSyntheticPorts(pc: PhysicalComponent) : Sequence(PhysicalPort) =
|
||||
invoke('com.irtsaintexupery.capella2aadl.requests.PhysicalLinkUtils', 'getSyntheticPorts(org.polarsys.capella.core.data.pa.PhysicalComponent)', Sequence{pc})
|
||||
/]
|
||||
|
||||
[query public getSyntheticLinks(pc: PhysicalComponent) : Sequence(PhysicalLink) =
|
||||
invoke('com.irtsaintexupery.capella2aadl.requests.PhysicalLinkUtils', 'getSyntheticLinks(org.polarsys.capella.core.data.pa.PhysicalComponent)', Sequence{pc})
|
||||
/]
|
||||
|
||||
[query public getBusTypeForPort(pp: PhysicalPort) : String =
|
||||
invoke('com.irtsaintexupery.capella2aadl.requests.PhysicalLinkUtils', 'getBusTypeForPort(org.polarsys.capella.core.data.cs.PhysicalPort)', Sequence{pp})
|
||||
/]
|
||||
|
||||
[query public getComponentVirtualBehaviorPort(pc: PhysicalComponent) : Sequence(PhysicalPort) =
|
||||
invoke('com.irtsaintexupery.capella2aadl.requests.ComponentExchangeUtils', 'getComponentVirtualBehaviorPort(org.polarsys.capella.core.data.pa.PhysicalComponent)', Sequence{pc})
|
||||
/]
|
||||
|
||||
[query public getComponentVirtualBehaviorLink(pc: PhysicalComponent) : Sequence(PhysicalLink) =
|
||||
invoke('com.irtsaintexupery.capella2aadl.requests.ComponentExchangeUtils', 'getComponentVirtualBehaviorLink(org.polarsys.capella.core.data.pa.PhysicalComponent)', Sequence{pc})
|
||||
/]
|
||||
|
||||
[query public getBusVirtualBehaviorLink(bus: String) : Sequence(PhysicalLink) =
|
||||
invoke('com.irtsaintexupery.capella2aadl.requests.ComponentExchangeUtils', 'getBusVirtualBehaviorLink(String)', Sequence{bus})
|
||||
/]
|
||||
|
||||
[query public getAllocatedVirtualBehaviorLink(pc: PhysicalComponent) : Sequence(PhysicalLink) =
|
||||
invoke('com.irtsaintexupery.capella2aadl.requests.ComponentExchangeUtils', 'getAllocatedVirtualBehaviorLink()', Sequence{pc})
|
||||
/]
|
||||
|
||||
Reference in New Issue
Block a user