此文档旨在使用对象OCL语言的建模者。使用或扩展OCL语言的语言工程师的详细文档位于此处。我们建议语言工程师在阅读详细文档之前阅读此文档。
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;
}
进一步的表达示例(包括Monticore的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
文本OCL表示主要取决于[Rum16,Rum17]中的定义。 OCL用于检查其他模型的正确性。在这里, Book
和Customer
类型是由类图定义的:
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];
}
本节介绍了OCL语言的命令行工具。该工具提供处理模型时使用的典型功能。为此,它为
OCL工具的构建和使用要求是(至少)JDK 8(JDK 11和JDK 14也得到了我们的正式支持),Git和Gradle已安装并可用于BASH。如果您使用的是Docker,也可以在不安装Java,Git或Gradle的情况下使用Docker容器。
以下小节描述了如何下载工具。然后,本文档描述了如何从源文件构建工具。之后,本文档包含用于使用该工具的教程。
准备使用该工具的版本可以以可执行的JAR文件的形式下载。您可以使用此下载链接下载该工具。
另外,您可以使用wget
下载该工具。以下命令下载了该工具的最新版本,并以您的工作目录中的名称MCOCL.jar
保存:
wget "monticore.de/download/MCOCL.jar" -O MCOCL.jar
可以使用工具的Docker映像的最新版本
docker pull monticore/ocl
如果您使用Docker,请在以下内容中替换java -jar MCOCL.jar
(对于Windows PowerShell,Mac终端或Linux Bash)
docker run --rm -v ${PWD}:/input -w /input monticore/ocl
或(对于Windows命令行)
docker run --rm -v %CD%:/input -w /input monticore/ocl
例如,此教程步骤2的命令
java -jar MCOCL.jar -i Example.ocl -pp
变成
docker run --rm -v ${PWD}:/input -w /input monticore/ocl -i Example.ocl -pp
使用Docker时。
可以从GitHub中的源文件构建一个可执行的工具罐。以下描述了使用bash从源文件构建工具的过程。对于Github中可用源文件的bash的可执行罐子,请执行以下命令。
首先,克隆存储库:
git clone https://github.com/MontiCore/ocl.git
将目录更改为克隆来源的根目录:
cd OCL
然后通过运行构建项目(信息:您需要为此安装Gradle):
gradle build
恭喜!现在,您可以在目录target/libs
(可通过cd target/libs
访问)中找到可执行的JAR文件MCOCL.jar
。
前面的部分描述了如何获得可执行的JAR文件(OCL命令行工具)。本节提供了使用OCL工具的教程。以下示例假设您本地命名为MCOCL
工具。如果您从源构建工具或上面使用了wget
命令,那么您就可以了。如果您手动下载了该工具,则应考虑重命名下载的JAR。
执行JAR文件没有任何选项,打印
到控制台的工具:
$ 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.
为了正常工作,该工具需要强制性参数-i,--input <file>
,该文件将至少一个包含SD模型的输入文件的文件路径。如果未指定其他参数,则该工具仅解析模型。
为了尝试此操作,请将MCOCL.jar
复制到您选择的目录中。之后,创建包含以下简单的OCL:
ocl Example {
}
将文本文件作为Example.ocl
保存在MCOCL.jar
所在的目录中。
现在执行以下命令:
java -jar MCOCL.jar -i Example.ocl
您可能会注意到该工具不会打印到控制台的输出。这意味着该工具已成功地解析了文件Example.ocl
。
该工具为OCL语言提供了相当局限性。可以使用一个相当通用的,例如,修复包含OCL的文件的格式。要执行漂亮的打印机-pp,--prettyprint
选项。使用该选项而没有任何参数,可以很好地打印到控制台输入文件中包含的模型。
执行以下命令尝试此操作:
java -jar MCOCL.jar -i Example.ocl -pp
该命令打印到控制台输入文件中包含的漂亮印刷模型:
ocl Example {
}
可以很好地打印输入文件中包含的模型到输出文件。对于此任务,可以将输出文件的名称作为参数为-pp,--prettyprint
选项。如果提供了输出文件的参数,则输出文件的数量必须等于输入文件的数量。第i-th输入文件非常印刷到第i-thupt ofupt文件中。
执行以下命令尝试此操作:
java -jar MCOCL.jar -i Example.ocl -pp Output.ocl
该命令将输入文件中包含的精美印刷模型打印到文件Output.ocl
中。
对于检查上下文条件,可以使用-c,--coco <arg>
选项。使用此选项无任何参数检查模型是否满足所有上下文条件。
如果您只想检查一个模型是否仅满足上下文条件的子集还是想阐明应检查所有上下文条件,则可以通过提供三个参数intra
, inter
和type
来做到这一点。
intra
仅执行上下文条件,涉及违反模型内部上下文条件的行为。例如,这些上下文条件,例如检查命名约定。inter
执行所有模型内部上下文条件,并检查是否定义了构造函数签名中的类型名称。type
执行所有上下文结合。这些上下文条件包括检查是否存在使用过的类型和方法。使用参数type
时的行为与不使用参数时的默认行为相等。执行以下命令尝试一个简单的示例:
java -jar MCOCL.jar -i Example.ocl -c -cd4c
您可能会注意到该工具在执行此命令时没有打印到控制台。这意味着该模型满足所有上下文条件。
现在让我们考虑一个更复杂的例子。从上面的An Example Model
部分中回顾OCL Bookshop
。要继续,请复制OCL Bookshop
的文本MCOCL.jar
Bookshop.ocl
中。为此,您需要一个包含与Bookshop.ocl
相对应的类图的符号的符号文件。这将在下一节中进行详细说明。目前,只需将-p src/test/resources/docs/Bookshop/ -cd4c
添加到命令中,以便使用该工具在哪里找到为此示例准备的符号文件以及如何处理它。
您可以使用-c,--coco <arg>
选项检查不同种类的上下文条件:
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
这些命令都不应产生输出。
要查看错误,请让模型添加一个错误。在Bookshop.ocl
中替换此行
{ book | Book book in booksInStock, book.iban == iban }
经过
{ book2 | Book book in booksInStock, book.iban == iban }
由于book2
不确定,该工具现在应在检查COCO时打印出错误消息:
$ 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
请记住要撤消“错误”。
在本节中,我们利用符号路径,并为工具提供另一个模型的符号文件(存储的符号表),其中包含必要的类型信息。
在工具MCOCL.jar
所在的目录中创建一个新的目录mytypes
。例如,第一个部分中的Bookshop.ocl
示例需要一个指定其数据类型的类图。您可以在SRC/TEST/RESOSDES/DOCS/BOOKSHOP/BOOKSHOP.CD下找到此类图文件。
要在OCL中使用它,您首先需要将其转换为一个符号文件。类图的符号文件Bookshop.sym
提供了所有必要的类型信息,以在OCL中使用其类型。如果您此时不想参与CD工具,则还可以在SRC/TEST/Resources/doc/docs/bookshop/bookshop.sym下找到现成的文件。只需将其复制到您的mytypes
文件夹中即可。否则,要将类图转换为符号文件,您需要使用CD4Analiss项目中的MCCD.jar
,并使用以下命令转换类图文件:
java -jar MCCD.jar -d false --fieldfromrole navigable -i src/test/resources/docs/Bookshop/Bookshop.cd -s mytypes/Bookshop.sym
作为语言用户,符号文件的内容对您而言至关重要。如果您很好奇并且会查看符号文件:符号文件包含模型中定义的符号的JSON表示。在这种情况下,符号文件包含有关定义类型的信息。通常,Monticore语言的工具会自动生成这些文件的内容,而作为语言用户,您不必关心其内容。
包含包含符号文件的目录结构的路径称为“符号路径”。如果我们提供工具的符号路径,它将在符号文件中搜索符号,这些符号存储在符号路径中的目录中。因此,如果我们希望该工具找到我们的符号文件,则必须通过--path <directory>
选项提供该工具的模型路径。您可以使用刚创建的mytypes
文件夹尝试一下:
java -jar MCOCL.jar -i Bookshop.ocl --path <SYMBOLPATH> -c type -cd4c
其中<SYMBOLPATH>
是存储下载的符号文件的路径。在我们的示例中,如果您将模型存储在目录mytypes
中,请执行以下命令:
java -jar MCOCL.jar -i Bookshop.ocl --path mytypes -c type -cd4c
请注意,此命令还使用-cd4c
标志。要解释提供给OCL工具的Symbolfiles,它需要了解如何解释CD工具存储的符号。 -cd4c
标志是用于CD4Code的简写。您也可以使用--typeSymbol
, --functionSymbol
和--variableSymbol
标志手动进行操作,然后是符号类型,应将其解释为TypeSymbol
, FunctionSymbol
和VariableSymbol
:
java -jar MCOCL.jar -i Bookshop.ocl --path mytypes -c type --typeSymbol <TYPE_SYMBOL_KINDS> --variableSymbol <VAR_SYMBOL_KINDS> --functionSymbol <FUNC_SYMBOL_KINDS>
其中<TYPE_SYMBOL_KINDS>
, <VAR_SYMBOL_KINDS>
和<FUNC_SYMBOL_KINDS>
是符号的完全合格名称。如果您想提供多种符号类型,只需将它们添加到一个空间分开即可。在我们的示例中,宣布CD4分析的符号看起来像这样:
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
请注意,该工具现在在无法解释的符号上发出许多警告。在OCL中,并非每个不同语言的符号都可能很有趣。为了抑制这些意外的警告,您可以使用--ignoreSymKind <SYM_KINDS_TO_IGNORE>
optain>“ option”来告诉您不想收到哪种符号类型的OCL工具。在我们的示例中,这看起来像这样:
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
对于日常使用,这有点复杂。因此请记住, -cd4c
标志可以将其简化为
java -jar MCOCL.jar -i Bookshop.ocl --path mytypes -c type -cd4c
上一节描述了如何从现有符号文件中加载符号。现在,我们将使用该工具为Bookshop.ocl
型号存储一个符号文件。存储的符号文件将包含有关OCL文件中定义的对象的信息。其他模型可以将其导入使用这些对象定义引入的符号,类似于我们更改文件Bookshop.ocl
的方式,用于导入符号文件Bookshop.sym
中包含的符号。
使用-s,-symboltable <file>
选项构建输入模型的符号表,并将它们存储在给出的文件路径中。要么不提供任何文件路径,要么必须为每个输入模型提供一个文件路径。第i-th输入模型的符号文件存储在第i-th文件路径定义的文件中。如果您不提供任何文件路径,则该工具将每个输入模型的符号表存储在“符号文件” target/symbols/{packageName}/{fileName}.oclsym
中,其中packageName
是包含文件中指定的包装的名称模型和fileName
是包含模型的文件的名称。该文件是相对于工作目录的存储,即,您执行存储符号文件的命令的目录。此外,请注意,为了正确存储符号,必须在所有方面都对模型进行良好的形式,因此,请事先检查所有上下文条件。
对于存储Bookshop.ocl
的符号文件,请执行以下命令(隐式上下文条件检查需要使用符号路径选项):
java -jar MCOCL.jar -i Bookshop.ocl --path mytypes -cd4c -s
该工具生成文件target/symbols/docs/Bookshop.oclsym
,现在可以通过其他模型导入的模型,这些模型需要使用OCL文件Bookshop
中定义的某些对象。
例如,在文件syms/Bookshop.oclsym
中存储Bookshop.ocl
的符号文件,例如,执行以下命令(再次,隐式上下文条件检查需要使用符号路径选项):
java -jar MCOCL.jar -i Bookshop.ocl -path mytypes -cd4c -s syms/Bookshop.oclsym
恭喜,您刚刚完成了有关保存SD符号文件的教程!