Generating Documentation for Aspect Models

Different types of artifacts can be generated from an Aspect model. All corresponding generators are included in the following dependency:

Maven
<dependency>
    <groupId>org.eclipse.esmf</groupId>
    <artifactId>esmf-aspect-model-document-generators</artifactId>
    <version>2.12.0</version>
</dependency>
Gradle Groovy DSL
implementation 'org.eclipse.esmf:esmf-aspect-model-document-generators:2.12.0'
Gradle Kotlin DSL
implementation("org.eclipse.esmf:esmf-aspect-model-document-generators:2.12.0")

The documentation generation APIs provide methods that take as an argument a Function<String, java.io.OutputStream>. This is a mapping function that takes a file name as an input (which is determined by the respective generator) and returns a corresponding OutputStream, for example (but not necessarily) a FileOutputStream. By providing this function when calling the generator method, you can control where the output is written to, even when the generator creates multiple files. For the code examples in the following subsections, we assume that the following method is defined for calling the generators:

OutputStream outputStreamForName( final String aspectFileName ) {
   // Create an OutputStream for the file name, e.g. a FileOutputStream
}

Generating SVG or PNG Diagrams

Using the AspectModelDiagramGenerator, automatically layouted diagrams can be created for Aspect models in the formats PNG and SVG.

Show used imports
import org.eclipse.esmf.aspectmodel.generator.diagram.AspectModelDiagramGenerator;
import org.eclipse.esmf.aspectmodel.generator.diagram.DiagramGenerationConfig;
import org.eclipse.esmf.aspectmodel.generator.diagram.DiagramGenerationConfigBuilder;
import org.eclipse.esmf.aspectmodel.loader.AspectModelLoader;
import org.eclipse.esmf.metamodel.AspectModel;
// AspectModel as returned by the AspectModelLoader
final AspectModel aspectModel = // ...

final DiagramGenerationConfig config = DiagramGenerationConfigBuilder.builder()
      .format( DiagramGenerationConfig.Format.SVG )
      .language( Locale.ENGLISH )
      .build();
new AspectModelDiagramGenerator( aspectModel.aspect(), config ) (1)
      .generate( this::outputStreamForName ); (2)
1 The diagram generator is initialized with the loaded model and the generation configuration.
2 The generation takes the output stream for the output file name as input and writes the generated diagram to the output stream.

Generating HTML Documentation

A HTML reference documentation for an Aspect model can be generated as shown in the following code sample. The documentation contains an overview diagram and describes the model elements as specified in the Aspect model. Preferred names and descriptions in the respective language from the Aspect model are shown in the resulting document as part of each model element.

Show used imports
import org.eclipse.esmf.aspectmodel.generator.docu.AspectModelDocumentationGenerator;
import org.eclipse.esmf.aspectmodel.generator.docu.DocumentationGenerationConfig;
import org.eclipse.esmf.aspectmodel.generator.docu.DocumentationGenerationConfigBuilder;
import org.eclipse.esmf.aspectmodel.loader.AspectModelLoader;
import org.eclipse.esmf.metamodel.AspectModel;
// AspectModel as returned by the AspectModelLoader
final AspectModel aspectModel = // ...
final DocumentationGenerationConfig config = DocumentationGenerationConfigBuilder.builder() (1)
      /* .stylesheet( customCss ) if required */
      .build();
final AspectModelDocumentationGenerator generator = (2)
      new AspectModelDocumentationGenerator( aspectModel.aspect(), config );
generator.generate( this::outputStreamForName );
1 HTML generation can be controlled via options.
2 The HTML generator is initialized with the context consisting of the loaded RDF model and the selected Aspect.

Generating Sample JSON Payload

The sample JSON payload generator is used to create a valid JSON payload for an Aspect model as it could be returned by an Aspect that implements that Aspect model. This follows the mapping rules as defined in the Meta Model specification. The generator uses `samm:exampleValue`s of Properties if present, otherwise random values corresponding to the respective data types are generated.

Show used imports
import org.eclipse.esmf.aspectmodel.generator.json.AspectModelJsonPayloadGenerator;
import org.eclipse.esmf.aspectmodel.loader.AspectModelLoader;
import org.eclipse.esmf.metamodel.AspectModel;
// AspectModel as returned by the AspectModelLoader
final AspectModel aspectModel = // ...

final AspectModelJsonPayloadGenerator generator = new AspectModelJsonPayloadGenerator( aspectModel.aspect() );

// Variant 1: Direct generation into a String
final String jsonString = generator.generateJson();

// Variant 2: Generate using mapping function
generator.generate( this::outputStreamForName );

Generating JSON Schema

The JSON schema generator creates a JSON Schema that describes the payload for an Aspect model as it could be returned by an Aspect that implements that Aspect model.

Show used imports
import org.eclipse.esmf.aspectmodel.generator.jsonschema.AspectModelJsonSchemaGenerator;
import org.eclipse.esmf.aspectmodel.generator.jsonschema.JsonSchemaGenerationConfig;
import org.eclipse.esmf.aspectmodel.generator.jsonschema.JsonSchemaGenerationConfigBuilder;
import org.eclipse.esmf.aspectmodel.loader.AspectModelLoader;
import org.eclipse.esmf.metamodel.AspectModel;

import java.util.Locale;
import com.fasterxml.jackson.databind.JsonNode;
// AspectModel as returned by the AspectModelLoader
final AspectModel aspectModel = // ...

final JsonSchemaGenerationConfig config = JsonSchemaGenerationConfigBuilder.builder()
      .locale( Locale.ENGLISH )
      .build();
final AspectModelJsonSchemaGenerator generator = new AspectModelJsonSchemaGenerator( aspectModel.aspect(), config );
// Get result as type-safe JSON object
final JsonNode jsonNode = generator.getContent();
// Or as pretty-printed JSON String:
final String json = generator.generateJson();

Generating OpenAPI Specification

The OpenAPI specification generator creates either a JSON Schema or a Yaml Spec that specifies an Aspect regarding to the OpenApi specification. The currently used versions corresponds Draft 4 of the JSON Schema specification, and 3.0.1.

Show used imports
import org.eclipse.esmf.aspectmodel.generator.openapi.AspectModelOpenApiGenerator;
import org.eclipse.esmf.aspectmodel.generator.openapi.OpenApiSchemaGenerationConfig;
import org.eclipse.esmf.aspectmodel.generator.openapi.OpenApiSchemaGenerationConfigBuilder;
import org.eclipse.esmf.aspectmodel.generator.openapi.PagingOption;
import org.eclipse.esmf.aspectmodel.loader.AspectModelLoader;
import org.eclipse.esmf.metamodel.AspectModel;

import com.fasterxml.jackson.databind.JsonNode;
Generate OpenAPI YAML
// AspectModel as returned by the AspectModelLoader
final AspectModel aspectModel = // ...

final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder()
      // Server URL
      .baseUrl( "http://www.example.com" )
      // The resource path which shall be added
      .resourcePath( "/testPath/{parameter}" )
      // Determines whether semantic versioning should be used for the API
      // i.e., true = v1.2.3, false = v1
      .useSemanticVersion( false )
      // A String containing all the information for dynamic properties mentioned in the resource path.
      // The string must be syntactically valid YAML.
      .properties( readYaml( """
            parameter:
              name: parameter
              in: path
              description: "A parameter."
              required: true
              schema:
                type: string
            """ ) )
      // Should the query API be added to the generated specification?
      .includeQueryApi( true )
      // The paging Option to be chosen. In case paging is possible:
      // The default for a time related collection is time-based paging.
      // Otherwise the default is offset-based paging.
      .pagingOption( PagingOption.OFFSET_BASED_PAGING )
      .build();

// Generate pretty-printed YAML
final AspectModelOpenApiGenerator generator = new AspectModelOpenApiGenerator( aspectModel.aspect(), config );
final String yaml = generator.generateYaml();
Generate OpenAPI JSON
// AspectModel as returned by the AspectModelLoader
final AspectModel aspectModel = // ...

final OpenApiSchemaGenerationConfig config = OpenApiSchemaGenerationConfigBuilder.builder()
      // Server URL
      .baseUrl( "http://www.example.com" )
      // The resource path which shall be added
      .resourcePath( "/testPath/{parameter}" )
      // Determines whether semantic versioning should be used for the API
      // i.e., true = v1.2.3, false = v1
      .useSemanticVersion( false )
      // A JsonNode containing all the information for variable properties mentioned
      // in the resource path .
      .properties( readYaml( """
               {
                 "test-Id": {
                   "name": "test-Id",
                   "in": "path",
                   "description": "The ID of the unit.",
                   "required": true,
                   "schema": {
                     "type": "string"
                   }
                 }
               }
            """ ) )
      // Should the query API be added to the generated specification?
      .includeQueryApi( true )
      // The paging Option to be chosen. In case paging is possible:
      // The default for a time related collection is time-based paging.
      // Otherwise the default is offset-based paging.
      .pagingOption( PagingOption.OFFSET_BASED_PAGING )
      .build();

// Generate the JSON
final AspectModelOpenApiGenerator generator = new AspectModelOpenApiGenerator( aspectModel.aspect(), config );
// Get result as type-safe JSON object
final JsonNode jsonNode = generator.getContent();
// Or as pretty-printed JSON String:
final String json = generator.generateJson();
For Enumerations with complex data types, the values are modelled as instances of the Entity defined as the Enumeration’s data type (see Declaring Enumerations for more information). In case the Entity instances contain Properties with a sorted collection as their data type, the order of the values of said collection in the Entity instances is not preserved in the generated OpenAPI specification. Preserving this order in OpenAPI is not possible at this point.

Generating AsyncAPI Specification

The AsyncAPI specification generator creates either a JSON Schema or a Yaml Spec that specifies an Aspect regarding to the AsyncApi specification. The currently used versions correspond to Draft 4 of the JSON Schema specification, and 3.0.0 of the AsyncAPI specification.

Show used imports
import org.eclipse.esmf.aspectmodel.generator.asyncapi.AspectModelAsyncApiGenerator;
import org.eclipse.esmf.aspectmodel.generator.asyncapi.AsyncApiSchemaGenerationConfig;
import org.eclipse.esmf.aspectmodel.generator.asyncapi.AsyncApiSchemaGenerationConfigBuilder;
import org.eclipse.esmf.aspectmodel.loader.AspectModelLoader;
import org.eclipse.esmf.metamodel.AspectModel;

import com.fasterxml.jackson.databind.JsonNode;
Generate AsyncAPI YAML
// AspectModel as returned by the AspectModelLoader
final AspectModel aspectModel = // ...

final AsyncApiSchemaGenerationConfig config = AsyncApiSchemaGenerationConfigBuilder.builder()
      // i.e., true = v1.2.3, false = v1
      .useSemanticVersion( false )
      // Set Application id
      .applicationId( "test:serve" )
      .channelAddress( "/123-456/789-012/movement/0.0.1/Movement" )
      .build();

// Generate pretty-printed YAML
final AspectModelAsyncApiGenerator generator = new AspectModelAsyncApiGenerator( aspectModel.aspect(), config );
final String yaml = generator.generateYaml();
Generate AsyncAPI JSON
// AspectModel as returned by the AspectModelLoader
final AspectModel aspectModel = // ...

final AsyncApiSchemaGenerationConfig config = AsyncApiSchemaGenerationConfigBuilder.builder()
      // i.e., true = v1.2.3, false = v1
      .useSemanticVersion( false )
      // Set Application id
      .applicationId( "test:serve" )
      .channelAddress( "/123-456/789-012/movement/0.0.1/Movement" )
      .build();

// Generate the JSON
final AspectModelAsyncApiGenerator generator = new AspectModelAsyncApiGenerator( aspectModel.aspect(), config );
// Get result as type-safe JSON object
final JsonNode jsonNode = generator.getContent();
// Or as pretty-printed JSON String:
final String json = generator.generateJson();