|
@@ -4,7 +4,7 @@
|
|
|
"cell_type": "markdown",
|
|
|
"metadata": {},
|
|
|
"source": [
|
|
|
- "# Create a new metamodel"
|
|
|
+ "# Initialization"
|
|
|
]
|
|
|
},
|
|
|
{
|
|
@@ -32,7 +32,7 @@
|
|
|
"cell_type": "markdown",
|
|
|
"metadata": {},
|
|
|
"source": [
|
|
|
- "## New metamodel"
|
|
|
+ "# New metamodel"
|
|
|
]
|
|
|
},
|
|
|
{
|
|
@@ -55,8 +55,7 @@
|
|
|
"cell_type": "markdown",
|
|
|
"metadata": {},
|
|
|
"source": [
|
|
|
- "Add the different attributes to be used, and define their name.\n",
|
|
|
- "Action language attributes can also be used, which goes outside of the simple attributes."
|
|
|
+ "We can now easily add an instance model."
|
|
|
]
|
|
|
},
|
|
|
{
|
|
@@ -65,46 +64,92 @@
|
|
|
"metadata": {},
|
|
|
"outputs": [],
|
|
|
"source": [
|
|
|
- "model_add(\"formalisms/MyOwnFSA\", \"formalisms/SimpleClassDiagrams\", \"\"\"\n",
|
|
|
- " include \"primitives.alh\"\n",
|
|
|
- "\n",
|
|
|
- " SimpleAttribute String {\n",
|
|
|
- " name = \"String\"\n",
|
|
|
- " }\n",
|
|
|
- "\n",
|
|
|
- " ActionLanguage Action {}\n",
|
|
|
- " \"\"\")"
|
|
|
+ "model_add(\"my_FSA\", \"formalisms/MyOwnFSA\")"
|
|
|
]
|
|
|
},
|
|
|
{
|
|
|
"cell_type": "markdown",
|
|
|
"metadata": {},
|
|
|
"source": [
|
|
|
- "Attributes are defined manually by the language engineer, so the constraints must also be made explicit, by mapping it to physical primitives."
|
|
|
+ "Nonetheless, we cannot instantiate any element in that model, as the metamodel is empty."
|
|
|
]
|
|
|
},
|
|
|
{
|
|
|
"cell_type": "code",
|
|
|
"execution_count": 4,
|
|
|
"metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "data": {
|
|
|
+ "text/plain": [
|
|
|
+ "set()"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ "execution_count": 4,
|
|
|
+ "metadata": {},
|
|
|
+ "output_type": "execute_result"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "types(\"my_FSA\")"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "And indeed, instantiating a state yields an exception."
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 5,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "name": "stdout",
|
|
|
+ "output_type": "stream",
|
|
|
+ "text": [
|
|
|
+ "Type State not defined!\n"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "try:\n",
|
|
|
+ " instantiate(\"my_FSA\", \"State\")\n",
|
|
|
+ "except UnknownElement:\n",
|
|
|
+ " print(\"Type State not defined!\")"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "# Creating classes"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "A first step is to define some classes that we would like to use, such as states and transitions.\n",
|
|
|
+ "This is done as follows, similar to the usual model instantiation."
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 6,
|
|
|
+ "metadata": {},
|
|
|
"outputs": [],
|
|
|
"source": [
|
|
|
"model_add(\"formalisms/MyOwnFSA\", \"formalisms/SimpleClassDiagrams\", \"\"\"\n",
|
|
|
- " include \"primitives.alh\"\n",
|
|
|
- " include \"modelling.alh\"\n",
|
|
|
- "\n",
|
|
|
- " SimpleAttribute String {\n",
|
|
|
- " name = \"String\"\n",
|
|
|
- " constraint = $\n",
|
|
|
- " String function constraint(model : Element, name : String):\n",
|
|
|
- " if (is_physical_string(model[\"model\"][name])):\n",
|
|
|
- " return \"OK\"!\n",
|
|
|
- " else:\n",
|
|
|
- " return \"String has non-string value\"!\n",
|
|
|
- " $\n",
|
|
|
+ " Class State {\n",
|
|
|
+ " name = \"State\"\n",
|
|
|
" }\n",
|
|
|
"\n",
|
|
|
- " ActionLanguage Action {}\n",
|
|
|
+ " Association Transition (State, State) {\n",
|
|
|
+ " name = \"Transition\"\n",
|
|
|
+ " }\n",
|
|
|
" \"\"\")"
|
|
|
]
|
|
|
},
|
|
@@ -112,45 +157,86 @@
|
|
|
"cell_type": "markdown",
|
|
|
"metadata": {},
|
|
|
"source": [
|
|
|
- "Add the different classes and associations of the metamodel."
|
|
|
+ "This allows us to instantiate elements of these types."
|
|
|
]
|
|
|
},
|
|
|
{
|
|
|
"cell_type": "code",
|
|
|
- "execution_count": 5,
|
|
|
+ "execution_count": 7,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "data": {
|
|
|
+ "text/plain": [
|
|
|
+ "{('State', 'Class'),\n",
|
|
|
+ " ('State.name', 'String'),\n",
|
|
|
+ " ('Transition', 'Association'),\n",
|
|
|
+ " ('Transition.name', 'String'),\n",
|
|
|
+ " ('__1049623', 'Class_name'),\n",
|
|
|
+ " ('__1049695', 'Class_name')}"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ "execution_count": 7,
|
|
|
+ "metadata": {},
|
|
|
+ "output_type": "execute_result"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "types(\"my_FSA\")"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 8,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "data": {
|
|
|
+ "text/plain": [
|
|
|
+ "'__1054163'"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ "execution_count": 8,
|
|
|
+ "metadata": {},
|
|
|
+ "output_type": "execute_result"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "instantiate(\"my_FSA\", \"State\")"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "# Inheritance"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "Another useful operation is to define inheritance between classes or associations.\n",
|
|
|
+ "For example, we can add the notion of an initial state, being a special case of the normal state."
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 9,
|
|
|
"metadata": {},
|
|
|
"outputs": [],
|
|
|
"source": [
|
|
|
"model_add(\"formalisms/MyOwnFSA\", \"formalisms/SimpleClassDiagrams\", \"\"\"\n",
|
|
|
- " include \"primitives.alh\"\n",
|
|
|
- " include \"modelling.alh\"\n",
|
|
|
- "\n",
|
|
|
- " SimpleAttribute String {\n",
|
|
|
- " name = \"String\"\n",
|
|
|
- " constraint = $\n",
|
|
|
- " String function constraint(model : Element, name : String):\n",
|
|
|
- " if (is_physical_string(model[\"model\"][name])):\n",
|
|
|
- " return \"OK\"!\n",
|
|
|
- " else:\n",
|
|
|
- " return \"String has non-string value\"!\n",
|
|
|
- " $\n",
|
|
|
- " }\n",
|
|
|
- "\n",
|
|
|
- " ActionLanguage Action {}\n",
|
|
|
- "\n",
|
|
|
" Class State {\n",
|
|
|
" name = \"State\"\n",
|
|
|
+ " }\n",
|
|
|
"\n",
|
|
|
- " constraint = $\n",
|
|
|
- " String function constraint(model : Element, name : String):\n",
|
|
|
- " if (string_len(read_attribute(model, name, \"name\")) > 3):\n",
|
|
|
- " return \"OK\"!\n",
|
|
|
- " else:\n",
|
|
|
- " return \"Name is too short\"!\n",
|
|
|
- " $\n",
|
|
|
+ " Class InitialState : State {\n",
|
|
|
+ " name = \"InitialState\"\n",
|
|
|
" }\n",
|
|
|
"\n",
|
|
|
" Association Transition (State, State) {\n",
|
|
|
+ " name = \"Transition\"\n",
|
|
|
" }\n",
|
|
|
" \"\"\")"
|
|
|
]
|
|
@@ -159,28 +245,58 @@
|
|
|
"cell_type": "markdown",
|
|
|
"metadata": {},
|
|
|
"source": [
|
|
|
- "Define attributes in the state and transitions, using the previously defined attribute types."
|
|
|
+ "And indeed, this allows us to create an initial state, which is handled as both an instance of state and initial."
|
|
|
]
|
|
|
},
|
|
|
{
|
|
|
"cell_type": "code",
|
|
|
- "execution_count": 6,
|
|
|
+ "execution_count": 10,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "name": "stdout",
|
|
|
+ "output_type": "stream",
|
|
|
+ "text": [
|
|
|
+ "All initial element IDs: {'__1063142'}\n",
|
|
|
+ "All state element IDs: {'__1054163', '__1063142'}\n"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "instantiate(\"my_FSA\", \"InitialState\")\n",
|
|
|
+ "print(\"All initial element IDs: \" + str(all_instances(\"my_FSA\", \"InitialState\")))\n",
|
|
|
+ "print(\"All state element IDs: \" + str(all_instances(\"my_FSA\", \"State\")))"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "# Attributes"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "On these classes and transitions, we want to define some attributes which instances can use.\n",
|
|
|
+ "To do that, however, we need to define attribute types.\n",
|
|
|
+ "The Modelverse does not predefine any attribute types at the modelling level (only physically), thereby giving the user full control over the supported types."
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 11,
|
|
|
"metadata": {},
|
|
|
"outputs": [],
|
|
|
"source": [
|
|
|
"model_add(\"formalisms/MyOwnFSA\", \"formalisms/SimpleClassDiagrams\", \"\"\"\n",
|
|
|
" include \"primitives.alh\"\n",
|
|
|
" include \"modelling.alh\"\n",
|
|
|
+ " include \"object_operations.alh\"\n",
|
|
|
"\n",
|
|
|
" SimpleAttribute String {\n",
|
|
|
" name = \"String\"\n",
|
|
|
- " constraint = $\n",
|
|
|
- " String function constraint(model : Element, name : String):\n",
|
|
|
- " if (is_physical_string(model[\"model\"][name])):\n",
|
|
|
- " return \"OK\"!\n",
|
|
|
- " else:\n",
|
|
|
- " return \"String has non-string value\"!\n",
|
|
|
- " $\n",
|
|
|
" }\n",
|
|
|
"\n",
|
|
|
" ActionLanguage Action {}\n",
|
|
@@ -188,20 +304,17 @@
|
|
|
" Class State {\n",
|
|
|
" name = \"State\"\n",
|
|
|
" name : String\n",
|
|
|
+ " }\n",
|
|
|
"\n",
|
|
|
- " constraint = $\n",
|
|
|
- " String function constraint(model : Element, name : String):\n",
|
|
|
- " if (string_len(read_attribute(model, name, \"name\")) > 3):\n",
|
|
|
- " return \"OK\"!\n",
|
|
|
- " else:\n",
|
|
|
- " return \"Name is too short\"!\n",
|
|
|
- " $\n",
|
|
|
+ " Class InitialState : State {\n",
|
|
|
+ " name = \"InitialState\"\n",
|
|
|
" }\n",
|
|
|
"\n",
|
|
|
" Association Transition (State, State) {\n",
|
|
|
- " trigger? : String {}\n",
|
|
|
- " raise? : String {}\n",
|
|
|
- " script? : Action {}\n",
|
|
|
+ " name = \"Transition\"\n",
|
|
|
+ " trigger : String {}\n",
|
|
|
+ " raise : String {}\n",
|
|
|
+ " script : Action {}\n",
|
|
|
" }\n",
|
|
|
" \"\"\")"
|
|
|
]
|
|
@@ -210,18 +323,130 @@
|
|
|
"cell_type": "markdown",
|
|
|
"metadata": {},
|
|
|
"source": [
|
|
|
- "Still missing the initial state, which we can define using inheritance."
|
|
|
+ "Now attributes can be instantiated on these instances."
|
|
|
]
|
|
|
},
|
|
|
{
|
|
|
"cell_type": "code",
|
|
|
- "execution_count": 7,
|
|
|
+ "execution_count": 12,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "name": "stdout",
|
|
|
+ "output_type": "stream",
|
|
|
+ "text": [
|
|
|
+ "{'name': 'FirstState'}\n"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "new_state = instantiate(\"my_FSA\", \"State\")\n",
|
|
|
+ "attr_assign(\"my_FSA\", new_state, \"name\", \"FirstState\")\n",
|
|
|
+ "print(read_attrs(\"my_FSA\", new_state))"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "Note, however, that our model now no longer conforms: there are still some states that do not have any value for the name attribute.\n",
|
|
|
+ "Indeed, our metamodel has evolved, thereby invalidating the model."
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 13,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "name": "stdout",
|
|
|
+ "output_type": "stream",
|
|
|
+ "text": [
|
|
|
+ "Lower cardinality violation for outgoing edge of type State_name at NODE __1054163 (ID: 1054163)\n"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "print(verify(\"my_FSA\", \"formalisms/MyOwnFSA\"))"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "If we now assign a value for every state that does not have a name, the model conforms again."
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 14,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "name": "stdout",
|
|
|
+ "output_type": "stream",
|
|
|
+ "text": [
|
|
|
+ "OK\n"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "for counter, state in enumerate(all_instances(\"my_FSA\", \"State\")):\n",
|
|
|
+ " attr_assign(\"my_FSA\", state, \"name\", \"State_\" + str(counter))\n",
|
|
|
+ "print(verify(\"my_FSA\", \"formalisms/MyOwnFSA\"))"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "# Attribute Constraints"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "As there are no types predefined, all constraints must be specified by the language engineer directly.\n",
|
|
|
+ "As such, it is now possible to assign whatever value to the attributes, as they are unconstrained."
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 15,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "name": "stdout",
|
|
|
+ "output_type": "stream",
|
|
|
+ "text": [
|
|
|
+ "OK\n"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "attr_assign(\"my_FSA\", new_state, \"name\", 123)\n",
|
|
|
+ "print(verify(\"my_FSA\", \"formalisms/MyOwnFSA\"))"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "We can now start constraining our custom string type as being a direct mapping to the physical type string, as defined in the MvS.\n",
|
|
|
+ "This is done by assigning a constraint function to the attribute."
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 16,
|
|
|
"metadata": {},
|
|
|
"outputs": [],
|
|
|
"source": [
|
|
|
"model_add(\"formalisms/MyOwnFSA\", \"formalisms/SimpleClassDiagrams\", \"\"\"\n",
|
|
|
" include \"primitives.alh\"\n",
|
|
|
" include \"modelling.alh\"\n",
|
|
|
+ " include \"object_operations.alh\"\n",
|
|
|
"\n",
|
|
|
" SimpleAttribute String {\n",
|
|
|
" name = \"String\"\n",
|
|
@@ -239,23 +464,17 @@
|
|
|
" Class State {\n",
|
|
|
" name = \"State\"\n",
|
|
|
" name : String\n",
|
|
|
- " \n",
|
|
|
- " constraint = $\n",
|
|
|
- " String function constraint(model : Element, name : String):\n",
|
|
|
- " if (string_len(read_attribute(model, name, \"name\")) > 3):\n",
|
|
|
- " return \"OK\"!\n",
|
|
|
- " else:\n",
|
|
|
- " return \"Name is too short\"!\n",
|
|
|
- " $\n",
|
|
|
" }\n",
|
|
|
"\n",
|
|
|
" Class InitialState : State {\n",
|
|
|
+ " name = \"InitialState\"\n",
|
|
|
" }\n",
|
|
|
"\n",
|
|
|
" Association Transition (State, State) {\n",
|
|
|
- " trigger? : String {}\n",
|
|
|
- " raise? : String {}\n",
|
|
|
- " script? : Action {}\n",
|
|
|
+ " name = \"Transition\"\n",
|
|
|
+ " trigger : String {}\n",
|
|
|
+ " raise : String {}\n",
|
|
|
+ " script : Action {}\n",
|
|
|
" }\n",
|
|
|
" \"\"\")"
|
|
|
]
|
|
@@ -264,12 +483,46 @@
|
|
|
"cell_type": "markdown",
|
|
|
"metadata": {},
|
|
|
"source": [
|
|
|
- "Require that there is exactly one initial state, by using a global constraint."
|
|
|
+ "This yields the expected result."
|
|
|
]
|
|
|
},
|
|
|
{
|
|
|
"cell_type": "code",
|
|
|
- "execution_count": 8,
|
|
|
+ "execution_count": 17,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "name": "stdout",
|
|
|
+ "output_type": "stream",
|
|
|
+ "text": [
|
|
|
+ "String has non-string value\n"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "attr_assign(\"my_FSA\", new_state, \"name\", 123)\n",
|
|
|
+ "print(verify(\"my_FSA\", \"formalisms/MyOwnFSA\"))"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "# Global Constraints"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "Similarly, global constraints can also be defined, which get access to the complete model.\n",
|
|
|
+ "These are special elements, similar to classes.\n",
|
|
|
+ "In this case, we check that there is at least one instance of the InitialState class."
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 18,
|
|
|
"metadata": {},
|
|
|
"outputs": [],
|
|
|
"source": [
|
|
@@ -294,23 +547,17 @@
|
|
|
" Class State {\n",
|
|
|
" name = \"State\"\n",
|
|
|
" name : String\n",
|
|
|
- "\n",
|
|
|
- " constraint = $\n",
|
|
|
- " String function constraint(model : Element, name : String):\n",
|
|
|
- " if (string_len(read_attribute(model, name, \"name\")) > 3):\n",
|
|
|
- " return \"OK\"!\n",
|
|
|
- " else:\n",
|
|
|
- " return \"Name is too short\"!\n",
|
|
|
- " $\n",
|
|
|
" }\n",
|
|
|
"\n",
|
|
|
" Class InitialState : State {\n",
|
|
|
+ " name = \"InitialState\"\n",
|
|
|
" }\n",
|
|
|
"\n",
|
|
|
" Association Transition (State, State) {\n",
|
|
|
- " trigger? : String {}\n",
|
|
|
- " raise? : String {}\n",
|
|
|
- " script? : Action {}\n",
|
|
|
+ " name = \"Transition\"\n",
|
|
|
+ " trigger : String {}\n",
|
|
|
+ " raise : String {}\n",
|
|
|
+ " script : Action {}\n",
|
|
|
" }\n",
|
|
|
"\n",
|
|
|
" GlobalConstraint {\n",
|
|
@@ -333,12 +580,24 @@
|
|
|
"cell_type": "markdown",
|
|
|
"metadata": {},
|
|
|
"source": [
|
|
|
- "More efficient implementation using predefined constructs (lower_cardinality and upper_cardinality)."
|
|
|
+ "# Local Constraint Helpers"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "Most constraints are related to the multiplicities of associations and classes.\n",
|
|
|
+ "For example, we want to make sure that there is exactly one instance of a specific class (e.g., InitialState).\n",
|
|
|
+ "Similarly, for an association we might want to define that there is at least one such.\n",
|
|
|
+ "The Modelverse provides various such attributes that can be set.\n",
|
|
|
+ "For example, to constrain the number of instances, use the *lower_cardinality* and *upper_cardinality* attributes.\n",
|
|
|
+ "For associations, there are additionally the *source_lower_cardinality*, *source_upper_cardinality*, *target_lower_cardinality*, and *target_upper_cardinality* attributes."
|
|
|
]
|
|
|
},
|
|
|
{
|
|
|
"cell_type": "code",
|
|
|
- "execution_count": 9,
|
|
|
+ "execution_count": 19,
|
|
|
"metadata": {},
|
|
|
"outputs": [],
|
|
|
"source": [
|
|
@@ -363,22 +622,76 @@
|
|
|
" Class State {\n",
|
|
|
" name = \"State\"\n",
|
|
|
" name : String\n",
|
|
|
+ " }\n",
|
|
|
+ "\n",
|
|
|
+ " Class InitialState : State {\n",
|
|
|
+ " name = \"InitialState\"\n",
|
|
|
+ " lower_cardinality = 1\n",
|
|
|
+ " upper_cardinality = 1\n",
|
|
|
+ " }\n",
|
|
|
"\n",
|
|
|
+ " Association Transition (State, State) {\n",
|
|
|
+ " name = \"Transition\"\n",
|
|
|
+ " trigger : String {}\n",
|
|
|
+ " raise : String {}\n",
|
|
|
+ " script : Action {}\n",
|
|
|
+ " }\n",
|
|
|
+ " \"\"\")"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "# Optional Attributes"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "Often, not all of the attributes are mandatory, and they can therefore be left empty.\n",
|
|
|
+ "During conformance checking, these attributes are then not enforced.\n",
|
|
|
+ "When reading out their value, however, the language engineer must take care that the value might be empty."
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 20,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "model_add(\"formalisms/MyOwnFSA\", \"formalisms/SimpleClassDiagrams\", \"\"\"\n",
|
|
|
+ " include \"primitives.alh\"\n",
|
|
|
+ " include \"modelling.alh\"\n",
|
|
|
+ " include \"object_operations.alh\"\n",
|
|
|
+ "\n",
|
|
|
+ " SimpleAttribute String {\n",
|
|
|
+ " name = \"String\"\n",
|
|
|
" constraint = $\n",
|
|
|
" String function constraint(model : Element, name : String):\n",
|
|
|
- " if (string_len(read_attribute(model, name, \"name\")) > 3):\n",
|
|
|
+ " if (is_physical_string(model[\"model\"][name])):\n",
|
|
|
" return \"OK\"!\n",
|
|
|
" else:\n",
|
|
|
- " return \"Name is too short\"!\n",
|
|
|
+ " return \"String has non-string value\"!\n",
|
|
|
" $\n",
|
|
|
" }\n",
|
|
|
"\n",
|
|
|
+ " ActionLanguage Action {}\n",
|
|
|
+ "\n",
|
|
|
+ " Class State {\n",
|
|
|
+ " name = \"State\"\n",
|
|
|
+ " name : String\n",
|
|
|
+ " }\n",
|
|
|
+ "\n",
|
|
|
" Class InitialState : State {\n",
|
|
|
+ " name = \"InitialState\"\n",
|
|
|
" lower_cardinality = 1\n",
|
|
|
" upper_cardinality = 1\n",
|
|
|
" }\n",
|
|
|
"\n",
|
|
|
" Association Transition (State, State) {\n",
|
|
|
+ " name = \"Transition\"\n",
|
|
|
" trigger? : String {}\n",
|
|
|
" raise? : String {}\n",
|
|
|
" script? : Action {}\n",
|
|
@@ -386,6 +699,13 @@
|
|
|
" \"\"\")"
|
|
|
]
|
|
|
},
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "# Incremental Construction"
|
|
|
+ ]
|
|
|
+ },
|
|
|
{
|
|
|
"cell_type": "markdown",
|
|
|
"metadata": {},
|
|
@@ -395,7 +715,7 @@
|
|
|
},
|
|
|
{
|
|
|
"cell_type": "code",
|
|
|
- "execution_count": 13,
|
|
|
+ "execution_count": 21,
|
|
|
"metadata": {},
|
|
|
"outputs": [],
|
|
|
"source": [
|
|
@@ -419,23 +739,15 @@
|
|
|
"state = instantiate(mm, \"Class\")\n",
|
|
|
"attr_assign(mm, state, \"name\", \"State\")\n",
|
|
|
"define_attribute(mm, state, \"name\", str_attr)\n",
|
|
|
- "attr_assign_code(mm, state, \"constraint\", \"\"\"\n",
|
|
|
- " include \"primitives.alh\"\n",
|
|
|
- " include \"modelling.alh\"\n",
|
|
|
- " \n",
|
|
|
- " String function constraint(model : Element, name : String):\n",
|
|
|
- " if (string_len(read_attribute(model, name, \"name\")) > 3):\n",
|
|
|
- " return \"OK\"!\n",
|
|
|
- " else:\n",
|
|
|
- " return \"Name is too short\"!\n",
|
|
|
- " \"\"\")\n",
|
|
|
"\n",
|
|
|
"initial = instantiate(mm, \"Class\")\n",
|
|
|
+ "attr_assign(mm, initial, \"name\", \"InitialState\")\n",
|
|
|
"instantiate(mm, \"Inheritance\", edge=(initial, state))\n",
|
|
|
"attr_assign(mm, initial, \"lower_cardinality\", 1)\n",
|
|
|
"attr_assign(mm, initial, \"upper_cardinality\", 1)\n",
|
|
|
"\n",
|
|
|
"transition = instantiate(mm, \"Association\", edge=(state, state))\n",
|
|
|
+ "attr_assign(mm, transition, \"name\", \"Transition\")\n",
|
|
|
"define_attribute(mm, transition, \"trigger\", str_attr)\n",
|
|
|
"attribute_optional(mm, transition, \"trigger\", True)\n",
|
|
|
"define_attribute(mm, transition, \"raise\", str_attr)\n",
|
|
@@ -443,13 +755,6 @@
|
|
|
"define_attribute(mm, transition, \"script\", al_attr)\n",
|
|
|
"attribute_optional(mm, transition, \"script\", True)"
|
|
|
]
|
|
|
- },
|
|
|
- {
|
|
|
- "cell_type": "code",
|
|
|
- "execution_count": null,
|
|
|
- "metadata": {},
|
|
|
- "outputs": [],
|
|
|
- "source": []
|
|
|
}
|
|
|
],
|
|
|
"metadata": {
|