From d0a4420390dfb8595f0a01de96cebbcb033931e9 Mon Sep 17 00:00:00 2001 From: Markus Hamann <markus.hamann1@tu-dresden.de> Date: Wed, 11 Dec 2024 11:24:26 +0100 Subject: [PATCH] Add base solution for exercise 5 --- README.md | 95 ++++--- model_examples/saxony.transportation_network | 20 +- .../.gitattributes | 12 + .../.gitignore | 5 + .../README.md | 24 ++ .../build.gradle | 98 +++++++ .../gradle.properties | 6 + .../gradle/libs.versions.toml | 2 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 43583 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + .../gradlew | 252 ++++++++++++++++++ .../gradlew.bat | 94 +++++++ .../metamodel/transportation_network.ecore | 77 ++++++ .../saxony_original.transportation_network | 45 ++++ .../report/.gitkeep | 0 .../scripts/rewrite.etl | 98 +++++++ .../scripts/test.eunit | 20 ++ .../settings.gradle | 9 + .../.project | 11 + .../validation.evl | 70 +++++ 20 files changed, 902 insertions(+), 43 deletions(-) create mode 100644 stgroup.mdsd.transportation_network.test/.gitattributes create mode 100644 stgroup.mdsd.transportation_network.test/.gitignore create mode 100644 stgroup.mdsd.transportation_network.test/README.md create mode 100644 stgroup.mdsd.transportation_network.test/build.gradle create mode 100644 stgroup.mdsd.transportation_network.test/gradle.properties create mode 100644 stgroup.mdsd.transportation_network.test/gradle/libs.versions.toml create mode 100644 stgroup.mdsd.transportation_network.test/gradle/wrapper/gradle-wrapper.jar create mode 100644 stgroup.mdsd.transportation_network.test/gradle/wrapper/gradle-wrapper.properties create mode 100644 stgroup.mdsd.transportation_network.test/gradlew create mode 100644 stgroup.mdsd.transportation_network.test/gradlew.bat create mode 100644 stgroup.mdsd.transportation_network.test/metamodel/transportation_network.ecore create mode 100644 stgroup.mdsd.transportation_network.test/model/saxony_original.transportation_network create mode 100644 stgroup.mdsd.transportation_network.test/report/.gitkeep create mode 100644 stgroup.mdsd.transportation_network.test/scripts/rewrite.etl create mode 100644 stgroup.mdsd.transportation_network.test/scripts/test.eunit create mode 100644 stgroup.mdsd.transportation_network.test/settings.gradle create mode 100644 stgroup.mdsd.transportation_network.validation/.project create mode 100644 stgroup.mdsd.transportation_network.validation/validation.evl diff --git a/README.md b/README.md index b430448..91860e9 100644 --- a/README.md +++ b/README.md @@ -1,51 +1,84 @@ # MDSD Example: Transportation Network - Sources -## Exercise 01 - Metamodel +## Exercise 05 - Model Validation and Testing -This repository includes the resources of the first task of the MDSD Example "Transportation Network". +This repository includes the resources of the 5. task of the MDSD Example "Transportation Network". ## Task Description -The main task of the exercise is to create a **metamodel for the domain of transportation networks**. +his exercise provides an introduction to **Model Validation** and **Testing of Model Transformations**. While similar, model validation focuses on validating syntactic or semantic constraints inside models. Model test engines validate the correctness of model transformations like model-to-model transformations or model rewrites. -To realize that, we use the *Eclipse Modeling Framework* to create the metamodel and afterwards prepare **multiple networks** to test the metamodel. These also double as test models for following exercises. +In this exercise, we will focus on validation and testing using the already known *Epsilon*[^epsilon] language family [@kolovos2010epsilon], particularly the **Epsilon Validation Language (EVL)**, to validate our *transportation network* models, and **EUnit**, which is a unit test framework for EMF, XML, JSON, ... models -To do so, complete the following subtasks: +[^epsilon]: [https://www.eclipse.org/epsilon/](https://www.eclipse.org/epsilon/) -1. Create an `Ecore Modeling Project` for your *transportation network metamodel* in your *Eclipse Modeling Tool* instance. +1. At first, you need to prepare an Epsilon EVL environment: - - `New...`➔`Other...`➔`Ecore Modeling Project` - - Name the project as you like - - The most important information is the `main package name` (second page) which will be the name of your metamodel and the file name extension of future models. + 1. Open an *Eclipse* workspace with your *transportation network* metamodel projects or import them into a new workspace. `Run` one metamodel project `as` an `Eclipse Application` to register the metamodel in *Eclipse*. **In the new *Eclipse* instance** you can start using *Epsilon*. -2. Model your metamodel in the `*.ecore` file. Use the editor that should open on project creation. See the **description of the transportation network** for details. - - - You only need to use the `Class`, `Attribut`, `Enumeration` `Reference`, `Composition`, and `Supertype` meta-elements for this example. - - Try to design the `Class`es connected by `Composition`s like a tree (containment hierarchy).The root of the tree should be an `Class` that represence your model itself ( for example `Transportation Network`). All classes except a root class should have (at least) one incoming composition. Use `Reference`s for non-containment relationships. - - Try too specify the properties of the metamodel elements as clear as possible in the property explorer below the diagram (The explorer shows the properties of the element selected in the diagram). + 2. *Epsilon* does not need specific projects to work. Create a new general `Project` in your workspace and create a new `*.evl` file. -3. Create the `Model`, `Edit`, and `Editor` implementation code through the `*.genmodel` file (open the file and right-click on the root element). This will generate the metamodel implementation and an editor plugin for *Eclipse*. -4. Right-click on the model project and choose `Run As...` and then `Eclipse Application`. A new *runtime* *Eclipse* instance will open. -5. There, create a new general `Project` with the `New...` option and a model `*.[your metamodel name]` with `New...`➔`Other...`➔`search for your metamodel name` (Please choose the metamodel's root element as `Model Object` in the following wizard). You should now be able to model your state machine with a *simple tree editor* by opening the file. + 3. You can now declare your model validation rules in this `*.evl` file (see Task 2 for details). To familiarize yourself with *EVL* and *Epsilon*, you can use the documentation[^epsilonDokuEVL][^epsilonDokuEOL], examples[^epsilonExample], or the playground[^epsilonPlayground]. -**The domain you need to metamodel is described as following:** + 4. To run the transformation, `right-click` on the `*.evl` file and choose `Run As -> Run Configuration`. In the next window, create a new `EVL Validation` configuration, select your `*.evl` file under `Source`, and add your `source` model under `Models` (as `EMF Models`, `source` is an example name, the names of the models should be the same as the ones used in your *EVL* file). After that, you can always re-run the configuration and start the validation by clicking on `Run` in the menu. -The first part of the domain describes the transportation network itself: +[^epsilonDokuEVL]: [https://www.eclipse.org/epsilon/doc/evl/](https://www.eclipse.org/epsilon/doc/evl/) +[^epsilonDokuEOL]: [https://www.eclipse.org/epsilon/doc/eol/](https://www.eclipse.org/epsilon/doc/eol/) +[^epsilonExample]: [https://www.eclipse.org/epsilon/examples/\#epsilon-transformation-language](https://www.eclipse.org/epsilon/examples/\#epsilon-validation-language) +[^epsilonPlayground]: [https://eclipse.dev/epsilon/playground/](https://eclipse.dev/epsilon/playground/) -> A `Transportation Network` must have an `identifier` to refer to it in the database of the users. It consists of multiple `Locations` and `Road Networks`. A location can have a `name` and can include multiple `Points Of Interest`. Each point of interest (POI) can include a `name`. There are different types of POIs: -> -> - A `Rest Stop` were drivers can take their mandetory breaks. -> - A `Gas Station` which could serve one or more`Fuel Types` like `Petrol`, `Diesel`, and `Electricity`. -> - `Warehouses` that could be `Company Warehouses` (owned by the user) or `Customer Warehouses` (Here the `customer name` should be included) -> - Last, there can be `Other` POIs which have a general `type`. -> -> Road networks must have an `identifier` and a `target` and `source` location. They can be marked as `directed` to allow mono- or bidirectional usage. They also can include the `length` of the network for later fuel calculations. Each network includes multiple, but at least one, `Road`s. Each road must be `identifiable` and also include their `length`, so that later the network length could be calculated. +1. Model validation checks if syntactic and semantic constraints defined in validation rules are met within your model. They often apply automatic rewriting if possible or propose fixes for the user. -The second part of the metamodel includes information for the usage of the transportation network: + 1. Write warnings for minor problems in your transportation network models. Examples of such problems are: + - Elements without names or identifiers + - Road Networks length is still `-1`. + - A Location is isolated in the model. + - Numbers are outside of a specific/normal range. + - Road Networks have no Roads + - There is no company warehouse in the model -> The transportation network also includes `Route`s that can be planed for transportation requests. Each route has an `identifier`and can have a `start` location, `end` location and/or a `list of road networks` the route includes. To execute the routes the transportation network also includes `Vehicle`s. These can be free to use (are in the `car park` of the company) or already included in a route. One route is always driven by one vehicle. The vehicle itself must have an `identifier`, `model`, `fuel capacity` and a `fuel type`. They can include a `location` to help their management for routes in case they are free to use. + 2. Write errors for problems that need to be addressed in your transportation network models. Examples of such problems are: + - Road Networks and Routes are missing a target or source. + - Routes have no references to road networks. + - The source of a route has no `Company Warehouse` POI + - The target of a route has no `Customer Warehouse` POI + - A Route has no `Vehicle` registered + - A Route is longer than a vehicle´s fuel capacity and has no `Gas Station` POI + + 3. Try to write automatic rewrites for the errors if possible or try to provide fixes to propose to the user. + +3. Next, you need to prepare an Epsilon EUnit environment: + 1. Download the **Epsilon Gradle Example**[^epsilongradleexample] and use it as a base. + + 2. If needed, create a new `*.eunit` file in the `./scripts` folder to write your model tests or use the existing file. + + 3. You can now declare your model testing rules in the `*.eunit` files (see Task 4 for details). To familiarize yourself with *EUnit* and *Epsilon*, you can use the documentation[^epsilonDokuEUnit][^epsilonDokuEOL], examples[^epsilonExampleEUnit], or the playground[^epsilonPlayground]. + + 4. Also, you can take a look at the documentation of the epsilon workflow support [^epsilongradle][^epsilonant] + + 5. To run the transformation, `right-click` on the `*.eunit` file and choose `Run As -> Run Configuration`. In the next window, create a new `EVL Validation` configuration, select your `*.eunit` file under `Source`, and add both your `source` and `target` models under `Models` (as `EMF Models`, `source` is an example name, the names of the models should be the same as the ones used in your *EUnit* file). After that, you can always re-run the configuration and start the transformation by clicking on `Run` in the menu. + +[^epsilonDokuEUnit]: [https://www.eclipse.org/epsilon/doc/eunit/](https://www.eclipse.org/epsilon/doc/eunit/) +[^epsilongradleexample]: [https://git-st.inf.tu-dresden.de/open-teaching-resources/model-driven-software-development/transportation_network-mdsd-pipeline/transportation_network-mdsd-epsilongradleexample](https://git-st.inf.tu-dresden.de/open-teaching-resources/model-driven-software-development/transportation_network-mdsd-pipeline/transportation_network-mdsd-epsilongradleexample) +[^epsilongradle]: [https://eclipse.dev/epsilon/doc/articles/running-epsilon-ant-tasks-from-command-line/#gradle](https://eclipse.dev/epsilon/doc/articles/running-epsilon-ant-tasks-from-command-line/#gradle) +[^epsilonant]: [https://eclipse.dev/epsilon/doc/workflow/](https://eclipse.dev/epsilon/doc/workflow/) +[^epsilonExampleEUnit]: [https://www.eclipse.org/epsilon/examples/\#eunit](https://www.eclipse.org/epsilon/examples/\#eunit) + +4. Model testing checks for semantic or syntactic errors introduced by other model transformations or rewrites. It can be compared to unit testing your MDSD *'programs'*. + + 1. Prepare a target model of a transformation you want to check and an expected model. + 1. Create a `.eunit` file to write your tests. + 2. Compare the target model with the expected model via a `EUnit` `@Test` + + 2. Prepare a source and a target model of a transformation you want to check. + 1. Try to abstract failure points from your model transformation and create a @Test for each test case. + 2. Abstract the expected rewrites from the source model and write assertions, checking if these rewrites exist in the target model. + + 3. (Optional) Prepare a source and a target model of a transformation you want to check. + 1. Try to use an EVL script inside your tests to check for validation problems caused by the transformation in the target model. ## How To Run the Base Solution -1. `Import` the `stgroup.mdsd.transportation_network.*` projects in your *Eclipse* workspace. -2. In the runtime *Eclipse* instance `import` the `model_examples` project to inspect and modify the example *transportation network* models. +1. `Import` the `stgroup.mdsd.transportation_network.metamodel.*` projects in your *Eclipse* workspace. +2. In the runtime *Eclipse* instance `import` the `model_examples` and the `stgroup.mdsd.transportation_network.metamodel` project and run the epsilone engine like it us described in exercise 4. +3. Run the gradle project in `stgroup.mdsd.transportation_network.test` like it is described in its `README.md` diff --git a/model_examples/saxony.transportation_network b/model_examples/saxony.transportation_network index bfce380..4c5cec4 100644 --- a/model_examples/saxony.transportation_network +++ b/model_examples/saxony.transportation_network @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <transportation_network:TransportationNetwork xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:transportation_network="http://www.stgroup.org/transportation_network" identifier="saxony"> - <roadnetworks identifier="DG" length="95.0" source="//@locations.0" target="//@locations.3"> + <roadnetworks identifier="DG" length="95.0" target="//@locations.3"> <roads identifier="A4" length="95.0"/> </roadnetworks> <roadnetworks identifier="DL" length="102.0" source="//@locations.0" target="//@locations.2"> @@ -8,12 +8,10 @@ <roads identifier="A14" length="67.0"/> <roads identifier="A38" length="15.0"/> </roadnetworks> - <roadnetworks identifier="DC" length="64.0" source="//@locations.0" target="//@locations.1"> + <roadnetworks identifier="DC" source="//@locations.0" target="//@locations.1"> <roads identifier="A4" length="64.0"/> </roadnetworks> - <roadnetworks identifier="LC" length="69.0" source="//@locations.2" target="//@locations.1"> - <roads identifier="A72" length="69.0"/> - </roadnetworks> + <roadnetworks identifier="LC" length="69.0" source="//@locations.2" target="//@locations.1"/> <locations name="Dresden"> <pois xsi:type="transportation_network:RestStop"/> <pois xsi:type="transportation_network:GasStation"> @@ -21,10 +19,8 @@ <fueltypes>DIESEL</fueltypes> <fueltypes>ELECTRICITY</fueltypes> </pois> - <pois xsi:type="transportation_network:CompanyWarehouse" name="A1"/> </locations> <locations name="Chemnitz"> - <pois xsi:type="transportation_network:CustomerWarehouse" name="OG-01" customerName="Office GmbH"/> <pois xsi:type="transportation_network:Other" name="Owner`s Home" type="Private House"/> </locations> <locations name="Leipzig"> @@ -38,9 +34,9 @@ <fueltypes>DIESEL</fueltypes> </pois> </locations> - <routes identifier="R1" networkList="//@roadnetworks.1 //@roadnetworks.3" start="//@locations.0" end="//@locations.1"> - <vehicle identifier="V03" location="//@locations.0" model="eTruck" fuelCapacity="150.0"/> - </routes> - <carPark identifier="V01" location="//@locations.0" model="eTruck" fuelCapacity="150.0"/> - <carPark identifier="V02" location="//@locations.2" model="eTruck" fuelCapacity="150.0"/> + <locations name="IsolatedLocation"/> + <routes identifier="R1" start="//@locations.0" end="//@locations.1"/> + <carPark identifier="V02" location="//@locations.2" model="eTruck" fuelCapacity="-150.0"/> + <carPark identifier="V03" location="//@locations.0" model="eTruck" fuelCapacity="150.0"/> + <carPark identifier="" location="//@locations.0" model="eTruck" fuelCapacity="150.0"/> </transportation_network:TransportationNetwork> diff --git a/stgroup.mdsd.transportation_network.test/.gitattributes b/stgroup.mdsd.transportation_network.test/.gitattributes new file mode 100644 index 0000000..f91f646 --- /dev/null +++ b/stgroup.mdsd.transportation_network.test/.gitattributes @@ -0,0 +1,12 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# Linux start script should use lf +/gradlew text eol=lf + +# These are Windows script files and should use crlf +*.bat text eol=crlf + +# Binary files should be left untouched +*.jar binary + diff --git a/stgroup.mdsd.transportation_network.test/.gitignore b/stgroup.mdsd.transportation_network.test/.gitignore new file mode 100644 index 0000000..1b6985c --- /dev/null +++ b/stgroup.mdsd.transportation_network.test/.gitignore @@ -0,0 +1,5 @@ +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore Gradle build output directory +build diff --git a/stgroup.mdsd.transportation_network.test/README.md b/stgroup.mdsd.transportation_network.test/README.md new file mode 100644 index 0000000..51ec64c --- /dev/null +++ b/stgroup.mdsd.transportation_network.test/README.md @@ -0,0 +1,24 @@ +# Epsilon Gradle Example for the Transportation Network Example + +This repository gives a simple working example of the usage of EMF models (model transformation and unit testing) outside the direct eclipse ecosystem. + +The example uses [Epsilon](https://eclipse.dev/epsilon/) and [Gradle](https://gradle.org/) to create a simple CI pipeline. + +The goal is to give interested students a base project to build their own MDSD pipeline. + +## Usage + +The example pipeline has three Parts. + +1. Create a copy of the original model with: + ``` + ./gradlew copyOriginalModel + ``` +2. Transform/Rewrite the copy with + ``` + ./gradlew transform + ``` +3. Test if the transformation was running by comparing the original model with the rewritten copy. Run the tests with: + ``` + ./gradlew test + ``` \ No newline at end of file diff --git a/stgroup.mdsd.transportation_network.test/build.gradle b/stgroup.mdsd.transportation_network.test/build.gradle new file mode 100644 index 0000000..017e5f9 --- /dev/null +++ b/stgroup.mdsd.transportation_network.test/build.gradle @@ -0,0 +1,98 @@ +configurations { + epsilon +} + +repositories { + mavenCentral() +} + +dependencies { + epsilon 'org.eclipse.epsilon:org.eclipse.epsilon.workflow:2.5.0' + epsilon 'org.eclipse.epsilon:org.eclipse.epsilon.workflow.emf:2.5.0' + epsilon 'org.eclipse.epsilon:org.eclipse.epsilon.eunit.cmp.emf:2.5.0' +} + +task setupEpsilonTasks { + // Set up the core Epsilon tasks + ant.taskdef(resource: 'org/eclipse/epsilon/workflow/tasks/tasks.xml', + classpath: configurations.epsilon.asPath, loaderref: 'epsilon') + // Set up the Epsilon EMF tasks + ant.taskdef(resource: 'org/eclipse/epsilon/workflow/tasks/emf/tasks.xml', + classpath: configurations.epsilon.asPath, loaderref: 'epsilon') + // Set logging level to info so that EOL's println() is not suppressed + ant.lifecycleLogLevel = 'INFO' +} + +task copyOriginalModel(type: Copy) { + from file(dir_model + 'saxony_original.transportation_network') + into dir_model + rename 'saxony_original','saxony' +} + +task register_source { + dependsOn setupEpsilonTasks, copyOriginalModel + + doFirst{ + // Load the EMF model + ant.'epsilon.emf.loadModel'( name: 'source', + modelfile: dir_model + 'saxony.transportation_network', + metamodelfile: dir_metamodel + 'transportation_network.ecore', + read: "true", + store: "true") + } +} + +task register_target { + dependsOn setupEpsilonTasks + + doFirst{ + // Load the EMF model + ant.'epsilon.emf.loadModel'( name: 'target', + modelfile: dir_model + 'saxony_t.transportation_network', + metamodelfile: dir_metamodel + 'transportation_network.ecore', + read: "false", + store: "false") + } +} + +task transform { + dependsOn register_source, register_target + + doFirst{ + ant.'epsilon.etl'(src: dir_script + "rewrite.etl"){ + model(ref: "source", alias: "source") + model(ref: "target", alias: "target") + } + } + + doLast{ + ant.'epsilon.disposeModel'(model: "source") + ant.'epsilon.disposeModel'(model: "target") + } + +} + +task test{ + dependsOn setupEpsilonTasks + + doFirst{ + ant.'epsilon.eunit'(src: dir_script + "test.eunit", failOnErrors: false, toDir: "./report/", report: "yes"){ + modelTasks() { + ant.'epsilon.emf.loadModel'( name: 'transformed', + modelfile: dir_model + 'saxony.transportation_network', + metamodelfile: dir_metamodel + 'transportation_network.ecore', + read: "true", + store: "false") + ant.'epsilon.emf.loadModel'( name: 'original', + modelfile: dir_model + 'saxony_original.transportation_network', + metamodelfile: dir_metamodel + 'transportation_network.ecore', + read: "true", + store: "false") + } + comparators() { + comparator(classname: 'org.eclipse.epsilon.eunit.cmp.emf.EMFModelComparator') + } + } + } + +} \ No newline at end of file diff --git a/stgroup.mdsd.transportation_network.test/gradle.properties b/stgroup.mdsd.transportation_network.test/gradle.properties new file mode 100644 index 0000000..59f0f28 --- /dev/null +++ b/stgroup.mdsd.transportation_network.test/gradle.properties @@ -0,0 +1,6 @@ +# This file was generated by the Gradle 'init' task. +# https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties + +dir_metamodel =./metamodel/ +dir_script =./scripts/ +dir_model =./model/ \ No newline at end of file diff --git a/stgroup.mdsd.transportation_network.test/gradle/libs.versions.toml b/stgroup.mdsd.transportation_network.test/gradle/libs.versions.toml new file mode 100644 index 0000000..4ac3234 --- /dev/null +++ b/stgroup.mdsd.transportation_network.test/gradle/libs.versions.toml @@ -0,0 +1,2 @@ +# This file was generated by the Gradle 'init' task. +# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format diff --git a/stgroup.mdsd.transportation_network.test/gradle/wrapper/gradle-wrapper.jar b/stgroup.mdsd.transportation_network.test/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..a4b76b9530d66f5e68d973ea569d8e19de379189 GIT binary patch literal 43583 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 literal 0 HcmV?d00001 diff --git a/stgroup.mdsd.transportation_network.test/gradle/wrapper/gradle-wrapper.properties b/stgroup.mdsd.transportation_network.test/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..e2847c8 --- /dev/null +++ b/stgroup.mdsd.transportation_network.test/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/stgroup.mdsd.transportation_network.test/gradlew b/stgroup.mdsd.transportation_network.test/gradlew new file mode 100644 index 0000000..f5feea6 --- /dev/null +++ b/stgroup.mdsd.transportation_network.test/gradlew @@ -0,0 +1,252 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/stgroup.mdsd.transportation_network.test/gradlew.bat b/stgroup.mdsd.transportation_network.test/gradlew.bat new file mode 100644 index 0000000..9d21a21 --- /dev/null +++ b/stgroup.mdsd.transportation_network.test/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/stgroup.mdsd.transportation_network.test/metamodel/transportation_network.ecore b/stgroup.mdsd.transportation_network.test/metamodel/transportation_network.ecore new file mode 100644 index 0000000..43d35f6 --- /dev/null +++ b/stgroup.mdsd.transportation_network.test/metamodel/transportation_network.ecore @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="transportation_network" nsURI="http://www.stgroup.org/transportation_network" + nsPrefix="transportation_network"> + <eClassifiers xsi:type="ecore:EClass" name="TransportationNetwork" eSuperTypes="#//IdentifiableElement"> + <eStructuralFeatures xsi:type="ecore:EReference" name="roadnetworks" upperBound="-1" + eType="#//RoadNetwork" containment="true"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="locations" upperBound="-1" + eType="#//Location" containment="true"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="routes" upperBound="-1" + eType="#//Route" containment="true"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="carPark" upperBound="-1" + eType="#//Vehicle" containment="true"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="Location" eSuperTypes="#//NamedElement"> + <eStructuralFeatures xsi:type="ecore:EReference" name="pois" upperBound="-1" eType="#//PointOfInterest" + containment="true"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="RoadNetwork" eSuperTypes="#//IdentifiableElement"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="isDirected" lowerBound="1" + eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EBoolean" defaultValueLiteral="false"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="length" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDouble" + defaultValueLiteral="-1.0"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="source" lowerBound="1" + eType="#//Location"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="target" lowerBound="1" + eType="#//Location"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="roads" upperBound="-1" + eType="#//Road" containment="true"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="Road" eSuperTypes="#//IdentifiableElement"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="length" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDouble" + defaultValueLiteral="0.0"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="IdentifiableElement" abstract="true"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="identifier" lowerBound="1" + eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="PointOfInterest" abstract="true" eSuperTypes="#//NamedElement"/> + <eClassifiers xsi:type="ecore:EClass" name="NamedElement" abstract="true"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="RestStop" eSuperTypes="#//PointOfInterest"/> + <eClassifiers xsi:type="ecore:EClass" name="GasStation" eSuperTypes="#//PointOfInterest"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="fueltypes" lowerBound="1" + upperBound="-1" eType="#//FuelType"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EEnum" name="FuelType"> + <eLiterals name="PETROL"/> + <eLiterals name="DIESEL" value="1"/> + <eLiterals name="ELECTRICITY" value="2"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="Warehouse" abstract="true" eSuperTypes="#//PointOfInterest"/> + <eClassifiers xsi:type="ecore:EClass" name="Other" eSuperTypes="#//PointOfInterest"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="type" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="CompanyWarehouse" eSuperTypes="#//Warehouse"/> + <eClassifiers xsi:type="ecore:EClass" name="CustomerWarehouse" eSuperTypes="#//Warehouse"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="customerName" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="Route" eSuperTypes="#//IdentifiableElement"> + <eStructuralFeatures xsi:type="ecore:EReference" name="networkList" upperBound="-1" + eType="#//RoadNetwork"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="start" eType="#//Location"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="end" eType="#//Location"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="vehicle" lowerBound="1" + eType="#//Vehicle" containment="true"/> + </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="Vehicle" eSuperTypes="#//IdentifiableElement"> + <eStructuralFeatures xsi:type="ecore:EReference" name="location" eType="#//Location"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="model" lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="fuelCapacity" lowerBound="1" + eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDouble"/> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="fuelType" lowerBound="1" + eType="#//FuelType" defaultValueLiteral="ELECTRICITY"/> + </eClassifiers> +</ecore:EPackage> diff --git a/stgroup.mdsd.transportation_network.test/model/saxony_original.transportation_network b/stgroup.mdsd.transportation_network.test/model/saxony_original.transportation_network new file mode 100644 index 0000000..3cdd3ef --- /dev/null +++ b/stgroup.mdsd.transportation_network.test/model/saxony_original.transportation_network @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<transportation_network:TransportationNetwork xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:transportation_network="http://www.stgroup.org/transportation_network" identifier="saxony"> + <roadnetworks identifier="DG" length="95.0" source="//@locations.0" target="//@locations.3"> + <roads identifier="A4" length="95.0"/> + </roadnetworks> + <roadnetworks identifier="DL" length="102.0" source="//@locations.0" target="//@locations.2"> + <roads identifier="A4" length="20.0"/> + <roads identifier="A14" length="67.0"/> + <roads identifier="A38" length="15.0"/> + </roadnetworks> + <roadnetworks identifier="DC" length="64.0" source="//@locations.0" target="//@locations.1"> + <roads identifier="A4" length="64.0"/> + </roadnetworks> + <roadnetworks identifier="LC" length="69.0" source="//@locations.2" target="//@locations.1"> + <roads identifier="A72" length="69.0"/> + </roadnetworks> + <locations name="Dresden"> + <pois xsi:type="transportation_network:RestStop"/> + <pois xsi:type="transportation_network:GasStation"> + <fueltypes>PETROL</fueltypes> + <fueltypes>DIESEL</fueltypes> + <fueltypes>ELECTRICITY</fueltypes> + </pois> + </locations> + <locations name="Chemnitz"> + <pois xsi:type="transportation_network:CustomerWarehouse" name="OG-01" customerName="Office GmbH"/> + <pois xsi:type="transportation_network:Other" name="Owner`s Home" type="Private House"/> + </locations> + <locations name="Leipzig"> + <pois xsi:type="transportation_network:CustomerWarehouse" name="DA-01" customerName="Delivery AG"/> + <pois xsi:type="transportation_network:RestStop"/> + </locations> + <locations name="Görlitz"> + <pois xsi:type="transportation_network:RestStop"/> + <pois xsi:type="transportation_network:GasStation"> + <fueltypes>PETROL</fueltypes> + <fueltypes>DIESEL</fueltypes> + </pois> + </locations> + <routes identifier="R1" networkList="//@roadnetworks.1 //@roadnetworks.3" start="//@locations.0" end="//@locations.1"> + <vehicle identifier="V01" location="//@locations.0" model="eTruck" fuelCapacity="150.0"/> + </routes> + <carPark identifier="V02" location="//@locations.2" model="eTruck" fuelCapacity="150.0"/> + <carPark identifier="V03" location="//@locations.0" model="eTruck" fuelCapacity="150.0"/> +</transportation_network:TransportationNetwork> diff --git a/stgroup.mdsd.transportation_network.test/report/.gitkeep b/stgroup.mdsd.transportation_network.test/report/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/stgroup.mdsd.transportation_network.test/scripts/rewrite.etl b/stgroup.mdsd.transportation_network.test/scripts/rewrite.etl new file mode 100644 index 0000000..eca5cfe --- /dev/null +++ b/stgroup.mdsd.transportation_network.test/scripts/rewrite.etl @@ -0,0 +1,98 @@ +/* +* Example of extending by rewriting a model. +* Here: Splitting a road network if the network +* use multiple roads. +*/ + +/* +* Normal configuration: +* Source model: Read=true, Write=true +* Target model: Read=false, Write=false +*/ + +pre { + "Model Extending/Rewrite Example".println(); + "-------------------------------------".println(); + "Start of transformation...".println(); +} + +post { + "... End of transformation.".println(); +} + +/* +* Option 1: Have a rule for the model elements which need to be extended. +* Write the extended elements in your source model. +*/ + +rule SplitRoadNetworks + transform s : source!Road + to l : source!Location, + rn : source!RoadNetwork + { + + var originalRN:source!RoadNetwork = s.eContainer(); + var network:source!TransportationNetwork = originalRN.eContainer(); + + network.roadnetworks.add(rn); + network.locations.add(l); + + rn.identifier = originalRN.identifier + "/" + originalRN.roads.size(); + rn.roads.add(s); + rn.length = s.length; + rn.source = originalRN.source; + if (originalRN.roads.isEmpty()){ + rn.target = originalRN.target; + delete l; + } else{ + rn.target = l; + originalRN.source = l; + } + +} + + +rule deleteEmptyRoadNetworks + transform s : source!RoadNetwork + to t : target!EObject + { + + if(s.roads.isEmpty()){ + delete s; + } +} + + +/* +* Optional Part for merging Road Networks with the help of an operation +*/ +rule mergeRoadNetworks + transform s : source!TransportationNetwork + to t : target!EObject{ + + for (r in s.roadnetworks) { + var toBeMergeRNs = r.RNtoMerge(); + if(not toBeMergeRNs.isEmpty()){ + toBeMergeRNs.add(r); + var minRoad = toBeMergeRNs.sortBy(rn | rn.roads.first().length).first(); + toBeMergeRNs.remove(minRoad); + for (mergingRN in toBeMergeRNs) { + mergingRN.source = minRoad.target; + mergingRN.roads.first().length -= minRoad.roads.first().length; + mergingRN.length = mergingRN.roads.first().length; + } + } + } +} + +operation source!RoadNetwork RNtoMerge() : Set { + if(self.eContainer() <> null){ + return self.eContainer().roadnetworks.select(rn | rn.source.equals(self.source) + and not (rn == self)) + .select(rn | (rn.roads.size() == 1) + and (rn.roads.first().identifier == self.roads.first().identifier)); + } else{ + return new Set; + } + +} diff --git a/stgroup.mdsd.transportation_network.test/scripts/test.eunit b/stgroup.mdsd.transportation_network.test/scripts/test.eunit new file mode 100644 index 0000000..99401b0 --- /dev/null +++ b/stgroup.mdsd.transportation_network.test/scripts/test.eunit @@ -0,0 +1,20 @@ +@Test +operation testModelChanged() { + assertNotEqualModels("The model should have be changed by a transformation!", "transformed", "original"); +} + +@Test +operation testNumberOfLocations() { + var numLocNew:Integer = transformed!Location.all().size(); + var numLocBefore:Integer = original!Location.all().size(); + assertEquals("The original Model should have 4 Locations. It has " + numLocBefore, numLocBefore, 4); + assertEquals("The transformed Model should have 6 Locations. It has " + numLocNew, numLocNew, 6); +} + +@Test +operation RoadNetworksShouldOnlyHaveOneRoad() { + for(rn in transformed!RoadNetwork.all()){ + var numRoads:Integer = rn.roads.size(); + assertEquals(rn.identifier + " should have 1 road, but it has " + numRoads, numRoads, 1); + } +} \ No newline at end of file diff --git a/stgroup.mdsd.transportation_network.test/settings.gradle b/stgroup.mdsd.transportation_network.test/settings.gradle new file mode 100644 index 0000000..29655b9 --- /dev/null +++ b/stgroup.mdsd.transportation_network.test/settings.gradle @@ -0,0 +1,9 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * The settings file is used to specify which projects to include in your build. + * For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.11.1/userguide/multi_project_builds.html in the Gradle documentation. + * This project uses @Incubating APIs which are subject to change. + */ + +rootProject.name = 'EpsilonGradleExample' diff --git a/stgroup.mdsd.transportation_network.validation/.project b/stgroup.mdsd.transportation_network.validation/.project new file mode 100644 index 0000000..d45f5a3 --- /dev/null +++ b/stgroup.mdsd.transportation_network.validation/.project @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>stgroup.mdsd.transportation_network.validation</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + </buildSpec> + <natures> + </natures> +</projectDescription> diff --git a/stgroup.mdsd.transportation_network.validation/validation.evl b/stgroup.mdsd.transportation_network.validation/validation.evl new file mode 100644 index 0000000..db955f9 --- /dev/null +++ b/stgroup.mdsd.transportation_network.validation/validation.evl @@ -0,0 +1,70 @@ +pre{ + "Model Validation Example".println(); + "-------------------------------------".println(); + "Start of validation...".println(); + +} + +post{ + "... End of validation.".println(); +} + +context source!NamedElement { + + critique ElementWithoutName{ + + guard: not self.isKindOf(source!Location) + + check: self.name <> null and not self.name.isEmpty() and not self.name.isBlank() + + message: "Name of an element should not be empty! Element: " + self + + fix { + title: "Give a default name" + do { + self.name = self.type().name + source!NamedElement.all().size(); + } + } + } +} + +context source!IdentifiableElement{ + + critique ElementWithoutId{ + + check: self.identifier <> null and not self.identifier.isEmpty() and not self.identifier.isBlank() + + message { + self.identifier = self.type().name + source!IdentifiableElement.all().size(); + return "Id of an element should not be empty! Default id was set! Element: " + self; + } + + } + +} + +context source!RoadNetwork{ + + constraint RoadNetworkWithoutSourceOrTarget{ + + check{ + var resultSource:Boolean = self.source <> null; + var resultTarget:Boolean = self.target <> null; + return (resultSource and resultTarget); + } + + message { + var returnMsg = "Element: " + self; + if(not resultTarget){ + returnMsg = "Target of a RoadNetwork must be set! " + returnMsg; + } + if(not resultSource){ + returnMsg = "Source of a RoadNetwork must be set! " + returnMsg; + } + return returnMsg; + } + + } + +} + -- GitLab