Skip to content

Commit a7cf8f2

Browse files
authored
Merge pull request #674 from bci-oss/669-invalid-attribute-in-sample-json-payload
Fix generation of JSON sample payload
2 parents 9869402 + 9c7735f commit a7cf8f2

File tree

94 files changed

+1810
-1311
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

94 files changed

+1810
-1311
lines changed

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

Lines changed: 0 additions & 35 deletions
This file was deleted.

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

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,23 @@
1313

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

16+
import java.io.Serial;
1617
import java.nio.file.Path;
1718
import java.util.Iterator;
1819
import java.util.Map;
1920
import java.util.Optional;
2021
import java.util.function.Function;
2122
import java.util.stream.Collectors;
2223

24+
import org.eclipse.esmf.aspectmodel.generator.jsonschema.AspectModelJsonSchemaGenerator;
2325
import org.eclipse.esmf.aspectmodel.urn.AspectModelUrn;
2426

25-
import com.fasterxml.jackson.core.JsonProcessingException;
2627
import com.fasterxml.jackson.databind.JsonNode;
2728
import com.fasterxml.jackson.databind.ObjectMapper;
2829
import com.fasterxml.jackson.databind.node.ArrayNode;
2930
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
3031
import com.fasterxml.jackson.databind.node.ObjectNode;
3132
import com.fasterxml.jackson.databind.node.TextNode;
32-
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
33-
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
34-
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
3533
import com.fasterxml.jackson.dataformat.yaml.util.StringQuotingChecker;
3634
import com.google.common.collect.ImmutableMap;
3735
import com.google.common.collect.Streams;
@@ -40,11 +38,17 @@
4038
import org.slf4j.LoggerFactory;
4139

4240
/**
43-
* The result of a schema generation where the schema is represented as a JSON document
41+
* The result of a schema generation where the schema is represented as a JSON document.
42+
*
43+
* @param <T> the concrete type of node of this artifact
4444
*/
45-
public abstract class AbstractSchemaArtifact<T extends JsonNode> implements Artifact<String, T> {
45+
public abstract class AbstractSchemaArtifact<T extends JsonNode> extends JsonArtifact<T> {
4646
private static final Logger LOG = LoggerFactory.getLogger( AbstractSchemaArtifact.class );
4747

48+
public AbstractSchemaArtifact( final String id, final T content ) {
49+
super( id, content );
50+
}
51+
4852
/**
4953
* Returns the OpenAPI schema with separate files for schemas. In the resulting map, the key is the path
5054
* that names a schema and the value is the corresponding JSON structure. The root schema will be called
@@ -126,38 +130,25 @@ private JsonNode updateRefValues( final JsonNode node, final Map<String, String>
126130
protected Map<Path, JsonNode> getContentWithSeparateSchemasAsJson( final Optional<String> mainSpec ) {
127131
final JsonNode jsonContent = getContent();
128132
final String aspectName = AspectModelUrn.fromUrn(
129-
jsonContent.get( "info" ).get( AbstractGenerator.SAMM_EXTENSION ).asText() ).getName();
133+
jsonContent.get( "info" ).get( AspectModelJsonSchemaGenerator.SAMM_EXTENSION ).asText() ).getName();
130134
return getSeparateSchemas( aspectName, "json", mainSpec );
131135
}
132136

133137
protected Map<Path, String> getContentWithSeparateSchemasAsYaml( final Optional<String> mainSpec ) {
134138
final JsonNode jsonContent = getContent();
135139
final String aspectName = AspectModelUrn.fromUrn(
136-
jsonContent.get( "info" ).get( AbstractGenerator.SAMM_EXTENSION ).asText() ).getName();
140+
jsonContent.get( "info" ).get( AspectModelJsonSchemaGenerator.SAMM_EXTENSION ).asText() ).getName();
137141
return getSeparateSchemas( aspectName, "yaml", mainSpec ).entrySet().stream().collect( Collectors.toMap(
138142
Map.Entry::getKey, entry -> jsonToYaml( entry.getValue() ) ) );
139143
}
140144

141-
protected String jsonToYaml( final JsonNode json ) {
142-
try {
143-
final YAMLFactory yamlFactory = YAMLFactory.builder()
144-
.stringQuotingChecker( new OpenApiStringQuotingChecker() ).build();
145-
return new YAMLMapper( yamlFactory ).enable( YAMLGenerator.Feature.MINIMIZE_QUOTES )
146-
.writeValueAsString( json );
147-
} catch ( final JsonProcessingException exception ) {
148-
LOG.error( "JSON could not be converted to YAML", exception );
149-
return json.toString();
150-
}
151-
}
152-
153145
public static class OpenApiStringQuotingChecker extends StringQuotingChecker.Default {
146+
@Serial
147+
private static final long serialVersionUID = 6044974890325771572L;
154148

155149
@Override
156150
protected boolean valueHasQuotableChar( final String inputStr ) {
157-
if ( inputStr.contains( "#" ) ) {
158-
return true;
159-
}
160-
return super.valueHasQuotableChar( inputStr );
151+
return inputStr.contains( "#" ) || super.valueHasQuotableChar( inputStr );
161152
}
162153
}
163154
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

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

16-
public class DocumentGenerationException extends RuntimeException {
16+
public class DocumentGenerationException extends GenerationException {
1717
private static final long serialVersionUID = -3592685602580476530L;
1818

1919
public DocumentGenerationException( final String message ) {
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright (c) 2024 Robert Bosch Manufacturing Solutions GmbH
3+
*
4+
* See the AUTHORS file(s) distributed with this work for additional
5+
* information regarding authorship.
6+
*
7+
* This Source Code Form is subject to the terms of the Mozilla Public
8+
* License, v. 2.0. If a copy of the MPL was not distributed with this
9+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
10+
*
11+
* SPDX-License-Identifier: MPL-2.0
12+
*/
13+
14+
package org.eclipse.esmf.aspectmodel.generator;
15+
16+
import java.nio.charset.StandardCharsets;
17+
18+
import com.fasterxml.jackson.core.JsonProcessingException;
19+
import com.fasterxml.jackson.databind.JsonNode;
20+
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
21+
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
22+
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
23+
import org.slf4j.Logger;
24+
import org.slf4j.LoggerFactory;
25+
26+
public class JsonArtifact<T extends JsonNode> implements Artifact<String, T> {
27+
private static final Logger LOG = LoggerFactory.getLogger( JsonArtifact.class );
28+
29+
private final String id;
30+
private final T content;
31+
32+
public JsonArtifact( final String id, final T content ) {
33+
this.id = id;
34+
this.content = content;
35+
}
36+
37+
@Override
38+
public String getId() {
39+
return id;
40+
}
41+
42+
@Override
43+
public T getContent() {
44+
return content;
45+
}
46+
47+
public String getContentAsYaml() {
48+
return jsonToYaml( getContent() );
49+
}
50+
51+
@Override
52+
public byte[] serialize() {
53+
return getContent().toPrettyString().getBytes( StandardCharsets.UTF_8 );
54+
}
55+
56+
protected String jsonToYaml( final JsonNode json ) {
57+
try {
58+
final YAMLFactory yamlFactory = YAMLFactory.builder()
59+
.stringQuotingChecker( new AbstractSchemaArtifact.OpenApiStringQuotingChecker() ).build();
60+
return new YAMLMapper( yamlFactory ).enable( YAMLGenerator.Feature.MINIMIZE_QUOTES )
61+
.writeValueAsString( json );
62+
} catch ( final JsonProcessingException exception ) {
63+
LOG.error( "JSON could not be converted to YAML", exception );
64+
return json.toString();
65+
}
66+
}
67+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Copyright (c) 2024 Robert Bosch Manufacturing Solutions GmbH
3+
*
4+
* See the AUTHORS file(s) distributed with this work for additional
5+
* information regarding authorship.
6+
*
7+
* This Source Code Form is subject to the terms of the Mozilla Public
8+
* License, v. 2.0. If a copy of the MPL was not distributed with this
9+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
10+
*
11+
* SPDX-License-Identifier: MPL-2.0
12+
*/
13+
14+
package org.eclipse.esmf.aspectmodel.generator;
15+
16+
public interface JsonGenerationConfig extends GenerationConfig {
17+
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
* Copyright (c) 2024 Robert Bosch Manufacturing Solutions GmbH
3+
*
4+
* See the AUTHORS file(s) distributed with this work for additional
5+
* information regarding authorship.
6+
*
7+
* This Source Code Form is subject to the terms of the Mozilla Public
8+
* License, v. 2.0. If a copy of the MPL was not distributed with this
9+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
10+
*
11+
* SPDX-License-Identifier: MPL-2.0
12+
*/
13+
14+
package org.eclipse.esmf.aspectmodel.generator;
15+
16+
import java.io.IOException;
17+
import java.io.OutputStream;
18+
import java.util.function.Function;
19+
20+
import org.eclipse.esmf.aspectmodel.jackson.AspectModelJacksonModule;
21+
import org.eclipse.esmf.metamodel.Aspect;
22+
23+
import com.fasterxml.jackson.databind.JsonNode;
24+
import com.fasterxml.jackson.databind.ObjectMapper;
25+
import com.fasterxml.jackson.databind.SerializationFeature;
26+
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
27+
28+
/**
29+
* Base class for generators that create JSON
30+
*
31+
* @param <C> the configuration type
32+
* @param <R> the result type, e.g., JsonNode or ObjectNode
33+
* @param <A> the corresponding artifact type
34+
*/
35+
public abstract class JsonGenerator<C extends JsonGenerationConfig, R extends JsonNode, A extends JsonArtifact<R>>
36+
extends AspectGenerator<String, R, C, A> {
37+
protected final ObjectMapper objectMapper;
38+
39+
public JsonGenerator( final Aspect aspect, final C config ) {
40+
super( aspect, config );
41+
42+
objectMapper = new ObjectMapper();
43+
objectMapper.registerModule( new JavaTimeModule() );
44+
objectMapper.registerModule( new AspectModelJacksonModule() );
45+
objectMapper.configure( SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false );
46+
objectMapper.configure( SerializationFeature.FAIL_ON_EMPTY_BEANS, false );
47+
}
48+
49+
/**
50+
* Generate a pretty-printed JSON output
51+
*
52+
* @return the formatted JSON string
53+
*/
54+
public String generateJson() {
55+
return getContent().toPrettyString();
56+
}
57+
58+
/**
59+
* Generate a pretty-printed YAML output
60+
*
61+
* @return the formatted JSON string
62+
*/
63+
public String generateYaml() {
64+
return singleResult().getContentAsYaml();
65+
}
66+
67+
/**
68+
* Kept for backwards compatibility
69+
*
70+
* @return the JSON representation of the generated artifact
71+
* @deprecated Use {@link #generateJson()} instead
72+
*/
73+
@Deprecated( forRemoval = true )
74+
public String generateJsonPretty() throws IOException {
75+
return generateJson();
76+
}
77+
78+
/**
79+
* Kept for backwards compatibility
80+
*
81+
* @param nameMapper the callback function that maps artifact identifiers to OutputStreams
82+
* @deprecated Use {@link #generate(Function)} instead
83+
*/
84+
@Deprecated( forRemoval = true )
85+
public void generateJsonPretty( final Function<String, OutputStream> nameMapper ) throws IOException {
86+
generate( nameMapper );
87+
}
88+
89+
/**
90+
* Kept for backwards compatibility
91+
*
92+
* @param nameMapper the callback function that maps artifact identifiers to OutputStreams
93+
* @deprecated Use {@link #generate(Function)} instead
94+
*/
95+
@Deprecated( forRemoval = true )
96+
public void generateJson( final Function<String, OutputStream> nameMapper ) throws IOException {
97+
generate( nameMapper );
98+
}
99+
100+
@Override
101+
protected void write( final Artifact<String, R> artifact, final Function<String, OutputStream> nameMapper ) {
102+
try ( final OutputStream output = nameMapper.apply( aspect().getName() ) ) {
103+
output.write( artifact.serialize() );
104+
output.flush();
105+
} catch ( final IOException exception ) {
106+
throw new DocumentGenerationException( exception );
107+
}
108+
}
109+
}

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
* plus some useful operations.
3636
*/
3737
public class NumericTypeTraits {
38-
3938
private static final Logger LOG = LoggerFactory.getLogger( NumericTypeTraits.class );
4039

4140
private static final List<Class<?>> FLOATING_POINT_TYPES = List.of( Float.class, Double.class, BigDecimal.class );

0 commit comments

Comments
 (0)