diff --git a/.github/workflows/deploy_snapshot.yml b/.github/workflows/deploy_snapshot.yml
index 7f04315b..9083cb7b 100644
--- a/.github/workflows/deploy_snapshot.yml
+++ b/.github/workflows/deploy_snapshot.yml
@@ -15,7 +15,7 @@ on:
types: [ trigger_after_upstream_deploy ]
env:
- GRADLE_VERSION: 8.5 # Gradle version used
+ GRADLE_VERSION: 8.14.5 # Gradle version used
JAVA_VERSION: 21 # Java version used
GRADLE_CLI_OPTS: "-Pci --build-cache --refresh-dependencies" # CLI options passed to Gradle
GRADLE_BUILD_ACTION_CACHE_KEY_JOB: "test-cache-${{ github.head_ref }}.${{ github.sha }}"
diff --git a/.github/workflows/test_branch.yml b/.github/workflows/test_branch.yml
index aeb5d8a9..5c846bd0 100644
--- a/.github/workflows/test_branch.yml
+++ b/.github/workflows/test_branch.yml
@@ -12,7 +12,7 @@ on:
branches-ignore: [ "dev" ] # Do not run this on the default branch
env:
- GRADLE_VERSION: 8.5 # Gradle version used
+ GRADLE_VERSION: 8.14.5 # Gradle version used
JAVA_VERSION: 21 # Java version used
GRADLE_CLI_OPTS: "-Pci --build-cache --refresh-dependencies" # CLI options passed to Gradle
GRADLE_BUILD_ACTION_CACHE_KEY_JOB: "test-cache-${{ github.head_ref }}.${{ github.sha }}"
diff --git a/.gitignore b/.gitignore
index 500d5bb5..2c6baa4b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,7 +10,6 @@ target/
**/.idea
**/target
.attach_pid*
-gradle.properties
**/.gradle
gradle/
gradlew
diff --git a/README.md b/README.md
index 8ea25223..0a993d26 100644
--- a/README.md
+++ b/README.md
@@ -1,21 +1,65 @@
-This documentation is intended for **modelers** who use the object diagram (OD) languages. A
-detailed documentation for **language engineers** using or extending the OD language is
-located **[here](src/main/grammars/de/monticore/OD4Report.md)**. We recommend that **language
-engineers** read this documentation before reading the detailed documentation.
-
-# An Example Model
-
-
- Figure 1: The graphical syntax of an example OD.
-
-
-
-Figure 1 depicts the OD ```MyFamily``` in graphical syntax. In textual syntax, the OD is defined as
-follows:
-
-```
+This documentation is primarily intended for **modelers** who work with object diagrams
+and want to use the **OD4Development** tool effectively. The goal is to help you become
+productive quickly, perform common modeling tasks confidently, and generate direct value
+from ODs (for example, deriving a class diagram).
+
+For **language engineers** (language development, grammar work, tool extensions), detailed
+technical documentation is available at
+[`src/main/grammars/de/monticore/OD4Development.md`](src/main/grammars/de/monticore/OD4Development.md).
+
+# Table of Contents
+
+- [What is OD4Development?](#what-is-od4development)
+- [Example Model](#example-model)
+- [OD Language Primer](#od-language-primer)
+ - [Object Diagrams](#object-diagrams)
+ - [Comments](#comments)
+ - [Packages and Imports](#packages-and-imports)
+ - [Objects](#objects)
+ - [Attributes and Values](#attributes-and-values)
+ - [Links](#links)
+ - [When CD References Are Required](#when-cd-references-are-required)
+- [Setup and Build](#setup-and-build)
+ - [Prerequisites](#prerequisites)
+ - [Getting the Tools](#getting-the-tools)
+- [Focus: OD4Development](#focus-od4development)
+ - [Quick Start](#quick-start)
+ - [CLI Reference: OD4Development](#cli-reference-od4development)
+ - [Typical Workflows](#typical-workflows)
+ - [1) Run CoCos](#1-run-cocos)
+ - [2) Pretty Printing](#2-pretty-printing)
+ - [3) Export Symbol Table](#3-export-symbol-table)
+ - [4) Resolve Symbols](#4-resolve-symbols-via--path)
+ - [5) Derive a Class Diagram from an OD](#5-derive-a-class-diagram-from-an-od--o)
+- [Further Information](#further-information)
+
+# What is OD4Development?
+
+OD4Development provides a complete toolchain for working with object diagrams:
+
+- **Model validation**: Constraint-on-Context (CoCo) checks verify model consistency and correctness
+ beyond syntax—catching logical issues before downstream processing.
+- **Model normalization**: Pretty printing reformats ODs into a canonical style, useful for version
+ control and team collaboration.
+- **Symbol management**: Export and import symbol tables to share type information across models
+ and enable cross-model references.
+- **Artifact derivation**: Generate class diagrams from ODs, creating a structured view of the
+ instances and relationships described in your model.
+- **Transparent feedback**: All operations report their results clearly via the command line,
+ making it easy to diagnose issues and verify success.
+
+# Example Model
+
+
+
+ Figure 1: The graphical syntax of the example OD.
+
+
+Figure 1 shows the OD `MyFamily`. In textual form:
+
+```txt
objectdiagram MyFamily {
alice:Person {
age = 29;
@@ -39,330 +83,346 @@ objectdiagram MyFamily {
}
```
-This was for us the most intuitive textual representation of ODs, which follows the syntax of class
-diagrams.
-
-# Command Line Tool
+This notation is intentionally aligned with the readability of class diagram syntax.
-This section describes the command line tool of the OD language. The tool provides typical functionality
-used when processing models. To this effect, it provides funcionality for
+# OD Language Primer
-* parsing,
-* coco-checking,
-* pretty-printing,
-* creating symbol tables,
-* storing symbols in symbol files,
-* ,and loading symbols from symbol files.
+This section gives a compact introduction to the OD language using the examples from this repository.
-The requirements for building and using the OD tool are that Java 21, Git, and Gradle 8.5 are
-installed and available for use in Bash.
+## Object Diagrams
-The following subsection describes how to download the tool. Then, this document describes how
-to build the tool from the source files. Afterward, this document contains a tutorial for using
-the tool.
+OD models are stored in `.od` files. Each file starts with `objectdiagram { ... }` and
+contains object instances and links between them.
-## Tool Set Up
-
-This section explains how to set up the command line interface tools for the OD languages. Each tool
-is contained in a separate jar file, which is produced as result of building the project with
-gradle. The following explains this.
+```txt
+objectdiagram Example {
+ // objects and links
+}
+```
-### Tool Download
+## Comments
-* [**Download OD Language OD4Data**][od4data-link]
-* [**Download OD Language OD4Report**][od4report-link]
+The textual syntax supports Java-style comments.
-Alternatively, the tools can be built from source code.
+```txt
+/** Multi-line comment */
+objectdiagram Example {
+ // Single-line comment
+}
+```
-### Prerequisites
+## Packages and Imports
-To build the project, it is required to install a Java 21 JDK and git.
+You can organize models with `package` declarations and import symbols from other models.
+Imports are especially useful when your OD references external types.
-#### Step 1: Clone Project with git
+```txt
+package my.examples;
+import Types.*;
- git clone
- cd od
+objectdiagram Example {
+ ...
+}
+```
-#### Step 2: Build Project with gradle
+## Objects
- gradle build --refresh-dependencies
+Objects are declared as `: { ... };`, for example `alice:Person { ... };`.
+The `MyFamily` example also shows anonymous typed objects like `:BMW { ... }`.
-Afterward, the jars of the tools are available in `od/target/libs`.
+```txt
+objectdiagram Example {
+ alice:Person {
+ age = 29;
+ };
-## Tutorial: Getting Started Using the OD Tool
+ :BMW {
+ color = BLUE;
+ };
+}
+```
-The previous sections describe how to obtain an executable JAR file
-(OD command line tool). This section provides a tutorial for using the OD tool. The following examples
-assume that you locally named the tool `MCOD4Report`. Note that after setting up the tool in the
-previous step, you will also find a `MCOD4Data`. The following instruction also hold for this tool.
+## Attributes and Values
-### Step 1: Laying the basis
+Attributes are assigned inside object blocks using `name = value;`. Values can be literals,
+lists, enum constants, and other expression forms supported by the language.
-Executing the Jar file without any options prints usage information of the tool to the console:
+```txt
+objectdiagram Example {
+ tiger:Jaguar {
+ color = RED;
+ length = 5.3;
+ };
-```
-java -jar MCOD4Report.jar
-usage: OD4ReportTool
- -c,--coco Checks the CoCos for the input ODs. Possible
- arguments are 'intra' and 'all'. When
- given the argument 'intra', only the intra-model
- CoCos are checked while when using 'all' all CoCos are
- checked. When no argument is specified, all CoCos
- are checked by default.
- -h,--help Prints this help dialog.
- -i,--input Processes the OD input artifacts specified as
- arguments. At least one input OD is mandatory.
- -path Sets the artifact path for imported symbols, space
- separated.
- -pp,--prettyprint Prints the input ODs to stdout or to the specified
- files (optional).
- -s,--symboltable Stores the serialized symbol tables of the input ODs
- in the specified files. The n-th input OD is stored
- in the file as specified by the n-th argument. If no
- arguments are given, the serialized symbol tables
- are stored in
- 'target/symbols/{packageName}/{artifactName}.odsym'
- by default.
+ bob:Person {
+ nicknames = ["Bob", "Bobby", "Robert"];
+ };
+}
```
-To work properly, the tool needs the mandatory argument `-i,--input `, which takes the file
-paths of at least one input file containing OD models. If no other arguments are specified, the
-tool solely parses the model(s).
+## Links
-For trying this out, copy the `MCOD4Report.jar` into a directory of your choice. Afterward, create
-a text file containing the following simple OD:
+Links represent relationships between object instances. In this example, you can see both
+top-level link statements and role-based references.
-```
+```txt
objectdiagram Example {
- bob:Person {
- age = 42;
- };
-
- alice:Person {
- age =40;
- };
-
- link married bob <-> alice;
+ bob:Person {
+ cars -> tiger;
+ };
+ tiger:Jaguar { };
+
+ link married bob <-> alice;
}
```
-Save the text file as `Example.od` in the directory where `MCOD4Report.jar` is located.
+## When CD References Are Required
-Now execute the following command:
+Referencing a class diagram (via imported symbol files) is **not always mandatory**.
-```
-java -jar MCOD4Report.jar -i Example.od -c intra
-```
+- You can use core tool functions like parsing and pretty printing without importing CD symbols.
+- Intra-model CoCos can also be run without full external type resolution.
+- CD symbol references become important when you want to resolve external types reliably,
+ for example in inter-model or full CoCo checks.
-You may notice that the tool prints no output to the console. This means that the tool has
-parsed the file `Example.od` successfully. Don't mind die option `c` at this point as it
-will be discussed later in step 3.
+In practice: start without imports for syntax and formatting tasks, and add `-path` plus `import`
+statements once your workflow requires cross-model type resolution.
-### Step 2: Pretty-Printing
+# Setup and Build
-The tool provides a pretty-printer for the OD language. A pretty-printer can be used, e.g., to
-fix the formatting of files containing ODs. To execute the pretty-printer, the `-pp,--prettyprint`
-option can be used. Using the option without any arguments pretty-prints the models contained in the
-input files to the console.
+## Prerequisites
-Execute the following command for trying this out:
+- Java 21 JDK
+- Git
+- Gradle 8.5+
-```
-java -jar MCOD4Report.jar -i Example.od -pp -c intra
-```
+> Note: This project has **no Gradle wrapper**. Use your locally installed
+> `gradle` command directly.
+
+## Getting the Tools
+
+You have two options:
+
+### Option A: Download Pre-built JARs (Recommended for Quick Start)
+
+Pre-built JARs are available for download:
-The command prints the pretty-printed model contained in the input file to the console:
+- [**OD4Development.jar**][od4dev-link]
+- [**OD4Report.jar**][od4report-link]
+Download the JAR you need and place it in your working directory. You can start using the tool immediately
+without any compilation step.
+
+### Option B: Build from Source
+
+Clone the repository and build locally:
+
+```bash
+git clone git@github.com:MontiCore/object-diagram.git
+cd object-diagram
+gradle build --refresh-dependencies
```
+
+Afterwards, the JARs are available in `target/libs`, including:
+
+- `MCOD4Development.jar`
+- `MCOD4Report.jar`
+
+# Focus: OD4Development
+
+## Quick Start
+
+Create an `Example.od` file:
+
+```txt
objectdiagram Example {
- bob:Person {
- age = 42;
- };
-
- alice:Person {
- age =40;
- };
-
- link married bob <-> alice;
+ bob:Person {
+ age = 42;
+ };
+
+ alice:Person {
+ age = 40;
+ };
+
+ link married bob <-> alice;
}
```
-It is possible to pretty-print the models contained in the input files to output files. For this
-task, it is possible to provide the names of output files as arguments to the `-pp,--prettyprint`
-option. If arguments for output files are provided, then the number of output files must be equal to
-the number of input files. The i-th input file is pretty-printed into the i-th output file.
+This simple example defines two persons (Bob and Alice) with their respective
+ages, and establishes a "married" link between them. It's a minimal but complete
+object diagram and therefore a good introductory example to demonstrate the
+basic syntax and testing the tool.
-Execute the following command for trying this out:
+Minimal command (parse only):
-```
-java -jar MCOD4Report.jar -i Example.od -pp PPExample.od -c intra
+```bash
+java -jar target/libs/MCOD4Development.jar -i Example.od
```
-The command prints the pretty-printed model contained in the input file into the file `PPExample.od`
+Typical successful output:
-### Step 3: Checking Context Conditions
+```txt
+Successfully parsed Example
+```
-For checking context conditions, the `-c,--coco ` option can be used. Using this option without
-any arguments checks whether the model satisfies all context conditions.
+This confirms the OD has been read and parsed without errors.
-If you are only interested in checking whether a model only satisfies a subset of the context
-conditions or want to explicate that all context conditions should be checked, you can do this by
-additionally providing one of the three arguments `intra` and `all`.
+## CLI Reference: OD4Development
-* Using the argument `intra` only executes context conditions concerning violations of intra-model
- context conditions. These context conditions, for example, check naming conventions.
-* Using the argument `all` executes all context conditions. These context conditions include
- checking whether used types exist. The behavior when using the argument `all` is also the default
- behavior when using no arguments.
+| Option | Meaning |
+| --- | --- |
+| `-h`, `--help` | Show help |
+| `-i`, `--input ` | **Required**: input OD |
+| `-path ` | Model/symbol path (multiple entries supported) |
+| `-pp`, `--prettyprint [file]` | Pretty print to stdout or file |
+| `-s`, `--symboltable [file]` | Store symbol table (`.odsym`) |
+| `-c`, `--coco [intra\|inter]` | Run CoCos (`no arg` = all CoCos) |
+| `-o`, `--output ` | Derive class diagram from OD |
+| `-d` | Enable debug logging |
-Execute the following command for trying out a simple example:
+## Typical Workflows
-```
-java -jar MCOD4Report.jar -i Example.od -c intra
-```
+### 1) Run CoCos
-You may notice that the tool prints nothing to the console when executing this command. This means
-that the model satisfies all context conditions.
+**Why?** CoCos validate your model for consistency, type correctness, and naming
+conventions to catch issues before they propagate downstream.
-Let us now consider a more complex scenario. Note that these commands do not work with the
-`MCOD4Data` Tool, since the `MyFamily.od` dates as attribute values.
-You can check the different kinds of context
-conditions, using the `-c,--coco ` option:
+Use the following command to run intra-model CoCos only:
-```
-java -jar MCOD4Report.jar -i MyFamily.od -c intra
+```bash
+java -jar target/libs/MCOD4Development.jar -i Example.od -c intra
```
-```
-java -jar MCOD4Report.jar -i MyFamily.od -c all
+Use the following command to run inter-model CoCos only:
+
+```bash
+java -jar target/libs/MCOD4Development.jar -i Example.od -c inter
```
+Use the following command to run all CoCos (intra + inter):
+
+```bash
+java -jar target/libs/MCOD4Development.jar -i Example.od -c
```
-java -jar MCOD4Report.jar -i MyFamily.od -c
+
+If no issues are found, the tool reports:
+
+```txt
+Successfully checked the CoCos for object diagram Example
```
-While the first call of the tool does not produce any errors, the others do. The error states
-something about types, in this case `Person` not being defined while being used. So how do we solve
-this problem?
+### 2) Pretty Printing
-The answer is that the symbol file of this model has to be imported by the OD model for accessing
-the type. For the OD language, we have not fixed a language for defining types. Instead, the types
-can be defined in arbitrary models of arbitrary languages, as long as the information about the
-definitions of the types are stored in the symbol files of the models and the OD imports these
-symbol files. This may sound complicated at this point, but conceptually it is actually quite
-simple. This has even a huge advantage because it allows us to use the OD language with any other
-language that defines types. You could even use languages that are not defined with MontiCore, as
-long as suitable symbol files are generated from the models of these languages.
+**Why?** Keep your ODs readable and consistent, especially in team environments.
+Pretty printing normalizes whitespace, indentation, and layout without changing
+the model's meaning.
-The following subsection describes how to fix the error in the example model `Example.od`
-by importing a symbol file defining the (yet undefined) types. .
+Use the following command to pretty print to stdout:
-### Step 4: Using the Model Path to Resolve Symbols
+```bash
+java -jar target/libs/MCOD4Development.jar -i Example.od -pp
+```
-In this section we make use of the model path and provide the tool with a symbol file (stored
-symbol table) of another model, which contains the necessary type information.
+Use the following command to pretty print to a file:
-Create a new directory `cd` in the directory where the tool `MCOD4Report.jar` is located. The
-symbol file `MyFamily.cdsym` of a model, which provides all necessary type information, can be
-found [here](doc/MyFamily.cdsym). Download the file, name it `MyFamily.cdsym`, and move it into the
-directory `cd`.
+```bash
+java -jar target/libs/MCOD4Development.jar -i Example.od -pp Example.pp.od
+```
-The contents of the symbol file are of minor importance for you as a language user. In case you are
-curious and had a look into the symbol file:
-The symbol file contains a JSON representation of the symbols defined in a model. In this case, the
-symbol file contains information about all sorts of symbols defined in a class diagram. Usually,
-the tools of MontiCore languages automatically generate the contents of these files and you, as
-a language user, must not be concerned with their contents.
+### 3) Export Symbol Table
-The path containing the directory structure that contains the symbol file is called the "Model Path"
-. If we provide the model path to the tool, it will search for symbols in symbol files, which are
-stored in directories contained in the model path. So, if we want the tool to find our symbol file,
-we have to provide the model path to the tool via the `-path ` option:
+Use the following command to export a symbol table with the default name (next to the model, e.g. `Example.odsym`):
-```
-java -jar MCOD4Report.jar -i Example.od -c -path
+```bash
+java -jar target/libs/MCOD4Development.jar -i Example.od -s
```
-where `` is the path where you stored the downloaded symbol file. In our example, in case
-you stored the model in the directory `cd`, execute the following command:
+Use the following command to export the symbol table to an explicit target path:
-```
-java -jar MCOD4Report.jar -i Example.od -c -path cd
+```bash
+java -jar target/libs/MCOD4Development.jar -i Example.od -s syms/Example.odsym
```
-Well, executing the above command still produces the same error message. This is because the symbol
-file needs to be imported first, just like in Java. Therefore, we add the following import statement
-to the beginning of the contents contained in the file `MyFamily.od` containing the OD `MyFamily`:
+On success, the tool reports:
+```txt
+Creation of symbol file successful
```
-import cd.MyFamily.*;
+
+### 4) Resolve Symbols via `-path`
+
+Object diagrams describe *instances* of types that must be defined elsewhere—typically in a class diagram.
+For example, the `MyFamily` OD uses types like `Person`, `BMW`, and `Jaguar`. These types are
+defined in a separate class diagram model, whose symbol information is stored in a symbol file
+(`.cdsym`).
+
+To validate that your OD uses only types that actually exist, you must:
+
+1. Make the symbol file(s) discoverable by setting a model path with `-path`.
+2. Import the symbol files in your OD using `import` statements.
+3. Run CoCo validation to check type references.
+
+**Example workflow:**
+
+Suppose you have a class diagram that defines `Person`, `BMW`, and `Jaguar` in a file called `Types.cd`.
+After processing that CD, you get a symbol file `Types.cdsym`. Now add to your OD:
+
+```txt
+import Types.*;
objectdiagram Example {
...
}
```
-The added import statement means that the file containing the OD imports all symbols that are stored
-in the symbol file `MyFamily`. Note that you may have to change the name here, depending on how you
-named the symbol file from above. The concrete file ending `.cdsym` is not important in this case.
-However, the file ending of the symbol file must end with `sym`, i.e., the name of the symbol file
-must be compatible to the pattern `*.*sym`. If you strictly followed the instructions of this
-tutorial, then you are fine.
-
-If we now execute the command again, the tool will print no output. This means that it processed
-the model successfully without any context condition violations. Great!
-
-### Step 5: Storing Symbols
-
-The previous section describes how to load symbols from an existing symbol file. Now, we will use
-the tool to store a symbol file for our `Example.od` model. The stored symbol file will contain
-information about the objects defined in the OD. It can be imported by other models for using the
-symbols introduced by these object definitions, similar to how we changed the file `Example.od` for
-importing the symbols contained in the symbol file `MyFamily.cdsym`.
-
-Using the `-s,-symboltable ` option builds the symbol tables of the input models and stores
-them in the file paths given as arguments. Either no file paths must be provided or exactly one file
-path has to be provided for each input model. The symbol file for the i-th input model is stored in
-the file defined by the i-th file path. If you do not provide any file paths, the tool stores
-the symbol table of each input model in the symbol
-file `target/symbols/{packageName}/{fileName}.odsym`
-where `packageName` is the name of the package as specified in the file containing the model
-and `fileName` is the name of the file containing the model. The file is stored relative to the
-working directory, i.e., the directory in which you execute the command for storing the symbol
-files. Furthermore, please notice that in order to store the symbols properly, the model has to be
-well-formed in all regards, and therefore all context conditions are checked beforehand.
-
-For storing the symbol file of `Example.od`, execute the following command
-(the implicit context condition checks require using the model path option):
+Then run validation:
-```
-java -jar MCOD4Report.jar -i Example.od -path cd -s
+```bash
+java -jar target/libs/MCOD4Development.jar -i Example.od -path cd -c
```
-The tool produces the file `target/symbols/MyFamily.odsym`, which can now be imported by other
-models, e.g., by models that need to use some of the objects defined in the OD `MyFamily`.
+Here, `cd` is the directory containing `Types.cdsym`. The tool will load the symbol file, resolve
+the type references in your OD, and report any mismatches.
-For storing the symbol file of `Example.od` in the file `syms/Example.odsym`, for example, execute
-the following command
-(again, the implicit context condition checks require using the model path option):
+**Troubleshooting symbol resolution:**
-```
-java -jar MCOD4Report.jar -i Example.od -path cd -s syms/Example.odsym
+If types cannot be resolved, check:
+
+- whether matching `*sym` files exist on the model path (file extensions must end with `sym`),
+- whether your OD `import` statements match the symbol file location and names,
+- whether `-path` points to the correct root directory containing the symbol files.
+
+### 5) Derive a Class Diagram from an OD (`-o`)
+
+**Why?** An OD shows a concrete snapshot of object instances and their relationships at a specific point in time.
+By analyzing these instances, you can reverse-engineer a class diagram that captures the underlying
+structure—the types, attributes, and associations that make up the model. This is useful when:
+
+- You have detailed instance data but need a class-level abstraction,
+- You want to document the structural design implied by your instances,
+- You need a CD as input for downstream code generation or further modeling,
+- You want to validate that your instances follow a coherent type structure.
+
+**Usage:**
+
+```bash
+java -jar target/libs/MCOD4Development.jar -i Example.od -o out
```
-Congratulations, you have just finished the tutorial about saving OD symbol files and are pretty
-much done reading this README!
+This analyzes the OD and generates a class diagram, written to the `out` directory.
+The resulting CD will contain classes for all object types referenced in the OD, their attributes,
+and the associations between them—essentially a schema that your instance data conforms to.
-## Further Information
+# Further Information
-* [Project root: MontiCore @github](https://github.com/MontiCore/monticore)
-* [MontiCore documentation](http://www.monticore.de/)
-* [**List of languages**](https://github.com/MontiCore/monticore/blob/opendev/docs/Languages.md)
-* [**MontiCore Core Grammar Library**](https://github.com/MontiCore/monticore/blob/opendev/monticore-grammar/src/main/grammars/de/monticore/Grammars.md)
-* [Best Practices](https://github.com/MontiCore/monticore/blob/opendev/docs/BestPractices.md)
-* [Publications about MBSE and MontiCore](https://www.se-rwth.de/publications/)
-* [Licence definition](https://github.com/MontiCore/monticore/blob/master/00.org/Licenses/LICENSE-MONTICORE-3-LEVEL.md)
+- [Project root: MontiCore @github](https://github.com/MontiCore/monticore)
+- [MontiCore documentation](http://www.monticore.de/)
+- [List of languages](https://github.com/MontiCore/monticore/blob/dev/docs/Languages.md)
+- [MontiCore Core Grammar Library](https://github.com/MontiCore/monticore/blob/dev/monticore-grammar/src/main/grammars/de/monticore/Grammars.md)
+- [Best Practices](https://github.com/MontiCore/monticore/blob/dev/docs/BestPractices.md)
+- [Publications about MBSE and MontiCore](https://www.se-rwth.de/publications/)
+- [Licence definition](https://github.com/MontiCore/monticore/blob/master/00.org/Licenses/LICENSE-MONTICORE-3-LEVEL.md)
[od4report-link]: http://www.monticore.de/download/MCOD4Report.jar
-[od4data-link]: http://www.monticore.de/download/MCOD4Data.jar
+[od4dev-link]: http://www.monticore.de/download/MCOD4Development.jar
diff --git a/build.gradle b/build.gradle
index 73840e7e..e1e29968 100644
--- a/build.gradle
+++ b/build.gradle
@@ -46,7 +46,7 @@ java {
dependencies {
grammar("de.monticore:monticore-grammar:$mc_version")
implementation "org.antlr:antlr4-runtime:4.12.0"
- implementation 'net.sourceforge.plantuml:plantuml:1.2023.12'
+ implementation "net.sourceforge.plantuml:plantuml:$plantuml_version"
implementation "de.se_rwth.commons:se-commons-logging:$mc_version"
implementation "de.monticore:monticore-runtime:$mc_version"
implementation "de.monticore.lang:cd4analysis:$mc_version"
@@ -79,21 +79,9 @@ test {
showStackTraces = true
showStandardStreams = true
}
-
- // listen to standard out and standard error of the test JVM(s)
- addTestOutputListener(new TestOutputListener() {
- @Override
- void onOutput(TestDescriptor testDescriptor, TestOutputEvent outputEvent) {
- logger.lifecycle("Test: " + testDescriptor.getName() + " produced standard out/err: " + outputEvent.getMessage())
- }
- })
finalizedBy jacocoTestReport
}
-shadowJar {
- duplicatesStrategy = DuplicatesStrategy.EXCLUDE
-}
-
// build sources jar in addition
tasks.register('sourcesJar', Jar) {
from(sourceSets.main.allJava)
@@ -103,7 +91,10 @@ tasks.register('sourcesJar', Jar) {
sourcesJar.dependsOn project.collect { it.tasks.withType(MCGenTask) }
tasks.withType(ShadowJar).configureEach {
+ // EXCLUDE must not be used: together with minimize() it produces jars without any files
duplicatesStrategy = DuplicatesStrategy.INCLUDE
+ // signature files of signed dependencies are invalid for the merged jar
+ exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.EC'
}
// build grammar jar as well
@@ -113,18 +104,6 @@ tasks.register('grammarJar', Jar) {
}
jar.dependsOn(grammarJar)
-tasks.register('buildOD4DataTool', ShadowJar) {
- minimize()
- archiveFileName = 'MCOD4Data.jar'
- archiveClassifier = "od4data-mc-tool"
- manifest {
- attributes('Main-Class': 'de.monticore.od4data.OD4DataTool')
- }
- from sourceSets.main.output
- configurations = [project.configurations.runtimeClasspath]
-}
-jar.dependsOn(buildOD4DataTool)
-
tasks.register('buildOD4ReportTool', ShadowJar) {
minimize()
archiveFileName = 'MCOD4Report.jar'
@@ -150,7 +129,7 @@ tasks.register('buildOD4DevelopmentTool', ShadowJar) {
jar.dependsOn(buildOD4DevelopmentTool)
tasks.register('testReport', TestReport) {
- destinationDirectory = file("${layout.buildDirectory}/reports/allTests")
+ destinationDirectory = layout.buildDirectory.dir("reports/allTests")
// Include the results from the 'test' task
getTestResults().from(tasks.withType(Test))
}
@@ -164,7 +143,6 @@ publishing {
from components.java
artifact sourcesJar
artifact buildOD4DevelopmentTool
- artifact buildOD4DataTool
artifact buildOD4ReportTool
}
}
@@ -192,13 +170,16 @@ tasks.register('showArtifacts') { group = "MLC" }
tasks.register('checkArtifacts') {group = "MLC" }
configurations { MLC }
dependencies {
- MLC("de.monticore.lang:mlc-gradle:$version")
+ MLC("de.monticore.lang:mlc-gradle:$mlc_version")
}
-def modelPath = [];
-configurations.compileClasspath.resolve().each { modelPath.addAll(["-mp", it.toString()]) }
-configurations.grammarSymbolDependencies.resolve().each { modelPath.addAll(["-mp", it.toString()]) }
-modelPath.addAll(["-mp", "$projectDir/target/symbols"])
+// the model path is resolved when an MLC task is executed, not for every build
+def mlcModelPath = { ->
+ (configurations.compileClasspath.files + configurations.grammarSymbolDependencies.files
+ + layout.buildDirectory.dir("symbols").get().asFile)
+ .collectMany { ["-mp", it.toString()] }
+}
+def mlcReportsDir = layout.buildDirectory.dir("reports").get().asFile.path
// two tasks per MLC file
// each task needs to depend on all internally promoted MLCs
@@ -210,8 +191,8 @@ fileTree("src").matching { include '**/*.mlc' }.each {
classpath = configurations.MLC
group = 'MLC'
mainClass = 'de.monticore.mlc.MLCTool'
- args = [ "-input", f, "-projectDir", projectDir, "-s", "-reports", "${layout.buildDirectory}/reports", "-a", "-noFQ"]
- args += modelPath
+ args = [ "-input", f, "-projectDir", projectDir, "-s", "-reports", mlcReportsDir, "-a", "-noFQ"]
+ argumentProviders.add({ mlcModelPath() } as CommandLineArgumentProvider)
dependsOn("generateMCGrammars")
}
showArtifacts.dependsOn("showArtifacts${mlcName}")
@@ -220,8 +201,8 @@ fileTree("src").matching { include '**/*.mlc' }.each {
classpath = configurations.MLC
group = 'MLC'
mainClass = 'de.monticore.mlc.MLCTool'
- args = ["-input", f, "-projectDir", projectDir, "-s", "-check", "-reports", "${layout.buildDirectory}/reports"]
- args += modelPath
+ args = ["-input", f, "-projectDir", projectDir, "-s", "-check", "-reports", mlcReportsDir]
+ argumentProviders.add({ mlcModelPath() } as CommandLineArgumentProvider)
dependsOn("generateMCGrammars")
}
checkArtifacts.dependsOn("checkArtifacts${mlcName}")
@@ -233,13 +214,11 @@ checkArtifactsODLink.dependsOn(checkArtifactsODBasis)
checkArtifactsODAttribute.dependsOn(checkArtifactsODBasis)
-checkArtifactsOD4Data.dependsOn(checkArtifactsODLink)
-checkArtifactsOD4Data.dependsOn(checkArtifactsODAttribute)
-
-checkArtifactsOD4Development.dependsOn(checkArtifactsOD4Data)
+checkArtifactsOD4Development.dependsOn(checkArtifactsODLink)
+checkArtifactsOD4Development.dependsOn(checkArtifactsODAttribute)
checkArtifactsOD4Report.dependsOn(checkArtifactsDateLiterals)
-checkArtifactsOD4Report.dependsOn(checkArtifactsOD4Data)
+checkArtifactsOD4Report.dependsOn(checkArtifactsOD4Development)
// MLC Show dependencies
// always depend on the shows of the mlc models which are allowed by an mlc
@@ -247,10 +226,8 @@ showArtifactsODLink.dependsOn(showArtifactsODBasis)
showArtifactsODAttribute.dependsOn(showArtifactsODBasis)
-showArtifactsOD4Data.dependsOn(showArtifactsODLink)
-showArtifactsOD4Data.dependsOn(showArtifactsODAttribute)
-
-showArtifactsOD4Development.dependsOn(showArtifactsOD4Data)
+showArtifactsOD4Development.dependsOn(showArtifactsODLink)
+showArtifactsOD4Development.dependsOn(showArtifactsODAttribute)
showArtifactsOD4Report.dependsOn(showArtifactsDateLiterals)
-showArtifactsOD4Report.dependsOn(showArtifactsOD4Data)
+showArtifactsOD4Report.dependsOn(showArtifactsOD4Development)
diff --git a/gradle.properties b/gradle.properties
index d4cf7d29..5b91f60f 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -10,6 +10,7 @@ guava_version=33.5.0-jre
commons_lang3_version=3.20.0
commons_cli_version=1.11.0
junit_version=6.0.3
+plantuml_version=1.2026.6
org.gradle.jvmargs=-Xmx4096m
org.gradle.parallel=true
diff --git a/src/main/grammars/de/monticore/OD4Data.mc4 b/src/main/grammars/de/monticore/OD4Data.mc4
deleted file mode 100644
index 76723158..00000000
--- a/src/main/grammars/de/monticore/OD4Data.mc4
+++ /dev/null
@@ -1,43 +0,0 @@
-/* (c) https://github.com/MontiCore/monticore */
-package de.monticore;
-
-/* This is a MontiCore stable grammar.
- * Adaptations -- if any -- are conservative. */
-
-/**
- OD4Data is used to store and transport object-oriented data sets.
-
- OD4Data is thefore similar to e.g. JSON and XML.
- The main difference is that OD4Data allows links to
- be explicitely defined and thus can build complex link structures,
- i.e. arbitrary object graphs directly (and not only trees).
-
- For that purpose, objects can have an explicit name.
-
- OD4Data fits very well to the class diagrams in CD4Analysis.
-
- This grammar brings together the following OD components
- * ODBasis.mc4
- for the core structure of ODs
- * ODAttribute.mc4
- for the forms of attribute values
- * ODLink.mc4
- defining the links between objects
-
- It includes MCCommonLiterals to allow a rich set of values
- (e.g. to define attribute and enum values.)
-*/
-
-grammar OD4Data extends de.monticore.ODAttribute,
- de.monticore.ODLink {
-
- start ODArtifact;
-
- splittoken "->", "<-", "<->", "--";
-
- // Certain keywords of the used grammars shall not become
- // restricted words in other context:
- nokeyword "aggregation", "composition", "link", "objectdiagram";
- nokeyword "conformsTo";
-
-}
diff --git a/src/main/grammars/de/monticore/OD4Data.mlc b/src/main/grammars/de/monticore/OD4Data.mlc
deleted file mode 100644
index 66527e31..00000000
--- a/src/main/grammars/de/monticore/OD4Data.mlc
+++ /dev/null
@@ -1,28 +0,0 @@
-/* (c) https://github.com/MontiCore/monticore */
-package de.monticore;
-
-mlc OD4Data {
-
- export "$projectDir/src/main/grammars" {
- include "**/OD4Data.mc4";
- }
-
- export "$projectDir/src/main/java" {
- include "de/monticore/od4data/**.java";
- }
-
- export "$projectDir/target/generated-sources/monticore/sourcecode" {
- include "de/monticore/od4data/**.java";
- }
-
- promote {
- // allow apache.commons.lang3
- include "$mp/org/apache/commons/lang3/**";
- }
-
- promote { // allow using other languages
- mlc "de.monticore.ODLink";
- mlc "de.monticore.ODAttribute";
- }
-
-}
diff --git a/src/main/grammars/de/monticore/OD4Development.mc4 b/src/main/grammars/de/monticore/OD4Development.mc4
index d4cc71de..cbc8172e 100644
--- a/src/main/grammars/de/monticore/OD4Development.mc4
+++ b/src/main/grammars/de/monticore/OD4Development.mc4
@@ -43,7 +43,8 @@ package de.monticore;
*/
-grammar OD4Development extends de.monticore.OD4Data {
+grammar OD4Development extends de.monticore.ODAttribute,
+ de.monticore.ODLink {
start ODArtifact;
diff --git a/src/main/grammars/de/monticore/OD4Report.md b/src/main/grammars/de/monticore/OD4Development.md
similarity index 69%
rename from src/main/grammars/de/monticore/OD4Report.md
rename to src/main/grammars/de/monticore/OD4Development.md
index 3674a9f3..0974e312 100644
--- a/src/main/grammars/de/monticore/OD4Report.md
+++ b/src/main/grammars/de/monticore/OD4Development.md
@@ -12,7 +12,7 @@ constraint language OCL
This MontiCore project contains
-* seven language components, defined by their own grammars,
+* six language components, defined by their own grammars,
* appropriate context conditions for each language component,
* which also includes a symbol table infrastructure for managing and storing symbol tables, and
* pretty-printers.
@@ -47,10 +47,10 @@ objectdiagram MyFamily {
examples.A graphical version is shown in Figure 1.
-
- Figure 1: The graphical syntax of example OD MyFamiliy.
-
-
+
+
+ Figure 1: The graphical syntax of the example OD.
+
The conceptual elements of ODs are similar to JSOM or XML, but deliver (hopefully) a better readable
syntax:
@@ -59,6 +59,7 @@ syntax:
like `tiger`.
* Objects also have a *type*, e.g. `:Person`.
* UML allows both to be optional, if not needed or reconstructable from context.
+ * However, OD4Development allows anonymous objects but always requires a type.
* *Attributes* are defined with their value, e.g. `color = RED`.
* *Link*s can be explicitly defined, allowing *arbitrary graph structures*, e.g. use of `tiger` or
the `alice <-> bob` link.
@@ -71,30 +72,24 @@ syntax:
Below follow more detailed explanations about the project:
-## Tools: `OD4ReportTool` and `ODDataTool`
+## Tools: `ODDataTool` and `OD4ReportTool`
-By default, the project creates two tools, stored in `MCOD4Report.jar` and `MCODData.jar`.
+By default, the project creates two tools, stored in `MCOD4Development.jar` and `MCOD4Report.jar`.
-Both classes, [```OD4ReportTool```](../../../java/de/monticore/od4report/OD4ReportTool.java)
-and [```OD4DataTool```](../../../java/de/monticore/od4data/OD4DataTool.java) provide typical
-functionality used when processing models from commandlin. To this effect, the classes
+Both classes, [```OD4DevelopmentTool```](../../../java/de/monticore/od4development/OD4DevelopmentTool.java)
+and [```OD4ReportTool```](../../../java/de/monticore/od4report/OD4ReportTool.java) provide typical
+functionality used when processing models from commandline. To this effect, the classes
provide methods for parsing, pretty-printing, creating symbol tables, storing symbols, and loading
symbols. Detailed information about the methods can be found in the Javadoc documentation of each
class.
-[```OD4DataTool```](../../../java/de/monticore/od4data/OD4DataTool.java) provides typical
-functionality used when processing models from commandline. To this effect, the class provides
-methods for parsing, pretty-printing, creating symbol tables, storing symbols, and loading symbols.
-Detailed information about the methods can be found in the Javadoc documentation of the
-class [```OD4DataTool```](../../../java/de/monticore/od4data/OD4DataTool.java).
-
-Each tool can be found in the ```target``` folder once the project build was successful. Each tool
+Each tool can be found in the ```target\libs``` folder once the project build was successful. Each tool
provides a ``-h`` parameter providing further information on how to use it.
Example calls:
```
- java -jar target/libs/MCOD4Data.jar -h
+ java -jar target/libs/MCOD4Development.jar -h
java -jar target/libs/MCOD4Report.jar -h
// pretty print an OD:
@@ -102,19 +97,19 @@ Example calls:
-pp
// read an OD and store the symbols it defines and exports in a symboltable:
- java -jar target/libs/MCOD4Data.jar -i src/test/resources/examples/od/Teaser.od \
+ java -jar target/libs/MCOD4Development.jar -i src/test/resources/examples/od/Teaser.od \
-s Teaser.symod
```
## Grammars (i.e. language components)
-This MontiCore project contains seven grammars, which provide the possibility to describe object
+This MontiCore project contains six grammars, which provide the possibility to describe object
diagrams in various extensions:
* [ODBasis](../../../grammars/de/monticore/ODBasis.mc4),
* [ODAttribute](../../../grammars/de/monticore/ODAttribute.mc4),
* [ODLink](../../../grammars/de/monticore/ODLink.mc4),
-* [OD4Data](../../../grammars/de/monticore/OD4Data.mc4),
+* [OD4Development](../../../grammars/de/monticore/OD4Development.mc4),
* [OD4Report](../../../grammars/de/monticore/OD4Report.mc4), and
* [DateLiterals](../../../grammars/de/monticore/DateLiterals.mc4).
@@ -131,60 +126,47 @@ The grammar [ODBasis](../../../grammars/de/monticore/ODBasis.mc4) defines the sy
The grammar [ODBasis](../../../grammars/de/monticore/ODBasis.mc4) extends the grammars
-* [MCBasicTypes](https://github.com/MontiCore/monticore/blob/opendev/monticore-grammar/src/main/grammars/de/monticore/types/MCBasicTypes.mc4)
+* [MCBasicTypes](https://github.com/MontiCore/monticore/blob/dev/monticore-grammar/src/main/grammars/de/monticore/types/MCBasicTypes.mc4)
that provides possible object types.
-* [OOSymbols](https://github.com/MontiCore/monticore/blob/opendev/monticore-grammar/src/main/grammars/de/monticore/symbols/OOSymbols.mc4)
+* [OOSymbols](https://github.com/MontiCore/monticore/blob/dev/monticore-grammar/src/main/grammars/de/monticore/symbols/OOSymbols.mc4)
for using symbols of kind `Diagram` and `Variable`.
-* [CommonExpressions](https://github.com/MontiCore/monticore/blob/opendev/monticore-grammar/src/main/grammars/de/monticore/expressions/CommonExpressions.mc4)
+* [CommonExpressions](https://github.com/MontiCore/monticore/blob/dev/monticore-grammar/src/main/grammars/de/monticore/expressions/CommonExpressions.mc4)
to be able to reuse simple forms of expressions (and the typechecking functionality).
-* [UMLStereotype](https://github.com/MontiCore/monticore/blob/opendev/monticore-grammar/src/main/grammars/de/monticore/UMLStereotype.mc4)
+* [UMLModifier](https://github.com/MontiCore/monticore/blob/dev/monticore-grammar/src/main/grammars/de/monticore/UMLModifier.mc4)
for adding UMLStereotypes as possible extension points to the grammar.
### ODAttribute
-The grammar [ODAttribute](../../../grammars/de/monticore/ODAttribute.mc4) adds more complex types of
-attributes, i.e. *lists* and *maps*, to UML/P ODs.
-
-The grammar [ODAttribute](../../../grammars/de/monticore/ODAttribute.mc4) defines the syntax for
-
-* lists of values,
-* and maps of key-value pairs.
+The grammar [ODAttribute](../../../grammars/de/monticore/ODAttribute.mc4) adds
+more complex types of attributes, i.e. *lists* and *maps*, to UML/P ODs by
+defining the syntax for *lists of values* and *maps of key-value pairs*.
### ODLink
-The grammar [ODLink](../../../grammars/de/monticore/ODLink.mc4) adds links to UML/P ODs. There are
-two main types of link representations, namely the explicit mentioning as `link`
-that connects two objects and the nested link, that occurs when the nesting objects into a
-hierarchy.
+The grammar [ODLink](../../../grammars/de/monticore/ODLink.mc4) adds links to
+UML/P ODs. There are two main types of link representations, namely the explicit
+mentioning as `link` that connects two objects and the nested link, that occurs
+when the nesting objects into a hierarchy.
-Furthermore, links may be *directed* and can be *ordinary*, *aggregations* or *compositions*, but
-also
-*derived*.
-
-### OD4Data
-
-The grammar [OD4Data](../../../grammars/de/monticore/OD4Data.mc4) only combines the language
-components `ODAttribute`
-and `ODLink` to form a variant of OD language mainly used for representing data. For that purpose,
-the language component also offers to use *dates* as expressions in certain structures of a model,
-e.g. attribute values.
+Furthermore, links may be *directed* and can be *ordinary*, *aggregations* or
+*compositions*, but also *derived*.
### OD4Development
-The [OD4Development](../../../grammars/de/monticore/OD4Development.mc4) grammar extends
-the `OD4Data` language by adding an extended namespace for objects and attribute values.
-
-It focusses on the modelling phase in typical object-oriented development projects and is therefore
-mainly used for data modelling. Consequently, it omits method signatures and complex generics.
+The [OD4Development](../../../grammars/de/monticore/OD4Development.mc4) grammar
+combines the language components `ODAttribute` and `ODLink`. It focuses on the
+modeling phase in typical object-oriented development projects and is therefore
+mainly used for data modeling. Consequently, it omits method signatures and
+complex generics.
`OD4Development` is the textual representation to describe UML object diagrams
-(it uses the UML/P variant). `OD4Development` covers objects, attributes with values (and optional)
-types, and all kinds of associations and composition, including qualified and ordered associations.
-It allows to define
+(it uses the UML/P variant). `OD4Development` covers objects, attributes with
+values (and optional) types, and all kinds of associations and composition,
+including qualified and ordered associations. It allows to define
* (1) desired object structures,
* (2) unwanted object structures,
-* (3) initial object structures e.g. for a test setup or the specifictaion of a construction method.
+* (3) initial object structures e.g. for a test setup or the specification of a construction method.
It allows incomplete structures (omitting uninteresting links or attributes); values can be either
given directly or as expressions using other values and thus also allows to describe
* (4) desired test results (oracle), and has also been used for
@@ -192,13 +174,13 @@ It allows to define
`OD4Development` fits very well to the `CD4Analysis`language component.
-It builds on MCTypes, but disallows e.g. List as type, because they can be represented via
+It builds on MCTypes, but disallows e.g. List as type, because they can be represented via
associations.
### OD4Report
-The [OD4Report](../../../grammars/de/monticore/OD4Report.mc4) grammar extends the `OD4Data` language
-by adding an extended namespace for objects and attribute values. Its main appliciation are
+The [OD4Report](../../../grammars/de/monticore/OD4Report.mc4) grammar extends the `OD4Development` language
+by adding an extended namespace for objects and attribute values. Its main application are
reporting, e.g. in MontiCore's generated reports, or data formats which need make use of the
extended namespace, e.g. artifact-based analyses. For that purpose, it mainly extends the
possibility to define names by nonterminal `ODSpecialName`, which encodes a number of additional
@@ -206,7 +188,7 @@ information into the object name. An example for such a special name is `@State(
this state has occurred in line 2, column 3. Moreover, the set of supported types is extended. The
grammar therefore extends:
-* [MCCollectionTypes](https://github.com/MontiCore/monticore/blob/opendev/monticore-grammar/src/main/grammars/de/monticore/types/MCCollectionTypes.mc4)
+* [MCCollectionTypes](https://github.com/MontiCore/monticore/blob/dev/monticore-grammar/src/main/grammars/de/monticore/types/MCCollectionTypes.mc4)
for the extension of supported types.
### DateLiterals
@@ -218,7 +200,7 @@ dates and times. Dates consist of a date part modeling year, month, and day, as
modeling hour, minute, and second.
The above defined object diagrams, especially the `OD4Report` language component makes heavy use of
-this possbility.
+this possibility.
## Context Conditions
@@ -226,7 +208,6 @@ This section lists the context conditions for
the [ODBasis](../../../grammars/de/monticore/ODBasis.mc4) grammar, context conditions for
the [ODAttribute](../../../grammars/de/monticore/ODAttribute.mc4) grammar, context conditions for
the [ODLink](../../../grammars/de/monticore/ODLink.mc4) grammar, context conditions for
-the [OD4Data](../../../grammars/de/monticore/OD4Data.mc4) grammar context conditions for
the [OD4Development](../../../grammars/de/monticore/OD4Development.mc4) grammar. context conditions
for the [OD4Report](../../../grammars/de/monticore/OD4Report.mc4) grammar. context conditions for
the [DateLiterals](../../../grammars/de/monticore/DateLiterals.mc4) grammar.
@@ -257,6 +238,10 @@ located [here](../../../java/de/monticore/odbasis/_cocos).
* The context
condition [```ValidObjectReferenceCoCo```](../../../java/de/monticore/odbasis/_cocos/object/ValidObjectReferenceCoCo.java)
checks object references as an attribute value actually exist.
+
+* The context
+ condition [```ValidObjectTypeCoCo```](../../../java/de/monticore/odbasis/_cocos/object/ValidObjectTypeCoCo.java)
+ checks object types actually exist.
### ODAttribute Context Conditions
@@ -281,10 +266,6 @@ located [here](../../../java/de/monticore/odlink/_cocos).
condition [```ValidLinkReferenceCoCo```](../../../java/de/monticore/odlink/_cocos/link/ValidLinkReferenceCoCo.java)
checks if the object referenced actually exist.
-### OD4Data Context Conditions
-
-None.
-
### OD4Development Context Conditions
None.
@@ -300,7 +281,7 @@ the [DateLiterals](../../../grammars/de/monticore/DateLiterals.mc4) grammar are
located [here](../../../java/de/monticore/dateliterals/_cocos).
* The context
- condition [```DateConcistencyCoCo```](../../../java/de/monticore/dateliterals/_cocos/date/DateConcistencyCoCo.java)
+ condition [```DateConsistencyCoCo```](../../../java/de/monticore/dateliterals/_cocos/date/DateConsistencyCoCo.java)
checks if a date is consistent in termns of day of year as well as time of day.
## Symbol Table
@@ -318,10 +299,10 @@ and [```OOTypeSymbols```][OOSymbolsRef].
### Symbol Table Data Structure
-
- Figure 2: The data structure of the symbol table of the OD language.
-
-
+
+
+ Figure 2: The data structure of the symbol table of the OD language.
+
Figure 2 depicts the symbol table data structure of
the [```OD4Report```](../../../grammars/de/monticore/OD4Report.mc4) language, when then built from
@@ -336,40 +317,36 @@ OD.
As usual the `OD4DReportArtifactScope` is not stored in the symboltable, but the top level symbols
and potentially associated scopes are.
-
- Figure 3: Symbol table instance of the OD depicted in Figure 1.
-
-
+
+
+ Figure 3: Symbol table instance of the OD depicted in Figure 1.
+
Figure 3 depicts the symbol table instance for the OD ```MyFamily```. The three explicitly named
objects
```alice:Person```, ```bob:Person``` and ```tiger:Jaguar``` are stored as
[```VariableSymbol```][BasicSymbolsRef]
-instances and maintaiend i the ```OD4ReportArtifactScope```. The object ```:DiagramSymbol```
+instances and are maintained in the ```OD4ReportArtifactScope```. The object ```:DiagramSymbol```
containing the name of the object diagram is also linked to that scope.
As usual, symbols can only be accessed, if they have an explicit name, which is why an anonymous
object, such as `:BMW`, as well as any form of links do not occur in the symbol table. Please also
note, that types, such as `BMW` or `Person`
-are imported by the object diagram, but not internally defined.
+are imported by the object diagram, but are not internally defined.
-Handwritten extensions of the symbol table creator can be found as follows:
+Handwritten extensions of the ScopesGenitor can be found as follows:
-* The creator for the [```ODBasis```](../../../grammars/de/monticore/ODBasis.mc4) grammar can be
+* The genitor for the [```ODBasis```](../../../grammars/de/monticore/ODBasis.mc4) grammar can be
found in the
- class [```ODBasisSymbolTableCreator```](../../../java/de/monticore/odbasis/_symboltable/ODBasisSymbolTableCreator.java)
+ class [```ODBasisScopesGenitor```](../../../java/de/monticore/odbasis/_symboltable/ODBasisScopesGenitor.java)
.
* The creator for the [```ODAttribute```](../../../grammars/de/monticore/ODAttribute.mc4) grammar
can be found in the
- class [```ODAttributeSymbolTableCreator```](../../../java/de/monticore/odattribute/_symboltable/ODAttributeSymbolTableCreator.java)
- .
-* The creator for the [```ODLink```](../../../grammars/de/monticore/ODLink.mc4) grammar can be found
- in the
- class [```ODLinkSymbolTableCreator```](../../../java/de/monticore/odlink/_symboltable/ODLinkSymbolTableCreator.java)
+ class [```ODAttributeScopesGenitor```](../../../java/de/monticore/odattribute/_symboltable/ODAttributeScopesGenitor.java)
.
* The creator for the [```OD4Report```](../../../grammars/de/monticore/OD4Report.mc4) grammar can be
found in the
- class [```OD4ReportSymbolTableCreator```](../../../java/de/monticore/od4report/_symboltable/OD4ReportSymbolTableCreator.java)
+ class [```OD4ReportScopesGenitor```](../../../java/de/monticore/od4report/_symboltable/OD4ReportScopesGenitor.java)
.
### Symbol kinds used by the OD Language (importable or subclassed)
@@ -384,7 +361,7 @@ None.
### Symbols imported by OD models:
-* ODs import [```VariableSymbols```][BasicSymbolsRef] as externally defined objects. The importet
+* ODs import [```VariableSymbols```][BasicSymbolsRef] as externally defined objects. The imported
objects can be used as attribute values and link targets.
* ODs import [```TypeSymbols```][BasicSymbolsRef] that can be used as types for objects.
@@ -394,7 +371,7 @@ None.
with explicit names are visible from outside the object diagram. There is no hiding, not even for
nested objects (this was a deliberate design decision; alternatives would have been possible.)
With this mechanism, object diagrams can extend each other, defining a more complex object
- structure in several artefacts.
+ structure in several artifacts.
* Each OD exports exactly one [```DiagramSymbol```][BasicSymbolsRef] corresponding to the
ODArtifact.
@@ -444,31 +421,31 @@ table instance depicted in Figure 3:
}
```
-[BasicSymbolsRef]:https://github.com/MontiCore/monticore/blob/opendev/monticore-grammar/src/main/grammars/de/monticore/symbols/BasicSymbols.mc4
+[BasicSymbolsRef]:https://github.com/MontiCore/monticore/blob/dev/monticore-grammar/src/main/grammars/de/monticore/symbols/BasicSymbols.mc4
-[TypeSymbolsRef]:https://github.com/MontiCore/monticore/tree/opendev/monticore-grammar/src/main/grammars/de/monticore/types
+[TypeSymbolsRef]:https://github.com/MontiCore/monticore/tree/dev/monticore-grammar/src/main/grammars/de/monticore/types
-[MCBasicTypesRef]:https://github.com/MontiCore/monticore/blob/opendev/monticore-grammar/src/main/grammars/de/monticore/types/MCBasicTypes.mc4
+[MCBasicTypesRef]:https://github.com/MontiCore/monticore/blob/dev/monticore-grammar/src/main/grammars/de/monticore/types/MCBasicTypes.mc4
-[OOSymbolsRef]:https://github.com/MontiCore/monticore/blob/opendev/monticore-grammar/src/main/grammars/de/monticore/symbols/OOSymbols.mc4
+[OOSymbolsRef]:https://github.com/MontiCore/monticore/blob/dev/monticore-grammar/src/main/grammars/de/monticore/symbols/OOSymbols.mc4
-[ExpressionsBasisRef]:https://github.com/MontiCore/monticore/blob/opendev/monticore-grammar/src/main/grammars/de/monticore/expressions/ExpressionsBasis.mc4
+[ExpressionsBasisRef]:https://github.com/MontiCore/monticore/blob/dev/monticore-grammar/src/main/grammars/de/monticore/expressions/ExpressionsBasis.mc4
-[UMLStereotypeRef]:https://github.com/MontiCore/monticore/blob/opendev/monticore-grammar/src/main/grammars/de/monticore/UMLStereotype.mc4
+[UMLStereotypeRef]:https://github.com/MontiCore/monticore/blob/dev/monticore-grammar/src/main/grammars/de/monticore/UMLStereotype.mc4
-[MCCommonLiteralsRef]:https://github.com/MontiCore/monticore/blob/opendev/monticore-grammar/src/main/grammars/de/monticore/literals/MCCommonLiterals.mc4
+[MCCommonLiteralsRef]:https://github.com/MontiCore/monticore/blob/dev/monticore-grammar/src/main/grammars/de/monticore/literals/MCCommonLiterals.mc4
-[CommonExpressionsRef]:https://github.com/MontiCore/monticore/blob/opendev/monticore-grammar/src/main/grammars/de/monticore/expressions/CommonExpressions.mc4
+[CommonExpressionsRef]:https://github.com/MontiCore/monticore/blob/dev/monticore-grammar/src/main/grammars/de/monticore/expressions/CommonExpressions.mc4
-[OCLExpressionsRef]:https://github.com/MontiCore/monticore/blob/opendev/monticore-grammar/src/main/grammars/de/monticore/expressions/OCLExpressions.mc4
+[OCLExpressionsRef]:https://github.com/MontiCore/monticore/blob/dev/monticore-grammar/src/main/grammars/de/monticore/expressions/OCLExpressions.mc4
## Further Information
* [Project root: MontiCore @github](https://github.com/MontiCore/monticore)
* [MontiCore documentation](http://www.monticore.de/)
-* [**List of languages**](https://github.com/MontiCore/monticore/blob/opendev/docs/Languages.md)
+* [**List of languages**](https://github.com/MontiCore/monticore/blob/dev/docs/Languages.md)
* [**MontiCore Core Grammar
- Library**](https://github.com/MontiCore/monticore/blob/opendev/monticore-grammar/src/main/grammars/de/monticore/Grammars.md)
-* [Best Practices](https://github.com/MontiCore/monticore/blob/opendev/docs/BestPractices.md)
+ Library**](https://github.com/MontiCore/monticore/blob/dev/monticore-grammar/src/main/grammars/de/monticore/Grammars.md)
+* [Best Practices](https://github.com/MontiCore/monticore/blob/dev/docs/BestPractices.md)
* [Publications about MBSE and MontiCore](https://www.se-rwth.de/publications/)
* [Licence definition](https://github.com/MontiCore/monticore/blob/master/00.org/Licenses/LICENSE-MONTICORE-3-LEVEL.md)
diff --git a/src/main/grammars/de/monticore/OD4Development.mlc b/src/main/grammars/de/monticore/OD4Development.mlc
index 31e27320..cdc19ae0 100644
--- a/src/main/grammars/de/monticore/OD4Development.mlc
+++ b/src/main/grammars/de/monticore/OD4Development.mlc
@@ -24,7 +24,8 @@ mlc OD4Development {
}
promote { // allow using other languages
- mlc "de.monticore.OD4Data";
- }
+ mlc "de.monticore.ODLink";
+ mlc "de.monticore.ODAttribute";
+ }
}
diff --git a/src/main/grammars/de/monticore/OD4Report.mc4 b/src/main/grammars/de/monticore/OD4Report.mc4
index 5c6472ce..8a140bad 100644
--- a/src/main/grammars/de/monticore/OD4Report.mc4
+++ b/src/main/grammars/de/monticore/OD4Report.mc4
@@ -23,11 +23,11 @@ package de.monticore;
for the forms of attribute values
* ODLink.mc4
defining the links between objects
- * OD4Data.mc4
+ * OD4Development.mc4
= ODAttribute.mc4 + ODLink.mc4
*/
-grammar OD4Report extends de.monticore.OD4Data,
+grammar OD4Report extends de.monticore.OD4Development,
de.monticore.DateLiterals,
de.monticore.types.MCCollectionTypes {
diff --git a/src/main/grammars/de/monticore/OD4Report.mlc b/src/main/grammars/de/monticore/OD4Report.mlc
index d4fbe9c8..6a686d2a 100644
--- a/src/main/grammars/de/monticore/OD4Report.mlc
+++ b/src/main/grammars/de/monticore/OD4Report.mlc
@@ -27,7 +27,7 @@ mlc OD4Report {
promote { // allow using other languages
mlc "de.monticore.DateLiterals";
- mlc "de.monticore.OD4Data";
+ mlc "de.monticore.OD4Development";
mlc "de.monticore.types.MCCollectionTypes";
}
diff --git a/src/main/grammars/de/monticore/ODLink.mc4 b/src/main/grammars/de/monticore/ODLink.mc4
index 7615dff1..e406403d 100644
--- a/src/main/grammars/de/monticore/ODLink.mc4
+++ b/src/main/grammars/de/monticore/ODLink.mc4
@@ -47,8 +47,9 @@ component grammar ODLink extends de.monticore.ODBasis {
ODBiDir implements ODLinkDirection = "<->";
ODUnspecifiedDir implements ODLinkDirection = "--";
- // this is needed to parse e.g. -3<-2 correctly:
- splittoken "<-";
+ // this is needed to parse e.g. -3<-2 correctly, and nested
+ // lists or array accesses like [[1], [2]] or a[b[1]] in values:
+ splittoken "<-", "[[", "]]";
// if needed, the following splitting of token can be heplful,
// and can be added in any subgrammar:
// splittoken "->", "<->", "--";
diff --git a/src/main/java/de/monticore/dateliterals/_ast/ASTDate.java b/src/main/java/de/monticore/dateliterals/_ast/ASTDate.java
index 0953e932..55788e04 100644
--- a/src/main/java/de/monticore/dateliterals/_ast/ASTDate.java
+++ b/src/main/java/de/monticore/dateliterals/_ast/ASTDate.java
@@ -63,7 +63,7 @@ public void setDate(LocalDateTime localDateTime) {
* @return year as int value
*/
public int getYear() {
- return Integer.valueOf(getDatePart().getYear().getDigits()).intValue();
+ return Integer.parseInt(getDatePart().getYear().getDigits());
}
/**
@@ -72,7 +72,7 @@ public int getYear() {
* @return month as int value
*/
public int getMonth() {
- return Integer.valueOf(getDatePart().getMonth().getDigits()).intValue();
+ return Integer.parseInt(getDatePart().getMonth().getDigits());
}
/**
@@ -81,7 +81,7 @@ public int getMonth() {
* @return day as int value
*/
public int getDay() {
- return Integer.valueOf(getDatePart().getDay().getDigits()).intValue();
+ return Integer.parseInt(getDatePart().getDay().getDigits());
}
/**
@@ -90,7 +90,7 @@ public int getDay() {
* @return hours as int value
*/
public int getHour() {
- return Integer.valueOf(getTimePart().getHour().getDigits()).intValue();
+ return Integer.parseInt(getTimePart().getHour().getDigits());
}
/**
@@ -99,7 +99,7 @@ public int getHour() {
* @return minutes as int value
*/
public int getMinute() {
- return Integer.valueOf(getTimePart().getMinute().getDigits()).intValue();
+ return Integer.parseInt(getTimePart().getMinute().getDigits());
}
/**
@@ -108,7 +108,7 @@ public int getMinute() {
* @return seconds as int value
*/
public int getSecond() {
- return Integer.valueOf(getTimePart().getSecond().getDigits()).intValue();
+ return Integer.parseInt(getTimePart().getSecond().getDigits());
}
}
diff --git a/src/main/java/de/monticore/dateliterals/_cocos/DateLiteralsCoCos.java b/src/main/java/de/monticore/dateliterals/_cocos/DateLiteralsCoCos.java
index 090e9e15..d7f5fc43 100644
--- a/src/main/java/de/monticore/dateliterals/_cocos/DateLiteralsCoCos.java
+++ b/src/main/java/de/monticore/dateliterals/_cocos/DateLiteralsCoCos.java
@@ -2,14 +2,14 @@
package de.monticore.dateliterals._cocos;
-import de.monticore.dateliterals._cocos.date.DateConcistencyCoCo;
+import de.monticore.dateliterals._cocos.date.DateConsistencyCoCo;
public class DateLiteralsCoCos {
public DateLiteralsCoCoChecker getCheckerForAllCoCos() {
final DateLiteralsCoCoChecker dateLiteralsCoCoChecker = new DateLiteralsCoCoChecker();
- dateLiteralsCoCoChecker.addCoCo(new DateConcistencyCoCo());
+ dateLiteralsCoCoChecker.addCoCo(new DateConsistencyCoCo());
return dateLiteralsCoCoChecker;
}
diff --git a/src/main/java/de/monticore/dateliterals/_cocos/date/DateConcistencyCoCo.java b/src/main/java/de/monticore/dateliterals/_cocos/date/DateConsistencyCoCo.java
similarity index 76%
rename from src/main/java/de/monticore/dateliterals/_cocos/date/DateConcistencyCoCo.java
rename to src/main/java/de/monticore/dateliterals/_cocos/date/DateConsistencyCoCo.java
index b83673f8..6fd0000e 100644
--- a/src/main/java/de/monticore/dateliterals/_cocos/date/DateConcistencyCoCo.java
+++ b/src/main/java/de/monticore/dateliterals/_cocos/date/DateConsistencyCoCo.java
@@ -1,7 +1,5 @@
// (c) https://github.com/MontiCore/monticore
-// (c) https://github.com/MontiCore/monticore
-
package de.monticore.dateliterals._cocos.date;
import de.monticore.dateliterals._ast.ASTDate;
@@ -15,7 +13,9 @@
/**
* Check if the ODDate is a consistent Date. Consistency is checked using {@link LocalDate}.
*/
-public class DateConcistencyCoCo implements DateLiteralsASTDateCoCo {
+public class DateConsistencyCoCo implements DateLiteralsASTDateCoCo {
+
+ public static final String ERROR_INCONSISTENT_DATE = "0x0D030: Invalid date: %s";
@Override
public void check(ASTDate node) {
@@ -26,7 +26,8 @@ public void check(ASTDate node) {
node.getTimePart().getMinute().getValue(), node.getTimePart().getSecond().getValue());
}
catch (DateTimeException e) {
- Log.error("0x0D009: Violation of CoCo 'DateConcistencyCoCo'", node.get_SourcePositionStart());
+ Log.error(String.format(ERROR_INCONSISTENT_DATE, e.getMessage()),
+ node.get_SourcePositionStart());
}
}
diff --git a/src/main/java/de/monticore/od2cd/CompositionPrinter.java b/src/main/java/de/monticore/od2cd/CompositionPrinter.java
index 6e768911..971656bc 100644
--- a/src/main/java/de/monticore/od2cd/CompositionPrinter.java
+++ b/src/main/java/de/monticore/od2cd/CompositionPrinter.java
@@ -14,8 +14,8 @@ public String create(ASTMCType type) {
IOD4DevelopmentGlobalScope gs = OD4DevelopmentMill.globalScope();
- if (gs.getSubScopes().size() >= 1) {
- IOD4DevelopmentArtifactScope as = (IOD4DevelopmentArtifactScope) gs.getSubScopes().get(0);
+ if (!gs.getSubScopes().isEmpty()) {
+ IOD4DevelopmentArtifactScope as = (IOD4DevelopmentArtifactScope) gs.getSubScopes().getFirst();
if (as.getTypeSymbols().containsKey(type.printType()) ||
as.getOOTypeSymbols().containsKey(type.printType()) ||
@@ -37,7 +37,7 @@ public String read() {
public String write(String type) {
IOD4DevelopmentGlobalScope gs = OD4DevelopmentMill.globalScope();
- if (gs.getSubScopes().size() >= 1) {
+ if (!gs.getSubScopes().isEmpty()) {
return ".build().get()";
}
return ".build()";
@@ -46,8 +46,8 @@ public String write(String type) {
public String update(String attribute, String value) {
IOD4DevelopmentGlobalScope gs = OD4DevelopmentMill.globalScope();
- if (gs.getSubScopes().size() >= 1) {
- String asName = gs.getSubScopes().get(0).getName();
+ if (!gs.getSubScopes().isEmpty()) {
+ String asName = gs.getSubScopes().getFirst().getName();
String res = "";
String line = "";
@@ -67,7 +67,7 @@ public String update(String attribute, String value) {
public String genType(ASTMCType type) {
IOD4DevelopmentGlobalScope gs = OD4DevelopmentMill.globalScope();
String genType = OD4DevelopmentMill.prettyPrint(type, false);
- if (gs.getSubScopes().size() >= 1) {
+ if (!gs.getSubScopes().isEmpty()) {
return genType + "Builder";
} else {
return genType;
diff --git a/src/main/java/de/monticore/od2cd/OD2CDObjectVisitor.java b/src/main/java/de/monticore/od2cd/OD2CDObjectVisitor.java
index bc2c6553..90ac1b98 100644
--- a/src/main/java/de/monticore/od2cd/OD2CDObjectVisitor.java
+++ b/src/main/java/de/monticore/od2cd/OD2CDObjectVisitor.java
@@ -8,7 +8,6 @@
import de.monticore.cdbasis._ast.ASTCDDefinition;
import de.monticore.cdbasis._ast.ASTCDPackage;
import de.monticore.generating.templateengine.GlobalExtensionManagement;
-import de.monticore.od4data._prettyprint.OD4DataFullPrettyPrinter;
import de.monticore.od4development.OD4DevelopmentMill;
import de.monticore.od4development._symboltable.CDRoleAdapter;
import de.monticore.od4development._symboltable.CDRoleAdapter.LinkCardinality;
@@ -16,7 +15,6 @@
import de.monticore.odbasis._visitor.ODBasisVisitor2;
import de.monticore.odlink._ast.*;
import de.monticore.odlink._symboltable.IODLinkScope;
-import de.monticore.prettyprint.IndentPrinter;
import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol;
import de.monticore.symbols.oosymbols._symboltable.FieldSymbol;
import de.monticore.types.mcbasictypes._ast.ASTMCImportStatement;
@@ -72,8 +70,8 @@ public void visit(ASTODArtifact odArtifact) {
.setCDDefinition(cdDefinition)
.build();
- if (odArtifact.getMCImportStatementList().size() > 0) {
- ASTMCImportStatement i = odArtifact.getMCImportStatementList().get(0);
+ if (!odArtifact.getMCImportStatementList().isEmpty()) {
+ ASTMCImportStatement i = odArtifact.getMCImportStatementList().getFirst();
imp = CDBasisMill.mCImportStatementBuilder()
.setMCQualifiedName(CDBasisMill.mCQualifiedNameBuilder().addParts(i.getQName().toLowerCase()).build())
.setStar(true).build();
@@ -94,12 +92,13 @@ public void visit(ASTODArtifact odArtifact) {
.setModifier(CDBasisMill.modifierBuilder().PUBLIC().build())
.build();
- cd4C.addImport(instantiatorClass, imp.getQName() + ".*");
cd4C.addImport(instantiatorClass, "java.time.*");
- cd4C.addImport(instancesClass, imp.getQName() + ".*");
cd4C.addImport(instancesClass, "java.time.*");
- cd4C.addImport(checkerClass, imp.getQName() + ".*");
-
+ if (imp != null) {
+ cd4C.addImport(instantiatorClass, imp.getQName() + ".*");
+ cd4C.addImport(instancesClass, imp.getQName() + ".*");
+ cd4C.addImport(checkerClass, imp.getQName() + ".*");
+ }
this.cdPackage.addCDElement(instantiatorClass);
this.cdPackage.addCDElement(instancesClass);
@@ -136,7 +135,7 @@ public void createInstantiator(ASTODNamedObject odElement) {
.collect(Collectors.toList()),
odElement.getODAttributeList()
.stream()
- .map(a -> new OD4DataFullPrettyPrinter(new IndentPrinter()).prettyprint(a.getODValue()))
+ .map(a -> OD4DevelopmentMill.prettyPrint(a.getODValue(), false))
.collect(Collectors.toList()),
odElement.getName());
@@ -156,15 +155,15 @@ public void createChecker(ASTODNamedObject odElement) {
.collect(Collectors.toList()),
odElement.getODAttributeList()
.stream()
- .map(a -> new OD4DataFullPrettyPrinter(new IndentPrinter()).prettyprint(a.getODValue()))
+ .map(a -> OD4DevelopmentMill.prettyPrint(a.getODValue(), false))
.collect(Collectors.toList()),
odElement.getMCObjectType().printType());
}
public void handleLinks(ASTODLink odLink) {
- List leftSides = odLink.getODLinkLeftSide().getReferenceNamesList().stream().map(ASTODName::getName).collect(Collectors.toList());
+ List leftSides = odLink.getODLinkLeftSide().getReferenceNamesList().stream().map(ASTODName::getName).toList();
- List rightSides = odLink.getODLinkRightSide().getReferenceNamesList().stream().map(ASTODName::getName).collect(Collectors.toList());
+ List rightSides = odLink.getODLinkRightSide().getReferenceNamesList().stream().map(ASTODName::getName).toList();
String rightRoleName = odLink.getODLinkRightSide().isPresentRole() ? odLink.getODLinkRightSide().getRole() : "";
String leftRoleName = odLink.getODLinkLeftSide().isPresentRole() ? odLink.getODLinkLeftSide().getRole() : "";
@@ -213,9 +212,9 @@ public void handleLinks(ASTODLink odLink) {
}
}
// in case of direction disruption, we choose how it is possible to navigate
- else if (cdRoleOfLeft.isPresent() && !cdRoleOfRight.isPresent()) {
+ else if (cdRoleOfLeft.isPresent() && cdRoleOfRight.isEmpty()) {
this.linkAttributeList.add(constructLink(left, right, rightRoleName, cdRoleOfLeft));
- } else if (!cdRoleOfLeft.isPresent() && cdRoleOfRight.isPresent()) {
+ } else if (cdRoleOfLeft.isEmpty() && cdRoleOfRight.isPresent()) {
this.linkAttributeList.add(constructLink(right, left, leftRoleName, cdRoleOfRight));
}
@@ -267,13 +266,20 @@ protected Optional findRole(String src, String tgt, String roleNa
if (objSym.isPresent()) {
// find type of object
String typeName = objSym.get().getMCObjectType().printType();
- TypeSymbol type = OD4DevelopmentMill.globalScope().resolveType(typeName).get();
+ Optional resolvedType = OD4DevelopmentMill.globalScope().resolveType(typeName);
+ if (resolvedType.isEmpty()) {
+ return res;
+ }
+ TypeSymbol type = resolvedType.get();
+ if (!(type.getSpannedScope() instanceof IODLinkScope)) {
+ return res;
+ }
// find hidden cdRole in resolved type
String roleName2resolve = roleName.isEmpty() ? tgt : roleName;
List types = ((IODLinkScope) type.getSpannedScope()).resolveFieldDownMany(roleName2resolve);
- if (types.size() > 0 && types.get(0) instanceof CDRoleAdapter) {
- res = Optional.of((CDRoleAdapter) types.get(0));
+ if (!types.isEmpty() && types.getFirst() instanceof CDRoleAdapter) {
+ res = Optional.of((CDRoleAdapter) types.getFirst());
}
}
@@ -301,7 +307,7 @@ protected String constructLink(String src, String tgt, String roleName, Optional
cardModifier = cardModifier(cdRole.get());
}
- if (OD4DevelopmentMill.globalScope().getSubScopes().size() >= 1) {
+ if (!OD4DevelopmentMill.globalScope().getSubScopes().isEmpty()) {
return src + "." + ((roleName.isEmpty())
? findObjectAccessorName4Role(tgt) + cardModifier
: roleName + cardModifier) + "(" + tgt + ")";
@@ -315,36 +321,16 @@ protected String constructLink(String src, String tgt, String roleName, Optional
protected String cardModifier(CDRoleAdapter cdRole) {
String cardModifier = "";
- if (OD4DevelopmentMill.globalScope().getSubScopes().size() >= 1) {
- switch (cdRole.getCardinality()) {
- case ONE:
- cardModifier = "";
- break;
- case OPTIONAL:
- cardModifier = "";
- break;
- case STAR:
- cardModifier = "Add";
- break;
- case PLUS:
- cardModifier = "Add";
- break;
- }
+ if (!OD4DevelopmentMill.globalScope().getSubScopes().isEmpty()) {
+ cardModifier = switch (cdRole.getCardinality()) {
+ case ONE, OPTIONAL -> "";
+ case STAR, PLUS -> "Add";
+ };
} else {
- switch (cdRole.getCardinality()) {
- case ONE:
- cardModifier = "set";
- break;
- case OPTIONAL:
- cardModifier = "set";
- break;
- case STAR:
- cardModifier = "add";
- break;
- case PLUS:
- cardModifier = "add";
- break;
- }
+ cardModifier = switch (cdRole.getCardinality()) {
+ case ONE, OPTIONAL -> "set";
+ case STAR, PLUS -> "add";
+ };
}
return cardModifier;
}
diff --git a/src/main/java/de/monticore/od2plantuml/ODPlantUMLTool.java b/src/main/java/de/monticore/od2plantuml/ODPlantUMLTool.java
index 1021b020..fcb311a5 100644
--- a/src/main/java/de/monticore/od2plantuml/ODPlantUMLTool.java
+++ b/src/main/java/de/monticore/od2plantuml/ODPlantUMLTool.java
@@ -2,43 +2,70 @@
import de.monticore.io.paths.MCPath;
import de.monticore.od2plantuml.prettyprinter.PlantUMLODFullPrettyPrinter;
-import de.monticore.od4data.trafo.OD4DataAttributeValueCompositionTrafo;
-import de.monticore.od4data.trafo.OD4DataDeAnonymizeObjectsTrafo;
import de.monticore.od4report.OD4ReportMill;
import de.monticore.od4report._parser.OD4ReportParser;
+import de.monticore.od4development._symboltable.CDRoleSymbolDeSer;
import de.monticore.od4report._symboltable.IOD4ReportArtifactScope;
import de.monticore.od4report._symboltable.OD4ReportScopesGenitorDelegator;
+import de.monticore.od4development.trafo.OD4DevelopmentAttributeValueCompositionTrafo;
+import de.monticore.od4development.trafo.OD4DevelopmentDeAnonymizeObjectsTrafo;
import de.monticore.odbasis._ast.ASTODArtifact;
+import de.monticore.symbols.basicsymbols.BasicSymbolsMill;
+import de.monticore.types.mcbasictypes._ast.ASTMCImportStatement;
import de.se_rwth.commons.logging.Log;
import net.sourceforge.plantuml.FileFormat;
import net.sourceforge.plantuml.FileFormatOption;
import net.sourceforge.plantuml.SourceStringReader;
+import net.sourceforge.plantuml.syntax.SyntaxChecker;
+import net.sourceforge.plantuml.syntax.SyntaxResult;
import org.apache.commons.cli.*;
+import org.apache.commons.cli.help.HelpFormatter;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Locale;
import java.util.Optional;
/**
- * Base class that is used to define the PlantUML based pretty printer.
+ * Tool for generating PlantUML diagrams from Object Diagram (OD) models.
*/
public class ODPlantUMLTool {
+ public static final String PARSE_ERROR_CLI = "0xA7105 Could not process parameters: %s";
+ public static final String PARSE_ERROR_MODEL = "0xA1050x51507 Model could not be parsed.";
+ public static final String PARSE_ERROR_IO = "0xA1051x70629 Failed to parse %s";
+ public static final String ERROR_MISSING_EXTENSION =
+ "0x0D011: Missing output file extension for -pp. Supported examples: .png, .svg, .eps.";
+ public static final String ERROR_UNSUPPORTED_FORMAT =
+ "0x0D012: Unsupported output format '%s' for -pp.";
+ public static final String ERROR_GENERATE_IMAGE = "0x0D010: Error generating diagram image: %s";
+ public static final String ERROR_INVALID_PLANTUML = "0x0D033: Generated PlantUML is invalid: %s";
+ public static final String SUCCESS_IMAGE_GENERATED = "Diagram image generated and saved as: %s";
+
/**
- * This is the driver method responsible for PlantUML tool creation.
+ * Processes CLI arguments and executes parsing, symbol table creation and PlantUML image
+ * generation.
+ *
+ *
+ *
{@code -h}/{@code --help}: prints the help dialog and exits.
+ *
{@code -i}/{@code --input }: sets the mandatory input OD file to parse.
+ *
{@code -path }: sets one or more symbol path entries for imported symbols.
+ *
{@code -pp}/{@code --prettyprint [file]}: generates a PlantUML image to the given file,
+ * or prints the PlantUML source to stdout when no file is given.
+ *
+ *
*
- * @param args Command line arguments enabling different features in the tool
- * -h description and help dialog of the tool
- * -i (mandatory) parse input OD file and return if successful -s
- * specify the symbol table -pp pretty printing the OD in different
- * formats(e.g. - PNG)
+ * @param args command line arguments
*/
public void run(String[] args) {
- Log.init();
OD4ReportMill.init();
+ // needed to load imported symbols that use primitive types
+ BasicSymbolsMill.initializePrimitives();
Options options = initOptions();
try {
@@ -67,37 +94,49 @@ public void run(String[] args) {
return;
}
- if (cmd.hasOption("s")) {
- MCPath mcPath = new MCPath(cmd.getOptionValue("s"));
+ // if -path is set: set symbol path and load imported diagrams
+ if (cmd.hasOption("path")) {
+ MCPath mcPath = new MCPath();
+ String[] paths = cmd.getOptionValues("path");
+ if (paths != null) {
+ // support multiple -path entries passed via CLI
+ Arrays.stream(paths).forEach(p -> mcPath.addEntry(Paths.get(p)));
+ }
OD4ReportMill.globalScope().setSymbolPath(mcPath);
- }
- else {
- createSymbolTable(ast.get());
+ OD4ReportMill.globalScope()
+ .putTypeSymbolDeSer("de.monticore.cdbasis._symboltable.CDTypeSymbol");
+ OD4ReportMill.globalScope()
+ .putSymbolDeSer("de.monticore.cdassociation._symboltable.CDRoleSymbol",
+ new CDRoleSymbolDeSer());
+
+ for (ASTMCImportStatement i : ast.get().getMCImportStatementList()) {
+ OD4ReportMill.globalScope().loadDiagram(i.getQName());
+ }
}
- new OD4DataDeAnonymizeObjectsTrafo().transform(ast.get());
- new OD4DataAttributeValueCompositionTrafo().transform(ast.get());
+ createSymbolTable(ast.get());
+
+ new OD4DevelopmentDeAnonymizeObjectsTrafo().transform(ast.get());
+ new OD4DevelopmentAttributeValueCompositionTrafo().transform(ast.get());
// -option pretty print
if (cmd.hasOption("pp")) {
String path = cmd.getOptionValue("pp", StringUtils.EMPTY);
- FileFormat extension = FileFormat.valueOf(FilenameUtils.getExtension(path).toUpperCase());
- String base = FilenameUtils.getBaseName(path);
- prettyPrint(ast.get(), base, extension);
+ prettyPrint(ast.get(), path);
}
}
catch (ParseException e) {
// an unexpected error from the apache CLI parser:
- Log.error("0xA7105 Could not process parameters: " + e.getMessage());
+ Log.error(String.format(PARSE_ERROR_CLI, e.getMessage()));
}
}
/**
- * This method parses the provided OD file.
+ * Parses the given OD model file and returns the resulting AST.
*
- * @param model filename for the OD model, not null
- * @return the ast for the OD artifact
+ * @param model path to the OD model file, not null
+ * @return the parsed {@link ASTODArtifact}, or {@link java.util.Optional#empty()} on failure
*/
private Optional parse(String model) {
try {
@@ -107,68 +146,58 @@ private Optional parse(String model) {
if (!parser.hasErrors() && optAst.isPresent()) {
return optAst;
}
- Log.error("0xA1050x51507 Model could not be parsed.");
+ Log.error(PARSE_ERROR_MODEL);
}
- catch (NullPointerException | IOException e) {
- Log.error("0xA1051x70629 Failed to parse " + model, e);
+ catch (IOException e) {
+ Log.error(String.format(PARSE_ERROR_IO, model), e);
}
return Optional.empty();
}
/**
- * This method initializes the command line arguments
+ * Initializes the CLI options for this tool.
*
- * @return {@link Options} object
+ * @return configured {@link Options} instance
*/
private Options initOptions() {
Options options = new Options();
- options.addOption(Option.builder("h")
- .longOpt("help")
- .desc("Prints this help dialog")
- .build());
+ options.addOption(Option.builder("h").longOpt("help").desc("Prints this help dialog").get());
- options.addOption(Option.builder("i")
- .longOpt("input")
- .argName("file")
- .hasArg()
- .desc("Reads the source file (mandatory) and parses the contents")
- .build());
+ options.addOption(Option.builder("i").longOpt("input").argName("file").hasArg()
+ .desc("Reads the source file (mandatory) and parses the contents").get());
- options.addOption(Option.builder("pp")
- .longOpt("prettyprint")
- .argName("file")
- .optionalArg(true)
- .numberOfArgs(1)
- .desc("Prints the AST to stdout or the specified file (optional)")
- .build());
+ options.addOption(Option.builder("pp").longOpt("prettyprint").argName("file").optionalArg(true)
+ .numberOfArgs(1).desc("Prints the AST to stdout or the specified file (optional)").get());
- options.addOption(Option.builder("s")
- .longOpt("symboltable")
- .argName("file")
- .hasArg()
- .desc("Serialized the Symbol table of the given artifact.")
- .build());
+ options.addOption(
+ Option.builder("path").argName("dirlist").hasArgs()
+ .desc("Sets the artifact path for imported symbols").get());
return options;
}
/**
- * This method prints the help dialog.
+ * Prints the help dialog to stdout.
*
- * @param options printing the initialized {@link Options}
+ * @param options the configured CLI options to display
*/
public void printHelp(Options options) {
- HelpFormatter formatter = new HelpFormatter();
- formatter.setWidth(80);
- formatter.printHelp("ODPlantUMLTool", options);
+ org.apache.commons.cli.help.HelpFormatter formatter = HelpFormatter.builder().get();
+ try {
+ formatter.printHelp("ODPlantUMLTool", "", options, "", true);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
}
/**
- * This method acts as a registry for injecting actual pretty printers into the framework.
+ * Generates a PlantUML image from the given AST and writes it to the given file using the
+ * specified format.
*
- * @param ast parsed ast for the OD
- * @param file the OD file
- * @param fileFormat pretty printed format of the OD(e.g. - PNG)
+ * @param ast parsed OD artifact
+ * @param file destination file path without extension
+ * @param fileFormat target image format (e.g. PNG)
*/
public void prettyPrint(ASTODArtifact ast, String file, FileFormat fileFormat) {
PlantUMLODFullPrettyPrinter printer = new PlantUMLODFullPrettyPrinter();
@@ -177,34 +206,78 @@ public void prettyPrint(ASTODArtifact ast, String file, FileFormat fileFormat) {
}
/**
- * Rendering the pretty printed OD into an image.
+ * Pretty prints the OD artifact either to stdout (when no path is given) or renders an image
+ * file. The image format is derived from the file extension of {@code path}.
+ *
+ * @param ast parsed OD artifact
+ * @param path output file path including extension; blank means stdout
+ */
+ public void prettyPrint(ASTODArtifact ast, String path) {
+ PlantUMLODFullPrettyPrinter printer = new PlantUMLODFullPrettyPrinter();
+ String result = printer.prettyprint(ast);
+
+ if (StringUtils.isBlank(path)) {
+ System.out.println(result);
+ return;
+ }
+
+ String extension = FilenameUtils.getExtension(path);
+ if (StringUtils.isBlank(extension)) {
+ Log.error(ERROR_MISSING_EXTENSION);
+ return;
+ }
+
+ try {
+ FileFormat fileFormat = FileFormat.valueOf(extension.toUpperCase(Locale.ROOT));
+ String destinationPath = FilenameUtils.removeExtension(path);
+ generateImage(result, destinationPath, fileFormat);
+ }
+ catch (IllegalArgumentException e) {
+ Log.error(String.format(ERROR_UNSUPPORTED_FORMAT, extension));
+ }
+ }
+
+ /**
+ * Renders the given PlantUML source string into an image file.
*
- * @param plantUMLSource pretty printed source OD string
- * @param destinationPath path to store the generated image
- * @param fileFormat format in which image must be generated(e.g. -PNG)
+ * @param plantUMLSource PlantUML source string to render
+ * @param destinationPath target file path without extension
+ * @param fileFormat target image format (e.g. PNG)
*/
public void generateImage(String plantUMLSource, String destinationPath, FileFormat fileFormat) {
+ // PlantUML renders an image showing the error for invalid sources, which must not be saved
+ SyntaxResult syntax = SyntaxChecker.checkSyntax(plantUMLSource);
+ if (syntax.isError()) {
+ Log.error(String.format(ERROR_INVALID_PLANTUML, String.join(", ", syntax.getErrors())));
+ return;
+ }
+
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
SourceStringReader reader = new SourceStringReader(plantUMLSource);
- reader.outputImage(outputStream, new FileFormatOption(fileFormat));
-
- try (FileOutputStream fileOutputStream = new FileOutputStream(
- destinationPath + fileFormat.getFileSuffix())) {
+ if (reader.outputImage(outputStream, new FileFormatOption(fileFormat)) == null) {
+ Log.error(String.format(ERROR_GENERATE_IMAGE, "no diagram found"));
+ return;
+ }
+
+ try (
+ FileOutputStream fileOutputStream = new FileOutputStream(
+ destinationPath + fileFormat.getFileSuffix())) {
outputStream.writeTo(fileOutputStream);
}
- Log.info("Diagram image generated and saved as: " + destinationPath, "SUCCESS");
+ System.out.println(
+ String.format(SUCCESS_IMAGE_GENERATED, destinationPath + fileFormat.getFileSuffix()));
}
catch (IOException e) {
- Log.error("0x0D010: Error generating diagram image: " + e.getMessage());
+ Log.error(String.format(ERROR_GENERATE_IMAGE, e.getMessage()));
}
}
/**
- * Create symbol table from the ast.
+ * Creates the symbol table for the given OD artifact.
*
- * @param node parsed ast for the OD
- * @return the symbol table
+ * @param node parsed OD artifact
+ * @return the resulting artifact scope
*/
public IOD4ReportArtifactScope createSymbolTable(ASTODArtifact node) {
OD4ReportScopesGenitorDelegator genitor = OD4ReportMill.scopesGenitorDelegator();
@@ -212,12 +285,28 @@ public IOD4ReportArtifactScope createSymbolTable(ASTODArtifact node) {
}
/**
- * The main method of the program.
+ * Entry point of the ODPlantUMLTool. Delegates to {@link #run(String[])} and exits with code
+ * {@code 0} on success or {@code 1} when errors occurred.
*
- * @param args The command-line arguments provided by the user.
+ * @param args command line arguments
*/
public static void main(String[] args) {
- ODPlantUMLTool tool = new ODPlantUMLTool();
- tool.run(args);
+ // initialized here, not in run, to keep a log configured by callers of run
+ Log.init();
+ try {
+ ODPlantUMLTool tool = new ODPlantUMLTool();
+ tool.run(args);
+ }
+ catch (Exception exception) {
+ // ensure a sane exit
+ Log.ensureInitialization();
+ Log.error(
+ "0xEEEEE an internal error occurred" + " during the execution of the ODPlantUMLTool."
+ + System.lineSeparator() + "This error is unexpected"
+ + " and does not indicate an issue with any provided models.", exception);
+ }
+ // properly exit with a code
+ Log.ensureInitialization();
+ System.exit(Log.getErrorCount() == 0 ? 0 : 1);
}
}
\ No newline at end of file
diff --git a/src/main/java/de/monticore/od2plantuml/REPORT.md b/src/main/java/de/monticore/od2plantuml/REPORT.md
index 0004fca3..ce4ced88 100644
--- a/src/main/java/de/monticore/od2plantuml/REPORT.md
+++ b/src/main/java/de/monticore/od2plantuml/REPORT.md
@@ -1,23 +1,60 @@
-# Object Diagram PlantUML Tool (ODPlantUMLTool)
+# Object Diagram PlantUML Tool (`ODPlantUMLTool`)
-The [ODPlantUMLTool](ODPlantUMLTool.java) is a Pretty Printer primarily used to pretty print
-*MontiCore's Object Diagram* models first into the PlantUML syntax and then generate
-the object diagrams as a diagrammatic image. Most of the information is kept, but some, e.g.
-attribute types are lost.
+The [`ODPlantUMLTool`](ODPlantUMLTool.java) is a pretty printer for MontiCore Object Diagrams (ODs).
+It transforms OD models into PlantUML text and then renders that text as an image.
+Most OD information is preserved during the transformation, but some details (for example attribute types)
+are currently not included in the generated PlantUML output.
-## Internal Structure of the Functionality
+## Usage of ODPlantUMLTool
+
+### Dependencies
+* Java 21 (or higher)
+* Gradle 8.5 (or higher)
+
+### Contributing to the project
+* Clone the project from GitHub
+* This project has **no Gradle wrapper** (`gradlew` is not part of the repository).
+* Ensure Gradle is installed locally and available on your `PATH`.
+
+```shell
+gradle clean build
+```
+
+### Running the application
-**Step 1. Parse the Object Diagrams**
+* The tool can be found here: [ODPlantUMLTool](ODPlantUMLTool.java)
+
+
+* Example invocations:
+ * Generate image output to file:
+ * ``` -i gentest/src/main/resources/Example.od -pp diagram.png ```
+ * Print PlantUML text to stdout:
+ * ``` -i gentest/src/main/resources/Example.od -pp ```
+ * Use symbol path(s) for imported symbols:
+ * ``` -i gentest/src/main/resources/Example.od -path some/symbol/dir another/symbol/dir -pp diagram.png ```
-1. The tool takes an Object Diagrams as input and parses it into
-its abstract syntax tree (AST) based on the
-[OD4Report](../../../grammar) grammar.
-### Example Object Diagram
+* Explanation of the CLI arguments:
+ * ``` -h ``` / ``` --help ``` prints CLI help and exits.
+ * ``` -i ``` / ``` --input ``` is **mandatory** and specifies the input `Object Diagram` model.
+ * ``` -pp ``` / ``` --prettyprint [file] ``` is optional:
+ * with a file argument, output is written/rendered to that file,
+ * without a file argument, generated PlantUML text is printed to stdout.
+ * ``` -path ``` is optional and takes one or more directories to configure symbol
+ paths. It can also be provided multiple times.
+ * If ``` -i ``` is missing, the tool prints help and exits.
+
+## How the Tool Works
-Below is an OD defined as in MontiCore's textual notation:
+### Step 1: Parse the Object Diagram
-```
+The tool reads an Object Diagram model and parses it into an Abstract Syntax Tree (AST)
+based on the OD4Report grammar. As OD4Report extends OD4Development, all OD4Development models
+are supported, as well as models using OD4Report features such as dates.
+
+### Example OD Input
+
+```text
objectdiagram Examples {
foo: A {
@@ -34,35 +71,35 @@ objectdiagram Examples {
}
```
-Objects in ODs can also be nested, expressions be used to define values. Objects and attributes
-are generally typed (here e.g. `A`, `B`), links can be explicitly defined quite like in
-MontiCore's class diagrams. Further extensions e.g. through language composition allow
-various forms and uses object diagrams.
+ODs may contain nested objects and expressions.
+Objects and attributes are typically typed (for example `A` and `B`), and links are modeled similarly to
+MontiCore class diagram associations.
-
- Figure 1: The OD ```Example``` in graphical syntax.
+
+ Figure 1: The OD Examples in graphical syntax.
+### Step 2: Pretty Print the OD to PlantUML
-**Step 2. Pretty Print the Object Diagram as a PlantUML text.**
+The tool uses MontiCore's visitor and handler infrastructure to traverse the AST and generate PlantUML text.
-1. The tool uses the [Monticore](https://monticore.github.io/monticore/) `Visitor` and
- `Handler` Infrastructure to iterate through the AST nodes and pretty prints the
+1. The tool uses the [Monticore](https://monticore.github.io/monticore/) `Visitor` and
+ `Handler` Infrastructure to iterate through the AST nodes and pretty prints the
PlantUML model.
-2. Detailed Implementation can be found here:
+2. Detailed Implementation can be found here:
[PlantUMLODFullPrettyPrinter](PlantUMLODFullPrettyPrinter.java)
This is the pretty-printed PlantUML model by the ODPlantUMLTool, which contains most of the
-OD information (but missing e.g. attribute types):
+OD information (but missing e.g. attribute types):
-```
+```text
@startuml
note "OD" as tag #white
object "__foo:A__" as foo {
- x = 5
+ x = 5
s = "hello"
}
object "__bar:B__" as bar {
- b = false
+ b = false
}
foo--> "blub" bar
@enduml
@@ -70,91 +107,26 @@ foo--> "blub" bar
**Step 3. Generate an image representing the OD as image.**
-1. The tool uses the PlantUML Java library to take the pretty printed
+1. The tool uses the PlantUML Java library to take the pretty printed
PlantUML text as input and generates an image representing the OD.
-2. Detailed Implementation can be found here: [generateImage](ODPlantUMLTool.java)
+2. Detailed Implementation can be found here: [generateImage](ODPlantUMLTool.java)
-
+
Figure 2: Generation of Object Diagram from PlantUML Model.
-## Usage of ODPlantUMLTool
-
-### Dependencies
-* Java 21 (or higher)
-* Gradle 8.5 (or higher)
-
-### Installation of the project
-* Clone the project from Gitlab
-* run *./gradlew clean*
-* run *./gradlew build*
-
-### Running the application
-
-* The tool can be found here: [ODPlantUMLTool](ODPlantUMLTool.java)
-
-
-* Run the Tool using the following CLI arguments:
- * ``` -i gentest/src/main/resources/Example.od -s gentest/src/main/resources/symboltable -pp diagram.png ```
-
-
-* Explanation of the CLI arguments:
- * ``` -i ``` flag is used to specify the location of the input `Object Diagram` model
- * ``` -s ``` flag is used to specify the location of the symbol table that must be used by the `Pretty Printer`.
- * ``` pp ``` flag is used to specify the name of the output image of the `Object Diagram` that is generated from the pretty printed `PlantUML` model.
- * These arguments values can be *modified according to individual user's requirements* like format of images (png, jpeg), location of models etc.
-
-
-* To view the pretty printed `PlantUML` model, then following steps must be performed:
- * Navigate to the tool: [ODPlantUMLTool](ODPlantUMLTool.java)
- * Move to the `prettyPrint` function at `Line 124`
- * Add and additional fragment to print the result `PlantUML model` at `Line 127` : Log.info(result,"INFO");
- * Build the project again.
- * Run the `PlantUML` Tool using suitable CLI arguments.
- * The pretty printed `PlantUML` model will be available in the logs.
-
-### Limitation of the Tool
-* Handling of Complex `Object Diagrams` with lists of objects:
- * The tool is not capable of handling OD models which have nested lists of objects within a given object.
- * An Example is shown below where we have a nested list of `cars` within an object `alice`:
-
-```
-objectdiagram MyFamily {
- alice:Person {
- age = 29;
- cars = [
- :BMW {
- bought = 2020-01-05 15:30:00;
- color = BLUE;
- },
- tiger:Jaguar {
- bought = 2000/01/05 15:00:00;
- color = RED;
- length = 5.3;
- }
- ];
- };
- bob:Person {
- nicknames = ["Bob", "Bobby", "Robert"];
- cars -> tiger;
- };
- link married alice <-> bob;
-}
-```
-
-
## Further Information
* [Project root: MontiCore @github](https://github.com/MontiCore/monticore)
* [MontiCore documentation](http://www.monticore.de/)
-* [**List of languages**](https://github.com/MontiCore/monticore/blob/opendev/docs/Languages.md)
+* [**List of languages**](https://github.com/MontiCore/monticore/blob/dev/docs/Languages.md)
* [**MontiCore Core Grammar
- Library**](https://github.com/MontiCore/monticore/blob/opendev/monticore-grammar/src/main/grammars/de/monticore/Grammars.md)
-* [Best Practices](https://github.com/MontiCore/monticore/blob/opendev/docs/BestPractices.md)
+ Library**](https://github.com/MontiCore/monticore/blob/dev/monticore-grammar/src/main/grammars/de/monticore/Grammars.md)
+* [Best Practices](https://github.com/MontiCore/monticore/blob/dev/docs/BestPractices.md)
* [Publications about MBSE and MontiCore](https://www.se-rwth.de/publications/)
* [Licence definition](https://github.com/MontiCore/monticore/blob/master/00.org/Licenses/LICENSE-MONTICORE-3-LEVEL.md)
[od4report-link]: http://www.monticore.de/download/MCOD4Report.jar
-[od4data-link]: http://www.monticore.de/download/MCOD4Data.jar
+[od4dev-link]: http://www.monticore.de/download/MCOD4Development.jar
diff --git a/src/main/java/de/monticore/od2plantuml/prettyprinter/PlantUMLODAttributePrettyPrinter.java b/src/main/java/de/monticore/od2plantuml/prettyprinter/PlantUMLODAttributePrettyPrinter.java
new file mode 100644
index 00000000..a029ad35
--- /dev/null
+++ b/src/main/java/de/monticore/od2plantuml/prettyprinter/PlantUMLODAttributePrettyPrinter.java
@@ -0,0 +1,73 @@
+/* (c) https://github.com/MontiCore/monticore */
+package de.monticore.od2plantuml.prettyprinter;
+
+import de.monticore.odattribute._ast.ASTODList;
+import de.monticore.odattribute._ast.ASTODMap;
+import de.monticore.odattribute._ast.ASTODMapElement;
+import de.monticore.odattribute._visitor.ODAttributeHandler;
+import de.monticore.odattribute._visitor.ODAttributeTraverser;
+import de.monticore.odbasis._ast.ASTODValue;
+import de.monticore.prettyprint.IndentPrinter;
+
+import java.util.List;
+
+/**
+ * Pretty prints lists and maps as attribute values, e.g., {@code [1, 2]} and {@code [1 -> 2]}.
+ */
+public class PlantUMLODAttributePrettyPrinter implements ODAttributeHandler {
+
+ private final IndentPrinter printer;
+ private ODAttributeTraverser traverser;
+
+ public PlantUMLODAttributePrettyPrinter(IndentPrinter printer) {
+ this.printer = printer;
+ }
+
+ @Override
+ public ODAttributeTraverser getTraverser() {
+ return traverser;
+ }
+
+ @Override
+ public void setTraverser(ODAttributeTraverser traverser) {
+ this.traverser = traverser;
+ }
+
+ @Override
+ public void handle(ASTODList node) {
+ List values = node.getODValueList();
+ printer.print("[");
+ for (int i = 0; i < values.size(); i++) {
+ if (i > 0) {
+ printer.stripTrailing();
+ printer.print(", ");
+ }
+ values.get(i).accept(getTraverser());
+ }
+ printer.stripTrailing();
+ printer.print("]");
+ }
+
+ @Override
+ public void handle(ASTODMap node) {
+ List elements = node.getODMapElementList();
+ printer.print("[");
+ for (int i = 0; i < elements.size(); i++) {
+ if (i > 0) {
+ printer.stripTrailing();
+ printer.print(", ");
+ }
+ elements.get(i).accept(getTraverser());
+ }
+ printer.stripTrailing();
+ printer.print("]");
+ }
+
+ @Override
+ public void handle(ASTODMapElement node) {
+ node.getKey().accept(getTraverser());
+ printer.stripTrailing();
+ printer.print(" -> ");
+ node.getVal().accept(getTraverser());
+ }
+}
diff --git a/src/main/java/de/monticore/od2plantuml/prettyprinter/PlantUMLODBasisPrettyPrinter.java b/src/main/java/de/monticore/od2plantuml/prettyprinter/PlantUMLODBasisPrettyPrinter.java
index a4b72037..b99ba1ea 100644
--- a/src/main/java/de/monticore/od2plantuml/prettyprinter/PlantUMLODBasisPrettyPrinter.java
+++ b/src/main/java/de/monticore/od2plantuml/prettyprinter/PlantUMLODBasisPrettyPrinter.java
@@ -17,7 +17,8 @@ public class PlantUMLODBasisPrettyPrinter implements ODBasisVisitor2, ODBasisHan
private final IndentPrinter printer;
private ODBasisTraverser traverser;
- private final Map anonymousObjectsNameCache = new LinkedHashMap<>();
+ /** Deterministic aliases for anonymous objects that were not named by a trafo. */
+ private final Map anonymousObjectsNameCache = new LinkedHashMap<>();
public PlantUMLODBasisPrettyPrinter(IndentPrinter printer) {
this.printer = printer;
@@ -64,8 +65,8 @@ protected boolean hasBeenDeAnonymizedByTrafo(ASTODNamedObject node) {
public void visit(ASTODAnonymousObject node) {
var typesPrinter = new MCBasicTypesFullPrettyPrinter(new IndentPrinter());
var printedType = typesPrinter.prettyprint(node.getMCObjectType());
- this.anonymousObjectsNameCache.putIfAbsent(node, UUID.randomUUID());
- String nodeName = this.anonymousObjectsNameCache.get(node).toString();
+ String nodeName = this.anonymousObjectsNameCache.computeIfAbsent(node,
+ n -> "__anonymous_" + (anonymousObjectsNameCache.size() + 1));
printer.println(
String.format("object \"__:%2$s__\" as %1$s {", nodeName, printedType));
}
@@ -104,4 +105,9 @@ public void endVisit(ASTObjectDiagram node) {
public void visit(ASTODName node) {
printer.print(node.getName());
}
+
+ @Override
+ public void visit(ASTODAbsent node) {
+ printer.print("...");
+ }
}
diff --git a/src/main/java/de/monticore/od2plantuml/prettyprinter/PlantUMLODFullPrettyPrinter.java b/src/main/java/de/monticore/od2plantuml/prettyprinter/PlantUMLODFullPrettyPrinter.java
index bfe3a750..9194c370 100644
--- a/src/main/java/de/monticore/od2plantuml/prettyprinter/PlantUMLODFullPrettyPrinter.java
+++ b/src/main/java/de/monticore/od2plantuml/prettyprinter/PlantUMLODFullPrettyPrinter.java
@@ -2,6 +2,7 @@
import de.monticore.dateliterals._prettyprint.DateLiteralsPrettyPrinter;
import de.monticore.expressions.commonexpressions._prettyprint.CommonExpressionsPrettyPrinter;
+import de.monticore.expressions.expressionsbasis._prettyprint.ExpressionsBasisPrettyPrinter;
import de.monticore.literals.mccommonliterals._prettyprint.MCCommonLiteralsPrettyPrinter;
import de.monticore.od4report.OD4ReportMill;
import de.monticore.od4report._visitor.OD4ReportTraverser;
@@ -24,6 +25,14 @@ public PlantUMLODFullPrettyPrinter() {
new MCCommonLiteralsPrettyPrinter(printer, false);
traverser.add4MCCommonLiterals(literalsPrettyPrinter);
traverser.setMCCommonLiteralsHandler(literalsPrettyPrinter);
+ ExpressionsBasisPrettyPrinter expressionsBasisPrettyPrinter =
+ new ExpressionsBasisPrettyPrinter(printer, false);
+ traverser.add4ExpressionsBasis(expressionsBasisPrettyPrinter);
+ traverser.setExpressionsBasisHandler(expressionsBasisPrettyPrinter);
+ // lists and maps as attribute values, printed in OD syntax
+ PlantUMLODAttributePrettyPrinter odAttributePrettyPrinter =
+ new PlantUMLODAttributePrettyPrinter(printer);
+ traverser.setODAttributeHandler(odAttributePrettyPrinter);
CommonExpressionsPrettyPrinter commonExpressionsPrettyPrinter =
new CommonExpressionsPrettyPrinter(printer, false);
traverser.add4CommonExpressions(commonExpressionsPrettyPrinter);
diff --git a/src/main/java/de/monticore/od2plantuml/prettyprinter/PlantUMLODLinkPrettyPrinter.java b/src/main/java/de/monticore/od2plantuml/prettyprinter/PlantUMLODLinkPrettyPrinter.java
index 78bebe4b..deaa23a4 100644
--- a/src/main/java/de/monticore/od2plantuml/prettyprinter/PlantUMLODLinkPrettyPrinter.java
+++ b/src/main/java/de/monticore/od2plantuml/prettyprinter/PlantUMLODLinkPrettyPrinter.java
@@ -2,9 +2,7 @@
import de.monticore.odbasis._visitor.ODBasisHandler;
import de.monticore.odbasis._visitor.ODBasisVisitor2;
-import de.monticore.odlink.ODLinkMill;
import de.monticore.odlink._ast.*;
-import de.monticore.odlink._util.IODLinkTypeDispatcher;
import de.monticore.odlink._visitor.ODLinkHandler;
import de.monticore.odlink._visitor.ODLinkTraverser;
import de.monticore.odlink._visitor.ODLinkVisitor2;
@@ -61,39 +59,47 @@ protected String getLinkRepresentation(ASTODLink node) {
String linkRepresentation = "--";
ASTODLinkDirection linkDirection = node.getODLinkDirection();
- IODLinkTypeDispatcher typeDispatcher = ODLinkMill.typeDispatcher();
-
- if (typeDispatcher.isODLinkASTODLeftToRightDir(linkDirection)) {
- if (!symbol.isEmpty()) {
- linkRepresentation = symbol + linkRepresentation;
- }
- linkRepresentation = linkRepresentation + ">";
- }
- else if (typeDispatcher.isODLinkASTODRightToLeftDir(linkDirection)) {
- if (!symbol.isEmpty()) {
- linkRepresentation = linkRepresentation + symbol;
- }
- linkRepresentation = "<" + linkRepresentation;
- }
- else if (typeDispatcher.isODLinkASTODBiDir(linkDirection)) {
- linkRepresentation =
- (symbol.isEmpty() ? "<" : symbol) + linkRepresentation + (symbol.isEmpty() ? ">"
- : symbol);
- }
+ linkRepresentation = switch (linkDirection) {
+ case ASTODLeftToRightDir dir -> (symbol.isEmpty() ? "" : symbol) + linkRepresentation + ">";
+ case ASTODRightToLeftDir dir -> "<" + linkRepresentation + (symbol.isEmpty() ? "" : symbol);
+ case ASTODBiDir dir -> (symbol.isEmpty() ? "<" : symbol) + linkRepresentation + (symbol.isEmpty() ? ">"
+ : symbol);
+ default -> symbol + linkRepresentation;
+ };
+
return " " + linkRepresentation + " ";
}
-
+
+ /** Prints {@code [qualifier] "role"}, as PlantUML expects it on the left side. */
@Override
public void handle(ASTODLinkLeftSide node) {
+ printQualifier(node);
if (node.isPresentRole()) {
printer.print(" \"" + node.getRole() + "\" ");
}
}
-
+
+ /** Prints {@code "role" [qualifier]}, as PlantUML expects it on the right side. */
@Override
public void handle(ASTODLinkRightSide node) {
if (node.isPresentRole()) {
printer.print(" \"" + node.getRole() + "\" ");
}
+ printQualifier(node);
+ }
+
+ protected void printQualifier(ASTODLinkSide node) {
+ if (!node.isPresentODLinkQualifier()) {
+ return;
+ }
+ ASTODLinkQualifier qualifier = node.getODLinkQualifier();
+ printer.print(" [");
+ if (qualifier.isPresentName()) {
+ printer.print(qualifier.getName());
+ }
+ else {
+ qualifier.getODValue().accept(getTraverser());
+ }
+ printer.print("] ");
}
}
\ No newline at end of file
diff --git a/src/main/java/de/monticore/od4data/OD4DataMill.java b/src/main/java/de/monticore/od4data/OD4DataMill.java
deleted file mode 100644
index 0d41e774..00000000
--- a/src/main/java/de/monticore/od4data/OD4DataMill.java
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * (c) https://github.com/MontiCore/monticore
- */
-
-package de.monticore.od4data;
-
-import de.monticore.od4data.types3.OD4DataTypeCheck3;
-
-public class OD4DataMill extends OD4DataMillTOP {
-
- /** additionally inits the TypeCheck */
- public static void init() {
- OD4DataMillTOP.init();
- OD4DataTypeCheck3.init();
- }
-}
diff --git a/src/main/java/de/monticore/od4data/OD4DataTool.java b/src/main/java/de/monticore/od4data/OD4DataTool.java
deleted file mode 100644
index a34aac31..00000000
--- a/src/main/java/de/monticore/od4data/OD4DataTool.java
+++ /dev/null
@@ -1,258 +0,0 @@
-/* (c) https://github.com/MontiCore/monticore */
-package de.monticore.od4data;
-
-import de.monticore.io.paths.MCPath;
-import de.monticore.od4data._symboltable.IOD4DataArtifactScope;
-import de.monticore.od4data._prettyprint.OD4DataFullPrettyPrinter;
-import de.monticore.odbasis._ast.ASTODArtifact;
-import de.monticore.prettyprint.IndentPrinter;
-import de.monticore.symbols.basicsymbols.BasicSymbolsMill;
-import de.se_rwth.commons.logging.Log;
-import org.apache.commons.cli.*;
-import org.apache.commons.io.FilenameUtils;
-import org.apache.commons.lang3.StringUtils;
-
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Arrays;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-/**
- * Command line interface for the OD language and corresponding tooling. Defines, handles, and
- * executes the corresponding command line options and arguments, such as --help
- */
-public class OD4DataTool extends OD4DataToolTOP {
-
- protected static final String PARSE_SUCCESSFUL = "Successfully parsed %s\n";
-
- protected static final String CHECK_SUCCESSFUL =
- "Successfully checked the CoCos for class " + "diagram %s\n";
-
- protected static final String CHECK_ERROR = "Error while parsing or CoCo checking";
-
- protected static final String STEXPORT_SUCCESSFUL = "Creation of symbol file %s successful\n";
-
- protected static final String INPUT_FILE_NOT_EXISTENT = "Input file '%s' does not exist\n";
-
- /*=================================================================*/
- /* Part 1: Handling the arguments and options
- /*=================================================================*/
-
- /**
- * Processes user input from command line and delegates to the corresponding tools.
- *
- * @param args The input parameters for configuring the OD tool.
- */
- @Override
- public void run(String[] args) {
- init();
- Options options = initOptions();
-
- try {
- // create CLI parser and parse input options from command line
- CommandLineParser cliparser = new DefaultParser();
- CommandLine cmd = cliparser.parse(options, args);
-
- // help: when --help
- if (cmd.hasOption("h")) {
- printHelp(options);
- // do not continue, when help is printed
- return;
- }
-
- // if -i input is missing: also print help and stop
- if (!cmd.hasOption("i")) {
- printHelp(options);
- // do not continue, when help is printed
- return;
- }
-
- // if -path is set: save the model paths
- MCPath symbolPath = new MCPath();
- if (cmd.hasOption("path")) {
- String[] paths = cmd.getOptionValues("path");
- Arrays.stream(paths).forEach(p -> symbolPath.addEntry(Paths.get(p)));
- BasicSymbolsMill.initializePrimitives();
- OD4DataMill.globalScope().putTypeSymbolDeSer("de.monticore.cdbasis._symboltable.CDTypeSymbol");
- }
- OD4DataMill.globalScope().setSymbolPath(symbolPath);
-
- // don't output to stdout when the prettyprint is output to stdout
- final boolean doPrintToStdOut = !(cmd.hasOption("pp") && cmd.getOptionValue("pp") == null);
-
- // parse input file
- String modelFile = cmd.getOptionValue("i");
- Path modelFilePath = Paths.get(modelFile);
- if (!modelFilePath.toFile().exists()) {
- System.out.printf(INPUT_FILE_NOT_EXISTENT, modelFile);
- return;
- }
-
- ASTODArtifact astodArtifact = parse(modelFile);
-
- if (doPrintToStdOut) {
- System.out.printf(PARSE_SUCCESSFUL, astodArtifact.getObjectDiagram().getName());
- }
-
- // -option check cocos
- Set cocoOptionValue = new LinkedHashSet<>();
- if (cmd.hasOption("c") && cmd.getOptionValues("c") != null) {
- cocoOptionValue.addAll(Arrays.asList(cmd.getOptionValues("c")));
- }
-
- // create symbol table
- IOD4DataArtifactScope od4DataArtifactScope = OD4DataToolAPI.createSymbolTable(astodArtifact,
- !cocoOptionValue.contains("intra"));
-
- // run cocos
- if (cmd.hasOption("c")) {
- if (cocoOptionValue.contains("intra")) {
- OD4DataToolAPI.runAllIntraCoCos(astodArtifact);
- }
- else {
- OD4DataToolAPI.runAllCoCos(astodArtifact);
- }
-
- if (doPrintToStdOut) {
- if (Log.getErrorCount() == 0) {
- System.out.printf(CHECK_SUCCESSFUL, astodArtifact.getObjectDiagram().getName());
- }
- else {
- System.out.println(CHECK_ERROR);
- return;
- }
- }
- }
-
- // -option pretty print
- if (cmd.hasOption("pp")) {
- String path = cmd.getOptionValue("pp", StringUtils.EMPTY);
- prettyPrint(astodArtifact, path);
- }
-
- // -option pretty print symboltable
- if (cmd.hasOption("s")) {
- Path symTabPath = storeSymTab(od4DataArtifactScope, modelFilePath,cmd.getOptionValue("s"));
- if (doPrintToStdOut) {
- System.out.printf(STEXPORT_SUCCESSFUL, symTabPath.toAbsolutePath());
- }
- }
- }
- catch (ParseException e) {
- // an unexpected error from the apache CLI parser:
- Log.error("0xA7121 Could not process CLI parameters: " + e.getMessage());
- }
- }
-
- /*=================================================================*/
- /* Part 2: Executing arguments
- /*=================================================================*/
-
- /**
- * Prints the contents of the OD-AST to stdout or a specified file.
- *
- * @param astodArtifact The OD-AST to be pretty printed
- * @param file The target file name for printing the OD artifact. If empty, the content
- * is printed to stdout instead
- */
- @Override
- public void prettyPrint(ASTODArtifact astodArtifact, String file) {
- // pretty print AST
- OD4DataFullPrettyPrinter pp = new OD4DataFullPrettyPrinter(new IndentPrinter());
- String od = pp.prettyprint(astodArtifact);
- print(od, file);
- }
-
-
- /*=================================================================*/
- /* Part 3: Defining the options incl. help-texts
- /*=================================================================*/
-
- /**
- * Initializes the standard options for the OD tool.
- *
- * @return The CLI options with arguments.
- */
- @Override
- public Options addStandardOptions(Options options) {
- // help dialog
- options.addOption(Option.builder("h").longOpt("help").desc("Prints this help dialog").build());
-
- // parse input file
- options.addOption(Option.builder("i")
- .longOpt("input")
- .argName("file")
- .hasArg()
- .desc("Reads the source file (mandatory) and parses the contents as an " + "object diagram")
- .build());
-
- // model paths
- options.addOption(Option.builder("path")
- .argName("dirlist")
- .numberOfArgs(Option.UNLIMITED_VALUES)
- .hasArg()
- .desc("Sets the artifact path for imported symbols")
- .build());
-
- // pretty print OD
- options.addOption(Option.builder("pp")
- .longOpt("prettyprint")
- .argName("file")
- .optionalArg(true)
- .numberOfArgs(1)
- .desc("Prints the OD-AST to stdout or the specified file (optional)")
- .build());
-
- // print OD symtab
- options.addOption(Option.builder("s")
- .longOpt("symboltable")
- .argName("file")
- .optionalArg(true)
- .numberOfArgs(1)
- .desc("Stores the symbol table of the OD. The default value is `{ODName}.odsym`.")
- .build());
-
- return options;
- }
-
- @Override
- public Options addAdditionalOptions(Options options) {
- // check cocos
- options.addOption(Option.builder("c")
- .longOpt("coco")
- .optionalArg(true)
- .numberOfArgs(3)
- .desc("Checks the CoCos for the input. Optional arguments are:\n"
- + "-c intra to check only the" + " intra-model CoCos,\n"
- + "-c inter checks also inter-model CoCos,\n" + "-c type "
- + "(default) checks all CoCos.")
- .build());
- return options;
- }
-
- /**
- * prints the symboltable of the given scope out to a file
- *
- * @param as symboltable to store
- * @param modelPath location of the file containing the OD
- * @param symTabPath location of the file or directory containing the printed table
- */
- public Path storeSymTab(IOD4DataArtifactScope as, Path modelPath, String symTabPath) {
- Path targetPath;
- if (symTabPath == null || symTabPath.isBlank()) {
- String symTabName = FilenameUtils.getBaseName(modelPath.toString()) + ".odsym";
- targetPath = modelPath.getParent().resolve(symTabName);
- }
- else {
- targetPath = Paths.get(symTabPath);
- if (targetPath.toFile().exists() && targetPath.toFile().isDirectory()) {
- String symTabName = FilenameUtils.getBaseName(modelPath.toString()) + ".odsym";
- targetPath = targetPath.resolve(symTabName);
- }
- }
- this.storeSymbols(as, targetPath.toString());
- return targetPath;
- }
-
-}
diff --git a/src/main/java/de/monticore/od4data/OD4DataToolAPI.java b/src/main/java/de/monticore/od4data/OD4DataToolAPI.java
deleted file mode 100644
index 6960055a..00000000
--- a/src/main/java/de/monticore/od4data/OD4DataToolAPI.java
+++ /dev/null
@@ -1,65 +0,0 @@
-// (c) https://github.com/MontiCore/monticore
-
-package de.monticore.od4data;
-
-import de.monticore.od4data._cocos.OD4DataCoCos;
-import de.monticore.od4data._parser.OD4DataParser;
-import de.monticore.od4data._symboltable.IOD4DataArtifactScope;
-import de.monticore.od4data._symboltable.OD4DataScopesGenitorDelegator;
-import de.monticore.odbasis._ast.ASTODArtifact;
-import de.se_rwth.commons.logging.Log;
-import org.antlr.v4.runtime.RecognitionException;
-
-import java.io.IOException;
-import java.util.Optional;
-
-public class OD4DataToolAPI {
-
- /**
- * Parse the model contained in the specified file.
- *
- * @param model - file to parse
- * @return Artifact containing the OD
- */
- public static ASTODArtifact parse(String model) {
- try {
- OD4DataParser parser = OD4DataMill.parser();
- Optional optODArtifact = parser.parse(model);
-
- if (!parser.hasErrors() && optODArtifact.isPresent()) {
- return optODArtifact.get();
- }
- Log.error("0x0D011: Model could not be parsed.");
- }
- catch (RecognitionException | IOException e) {
- Log.error("0x0D012: Failed to parse " + model, e);
- }
- return null;
- }
-
- /**
- * Create the symbol table from the parsed AST.
- *
- * @param ast ODArtifact ast
- * @return Symboltable created form AST
- */
- public static IOD4DataArtifactScope createSymbolTable(ASTODArtifact ast, boolean checkTypes) {
- OD4DataScopesGenitorDelegator od4DataScopesGenitorDelegator =
- OD4DataMill.scopesGenitorDelegator();
- od4DataScopesGenitorDelegator.setCheckTypes(checkTypes);
- return od4DataScopesGenitorDelegator.createFromAST(ast);
- }
-
- public static IOD4DataArtifactScope createSymbolTable(ASTODArtifact ast) {
- return OD4DataToolAPI.createSymbolTable(ast, false);
- }
-
- public static void runAllCoCos(ASTODArtifact ast) {
- new OD4DataCoCos().getCheckerForAllCoCos().checkAll(ast);
- }
-
- public static void runAllIntraCoCos(ASTODArtifact ast) {
- new OD4DataCoCos().getCheckerForAllIntraCoCos().checkAll(ast);
- }
-
-}
diff --git a/src/main/java/de/monticore/od4data/_cocos/OD4DataCoCos.java b/src/main/java/de/monticore/od4data/_cocos/OD4DataCoCos.java
deleted file mode 100644
index 6b3ee871..00000000
--- a/src/main/java/de/monticore/od4data/_cocos/OD4DataCoCos.java
+++ /dev/null
@@ -1,26 +0,0 @@
-// (c) https://github.com/MontiCore/monticore
-
-package de.monticore.od4data._cocos;
-
-import de.monticore.odbasis._cocos.ODBasicsCoCos;
-import de.monticore.odlink._cocos.ODLinkCoCos;
-
-public class OD4DataCoCos {
-
- public OD4DataCoCoChecker getCheckerForAllIntraCoCos() {
- final OD4DataCoCoChecker checker = new OD4DataCoCoChecker();
- checker.addChecker(new ODBasicsCoCos().getCheckerForAllIntraCoCos());
- checker.addChecker(new ODLinkCoCos().getCheckerForAllIntraCoCos());
-
- return checker;
- }
-
- public OD4DataCoCoChecker getCheckerForAllCoCos() {
- final OD4DataCoCoChecker checker = new OD4DataCoCoChecker();
- checker.addChecker(new ODBasicsCoCos().getCheckerForAllCoCos());
- checker.addChecker(new ODLinkCoCos().getCheckerForAllCoCos());
-
- return checker;
- }
-
-}
diff --git a/src/main/java/de/monticore/od4data/_symboltable/OD4DataGlobalScope.java b/src/main/java/de/monticore/od4data/_symboltable/OD4DataGlobalScope.java
deleted file mode 100644
index e5225286..00000000
--- a/src/main/java/de/monticore/od4data/_symboltable/OD4DataGlobalScope.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- (c) https://github.com/MontiCore/monticore
- */
-
-package de.monticore.od4data._symboltable;
-
-import de.monticore.io.paths.MCPath;
-import de.se_rwth.commons.Names;
-
-import java.util.Set;
-
-public class OD4DataGlobalScope extends OD4DataGlobalScopeTOP {
- private OD4DataGlobalScope realThis;
-
- public OD4DataGlobalScope() {
- realThis = this;
- }
-
- public OD4DataGlobalScope(MCPath modelPath, String extension) {
- super(modelPath, extension);
- }
-
- @Override
- public OD4DataGlobalScope getRealThis() {
- return realThis;
- }
-
- public void setRealThis(OD4DataGlobalScope realThis) {
- this.realThis = realThis;
- }
-
- @Override
- public Set calculateModelNamesForOOType(String name) {
- Set result = super.calculateModelNamesForOOType(name);
-
- while (name.contains(".")) {
- name = Names.getQualifier(name);
- result.add(name);
- }
- return result;
- }
-
- @Override
- public Set calculateModelNamesForType(String name) {
- return calculateModelNamesForOOType(name);
- }
-
-}
diff --git a/src/main/java/de/monticore/od4data/_symboltable/OD4DataScopesGenitor.java b/src/main/java/de/monticore/od4data/_symboltable/OD4DataScopesGenitor.java
deleted file mode 100644
index f4be5113..00000000
--- a/src/main/java/de/monticore/od4data/_symboltable/OD4DataScopesGenitor.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/* (c) https://github.com/MontiCore/monticore */
-package de.monticore.od4data._symboltable;
-
-import com.google.common.base.Preconditions;
-import de.monticore.odbasis._ast.ASTODArtifact;
-import de.monticore.odbasis._symboltable.ODBasisScopesGenitor;
-import de.monticore.symboltable.ImportStatement;
-import de.se_rwth.commons.logging.Log;
-
-import java.util.ArrayList;
-
-public class OD4DataScopesGenitor extends OD4DataScopesGenitorTOP {
-
- private ODBasisScopesGenitor odBasisScopesGenitor = new ODBasisScopesGenitor();
-
- public OD4DataScopesGenitor() {
- super();
- }
-
- @Override
- public IOD4DataArtifactScope createFromAST(ASTODArtifact rootNode) {
- Preconditions.checkNotNull(rootNode,
- "0xAE882 Error by creating of the OD4DataScopesGenitor symbol table: top ast node"
- + " is null");
- IOD4DataArtifactScope artifactScope = de.monticore.od4data.OD4DataMill.artifactScope();
- if (rootNode.isPresentMCPackageDeclaration()) {
- artifactScope.setPackageName(
- rootNode.getMCPackageDeclaration().getMCQualifiedName().getQName());
- }
- else {
- artifactScope.setPackageName("");
- }
- artifactScope.setImportsList(new ArrayList<>());
- rootNode.getMCImportStatementList()
- .forEach(i -> artifactScope.addImports(new ImportStatement(i.getQName(), i.isStar())));
- artifactScope.setName(rootNode.getObjectDiagram().getName());
- putOnStack(artifactScope);
- rootNode.accept(getTraverser());
- return artifactScope;
- }
-
-}
diff --git a/src/main/java/de/monticore/od4data/_symboltable/OD4DataScopesGenitorDelegator.java b/src/main/java/de/monticore/od4data/_symboltable/OD4DataScopesGenitorDelegator.java
deleted file mode 100644
index 5de5c4aa..00000000
--- a/src/main/java/de/monticore/od4data/_symboltable/OD4DataScopesGenitorDelegator.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- (c) https://github.com/MontiCore/monticore
- */
-
-package de.monticore.od4data._symboltable;
-
-import de.monticore.odbasis.ODBasisMill;
-import de.monticore.odbasis._symboltable.ODBasisScopesGenitor;
-
-public class OD4DataScopesGenitorDelegator extends OD4DataScopesGenitorDelegatorTOP {
-
- public OD4DataScopesGenitorDelegator() {
- super();
- }
-
- public void setCheckTypes(boolean typeCheck) {
- traverser.getODBasisVisitorList().clear();
- ODBasisScopesGenitor odBasisScopesGenitor = ODBasisMill.scopesGenitor();
- odBasisScopesGenitor.setScopeStack(scopeStack);
- odBasisScopesGenitor.setCheckTypes(typeCheck);
- traverser.add4ODBasis(odBasisScopesGenitor);
- traverser.setODBasisHandler(odBasisScopesGenitor);
- }
-}
diff --git a/src/main/java/de/monticore/od4data/trafo/OD4DataAttributeValueCompositionTrafo.java b/src/main/java/de/monticore/od4data/trafo/OD4DataAttributeValueCompositionTrafo.java
deleted file mode 100644
index f331e1b4..00000000
--- a/src/main/java/de/monticore/od4data/trafo/OD4DataAttributeValueCompositionTrafo.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * (c) https://github.com/MontiCore/monticore
- */
-
-/*
- * (c) https://github.com/MontiCore/monticore
- */
-
-package de.monticore.od4data.trafo;
-
-import de.monticore.od4data.OD4DataMill;
-import de.monticore.od4data._visitor.OD4DataTraverser;
-import de.monticore.odbasis._ast.ASTODArtifact;
-
-public class OD4DataAttributeValueCompositionTrafo {
-
- protected OD4DataTraverser traverser;
-
- public OD4DataAttributeValueCompositionTrafo() {
- this.traverser = OD4DataMill.inheritanceTraverser();
-
- init(traverser);
- }
-
- public static void init(OD4DataTraverser traverser) {
- final OD4DataAttributeValueCompositionTrafoExtension trafo =
- new OD4DataAttributeValueCompositionTrafoExtension();
- traverser.add4ODBasis(trafo);
- traverser.add4ODAttribute(trafo);
- traverser.add4ODLink(trafo);
- }
-
- public OD4DataTraverser getTraverser() {
- return traverser;
- }
-
- public void setTraverser(OD4DataTraverser traverser) {
- this.traverser = traverser;
- }
-
- public void transform(ASTODArtifact diagram) {
- diagram.accept(getTraverser());
- }
-}
diff --git a/src/main/java/de/monticore/od4data/trafo/OD4DataDeAnonymizeObjectsTrafo.java b/src/main/java/de/monticore/od4data/trafo/OD4DataDeAnonymizeObjectsTrafo.java
deleted file mode 100644
index f4f0d761..00000000
--- a/src/main/java/de/monticore/od4data/trafo/OD4DataDeAnonymizeObjectsTrafo.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * (c) https://github.com/MontiCore/monticore
- */
-
-package de.monticore.od4data.trafo;
-
-import de.monticore.od4data.OD4DataMill;
-import de.monticore.od4data._visitor.OD4DataTraverser;
-import de.monticore.odbasis._ast.ASTODArtifact;
-
-public class OD4DataDeAnonymizeObjectsTrafo {
-
- protected OD4DataTraverser traverser;
-
- public OD4DataDeAnonymizeObjectsTrafo() {
- this.traverser = OD4DataMill.inheritanceTraverser();
-
- init(traverser);
- }
-
- public static void init(OD4DataTraverser traverser) {
- final OD4DataDeAnonymizeObjectsTrafoExtension trafo =
- new OD4DataDeAnonymizeObjectsTrafoExtension();
- traverser.add4ODBasis(trafo);
- traverser.add4ODAttribute(trafo);
- }
-
- public OD4DataTraverser getTraverser() {
- return traverser;
- }
-
- public void setTraverser(OD4DataTraverser traverser) {
- this.traverser = traverser;
- }
-
- public void transform(ASTODArtifact diagram) {
- diagram.accept(getTraverser());
- }
-}
diff --git a/src/main/java/de/monticore/od4data/types3/OD4DataTypeCheck3.java b/src/main/java/de/monticore/od4data/types3/OD4DataTypeCheck3.java
deleted file mode 100644
index 43d28c95..00000000
--- a/src/main/java/de/monticore/od4data/types3/OD4DataTypeCheck3.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * (c) https://github.com/MontiCore/monticore
- */
-
-package de.monticore.od4data.types3;
-
-import de.monticore.expressions.commonexpressions.types3.CommonExpressionsCTTIVisitor;
-import de.monticore.expressions.expressionsbasis.types3.ExpressionBasisCTTIVisitor;
-import de.monticore.literals.mccommonliterals.types3.MCCommonLiteralsTypeVisitor;
-import de.monticore.od4data.OD4DataMill;
-import de.monticore.od4data._visitor.OD4DataTraverser;
-import de.monticore.types.mcbasictypes.types3.MCBasicTypesTypeVisitor;
-import de.monticore.types3.SymTypeRelations;
-import de.monticore.types3.Type4Ast;
-import de.monticore.types3.generics.context.InferenceContext4Ast;
-import de.monticore.types3.util.*;
-import de.monticore.visitor.ITraverser;
-import de.se_rwth.commons.logging.Log;
-
-/**
- * TypeCheck3 implementation for the OD4Data language.
- * After calling {@link #init()},
- * this implementation will be available through the TypeCheck3 interface.
- */
-public class OD4DataTypeCheck3 extends MapBasedTypeCheck3 {
-
- public static void init() {
- initTC3Delegate();
- SymTypeRelations.init();
- OOWithinTypeBasicSymbolsResolver.init();
- OOWithinScopeBasicSymbolsResolver.init();
- TypeContextCalculator.init();
- TypeVisitorOperatorCalculator.init();
- TypeVisitorLifting.init();
- }
-
- protected static void initTC3Delegate() {
- Log.trace("init OD4DataTypeCheck3", "TypeCheck setup");
-
- OD4DataTraverser traverser = OD4DataMill.inheritanceTraverser();
- Type4Ast type4Ast = new Type4Ast();
- InferenceContext4Ast ctx4Ast = new InferenceContext4Ast();
-
- // Expressions
-
- CommonExpressionsCTTIVisitor visCommonExpressions = new CommonExpressionsCTTIVisitor();
- visCommonExpressions.setType4Ast(type4Ast);
- visCommonExpressions.setContext4Ast(ctx4Ast);
- traverser.add4CommonExpressions(visCommonExpressions);
- traverser.setCommonExpressionsHandler(visCommonExpressions);
-
- ExpressionBasisCTTIVisitor visExpressionBasis = new ExpressionBasisCTTIVisitor();
- visExpressionBasis.setType4Ast(type4Ast);
- visExpressionBasis.setContext4Ast(ctx4Ast);
- traverser.add4ExpressionsBasis(visExpressionBasis);
- traverser.setExpressionsBasisHandler(visExpressionBasis);
-
- MCCommonLiteralsTypeVisitor visMCCommonLiterals = new MCCommonLiteralsTypeVisitor();
- visMCCommonLiterals.setType4Ast(type4Ast);
- traverser.add4MCCommonLiterals(visMCCommonLiterals);
-
- // MCTypes
-
- MCBasicTypesTypeVisitor visMCBasicTypes = new MCBasicTypesTypeVisitor();
- visMCBasicTypes.setType4Ast(type4Ast);
- traverser.add4MCBasicTypes(visMCBasicTypes);
-
- // create delegate
- OD4DataTypeCheck3 oclTC3 = new OD4DataTypeCheck3(traverser, type4Ast, ctx4Ast);
- oclTC3.setThisAsDelegate();
- }
-
- protected OD4DataTypeCheck3(ITraverser typeTraverser, Type4Ast type4Ast,
- InferenceContext4Ast ctx4Ast) {
- super(typeTraverser, type4Ast, ctx4Ast);
- }
-}
diff --git a/src/main/java/de/monticore/od4development/OD4DevelopmentTool.java b/src/main/java/de/monticore/od4development/OD4DevelopmentTool.java
index 13ecc0f4..cd4271b4 100644
--- a/src/main/java/de/monticore/od4development/OD4DevelopmentTool.java
+++ b/src/main/java/de/monticore/od4development/OD4DevelopmentTool.java
@@ -13,19 +13,25 @@
import de.monticore.od2cd.OD2CDConverter;
import de.monticore.od4development._cocos.OD4DevelopmentCoCoChecker;
import de.monticore.od4development._cocos.OD4DevelopmentCoCos;
+import de.monticore.od4development._prettyprint.OD4DevelopmentFullPrettyPrinter;
import de.monticore.od4development._symboltable.CDRoleSymbolDeSer;
import de.monticore.od4development._symboltable.IOD4DevelopmentArtifactScope;
+import de.monticore.od4development._visitor.OD4DevelopmentTraverser;
import de.monticore.odbasis._ast.ASTODArtifact;
-import de.monticore.odbasis._prettyprint.ODBasisFullPrettyPrinter;
+import de.monticore.odbasis._symboltable.ODBasisSymbolTableCompleter;
import de.monticore.prettyprint.IndentPrinter;
import de.monticore.symbols.basicsymbols.BasicSymbolsMill;
import de.monticore.types.mcbasictypes._ast.ASTMCImportStatement;
import de.se_rwth.commons.logging.Log;
-import org.apache.commons.cli.*;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
@@ -33,168 +39,256 @@
public class OD4DevelopmentTool extends OD4DevelopmentToolTOP {
- protected static final String PARSE_SUCCESSFUL = "Successfully parsed %s\n";
+ protected static final String PARSE_SUCCESSFUL = "Successfully parsed %s";
protected static final String CHECK_SUCCESSFUL =
- "Successfully checked the CoCos for class " + "diagram %s\n";
+ "Successfully checked the CoCos for object diagram %s";
- protected static final String CHECK_ERROR = "Error while parsing or CoCo checking";
+ protected static final String CHECK_ERROR = "0x0D020 Error while processing the object diagram";
- protected static final String STEXPORT_SUCCESSFUL = "Creation of symbol file %s successful\n";
+ protected static final String STEXPORT_SUCCESSFUL = "Creation of symbol file %s successful";
+ protected static final String PRETTYPRINT_SUCCESSFUL = "Pretty printed OD to file %s";
- protected static final String INPUT_FILE_NOT_EXISTENT = "Input file '%s' does not exist\n";
-
- public void run(String[] args) {
- Log.init();
- OD4DevelopmentMill.init();
- Options options = initOptions();
-
- try {
-
- // create CLI parser and parse input options from command line
- CommandLineParser cliParser = new DefaultParser();
- CommandLine cmd = cliParser.parse(options, args);
-
- // help: when --help
- if (cmd.hasOption("h")) {
- printHelp(options);
- // do not continue, when help is printed
- return;
- }
-
- // if -i input is missing: also print help and stop
- if (!cmd.hasOption("i")) {
- printHelp(options);
- // do not continue, when help is printed
- return;
- }
+ protected static final String INPUT_FILE_NOT_EXISTENT = "0x0D015 Input file '%s' does not exist";
+ protected static final String INPUT_OPTION_NOT_PRESENT = "0x0D026 No input file given. Use -i to declare the tool input.";
+ protected static final String OUTPUT_PATH_INVALID =
+ "0x0D016 Output path '%s' is not a valid directory path";
+ protected static final String OUTPUT_OPTION_MISSING_ARG =
+ "0x0D017 Option -o requires an argument specifying the output directory.";
+ protected static final String COCO_OPTION_INVALID =
+ "0x0D018 Invalid argument '%s' for option -c. Allowed values are: intra, inter.";
+ protected static final String COCO_OPTION_TOO_MANY_ARGS =
+ "0x0D019 Option -c accepts at most one argument: intra or inter.";
+ protected static final String PARSE_EXCEPTION_MSG = "0x0D021 Could not process parameters: %s";
+ protected static final String REPORT_OPTION_NOT_SUPPORTED =
+ "0x0D028 Option -r is not supported by the OD4Development tool.";
+ /**
+ * Processes CLI arguments and executes parsing, symbol table creation, CoCo checks,
+ * pretty printing, symbol export and optional OD-to-CD generation.
+ *
+ *
+ *
{@code -h}/{@code --help}: prints the help dialog and exits.
+ *
{@code -v}/{@code --version}: prints version information and exits.
+ *
{@code -i}/{@code --input }: sets the mandatory input OD file to parse.
+ *
{@code -path }: sets one or more symbol path entries for imported symbols.
+ *
{@code -pp}/{@code --prettyprint [file]}: pretty prints the AST to stdout or the optional file.
+ *
{@code -s}/{@code --symboltable [file]}: writes the symbol table to the optional file or a default name.
+ *
{@code -c}/{@code --coco [intra|inter]}: runs all CoCos by default, or only intra/inter CoCos when specified.
+ *
{@code -o}/{@code --output }: generates a class diagram into the given output directory.
+ *
{@code --stacktrace}: prints stack traces for errors.
+ *
{@code -r}/{@code --report}: generated standard option, not supported by this tool.
+ *
+ *
+ *
+ * @param cmd command line
+ */
+ public void doRun(CommandLine cmd) {
+ if (cmd.hasOption("r")) {
+ Log.error(REPORT_OPTION_NOT_SUPPORTED);
+ return;
+ }
- // -option developer logging
- if (cmd.hasOption("d")) {
- Log.initDEBUG();
- } else {
- Log.init();
+ // if -i input is missing: stop
+ if (!cmd.hasOption("i")) {
+ Log.error(INPUT_OPTION_NOT_PRESENT);
+ return;
+ }
+
+ // avoid duplicate console output when pretty print already writes to stdout
+ final boolean doPrintToStdOut = !(cmd.hasOption("pp") && cmd.getOptionValue("pp") == null);
+
+ // parse input file
+ String modelFile = cmd.getOptionValue("i");
+ Path modelFilePath = Paths.get(modelFile);
+ if (!modelFilePath.toFile().exists()) {
+ Log.error(String.format(INPUT_FILE_NOT_EXISTENT, modelFile));
+ return;
+ }
+
+ ASTODArtifact ast = parse(modelFile);
+
+ if (doPrintToStdOut) {
+ Log.info(String.format(PARSE_SUCCESSFUL, ast.getObjectDiagram().getName()),
+ getClass().getName());
+ }
+
+ // initialize primitives
+ BasicSymbolsMill.initializePrimitives();
+
+ // if -path is set: set symbol path and load imported diagrams
+ if (cmd.hasOption("path")) {
+ MCPath mcPath = new MCPath();
+ String[] paths = cmd.getOptionValues("path");
+ if (paths != null) {
+ // support multiple -path entries passed via CLI
+ Arrays.stream(paths).forEach(p -> mcPath.addEntry(Paths.get(p)));
}
+ OD4DevelopmentMill.globalScope().setSymbolPath(mcPath);
+ OD4DevelopmentMill.globalScope()
+ .putTypeSymbolDeSer("de.monticore.cdbasis._symboltable.CDTypeSymbol");
+ OD4DevelopmentMill.globalScope()
+ .putSymbolDeSer("de.monticore.cdassociation._symboltable.CDRoleSymbol",
+ new CDRoleSymbolDeSer());
- // don't output to stdout when the prettyprint is output to stdout
- final boolean doPrintToStdOut = !(cmd.hasOption("pp") && cmd.getOptionValue("pp") == null);
-
- // parse input file
- String modelFile = cmd.getOptionValue("i");
- Path modelFilePath = Paths.get(modelFile);
- if (!modelFilePath.toFile().exists()) {
- System.out.printf(INPUT_FILE_NOT_EXISTENT, modelFile);
- return;
+ for (ASTMCImportStatement i : ast.getMCImportStatementList()) {
+ OD4DevelopmentMill.globalScope().loadDiagram(i.getQName());
}
-
- ASTODArtifact ast = parse(modelFile);
-
+ }
+
+ IOD4DevelopmentArtifactScope as = createSymbolTable(ast);
+
+ boolean checkTypes = cmd.hasOption("s") || cmd.hasOption("o") || (cmd.hasOption("c") && (
+ cmd.getOptionValue("c") == null || cmd.getOptionValue("c").equals("inter")));
+ completeSymbolTable(ast, checkTypes);
+
+ if (cmd.hasOption("s")) {
+ Path symTabPath = storeSymTab(as, modelFilePath, cmd.getOptionValue("s"));
if (doPrintToStdOut) {
- System.out.printf(PARSE_SUCCESSFUL, ast.getObjectDiagram().getName());
+ Log.info(String.format(STEXPORT_SUCCESSFUL, symTabPath.toAbsolutePath()),
+ getClass().getName());
}
-
- if(cmd.hasOption("path")) {
- MCPath mcPath = new MCPath(cmd.getOptionValue("path"));
- OD4DevelopmentMill.globalScope().setSymbolPath(mcPath);
- OD4DevelopmentMill.globalScope().putTypeSymbolDeSer("de.monticore.cdbasis._symboltable.CDTypeSymbol");
- OD4DevelopmentMill.globalScope().putSymbolDeSer("de.monticore.cdassociation._symboltable.CDRoleSymbol", new CDRoleSymbolDeSer());
- BasicSymbolsMill.initializePrimitives();
-
- for (ASTMCImportStatement i : ast.getMCImportStatementList()) {
- OD4DevelopmentMill.globalScope().loadDiagram(i.getQName());
+ }
+
+ // -option check cocos
+ if (cmd.hasOption("c")) {
+ String[] cocoArgs = cmd.getOptionValues("c");
+ if (cocoArgs == null || cocoArgs.length == 0) {
+ runAllCoCos(ast);
+ }
+ else if (cocoArgs.length == 1) {
+ String cocoArg = cocoArgs[0];
+ if ("intra".equals(cocoArg)) {
+ runDefaultCoCos(ast);
+ }
+ else if ("inter".equals(cocoArg)) {
+ runInterCoCos(ast);
+ }
+ else {
+ Log.error(String.format(COCO_OPTION_INVALID, cocoArg));
+ return;
}
}
+ else {
+ Log.error(COCO_OPTION_TOO_MANY_ARGS);
+ return;
+ }
- IOD4DevelopmentArtifactScope as = createSymbolTable(ast);
-
- if (cmd.hasOption("s")) {
- Path symTabPath = storeSymTab(as, modelFilePath, cmd.getOptionValue("s"));
- if (doPrintToStdOut) {
- System.out.printf(STEXPORT_SUCCESSFUL, symTabPath.toAbsolutePath());
+ if (doPrintToStdOut) {
+ if (Log.getErrorCount() == 0) {
+ Log.info(String.format(CHECK_SUCCESSFUL, ast.getObjectDiagram().getName()),
+ getClass().getName());
}
- }
-
- if (cmd.hasOption("c")) {
- runDefaultCoCos(ast);
-
- if (doPrintToStdOut) {
- if (Log.getErrorCount() == 0) {
- System.out.printf(CHECK_SUCCESSFUL, ast.getObjectDiagram().getName());
- }
- else {
- System.out.println(CHECK_ERROR);
- return;
- }
+ else {
+ Log.error(CHECK_ERROR);
+ return;
}
}
-
- // -option pretty print
- if (cmd.hasOption("pp")) {
- String path = cmd.getOptionValue("pp", StringUtils.EMPTY);
- prettyPrint(ast, path);
+ }
+
+ // -option pretty print
+ if (cmd.hasOption("pp")) {
+ String path = cmd.getOptionValue("pp", StringUtils.EMPTY);
+ prettyPrint(ast, path);
+ if (StringUtils.isNotBlank(path)) {
+ Log.info(PRETTYPRINT_SUCCESSFUL.formatted(path), getClass().getName());
}
-
- String outputDir = cmd.hasOption("o")
- ? cmd.getOptionValue("o")
- : "target/gen-test/";
- if(cmd.hasOption("o")) {
- generateCD(ast, outputDir);
+ }
+
+ if (cmd.hasOption("o")) {
+ String outputDirArgument = cmd.getOptionValue("o");
+ if (outputDirArgument == null || outputDirArgument.isBlank()) {
+ Log.error(OUTPUT_OPTION_MISSING_ARG);
+ return;
+ }
+ try {
+ Path outputDirPath = Paths.get(outputDirArgument);
+ // allow non-existing directory paths; reject only existing non-directory targets
+ if (!Files.exists(outputDirPath) || Files.isDirectory(outputDirPath)) {
+ generateCD(ast, outputDirPath);
+ }
+ else {
+ Log.error(String.format(OUTPUT_PATH_INVALID, outputDirArgument));
+ }
+ }
+ catch (InvalidPathException e) {
+ Log.error(String.format(OUTPUT_PATH_INVALID, outputDirArgument));
}
-
- } catch (ParseException e) {
- // an unexpected error from the apache CLI parser:
- Log.error("0xA7105 Could not process parameters: " + e.getMessage());
}
}
-
+
+ /**
+ * Pretty prints the OD artifact either to stdout or to the given target file.
+ *
+ * @param ast parsed OD artifact
+ * @param file target file path; empty means stdout
+ */
@Override
public void prettyPrint(ASTODArtifact ast, String file) {
- ODBasisFullPrettyPrinter printer = new ODBasisFullPrettyPrinter(new IndentPrinter());
+ OD4DevelopmentFullPrettyPrinter printer = new OD4DevelopmentFullPrettyPrinter(new IndentPrinter());
String result = printer.prettyprint(ast);
print(result, file);
}
-
+
+ /**
+ * Runs only intra-model CoCos.
+ *
+ * @param ast parsed OD artifact
+ */
@Override
public void runDefaultCoCos(ASTODArtifact ast) {
+ OD4DevelopmentCoCoChecker checker = new OD4DevelopmentCoCos().getCheckerForAllIntraCoCos();
+ checker.checkAll(ast);
+ }
+
+ /**
+ * Runs all available CoCos (intra- and inter-model checks).
+ *
+ * @param ast parsed OD artifact
+ */
+ public void runAllCoCos(ASTODArtifact ast) {
OD4DevelopmentCoCoChecker checker = new OD4DevelopmentCoCos().getCheckerForAllCoCos();
checker.checkAll(ast);
}
-
- public void generateCD(ASTODArtifact ast, String outputDir) {
+
+ /**
+ * Runs only inter-model CoCos.
+ *
+ * @param ast parsed OD artifact
+ */
+ public void runInterCoCos(ASTODArtifact ast) {
+ OD4DevelopmentCoCoChecker checker = new OD4DevelopmentCoCos().getCheckerForAllInterCoCos();
+ checker.checkAll(ast);
+ }
+
+ /**
+ * Generates a class diagram from the given OD artifact into the provided output directory.
+ *
+ * @param ast parsed OD artifact
+ * @param outputDir target directory for generated files
+ */
+ public void generateCD(ASTODArtifact ast, Path outputDir) {
GeneratorSetup setup = new GeneratorSetup();
GlobalExtensionManagement glex = new GlobalExtensionManagement();
setup.setGlex(glex);
glex.setGlobalValue("cdPrinter", new CdUtilsPrinter());
glex.setGlobalValue("cp", new CompositionPrinter());
-
- if (!outputDir.isEmpty()){
- File targetDir = new File(outputDir);
- setup.setOutputDirectory(targetDir);
- }
-
+
+ File targetDir = outputDir.toFile();
+ setup.setOutputDirectory(targetDir);
+
String configTemplate = "od2cd.OD2CD";
TemplateController tc = setup.getNewTemplateController(configTemplate);
CDGenerator generator = new CDGenerator(setup);
TemplateHookPoint hpp = new TemplateHookPoint(configTemplate);
List