diff --git a/capellambse/model/modeltypes.py b/capellambse/model/modeltypes.py index 608abc6a..709735ee 100644 --- a/capellambse/model/modeltypes.py +++ b/capellambse/model/modeltypes.py @@ -128,6 +128,12 @@ class DiagramType(_StringyEnumMixin, _enum.Enum): CIBD = "Configuration Items Breakdown" +@_enum.unique +class AccessPolicy(_StringyEnumMixin, _enum.Enum): + READ_ONLY = "readOnly" + READ_AND_WRITE = "readAndWrite" + + @_enum.unique class AggregationKind(_StringyEnumMixin, _enum.Enum): """Defines the specific kind of a relationship, as per UML definitions.""" @@ -157,6 +163,49 @@ class AggregationKind(_StringyEnumMixin, _enum.Enum): """ +@_enum.unique +class BinaryOperator(_StringyEnumMixin, _enum.Enum): + """Specifies the kind of this binary operator.""" + + UNSET = "UNSET" + """The binary operator is not initialized.""" + ADD = "ADD" + """The binary operator refers to an addition.""" + MUL = "MUL" + """The binary operator refers to a multiplication.""" + SUB = "SUB" + """The binary operator refers to a substraction.""" + DIV = "DIV" + """The binary operator refers to a division.""" + POW = "POW" + """The binary operator refers to a power operation.""" + MIN = "MIN" + """The binary operator refers to a min operation.""" + MAX = "MAX" + """The binary operator refers to a max operation.""" + EQU = "EQU" + """The binary operator refers to an equal operation.""" + IOR = "IOR" + """The binary operator refers to a logical inclusive OR operation.""" + XOR = "XOR" + """The binary operator refers to a logical exclusive OR operation.""" + AND = "AND" + """The binary operator refers to a logical AND operation.""" + + +@_enum.unique +class CatalogElementKind(_StringyEnumMixin, _enum.Enum): + REC = "REC" + RPL = "RPL" + REC_RPL = "REC_RPL" + GROUPING = "GROUPING" + + +@_enum.unique +class ChangeEventKind(_StringyEnumMixin, _enum.Enum): + WHEN = "WHEN" + + @_enum.unique class CollectionKind(_StringyEnumMixin, _enum.Enum): """Defines the specific kind of a Collection structure.""" @@ -167,6 +216,56 @@ class CollectionKind(_StringyEnumMixin, _enum.Enum): """The collection is to be considered as a sequence (list) of elements.""" +@_enum.unique +class CommunicationLinkKind(_StringyEnumMixin, _enum.Enum): + """Enumeration listing the various possibilities of communication links.""" + + UNSET = "UNSET" + """The CommunicationLink protocol is not yet set.""" + PRODUCE = "PRODUCE" + """The CommunicationLink describes a production of ExchangeItem.""" + CONSUME = "CONSUME" + """The CommunicationLink describes a comsumption of ExchangeItem.""" + SEND = "SEND" + """The CommunicationLink describes a sending of ExchangeItem.""" + RECEIVE = "RECEIVE" + """The CommunicationLink describes a reception of ExchangeItem.""" + CALL = "CALL" + """The CommunicationLink describes a call of ExchangeItem.""" + EXECUTE = "EXECUTE" + """The CommunicationLink describes an execution of ExchangeItem.""" + WRITE = "WRITE" + """The CommunicationLink describes a writing of ExchangeItem.""" + ACCESS = "ACCESS" + """The CommunicationLink describes an access to the ExchangeItem.""" + ACQUIRE = "ACQUIRE" + """The CommunicationLink describes an acquisition of ExchangeItem.""" + TRANSMIT = "TRANSMIT" + """The CommunicationLink describes a transmission of ExchangeItem.""" + + +@_enum.unique +class CommunicationLinkProtocol(_StringyEnumMixin, _enum.Enum): + """The various possibilities for the protocol of the communication link.""" + + UNSET = "UNSET" + """The CommunicationLink protocol is not yet set.""" + UNICAST = "UNICAST" + """Describes sending an ExchangeItem using the unicast protocol.""" + MULTICAST = "MULTICAST" + """Describes sending an ExchangeItem using the multicast protocol.""" + BROADCAST = "BROADCAST" + """Describes sending an ExchangeItem using the broadcast protocol.""" + SYNCHRONOUS = "SYNCHRONOUS" + """Describes a call of the ExchangeItem using the synchronous protocol.""" + ASYNCHRONOUS = "ASYNCHRONOUS" + """Describes a call of the ExchangeItem using the asynchronous protocol.""" + READ = "READ" + """Describes access to the ExchangeItem by reading it.""" + ACCEPT = "ACCEPT" + """Describes access to the ExchangeItem by accepting it.""" + + @_enum.unique class ComponentExchangeKind(_StringyEnumMixin, _enum.Enum): """The kind of a ComponentExchange.""" @@ -181,6 +280,41 @@ class ComponentExchangeKind(_StringyEnumMixin, _enum.Enum): """Describes a flow communication.""" +@_enum.unique +class ComponentPortKind(_StringyEnumMixin, _enum.Enum): + STANDARD = "STANDARD" + """Describes a standard port. + + A port is an interaction point between a Block or sub-Block and its + environment that supports Exchanges with other ports. + """ + FLOW = "FLOW" + """Describes a flow port. + + A flow port is an interaction point through which input and/or + output of items such as data, material, or energy may flow. + """ + + +@_enum.unique +class ConfigurationItemKind(_StringyEnumMixin, _enum.Enum): + UNSET = "Unset" + COTSCI = "COTSCI" + """Commercial Off The Shelves Configuration Item.""" + CSCI = "CSCI" + """Computer Software Configuration Item.""" + HWCI = "HWCI" + """Hardware Configuration Item.""" + INTERFACE_CI = "InterfaceCI" + """Interface Configuration Item.""" + NDICI = "NDICI" + """Non Developmental Configuration Item.""" + PRIME_ITEM_CI = "PrimeItemCI" + """Prime Item Configuration Item.""" + SYSTEM_CI = "SystemCI" + """System Configuration Item.""" + + @_enum.unique class ControlNodeKind(_StringyEnumMixin, _enum.Enum): OR = "OR" @@ -188,6 +322,16 @@ class ControlNodeKind(_StringyEnumMixin, _enum.Enum): ITERATE = "ITERATE" +@_enum.unique +class ElementKind(_StringyEnumMixin, _enum.Enum): + """The visibility options for features of a class.""" + + TYPE = "TYPE" + """The ExchangeItemElement is a type for its ExchangeItem.""" + MEMBER = "MEMBER" + """The ExchangeItemElement is a member for its ExchangeItem.""" + + @_enum.unique class ExchangeMechanism(_StringyEnumMixin, _enum.Enum): """Enumeration of the different exchange mechanisms.""" @@ -224,6 +368,56 @@ class FunctionKind(_StringyEnumMixin, _enum.Enum): ROUTE = "ROUTE" +@_enum.unique +class InteractionOperatorKind(_StringyEnumMixin, _enum.Enum): + UNSET = "UNSET" + ALT = "ALT" + OPT = "OPT" + PAR = "PAR" + LOOP = "LOOP" + CRITICAL = "CRITICAL" + NEG = "NEG" + ASSERT = "ASSERT" + STRICT = "STRICT" + SEQ = "SEQ" + IGNORE = "IGNORE" + CONSIDER = "CONSIDER" + + +@_enum.unique +class MessageKind(_StringyEnumMixin, _enum.Enum): + """Identifies the type of message. + + This concept is similar to UML ``MessageSort``. + """ + + UNSET = "UNSET" + """The message kind is not specified.""" + ASYNCHRONOUS_CALL = "ASYNCHRONOUS_CALL" + """The message was generated by an asynchronous call to an operation. + + Equivalent to UML ``MessageSort::asynchCall``. + """ + SYNCHRONOUS_CALL = "SYNCHRONOUS_CALL" + """The message was generated by a synchronous call to an operation. + + Equivalent to UML ``MessageSort::synchCall``. + """ + REPLY = "REPLY" + """The message is a reply message to an operation call. + + Equivalent to UML ``MessageSort::reply``. + """ + DELETE = "DELETE" + """The message designates the termination of another lifeline. + + Equivalent to UML ``MessageSort::deleteMessage``. + """ + CREATE = "CREATE" + """The message designates the creation of an instance role.""" + TIMER = "TIMER" + + @_enum.unique class NumericTypeKind(_StringyEnumMixin, _enum.Enum): """The kind of this numeric data type.""" @@ -232,6 +426,42 @@ class NumericTypeKind(_StringyEnumMixin, _enum.Enum): FLOAT = "FLOAT" +@_enum.unique +class ObjectNodeKind(_StringyEnumMixin, _enum.Enum): + """The behavior type of the object node with respect to incoming data.""" + + UNSPECIFIED = "Unspecified" + """Used when incoming object node management policy is not specified.""" + NO_BUFFER = "NoBuffer" + """Discard incoming tokens if they are refused. + + When the "nobuffer" stereotype is applied to object nodes, tokens + arriving at the node are discarded if they are refused by outgoing + edges, or refused by actions for object nodes that are input pins. + """ + OVERWRITE = "Overwrite" + """Incoming tokens may overwrite existing ones. + + When the "overwrite" stereotype is applied to object nodes, a token + arriving at a full object node replaces the ones already there. A + full object node has as many tokens as allowed by its upper bound. + """ + + +@_enum.unique +class ObjectNodeOrderingKind(_StringyEnumMixin, _enum.Enum): + """Indicates queuing order within a node.""" + + FIFO = "FIFO" + """First In First Out ordering.""" + LIFO = "LIFO" + """Last In First Out ordering.""" + ORDERED = "ordered" + """Indicates that object node tokens are ordered.""" + UNORDERED = "unordered" + """Indicates that object node tokens are unordered.""" + + @_enum.unique class OrientationPortKind(_StringyEnumMixin, _enum.Enum): """Direction of component ports.""" @@ -246,6 +476,50 @@ class OrientationPortKind(_StringyEnumMixin, _enum.Enum): """The port represents both an input and on output of the component.""" +@_enum.unique +class ParameterDirection(_StringyEnumMixin, _enum.Enum): + """The direction in which data is passed along through a parameter.""" + + IN = "IN" + """The parameter represents an input of the operation it is used in.""" + OUT = "OUT" + """The parameter represents an output of the operation it is used in.""" + INOUT = "INOUT" + """The parameter represents both an input and output of the operation.""" + RETURN = "RETURN" + """The parameter represents the return value of the operation.""" + EXCEPTION = "EXCEPTION" + """The parameter is like an exception.""" + UNSET = "UNSET" + """The CommunicationLink protocol is not yet set.""" + + +@_enum.unique +class ParameterEffectKind(_StringyEnumMixin, _enum.Enum): + """A behavior's effect on values passed in or out of its parameters.""" + + CREATE = "create" + """The parameter value is being created upon behavior execution.""" + READ = "read" + """The parameter value is only being read upon behavior execution.""" + UPDATE = "update" + """The parameter value is being updated upon behavior execution.""" + DELETE = "delete" + """The parameter value is being deleted upon behavior execution.""" + + +@_enum.unique +class PassingMode(_StringyEnumMixin, _enum.Enum): + """The data passing mechanism for parameters of an operation.""" + + UNSET = "UNSET" + """The data passing mechanism is not precised.""" + BY_REF = "BY_REF" + """The data is being passed by reference to the operation.""" + BY_VALUE = "BY_VALUE" + """The data is being passed by value to the operation.""" + + @_enum.unique class PhysicalComponentKind(_StringyEnumMixin, _enum.Enum): """Categories of physical components. @@ -302,6 +576,18 @@ class PhysicalComponentNature(_StringyEnumMixin, _enum.Enum): """ +@_enum.unique +class RateKind(_StringyEnumMixin, _enum.Enum): + """The possible caracterizations for the rate of a streaming parameter.""" + + UNSPECIFIED = "Unspecified" + """The rate kind is not specified.""" + CONTINUOUS = "Continuous" + """The rate characterizes a continuous flow.""" + DISCRETE = "Discrete" + """The rate characterizes a discrete flow.""" + + @_enum.unique class ScenarioKind(_StringyEnumMixin, _enum.Enum): UNSET = "UNSET" @@ -311,6 +597,58 @@ class ScenarioKind(_StringyEnumMixin, _enum.Enum): FUNCTIONAL = "FUNCTIONAL" +@_enum.unique +class SynchronismKind(_StringyEnumMixin, _enum.Enum): + """The synchronicity of an operation invocation.""" + + UNSET = "UNSET" + SYNCHRONOUS = "SYNCHRONOUS" + ASYNCHRONOUS = "ASYNCHRONOUS" + + +@_enum.unique +class TimeEventKind(_StringyEnumMixin, _enum.Enum): + AT = "AT" + """Trigger at a specific time. + + An absolute time trigger is specified with the keyword 'at' followed + by an expression that evaluates to a time value, such as 'Jan. 1, + 2000, Noon'. + """ + AFTER = "AFTER" + """Trigger after a relative time duration has passed. + + A relative time trigger is specified with the keyword 'after' + followed by an expression that evaluates to a time value, such as + 'after (5 seconds)'. + """ + + +@_enum.unique +class TransitionKind(_StringyEnumMixin, _enum.Enum): + INTERNAL = "internal" + LOCAL = "local" + EXTERNAL = "external" + + +@_enum.unique +class UnaryOperator(_StringyEnumMixin, _enum.Enum): + """The operator of a unary expression.""" + + UNSET = "UNSET" + """The unary operator is not initialized.""" + NOT = "NOT" + """The unary operator refers to a NOT operation.""" + POS = "POS" + """The unary operator refers to a position operation.""" + VAL = "VAL" + """The unary operator refers to a value operation.""" + SUC = "SUC" + """The unary operator refers to a successor operation.""" + PRE = "PRE" + """The unary operator refers to a predecessor operation.""" + + @_enum.unique class UnionKind(_StringyEnumMixin, _enum.Enum): UNION = "UNION" diff --git a/scripts/generate_enums.py b/scripts/generate_enums.py new file mode 100755 index 00000000..f460a935 --- /dev/null +++ b/scripts/generate_enums.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python +# SPDX-FileCopyrightText: Copyright DB InfraGO AG +# SPDX-License-Identifier: Apache-2.0 + +from __future__ import annotations + +import logging +import re +from typing import NamedTuple + +import click +from lxml import etree + +import capellambse +from capellambse import helpers + + +@click.command() +@click.argument( + "metamodel", + default="git+https://github.com/eclipse-capella/capella.git", +) +def main(metamodel: str): + """Import all EEnum definitions from the given METAMODEL.""" + logging.basicConfig(level="INFO") + handler = capellambse.get_filehandler(metamodel) + + print("import enum as _enum") + print("class _StringyEnumMixin: ...") + + classes = {} + for path in handler.rootdir.rglob("*.ecore"): + with path.open("rb") as file: + tree = etree.parse(file) + for elem in tree.getroot().iter(): + if ( + elem.tag != "eClassifiers" + or helpers.xtype_of(elem) != "ecore:EEnum" + ): + continue + + clsname = elem.attrib["name"] + if clsname in classes: + continue + + literals = [ + Literal(l.attrib["name"], l.get("value", "0"), getdoc(l)) + for l in elem.iterchildren("eLiterals") + ] + classes[clsname] = Class(clsname, literals, getdoc(elem)) + + for i, cls in enumerate(sorted(classes.values())): + if i: + print("\n\n", end="") + + print("@_enum.unique") + print(f"class {cls.name}(_StringyEnumMixin, _enum.Enum):") + if cls.doc: + print(f' """{cls.doc}"""\n') + for l in cls.literals: + print(f" {fixname(l.name)} = {l.name!r}") + if l.doc: + print(f' """{l.doc}"""') + + +def getdoc(elem: etree._Element) -> str: + try: + annotation = next( + i + for i in elem.iterchildren("eAnnotations") + if i.get("source") + == "http://www.polarsys.org/kitalpha/ecore/documentation" + ) + except StopIteration: + return "" + + detail = annotation.xpath(".//details[@key='description']/@value") + if not detail: + return "" + return detail[0].replace("\r", "") + + +def fixname(name: str) -> str: + return re.sub( + r"[a-z]+", + lambda m: m.group(0).upper() + "_" * (m.span(0)[1] != len(name)), + name, + ) + + +class Class(NamedTuple): + name: str + literals: list[Literal] + doc: str + + +class Literal(NamedTuple): + name: str + value: str + doc: str + + +if __name__ == "__main__": + main()