diff options
Diffstat (limited to 'extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/BootLoaderGen.java')
-rw-r--r-- | extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/BootLoaderGen.java | 546 |
1 files changed, 0 insertions, 546 deletions
diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/BootLoaderGen.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/BootLoaderGen.java deleted file mode 100644 index 595e5aba037..00000000000 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/BootLoaderGen.java +++ /dev/null @@ -1,546 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2013 CEA LIST. - * - * - * 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: - * Ansgar Radermacher ansgar.radermacher@cea.fr - * - *****************************************************************************/ - -package org.eclipse.papyrus.qompass.designer.core.deployment; - -import java.util.Arrays; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Map; -import java.util.Stack; - -import org.eclipse.emf.common.util.BasicEList; -import org.eclipse.emf.common.util.EList; -import org.eclipse.papyrus.C_Cpp.Include; -import org.eclipse.papyrus.FCM.InitPrecedence; -import org.eclipse.papyrus.MARTE.MARTE_DesignModel.SRM.SW_Concurrency.SwSchedulableResource; -import org.eclipse.papyrus.qompass.designer.core.Messages; -import org.eclipse.papyrus.qompass.designer.core.StUtils; -import org.eclipse.papyrus.qompass.designer.core.UMLTool; -import org.eclipse.papyrus.qompass.designer.core.Utils; -import org.eclipse.papyrus.qompass.designer.core.transformations.ExecuteOOTrafo; -import org.eclipse.papyrus.qompass.designer.core.transformations.LazyCopier; -import org.eclipse.papyrus.qompass.designer.core.transformations.PrefixConstants; -import org.eclipse.papyrus.qompass.designer.core.transformations.TransformationException; -import org.eclipse.papyrus.uml.tools.utils.ConnectorUtil; -import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil; -import org.eclipse.uml2.uml.Class; -import org.eclipse.uml2.uml.Connector; -import org.eclipse.uml2.uml.ConnectorEnd; -import org.eclipse.uml2.uml.Element; -import org.eclipse.uml2.uml.InstanceSpecification; -import org.eclipse.uml2.uml.OpaqueBehavior; -import org.eclipse.uml2.uml.Operation; -import org.eclipse.uml2.uml.Port; -import org.eclipse.uml2.uml.Property; -import org.eclipse.uml2.uml.Slot; -import org.eclipse.uml2.uml.StructuralFeature; -import org.eclipse.uml2.uml.UMLPackage; -import org.eclipse.uml2.uml.ValueSpecification; -import org.eclipse.uml2.uml.util.UMLUtil; - -/** - * The task of the boot-loader is twofold: create the instances of all - * implementations (non-recursive). - * - create Connections: what should be done? - * - * TODO: factor out common code (TemplateInstantiation mechanism & createConnections below) - * Split between C++ specific and C++ independent aspects - */ -public class BootLoaderGen { - - private static final String EMPTYSTR = ""; //$NON-NLS-1$ - - final public static String NODE_INFO = "NodeInfo"; //$NON-NLS-1$ - - final public static String INIT_OP_NAME = "init"; //$NON-NLS-1$ - - final public static String NL = "\n"; //$NON-NLS-1$ - - final public static String EOL = ";\n"; //$NON-NLS-1$ - - final public static String BOOTLOADER_NAME = "BootLoader"; //$NON-NLS-1$ - - /** - * Create a new boot-loader in a specific package - * (which represents a node of the system). - * - * @param copier a lazy copier - * @param nodeIndex the index of the node - * @param numberOfNodes the number of nodes - * @throws TransformationException - */ - public BootLoaderGen(LazyCopier copier, int nodeIndex, int numberOfNodes) - throws TransformationException { - // Class composite = (Class) ut.getClassifier (mainInstance); - // place in root (getModel()) to avoid the problem that the declaration of the bootLoader - // instance is within a namespace (a static attribute on the model level would not solve the - // problem as it must be accessed by function main). - - Class nodeInfo = copier.target.createOwnedClass(NODE_INFO, false); - String headerStr = - "const int nodeIndex = " + nodeIndex + ";" + NL + //$NON-NLS-1$//$NON-NLS-2$ - "const int numberOfNodes = " + numberOfNodes + ";" + NL; //$NON-NLS-1$ //$NON-NLS-2$ - Include cppIncludeNodeInfo = StereotypeUtil.applyApp(nodeInfo, Include.class); - if (cppIncludeNodeInfo == null) { - throw new TransformationException("Can not apply C++ stereotypes during bootloader generation. Please apply the C++ profile to the source model"); - } - cppIncludeNodeInfo.setHeader(headerStr); - - // bootLoader.createOwnedAttribute (mainInstance.getName (), composite); - - m_bootLoader = copier.target.createOwnedClass(BOOTLOADER_NAME, false); - outputSizeof = false; - m_copy = copier; - Class template = (Class) Utils.getQualifiedElement(copier.source, bootloaderQNAME); - if (template == null) { - throw new TransformationException(String.format( - Messages.BootLoaderGen_CannotRetrieveTemplate, bootloaderQNAME)); - } - // TODO: currently, only stereotypes are copied from template - StUtils.copyStereotypes(template, m_bootLoader); - - - // TODO: commented code below already fixed? - /* - * Problem: defaultValue not taken into account by code generator - * => use global variables via cppInclude instead (see below: "bodyStr = ...") - * NamedElement corba_long = Utils.getQualifiedElement (owner, "CORBA::Long"); - * if (corba_long instanceof Type) { - * Property nodeNumber = - * m_bootLoader.createOwnedAttribute ("nodeNumber", (Type) corba_long); - * nodeNumber.setIsStatic (true); - * nodeNumber.setDefault ("0"); // for testing - * Property numberOfNodes = - * m_bootLoader.createOwnedAttribute ("numberOfNodes", (Type) corba_long); - * numberOfNodes.setIsStatic (true); - * numberOfNodes.setDefault ("2"); - * } - */ - Include cppInclude = StereotypeUtil.applyApp(m_bootLoader, Include.class); - if (cppInclude == null) { - throw new TransformationException(Messages.BootLoaderGen_CannotApplyCppInclude); - } - String existingBody = cppInclude.getBody(); - String bodyStr = EMPTYSTR; - - if (outputSizeof) { - bodyStr += - "#include <iostream>" + NL + //$NON-NLS-1$ - "using namespace std;" + NL; //$NON-NLS-1$ - } - cppInclude.setBody(existingBody + bodyStr); - - // bootLoader.createOwnedAttribute (mainInstance.getName (), composite); - - m_initCode = EMPTYSTR; - m_initCodeRun = EMPTYSTR; - m_activation = new HashMap<Class, EList<String>>(); - m_initCodeCConnections = EMPTYSTR; - m_initCodeCConfig = EMPTYSTR; - - if (outputSizeof) { - m_initCode += "cout << \"sizeof bootloader: \" << sizeof (bootloader) << endl;" + EOL; //$NON-NLS-1$ - } - // indexMap = new HashMap<String, Integer>(); - } - - /** - * Return the path from the main instance towards a sub-instance using the proper dereference - * operators, i.e. ".", if the sub-instance is enclosed via composition or "->" if the sub-instance - * is a pointer (since created by the bootloader). - * - * @param slotPath - * @param instance - * @param accessName - * return the name to access the feature. Returns access path to instance, not - * the name of the variable for this instance (if instantiated by bootloader) - * @return - */ - public String getPath(Stack<Slot> slotPath, InstanceSpecification instance, boolean accessName) { - if (slotPath.size() > 0) { - // start with first instance - String path = slotPath.get(0).getOwningInstance().getName(); - boolean previousInstantiatedByBL = false; - for (Slot pathElement : slotPath) { - if (pathElement != null) { - if (previousInstantiatedByBL && accessName) { - // If an instance is instantiated by the bootloader, it is only referenced via its type in the - // owning composite. Thus, configuration (and activation calls) might fail as the type might not - // have these configuration properties or operations. - // Therefore, configuration and initial calls use - // - the path, if instantiated by the composite - // - the variable name, if done by the bootloader - path = UMLTool.varName(path); // use variable name instead. - } - path += "." + pathElement.getDefiningFeature().getName(); //$NON-NLS-1$ - previousInstantiatedByBL = ExecuteOOTrafo.instantiateViaBootloader(pathElement.getDefiningFeature()); - } - } - if (previousInstantiatedByBL && !accessName) { - // name of the variable for this expression instantiated by the bootloader - path = UMLTool.varName(path); - } - return path; - } - else { - return instance.getName(); // instance has no path via slots, it is a top level instance - } - } - - public Property addInstance(Stack<Slot> slotPath, InstanceSpecification instance, Class implementation, InstanceSpecification node) - throws TransformationException - { - // TODO: comments not clear. seems unnecessary complex. Problem in general is that access to - // shared instances needs to be configured. - // It should always be possible to configure this instance via a path w/o sharing. - String accessName = getPath(slotPath, instance, true); - String varName = getPath(slotPath, instance, false); - - Property implemPart = null; - - // containing instance not null (=> neither main instance nor singleton) - Slot containerSlot = null; - if (slotPath.size() > 0) { - containerSlot = slotPath.peek(); - - // initialize part/property in containing instance. The containing instance itself is accessed - // via the naming of the associated instance, the part itself via the name of the defining feature. - if (DepUtils.isShared(containerSlot)) { - // we need to initialize the property (a reference) with the given instance - Stack<Slot> referencePath = DepUtils.getAccessPath(instance); - String referenceVarName = getPath(referencePath, instance, false); - - // add code for initialization - m_initCode += accessName + " = &" + referenceVarName + EOL; //$NON-NLS-1$ - // is a reference which should not be called via activation & start - // return now and skip code below - return implemPart; - } - else if (ExecuteOOTrafo.instantiateViaBootloader(containerSlot.getDefiningFeature())) { - // let bootloader instantiate - implemPart = m_bootLoader.createOwnedAttribute(/* "i_" + */varName, implementation); - // add code for initialization - m_initCode += accessName + " = &" + varName + EOL; //$NON-NLS-1$ - implemPart.setIsComposite(true); - } - } - else { - // top level, either main instance or singleton => bootloader instantiates, create attribute - implemPart = m_bootLoader.createOwnedAttribute(/* "i_" + */varName, implementation); - implemPart.setIsComposite(true); - } - if (outputSizeof) { - m_initCode += "cout << \"sizeof " + implementation.getName() + ": \" << sizeof (" + varName + ") << endl;" + EOL; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ - } - - // if start thread => existing thread activation interceptor? Connection? - if (StereotypeUtil.isApplied(implementation, SwSchedulableResource.class)) { - // yes, but is the thread instance part of the deployment plan?? [mmh, probably yes...] - // call threads start routine here? (via main thread?) which in turn will activate the start routine? - } - - // implementation contains get_start operation => has start port - // which is called automatically - String get_start = PrefixConstants.getP_Prefix + "start"; //$NON-NLS-1$ - - // Need to check whether implementation is an executor which is encapsulated in a container. In this case, only - // the method of the container and not the method of the executor (which owns the same port) maybe called. - // Currently, this check is based on the use of "executor" as reserved part name (validation checks that the - // user does not use this name for application components) - if (hasUnconnectedStartRoutine(m_copy, implementation, containerSlot)) { - if (m_initCodeRun.equals(EMPTYSTR)) { - // call start's run method - // TODO: Need path that uses the right dereference operator ("->" or ".") - m_initCodeRun = varName + "." + get_start + "()->run()" + EOL; //$NON-NLS-1$ //$NON-NLS-2$ - } else { - throw new TransformationException(String.format( - Messages.BootLoaderGen_AtLeastOneBlockingCall, - varName, m_initCodeRun)); - } - } - if (hasUnconnectedLifeCycle(m_copy, implementation, containerSlot)) { - // precedence is checked below (when code is actually produced) - // multiple varNames might share the same implementation. Put a list of variable names into the table - EList<String> varNameList = m_activation.get(implementation); - if (varNameList == null) { - varNameList = new BasicEList<String>(); - } - varNameList.add(varName + "."); //$NON-NLS-1$ - m_activation.put(implementation, varNameList); - } - - // check, if implementation contains a composite if (implementation.getOwnedOperation (StaticOOTrafo.CREATE_CONNECTIONS, null, null) != null) { - boolean bCreateConn = false; - for (Connector connector : implementation.getOwnedConnectors()) { - if (ConnectorUtil.isAssembly(connector)) { - bCreateConn = true; - break; - } - } - - if (bCreateConn) { - m_initCodeCConnections += varName + "." + ExecuteOOTrafo.CREATE_CONNECTIONS +"();\n"; //$NON-NLS-1$ //$NON-NLS-2$ - } - return implemPart; - } - - /** - * Check whether the passed implementation has an unconnected start port. - * This information is required, since only unconnected start ports are automatically called by the - * bootloader, in particular we want to avoid calling a start port of an executor (which is connected) - * and its container. - * - * @param implementation - * @param containerSlot - * @return - */ - public static boolean hasUnconnectedStartRoutine(LazyCopier copy, Class implementation, Slot containerSlot) { - if (implementation != null) { - Port startPort = AllocUtils.getStartPort(implementation); - if (startPort != null) { - return !isConnected(copy, containerSlot, startPort); - } - } - return false; - } - - /** - * Check, if the passed implementation has an unconnected life-cycle interface (activate/deactivate). - * This information is required, since only unconnected life cycle ports are automatically called by the - * bootloader, in particular we want to avoid calling a life cycle port of an executor (which is connected) - * and its container. - * - * @param implementation - * @param name - * @return - */ - public static boolean hasUnconnectedLifeCycle(LazyCopier copy, Class implementation, Slot containerSlot) { - if (implementation != null) { - Element lcPortElem = Utils.getNamedElementFromList(implementation.getAllAttributes(), "lc"); //$NON-NLS-1$ - if (lcPortElem instanceof Port) { - Port lcPort = (Port) lcPortElem; - // check, if port typed with ILifeCycle interface - if (lcPort.getType().getName().equals("ILifeCycle")) { //$NON-NLS-1$ - return !isConnected(copy, containerSlot, lcPort); - } - } - - } - return false; - } - - /** - * The check verifies whether the passed port is connected within - * the context of the composite represented by the passed slot - * - * @param containerSlot - * a slot within an instance that represents a composite class - * @Param a port that is checked for being connected - * @return true, if connected - */ - private static boolean isConnected(LazyCopier copy, Slot containerSlot, Port port) { - if (containerSlot != null) { - StructuralFeature sf = containerSlot.getDefiningFeature(); - if (sf instanceof Property) { - // instance still points to a part in the tmp-model (there are no - // instance specifications in the final model). Therefore, we use copy to - // obtain the mapped instance. - Property part = (Property) copy.copy(sf); - Class composite = part.getClass_(); - for (Connector connector : composite.getOwnedConnectors()) { - // must assure same connector end connects part & port - ConnectorEnd end = ConnectorUtil.connEndForPart(connector, part); - if ((end != null) && (end.getRole() == port)) { - return true; - } - } - } - } - return false; - } - - public void instanceConfig(Stack<Slot> slotPath, InstanceSpecification instance) throws TransformationException { - Slot slot = slotPath.peek(); - // String varName = getPath(slotPath, instance, false); - StructuralFeature sf = slot.getDefiningFeature(); - if (sf == null) { - throw new TransformationException(String.format("A slot for instance %s has no defining feature", instance.getName())); //$NON-NLS-1$ - } - - String varName = instance.getName() + "." + sf.getName(); //$NON-NLS-1$ - for (ValueSpecification value : slot.getValues()) { - - // only set value, if not null - if (value.stringValue() != null) { - m_initCodeCConfig += varName + " = " + value.stringValue() + EOL; //$NON-NLS-1$ - } - } - } - - public void addCreateConnections() { - // code generators do not handle connectors in a suitable way. Remove - // (alternative: no-code-gen tag, as available for C++) - m_bootLoader.getOwnedConnectors().clear(); - } - - /** - * add the initialize operation. Must be called after a set of addInstance invocations - * @param mainInstance - */ - public void addInit(String language) { - // TODO: use template - Operation init = m_bootLoader.createOwnedOperation(INIT_OP_NAME, null, null); - OpaqueBehavior initBehavior = (OpaqueBehavior) - m_bootLoader.createOwnedBehavior(INIT_OP_NAME, UMLPackage.eINSTANCE.getOpaqueBehavior()); - init.getMethods().add(initBehavior); - - initBehavior.getLanguages().add(language); - String code = m_initCode + "\n"; //$NON-NLS-1$ - if (m_initCodeCConfig.length() > 0) { - code += "\n// instance configuration\n" + //$NON-NLS-1$ - m_initCodeCConfig + "\n"; //$NON-NLS-1$ - } - if (m_initCodeCConnections.length() > 0) { - code += "\n// create connections between instances\n" + //$NON-NLS-1$ - m_initCodeCConnections + "\n"; //$NON-NLS-1$ - } - Comparator<Class> comparator = new Comparator<Class>() { - - @Override - public int compare(Class clazz1, Class clazz2) { - - InitPrecedence precedenceC1 = UMLUtil.getStereotypeApplication(clazz1, InitPrecedence.class); - InitPrecedence precedenceC2 = UMLUtil.getStereotypeApplication(clazz2, InitPrecedence.class); - if (precedenceC1 != null) { - // need to use named comparison instead of precedenceC1.getInvokeAfter ().contains (clazz2) - // since class referenced by stereotype attribute still points to element in source model - if (Utils.getNamedElementFromList(precedenceC1.getInvokeAfter(), clazz2.getName()) != null) { - return 1; - } - else if (Utils.getNamedElementFromList(precedenceC1.getInvokeBefore(), clazz2.getName()) != null) { - return -1; - } - } - else if (precedenceC2 != null) { - if (Utils.getNamedElementFromList(precedenceC2.getInvokeAfter(), clazz1.getName()) != null) { - return -1; - } - else if (Utils.getNamedElementFromList(precedenceC2.getInvokeBefore(), clazz1.getName()) != null) { - return 1; - } - } - // singletons have precedence over "normal" classes - boolean ci1IsSingleton = Utils.isSingleton(clazz1); - boolean ci2IsSingleton = Utils.isSingleton(clazz2); - if (ci1IsSingleton) { - if (!ci2IsSingleton) { - // not both are singletons - return -1; - } - } - else if (ci2IsSingleton) { - return 1; - } - return 0; - } - }; - Class[] activationKeys = m_activation.keySet().toArray(new Class[0]); - String get_lc = PrefixConstants.getP_Prefix + "lc"; //$NON-NLS-1$ - if (activationKeys.length > 0) { - Arrays.sort(activationKeys, comparator); - code += "// activation code\n"; //$NON-NLS-1$ - for (Class implementation : activationKeys) { - EList<String> varNameList = m_activation.get(implementation); - for (String varName : varNameList) { - code += varName + get_lc + "()->activate();\n"; //$NON-NLS-1$ - } - } - } - - Include cppInclude = UMLUtil.getStereotypeApplication(m_bootLoader, Include.class); - if (m_initCodeRun.length() > 0) { - code += "// initial user start\n" + m_initCodeRun; //$NON-NLS-1$ - } else { - // no component implements the initial start, therefore enter a sleep - // unistd is required (at least on unix systems) for sleep - cppInclude.setPreBody("#include <unistd.h> // for sleep\n"); //$NON-NLS-1$ - - code += "// sleep forever\n"; //$NON-NLS-1$ - code += "for (;;) { sleep(100); }\n"; //$NON-NLS-1$ - // throw new TransformationRTException("no component implements the initial start. Assure that one component inherits from the CStart component"); - } - if (activationKeys.length > 0) { - code += "// deactivation code (reverse order)\n"; //$NON-NLS-1$ - - // traverse in reverse order - for (int i = activationKeys.length - 1; i >= 0; i--) { - Class implementation = activationKeys[i]; - EList<String> varNameList = m_activation.get(implementation); - for (String varName : varNameList) { - code += varName + get_lc + "()->deactivate();\n"; //$NON-NLS-1$ - } - } - } - - initBehavior.getBodies().add(code); - } - - public Class getUML() { - return m_bootLoader; - } - - private Class m_bootLoader; - - private final static String bootloaderQNAME = "core::composites::BootLoader"; //$NON-NLS-1$ - - /** - * Initialization code, in particular assignment of part properties within composites - */ - private String m_initCode; - - /** - * Init code for create connections calls in composites with at least one assembly - * connector - */ - private String m_initCodeCConfig; - - /** - * Init code for create connections calls in composites with at least one assembly - * connector - */ - private String m_initCodeCConnections; - - /** - * Init code for blocking "run" calls (related to CStart system component) - */ - private String m_initCodeRun; - - /** - * Map containing activations/de-activations - */ - private Map<Class, EList<String>> m_activation; - - private boolean outputSizeof; - - /** - * copy variable (instances still point to non-copied classes) - */ - private LazyCopier m_copy; - - /** - * Store a map with index values to manage configuration of arrays - */ - // protected Map<String, Integer> indexMap; -} |