Skip to content

Commit b7cf4f2

Browse files
committed
Introduce generator inheritance hierarchy
1 parent f20b4f9 commit b7cf4f2

File tree

13 files changed

+186
-132
lines changed

13 files changed

+186
-132
lines changed

core/esmf-aspect-model-document-generators/src/main/java/org/eclipse/esmf/aspectmodel/generator/JsonGenerator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
* @param <A> the corresponding artifact type
3434
*/
3535
public abstract class JsonGenerator<C extends JsonGenerationConfig, R extends JsonNode, A extends JsonArtifact<R>>
36-
extends Generator<String, R, C, A> {
36+
extends AspectGenerator<String, R, C, A> {
3737
protected final ObjectMapper objectMapper;
3838

3939
public JsonGenerator( final Aspect aspect, final C config ) {

core/esmf-aspect-model-document-generators/src/main/java/org/eclipse/esmf/aspectmodel/generator/asyncapi/AspectModelAsyncApiGenerator.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,27 +57,27 @@ public Stream<AsyncApiSchemaArtifact> generate() {
5757
AsyncApiSchemaArtifact result;
5858
try {
5959
final ObjectNode rootNode = getRootJsonNode();
60-
final String apiVersion = getApiVersion( aspect, config.useSemanticVersion() );
60+
final String apiVersion = getApiVersion( aspect(), config.useSemanticVersion() );
6161

6262
if ( StringUtils.isNotBlank( config.applicationId() ) ) {
6363
rootNode.put( "id", config.applicationId() );
6464
}
6565

6666
final ObjectNode info = (ObjectNode) rootNode.get( "info" );
67-
info.put( TITLE_FIELD, aspect.getPreferredName( config.locale() ) + " MQTT API" );
67+
info.put( TITLE_FIELD, aspect().getPreferredName( config.locale() ) + " MQTT API" );
6868
info.put( "version", apiVersion );
69-
info.put( DESCRIPTION_FIELD, getDescription( aspect.getDescription( config.locale() ) ) );
70-
info.put( AbstractGenerator.SAMM_EXTENSION, aspect.urn().toString() );
69+
info.put( DESCRIPTION_FIELD, getDescription( aspect().getDescription( config.locale() ) ) );
70+
info.put( AbstractGenerator.SAMM_EXTENSION, aspect().urn().toString() );
7171

72-
rootNode.set( "channels", getChannelNode( aspect, config ) );
73-
if ( !aspect.getEvents().isEmpty() || !aspect.getOperations().isEmpty() ) {
74-
setOperations( aspect, rootNode );
75-
setComponents( aspect, rootNode, config.locale() );
72+
rootNode.set( "channels", getChannelNode( aspect(), config ) );
73+
if ( !aspect().getEvents().isEmpty() || !aspect().getOperations().isEmpty() ) {
74+
setOperations( aspect(), rootNode );
75+
setComponents( aspect(), rootNode, config.locale() );
7676
}
77-
result = new AsyncApiSchemaArtifact( aspect.getName(), rootNode );
77+
result = new AsyncApiSchemaArtifact( aspect().getName(), rootNode );
7878
} catch ( final Exception exception ) {
7979
LOG.error( "There was an exception during the read of the root or the validation.", exception );
80-
result = new AsyncApiSchemaArtifact( aspect.getName(), FACTORY.objectNode() );
80+
result = new AsyncApiSchemaArtifact( aspect().getName(), FACTORY.objectNode() );
8181
}
8282
return Stream.of( result );
8383
}

core/esmf-aspect-model-document-generators/src/main/java/org/eclipse/esmf/aspectmodel/generator/docu/AspectModelDocumentationGenerator.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@
2727
import java.util.function.Function;
2828
import java.util.stream.Stream;
2929

30+
import org.eclipse.esmf.aspectmodel.generator.AspectGenerator;
3031
import org.eclipse.esmf.aspectmodel.generator.AspectModelHelper;
3132
import org.eclipse.esmf.aspectmodel.generator.DocumentGenerationException;
32-
import org.eclipse.esmf.aspectmodel.generator.Generator;
3333
import org.eclipse.esmf.aspectmodel.generator.I18nLanguageBundle;
3434
import org.eclipse.esmf.aspectmodel.generator.LanguageCollector;
3535
import org.eclipse.esmf.aspectmodel.generator.TemplateEngine;
@@ -46,7 +46,8 @@
4646
/**
4747
* Asciidoc generator for a aspect model.
4848
*/
49-
public class AspectModelDocumentationGenerator extends Generator<String, String, DocumentationGenerationConfig, DocumentationArtifact> {
49+
public class AspectModelDocumentationGenerator extends
50+
AspectGenerator<String, String, DocumentationGenerationConfig, DocumentationArtifact> {
5051
public static final DocumentationGenerationConfig DEFAULT_CONFIG = DocumentationGenerationConfigBuilder.builder().build();
5152
private static final Logger LOG = LoggerFactory.getLogger( AspectModelDocumentationGenerator.class );
5253
private static final String DOCU_ROOT_DIR = "/docu";
@@ -86,18 +87,18 @@ public AspectModelDocumentationGenerator( final Aspect aspect, final Documentati
8687
@Override
8788
public Stream<DocumentationArtifact> generate() {
8889
final Map<String, Object> templateContext = new HashMap<>();
89-
templateContext.put( "aspectModel", aspect );
90+
templateContext.put( "aspectModel", aspect() );
9091
templateContext.put( "aspectModelHelper", new AspectModelHelper() );
9192
templateContext.put( "Scalar", Scalar.class );
9293

9394
final Set<Locale> targetLanguages = config.locale() == null
94-
? LanguageCollector.collectUsedLanguages( aspect )
95+
? LanguageCollector.collectUsedLanguages( aspect() )
9596
: Set.of( Locale.ENGLISH );
9697
return targetLanguages.stream().map( language -> {
97-
logMissingTranslations( aspect, language );
98+
logMissingTranslations( aspect(), language );
9899
templateContext.put( "i18n", new I18nLanguageBundle( language ) );
99100
final TemplateEngine templateEngine = new TemplateEngine( templateContext, engineConfiguration );
100-
final String artifactName = getArtifactName( aspect, language );
101+
final String artifactName = getArtifactName( aspect(), language );
101102
String source = templateEngine.apply( DOCU_ROOT_DIR + "/templates/html/aspect-model-documentation" );
102103
source = insertAspectModelDiagram( source, language );
103104
source = insertStaticPlaceholders( source );
@@ -122,7 +123,7 @@ public void generate( final Function<String, OutputStream> nameMapper, final Map
122123
final DocumentationGenerationConfig config = DocumentationGenerationConfigBuilder.builder()
123124
.stylesheet( generationOptions.get( HtmlGenerationOption.STYLESHEET ) )
124125
.build();
125-
new AspectModelDocumentationGenerator( aspect, config ).generate( nameMapper );
126+
new AspectModelDocumentationGenerator( aspect(), config ).generate( nameMapper );
126127
}
127128

128129
/**
@@ -144,15 +145,15 @@ public void generate( final Function<String, OutputStream> nameMapper, final Map
144145
.stylesheet( generationOptions.get( HtmlGenerationOption.STYLESHEET ) )
145146
.locale( language )
146147
.build();
147-
new AspectModelDocumentationGenerator( aspect, config ).generate( nameMapper );
148+
new AspectModelDocumentationGenerator( aspect(), config ).generate( nameMapper );
148149
}
149150

150151
private String getArtifactName( final Aspect aspectModel, final Locale locale ) {
151152
return aspectModel.getName() + "_" + locale.toLanguageTag();
152153
}
153154

154155
private String insertAspectModelDiagram( final String html, final Locale language ) {
155-
final AspectModelDiagramGenerator diagramGenerator = new AspectModelDiagramGenerator( aspect );
156+
final AspectModelDiagramGenerator diagramGenerator = new AspectModelDiagramGenerator( aspect() );
156157
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
157158
diagramGenerator.generateDiagram( AspectModelDiagramGenerator.Format.SVG, language, buffer );
158159
final String encodedImage = "data:image/svg+xml;base64," + Base64.getEncoder().encodeToString( buffer.toByteArray() );

core/esmf-aspect-model-document-generators/src/main/java/org/eclipse/esmf/aspectmodel/generator/json/AspectModelJsonPayloadGenerator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ public AspectModelJsonPayloadGenerator( final Aspect aspect, final Random random
104104

105105
@Override
106106
public Stream<JsonPayloadArtifact> generate() {
107-
return Stream.of( new PayloadGenerator( objectMapper ).apply( aspect, config ) );
107+
return Stream.of( new PayloadGenerator( objectMapper ).apply( aspect(), config ) );
108108
}
109109

110110
private static class PayloadGenerator

core/esmf-aspect-model-document-generators/src/main/java/org/eclipse/esmf/aspectmodel/generator/jsonld/AspectModelToJsonLdGenerator.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@ public AspectModelToJsonLdGenerator( final Aspect aspect, final JsonLdGeneration
4343
@Override
4444
public Stream<JsonLdArtifact> generate() {
4545
final StringWriter stringWriter = new StringWriter();
46-
aspect.getSourceFile().sourceModel().write( stringWriter, RDFLanguages.strLangJSONLD );
46+
aspect().getSourceFile().sourceModel().write( stringWriter, RDFLanguages.strLangJSONLD );
4747
final String content = stringWriter.toString();
4848
try {
49-
return Stream.of( new JsonLdArtifact( aspect.getName() + ".json", objectMapper.readTree( content ) ) );
49+
return Stream.of( new JsonLdArtifact( aspect().getName() + ".json", objectMapper.readTree( content ) ) );
5050
} catch ( final JsonProcessingException exception ) {
51-
LOG.error( "Could not parse JSON-LD for {}", aspect.getName() );
51+
LOG.error( "Could not parse JSON-LD for {}", aspect().getName() );
5252
}
5353
return Stream.empty();
5454
}

core/esmf-aspect-model-document-generators/src/main/java/org/eclipse/esmf/aspectmodel/generator/jsonschema/AspectModelJsonSchemaGenerator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public JsonSchemaArtifact apply( final Aspect aspect, final JsonSchemaGeneration
5151
@Override
5252
public Stream<JsonSchemaArtifact> generate() {
5353
final AspectModelJsonSchemaVisitor visitor = new AspectModelJsonSchemaVisitor( config );
54-
final JsonNode result = aspect.accept( visitor, null );
55-
return Stream.of( new JsonSchemaArtifact( aspect.getName(), result ) );
54+
final JsonNode result = aspect().accept( visitor, null );
55+
return Stream.of( new JsonSchemaArtifact( aspect().getName(), result ) );
5656
}
5757
}

core/esmf-aspect-model-document-generators/src/main/java/org/eclipse/esmf/aspectmodel/generator/openapi/AspectModelOpenApiGenerator.java

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@
4848
import org.eclipse.esmf.metamodel.Property;
4949

5050
import com.fasterxml.jackson.databind.JsonNode;
51-
import com.fasterxml.jackson.databind.ObjectMapper;
5251
import com.fasterxml.jackson.databind.node.ArrayNode;
5352
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
5453
import com.fasterxml.jackson.databind.node.ObjectNode;
@@ -133,23 +132,23 @@ public Stream<OpenApiSchemaArtifact> generate() {
133132
OpenApiSchemaArtifact artifact;
134133
try {
135134
final ObjectNode rootNode = getRootJsonNode( config.generateCommentForSeeAttributes() );
136-
final String apiVersion = getApiVersion( aspect, config.useSemanticVersion() );
135+
final String apiVersion = getApiVersion( aspect(), config.useSemanticVersion() );
137136

138137
( (ObjectNode) rootNode.get( "info" ) )
139-
.put( "title", aspect.getPreferredName( config.locale() ) )
138+
.put( "title", aspect().getPreferredName( config.locale() ) )
140139
.put( "version", apiVersion )
141-
.put( AbstractGenerator.SAMM_EXTENSION, aspect.urn().toString() );
140+
.put( AbstractGenerator.SAMM_EXTENSION, aspect().urn().toString() );
142141
setServers( rootNode, config.baseUrl(), apiVersion, READ_SERVER_PATH );
143-
final boolean includePaging = includePaging( aspect, config.pagingOption() );
144-
setOptionalSchemas( aspect, config, includePaging, rootNode );
145-
setAspectSchemas( aspect, config, rootNode );
146-
setRequestBodies( aspect, config, rootNode );
147-
setResponseBodies( aspect, rootNode, includePaging );
148-
rootNode.set( "paths", getPathsNode( aspect, config, apiVersion, config.properties(), config.queriesTemplate() ) );
149-
artifact = new OpenApiSchemaArtifact( aspect.getName(), merge( rootNode, config.documentTemplate() ) );
142+
final boolean includePaging = includePaging( aspect(), config.pagingOption() );
143+
setOptionalSchemas( aspect(), config, includePaging, rootNode );
144+
setAspectSchemas( aspect(), config, rootNode );
145+
setRequestBodies( aspect(), config, rootNode );
146+
setResponseBodies( aspect(), rootNode, includePaging );
147+
rootNode.set( "paths", getPathsNode( aspect(), config, apiVersion, config.properties(), config.queriesTemplate() ) );
148+
artifact = new OpenApiSchemaArtifact( aspect().getName(), merge( rootNode, config.documentTemplate() ) );
150149
} catch ( final Exception exception ) {
151150
LOG.error( "There was an exception during the read of the root or the validation.", exception );
152-
artifact = new OpenApiSchemaArtifact( aspect.getName(), FACTORY.objectNode() );
151+
artifact = new OpenApiSchemaArtifact( aspect().getName(), FACTORY.objectNode() );
153152
}
154153
return Stream.of( artifact );
155154
}

core/esmf-aspect-model-document-generators/src/test/java/org/eclipse/esmf/aspectmodel/generator/jsonld/AspectModelJsonLdGeneratorTest.java

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,11 @@ void generateTest() {
2020
}
2121

2222
private void assertJsonLdMeta( final String generatedJsonLd, final AspectModelUrn aspectModelUrn ) {
23-
final String context = """
24-
"@context": {
25-
"xsd": "http://www.w3.org/2001/XMLSchema#",
26-
"samm-c": "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#",
27-
"samm": "urn:samm:org.eclipse.esmf.samm:meta-model:2.1.0#",
28-
"@vocab": "urn:samm:org.eclipse.esmf.test:1.0.0#"
29-
}
30-
""";
31-
32-
assertThat( generatedJsonLd ).contains( "\"@graph\": [" );
33-
assertThat( generatedJsonLd ).contains( context );
34-
assertThat( generatedJsonLd ).contains( "\"xsd\": \"http://www.w3.org/2001/XMLSchema#\"," );
35-
assertThat( generatedJsonLd ).contains( String.format( "\"@id\": \"%s\"", aspectModelUrn.toString() ) );
23+
assertThat( generatedJsonLd ).contains( "\"@graph\" : [" );
24+
assertThat( generatedJsonLd ).contains( "\"xsd\" : \"http://www.w3.org/2001/XMLSchema#\"," );
25+
assertThat( generatedJsonLd ).contains( "\"samm-c\" : \"urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#\"" );
26+
assertThat( generatedJsonLd ).contains( "\"samm\" : \"urn:samm:org.eclipse.esmf.samm:meta-model:2.1.0#\"" );
27+
assertThat( generatedJsonLd ).contains( "\"@vocab\" : \"urn:samm:org.eclipse.esmf.test:1.0.0#\"" );
28+
assertThat( generatedJsonLd ).contains( String.format( "\"@id\" : \"%s\"", aspectModelUrn.toString() ) );
3629
}
3730
}

core/esmf-aspect-model-generator/src/main/java/org/eclipse/esmf/aspectmodel/generator/AspectGenerator.java

Lines changed: 8 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -13,51 +13,33 @@
1313

1414
package org.eclipse.esmf.aspectmodel.generator;
1515

16-
import java.io.IOException;
17-
import java.io.OutputStream;
18-
import java.io.OutputStreamWriter;
19-
import java.io.Writer;
20-
import java.nio.charset.StandardCharsets;
21-
import java.util.Comparator;
22-
import java.util.function.Function;
2316
import java.util.stream.Stream;
2417

2518
import org.eclipse.esmf.aspectmodel.visitor.AspectStreamTraversalVisitor;
2619
import org.eclipse.esmf.metamodel.Aspect;
2720
import org.eclipse.esmf.metamodel.ModelElement;
2821

29-
import org.slf4j.Logger;
30-
import org.slf4j.LoggerFactory;
31-
3222
/**
33-
* Base class for the generation of {@link Artifact}s.
23+
* Base class for the generation of {@link Artifact}s from a single {@link Aspect}.
3424
*
3525
* @param <I> the type that uniquely identifies the artifact in the scope of the generation process
3626
* @param <T> the artifact's content type, e.g. String or byte[]
3727
* @param <C> the config object for the genererator
3828
* @param <A> the type of the artifact that is generated
3929
*/
40-
public abstract class Generator<I, T, C extends GenerationConfig, A extends Artifact<I, T>> {
41-
private static final Logger LOG = LoggerFactory.getLogger( Generator.class );
42-
protected final C config;
43-
protected final Aspect aspect;
44-
protected final Comparator<ModelElement> uniqueByModelElementIdentifier = ( modelElementOne, modelElementTwo ) -> {
45-
final String modelElementOneIdentifier = modelElementOne.urn().toString();
46-
final String modelElementTwoIdentifier = modelElementTwo.urn().toString();
47-
return modelElementOneIdentifier.compareTo( modelElementTwoIdentifier );
48-
};
30+
public abstract class AspectGenerator<I, T, C extends GenerationConfig, A extends Artifact<I, T>>
31+
extends Generator<Aspect, I, T, C, A> {
4932

50-
protected Generator( final Aspect aspect, final C config ) {
51-
this.aspect = aspect;
52-
this.config = config;
33+
protected AspectGenerator( final Aspect aspect, final C config ) {
34+
super( aspect, config );
5335
}
5436

55-
public C getConfig() {
56-
return config;
37+
protected Aspect aspect() {
38+
return focus;
5739
}
5840

5941
protected <E extends ModelElement> Stream<E> elements( final Class<E> clazz ) {
60-
return aspect.accept( new AspectStreamTraversalVisitor(), null )
42+
return aspect().accept( new AspectStreamTraversalVisitor(), null )
6143
.filter( clazz::isInstance )
6244
.map( clazz::cast )
6345
.sorted( uniqueByModelElementIdentifier )
@@ -68,57 +50,4 @@ protected <E extends ModelElement> Stream<A> applyTemplate(
6850
final Class<E> clazz, final ArtifactGenerator<I, T, E, C, A> artifactGenerator, final C config ) {
6951
return elements( clazz ).map( element -> artifactGenerator.apply( element, config ) );
7052
}
71-
72-
/**
73-
* Generates artifacts from the given Aspect model. As this generation may produce multiple artifacts, the generator
74-
* provides the caller with the identifer of the respective artifact via the callback function. The caller needs to
75-
* provide an {@link OutputStream} for the artifact, e.g. a suitable FileOutputStream.
76-
*
77-
* @param nameMapper the callback function that maps artifact identifiers to OutputStreams
78-
*/
79-
public void generate( final Function<I, OutputStream> nameMapper ) {
80-
generate().toList().forEach( generationResult -> write( generationResult, nameMapper ) );
81-
}
82-
83-
/**
84-
* Generates artifacts for the given Aspect model
85-
*
86-
* @return the stream of artifacts
87-
*/
88-
public abstract Stream<A> generate();
89-
90-
/**
91-
* Assumes that the generator returns exactly one artifact and returns this
92-
*
93-
* @return the generated artifact
94-
*/
95-
public A singleResult() {
96-
return generate()
97-
.findFirst()
98-
.orElseThrow( () -> new GenerationException( "Could not generate artifact for " + aspect.getName() ) );
99-
}
100-
101-
/**
102-
* Assumes that the generator returns exactly one artifact and returns its content
103-
*
104-
* @return the artifact's content
105-
*/
106-
public T getContent() {
107-
return singleResult().getContent();
108-
}
109-
110-
/**
111-
* Writes an artifact to the corresponding output stream
112-
*
113-
* @param artifact the artifact
114-
* @param nameMapper the function that provides the output stream for the artifact
115-
*/
116-
protected void write( final Artifact<I, T> artifact, final Function<I, OutputStream> nameMapper ) {
117-
try ( final OutputStream output = nameMapper.apply( artifact.getId() ) ) {
118-
output.write( artifact.serialize() );
119-
output.flush();
120-
} catch ( final IOException exception ) {
121-
LOG.error( "Failure during writing of generated artifact", exception );
122-
}
123-
}
12453
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright (c) 2024 Bosch Software Innovations GmbH. All rights reserved.
3+
*/
4+
5+
package org.eclipse.esmf.aspectmodel.generator;
6+
7+
public abstract class BinaryArtifact implements Artifact<String, byte[]> {
8+
private final String id;
9+
private final byte[] content;
10+
11+
public BinaryArtifact( final String id, final byte[] content ) {
12+
this.id = id;
13+
this.content = content;
14+
}
15+
16+
@Override
17+
public String getId() {
18+
return id;
19+
}
20+
21+
@Override
22+
public byte[] getContent() {
23+
return content;
24+
}
25+
26+
@Override
27+
public byte[] serialize() {
28+
return content;
29+
}
30+
}

0 commit comments

Comments
 (0)