metanorma / metanorma-plugin-lutaml

Metanorma plugin: access LutaML objects from within a Metanorma document
BSD 2-Clause "Simplified" License
1 stars 1 forks source link

= Metanorma LutaML plugin (metanorma-plugin-lutaml)

image:https://github.com/metanorma/metanorma-plugin-lutaml/workflows/rake/badge.svg["Build Status", link="https://github.com/metanorma/metanorma-plugin-lutaml/actions?workflow=rake"]

== Purpose

LutaML is a data model accessor that supports various data model formats, including:

This plugin allows you to access LutaML models from within a Metanorma document.

== Installation

[source,console]

$ gem install metanorma-plugin-lutaml

== Usage with EXPRESS

=== General

LutaML supports accessing EXPRESS models via the https://github.com/lutaml/expressir[Expressir] parser.

=== Usage of the lutaml command

Given an example.exp EXPRESS file with content:

[source,exp]

SCHEMA test_schema 'test';

( Need select elements for measure_value ) REFERENCE FROM measure_schema (measure_value);

TYPE my_type1 = EXTENSIBLE SELECT; END_TYPE;

TYPE my_type2 = EXTENSIBLE ENUMERATION; END_TYPE;

TYPE my_type3 = EXTENSIBLE ENUMERATION; END_TYPE;

TYPE my_type4 = EXTENSIBLE ENUMERATION; END_TYPE;

TYPE my_type5 = EXTENSIBLE ENUMERATION; END_TYPE; END_SCHEMA;

And the lutaml block:

[source,adoc]

[lutaml,example.exp,my_context]

{% for schema in my_context.schemas %} == {{schema.id}}

{% for entity in schema.entities %} === {{entity.id}} {% endfor %}

{% endfor %}


Where:

** The context object is a serialized Expressir::Model::Repository object with all variable names available. See https://github.com/lutaml/expressir[Expressir] docs for reference. {my_context} has schemas method to access Expressir https://github.com/lutaml/expressir/blob/master/lib/expressir/model/schema.rb[schemas]

Will produce this output:


== test_schema

=== my_type1 === my_type2 === my_type3 === my_type4 === my_type5


This command also supports .lutaml files.

Instead of using the direct path to the file one can use lutaml-express-index document attribute to supply directory with express files or YAML index file to parse as well as the cache file location.

The syntax is as follows:

[source,adoc]

:lutaml-express-index: my_custom_name; dir_or_index_path[; cache=cache_path]

Where:

Example of usage:

[source,adoc]

= Document title Author :lutaml-express-index: index_name; /path/to/express_files; cache=/path/to/cache_file.yaml

[lutaml,index_name,context]

{% for schema in context.schemas %} == {{schema.id}} {% endfor %}


=== Using config.yaml

This functionality allows [lutaml_express] blocks to load a full set of EXPRESS schemas in one index, and then provide a select ("filter") option per-block via a separate YAML file.

[source,adoc]

:lutaml-express-index: all_schemas; ../schemas_all.yaml;

[lutaml_express,all_schemas,context,leveloffset=+1,config_yaml=schemas.yaml]

{% assign selected = context.schemas | where: "selected" %} {% render "templates/resources/schema" for selected as schema %}


Where schemas_all.yml provides all schemas:

[source,yaml]


schemas: action_schema: path: "../../schemas/resources/action_schema/action_schema.exp" application_context_schema: path: "../../schemas/resources/application_context_schema/application_context_schema.exp" approval_schema: path: "../../schemas/resources/approval_schema/approval_schema.exp" ...

And schemas.yaml only selects 2 schemas:

[source,yaml]


schemas: action_schema: anything: ... application_context_schema: anything: ...

The resulting block adds the select attribute to every schema of the the "context" object, which allows you to filter those out for complex operations via Liquid:

[source,liquid]

[lutaml_express,schemas_1,repo,leveloffset=+1,config_yaml=select.yaml]

{% assign selected = repo.schemas | where: "selected" %} ... do things with selected ...

NOTE: This functionality is used in the ISO 10303 SRL to load the full schema set at once but only render the selected schemas in individual documents.

== Usage with UML

=== Rendering a LutaML view: lutaml_diagram

This command allows to quickly render a LutaML view as an image file.

Given a file example.lutaml file with content:

[source,java]

diagram MyView { title "my diagram"

enum AddressClassProfile { imlicistAttributeProfile: CharacterString [0..1] { definition this is multiline with asciidoc end definition } }

class AttributeProfile { +addressClassProfile: CharacterString [0..1] imlicistAttributeProfile: CharacterString [0..1] { definition this is attribute definition } } }

The lutaml_diagram command will add the image to the document.

[source,adoc]

lutaml_diagram::example.lutaml[]

The lutaml_diagram command can also be used to denote a block with an embedded LutaML view.

For example:

[source,java]

[lutaml_diagram] .... diagram MyView { title "my diagram"

enum AddressClassProfile { imlicistAttributeProfile: CharacterString [0..1] { definition { This is multiline AsciiDoc content. } } }

class AttributeProfile { +addressClassProfile: CharacterString [0..1] imlicistAttributeProfile: CharacterString [0..1] { definition this is attribute definition } } } ....

=== Rendering a LutaML Enterprise Architect diagram from XMI: lutaml_ea_diagram

This command allows to quickly render a LutaML diagram as an image file by specifying the name of diagram.

[source,adoc]

lutaml_ea_diagram::[name="name_of_diagram",base_path="/path/to/xmi-images",format="png"]

The code will search the diagram with name name_of_diagram and then render it as:

[source,adoc]

[[figure-{{ diagram.xmi_id }}]] .{{ diagram.name }} image::{{ image_base_path }}/{{ diagram.xmi_id }}.{{ format | default: 'png' }}[]

=== Rendering a LutaML GML Dictionary: lutaml_gml_dictionary

This command allows to render a LutaML GML Dictionary by using Liquid Drop.

GmlDictionaryDrop has the following attributes:

Each dictionary_entry has the following attributes:

[source,adoc]

lutaml_gml_dictionary::/path/to/dictionary.xml[template="/path/to/template.liquid",context=dict]

The command accepts the options listed below:

[source,adoc]

[cols="3a,22a"] |=== | Name | {{ dict.file_name }}

h| Code h| Description {% for entry in dict.dictionary_entry %} | {{ entry.name }} | {{ entry.description }} {% endfor %} |===

[.source] <>

In spite of specifying the path of the template, you can also define an inline template within a block by [lutaml_gml_dictionary,"/path/to/dictionary.xml",context=dict].

[source,adoc]

[lutaml_gml_dictionary,"/path/to/dictionary.xml",context=dict]

{% capture link %}https://www.test.com/{{ dict.file_name }}{% endcapture %}

[cols="3a,22a"] |=== | File Name | {{ dict.file_name }} h| URL | {{ link }} h| Help | Description {% for entry in dict.dictionary_entry %} | {{ entry.name }} | {{ entry.description }} {% endfor %} |===

[.source] <>


=== Rendering a LutaML table of a class: lutaml_klass_table

This command allows to render a LutaML table of a class by using Liquid Drop.

The table will show:

[source,adoc]

lutaml_klass_table::/path/to/example.xmi[name="NameOfClass",template="/path/to/templates/_my_klass_table.liquid"]

The command accepts the options listed below:

=== Generating UML class and attributes: lutaml_uml_class

This command allows rendering a definition clause for a UML class.

Given example.lutaml with this content:

[source,java]

class Register { definition { A register of information. }

identifier: String[1] { definition { Unique identifier of the register. } }

concepts: Concept[0..*] { definition { Concepts. } } }

The command:

[source,adoc]

[lutaml_uml_class,views/Register_Register.lutaml,Register]

Will produce this output:


== Register

A register of information.

=== Attributes

==== identifier

Unique identifier of the register.

.Specification of Register.identifier |=== h|Value type and multiplicity | String [1] |===

==== concepts

Concepts.

.Specification of Register.concepts |=== h|Value type and multiplicity | Concepts [0..*] |===


The command accepts two options:

=== lutaml_uml_attributes_table

This command allows rendering definition tables for a UML model.

Given example.lutaml file with the content:

[source,java]

diagram MyView { title "my diagram"

enum AddressClassProfile { imlicistAttributeProfile: CharacterString [0..1] { definition this is multiline with ascidoc end definition } }

class AttributeProfile { +addressClassProfile: CharacterString [0..1] imlicistAttributeProfile: CharacterString [0..1] { definition this is attribute definition } } }

And the lutaml_uml_attributes_table macro:

[source,adoc]

[lutaml_uml_attributes_table, example.lutaml, AttributeProfile]

Will produce this output:


=== AttributeProfile

.AttributeProfile attributes |=== |Name |Definition |Mandatory/ Optional/ Conditional |Max Occur |Data Type

|addressClassProfile |TODO: enum's definition |M |1 | CharacterString

|imlicistAttributeProfile |this is attribute definition with multiply lines |M |1 | CharacterString

|===


In case of "enumeration" (AddressClassProfile) entity:

[source,adoc]

[lutaml_uml_attributes_table, example.lutaml, AddressClassProfile]

Will produce this output:


=== AddressClassProfile

.AddressClassProfile values |=== |Name |Definition

|imlicistAttributeProfile |this is multiline with asciidoc

|===


=== Usage of lutaml_uml_datamodel_description macro

This command allows to quickly render data model packages and its dependent objects for supplied XMI file.

Given an Enterprise Architect example.xmi file with 2 packages:

The lutaml_uml_datamodel_description macro can be used:

[source,adoc]

[lutaml_uml_datamodel_description, path/to/example.xmi]

[.before] .... my text ....

[.diagram_include_block, base_path="requirements/", format="emf"] .... Diagram text ....

[.include_block, package="Another", base_path="spec/fixtures"] .... my text ....

[.include_block, base_path="spec/fixtures"] .... my text ....

[.before, package="Another"] .... text before Another package ....

[.after, package="Another"] .... text after Another package ....

[.after, package="CityGML"] .... text after CityGML package ....

[.after] .... footer text ....

--

Where:

{% if diagram.definition %} {{ diagram.definition | html2adoc }} {% endif %} {% endfor %}

For instance, the script will take package diagrams supplied in the XMI file and will try to include image with the name equal to diagram' xmi_id attribute plus .png. Also one can add any text to the macro text, it will be added as paragraph before each image include.

NOTE: .after, .before, package_text and include_block macroses all can be used with additional option - liquid, if this option is supplied then the code inside block will be interpolated in liquid context

There are two other commands that are used to refer to LutaML generated document elements:

The syntax is as follows:

[source,adoc]

// For lutaml_figure This is lutaml_figure::[package="Wrapper root package", name="Fig B1 Full model"] figure

// For lutaml_table This is lutaml_table::[package="Wrapper root package"] package This is lutaml_table::[package="Wrapper root package", class="my name"] class This is lutaml_table::[package="Wrapper root package", enum="my name"] enumeration This is lutaml_table::[package="Wrapper root package", data_type="my name"] data type

This code will be transformed into <<figure-{diagram.xmi_id}>> and will point to diagram figure. One can only use this macro when document rendered lutaml_uml_datamodel_description macro as it needs diagram lookup table in order to reference package diagram.

Will produce this output:

[source,adoc]

my text == CityGML package === CityGML overview

Diagram text

[[figure-EAID_ACBB5EE3_3428_40f5_9C7C_E41923419F29]] .CityGML Package Diagram image::requirements/EAID_ACBB5EE3_3428_40f5_9C7C_E41923419F29.png[]

BuildingFurnitureFunctionValue is a code list that enumerates the different purposes of a BuildingFurniture.

[[figure-EAID_938AE961_1C57_4052_B964_997D1894A58D]] .Use of ISO and OASIS standards in CityGML image::requirements/EAID_938AE961_1C57_4052_B964_997D1894A58D.png[]

The CityGML package is organized into 2 packages with 1 modules:

. Another package . CityTML package

my text

Content for CityGML package

==== Defining tables

.<> -- Elements of “Another::AbstractAtomicTimeseries” (class)

[[section-EAPK_9C96A88B_E98B_490b_8A9C_24AEDAC64293]] .Elements of “Another::AbstractAtomicTimeseries” (class) [width="100%",cols="a,a,a,a,a,a,a,a"] === h Name: 7+ AbstractAtomicTimeseries h Definition: 7+ h Stereotype: 7+ interface h Abstract: 7+ h Associations: 7+ (none) .4+h Public attributes: Name 2+ Definition Derived Obligation Maximum occurrence Data type adeOfAbstractAtomicTimeseries 2+
C
*
ADEOfAbstractAtomicTimeseries
observationProperty
2+
M
1
CharacterString
uom
2+
C
1
CharacterString
h Constraints: 7+ (none)
===

=== Additional Information

text after CityGML package

In addition to the XMI file, this macro also supports a YAML configuration file that specifies:

The format for using the YAML configuration file:

[source,yaml]


packages:

includes these packages

Where:

** entity_list

** data_dictionary; or

** default

Usage with macro:

[source,adoc]

[lutaml_uml_datamodel_description, path/to/example.xmi, path/to/config.yml]

[.diagram_include_block, base_path="models/Images", format="png"] ... ...

--

The processor will read the supplied YAML config file (path/to/config.yml), and iterate through packages according to the order supplied in the file. All packages that matches skip in the YAML config file will be skipped during render.

=== Usage of lutaml_ea_xmi macro

This command is a replacement for lutaml_uml_datamodel_description to perform the same functionalities of lutaml_uml_datamodel_description, which is to render data model packages and its dependent objects for supplied XMI file, by using Liquid Drop. The performance of lutaml_ea_xmi can be improved by 10~20 times. (Tested with a 10.6MB XMI file with 120000+ lines)

To use this macro, you only need to replace lutaml_uml_datamodel_description by lutaml_ea_xmi.

Replace:

[source,adoc]

[lutaml_uml_datamodel_description, path/to/example.xmi] ...

By:

[source,adoc]

[lutaml_ea_xmi, path/to/example.xmi] ...

== Documentation

Please refer to https://www.metanorma.org.