| /***************************************************************************** |
| * Copyright (c) 2015-2019 CEA LIST. |
| * |
| * |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Ansgar Radermacher ansgar.radermacher@cea.fr |
| * Shuai Li (CEA LIST) <shuai.li@cea.fr> - Bug 530651 |
| * Shuai Li (CEA LIST) <shuai.li@cea.fr> - Bug 531771 |
| * Yoann Farre (CIL4Sys) <yoann.farre@cil4sys.com> - Bug 543072, Bug 559033 |
| * |
| *****************************************************************************/ |
| package org.eclipse.papyrus.designer.components.transformation.cpp.xtend |
| |
| import org.eclipse.papyrus.designer.components.modellibs.core.transformations.AbstractCompToOO |
| import org.eclipse.papyrus.designer.components.modellibs.core.transformations.Constants |
| import org.eclipse.papyrus.designer.components.transformation.PortInfo |
| import org.eclipse.papyrus.designer.components.transformation.PortUtils |
| import org.eclipse.papyrus.designer.components.transformation.component.PrefixConstants |
| import org.eclipse.papyrus.designer.components.transformation.extensions.IOOTrafo |
| import org.eclipse.papyrus.designer.languages.common.profile.Codegen.NoCodeGen |
| import org.eclipse.papyrus.designer.languages.cpp.profile.C_Cpp.Array |
| import org.eclipse.papyrus.designer.languages.cpp.profile.C_Cpp.Const |
| import org.eclipse.papyrus.designer.languages.cpp.profile.C_Cpp.ConstInit |
| import org.eclipse.papyrus.designer.languages.cpp.profile.C_Cpp.Friend |
| import org.eclipse.papyrus.designer.languages.cpp.profile.C_Cpp.Inline |
| import org.eclipse.papyrus.designer.languages.cpp.profile.C_Cpp.Ptr |
| import org.eclipse.papyrus.designer.languages.cpp.profile.C_Cpp.Ref |
| import org.eclipse.papyrus.designer.languages.cpp.profile.C_Cpp.Typedef |
| import org.eclipse.papyrus.designer.languages.cpp.profile.C_Cpp.Variadic |
| import org.eclipse.papyrus.designer.languages.cpp.profile.C_Cpp.Virtual |
| import org.eclipse.papyrus.designer.languages.cpp.profile.C_Cpp.Volatile |
| import org.eclipse.papyrus.designer.transformation.base.utils.CopyUtils |
| import org.eclipse.papyrus.designer.transformation.base.utils.PartsUtil |
| import org.eclipse.papyrus.designer.transformation.base.utils.TransformationException |
| import org.eclipse.papyrus.designer.transformation.core.transformations.LazyCopier |
| import org.eclipse.papyrus.uml.tools.utils.ConnectorUtil |
| import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil |
| import org.eclipse.uml2.uml.AggregationKind |
| import org.eclipse.uml2.uml.BehavioredClassifier |
| import org.eclipse.uml2.uml.Class |
| import org.eclipse.uml2.uml.Classifier |
| import org.eclipse.uml2.uml.Connector |
| import org.eclipse.uml2.uml.ConnectorEnd |
| import org.eclipse.uml2.uml.Element |
| import org.eclipse.uml2.uml.Interface |
| import org.eclipse.uml2.uml.OpaqueBehavior |
| import org.eclipse.uml2.uml.Operation |
| import org.eclipse.uml2.uml.Parameter |
| import org.eclipse.uml2.uml.Port |
| import org.eclipse.uml2.uml.PrimitiveType |
| import org.eclipse.uml2.uml.Property |
| import org.eclipse.uml2.uml.UMLPackage |
| import org.eclipse.uml2.uml.util.UMLUtil |
| import org.eclipse.uml2.uml.Type |
| |
| /** |
| * This class realizes the transformation from component-based to object-oriented |
| * models for C++. It refines the abstract component to OO transformation |
| */ |
| class StaticCppToOO extends AbstractCompToOO implements IOOTrafo { |
| override init(LazyCopier copier, Class bootloader) { |
| super.init(copier, bootloader) |
| progLang = "C/C++"; |
| } |
| |
| override nameRef(Property attribute) { |
| CppUtils.nameRef(attribute) |
| } |
| |
| /** |
| * Apply a pointer to the (typed) element |
| */ |
| override applyRef(Element element) { |
| StereotypeUtil.apply(element, Ptr) |
| } |
| |
| /** |
| * Create a ptr_type for the given typed element |
| * This is required, in order to create a vector of pointers |
| * instead of a pointer towards a vector |
| */ |
| def createPtrType(Type type) { |
| // check, if an "_ptr" type already exists |
| if (!type.name.endsWith("_ptr")) { |
| val pkg = type.nearestPackage |
| val name = type.name + "_ptr" |
| var ptrType = pkg.getPackagedElement(name) as PrimitiveType |
| if (ptrType === null) { |
| ptrType = pkg.createOwnedPrimitiveType(name) |
| val typedef = StereotypeUtil.applyApp(ptrType, Typedef) |
| // dependencies do not work for primitive types, as a |
| // workaround, prefix typedef with class (ok for pointer types) |
| typedef.definition = '''class «type.name» *''' |
| } |
| return ptrType; |
| } |
| else { |
| return type; |
| } |
| } |
| |
| override getRef(Property attribute) { |
| CppUtils.getRef(attribute) |
| } |
| |
| /** |
| * Transform parts if necessary. |
| * |
| * If the bootloader is responsible for creating an instance (if it is a |
| * abstract type), mark the associated part as a C++ pointer. We do not want |
| * to change the aggregation kind, since it remains logically a composition, |
| * it is merely an implementation issue that it must be a pointer for C++ if |
| * the concrete type is not yet known. |
| * |
| * @param compositeImplementation |
| * a (composite) component |
| */ |
| override transformParts(Class compositeImplementation) { |
| |
| for (Property attribute : PartsUtil.getParts(compositeImplementation)) { |
| val type = attribute.type |
| if (type instanceof Class) { |
| // => requires adaptations of boot-loader which is then only |
| // responsible for creating instances corresponding to types |
| if (instantiateViaBootloader(type)) { |
| StereotypeUtil.apply(attribute, Ptr) |
| } |
| } |
| } |
| } |
| |
| override addGetPortOperation(Class implementation, PortInfo portInfo, Interface providedIntf, String portName) { |
| // port provides an interface, add "get_p" operation and implementation |
| val opName = PrefixConstants.getP_Prefix + portName |
| var op = implementation.getOwnedOperation(opName, null, null) |
| if (op !== null) { |
| // operation already exists. Assume that user wants to |
| // override standard delegation |
| if (op.type != providedIntf) { |
| op.createOwnedParameter(Constants.retParamName, providedIntf) |
| } |
| } else { |
| op = implementation.createOwnedOperation(opName, null, null, providedIntf) |
| val retParam = op.getOwnedParameters().get(0) |
| retParam.setName(Constants.retParamName) |
| applyRef(retParam) |
| |
| val behavior = implementation.createOwnedBehavior(opName, |
| UMLPackage.eINSTANCE.getOpaqueBehavior()) as OpaqueBehavior |
| op.getMethods().add(behavior) |
| |
| val ces = ConnectorUtil.getDelegations(implementation, portInfo.getModelPort()) |
| var connectedDelegations = 0 |
| for (ce : ces) { |
| val role = ce.role |
| |
| if (role instanceof Port) { |
| val rolePort = role as Port |
| if (rolePort.provideds.contains(providedIntf)) { |
| connectedDelegations++ |
| } |
| } else { |
| if (role instanceof Property) { |
| val roleType = (role as Property).type; |
| if (roleType instanceof BehavioredClassifier && |
| (roleType as BehavioredClassifier).getInterfaceRealization(null, providedIntf) !== null) { |
| connectedDelegations++ |
| } |
| } |
| } |
| } |
| val isMultipleDelegations = connectedDelegations > 1 |
| |
| var String body |
| |
| if (isMultipleDelegations) { |
| val dc = new CreateMultiRefClass(this, copier) |
| body = dc.createDelegationProvided(implementation, ces, portInfo.port, portName, providedIntf); |
| } else if (!ces.empty) { |
| // If there is an delegation to one, and one only, inner property, delegate to it |
| // Make distinction between delegation to a port of the class typing an inner property or the property itself |
| body = "return " |
| |
| var i = 0 |
| while (i < ces.size && body.equals("return ")) { |
| val part = ces.get(i).partWithPort |
| val role = ces.get(i).role |
| |
| if (role instanceof Port) { |
| val rolePort = role as Port |
| if (rolePort.provideds.contains(providedIntf)) { |
| if (rolePort.provideds.size > 1 || !(rolePort.type instanceof Interface)) { |
| body += |
| '''«part.nameRef»«PrefixConstants.getP_Prefix»«role.name»«providedIntf.name»();''' |
| } else { |
| body += '''«part.nameRef»«PrefixConstants.getP_Prefix»«role.name»();''' |
| } |
| } |
| } else { |
| // role is not a port: connector connects directly to a |
| // structural feature without passing via a port |
| if (role instanceof Property) { |
| val roleType = (role as Property).type; |
| if (roleType instanceof BehavioredClassifier && |
| (roleType as BehavioredClassifier).getInterfaceRealization(null, providedIntf) !== |
| null) { |
| body += role.name |
| } |
| } |
| } |
| i++ |
| } |
| |
| if (body.equals("return ")) { |
| body += "NULL;" |
| } |
| } else { |
| // no delegation, check whether port implements provided interface |
| var implementsIntf = implementation.getInterfaceRealization(null, providedIntf) !== null |
| if (!implementsIntf) { |
| |
| // The extended port itself is not copied to the target |
| // model (since referenced via a stereotype). Therefore, |
| // a port of an extended port still points to the |
| // original model. We try whether the providedIntf |
| // within the target model is within the interface |
| // realizations. |
| val providedIntfInCopy = copier.getCopy(providedIntf) |
| implementsIntf = implementation.getInterfaceRealization(null, providedIntfInCopy) !== null |
| } |
| if (implementsIntf) { |
| body = "return this;" |
| } else { |
| throw new RuntimeException( |
| String.format( |
| "Interface <%s> provided by port <%s> of class <%s> is not implemented by the component itself nor does the port delegate to a part", |
| providedIntf.name, portName, implementation.name)) |
| } |
| } |
| behavior.getLanguages().add(progLang) |
| behavior.getBodies().add(body) |
| } |
| } |
| |
| override addConnectPortOperation(Class implementation, PortInfo portInfo, Interface requiredIntf, String portName) { |
| // port requires an interface, add "connect_p" operation and implementation |
| val opName = PrefixConstants.connectQ_Prefix + portName |
| |
| if (implementation.getOwnedOperation(opName, null, null) !== null) { |
| // do not add the operation, if it already exists. This means that the |
| // user wants to override it with custom behavior. In case of extended |
| // ports, we may have to do that. |
| } else { |
| var op = implementation.createOwnedOperation(opName, null, null) |
| val refParam = op.createOwnedParameter("ref", requiredIntf) |
| applyRef(refParam) |
| |
| val behavior = implementation.createOwnedBehavior(opName, |
| UMLPackage.eINSTANCE.getOpaqueBehavior()) as OpaqueBehavior |
| |
| op.getMethods().add(behavior) |
| |
| val ces = ConnectorUtil.getDelegations(implementation, portInfo.getModelPort()) |
| |
| // if there is an delegation to an inner property, delegate to it |
| // Make distinction between delegation to component (with a port) or |
| // "normal" class (without). |
| var String body = "" |
| if (!ces.empty) { |
| var i = 0 |
| while (i < ces.size) { |
| val part = ces.get(i).partWithPort |
| val role = ces.get(i).role |
| var bodyConstruction = "" |
| if (role instanceof Port) { |
| val rolePort = role as Port |
| if (rolePort.requireds.contains(requiredIntf)) { |
| // in case of a delegation, use name of target port which might be different |
| var targetOpName = PrefixConstants.connectQ_Prefix + role.name |
| if (rolePort.requireds.size > 1 || !(rolePort.type instanceof Interface)) { |
| targetOpName += requiredIntf.name |
| } |
| |
| if (part.upper > 1) { |
| for (var j = 0; j < part.upper; j++) { |
| bodyConstruction += '''«part.name»[«i»].«targetOpName»(ref);''' |
| } |
| } else { |
| bodyConstruction += '''«part.nameRef»«targetOpName»(ref);''' |
| } |
| } |
| } else { |
| if (part.type instanceof Classifier && |
| (part.type as Classifier).getAllUsedInterfaces().contains(requiredIntf)) { |
| if (part.upper > 1) { |
| for (var j = 0; j < part.upper; j++) { |
| bodyConstruction += '''«part.name»[«i»];''' |
| } |
| } else { |
| bodyConstruction += '''«part.name»;''' |
| } |
| } |
| } |
| |
| if (!bodyConstruction.empty) { |
| body += bodyConstruction |
| if (i < ces.size - 1) { |
| body += NL |
| } |
| } |
| |
| i++ |
| } |
| } else { |
| |
| val attributeName = PrefixConstants.attributePrefix + portName |
| val port = portInfo.port |
| |
| if (port.upper != 1) { |
| val dc = new CreateMultiRefClass(this, copier) |
| body += dc.createDelegationRequired(implementation, portName, requiredIntf); |
| } else { |
| // No delegation and no multiple providers |
| var attr = implementation.getOwnedAttribute(attributeName, null) |
| if (attr === null || attr instanceof Port) { |
| attr = implementation.createOwnedAttribute(attributeName, requiredIntf) |
| CopyUtils.copyMultElemModifiers(portInfo.port, attr) |
| |
| // is shared (should store a reference) |
| attr.setAggregation(AggregationKind.SHARED_LITERAL) |
| } |
| body += '''«attributeName» = ref;''' |
| } |
| } |
| |
| behavior.getLanguages().add(progLang) |
| behavior.getBodies().add(body) |
| |
| // ------------------------- |
| // add body to get-connection operation (which exists already if the port is also |
| // owned, since it is synchronized automatically during model edit) |
| // getConnQ prefix may be empty to indicate that the port is accessed directly |
| // TODO: reconsider optimization that delegated required ports do not have a |
| // local attribute and associated operation (an inner class may delegate, but the |
| // composite may be using it as well). |
| if ((PrefixConstants.getConnQ_Prefix.length() > 0) && (!ces.empty)) { |
| val getConnOpName = PrefixConstants.getConnQ_Prefix + portName |
| var getConnOp = implementation.getOwnedOperation(getConnOpName, null, null) |
| if (getConnOp === null) { |
| getConnOp = implementation.createOwnedOperation(getConnOpName, null, null, requiredIntf) |
| val retParam = op.getOwnedParameters().get(0) |
| retParam.setName(Constants.retParamName) |
| applyRef(retParam) |
| } |
| val getConnBehavior = implementation.createOwnedBehavior(getConnOpName, |
| UMLPackage.eINSTANCE.getOpaqueBehavior()) as OpaqueBehavior |
| getConnOp.getMethods().add(getConnBehavior) |
| |
| // no delegation |
| val String name = PrefixConstants.attributePrefix + portName |
| body = '''return «name»;''' |
| behavior.getLanguages().add(progLang) |
| behavior.getBodies().add(body.trim) |
| } else { |
| } |
| } |
| } |
| |
| override connectPorts(Connector connector, ConnectorEnd receptacleEnd, |
| ConnectorEnd facetEnd, Port subPort) throws TransformationException { |
| val association = connector.type |
| if ((receptacleEnd.role instanceof Port) && (facetEnd.role instanceof Port)) { |
| val facetPort = facetEnd.role as Port |
| val receptaclePort = receptacleEnd.role as Port |
| val facetPI = PortInfo.fromSubPort(facetPort, subPort) |
| val receptaclePI = PortInfo.fromSubPort(receptaclePort, subPort) |
| |
| if ((facetPI.getProvided() !== null) && (receptaclePI.getRequired() !== null)) { |
| val facetPart = facetEnd.partWithPort |
| val receptaclePart = receptacleEnd.partWithPort |
| |
| var subPortName = "" |
| if(subPort !== null) subPortName += "_" + subPort.name |
| |
| var result = "" |
| |
| if (receptaclePI.getRequireds().size == 1 && receptaclePI.port.type instanceof Interface) { // receptaclePort requires only 1 interface |
| var facetPortName = "" |
| |
| if (facetPI.getProvideds().size == 1 && facetPI.port.type instanceof Interface) { // Original behavior in case of single interface, where we always connect without check of interface consistency |
| facetPortName = facetPI.name |
| } else if (facetPI.getProvideds().size >= 1 && |
| facetPI.getProvideds().contains(receptaclePI.getRequired())) { |
| facetPortName += facetPI.name + receptaclePI.getRequired().name |
| } |
| |
| if (!facetPortName.empty) { |
| val setter = '''«receptaclePart.nameRef»connect_«receptaclePort.name»«subPortName»''' |
| if (facetPart.upper > 1) { |
| for (var i = 0; i < facetPart.upper; i++) { |
| val getter = '''«facetPart.name»[«i»].get_«facetPortName»«subPortName»()''' |
| result += '''«setter»(«getter»);''' + NL |
| } |
| } else { |
| val getter = '''«facetPart.nameRef»get_«facetPortName»«subPortName»()''' |
| result += '''«setter»(«getter»);''' + NL |
| } |
| } |
| } else { // receptaclePort requires several interfaces or one interface through a class |
| for (requiredInterface : receptaclePI.getRequireds()) { |
| var receptaclePortName = receptaclePI.name + requiredInterface.name |
| var facetPortName = "" |
| |
| if (facetPI.getProvideds().contains(requiredInterface)) { |
| facetPortName += facetPI.name |
| if (facetPI.getProvideds().size > 1 || !(facetPI.port.type instanceof Interface)) { |
| facetPortName += requiredInterface.name |
| } |
| } |
| |
| if (!facetPortName.empty) { |
| val setter = '''«receptaclePart.nameRef»connect_«receptaclePortName»«subPortName»''' |
| if (facetPart.upper > 1) { |
| for (var i = 0; i < facetPart.upper; i++) { |
| val getter = '''«facetPart.name»[«i»].get_«facetPortName»«subPortName»()''' |
| result += '''«setter»(«getter»);''' + NL |
| } |
| } else { |
| val getter = '''«facetPart.nameRef»get_«facetPortName»«subPortName»()''' |
| result += '''«setter»(«getter»);''' + NL |
| } |
| } |
| } |
| } |
| |
| return result |
| } |
| } else if (receptacleEnd.role instanceof Port) { |
| |
| // only the receptacle end is of type port. |
| val Port receptaclePort = receptacleEnd.role as Port |
| if (PortUtils.getRequired(receptaclePort) !== null) { |
| val facetPart = facetEnd.role as Property |
| val receptaclePart = facetEnd.partWithPort |
| |
| var result = "" |
| |
| if (receptaclePort.getRequireds().size > 1) { // receptaclePort requires several interfaces |
| for (requiredInterface : receptaclePort.getRequireds()) { |
| var receptaclePortName = receptaclePort.name + requiredInterface.name |
| |
| val setter = '''«receptaclePart.nameRef»connect_«receptaclePortName»''' |
| if (facetPart.upper > 1) { |
| for (var i = 0; i < facetPart.upper; i++) { |
| val getter = '''«facetPart.name»[«i»]''' |
| result += '''«setter»(«getter»);''' + NL |
| } |
| } else { |
| val getter = '''«facetPart.getRef»''' |
| result += '''«setter»(«getter»);''' + NL |
| } |
| } |
| } else { |
| val setter = '''«receptaclePart.nameRef»connect_«receptaclePort.name»''' |
| if (facetPart.upper > 1) { |
| for (var i = 0; i < facetPart.upper; i++) { |
| val getter = '''«facetPart.name»[«i»]''' |
| result += '''«setter»(«getter»);''' + NL |
| } |
| } else { |
| val getter = '''«facetPart.getRef»''' |
| result += '''«setter»(«getter»);''' + NL |
| } |
| } |
| |
| return result |
| } |
| } else if (facetEnd.role instanceof Port) { |
| |
| // only the facet end is of type port. Unsupported combination |
| val facetPort = facetEnd.role as Port |
| if (PortUtils.getProvided(facetPort) !== null) { |
| val facetPart = facetEnd.partWithPort |
| val receptaclePart = facetEnd.role as Property |
| |
| var result = "" |
| |
| if (facetPort.getProvideds().size > 1) { // facetPort provides several interfaces |
| for (providedInterface : facetPort.getProvideds()) { |
| var facetPortName = facetPort.name + providedInterface.name |
| val setter = receptaclePart.name |
| if (facetPart.upper > 1) { |
| for (var i = 0; i < facetPart.upper; i++) { |
| val getter = '''«facetPart.name»[«i»].get_«facetPortName»();''' |
| result += '''«setter» = «getter»;''' + NL |
| } |
| } else { |
| val getter = '''«facetPart.nameRef»get_«facetPortName»();''' |
| result += '''«setter» = «getter»;''' + NL |
| } |
| } |
| } else { |
| val setter = receptaclePart.name |
| if (facetPart.upper > 1) { |
| for (var i = 0; i < facetPart.upper; i++) { |
| val getter = '''«facetPart.name»[«i»].get_«facetPort.name»();''' |
| result += '''«setter» = «getter»;''' + NL |
| } |
| } else { |
| val getter = '''«facetPart.nameRef»get_«facetPort.name»();''' |
| result += '''«setter» = «getter»;''' + NL |
| } |
| } |
| |
| return result |
| } |
| } else if (association !== null) { |
| |
| // both connector ends do not target ports. In this case, we require that the connector is typed |
| // with an association. We use this association to find out which end is navigable and assume that |
| // the part pointed to by the other end is a pointer that gets initialized with the part of the |
| // navigable end. |
| val facetPart = facetEnd.role as Property |
| val receptaclePart = receptacleEnd.role as Property |
| |
| val assocProp1 = association.getMemberEnd(null, facetPart.type) |
| |
| if ((assocProp1 !== null) && assocProp1.isNavigable) { |
| var setter = '''«receptaclePart.name».«assocProp1.name»''' |
| val getter = '''«facetPart.name»''' |
| return '''«setter» = «getter»;''' + NL |
| } |
| |
| } else { |
| |
| // not handled (a connector not targeting a port must be typed) |
| throw new TransformationException("Connector <" + connector.name + |
| "> does not use ports, but it is not typed (only connectors between ports should not be typed)") |
| } |
| return "" |
| } |
| |
| def void copyCppOperationAndParameterStereotypes(Element source, Element target) { |
| if ((source instanceof Operation && target instanceof Operation) || |
| (source instanceof Parameter && target instanceof Parameter)) { |
| if (UMLUtil.getStereotypeApplication(source, Array) !== null) { |
| StereotypeUtil.apply(target, Array) |
| } |
| |
| if (UMLUtil.getStereotypeApplication(source, Const) !== null) { |
| StereotypeUtil.apply(target, Const) |
| } |
| |
| if (UMLUtil.getStereotypeApplication(source, Ptr) !== null) { |
| val sourceStereotype = UMLUtil.getStereotypeApplication(source, Ptr) |
| StereotypeUtil.apply(target, Ptr) |
| var stereotype = UMLUtil.getStereotypeApplication(target, Ptr) |
| if (stereotype !== null) { |
| if (sourceStereotype.declaration !== null) { |
| stereotype.declaration = new String(sourceStereotype.declaration) |
| } |
| } |
| } |
| |
| if (UMLUtil.getStereotypeApplication(source, Ref) !== null) { |
| val sourceStereotype = UMLUtil.getStereotypeApplication(source, Ref) |
| StereotypeUtil.apply(target, Ref) |
| var stereotype = UMLUtil.getStereotypeApplication(target, Ref) |
| if (stereotype !== null) { |
| if (sourceStereotype.declaration !== null) { |
| stereotype.declaration = new String(sourceStereotype.declaration) |
| } |
| } |
| } |
| |
| if (UMLUtil.getStereotypeApplication(source, NoCodeGen) !== null) { |
| StereotypeUtil.apply(target, NoCodeGen) |
| } |
| |
| if (UMLUtil.getStereotypeApplication(source, Volatile) !== null) { |
| StereotypeUtil.apply(target, Volatile) |
| } |
| |
| if (UMLUtil.getStereotypeApplication(source, ConstInit) !== null) { |
| val sourceStereotype = UMLUtil.getStereotypeApplication(source, ConstInit) |
| StereotypeUtil.apply(target, Array) |
| var stereotype = UMLUtil.getStereotypeApplication(target, ConstInit) |
| if (stereotype !== null) { |
| if (sourceStereotype.initialisation !== null) { |
| stereotype.initialisation = new String(sourceStereotype.initialisation) |
| } |
| } |
| } |
| |
| if (UMLUtil.getStereotypeApplication(source, Friend) !== null) { |
| StereotypeUtil.apply(target, Friend) |
| } |
| |
| if (UMLUtil.getStereotypeApplication(source, Inline) !== null) { |
| StereotypeUtil.apply(target, Inline) |
| } |
| |
| if (UMLUtil.getStereotypeApplication(source, Virtual) !== null) { |
| StereotypeUtil.apply(target, Virtual) |
| } |
| |
| if (UMLUtil.getStereotypeApplication(source, Variadic) !== null) { |
| StereotypeUtil.apply(target, Variadic) |
| } |
| |
| if (source instanceof Operation && target instanceof Operation) { |
| if ((source as Operation).ownedParameters.size == (target as Operation).ownedParameters.size) { |
| var i = 0 |
| while (i < (source as Operation).ownedParameters.size) { |
| copyCppOperationAndParameterStereotypes((source as Operation).ownedParameters.get(i), |
| (target as Operation).ownedParameters.get(i)) |
| i++ |
| } |
| } |
| } |
| } |
| } |
| } |