Skip to content

Commit 87fa052

Browse files
committed
Fix problems with JSON payload generation.
1 parent 78de46f commit 87fa052

File tree

11 files changed

+335
-31
lines changed

11 files changed

+335
-31
lines changed

core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/loader/Instantiator.java

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,9 @@
3434
import org.apache.jena.rdf.model.Statement;
3535
import org.apache.jena.vocabulary.RDF;
3636
import org.apache.jena.vocabulary.RDFS;
37-
38-
import org.eclipse.esmf.aspectmodel.vocabulary.SAMM;
39-
import org.eclipse.esmf.samm.KnownVersion;
4037
import org.eclipse.esmf.aspectmodel.resolver.services.ExtendedXsdDataType;
4138
import org.eclipse.esmf.aspectmodel.urn.AspectModelUrn;
39+
import org.eclipse.esmf.aspectmodel.vocabulary.SAMM;
4240
import org.eclipse.esmf.aspectmodel.vocabulary.SAMMC;
4341
import org.eclipse.esmf.aspectmodel.vocabulary.UNIT;
4442
import org.eclipse.esmf.metamodel.AbstractEntity;
@@ -53,10 +51,11 @@
5351
import org.eclipse.esmf.metamodel.Type;
5452
import org.eclipse.esmf.metamodel.Value;
5553
import org.eclipse.esmf.metamodel.datatypes.LangString;
56-
import org.eclipse.esmf.metamodel.impl.DefaultScalarValue;
5754
import org.eclipse.esmf.metamodel.impl.DefaultCollectionValue;
5855
import org.eclipse.esmf.metamodel.impl.DefaultEntityInstance;
5956
import org.eclipse.esmf.metamodel.impl.DefaultScalar;
57+
import org.eclipse.esmf.metamodel.impl.DefaultScalarValue;
58+
import org.eclipse.esmf.samm.KnownVersion;
6059

6160
public abstract class Instantiator<T extends ModelElement> extends AttributeValueRetriever implements Function<Resource, T> {
6261
protected final ModelElementFactory modelElementFactory;
@@ -223,9 +222,7 @@ private ScalarValue buildScalarValue( final Literal literal ) {
223222
// but _not_ org.eclipse.esmf.metamodel.datatypes.LangString as we would like to.
224223
// 3. So we construct an instance of LangString here from the RDFLangString.
225224
if ( literal.getDatatypeURI().equals( RDF.langString.getURI() ) ) {
226-
final LangString langString = new LangString( literal.getString(), Locale.forLanguageTag( literal.getLanguage() ) );
227-
final Scalar type = new DefaultScalar( RDF.langString.getURI(), metaModelVersion );
228-
return new DefaultScalarValue( langString, type );
225+
return buildLanguageString( literal );
229226
}
230227

231228
return Stream.concat( ExtendedXsdDataType.supportedXsdTypes.stream(), Stream.of( curieDataType ) )
@@ -236,6 +233,12 @@ private ScalarValue buildScalarValue( final Literal literal ) {
236233
.orElseThrow( () -> new AspectLoadingException( "Literal can not be parsed: " + literal ) );
237234
}
238235

236+
protected ScalarValue buildLanguageString( final Literal literal ) {
237+
final LangString langString = new LangString( literal.getString(), Locale.forLanguageTag( literal.getLanguage() ) );
238+
final Scalar type = new DefaultScalar( RDF.langString.getURI(), metaModelVersion );
239+
return new DefaultScalarValue( langString, type );
240+
}
241+
239242
private CollectionValue buildCollectionValue( final RDFList list, final CollectionValue.CollectionType collectionType,
240243
final Optional<Resource> elementCharacteristic, final Type elementType ) {
241244
final java.util.Collection<Value> values = createEmptyCollectionForType( collectionType );

core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/loader/instantiator/PropertyInstantiator.java

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,10 @@
1818
import java.util.Optional;
1919

2020
import org.apache.jena.datatypes.BaseDatatype;
21+
import org.apache.jena.rdf.model.Literal;
2122
import org.apache.jena.rdf.model.Resource;
2223
import org.apache.jena.rdf.model.Statement;
2324
import org.apache.jena.vocabulary.RDF;
24-
25-
import org.eclipse.esmf.samm.KnownVersion;
2625
import org.eclipse.esmf.aspectmodel.resolver.exceptions.InvalidModelException;
2726
import org.eclipse.esmf.metamodel.Characteristic;
2827
import org.eclipse.esmf.metamodel.Property;
@@ -35,6 +34,7 @@
3534
import org.eclipse.esmf.metamodel.loader.Instantiator;
3635
import org.eclipse.esmf.metamodel.loader.MetaModelBaseAttributes;
3736
import org.eclipse.esmf.metamodel.loader.ModelElementFactory;
37+
import org.eclipse.esmf.samm.KnownVersion;
3838

3939
public class PropertyInstantiator extends Instantiator<Property> {
4040
private final Characteristic fallbackCharacteristic;
@@ -81,18 +81,22 @@ public Property apply( final Resource property ) {
8181
}
8282
return type.as( Scalar.class );
8383
} )
84-
.map( type -> {
85-
final Object literal = statement.getLiteral().getValue();
86-
final Object value = literal instanceof BaseDatatype.TypedValue
87-
? statement.getLiteral().getLexicalForm()
88-
: literal;
89-
return new DefaultScalarValue( value, type );
90-
} ) );
84+
.map( type -> buildScalarValue( statement.getLiteral(), type ) ) );
9185

9286
defProperty = new DefaultProperty( metaModelBaseAttributes, Optional.of( characteristic ), exampleValue, isOptional,
9387
isNotInPayload, payloadName, isAbstract, extends_ );
9488
}
9589
defaultPropertyWrapper.setProperty( defProperty );
9690
return defaultPropertyWrapper;
9791
}
92+
93+
private ScalarValue buildScalarValue( final Literal literal, final Scalar type ) {
94+
final Object literalValue = literal.getValue();
95+
if ( literalValue instanceof BaseDatatype.TypedValue ) {
96+
return new DefaultScalarValue( literal.getLexicalForm(), type );
97+
} else if ( literal.getDatatypeURI().equals( RDF.langString.getURI() ) ) {
98+
return buildLanguageString( literal );
99+
}
100+
return new DefaultScalarValue( literalValue, type );
101+
}
98102
}

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

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -220,10 +220,21 @@ private Map<String, Object> transformCollectionProperty( final BasicProperty pro
220220
if ( characteristic.is( Collection.class ) ) {
221221
final List<Object> collectionValues = getCollectionValues( property, (Collection) characteristic );
222222
return toMap( property.getName(), collectionValues );
223+
} else if ( isConstrainedCollection( characteristic ) ) {
224+
return toMap( property.getName(), getCollectionValues( property, characteristic.as( Trait.class ).getBaseCharacteristic().as( Collection.class ) ) );
223225
}
224226
return ImmutableMap.of();
225227
}
226228

229+
private boolean isConstrainedCollection( final Characteristic characteristic ) {
230+
if ( !characteristic.is( Trait.class ) ) {
231+
return false;
232+
}
233+
final Trait trait = characteristic.as( Trait.class );
234+
return trait.getBaseCharacteristic().is( Collection.class ) && (trait.getConstraints().size() == 1) &&
235+
trait.getConstraints().get( 0 ).is( LengthConstraint.class );
236+
}
237+
227238
private Map<String, Object> transformAbstractEntityProperty( final BasicProperty property ) {
228239
final Optional<AbstractEntity> dataType = getForCharacteristic( property.getCharacteristic(), AbstractEntity.class );
229240
if ( dataType.isPresent() ) {
@@ -314,7 +325,8 @@ private List<Object> getCollectionValues( final BasicProperty property, final Co
314325
return ImmutableList.of( transformProperties( entity.getAllProperties() ) );
315326
}
316327
if ( dataType.is( Scalar.class ) ) {
317-
return ImmutableList.of( getExampleValueOrElseRandom( property ) );
328+
final Object payload = getExampleValueOrElseRandom( property );
329+
return payload instanceof List ? (List) payload : ImmutableList.of( payload );
318330
}
319331
throw new IllegalArgumentException( String.format( "DataType %s is unknown", dataType ) );
320332
}
@@ -488,21 +500,22 @@ private Object getRandomValue( final LengthConstraint lengthConstraint,
488500
final BigInteger maxLength = lengthConstraint.getMaxValue().orElse( BigInteger.valueOf( Integer.MAX_VALUE ) );
489501
final BigInteger minLength = lengthConstraint.getMinValue().orElse( BigInteger.ZERO );
490502

491-
final EasyRandomParameters easyRandomParameters = new EasyRandomParameters().stringLengthRange( minLength.intValue(), maxLength.intValue() );
492-
final EasyRandom easyRandom = new EasyRandom( easyRandomParameters );
493503
if ( traitBaseCharacteristic.is( Collection.class ) ) {
494504
final List<Object> returnValues = new ArrayList<>();
495505
// Fill in minLength elements
496506
for ( int i = 0; i < minLength.intValue(); i++ ) {
497-
returnValues.add( easyRandom.nextObject( (Class<?>) exampleValueType ) );
507+
returnValues.add( defaultEasyRandom.nextObject( (Class<?>) exampleValueType ) );
498508
}
499509
// Add between minLength and maxLength-minLength elements, but not more than 5
500510
final int amount = getRandomInteger( minLength.intValue(), Math.min( maxLength.intValue() - minLength.intValue(), 5 ) );
501511
for ( int i = 0; i < amount; i++ ) {
502-
returnValues.add( easyRandom.nextObject( (Class<?>) exampleValueType ) );
512+
returnValues.add( defaultEasyRandom.nextObject( (Class<?>) exampleValueType ) );
503513
}
504514
return returnValues;
505515
}
516+
517+
final EasyRandomParameters easyRandomParameters = new EasyRandomParameters().stringLengthRange( minLength.intValue(), maxLength.intValue() );
518+
final EasyRandom easyRandom = new EasyRandom( easyRandomParameters );
506519
return easyRandom.nextObject( (Class<?>) exampleValueType );
507520
}
508521

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

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import org.eclipse.esmf.aspectmodel.generator.json.testclasses.AspectWithCollectionOfSimpleType;
5252
import org.eclipse.esmf.aspectmodel.generator.json.testclasses.AspectWithCollectionWithAbstractEntity;
5353
import org.eclipse.esmf.aspectmodel.generator.json.testclasses.AspectWithComplexEntityCollectionEnum;
54+
import org.eclipse.esmf.aspectmodel.generator.json.testclasses.AspectWithConstrainedSet;
5455
import org.eclipse.esmf.aspectmodel.generator.json.testclasses.AspectWithConstraintProperties;
5556
import org.eclipse.esmf.aspectmodel.generator.json.testclasses.AspectWithConstraints;
5657
import org.eclipse.esmf.aspectmodel.generator.json.testclasses.AspectWithCurie;
@@ -65,6 +66,7 @@
6566
import org.eclipse.esmf.aspectmodel.generator.json.testclasses.AspectWithGTypeForRangeConstraints;
6667
import org.eclipse.esmf.aspectmodel.generator.json.testclasses.AspectWithGenericNumericProperty;
6768
import org.eclipse.esmf.aspectmodel.generator.json.testclasses.AspectWithMultiLanguageText;
69+
import org.eclipse.esmf.aspectmodel.generator.json.testclasses.AspectWithMultilanguageExampleValue;
6870
import org.eclipse.esmf.aspectmodel.generator.json.testclasses.AspectWithMultipleCollectionsOfSimpleType;
6971
import org.eclipse.esmf.aspectmodel.generator.json.testclasses.AspectWithMultipleEntities;
7072
import org.eclipse.esmf.aspectmodel.generator.json.testclasses.AspectWithMultipleEntitiesAndEither;
@@ -347,6 +349,17 @@ public void testGenerateAspectWithMultiLanguageText( final KnownVersion metaMode
347349
assertThat( aspectWithMultiLanguageText.getProp() ).has( isEnglishLangString );
348350
}
349351

352+
@ParameterizedTest
353+
@MethodSource( "allVersions" )
354+
public void testGenerateAspectWithMultiLanguageExampleValue( final KnownVersion metaModelVersion ) throws IOException {
355+
final String generatedJson = generateJsonForModel( TestAspect.ASPECT_WITH_MULTILANGUAGE_EXAMPLE_VALUE, metaModelVersion );
356+
final AspectWithMultilanguageExampleValue aspectWithMultiLanguageText = parseJson( generatedJson, AspectWithMultilanguageExampleValue.class );
357+
final Condition<LangString> isGermanLangString = new Condition<>( l -> l.getLanguageTag().equals( Locale.GERMAN ), "is german" );
358+
assertThat( aspectWithMultiLanguageText.getProp() ).has( isGermanLangString );
359+
final Condition<LangString> text = new Condition<>( l -> l.getValue().equals( "Multilanguage example value." ), "is equal" );
360+
assertThat( aspectWithMultiLanguageText.getProp() ).has( text );
361+
}
362+
350363
@ParameterizedTest
351364
@MethodSource( "allVersions" )
352365
public void testGenerateAspectWithConstraint( final KnownVersion metaModelVersion ) throws IOException {
@@ -583,6 +596,14 @@ public void testGenerateJsonForAspectWithAbstractSingleEntity( final KnownVersio
583596
assertThat( extendingTestEntity.getEntityProperty() ).isNotBlank();
584597
}
585598

599+
@ParameterizedTest
600+
@MethodSource( "allVersions" )
601+
void testGenerateJsonForAspectWithConstrainedSetProperty( final KnownVersion metaModelVersion ) throws IOException {
602+
final String generatedJson = generateJsonForModel( TestAspect.ASPECT_WITH_CONSTRAINED_SET, metaModelVersion );
603+
final AspectWithConstrainedSet aspectWithConstrainedSet = parseJson( generatedJson, AspectWithConstrainedSet.class );
604+
assertThat( aspectWithConstrainedSet.getTestProperty() ).hasSizeGreaterThan( 0 );
605+
}
606+
586607
private String generateJsonForModel( final TestAspect model, final KnownVersion testedVersion ) {
587608
final VersionedModel versionedModel = TestResources.getModel( model, testedVersion ).get();
588609
final Aspect aspect = AspectModelLoader.getSingleAspectUnchecked( versionedModel );
@@ -619,16 +640,16 @@ private <T> T parseJson( final String json, final Class<T> targetClass ) throws
619640
private static List<Arguments> rangeTestSource() {
620641
final List<Arguments> result = new ArrayList<>();
621642
Lists.cartesianProduct( getMetaModelNumericTypes(), RANGE_CONSTRAINTS_TO_TEST )
622-
.forEach( list -> result.add( Arguments.of( list.get( 0 ), list.get( 1 ) ) ) );
643+
.forEach( list -> result.add( Arguments.of( list.get( 0 ), list.get( 1 ) ) ) );
623644
return result;
624645
}
625646

626647
private static List<RDFDatatype> getMetaModelNumericTypes() {
627648
return DataType.getAllSupportedTypes()
628-
.stream()
629-
.filter( dataType -> dataType.getJavaClass() != null )
630-
.filter( dataType -> Number.class.isAssignableFrom( dataType.getJavaClass() ) )
631-
.collect( Collectors.toList() );
649+
.stream()
650+
.filter( dataType -> dataType.getJavaClass() != null )
651+
.filter( dataType -> Number.class.isAssignableFrom( dataType.getJavaClass() ) )
652+
.collect( Collectors.toList() );
632653
}
633654

634655
private static final List<Optional<BoundDefinition>> RANGE_CONSTRAINTS_TO_TEST = Arrays.asList(
@@ -681,11 +702,11 @@ private BoundDefinition getMatchingUpperBound( final BoundDefinition boundKind )
681702

682703
Characteristic createBasicCharacteristic( final KnownVersion modelVersion, final Type dataType, final SAMM samm ) {
683704
return new DefaultCharacteristic( MetaModelBaseAttributes.builderFor( "NumberCharacteristic" )
684-
.withMetaModelVersion( modelVersion )
685-
.withUrn( AspectModelUrn.fromUrn( samm.baseCharacteristic().getURI() ) )
686-
.withPreferredName( Locale.forLanguageTag( "en" ), "NumberCharacteristic" )
687-
.withDescription( Locale.forLanguageTag( "en" ), "A simple numeric property." )
688-
.build(),
705+
.withMetaModelVersion( modelVersion )
706+
.withUrn( AspectModelUrn.fromUrn( samm.baseCharacteristic().getURI() ) )
707+
.withPreferredName( Locale.forLanguageTag( "en" ), "NumberCharacteristic" )
708+
.withDescription( Locale.forLanguageTag( "en" ), "A simple numeric property." )
709+
.build(),
689710
Optional.of( dataType ) );
690711
}
691712

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package org.eclipse.esmf.aspectmodel.generator.json.testclasses;
2+
3+
import java.util.Objects;
4+
import java.util.Set;
5+
6+
import javax.validation.constraints.NotNull;
7+
import javax.validation.constraints.Size;
8+
9+
import com.fasterxml.jackson.annotation.JsonCreator;
10+
import com.fasterxml.jackson.annotation.JsonProperty;
11+
12+
/**
13+
* Generated class for Test Aspect. This is a test description
14+
*/
15+
public class AspectWithConstrainedSet {
16+
17+
@NotNull
18+
@Size( min = 1 )
19+
20+
private Set<String> testProperty;
21+
22+
@JsonCreator
23+
public AspectWithConstrainedSet( @JsonProperty( value = "testProperty" ) final Set<String> testProperty ) {
24+
super(
25+
26+
);
27+
this.testProperty = testProperty;
28+
}
29+
30+
/**
31+
* Returns Test Property
32+
*
33+
* @return {@link #testProperty}
34+
*/
35+
public Set<String> getTestProperty() {
36+
return testProperty;
37+
}
38+
39+
@Override
40+
public boolean equals( final Object o ) {
41+
if ( this == o ) {
42+
return true;
43+
}
44+
if ( o == null || getClass() != o.getClass() ) {
45+
return false;
46+
}
47+
48+
final AspectWithConstrainedSet that = (AspectWithConstrainedSet) o;
49+
return Objects.equals( testProperty, that.testProperty );
50+
}
51+
52+
@Override
53+
public int hashCode() {
54+
return Objects.hash( testProperty );
55+
}
56+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package org.eclipse.esmf.aspectmodel.generator.json.testclasses;
2+
3+
import java.util.Objects;
4+
5+
import javax.validation.constraints.NotNull;
6+
7+
import org.eclipse.esmf.metamodel.datatypes.LangString;
8+
9+
import com.fasterxml.jackson.annotation.JsonCreator;
10+
import com.fasterxml.jackson.annotation.JsonProperty;
11+
12+
/**
13+
* Generated class for AspectWithMultilanguageExampleValue.
14+
*
15+
*/
16+
public class AspectWithMultilanguageExampleValue {
17+
18+
@NotNull
19+
private LangString prop;
20+
21+
@JsonCreator
22+
public AspectWithMultilanguageExampleValue( @JsonProperty( value = "prop" ) final LangString prop ) {
23+
super(
24+
25+
);
26+
this.prop = prop;
27+
}
28+
29+
/**
30+
* Returns prop
31+
*
32+
* @return {@link #prop}
33+
*/
34+
public LangString getProp() {
35+
return prop;
36+
}
37+
38+
@Override
39+
public boolean equals( final Object o ) {
40+
if ( this == o ) {
41+
return true;
42+
}
43+
if ( o == null || getClass() != o.getClass() ) {
44+
return false;
45+
}
46+
47+
final AspectWithMultilanguageExampleValue that = (AspectWithMultilanguageExampleValue) o;
48+
return Objects.equals( prop, that.prop );
49+
}
50+
51+
@Override
52+
public int hashCode() {
53+
return Objects.hash( prop );
54+
}
55+
}

core/esmf-test-aspect-models/src/main/java/org/eclipse/esmf/test/TestAspect.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,9 @@ public enum TestAspect implements TestModel {
193193
MODEL_WITH_CYCLES,
194194
MODEL_WITH_BROKEN_CYCLES,
195195

196+
ASPECT_WITH_CONSTRAINED_SET,
197+
ASPECT_WITH_MULTILANGUAGE_EXAMPLE_VALUE,
198+
196199
MODEL_WITH_BLANK_AND_ADDITIONAL_NODES;
197200

198201
@Override

0 commit comments

Comments
 (0)