Skip to content

Armatiek/mim-serialization-api-4-java

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

42 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MIM serialization API for Java

standard-readme compliant

The "MIM serialization API for Java" is a library for JVM based languages (Java, Kotlin, Scala, Groovy, Clojure etc.) for reading (and navigating) and writing MIM (Metamodel voor Informatiemodellering) XML serializations following MIM versions 1.1.0, 1.1.1 and 1.2. The library makes use of the JAXB framework to map Java classes to XML and vice versa based on the MIM XML Schemas. A number of the generated classes is extended to provide important extra functionality.

Table of Contents

Adding the API to your build

The API's Maven group ID is nl.armatiek.mim, and its artifact ID is mim-serialization-api.

To add a dependency on the API using Maven, use the following:

<dependency>
  <groupId>nl.armatiek.mim</groupId>
  <artifactId>mim-serialization-api</artifactId>
  <version>0.9.1</version>
</dependency>

To add a dependency using Gradle:

dependencies {
  implementation("nl.armatiek.mim:mim-serialization-api:0.9.1")
}

Loading an existing MIM serialization

An existing MIM serialization (like the ones that are generated by Imvertor) can be loaded (or "unmarshalled", "deserialized") using the static methods loadModel of the class MimSerializationApi:

public static MimModel loadModel(InputStream mimSerialization) throws MimSerializationApiLoadException;

or:

public static MimModel loadModel(Path mimSerializationPath) throws MimSerializationApiLoadException;

The MimModel that is returned is of one of the classes:

  • nl.geostandaarden.mim_1_2.relatiesoort.MimModel
  • nl.geostandaarden.mim_1_2.relatierol.MimModel
  • nl.geostandaarden.mim_1_1_1.relatiesoort.MimModel
  • nl.geostandaarden.mim_1_1_1.relatierol.MimModel
  • nl.geostandaarden.mim_1_1_0.relatiesoort.MimModel
  • nl.geostandaarden.mim_1_1_0.relatierol.MimModel

depending on the MIM versie and the relatiemodelleringstype ("Relatiesoort leidend" or "Relatierol leidend") that the API detected in the MIM serialization.

The API can also validate the MIM serialization against the MIM XML schema during load:

public static MimModel loadModel(InputStream mimSerialization, ValidationEventHandler eventHandler) throws MimSerializationApiLoadException;

or:

public static MimModel loadModel(Path mimSerializationPath, ValidationEventHandler eventHandler) throws MimSerializationApiLoadException;

for instance:

MimModel mimModel = MimSerializationApi.loadModel(mimSerialization, new ValidationEventHandler() {
  @Override
  public boolean handleEvent(ValidationEvent event) {
    System.out.println("Validation error: " + event.getMessage() + " (" + event.getSeverity() + ")");
    return event.getSeverity() == ValidationEvent.WARNING;
  }
});

The return value of the handleEvent method indicates that the loading should only continue if the severity of the parse error is WARNING.

Traversal of the MIM model starts with obtaining the Informatiemodel object:

Informatiemodel informatiemodel = mimModel.getInformatiemodel();

For instance getting all Objecttypes of the first Domein:

List<Objecttype> objectTypes = mimModel.getInformatiemodel().getPackages().getDomein().get(0).getObjecttypen().getObjecttype();

A number of the classes that were generated by JAXB are extended to provide important extra functionality. These classes have a name ending on "Ex", like ObjecttypeEx, AttribuutsoortEx, RefTypeEx or XhtmlTextEx. During traversal of the information model an object of for instance the class Objectype, Attribuutsoort, RefType or XhtmlText can always be cast to ObjecttypeEx, AttribuutsoortEx, RefTypeEx and XhtmlTextEx to access this extra functionality.

Following links

A typical MIM serialization contains a lot of internal links, like links from an Attribuutsoort to a Datatype (like a Primitief datatype, Gestructureerd datatype, Enumeratie, Referentielijst or a Codelijst), links from an Objecttype to its supertype and so on. In the MIM serialisation these links are coded according to the XLink standard, for instance:

<mim:PrimitiefDatatype id="fietsenwinkel-contacten-iban">
  ...
  <mim:naam>IBAN</mim:naam>
  ...             
</mim:PrimitiefDatatype>

<mim:Attribuutsoort id="fietsenwinkel-contacten-bankrekening-rekeningnummer">
  ...
  <mim:type>
    <mim-ref:DatatypeRef xlink:href="#fietsenwinkel-contacten-iban">IBAN</mim-ref:DatatypeRef>
  </mim:type>
  ...
</mim:Attribuutsoort>

XLink is not supported by JAXB. Therefore all RefType classes (that are a mapping of the schema type mim:RefType) have a subclass RefTypeEx with two helper methods:

public Object getTarget(); // To be used after loading a MIM serialization and traversing the model

public void setTarget(Object target); // To be used when constructing a new MIM model

Getting and setting XHTML content

A number of text fields in MIM (like Objecttype.definitie) can contain XHTML content. To support getting and setting XHTML as a string, all XhtmlText classes have a subclass XhtmlTextEx with two helper methods:

public void setContentAsString(String xhtml) throws MimSerializationApiXhtmlException;

public String getContentAsString() throws MimSerializationApiXhtmlException;

Getting the type of an Attribuutsoort

According to the MIM standard, the type of an attribuutsoort can be:

  • One of the externally defined standard primitive datatype, like CharacterString, Integer or Date.
  • A reference to a Primitief datatype, Gestructureerd datatype, Enumeratie, Referentielijst or Codelijst that is defined in the model elsewhere.
  • A reference to a Keuze (a choice between datatypes).
  • A reference to a Constructie (part of the MIM extension mechanism).

To obtain the actual type using the JAXB generated classes involves calling a lot of different methods and following quite some references. For this reason every Attribuutsoort can be cast to an AttribuutsoortEx that provides one extra method:

public AttribuutsoortType getAttribuutsoortType();

AttribuutsoortType is a marker interface that is implemented by the classes Datatype, DatatypeAbstract (and all its subclasses like PrimitiefDatatype, Codelijst and Referentielijst), Keuze and Constructie (see AttribuutsoortType javadocs).

Getting the supertypes of an Objecttype

You can get the supertypes of an Objecttype by casting the Objecttype to ObjecttypeEx and use the method:

public List<Objecttype> getSupertypen(boolean excludeStaticOrMixinTypes); // MIM 1.2+

or:

public List<Objecttype> getSupertypen(boolean excludeStaticTypes); // MIM 1.1.*

Using the parameter excludeStaticOrMixinTypes or excludeStaticTypes it is possible to filter out any non-direct "static" or "mixin" supertypes.

Getting model elements of an Objecttype by name

You can get the "inner" model elements of an Objecttype by name by casting the Objecttype to ObjecttypeEx and use one of the methods:

public Attribuutsoort getAttribuutsoort(String name);

public Gegevensgroep getGegevensgroep(String name);

public Relatiesoort getRelatiesoort(String name);

public Keuze getKeuze(String name);

public Constraint getConstraint(String name);

public Kenmerk getKenmerk(String name);

The name is always case sensitive.

Getting any model element by unique identifier or name

You get get any model element by unique identifier or name using the methods:

public Object getModelElementById(String id);

public List<Object> getModelElementsByName(String name);

of the MimModel. Both the identifier and name are case sensitive.

Please create an Github issue when you need more of these utility/helper methods!

Following parent relationships

All model element Java classes implement the interface org.jvnet.jaxb.lang.Child which has a method:

public Object getParent();

that can be used to get the parent object. If for example the method MimSerializationApi.getModelElementsByName() was used to find an Objecttype, this objecttype can be cast to the Child interface on which the getParent() can be called to navigate to the package this objectype is part of.

See the sample application: LoadMimModel.java

Creating a new MIM model

A new MIM model can be created using the method MimSerializationApi.newModel, for instance:

MimModel mimModel = MimSerializationApi.newModel(MIM_VERSION.VERSION_1_2, MIM_RELATIEMODELLERINGSTYPE.RELATIESOORT_LEIDEND);

In this example the mimModel will be of the class nl.geostandaarden.mim_1_2.relatiesoort.MimModel.

After the model is created the (required) properties of the Informatiemodel object can be set and new model elements can be added, for instance:

mimModel.setNaam("Mijn nieuwe model");
mimModel.setMIMTaal("NL");
// ... etc. ...

Informatiemodel.Packages packages = new Informatiemodel.Packages();
model.setPackages(packages);
Domein domeinContacts = new Domein();
packages.getDomein().add(domein);

domeinContacts.setNaam("Contacten")   
domeinContacts.setId("domein-contacten");
// ... etc. ...

Reindexing references

When constructing a new model, the RefTypeEx.getTarget() methods and other functionality that relies on these methods, like getting the AttribuurtsoortType of an Attribuutsoort, can only be used after the XLink references are indexed. This indexing can be triggered by calling the method:

public void indexReferences();

on the MimModel object.

Fluent API

The generated Java classes also support a Fluent API. So for instance when constructing a model, a Domein could be constructed like this

Domein domein = new Domein();
domein.setId("mijn-domein-1");
domein.setNaam("Mijn Naam");
domein.setHerkomst("Dit is de herkomst");
XhtmlTextEx definitieText = new XhtmlTextEx();
definitieText.setContentAsString("<xhtml:body><xhtml:p>Dit is een tekst met <xhtml:b>mixed</xhtml:b> <xhtml:i>content</xhtml:i>.</xhtml:p></xhtml:body>");
domein.setDefinitie(definitieText);
domein.setHerkomstDefinitie("Dit is de herkomst van de definitie");
domein.setDatumOpname("2025-01-01");

but using the Fluent API also like this:

Domein domein = new Domein()
  .withId("mijn-domein-1")
  .withNaam("Mijn Naam")
  .withHerkomst("Dit is de herkomst")
  .withDefinitie(definitieText)
  .withHerkomstDefinitie("Dit is de herkomst van de definitie")
  .withDatumOpname("2025-01-01");

Saving a MIM model

A MIM model can be saved (or "marshalled", "serialized") using the save methods of MimModel:

public void MimModel.save(OutputStream mimSerialization) throws MimSerializationApiSaveException;

or:

public void MimModel.save(Path mimSerializationPath) throws MimSerializationApiSaveException;

The API can also validate the MIM serialization against the MIM XML schema during save:

public void MimModel.save(OutputStream mimSerialization, ValidationEventHandler eventHandler) throws MimSerializationApiSaveException;

or:

public void MimModel.save(Path mimSerializationPath, ValidationEventHandler eventHandler) throws MimSerializationApiSaveException;

for instance:

mimModel.save(outputStream, new ValidationEventHandler() {
  @Override
  public boolean handleEvent(ValidationEvent event) {
    System.out.println("Validation error: " + event.getMessage() + " (" + event.getSeverity() + ")");
    return event.getSeverity() == ValidationEvent.WARNING;
  }
});

See the sample application: SaveMimModel.java

About

MIM serialization API for Java

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages