From 9e9b918f2c9f5068162a02729e4e715d93093ca4 Mon Sep 17 00:00:00 2001 From: "Textor Andreas (BCI/ESW17)" Date: Fri, 3 Nov 2023 10:56:52 +0100 Subject: [PATCH 1/5] Make GraalVM js-scriptengine an explicit validator dependency --- core/esmf-aspect-model-validator/pom.xml | 4 ++++ tools/samm-cli/pom.xml | 5 ----- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/core/esmf-aspect-model-validator/pom.xml b/core/esmf-aspect-model-validator/pom.xml index e94a6bbab..9206d1600 100644 --- a/core/esmf-aspect-model-validator/pom.xml +++ b/core/esmf-aspect-model-validator/pom.xml @@ -52,6 +52,10 @@ org.graalvm.js js + + org.graalvm.js + js-scriptengine + org.projectlombok lombok diff --git a/tools/samm-cli/pom.xml b/tools/samm-cli/pom.xml index 91bc920d7..5005ffb2e 100644 --- a/tools/samm-cli/pom.xml +++ b/tools/samm-cli/pom.xml @@ -80,11 +80,6 @@ org.graalvm.js js - - org.graalvm.js - js-scriptengine - ${graalvm-version} - From 7861f7b973adeb352ad0d2cb9f086c929b8d1700 Mon Sep 17 00:00:00 2001 From: "Textor Andreas (BCI/ESW17)" Date: Fri, 3 Nov 2023 10:57:21 +0100 Subject: [PATCH 2/5] Add test model with custom quantity kind declaration --- .../org/eclipse/esmf/test/TestAspect.java | 1 + .../AspectWithCustomUnitAndQuantityKind.ttl | 35 +++++++++++++++++++ .../AspectWithCustomUnitAndQuantityKind.ttl | 35 +++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 core/esmf-test-aspect-models/src/main/resources/valid/samm_2_0_0/org.eclipse.esmf.test/1.0.0/AspectWithCustomUnitAndQuantityKind.ttl create mode 100644 core/esmf-test-aspect-models/src/main/resources/valid/samm_2_1_0/org.eclipse.esmf.test/1.0.0/AspectWithCustomUnitAndQuantityKind.ttl diff --git a/core/esmf-test-aspect-models/src/main/java/org/eclipse/esmf/test/TestAspect.java b/core/esmf-test-aspect-models/src/main/java/org/eclipse/esmf/test/TestAspect.java index d3aaa1003..a1160f051 100644 --- a/core/esmf-test-aspect-models/src/main/java/org/eclipse/esmf/test/TestAspect.java +++ b/core/esmf-test-aspect-models/src/main/java/org/eclipse/esmf/test/TestAspect.java @@ -57,6 +57,7 @@ public enum TestAspect implements TestModel { ASPECT_WITH_CURIE_ENUMERATION, ASPECT_WITH_CUSTOM_NAMESPACE, ASPECT_WITH_CUSTOM_UNIT, + ASPECT_WITH_CUSTOM_UNIT_AND_QUANTITY_KIND, ASPECT_WITH_DATE_TIME_TYPE_FOR_RANGE_CONSTRAINTS, ASPECT_WITH_DESCRIPTIONS, ASPECT_WITH_DESCRIPTION_IN_PROPERTY, diff --git a/core/esmf-test-aspect-models/src/main/resources/valid/samm_2_0_0/org.eclipse.esmf.test/1.0.0/AspectWithCustomUnitAndQuantityKind.ttl b/core/esmf-test-aspect-models/src/main/resources/valid/samm_2_0_0/org.eclipse.esmf.test/1.0.0/AspectWithCustomUnitAndQuantityKind.ttl new file mode 100644 index 000000000..86f028e99 --- /dev/null +++ b/core/esmf-test-aspect-models/src/main/resources/valid/samm_2_0_0/org.eclipse.esmf.test/1.0.0/AspectWithCustomUnitAndQuantityKind.ttl @@ -0,0 +1,35 @@ +# Copyright (c) 2023 Robert Bosch Manufacturing Solutions GmbH +# +# See the AUTHORS file(s) distributed with this work for additional +# information regarding authorship. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 + +@prefix : . +@prefix samm: . +@prefix samm-c: . +@prefix xsd: . +@prefix unit: . + +:AspectWithCustomUnitAndQuantityKind a samm:Aspect ; + samm:properties ( :emissions ) ; + samm:operations ( ) . + +:emissions a samm:Property ; + samm:characteristic :Emissions . + +:Emissions a samm-c:Quantifiable ; + samm:dataType xsd:int ; + samm-c:unit :gCO2eqPerkWh . + +:gCO2eqPerkWh a samm:Unit ; + samm:preferredName "gram CO₂ equivalent per kWh"@en ; + samm:quantityKind :greenhouseGasEmissions ; + samm:symbol "gCO₂eq/kWh" . + +:greenhouseGasEmissions a samm:QuantityKind ; + samm:preferredName "greenhouse gas emissions"@en . \ No newline at end of file diff --git a/core/esmf-test-aspect-models/src/main/resources/valid/samm_2_1_0/org.eclipse.esmf.test/1.0.0/AspectWithCustomUnitAndQuantityKind.ttl b/core/esmf-test-aspect-models/src/main/resources/valid/samm_2_1_0/org.eclipse.esmf.test/1.0.0/AspectWithCustomUnitAndQuantityKind.ttl new file mode 100644 index 000000000..dc5bab87a --- /dev/null +++ b/core/esmf-test-aspect-models/src/main/resources/valid/samm_2_1_0/org.eclipse.esmf.test/1.0.0/AspectWithCustomUnitAndQuantityKind.ttl @@ -0,0 +1,35 @@ +# Copyright (c) 2023 Robert Bosch Manufacturing Solutions GmbH +# +# See the AUTHORS file(s) distributed with this work for additional +# information regarding authorship. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 + +@prefix : . +@prefix samm: . +@prefix samm-c: . +@prefix xsd: . +@prefix unit: . + +:AspectWithCustomUnitAndQuantityKind a samm:Aspect ; + samm:properties ( :emissions ) ; + samm:operations ( ) . + +:emissions a samm:Property ; + samm:characteristic :Emissions . + +:Emissions a samm-c:Quantifiable ; + samm:dataType xsd:int ; + samm-c:unit :gCO2eqPerkWh . + +:gCO2eqPerkWh a samm:Unit ; + samm:preferredName "gram CO₂ equivalent per kWh"@en ; + samm:quantityKind :greenhouseGasEmissions ; + samm:symbol "gCO₂eq/kWh" . + +:greenhouseGasEmissions a samm:QuantityKind ; + samm:preferredName "greenhouse gas emissions"@en . \ No newline at end of file From 8a4529d58894ba468ed18d1857a614ede976d5cb Mon Sep 17 00:00:00 2001 From: "Textor Andreas (BCI/ESW17)" Date: Fri, 3 Nov 2023 10:57:47 +0100 Subject: [PATCH 3/5] Fix loading of custom quantity kinds --- .../metamodel/impl/DefaultQuantityKind.java | 73 +++++++++++++++++++ .../metamodel/loader/ModelElementFactory.java | 34 +++++---- 2 files changed, 92 insertions(+), 15 deletions(-) create mode 100644 core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/impl/DefaultQuantityKind.java diff --git a/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/impl/DefaultQuantityKind.java b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/impl/DefaultQuantityKind.java new file mode 100644 index 000000000..36bc00733 --- /dev/null +++ b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/impl/DefaultQuantityKind.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2023 Robert Bosch Manufacturing Solutions GmbH + * + * See the AUTHORS file(s) distributed with this work for additional + * information regarding authorship. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + +package org.eclipse.esmf.metamodel.impl; + +import java.util.Objects; +import java.util.StringJoiner; + +import org.eclipse.esmf.metamodel.QuantityKind; +import org.eclipse.esmf.metamodel.loader.MetaModelBaseAttributes; +import org.eclipse.esmf.metamodel.visitor.AspectVisitor; + +public class DefaultQuantityKind extends ModelElementImpl implements QuantityKind { + private final String label; + + public DefaultQuantityKind( final MetaModelBaseAttributes metaModelBaseAttributes, final String label ) { + super( metaModelBaseAttributes ); + this.label = label; + } + + @Override + public String getLabel() { + return label; + } + + @Override + public boolean equals( final Object o ) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + if ( !super.equals( o ) ) { + return false; + } + final DefaultQuantityKind that = (DefaultQuantityKind) o; + return Objects.equals( label, that.label ); + } + + @Override + public int hashCode() { + return Objects.hash( super.hashCode(), label ); + } + + /** + * Accepts an Aspect visitor + * + * @param visitor The visitor to accept + * @param The result type of the traversal operation + * @param The context of the visitor traversal + */ + @Override + public T accept( final AspectVisitor visitor, final C context ) { + return visitor.visitQuantityKind( this, context ); + } + + @Override + public String toString() { + return new StringJoiner( ", ", DefaultQuantityKind.class.getSimpleName() + "[", "]" ) + .toString(); + } +} diff --git a/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/loader/ModelElementFactory.java b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/loader/ModelElementFactory.java index 9394d77e4..10d4212e6 100644 --- a/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/loader/ModelElementFactory.java +++ b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/loader/ModelElementFactory.java @@ -23,12 +23,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import org.apache.jena.rdf.model.Model; -import org.apache.jena.rdf.model.RDFNode; -import org.apache.jena.rdf.model.Resource; -import org.apache.jena.rdf.model.Statement; -import org.apache.jena.vocabulary.RDF; -import org.apache.jena.vocabulary.RDFS; import org.eclipse.esmf.aspectmodel.urn.AspectModelUrn; import org.eclipse.esmf.aspectmodel.vocabulary.SAMM; import org.eclipse.esmf.aspectmodel.vocabulary.SAMMC; @@ -41,6 +35,7 @@ import org.eclipse.esmf.metamodel.QuantityKinds; import org.eclipse.esmf.metamodel.Unit; import org.eclipse.esmf.metamodel.Units; +import org.eclipse.esmf.metamodel.impl.DefaultQuantityKind; import org.eclipse.esmf.metamodel.impl.DefaultUnit; import org.eclipse.esmf.metamodel.loader.instantiator.AbstractEntityInstantiator; import org.eclipse.esmf.metamodel.loader.instantiator.AspectInstantiator; @@ -76,6 +71,12 @@ import org.eclipse.esmf.samm.KnownVersion; import com.google.common.collect.Streams; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.Statement; +import org.apache.jena.vocabulary.RDF; +import org.apache.jena.vocabulary.RDFS; public class ModelElementFactory extends AttributeValueRetriever { private final KnownVersion metaModelVersion; @@ -86,7 +87,8 @@ public class ModelElementFactory extends AttributeValueRetriever { private final Map loadedElements = new HashMap<>(); private Set namespaces; - public ModelElementFactory( final KnownVersion metaModelVersion, final Model model, final Map> additionalInstantiators ) { + public ModelElementFactory( final KnownVersion metaModelVersion, final Model model, + final Map> additionalInstantiators ) { super( new SAMM( metaModelVersion ) ); this.metaModelVersion = metaModelVersion; this.model = model; @@ -144,7 +146,7 @@ public T create( final Class clazz, final Resource m return (T) findOrCreateUnit( modelElement ); } if ( samm.QuantityKind().equals( targetType ) ) { - return (T) findQuantityKind( modelElement ); + return (T) findOrCreateQuantityKind( modelElement ); } final Instantiator instantiator = (Instantiator) instantiators.get( targetType ); if ( instantiator != null ) { @@ -160,14 +162,15 @@ public T create( final Class clazz, final Resource m final Entity entity = create( Entity.class, targetType ); if ( entity == null ) { throw new AspectLoadingException( "Could not load " + modelElement + ": Expected " + targetType + " to be an Entity" ); - } return (T) new EntityInstanceInstantiator( this, entity ).apply( modelElement ); } - public QuantityKind findQuantityKind( final Resource quantityKindResource ) { - return QuantityKinds.fromName( quantityKindResource.getLocalName() ).orElseThrow( () -> - new AspectLoadingException( "QuantityKind " + quantityKindResource + " is invalid" ) ); + public QuantityKind findOrCreateQuantityKind( final Resource quantityKindResource ) { + final Optional predefinedQuantityKind = QuantityKinds.fromName( quantityKindResource.getLocalName() ); + return predefinedQuantityKind.orElseGet( () -> new DefaultQuantityKind( + MetaModelBaseAttributes.fromModelElement( metaModelVersion, quantityKindResource, model, samm ), + attributeValue( quantityKindResource, samm.preferredName() ).getLiteral().getLexicalForm() ) ); } public Unit findOrCreateUnit( final Resource unitResource ) { @@ -177,15 +180,16 @@ public Unit findOrCreateUnit( final Resource unitResource ) { new AspectLoadingException( "Unit definition for " + unitUrn + " is invalid" ) ); } + final Set quantityKinds = Streams.stream( model.listStatements( unitResource, samm.quantityKind(), (RDFNode) null ) ) + .map( quantityKindStatement -> findOrCreateQuantityKind( quantityKindStatement.getObject().asResource() ) ) + .collect( Collectors.toSet() ); return new DefaultUnit( MetaModelBaseAttributes.fromModelElement( metaModelVersion, unitResource, model, samm ), optionalAttributeValue( unitResource, samm.symbol() ).map( Statement::getString ), optionalAttributeValue( unitResource, samm.commonCode() ).map( Statement::getString ), optionalAttributeValue( unitResource, samm.referenceUnit() ).map( Statement::getResource ).map( Resource::getLocalName ), optionalAttributeValue( unitResource, samm.conversionFactor() ).map( Statement::getString ), - Streams.stream( model.listStatements( unitResource, samm.quantityKind(), (RDFNode) null ) ) - .flatMap( quantityKindStatement -> QuantityKinds.fromName( quantityKindStatement.getObject().asResource().getLocalName() ).stream() ) - .collect( Collectors.toSet() ) ); + quantityKinds ); } private Resource resourceType( final Resource resource ) { From 0f18c2bcef80481e4ecf28d821c559104dd3851e Mon Sep 17 00:00:00 2001 From: "Textor Andreas (BCI/ESW17)" Date: Fri, 3 Nov 2023 10:58:07 +0100 Subject: [PATCH 4/5] Fix RdfModelCreatorVisitor to work with custom quantity kinds --- .../serializer/RdfModelCreatorVisitor.java | 109 +++++++++++------- 1 file changed, 68 insertions(+), 41 deletions(-) diff --git a/core/esmf-aspect-model-serializer/src/main/java/org/eclipse/esmf/aspectmodel/serializer/RdfModelCreatorVisitor.java b/core/esmf-aspect-model-serializer/src/main/java/org/eclipse/esmf/aspectmodel/serializer/RdfModelCreatorVisitor.java index 4360b8a2f..5a0012edc 100644 --- a/core/esmf-aspect-model-serializer/src/main/java/org/eclipse/esmf/aspectmodel/serializer/RdfModelCreatorVisitor.java +++ b/core/esmf-aspect-model-serializer/src/main/java/org/eclipse/esmf/aspectmodel/serializer/RdfModelCreatorVisitor.java @@ -24,20 +24,7 @@ import java.util.Map; import java.util.Optional; import java.util.function.Function; -import java.util.stream.Collectors; -import org.apache.jena.datatypes.RDFDatatype; -import org.apache.jena.rdf.model.Literal; -import org.apache.jena.rdf.model.Model; -import org.apache.jena.rdf.model.ModelFactory; -import org.apache.jena.rdf.model.RDFList; -import org.apache.jena.rdf.model.RDFNode; -import org.apache.jena.rdf.model.Resource; -import org.apache.jena.rdf.model.ResourceFactory; -import org.apache.jena.rdf.model.Statement; -import org.apache.jena.vocabulary.RDF; -import org.apache.jena.vocabulary.XSD; -import org.eclipse.esmf.aspectmodel.resolver.exceptions.InvalidModelException; import org.eclipse.esmf.aspectmodel.resolver.services.DataType; import org.eclipse.esmf.aspectmodel.resolver.services.ExtendedXsdDataType; import org.eclipse.esmf.aspectmodel.urn.AspectModelUrn; @@ -90,9 +77,20 @@ import org.eclipse.esmf.metamodel.visitor.AspectVisitor; import org.eclipse.esmf.samm.KnownVersion; +import org.apache.jena.datatypes.RDFDatatype; +import org.apache.jena.rdf.model.Literal; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.RDFList; +import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.ResourceFactory; +import org.apache.jena.rdf.model.Statement; +import org.apache.jena.vocabulary.RDF; +import org.apache.jena.vocabulary.XSD; + /** * AspectVisitor that translates an {@link Aspect} into the corresponding {@link Model}. - * * The usual usage is calling {@link #visitAspect(Aspect, ModelElement)}. * The context (i.e., the second argument of the visit methods) refers to the parent element in the model graph * traversal. @@ -174,7 +172,8 @@ private Model serializeDescriptions( final Resource elementResource, final Named } @SuppressWarnings( "squid:S2250" ) - // Amount of elements in list is regarding amount of properties in Aspect Model. Even in bigger aspects this should not lead to performance issues + // Amount of elements in list is regarding amount of properties in Aspect Model. Even in bigger aspects this should not lead to + // performance issues private Model serializePropertiesOrParameters( final Resource elementResource, final HasProperties element, final org.apache.jena.rdf.model.Property theProperty ) { final Model model = ModelFactory.createDefaultModel(); @@ -367,10 +366,12 @@ public ElementModel visitLengthConstraint( final LengthConstraint lengthConstrai final Model model = visitConstraint( lengthConstraint, null ).getModel(); final Resource resource = getElementResource( lengthConstraint ); lengthConstraint.getMinValue().stream().map( minValue -> - createStatement( resource, sammc.minValue(), serializeTypedValue( minValue.toString(), ExtendedXsdDataType.NON_NEGATIVE_INTEGER ) ) ) + createStatement( resource, sammc.minValue(), + serializeTypedValue( minValue.toString(), ExtendedXsdDataType.NON_NEGATIVE_INTEGER ) ) ) .forEach( model::add ); lengthConstraint.getMaxValue().stream().map( maxValue -> - createStatement( resource, sammc.maxValue(), serializeTypedValue( maxValue.toString(), ExtendedXsdDataType.NON_NEGATIVE_INTEGER ) ) ) + createStatement( resource, sammc.maxValue(), + serializeTypedValue( maxValue.toString(), ExtendedXsdDataType.NON_NEGATIVE_INTEGER ) ) ) .forEach( model::add ); model.add( resource, RDF.type, sammc.LengthConstraint() ); return new ElementModel( model, Optional.of( resource ) ); @@ -401,7 +402,8 @@ public ElementModel visitRangeConstraint( final RangeConstraint rangeConstraint, } @Override - public ElementModel visitRegularExpressionConstraint( final RegularExpressionConstraint regularExpressionConstraint, final ModelElement context ) { + public ElementModel visitRegularExpressionConstraint( final RegularExpressionConstraint regularExpressionConstraint, + final ModelElement context ) { final Model model = visitConstraint( regularExpressionConstraint, null ).getModel(); final Resource resource = getElementResource( regularExpressionConstraint ); model.add( resource, RDF.type, sammc.RegularExpressionConstraint() ); @@ -466,7 +468,7 @@ public ElementModel visitEnumeration( final Enumeration enumeration, final Model final ElementModel valueElementModel = value.accept( this, enumeration ); model.add( valueElementModel.getModel() ); return valueElementModel.getFocusElement().stream(); - } ).collect( Collectors.toList() ); + } ).toList(); model.add( resource, sammc.values(), model.createList( elements.iterator() ) ); return new ElementModel( model, Optional.of( resource ) ); } @@ -477,7 +479,8 @@ public ElementModel visitEntityInstance( final EntityInstance instance, final Mo final Resource resource = getElementResource( instance ); model.add( resource, RDF.type, getElementResource( instance.getEntityType() ) ); instance.getAssertions().forEach( ( key, value ) -> { - final org.apache.jena.rdf.model.Property property = ResourceFactory.createProperty( key.getAspectModelUrn().orElseThrow().toString() ); + final org.apache.jena.rdf.model.Property property = ResourceFactory.createProperty( + key.getAspectModelUrn().orElseThrow().toString() ); final ElementModel valueElementModel = value.accept( this, instance ); model.add( valueElementModel.getModel() ); valueElementModel.getFocusElement().ifPresent( elementValue -> model.add( resource, property, elementValue ) ); @@ -500,7 +503,8 @@ public ElementModel visitScalarValue( final ScalarValue value, final ModelElemen if ( targetType.isEmpty() || type.getUrn().equals( XSD.xstring.getURI() ) ) { return new ElementModel( model, Optional.of( ResourceFactory.createStringLiteral( value.getValue().toString() ) ) ); } - return new ElementModel( model, Optional.of( ResourceFactory.createTypedLiteral( targetType.get().unparse( value.getValue() ), targetType.get() ) ) ); + return new ElementModel( model, + Optional.of( ResourceFactory.createTypedLiteral( targetType.get().unparse( value.getValue() ), targetType.get() ) ) ); } @Override @@ -510,7 +514,7 @@ public ElementModel visitCollectionValue( final CollectionValue collection, fina final ElementModel valueElementModel = value.accept( this, collection ); model.add( valueElementModel.getModel() ); return valueElementModel.getFocusElement().stream(); - } ).collect( Collectors.toList() ); + } ).toList(); final RDFNode rdfList = model.createList( elements.iterator() ); return new ElementModel( model, Optional.of( rdfList ) ); } @@ -540,8 +544,11 @@ public ElementModel visitMeasurement( final Measurement measurement, final Model final Resource resource = getElementResource( measurement ); model.add( resource, RDF.type, sammc.Measurement() ); - getUnitStatement( measurement, resource ).ifPresent( model::add ); - measurement.getUnit().map( unit -> unit.accept( this, measurement ) ).ifPresent( elementModel -> model.add( elementModel.getModel() ) ); + measurement.getUnit().ifPresent( unit -> { + final ElementModel unitModel = unit.accept( this, measurement ); + model.add( unitModel.getModel() ); + unitModel.getFocusElement().ifPresent( unitResource -> model.add( resource, sammc.unit(), unitResource ) ); + } ); return new ElementModel( model, Optional.of( resource ) ); } @@ -551,8 +558,11 @@ public ElementModel visitQuantifiable( final Quantifiable quantifiable, final Mo final Resource resource = getElementResource( quantifiable ); model.add( resource, RDF.type, sammc.Quantifiable() ); - getUnitStatement( quantifiable, resource ).ifPresent( model::add ); - quantifiable.getUnit().map( unit -> unit.accept( this, quantifiable ) ).ifPresent( elementModel -> model.add( elementModel.getModel() ) ); + quantifiable.getUnit().ifPresent( unit -> { + final ElementModel unitModel = unit.accept( this, quantifiable ); + model.add( unitModel.getModel() ); + unitModel.getFocusElement().ifPresent( unitResource -> model.add( resource, sammc.unit(), unitResource ) ); + } ); return new ElementModel( model, Optional.of( resource ) ); } @@ -612,11 +622,13 @@ public ElementModel visitAspect( final Aspect aspect, final ModelElement context model.add( serializeProperties( resource, aspect ) ); model.add( resource, samm.operations(), model.createList( aspect.getOperations().stream().map( this::getElementResource ).iterator() ) ); - aspect.getOperations().stream().map( operation -> operation.accept( this, aspect ) ).forEach( elementModel -> model.add( elementModel.getModel() ) ); + aspect.getOperations().stream().map( operation -> operation.accept( this, aspect ) ) + .forEach( elementModel -> model.add( elementModel.getModel() ) ); if ( !aspect.getEvents().isEmpty() ) { model.add( resource, samm.events(), model.createList( aspect.getEvents().stream().map( this::getElementResource ).iterator() ) ); - aspect.getEvents().stream().map( event -> event.accept( this, aspect ) ).forEach( elementModel -> model.add( elementModel.getModel() ) ); + aspect.getEvents().stream().map( event -> event.accept( this, aspect ) ) + .forEach( elementModel -> model.add( elementModel.getModel() ) ); } return new ElementModel( model, Optional.of( resource ) ); } @@ -674,11 +686,13 @@ public ElementModel visitOperation( final Operation operation, final ModelElemen final Resource resource = getElementResource( operation ); model.add( resource, RDF.type, samm.Operation() ); model.add( serializeDescriptions( resource, operation ) ); - final List inputProperties = operation.getInput().stream().map( this::getElementResource ).collect( Collectors.toList() ); + final List inputProperties = operation.getInput().stream().map( this::getElementResource ).toList(); model.add( resource, samm.input(), model.createList( inputProperties.iterator() ) ); - operation.getInput().stream().map( property -> property.accept( this, operation ) ).forEach( elementModel -> model.add( elementModel.getModel() ) ); + operation.getInput().stream().map( property -> property.accept( this, operation ) ) + .forEach( elementModel -> model.add( elementModel.getModel() ) ); operation.getOutput().ifPresent( outputProperty -> model.add( resource, samm.output(), getElementResource( outputProperty ) ) ); - operation.getOutput().map( outputProperty -> outputProperty.accept( this, operation ) ).ifPresent( elementModel -> model.add( elementModel.getModel() ) ); + operation.getOutput().map( outputProperty -> outputProperty.accept( this, operation ) ) + .ifPresent( elementModel -> model.add( elementModel.getModel() ) ); return new ElementModel( model, Optional.of( resource ) ); } @@ -695,7 +709,8 @@ public ElementModel visitEvent( final Event event, final ModelElement context ) @Override public ElementModel visitCharacteristic( final Characteristic characteristic, final ModelElement context ) { if ( !isLocalElement( characteristic ) ) { - return new ElementModel( ModelFactory.createDefaultModel(), characteristic.getAspectModelUrn().map( urn -> createResource( urn.toString() ) ) ); + return new ElementModel( ModelFactory.createDefaultModel(), + characteristic.getAspectModelUrn().map( urn -> createResource( urn.toString() ) ) ); } final Model model = createCharacteristicsModel( characteristic ); final Resource resource = getElementResource( characteristic ); @@ -734,7 +749,7 @@ public ElementModel visitComplexType( final ComplexType complexType, final Model public ElementModel visitAbstractEntity( final AbstractEntity abstractEntity, final ModelElement context ) { if ( abstractEntity.getUrn().startsWith( samme.getNamespace() ) ) { return new ElementModel( ModelFactory.createDefaultModel(), - abstractEntity.getAspectModelUrn().map( urn -> ResourceFactory.createResource( urn.toString() ) ) ); + abstractEntity.getAspectModelUrn().map( urn -> createResource( urn.toString() ) ) ); } final Model model = visitComplexType( abstractEntity, context ).getModel(); abstractEntity.getExtendingElements().forEach( complexType -> model.add( complexType.accept( this, complexType ).getModel() ) ); @@ -744,24 +759,36 @@ public ElementModel visitAbstractEntity( final AbstractEntity abstractEntity, fi @Override public ElementModel visitUnit( final Unit unit, final ModelElement context ) { final Model model = ModelFactory.createDefaultModel(); - final String unitUrn = unit.getAspectModelUrn().map( AspectModelUrn::toString ) - .orElseThrow( () -> new InvalidModelException( "Invalid unit without URN." ) ); - if ( !createResource( unitUrn ).getNameSpace().equals( unitNamespace.getNamespace() ) ) { + final Resource unitResource = getElementResource( unit ); + if ( !unitResource.getNameSpace().equals( unitNamespace.getNamespace() ) ) { // This is a unit defined in the scope of the Aspect model - final Resource unitResource = getElementResource( unit ); model.add( unitResource, RDF.type, samm.Unit() ); - unit.getQuantityKinds().forEach( quantityKind -> - model.add( unitResource, samm.quantityKind(), unitNamespace.resource( quantityKind.getName() ) ) ); + unit.getQuantityKinds().forEach( quantityKind -> { + final ElementModel quantityKindModel = quantityKind.accept( this, context ); + model.add( quantityKindModel.getModel() ); + quantityKindModel.getFocusElement().ifPresent( quantityKindResource -> + model.add( unitResource, samm.quantityKind(), quantityKindResource ) ); + } ); model.add( serializeDescriptions( unitResource, unit ) ); unit.getSymbol().ifPresent( symbol -> model.add( unitResource, samm.symbol(), serializePlainString( symbol ) ) ); return new ElementModel( model, Optional.of( unitResource ) ); } - return new ElementModel( model, Optional.empty() ); + return new ElementModel( model, Optional.of( unitResource ) ); } @Override public ElementModel visitQuantityKind( final QuantityKind quantityKind, final ModelElement context ) { - return new ElementModel( ModelFactory.createDefaultModel(), Optional.empty() ); + final Model model = ModelFactory.createDefaultModel(); + final Resource quantityKindResource = getElementResource( quantityKind ); + if ( !quantityKindResource.getNameSpace().equals( unitNamespace.getNamespace() ) ) { + if ( quantityKind.getAspectModelUrn().map( quantityKindUrn -> + quantityKindUrn.getUrnPrefix().equals( unitNamespace.getNamespace() ) ).orElse( true ) ) { + return new ElementModel( model, Optional.empty() ); + } + model.add( quantityKindResource, RDF.type, samm.QuantityKind() ); + model.add( quantityKindResource, samm.preferredName(), ResourceFactory.createLangLiteral( quantityKind.getLabel(), "en" ) ); + } + return new ElementModel( model, Optional.of( quantityKindResource ) ); } @Override From dd7f296e2b0a63b710b7bf60120e1823551af4be Mon Sep 17 00:00:00 2001 From: "Textor Andreas (BCI/ESW17)" Date: Fri, 3 Nov 2023 10:58:28 +0100 Subject: [PATCH 5/5] Fix static Java code generation to work with custom quantity kinds --- .../java/ValueExpressionVisitor.java | 10 +- .../aspectmodel/java/ValueInitializer.java | 38 +++--- .../metamodel/StaticMetaModelVisitor.java | 114 +++++++++++------- 3 files changed, 99 insertions(+), 63 deletions(-) diff --git a/core/esmf-aspect-model-java-generator/src/main/java/org/eclipse/esmf/aspectmodel/java/ValueExpressionVisitor.java b/core/esmf-aspect-model-java-generator/src/main/java/org/eclipse/esmf/aspectmodel/java/ValueExpressionVisitor.java index 642e8f5aa..ba31f1f2f 100644 --- a/core/esmf-aspect-model-java-generator/src/main/java/org/eclipse/esmf/aspectmodel/java/ValueExpressionVisitor.java +++ b/core/esmf-aspect-model-java-generator/src/main/java/org/eclipse/esmf/aspectmodel/java/ValueExpressionVisitor.java @@ -19,6 +19,7 @@ import org.apache.jena.rdf.model.Resource; import org.apache.jena.rdf.model.ResourceFactory; import org.apache.jena.vocabulary.RDF; + import org.eclipse.esmf.aspectmodel.java.exception.CodeGenerationException; import org.eclipse.esmf.aspectmodel.resolver.services.DataType; import org.eclipse.esmf.metamodel.CollectionValue; @@ -37,7 +38,8 @@ *
  • If the value is (int) 3, it will return "3"
  • *
  • If the value is (String) "hi", it will return "\"hi\""
  • *
  • If the value is (LangString) "hi"@en, it will return "new LangString(\"hi\", Locale.forLanguageTag(\"en\"))"
  • - *
  • If the value is a collection, it will return the corresponding collection, e.g. "new ArrayList<>(){{ add(1); add(2); add(3); }}"
  • + *
  • If the value is a collection, it will return the corresponding collection, e.g. "new ArrayList<>(){{ add(1); add(2); add(3); }} + * "
  • *
  • If the value is an Entity, it will return the corresponding constructor call, e.g. "new MyEntity(\"foo\", 2, 3)"
  • * */ @@ -70,7 +72,8 @@ private String generateValueExpression( final ScalarValue value, final Context c context.getCodeGenerationConfig().importTracker().importExplicit( LangString.class ); context.getCodeGenerationConfig().importTracker().importExplicit( Locale.class ); final LangString langStringValue = (LangString) value.as( ScalarValue.class ).getValue(); - return String.format( "new LangString(\"%s\", Locale.forLanguageTag(\"%s\"))", AspectModelJavaUtil.escapeForLiteral( langStringValue.getValue() ), + return String.format( "new LangString(\"%s\", Locale.forLanguageTag(\"%s\"))", + AspectModelJavaUtil.escapeForLiteral( langStringValue.getValue() ), langStringValue.getLanguageTag().toLanguageTag() ); } @@ -107,7 +110,8 @@ public String visitEntityInstance( final EntityInstance instance, final Context if ( property.isOptional() ) { return "null"; } - throw new CodeGenerationException( "EntityInstance " + instance.getName() + " is missing value for Property " + property.getName() ); + throw new CodeGenerationException( + "EntityInstance " + instance.getName() + " is missing value for Property " + property.getName() ); } final Context newContext = new Context( context.codeGenerationConfig, property.isOptional() ); return value.accept( this, newContext ); diff --git a/core/esmf-aspect-model-java-generator/src/main/java/org/eclipse/esmf/aspectmodel/java/ValueInitializer.java b/core/esmf-aspect-model-java-generator/src/main/java/org/eclipse/esmf/aspectmodel/java/ValueInitializer.java index b80d2691a..6539181b0 100644 --- a/core/esmf-aspect-model-java-generator/src/main/java/org/eclipse/esmf/aspectmodel/java/ValueInitializer.java +++ b/core/esmf-aspect-model-java-generator/src/main/java/org/eclipse/esmf/aspectmodel/java/ValueInitializer.java @@ -37,17 +37,18 @@ public class ValueInitializer { static { final BiFunction, String, String> literalExpression = ( type, valueExpression ) -> valueExpression; - final BiFunction, String, String> stringConstructor = ( type, valueExpression ) -> String.format( "new %s( %s )", type.getSimpleName(), - valueExpression ); - final BiFunction, String, String> create = ( type, valueExpression ) -> String.format( "%s.create( %s )", type.getSimpleName(), - valueExpression ); - final BiFunction, String, String> parseTypeName = ( type, valueExpression ) -> String.format( "%s.parse%s( %s )", type.getSimpleName(), + final BiFunction, String, String> stringConstructor = ( type, valueExpression ) -> String.format( "new %s( %s )", type.getSimpleName(), valueExpression ); - final BiFunction, String, String> valueOf = ( type, valueExpression ) -> String.format( "%s.valueOf( %s )", type.getSimpleName(), - valueExpression ); - final BiFunction, String, String> gregorianCalendar = ( type, valueExpression ) -> "_datatypeFactory.newXMLGregorianCalendar( " + valueExpression + final BiFunction, String, String> create = ( type, valueExpression ) -> String.format( "%s.create( %s )", + type.getSimpleName(), valueExpression ); + final BiFunction, String, String> parseTypeName = ( type, valueExpression ) -> String.format( "%s.parse%s( %s )", + type.getSimpleName(), type.getSimpleName(), valueExpression ); + final BiFunction, String, String> valueOf = ( type, valueExpression ) -> String.format( "%s.valueOf( %s )", + type.getSimpleName(), valueExpression ); + final BiFunction, String, String> gregorianCalendar = ( type, valueExpression ) -> + "_datatypeFactory.newXMLGregorianCalendar( " + valueExpression + " )"; + final BiFunction, String, String> duration = ( type, valueExpression ) -> "_datatypeFactory.newDuration( " + valueExpression + " )"; - final BiFunction, String, String> duration = ( type, valueExpression ) -> "_datatypeFactory.newDuration( " + valueExpression + " )"; INITIALIZERS = new HashMap<>(); INITIALIZERS.put( XSD.xstring, literalExpression ); @@ -59,11 +60,13 @@ public class ValueInitializer { INITIALIZERS.put( XSD.date, gregorianCalendar ); INITIALIZERS.put( XSD.dateTime, gregorianCalendar ); INITIALIZERS.put( XSD.dateTimeStamp, gregorianCalendar ); - INITIALIZERS.put( XSD.gYear, ( type, valueExpression ) -> "_datatypeFactory.newXMLGregorianCalendarDate( Integer.valueOf( " + valueExpression + " )" - + ", DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED )" ); + INITIALIZERS.put( XSD.gYear, + ( type, valueExpression ) -> "_datatypeFactory.newXMLGregorianCalendarDate( Integer.valueOf( " + valueExpression + " )" + + ", DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED )" ); INITIALIZERS.put( XSD.gMonth, - ( type, valueExpression ) -> "_datatypeFactory.newXMLGregorianCalendarDate( DatatypeConstants.FIELD_UNDEFINED, Integer.valueOf( " + valueExpression - + " )" + ", DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED )" ); + ( type, valueExpression ) -> + "_datatypeFactory.newXMLGregorianCalendarDate( DatatypeConstants.FIELD_UNDEFINED, Integer.valueOf( " + valueExpression + + " )" + ", DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED )" ); INITIALIZERS.put( XSD.gYearMonth, gregorianCalendar ); INITIALIZERS.put( XSD.gMonthDay, gregorianCalendar ); INITIALIZERS.put( XSD.gDay, gregorianCalendar ); @@ -88,8 +91,10 @@ public class ValueInitializer { } public boolean needInitializationToConstructor( final List deconstructionSets ) { - return deconstructionSets.stream().flatMap( deconstructionSet -> deconstructionSet.getElementProperties().stream().map( property -> property.getDataType() - .map( type -> DataType.getJavaTypeForMetaModelType( ResourceFactory.createResource( type.getUrn() ), property.getMetaModelVersion() ) ) ) ) + return deconstructionSets.stream() + .flatMap( deconstructionSet -> deconstructionSet.getElementProperties().stream().map( property -> property.getDataType() + .map( type -> DataType.getJavaTypeForMetaModelType( ResourceFactory.createResource( type.getUrn() ), + property.getMetaModelVersion() ) ) ) ) .anyMatch( dataType -> dataType.map( type -> type == XMLGregorianCalendar.class ).orElse( false ) ); } @@ -114,7 +119,8 @@ public String apply( final Resource rdfType, final String valueExpression, final * @param valueExpression an expression that, when evaluated, will return the input value as a string. * @param metaModelVersion the used meta model version */ - public String apply( final Resource rdfType, final Class javaType, final String valueExpression, final KnownVersion metaModelVersion ) { + public String apply( final Resource rdfType, final Class javaType, final String valueExpression, + final KnownVersion metaModelVersion ) { final SAMM samm = new SAMM( metaModelVersion ); if ( rdfType.equals( samm.curie() ) ) { return String.format( "new Curie( %s )", valueExpression ); diff --git a/core/esmf-aspect-model-java-generator/src/main/java/org/eclipse/esmf/aspectmodel/java/metamodel/StaticMetaModelVisitor.java b/core/esmf-aspect-model-java-generator/src/main/java/org/eclipse/esmf/aspectmodel/java/metamodel/StaticMetaModelVisitor.java index d3410a182..3390003eb 100644 --- a/core/esmf-aspect-model-java-generator/src/main/java/org/eclipse/esmf/aspectmodel/java/metamodel/StaticMetaModelVisitor.java +++ b/core/esmf-aspect-model-java-generator/src/main/java/org/eclipse/esmf/aspectmodel/java/metamodel/StaticMetaModelVisitor.java @@ -23,10 +23,6 @@ import java.util.function.Supplier; import java.util.stream.Collectors; -import org.apache.commons.text.StringEscapeUtils; -import org.apache.jena.rdf.model.Resource; -import org.apache.jena.rdf.model.ResourceFactory; -import org.apache.jena.vocabulary.XSD; import org.eclipse.esmf.aspectmodel.java.AspectModelJavaUtil; import org.eclipse.esmf.aspectmodel.java.ValueExpressionVisitor; import org.eclipse.esmf.aspectmodel.java.ValueInitializer; @@ -89,17 +85,24 @@ import org.eclipse.esmf.metamodel.impl.DefaultCollectionValue; import org.eclipse.esmf.metamodel.impl.DefaultEntity; import org.eclipse.esmf.metamodel.impl.DefaultEntityInstance; +import org.eclipse.esmf.metamodel.impl.DefaultQuantityKind; import org.eclipse.esmf.metamodel.impl.DefaultScalar; import org.eclipse.esmf.metamodel.impl.DefaultScalarValue; import org.eclipse.esmf.metamodel.impl.DefaultUnit; import org.eclipse.esmf.metamodel.visitor.AspectVisitor; import org.eclipse.esmf.samm.KnownVersion; +import org.apache.commons.text.StringEscapeUtils; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.ResourceFactory; +import org.apache.jena.vocabulary.XSD; + public class StaticMetaModelVisitor implements AspectVisitor { private final ValueExpressionVisitor valueExpressionVisitor = new ValueExpressionVisitor(); private final ValueInitializer valueInitializer = new ValueInitializer(); - private final Supplier noTypeException = () -> new CodeGenerationException( "Characteristic is missing its dataType" ); + private final Supplier noTypeException = () -> new CodeGenerationException( + "Characteristic is missing its dataType" ); @Override public String visitBase( final ModelElement modelElement, final StaticCodeGenerationContext context ) { @@ -191,28 +194,22 @@ public String visitSingleEntity( final SingleEntity singleEntity, final StaticCo @Override public String visitCollection( final Collection collection, final StaticCodeGenerationContext context ) { - final Class implementationClass; - switch ( collection.getCollectionType() ) { - case LIST: - implementationClass = DefaultList.class; - break; - case SET: - implementationClass = DefaultSet.class; - break; - case SORTEDSET: - implementationClass = DefaultSortedSet.class; - break; - default: - implementationClass = DefaultCollection.class; - break; - } + final Class implementationClass = switch ( collection.getCollectionType() ) { + case LIST -> DefaultList.class; + case SET -> DefaultSet.class; + case SORTEDSET -> DefaultSortedSet.class; + default -> DefaultCollection.class; + }; context.getCodeGenerationConfig().importTracker().importExplicit( implementationClass ); - final String optionalType = collection.getDataType().map( type -> type.accept( this, context ) ).map( type -> "Optional.of(" + type + ")" ) + final String optionalType = collection.getDataType().map( type -> type.accept( this, context ) ) + .map( type -> "Optional.of(" + type + ")" ) .orElse( "Optional.empty()" ); - final String optionalElementCharacteristic = collection.getElementCharacteristic().map( characteristic -> characteristic.accept( this, context ) ) + final String optionalElementCharacteristic = collection.getElementCharacteristic() + .map( characteristic -> characteristic.accept( this, context ) ) .map( characteristic -> "Optional.of(" + characteristic + ")" ).orElse( "Optional.empty()" ); - return "new " + implementationClass.getSimpleName() + "(" + getMetaModelBaseAttributes( collection, context ) + "," + optionalType + "," + return "new " + implementationClass.getSimpleName() + "(" + getMetaModelBaseAttributes( collection, context ) + "," + optionalType + + "," + optionalElementCharacteristic + ")"; } @@ -285,8 +282,18 @@ public String visitUnit( final Unit unit, final StaticCodeGenerationContext cont @Override public String visitQuantityKind( final QuantityKind quantityKind, final StaticCodeGenerationContext context ) { - context.getCodeGenerationConfig().importTracker().importExplicit( QuantityKinds.class ); - return "QuantityKinds." + AspectModelJavaUtil.toConstant( quantityKind.getName() ); + // The quantity kind is one of the default ones defined in the QuantityKinds enum? + if ( QuantityKinds.fromName( quantityKind.getName() ).isPresent() ) { + context.getCodeGenerationConfig().importTracker().importExplicit( QuantityKinds.class ); + return "QuantityKinds." + AspectModelJavaUtil.toConstant( quantityKind.getName() ); + } + + // If not, create a new instance of the default implementation + context.getCodeGenerationConfig().importTracker().importExplicit( DefaultQuantityKind.class ); + return "new DefaultQuantityKind(" + + getMetaModelBaseAttributes( quantityKind, context ) + "," + + "\"" + StringEscapeUtils.escapeJava( quantityKind.getLabel() ) + "\"" + + ")"; } @Override @@ -300,7 +307,8 @@ public String visitState( final State state, final StaticCodeGenerationContext c // Type type + state.getDataType().orElseThrow( noTypeException ).accept( this, context ) + "," // List values - + "new ArrayList(){{" + state.getValues().stream().sorted().map( value -> String.format( "add(%s);", value.accept( this, context ) ) ) + + "new ArrayList(){{" + state.getValues().stream().sorted() + .map( value -> String.format( "add(%s);", value.accept( this, context ) ) ) .collect( Collectors.joining() ) + "}}," // Value defaultValue + state.getDefaultValue().accept( this, context ) + ")"; @@ -317,7 +325,8 @@ public String visitEnumeration( final Enumeration enumeration, final StaticCodeG // Type type + enumeration.getDataType().orElseThrow( noTypeException ).accept( this, context ) + "," // List values - + "new ArrayList(){{" + enumeration.getValues().stream().sorted().map( value -> String.format( "add(%s);", value.accept( this, context ) ) ) + + "new ArrayList(){{" + enumeration.getValues().stream().sorted() + .map( value -> String.format( "add(%s);", value.accept( this, context ) ) ) .collect( Collectors.joining() ) + "}})"; } @@ -334,7 +343,8 @@ public String visitStructuredValue( final StructuredValue structuredValue, final + AspectModelJavaUtil.createLiteral( structuredValue.getDeconstructionRule() ) + "," // List elements + "new ArrayList(){{" + structuredValue.getElements().stream().sequential() - .map( element -> String.format( "add(%s);", AspectModelJavaUtil.printStructuredValueElement( element ) ) ).collect( Collectors.joining() ) + "}})"; + .map( element -> String.format( "add(%s);", AspectModelJavaUtil.printStructuredValueElement( element ) ) ) + .collect( Collectors.joining() ) + "}})"; } @Override @@ -359,7 +369,8 @@ public String visitCharacteristic( final Characteristic characteristic, final St // MetaModelBaseAttributes + getMetaModelBaseAttributes( characteristic, context ) + "," // Optional type - + characteristic.getDataType().map( type -> "Optional.of(" + type.accept( this, context ) + ")" ).orElse( "Optional.empty()" ) + ")"; + + characteristic.getDataType().map( type -> "Optional.of(" + type.accept( this, context ) + ")" ).orElse( "Optional.empty()" ) + + ")"; } @Override @@ -370,9 +381,11 @@ public String visitLengthConstraint( final LengthConstraint lengthConstraint, fi // MetaModelBaseAttributes + getMetaModelBaseAttributes( lengthConstraint, context ) + "," // Optional min - + getOptionalStaticDeclarationValue( nonNegativeInteger, lengthConstraint.getMinValue(), lengthConstraint.getMetaModelVersion(), context ) + "," + + getOptionalStaticDeclarationValue( nonNegativeInteger, lengthConstraint.getMinValue(), lengthConstraint.getMetaModelVersion(), + context ) + "," // Optional max - + getOptionalStaticDeclarationValue( nonNegativeInteger, lengthConstraint.getMaxValue(), lengthConstraint.getMetaModelVersion(), context ) + ")"; + + getOptionalStaticDeclarationValue( nonNegativeInteger, lengthConstraint.getMaxValue(), lengthConstraint.getMetaModelVersion(), + context ) + ")"; } @Override @@ -384,9 +397,11 @@ public String visitRangeConstraint( final RangeConstraint rangeConstraint, final // MetaModelBaseAttributes + getMetaModelBaseAttributes( rangeConstraint, context ) + "," // Optional minValue - + getOptionalStaticDeclarationValue( characteristicType, rangeConstraint.getMinValue(), rangeConstraint.getMetaModelVersion(), context ) + "," + + getOptionalStaticDeclarationValue( characteristicType, rangeConstraint.getMinValue(), rangeConstraint.getMetaModelVersion(), + context ) + "," // Optional maxValue - + getOptionalStaticDeclarationValue( characteristicType, rangeConstraint.getMaxValue(), rangeConstraint.getMetaModelVersion(), context ) + "," + + getOptionalStaticDeclarationValue( characteristicType, rangeConstraint.getMaxValue(), rangeConstraint.getMetaModelVersion(), + context ) + "," // BoundDefinition lowerBoundDefinition + "BoundDefinition." + rangeConstraint.getLowerBoundDefinition().name() + "," // BoundDefinition upperBoundDefinition @@ -394,7 +409,8 @@ public String visitRangeConstraint( final RangeConstraint rangeConstraint, final } @Override - public String visitRegularExpressionConstraint( final RegularExpressionConstraint regularExpressionConstraint, final StaticCodeGenerationContext context ) { + public String visitRegularExpressionConstraint( final RegularExpressionConstraint regularExpressionConstraint, + final StaticCodeGenerationContext context ) { context.getCodeGenerationConfig().importTracker().importExplicit( DefaultRegularExpressionConstraint.class ); return "new DefaultRegularExpressionConstraint(" // MetaModelBaseAttributes @@ -477,7 +493,8 @@ public String visitAbstractEntity( final AbstractEntity abstractEntity, final St + extendsComplexType( abstractEntity, context ) + "," // List extendingElements + "List.of(" + abstractEntity.getExtendingElements().stream().sorted() - .map( extendingElement -> "AspectModelUrn.fromUrn(\"" + extendingElement.getUrn() + "\")" ).collect( Collectors.joining( "," ) ) + "))"; + .map( extendingElement -> "AspectModelUrn.fromUrn(\"" + extendingElement.getUrn() + "\")" ).collect( Collectors.joining( "," ) ) + + "))"; } @Override @@ -495,19 +512,23 @@ private String extendsComplexType( final ComplexType complexType, final StaticCo if ( type.is( Entity.class ) ) { final Entity entity = type.as( Entity.class ); context.getCodeGenerationConfig().importTracker().importExplicit( DefaultEntity.class ); - return "Optional.of(DefaultEntity.createDefaultEntity(" + getMetaModelBaseAttributes( complexType, context ) + "," + "Meta" + entity.getName() + return "Optional.of(DefaultEntity.createDefaultEntity(" + getMetaModelBaseAttributes( complexType, context ) + "," + "Meta" + + entity.getName() + ".INSTANCE.getProperties()," + extendsComplexType( entity, context ) + "))"; } // AbstractEntity final AbstractEntity abstractEntity = type.as( AbstractEntity.class ); context.getCodeGenerationConfig().importTracker().importExplicit( DefaultAbstractEntity.class ); - return "Optional.of(DefaultAbstractEntity.createDefaultAbstractEntity(" + getMetaModelBaseAttributes( abstractEntity, context ) + "," + "Meta" + return "Optional.of(DefaultAbstractEntity.createDefaultAbstractEntity(" + getMetaModelBaseAttributes( abstractEntity, context ) + "," + + "Meta" + abstractEntity.getName() + ".INSTANCE.getProperties()," + extendsComplexType( abstractEntity, context ) + "," + "List.of(" + abstractEntity.getExtendingElements().stream().sorted() - .map( extendingElement -> "AspectModelUrn.fromUrn( \"" + extendingElement.getUrn() + "\" )" ).collect( Collectors.joining( "," ) ) + ")" + "))"; + .map( extendingElement -> "AspectModelUrn.fromUrn( \"" + extendingElement.getUrn() + "\" )" ) + .collect( Collectors.joining( "," ) ) + ")" + "))"; } - private String getOptionalStaticDeclarationValue( final Type type, final Optional optionalValue, final KnownVersion metaModelVersion, + private String getOptionalStaticDeclarationValue( final Type type, final Optional optionalValue, + final KnownVersion metaModelVersion, final StaticCodeGenerationContext context ) { if ( optionalValue.isEmpty() ) { return "Optional.empty()"; @@ -538,9 +559,11 @@ public String metaModelBaseAttributes( final Property property, final StaticCode return getMetaModelBaseAttributes( property, context ); } - public String getMetaModelBaseAttributes( final T element, final StaticCodeGenerationContext context ) { + public String getMetaModelBaseAttributes( final T element, + final StaticCodeGenerationContext context ) { if ( element.getPreferredNames().isEmpty() && element.getDescriptions().isEmpty() && element.getSee().isEmpty() ) { - return "MetaModelBaseAttributes.from(" + "KnownVersion." + element.getMetaModelVersion().toString() + ", " + elementUrn( element, context ) + ", " + return "MetaModelBaseAttributes.from(" + "KnownVersion." + element.getMetaModelVersion().toString() + ", " + elementUrn( element, + context ) + ", " + "\"" + element.getName() + "\" )"; } @@ -549,14 +572,17 @@ public String getMetaModelBaseAttributes builder.append( ".withMetaModelVersion(KnownVersion." ).append( element.getMetaModelVersion().toString() ).append( ")" ); builder.append( ".withUrn(" ).append( elementUrn( element, context ) ).append( ")" ); element.getPreferredNames().stream().sorted().forEach( preferredName -> { - builder.append( ".withPreferredName(Locale.forLanguageTag(\"" ).append( preferredName.getLanguageTag().toLanguageTag() ).append( "\")," ); + builder.append( ".withPreferredName(Locale.forLanguageTag(\"" ).append( preferredName.getLanguageTag().toLanguageTag() ) + .append( "\")," ); builder.append( AspectModelJavaUtil.createLiteral( preferredName.getValue() ) ).append( ")" ); } ); element.getDescriptions().stream().sorted().forEach( description -> { - builder.append( ".withDescription(Locale.forLanguageTag(\"" ).append( description.getLanguageTag().toLanguageTag() ).append( "\")," ); + builder.append( ".withDescription(Locale.forLanguageTag(\"" ).append( description.getLanguageTag().toLanguageTag() ) + .append( "\")," ); builder.append( AspectModelJavaUtil.createLiteral( description.getValue() ) ).append( ")" ); } ); - element.getSee().stream().sorted().forEach( see -> builder.append( ".withSee(" ).append( AspectModelJavaUtil.createLiteral( see ) ).append( ")" ) ); + element.getSee().stream().sorted() + .forEach( see -> builder.append( ".withSee(" ).append( AspectModelJavaUtil.createLiteral( see ) ).append( ")" ) ); builder.append( ".build()" ); return builder.toString(); }