Skip to content

Commit 68c17ba

Browse files
authored
Merge branch 'main' into 609-display-copyright-license-in-provided-ttl-file
2 parents 7ebe833 + d629250 commit 68c17ba

File tree

52 files changed

+238
-145
lines changed

Some content is hidden

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

52 files changed

+238
-145
lines changed

core/esmf-aspect-meta-model-interface/src/main/java/org/eclipse/esmf/metamodel/datatype/CurieType.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,15 @@
2828
* Represents the samm:curie datatype itself. For the class that represents a Curie value, see {@link Curie}.
2929
*/
3030
public class CurieType implements SammType<Curie> {
31+
public static final CurieType INSTANCE = new CurieType();
3132
public static final String CURIE_REGEX = "[a-zA-Z]*:[a-zA-Z]+";
3233
private final Function<String, Curie> parser = Curie::new;
3334
private final Function<Curie, String> unparser = Curie::value;
3435
private final Predicate<String> lexicalValidator = value -> value.matches( CURIE_REGEX );
3536

37+
private CurieType() {
38+
}
39+
3640
@Override
3741
public Optional<Curie> parseTyped( final String lexicalForm ) {
3842
try {

core/esmf-aspect-meta-model-interface/src/main/java/org/eclipse/esmf/metamodel/datatype/SammXsdType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ private SammXsdType( final Resource dataTypeResource, final XSSimpleType xstype,
250250
G_YEAR, G_MONTH, G_YEAR_MONTH, G_DAY, G_MONTH_DAY, DURATION, YEAR_MONTH_DURATION, DAY_TIME_DURATION,
251251
BYTE, SHORT, INT, LONG, UNSIGNED_BYTE, UNSIGNED_SHORT, UNSIGNED_INT, UNSIGNED_LONG,
252252
POSITIVE_INTEGER, NON_NEGATIVE_INTEGER, NEGATIVE_INTEGER, NON_POSITIVE_INTEGER, HEX_BINARY,
253-
BASE64_BINARY, ANY_URI, RDFLangString.rdfLangString, new CurieType() );
253+
BASE64_BINARY, ANY_URI, RDFLangString.rdfLangString, CurieType.INSTANCE );
254254

255255
public static void setChecking( final boolean checking ) {
256256
SammXsdType.checking = checking;

core/esmf-aspect-model-aas-generator/src/test/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAasGeneratorTest.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import java.nio.charset.StandardCharsets;
2222
import java.util.List;
2323
import java.util.Set;
24-
2524
import javax.xml.XMLConstants;
2625
import javax.xml.transform.stream.StreamSource;
2726
import javax.xml.validation.Schema;

core/esmf-aspect-model-document-generators/pom.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,14 @@
137137
<artifactId>esmf-aspect-model-java-core</artifactId>
138138
<scope>test</scope>
139139
</dependency>
140+
<dependency>
141+
<groupId>org.eclipse.esmf</groupId>
142+
<artifactId>esmf-aspect-model-java-generator</artifactId>
143+
<version>${project.version}</version>
144+
<classifier>tests</classifier>
145+
<type>test-jar</type>
146+
<scope>test</scope>
147+
</dependency>
140148
<dependency>
141149
<groupId>io.swagger.parser.v3</groupId>
142150
<artifactId>swagger-parser</artifactId>

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

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,16 @@
1919
import java.math.BigInteger;
2020
import java.math.MathContext;
2121
import java.math.RoundingMode;
22+
import java.nio.charset.StandardCharsets;
2223
import java.text.DateFormat;
2324
import java.text.SimpleDateFormat;
2425
import java.util.ArrayList;
2526
import java.util.Arrays;
27+
import java.util.Base64;
2628
import java.util.Date;
2729
import java.util.GregorianCalendar;
2830
import java.util.HashMap;
31+
import java.util.HexFormat;
2932
import java.util.LinkedList;
3033
import java.util.List;
3134
import java.util.Locale;
@@ -227,7 +230,7 @@ private boolean isConstrainedCollection( final Characteristic characteristic ) {
227230
return false;
228231
}
229232
final Trait trait = characteristic.as( Trait.class );
230-
return trait.getBaseCharacteristic().is( Collection.class ) && ( !trait.getConstraints().isEmpty() );
233+
return trait.getBaseCharacteristic().is( Collection.class ) && (!trait.getConstraints().isEmpty());
231234
}
232235

233236
private Map<String, Object> transformAbstractEntityProperty( final BasicProperty property, final boolean useModelExampleValue ) {
@@ -296,7 +299,7 @@ private Object getExampleValueOrElseRandom( final BasicProperty property, final
296299

297300
Optional<Characteristic> elementCharacteristics = Optional.empty();
298301
if ( characteristic.is( Collection.class ) ) {
299-
elementCharacteristics = ( (Collection) characteristic ).getElementCharacteristic();
302+
elementCharacteristics = ((Collection) characteristic).getElementCharacteristic();
300303
}
301304
final Characteristic effectiveCharacteristics = elementCharacteristics.orElse( characteristic );
302305

@@ -306,7 +309,7 @@ private Object getExampleValueOrElseRandom( final BasicProperty property, final
306309

307310
return property.getExampleValue()
308311
.map( exampleValue -> exampleValue.as( ScalarValue.class ).getValue() )
309-
.map( value -> value instanceof Curie ? ( (Curie) value ).value() : value )
312+
.map( value -> value instanceof Curie ? ((Curie) value).value() : value )
310313
.orElseGet( () -> generateExampleValue( effectiveCharacteristics ) );
311314
}
312315

@@ -432,7 +435,7 @@ private Type getDataType( final Characteristic characteristic ) {
432435
private Object generateExampleValue( final Characteristic characteristic ) {
433436
final Type dataType = getDataType( characteristic );
434437

435-
if ( !( dataType.is( Scalar.class ) ) ) {
438+
if ( !(dataType.is( Scalar.class )) ) {
436439
throw new IllegalArgumentException( "Example values can only be generated for scalar types." );
437440
}
438441

@@ -452,6 +455,9 @@ private Object generateExampleValue( final Characteristic characteristic ) {
452455
if ( Duration.class.equals( exampleValueType ) ) {
453456
return DatatypeFactory.newDefaultInstance().newDuration( defaultEasyRandom.nextLong() );
454457
}
458+
if ( byte[].class.equals( exampleValueType ) ) {
459+
return getBinaryRandomValue( dataType );
460+
}
455461

456462
if ( characteristic.is( Trait.class ) ) {
457463
final Optional<Object> traitExampleValue = generateExampleValueForTrait( characteristic.as( Trait.class ), exampleValueType,
@@ -487,6 +493,13 @@ private Optional<Object> generateExampleValueForTrait( final Trait trait, final
487493
return Optional.empty();
488494
}
489495

496+
private Object getBinaryRandomValue( final Type dataType ) {
497+
final byte[] value = defaultEasyRandom.nextObject( String.class ).getBytes( StandardCharsets.UTF_8 );
498+
return dataType.getUrn().equals( XSD.base64Binary.getURI() )
499+
? Base64.getEncoder().encodeToString( value )
500+
: HexFormat.of().formatHex( value );
501+
}
502+
490503
private Object getGregorianRandomValue( final Type dataType ) {
491504
final XMLGregorianCalendar randomCalendar = DatatypeFactory.newDefaultInstance()
492505
.newXMLGregorianCalendar( new GregorianCalendar() );
@@ -574,7 +587,7 @@ private Number generateForNumericTypeInRange( final java.lang.reflect.Type value
574587

575588
// narrowing conversion from BigDecimal to double
576589
private double safelyNarrowDown( final Number bound ) {
577-
if ( !( BigDecimal.class.equals( bound.getClass() ) ) ) {
590+
if ( !(BigDecimal.class.equals( bound.getClass() )) ) {
578591
return bound.doubleValue();
579592
}
580593

@@ -583,7 +596,7 @@ private double safelyNarrowDown( final Number bound ) {
583596
// Example: xsd:unsignedLong has a max. value of 18446744073709551615; when converting it to double
584597
// it will get represented as 1.8446744073709552E16, thereby exceeding the upper bound.
585598
// Therefore we need to take care of always rounding down when narrowing to double.
586-
final BigDecimal narrowed = ( (BigDecimal) bound ).round( new MathContext( 15, RoundingMode.DOWN ) );
599+
final BigDecimal narrowed = ((BigDecimal) bound).round( new MathContext( 15, RoundingMode.DOWN ) );
587600
return narrowed.doubleValue();
588601
}
589602

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

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,19 @@
1313
package org.eclipse.esmf.aspectmodel.generator.json;
1414

1515
import static org.assertj.core.api.Assertions.assertThat;
16+
import static org.assertj.core.api.Assertions.assertThatCode;
1617

18+
import java.io.ByteArrayOutputStream;
1719
import java.io.IOException;
1820
import java.io.Serial;
1921
import java.math.BigDecimal;
2022
import java.math.BigInteger;
23+
import java.nio.charset.StandardCharsets;
2124
import java.util.ArrayList;
2225
import java.util.Arrays;
2326
import java.util.Collection;
2427
import java.util.Iterator;
28+
import java.util.LinkedHashMap;
2529
import java.util.List;
2630
import java.util.Locale;
2731
import java.util.Map;
@@ -32,6 +36,7 @@
3236
import java.util.stream.DoubleStream;
3337
import java.util.stream.IntStream;
3438
import java.util.stream.LongStream;
39+
import java.util.stream.Stream;
3540
import javax.xml.datatype.DatatypeConfigurationException;
3641
import javax.xml.datatype.DatatypeFactory;
3742

@@ -76,6 +81,10 @@
7681
import org.eclipse.esmf.aspectmodel.generator.json.testclasses.NestedEntity;
7782
import org.eclipse.esmf.aspectmodel.generator.json.testclasses.TestEntityWithSimpleTypes;
7883
import org.eclipse.esmf.aspectmodel.jackson.AspectModelJacksonModule;
84+
import org.eclipse.esmf.aspectmodel.java.JavaCodeGenerationConfig;
85+
import org.eclipse.esmf.aspectmodel.java.JavaCodeGenerationConfigBuilder;
86+
import org.eclipse.esmf.aspectmodel.java.QualifiedName;
87+
import org.eclipse.esmf.aspectmodel.java.pojo.AspectModelJavaGenerator;
7988
import org.eclipse.esmf.aspectmodel.loader.MetaModelBaseAttributes;
8089
import org.eclipse.esmf.aspectmodel.urn.AspectModelUrn;
8190
import org.eclipse.esmf.metamodel.Aspect;
@@ -99,7 +108,9 @@
99108
import org.eclipse.esmf.test.TestAspect;
100109
import org.eclipse.esmf.test.TestModel;
101110
import org.eclipse.esmf.test.TestResources;
111+
import org.eclipse.esmf.test.shared.compiler.JavaCompiler;
102112

113+
import com.fasterxml.jackson.core.JsonParser;
103114
import com.fasterxml.jackson.databind.ObjectMapper;
104115
import com.fasterxml.jackson.databind.SerializationFeature;
105116
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
@@ -116,9 +127,11 @@
116127
import org.junit.jupiter.api.Test;
117128
import org.junit.jupiter.params.ParameterizedTest;
118129
import org.junit.jupiter.params.provider.Arguments;
130+
import org.junit.jupiter.params.provider.EnumSource;
119131
import org.junit.jupiter.params.provider.MethodSource;
120132

121133
public class AspectModelJsonPayloadGeneratorTest {
134+
private static final String PACKAGE = "org.eclipse.esmf.test.generatedtestclasses";
122135
private static DatatypeFactory datatypeFactory;
123136

124137
@BeforeAll
@@ -130,6 +143,51 @@ static void setup() {
130143
}
131144
}
132145

146+
@ParameterizedTest
147+
@EnumSource( value = TestAspect.class, mode = EnumSource.Mode.EXCLUDE, names = {
148+
"MODEL_WITH_BROKEN_CYCLES"
149+
} )
150+
public void testDeserializationForGeneratedJson( final TestAspect testAspect ) throws IOException, InterruptedException {
151+
final Aspect aspect = TestResources.load( testAspect ).aspect();
152+
final JavaCompiler.CompilationResult compilationResult = compile( aspect );
153+
154+
final Class<?> aspectClass = compilationResult.compilationUnits().entrySet().stream()
155+
.filter( entry -> entry.getKey().getClassName().equals( aspect.getName() ) )
156+
.map( Map.Entry::getValue )
157+
.findFirst()
158+
.orElseThrow();
159+
assertThatCode( () -> {
160+
final String payload = new AspectModelJsonPayloadGenerator( aspect ).generateJson();
161+
final ObjectMapper mapper = objectMapper();
162+
mapper.setTypeFactory( mapper.getTypeFactory().withClassLoader( compilationResult.classLoader() ) );
163+
mapper.readValue( payload, aspectClass );
164+
} ).doesNotThrowAnyException();
165+
}
166+
167+
private JavaCompiler.CompilationResult compile( final Aspect aspect ) {
168+
final JavaCodeGenerationConfig config = JavaCodeGenerationConfigBuilder.builder()
169+
.packageName( PACKAGE )
170+
.enableJacksonAnnotations( true )
171+
.executeLibraryMacros( false )
172+
.build();
173+
final AspectModelJavaGenerator codeGenerator = new AspectModelJavaGenerator( aspect, config );
174+
final Map<QualifiedName, ByteArrayOutputStream> outputs = new LinkedHashMap<>();
175+
codeGenerator.generate( name -> outputs.computeIfAbsent( name, name2 -> new ByteArrayOutputStream() ) );
176+
177+
final Map<QualifiedName, String> sources = new LinkedHashMap<>();
178+
final List<QualifiedName> loadOrder = new ArrayList<>();
179+
for ( final Map.Entry<QualifiedName, ByteArrayOutputStream> entry : outputs.entrySet() ) {
180+
loadOrder.add( entry.getKey() );
181+
sources.put( entry.getKey(), entry.getValue().toString( StandardCharsets.UTF_8 ) );
182+
}
183+
184+
final List<String> referencedClasses = Stream
185+
.concat( codeGenerator.getConfig().importTracker().getUsedImports().stream(),
186+
codeGenerator.getConfig().importTracker().getUsedStaticImports().stream() )
187+
.collect( Collectors.toList() );
188+
return JavaCompiler.compile( loadOrder, sources, referencedClasses );
189+
}
190+
133191
@Test
134192
public void testGenerateJsonForAspectWithCollectionOfEntities() throws IOException {
135193
final String generatedJson = generateJsonForModel( TestAspect.ASPECT_WITH_ENTITY_LIST );
@@ -613,14 +671,19 @@ private void assertTestEntityWithSimpleTypes( final TestEntityWithSimpleTypes te
613671
assertThat( testEntityWithSimpleTypes.getTestString() ).isEqualTo( "Example Value Test" );
614672
}
615673

616-
private <T> T parseJson( final String json, final Class<T> targetClass ) throws IOException {
674+
private ObjectMapper objectMapper() {
617675
final ObjectMapper mapper = new ObjectMapper();
618676
mapper.registerModule( new JavaTimeModule() );
619677
mapper.registerModule( new Jdk8Module() );
620678
mapper.registerModule( new AspectModelJacksonModule() );
679+
mapper.configure( JsonParser.Feature.INCLUDE_SOURCE_IN_LOCATION, true );
621680
mapper.configure( SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false );
622681
mapper.configure( SerializationFeature.FAIL_ON_EMPTY_BEANS, false );
623-
return mapper.readValue( json, targetClass );
682+
return mapper;
683+
}
684+
685+
private <T> T parseJson( final String json, final Class<T> targetClass ) throws IOException {
686+
return objectMapper().readValue( json, targetClass );
624687
}
625688

626689
// combination of all numeric meta model types with various range types

core/esmf-aspect-model-jackson/src/main/java/org/eclipse/esmf/aspectmodel/jackson/AspectModelJacksonModule.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import javax.xml.datatype.XMLGregorianCalendar;
1717

18+
import org.eclipse.esmf.metamodel.datatype.Curie;
1819
import org.eclipse.esmf.metamodel.datatype.LangString;
1920

2021
import com.fasterxml.jackson.databind.module.SimpleModule;
@@ -32,7 +33,9 @@ public AspectModelJacksonModule() {
3233
addDeserializer( byte[].class, HexBinaryDeserializer.INSTANCE );
3334
addSerializer( byte[].class, Base64BinarySerializer.INSTANCE );
3435
addDeserializer( byte[].class, Base64BinaryDeserializer.INSTANCE );
35-
addDeserializer( LangString.class, LangStringDeserializer.INSTANCE );
3636
addSerializer( LangString.class, LangStringSerializer.INSTANCE );
37+
addDeserializer( LangString.class, LangStringDeserializer.INSTANCE );
38+
addSerializer( Curie.class, CurieSerializer.INSTANCE );
39+
addDeserializer( Curie.class, CurieDeserializer.INSTANCE );
3740
}
3841
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
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.jackson;
15+
16+
import java.io.IOException;
17+
import java.io.Serial;
18+
import java.util.Optional;
19+
20+
import org.eclipse.esmf.metamodel.datatype.Curie;
21+
import org.eclipse.esmf.metamodel.datatype.CurieType;
22+
23+
import com.fasterxml.jackson.core.JacksonException;
24+
import com.fasterxml.jackson.core.JsonParser;
25+
import com.fasterxml.jackson.core.JsonTokenId;
26+
import com.fasterxml.jackson.databind.DeserializationContext;
27+
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
28+
29+
public class CurieDeserializer extends StdDeserializer<Curie> {
30+
@Serial
31+
private static final long serialVersionUID = 1285377288430239636L;
32+
public static final CurieDeserializer INSTANCE = new CurieDeserializer();
33+
34+
private CurieDeserializer() {
35+
super( Curie.class );
36+
}
37+
38+
@Override
39+
public Curie deserialize( final JsonParser parser, final DeserializationContext context ) throws IOException, JacksonException {
40+
if ( parser.currentTokenId() == JsonTokenId.ID_STRING ) {
41+
final Optional<Curie> value = CurieType.INSTANCE.parseTyped( parser.getText() );
42+
if ( value.isPresent() ) {
43+
return value.get();
44+
}
45+
}
46+
47+
return (Curie) context.handleUnexpectedToken( Curie.class, parser );
48+
}
49+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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.jackson;
15+
16+
import java.io.IOException;
17+
import java.io.Serial;
18+
19+
import org.eclipse.esmf.metamodel.datatype.Curie;
20+
import org.eclipse.esmf.metamodel.datatype.CurieType;
21+
22+
import com.fasterxml.jackson.core.JsonGenerator;
23+
import com.fasterxml.jackson.databind.SerializerProvider;
24+
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
25+
26+
public class CurieSerializer extends StdSerializer<Curie> {
27+
@Serial
28+
private static final long serialVersionUID = -6772194217411185019L;
29+
public static final CurieSerializer INSTANCE = new CurieSerializer();
30+
31+
private CurieSerializer() {
32+
super( Curie.class );
33+
}
34+
35+
@Override
36+
public void serialize( final Curie value, final JsonGenerator generator, final SerializerProvider provider ) throws IOException {
37+
generator.writeString( CurieType.INSTANCE.unparseTyped( value ) );
38+
}
39+
}

0 commit comments

Comments
 (0)