This documentation is intended for modelers who use the object OCL languages. A detailed documentation for language engineers using or extending the OCL language is located here. We recommend that language engineers read this documentation before reading the detailed documentation.
ocl Bookshop {
context Shop s inv CustomerPaysBeforeNewOrder: // invariant
forall Customer c in s.customers: // quantifiers available
c.allowedToOrder implies !exists Invoice i in s.invoices:
i.buyer == c && i.moneyPayed < i.invoiceAmount ;
// Method specification for selling a book
context Invoice Stock.sellBook(String iban, int discountPercent, Customer c)
let availableBooks = // set comprehension
{ book | Book book in booksInStock, book.iban == iban }
pre: !availableBooks.isEmpty && // precondition
c.allowedToOrder;
post: let discount = (100 - discountPercent)/100; // postcondition, let
b = result.soldBook // result variable
in
!(b isin booksInStock) &&
booksInStock.size@pre == booksInStock.size + 1 && // @pre
result.invoiceAmount == b.price * discount;
}
Further expression examples (including MontiCore's CommonExpressions):
a + 3*4; // number expressions
a >= b; a < 3; a == "myName"; // equalities
b implies (c && a) || d; // boolean expressions
forall a in S: foo(a) > 3; // quantifiers
exists a in S: foo(a) > 3;
a ?== b; c ?<= d // elvis operators (dealing with optionals)
S.first; S.size; S.addAll(T); // 30 operators for Lists
a in S; S.add(a); // + more for Sets
max(S) > 3; // + more for numbers
The textual OCL representation mostly relies on the definition in [Rum16,
Rum17].
OCL is used to check the correctness of other models.
Here, the Book
and Customer
types are, for example, defined by a
class diagram:
classdiagram Bookshop {
class Book {
String name;
String iban;
double cost;
double price;
}
class Shop;
association [1] Shop -> (invoices) Invoice [*];
association [1] Shop -> (customers) Customer [*];
class Stock {
void addBook(Book b);
Invoice sellBook(Book bookToSell, int discountPercent, Customer buyer);
}
association [1] Stock -> (booksInStock) Book [*];
class Customer {
String name;
String phoneNumber;
int customerNumber;
boolean allowedToOrder;
void payInvoice(double moneyWired, Invoice invoice);
}
class Invoice {
int invoiceNumber;
double invoiceAmount;
double moneyPayed;
}
association [1] Invoice <-> (buyer) Customer [1];
association [1] Invoice <-> (soldBook) Book [1];
}
This section describes the command line tool of the OCL language. The tool provides typical functionality used when processing models. To this effect, it provides funcionality for
- parsing,
- coco-checking,
- pretty-printing,
- creating symbol tables,
- storing symbols in symbol files, and
- loading symbols from symbol files.
The requirements for building and using the OCL tool are that (at least) JDK 8 (JDK 11 and JDK 14 are also officially supported by us), Git, and Gradle are installed and available for use in Bash. If you're using Docker, you can also use the Docker container without installing Java, Git, or Gradle.
The following subsection describes how to download the tool. Then, this document describes how to build the tool from the source files. Afterwards, this document contains a tutorial for using the tool.
A ready to use version of the tool can be downloaded in the form of an executable JAR file. You can use this download link for downloading the tool.
Alternatively, you can download the tool using wget
.
The following command downloads the latest version of the tool and saves it
under the name MCOCL.jar
in your working directory:
wget "monticore.de/download/MCOCL.jar" -O MCOCL.jar
The latest version of the tools's Docker image can be obtained using
docker pull monticore/ocl
In case you're using Docker, replace java -jar MCOCL.jar
in the following
by (for Windows PowerShell, Mac Terminal, or Linux Bash)
docker run --rm -v ${PWD}:/input -w /input monticore/ocl
or (for Windows Command Line)
docker run --rm -v %CD%:/input -w /input monticore/ocl
For example, this command from Step 2 of this tutorial
java -jar MCOCL.jar -i Example.ocl -pp
becomes
docker run --rm -v ${PWD}:/input -w /input monticore/ocl -i Example.ocl -pp
when using Docker.
It is possible to build an executable JAR of the tool from the source files located in GitHub. The following describes the process for building the tool from the source files using Bash. For building an executable Jar with Bash from the source files available in GitHub, execute the following commands.
First, clone the repository:
git clone https://github.com/MontiCore/ocl.git
Change the directory to the root directory of the cloned sources:
cd OCL
Then build the project by running (Info: you need to have Gradle installed for this):
gradle build
Congratulations! You can now find the executable JAR file MCOCL.jar
in
the directory target/libs
(accessible via cd target/libs
).
The previous sections describe how to obtain an executable JAR file
(OCL command line tool). This section provides a tutorial for
using the OCL tool. The following examples assume
that you locally named the tool MCOCL
.
If you build the tool from the sources or used the wget
command above, then you are fine. If you manually downloaded
the tool, then you should consider renaming the downloaded JAR.
Executing the Jar file without any options prints usage information of the
tool to the console:
$ java -jar MCOCL.jar
usage: OCLTool
-c,--coco <arg> Checks the CoCos for the input. Optional
arguments are:
-c intra to check only the intra-model CoCos,
-c inter checks also inter-model CoCos,
-c type (default) checks all CoCos.
-cd4c,--cd4code Load symbol kinds from CD4C. Shortcut for loading
CDTypeSymbol as TypeSymbol,
CDMethodSignatureSymbol as FunctionSymbol, and
FieldSymbol as VariableSymbol. Furthermore,
warnings about not deserializing
CDAssociationSymbol and CDRoleSymbol will be
ignored.
-d,--dev Specifies whether developer level logging should
be used (default is false)
-fs,--functionSymbol <fqns> Takes the fully qualified name of one or more
symbol kind(s) that should be treated as
FunctionSymbol when deserializing symbol files.
Multiple symbol kinds should be separated by
spaces.
-h,--help Prints this help dialog
-i,--input <files> Processes the list of OCL input artifacts.
Argument list is space separated. CoCos are not
checked automatically (see -c).
-is,--ignoreSymKind <fqns> Takes the fully qualified name of one or more
symbol kind(s) for which no warnings about not
being able to deserialize them shall be printed.
Allows cleaner outputs. Multiple symbol kinds
should be separated by spaces.
-p,--path <directory> Sets the artifact path for imported symbols.
Directory will be searched recursively for files
with the ending ".*sym" (for example ".cdsym" or
".sym"). Defaults to the current folder.
-pp,--prettyprint <files> Prints the OCL model to stdout or the specified
file(s) (optional). Multiple files should be
separated by spaces and will be used in the same
order in which the input files (-i option) are
provided.
-s,--symboltable <files> Stores the symbol tables of the input OCL
artifacts in the specified files. For each input
OCL artifact (-i option) please provide one
output symbol file (using same order in which the
input artifacts are provided) to store its
symbols in. For example, -i x.ocl y.ocl -s
a.oclsym b.oclsym will store the symbols of x.ocl
to a.oclsym and the symbols of y.ocl to b.oclsym.
Arguments are separated by spaces. If no
arguments are given, output is stored to
'target/symbols/{packageName}/{artifactName}.ocls
ym'.
-ts,--typeSymbol <fqns> Takes the fully qualified name of one or more
symbol kind(s) that should be treated as
TypeSymbol when deserializing symbol files.
Multiple symbol kinds should be separated by
spaces.
-vs,--variableSymbol <fqns> Takes the fully qualified name of one or more
symbol kind(s) that should be treated as
VariableSymbol when deserializing symbol files.
Multiple symbol kinds should be separated by
spaces.
To work properly, the tool needs the mandatory argument -i,--input <file>
,
which takes the file paths of at least one input file containing SD models.
If no other arguments are specified, the tool solely parses the model(s).
For trying this out, copy the MCOCL.jar
into a directory of your
choice.
Afterwards, create containing the following simple OCL :
ocl Example {
}
Save the text file as Example.ocl
in the directory where MCOCL.jar
is
located.
Now execute the following command:
java -jar MCOCL.jar -i Example.ocl
You may notice that the tool prints no output to the console.
This means that the tool has parsed the file Example.ocl
successfully.
The tool provides a pretty-printer for the OCL language.
A pretty-printer can be used, e.g., to fix the formatting of files containing
OCL.
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.
Execute the following command for trying this out:
java -jar MCOCL.jar -i Example.ocl -pp
The command prints the pretty-printed model contained in the input file to the console:
ocl Example {
}
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.
Execute the following command for trying this out:
java -jar MCOCL.jar -i Example.ocl -pp Output.ocl
The command prints the pretty-printed model contained in the input file into the
file Output.ocl
.
For checking context conditions, the -c,--coco <arg>
option can be used.
Using this option without any arguments checks whether the model satisfies all
context conditions.
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
, inter
, and type
.
- 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
inter
executes all intra-model context conditions and additionally checks whether type names in constructor signatures are defined. - Using the argument
type
executes all context coniditions. These context conditions include checking whether used types and methods exist. The behavior when using the argumenttype
is the equal to the default behavior when using no arguments.
Execute the following command for trying out a simple example:
java -jar MCOCL.jar -i Example.ocl -c -cd4c
You may notice that the tool prints nothing to the console when executing this command. This means that the model satisfies all context condtions.
Let us now consider a more complex example.
Recall the OCL Bookshop
from the An Example Model
section above.
For continuing, copy the textual representation of the OCL Bookshop
and
save it in a file Bookshop.ocl
in the directory where the file MCOCL.jar
is located.
For this you will need a symbol file containing the symbols of a class diagram
corresponding to the Bookshop.ocl
.
This will be explained in more detail in the following section.
For now, just add -p src/test/resources/docs/Bookshop/ -cd4c
to the command to use tell
the tool where to find the symbol file prepared for this example and how to
process it.
You can check the different kinds of context conditions, using the
-c,--coco <arg>
option:
java -jar MCOCL.jar -i Bookshop.ocl -p src/test/resources/docs/Bookshop/ -cd4c -c intra
java -jar MCOCL.jar -i Bookshop.ocl -p src/test/resources/docs/Bookshop/ -cd4c -c inter
java -jar MCOCL.jar -i Bookshop.ocl -p src/test/resources/docs/Bookshop/ -cd4c -c type
None of these commands should produce output.
To see an error lets add a mistake to the model.
Replace this line in Bookshop.ocl
{ book | Book book in booksInStock, book.iban == iban }
by
{ book2 | Book book in booksInStock, book.iban == iban }
As book2
is undefined, the tool should now print an Error message when
checking the cocos:
$ java -jar MCOCL.jar -i Bookshop.ocl -p src/test/resources/docs/Bookshop/ -cd4c -c
[INFO] DeriveSymTypeOfExpression package suspected
[ERROR] 0xA0309 Bookshop.ocl:<13,12> Could not calculate type of expression "book2" on the left side of SetComprehension
Please remember to undo the "mistake".
In this section we make use of the symbol path and provide the tool with a symbol file (stored symbol table) of another model, which contains the necessary type information.
Create a new directory mytypes
in the directory where the tool
MCOCL.jar
is located.
For example, the Bookshop.ocl
example from the first section required a
class diagram that specified its datatypes.
You can find this class diagram file under
src/test/resources/docs/Bookshop/Bookshop.cd.
To use it in OCL, you first need to convert it info a symbol file.
The symbol file Bookshop.sym
of the class diagram provides all necessary type
information to use its types in OCL.
If you don't want to get involved with the CD tool at this point, you can also find the
ready-to-use file under
src/test/resources/docs/Bookshop/Bookshop.sym.
Just copy it into your mytypes
folder.
Otherwise, to convert the class diagram into a symbol file you need to use the
MCCD.jar
from the
CD4Analysis Project and convert the class diagram file using the following command:
java -jar MCCD.jar -d false --fieldfromrole navigable -i src/test/resources/docs/Bookshop/Bookshop.cd -s mytypes/Bookshop.sym
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 defined types. 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.
The path containing the directory structure that contains the symbol file is
called the "Symbol Path".
If we provide the symbol path to the tool, it will search for symbols in symbol
files, which are stored in directories contained in the symbol 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 <directory>
option.
You can try that out using the mytypes
folder you just created:
java -jar MCOCL.jar -i Bookshop.ocl --path <SYMBOLPATH> -c type -cd4c
where <SYMBOLPATH>
is the path where you stored the downloaded symbol file.
In our example, in case you stored the model in the directory mytypes
,
execute the following command:
java -jar MCOCL.jar -i Bookshop.ocl --path mytypes -c type -cd4c
Notice that this command also uses the -cd4c
flag.
To interpret the symbolfiles provided to the OCL tool, it
needs to understand how to interpret the symbols stored by the
CD tool.
The -cd4c
flag is a shorthand for doing this for CD4Code.
You can also do it manually by using the --typeSymbol
,
--functionSymbol
, and --variableSymbol
flags followed by
the symbol kinds that should be interpreted as TypeSymbol
,
FunctionSymbol
and VariableSymbol
:
java -jar MCOCL.jar -i Bookshop.ocl --path mytypes -c type --typeSymbol <TYPE_SYMBOL_KINDS> --variableSymbol <VAR_SYMBOL_KINDS> --functionSymbol <FUNC_SYMBOL_KINDS>
where <TYPE_SYMBOL_KINDS>
, <VAR_SYMBOL_KINDS>
, and
<FUNC_SYMBOL_KINDS>
are the fully qualified names of the symbols.
In case you want to provide multiple symbol types, just add them
separated by a space.
In our example, declaring the symbols from CD4Analysis
would look like this:
java -jar MCOCL.jar -i Bookshop.ocl --path mytypes -c type --typeSymbol de.monticore.cdbasis._symboltable.CDTypeSymbol --variableSymbol de.monticore.symbols.oosymbols._symboltable.FieldSymbol --functionSymbol de.monticore.cd4codebasis._symboltable.CDMethodSignatureSymbol
Notice that the tool now produces a lot of warnings on symbols
that could not be interpreted.
Not every symbol of a differnt language might be interesting in
OCL.
To suppress these unintended warnings, you can tell the OCL tool
for which symbol kinds you do not want to receive them using the
--ignoreSymKind <SYM_KINDS_TO_IGNORE>
option.
In our example, this would look like this:
java -jar MCOCL.jar -i Bookshop.ocl --path mytypes -c type --typeSymbol de.monticore.cdbasis._symboltable.CDTypeSymbol --variableSymbol de.monticore.symbols.oosymbols._symboltable.FieldSymbol --functionSymbol de.monticore.cd4codebasis._symboltable.CDMethodSignatureSymbol --ignoreSymKind de.monticore.cdassociation._symboltable.CDAssociationSymbol de.monticore.cdassociation._symboltable.CDRoleSymbol
For everyday use, this is a little complicated.
So remember that the -cd4c
flag can reduce this to only
java -jar MCOCL.jar -i Bookshop.ocl --path mytypes -c type -cd4c
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 Bookshop.ocl
model.
The stored symbol file will contain information about the objects defined in the
OCL file.
It can be imported by other models for using the symbols introduced by these
object definitions, similar to how we changed the file Bookshop.ocl
for
importing the symbols contained in the symbol file Bookshop.sym
.
Using the -s,-symboltable <file>
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}.oclsym
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 Bookshop.ocl
, execute the following command
(the implicit context condition checks require using the symbol path option):
java -jar MCOCL.jar -i Bookshop.ocl --path mytypes -cd4c -s
The tool produces the file target/symbols/docs/Bookshop.oclsym
, which
can now be imported by other models, e.g., by models that need to use some
of the objects defined in the OCL file Bookshop
.
For storing the symbol file of Bookshop.ocl
in the file
syms/Bookshop.oclsym
, for example, execute the following command
(again, the implicit context condition checks require using the symbol path
option):
java -jar MCOCL.jar -i Bookshop.ocl -path mytypes -cd4c -s syms/Bookshop.oclsym
Congratulations, you have just finished the tutorial about saving SD symbol files!