diff --git a/.github/workflows/pull-request-check.yml b/.github/workflows/pull-request-check.yml index f47a038ec..bdf65bf43 100644 --- a/.github/workflows/pull-request-check.yml +++ b/.github/workflows/pull-request-check.yml @@ -66,8 +66,10 @@ jobs: run: | java --version export MAVEN_OPTS="-Xmx4096m" + export JAVA_TOOL_OPTIONS="-Dfile.encoding=UTF8" mvn -B -pl '!org.eclipse.esmf:samm-cli' clean install -Dmaven.wagon.httpconnectionManager.ttlSeconds=60 cd tools/samm-cli + unset JAVA_TOOL_OPTIONS mvn -B clean verify -Dmaven.wagon.httpconnectionManager.ttlSeconds=60 mvn -B verify -Pnative -Dmaven.wagon.httpconnectionManager.ttlSeconds=60 shell: bash diff --git a/.github/workflows/release-workflow.yml b/.github/workflows/release-workflow.yml index ff35a1e24..75acb3fd5 100644 --- a/.github/workflows/release-workflow.yml +++ b/.github/workflows/release-workflow.yml @@ -90,6 +90,7 @@ jobs: - name: Build and run tests run: | export MAVEN_OPTS="-Xmx4096m" + export JAVA_TOOL_OPTIONS="-Dfile.encoding=UTF8" # Required for reactor dependencies mvn clean install -DskipTests -Dmaven.javadoc.skip=true mvn versions:set -DnewVersion=${{ github.event.inputs.release_version }} @@ -101,6 +102,7 @@ jobs: mvn -B -pl '!org.eclipse.esmf:samm-cli' clean deploy -Dmaven.wagon.httpconnectionManager.ttlSeconds=60 -DaltDeploymentRepository=local::default::file://nexus-staging -Psign # Build of CLI pushd tools/samm-cli + unset JAVA_TOOL_OPTIONS mvn -B clean verify -Dmaven.wagon.httpconnectionManager.ttlSeconds=60 mvn -B verify -Pnative -Dmaven.wagon.httpconnectionManager.ttlSeconds=60 popd diff --git a/core/esmf-aspect-meta-model-java/buildSrc/main/groovy/unit2java.groovy b/core/esmf-aspect-meta-model-java/buildSrc/main/groovy/unit2java.groovy deleted file mode 100644 index 60a5617df..000000000 --- a/core/esmf-aspect-meta-model-java/buildSrc/main/groovy/unit2java.groovy +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (c) 2021 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 - */ - - -import com.google.common.collect.Lists -import org.apache.jena.query.QueryExecutionFactory -import org.apache.jena.rdf.model.ModelFactory -import org.apache.jena.riot.RDFLanguages - -import java.nio.charset.StandardCharsets -import java.nio.file.Paths - -def generateUnitsClass(List units) { - List> slices = Lists.partition(units, 100) - int numSlices = slices.size() - def initMethods = [] - def initMethodCalls = [] - for (int slice = 0; slice < numSlices; slice++) { - String method = """ - private static void init${slice}() { - ${slices[slice].join("\n ")} - } -""" - initMethods << method - initMethodCalls << "init${slice}();" - } - - return """\ -/* - * Copyright (c) 2021 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; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.HashSet; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.eclipse.esmf.samm.KnownVersion; -import org.eclipse.esmf.aspectmodel.urn.AspectModelUrn; -import org.eclipse.esmf.metamodel.impl.DefaultUnit; -import org.eclipse.esmf.metamodel.loader.MetaModelBaseAttributes; - -/** - * Enumeration of Units as defined in Recommendation 20 by the - * UNECE (United Nations Economic Commission for Europe). - */ -public class Units { - private static final Map> UNITS_BY_NAME = new HashMap<>(); - private static final KnownVersion LATEST = KnownVersion.getLatest(); - - private Units() { - } - - private static AspectModelUrn urn( final KnownVersion version, final String name ) { - return AspectModelUrn.fromUrn( - String.format( "urn:samm:org.eclipse.esmf.samm:unit:%s#%s", version.toVersionString(), name ) ); - } - - ${initMethods.join("\n")} - - /** - * Returns the unit with a given name - */ - public static synchronized Optional fromName( final String name, final KnownVersion metaModelVersion ) { - if ( UNITS_BY_NAME.isEmpty() ) { - ${initMethodCalls.join("\n ")} - } - return Optional.ofNullable( UNITS_BY_NAME.get( name ) ).map( unitGenerator -> unitGenerator.apply( metaModelVersion ) ); - } - - /** - * Returns the unit with a given name - */ - public static Optional fromName( final String name ) { - return fromName( name, LATEST ); - } - - /** - * Finds the unit with a given code - */ - public static Optional fromCode( final String code, final KnownVersion metaModelVersion ) { - if ( UNITS_BY_NAME.isEmpty() ) { - fromName( "" ); - } - return UNITS_BY_NAME.values() - .stream() - .map( unitGenerator -> unitGenerator.apply( metaModelVersion ) ) - .filter( unit -> unit.getCode().map( code2 -> code2.equals( code ) ).orElse( false ) ) - .findAny(); - } - - /** - * Finds the unit with a given code - */ - public static Optional fromCode( final String code ) { - return fromCode( code, LATEST ); - } - - /** - * Finds the units with a given symbol. In most, but not all cases, this set will contain exactly one unit. - */ - public static Set fromSymbol( final String symbol, final KnownVersion metaModelVersion ) { - if ( UNITS_BY_NAME.isEmpty() ) { - fromName( "" ); - } - return UNITS_BY_NAME.values() - .stream() - .map( unitGenerator -> unitGenerator.apply( metaModelVersion ) ) - .flatMap( unit -> unit.getSymbol() - .filter( symbol2 -> symbol2.equals( symbol ) ) - .stream() - .map( symbol2 -> unit ) ) - .collect( Collectors.toSet() ); - } - - /** - * Finds the units with a given symbol. In most, but not all cases, this set will contain exactly one unit. - */ - public static Set fromSymbol( final String symbol ) { - return fromSymbol( symbol, LATEST ); - } - - /** - * Returns all units of a given quantity kind - */ - public static Set unitsWithQuantityKind( final QuantityKind quantityKind, - final KnownVersion metaModelVersion ) { - if ( UNITS_BY_NAME.isEmpty() ) { - fromName( "" ); - } - return UNITS_BY_NAME.values() - .stream() - .map( unitGenerator -> unitGenerator.apply( metaModelVersion ) ) - .filter( unit -> unit.getQuantityKinds().contains( quantityKind ) ) - .collect( Collectors.toSet() ); - } - - /** - * Returns all units of a given quantity kind - */ - public static Set unitsWithQuantityKind( final QuantityKind quantityKind ) { - return unitsWithQuantityKind( quantityKind, LATEST ); - } - -} -""" -} - -def generateQuantityKindClass(List quantityKinds) { - def joinedQuantityKinds = quantityKinds.join(",\n ") - return """\ -/* - * Copyright (c) 2021 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; - -import java.util.Arrays; -import java.util.Collections; -import java.util.Locale; -import java.util.Set; -import java.util.Optional; - -import org.eclipse.esmf.samm.KnownVersion; -import org.eclipse.esmf.aspectmodel.urn.AspectModelUrn; -import org.eclipse.esmf.metamodel.datatypes.LangString; -import org.eclipse.esmf.metamodel.visitor.AspectVisitor; - -/** - * Enumeration of Quantity Kinds as defined in Recommendation 20 - * by the UNECE (United Nations Economic Commission for Europe). - */ -public enum QuantityKinds implements QuantityKind { - ${joinedQuantityKinds}; - - private static final KnownVersion LATEST = KnownVersion.getLatest(); - private final String name; - private final String label; - - QuantityKinds( final String name, final String label ) { - this.name = name; - this.label = label; - } - - /** - * Returns the quantity kind's unique name - */ - public String getName() { - return this.name; - } - - /** - * Returns the quantity kind's human-readable name - */ - public String getLabel() { - return this.label; - } - - /** - * Returns the quantity kind's human-readable name - */ - @Override - public String toString() { - return getLabel(); - } - - @Override - public Optional getAspectModelUrn() { - return Optional.of( AspectModelUrn.fromUrn( String.format( "urn:samm:org.eclipse.esmf.samm:unit:%s#%s", LATEST.toVersionString(), this.name ) ) ); - } - - @Override - public KnownVersion getMetaModelVersion() { - return LATEST; - } - - @Override - public T accept( final AspectVisitor visitor, C context ) { - return visitor.visitQuantityKind( this, context ); - } - - /** - * Finds the quantity kind with a given name - */ - public static Optional fromName( final String name ) { - return Arrays.stream( QuantityKinds.values() ) - .filter( quantityKind -> quantityKind.getName().equals( name ) ) - .map( QuantityKind.class::cast ) - .findAny(); - } -} -""" -} - -def toUpperSnakeCase(String s) { - return s.replaceAll(/([A-Z])/, /_$1/).toUpperCase().replaceAll(/^_/, '') -} - -def model = ModelFactory.createDefaultModel() -model.read(getClass().getResourceAsStream("samm/unit/1.0.0/units.ttl"), "", RDFLanguages.TURTLE.getName()) - -def units = [] -QueryExecutionFactory.create(new File("${project.basedir}/buildSrc/main/resources/units.sparql").text, model).execSelect().each { unit -> - def unitName = unit.get("unitName").asLiteral().toString() - def label = unit.get("label").asLiteral().toString() - def symbol = unit.get("symbol") == null ? "Optional.empty()" : "Optional.of( \"" + unit.get("symbol") + "\" )" - def code = unit.get("code") == null ? "Optional.empty()" : "Optional.of( \"" + unit.get("code") + "\" )" - def referenceUnitName = unit.get("referenceUnitName") == null ? "Optional.empty()" : - "Optional.of( \"" + unit.get("referenceUnitName").asLiteral().toString() + "\" )" - def conversionFactor = unit.get("conversionFactor") == null ? "Optional.empty()" : - "Optional.of( \"" + unit.get("conversionFactor").asLiteral().toString() + "\" )" - - def quantityKindsString = unit.get("quantityKinds") == null ? "" : unit.get("quantityKinds").asLiteral().toString().split(",") - .collect { quantityKind -> "QuantityKinds." + toUpperSnakeCase(quantityKind) }.join(", ") - def quantityKinds = unit.get("quantityKinds") == null ? "Collections.emptySet()" : - "new HashSet<>( Arrays.asList( " + quantityKindsString + " ) )" - units.add(""" UNITS_BY_NAME.put( "${unitName}", version -> new DefaultUnit( MetaModelBaseAttributes.from( version, urn( version, "${unitName}" ), "${unitName}", "${label}" ), ${symbol}, ${code}, ${referenceUnitName}, ${conversionFactor}, ${quantityKinds} ) );""") -} - -def quantityKinds = [] -QueryExecutionFactory.create(new File("${project.basedir}/buildSrc/main/resources/quantitykinds.sparql").text, model).execSelect().each { unit -> - def quantityKindName = unit.get("quantityKindName").asLiteral().toString() - def label = unit.get("label").asLiteral().toString() - def enumFieldName = toUpperSnakeCase(quantityKindName) - quantityKinds.add("""${enumFieldName}( "${quantityKindName}", "${label}" )""") -} - -def path = "${project.basedir}/src-gen/main/java/org/eclipse/esmf/metamodel" -new File(path).mkdirs() -System.out.println("Writing generated source file: " + path + "/Units.java") -Paths.get(path).resolve("Units.java") - .toFile() - .newWriter(StandardCharsets.UTF_8.name()) - .withWriter { w -> w << generateUnitsClass(units) } -System.out.println("Writing generated source file: " + path + "/QuantityKinds.java") -Paths.get(path).resolve("QuantityKinds.java") - .toFile() - .newWriter(StandardCharsets.UTF_8.name()) - .withWriter { w -> w << generateQuantityKindClass(quantityKinds) } diff --git a/core/esmf-aspect-meta-model-java/buildSrc/main/groovy/unit2js.groovy b/core/esmf-aspect-meta-model-java/buildSrc/main/groovy/unit2js.groovy deleted file mode 100644 index bda71edce..000000000 --- a/core/esmf-aspect-meta-model-java/buildSrc/main/groovy/unit2js.groovy +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2021 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 - */ - -import org.apache.jena.query.QueryExecutionFactory -import org.apache.jena.rdf.model.ModelFactory -import org.apache.jena.riot.RDFLanguages - -import java.nio.charset.StandardCharsets -import java.nio.file.Paths - -def generateJs(List quantityKinds, List units) { - def joinedQuantityKinds = quantityKinds.join(",\n ") - def joinedUnits = units.join(",\n ") - return """\ -/* - * Copyright (c) 2021 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 - */ - -var samm = { - quantityKinds: { - ${joinedQuantityKinds} - }, - - units: { - ${joinedUnits} - } -}; -""" -} - -def model = ModelFactory.createDefaultModel() -model.read(getClass().getResourceAsStream("samm/unit/1.0.0/units.ttl"), "", RDFLanguages.TURTLE.getName()) - -def quantityKinds = [] -QueryExecutionFactory.create(new File("${project.basedir}/buildSrc/main/resources/quantitykinds.sparql").text, model).execSelect().each { unit -> - def quantityKindName = unit.get("quantityKindName").asLiteral().toString() - def label = unit.get("label").asLiteral().toString() - quantityKinds.add(""""${quantityKindName}": { name: "${quantityKindName}", label: "${label}" }""") -} - -def units = [] -QueryExecutionFactory.create(new File("${project.basedir}/buildSrc/main/resources/units.sparql").text, model).execSelect().each { unit -> - def unitName = unit.get("unitName").asLiteral().toString() - def label = unit.get("label").asLiteral().toString() - def symbol = unit.get("symbol") == null ? "null" : "\"" + unit.get("symbol") + "\"" - def code = unit.get("code") == null ? "null" : "\"" + unit.get("code") + "\"" - def referenceUnitName = unit.get("referenceUnitName") == null ? "null" : - "function() { return samm.units[\"" + unit.get("referenceUnitName").asLiteral().toString() + "\"] }" - def conversionFactor = unit.get("conversionFactor") == null ? "null" : - "\"" + unit.get("conversionFactor").asLiteral().toString() + "\"" - def quantityKindsString = unit.get("quantityKinds") == null ? "null" : - "[ " + unit.get("quantityKinds").asLiteral().toString().split(",") - .collect { quantityKind -> "\"" + quantityKind + "\"" }.join(", ") + " ]" - - units.add(""""${unitName}": { name: "${unitName}", label: "${label}", symbol: ${symbol}, code: ${code}, """ - + """referenceUnit: ${referenceUnitName}, conversionFactor: ${conversionFactor}, """ - + """quantityKinds: ${quantityKindsString} }""") -} - -def path = "${project.basedir}/src-gen/main/resources" -new File(path).mkdirs() -System.out.println("Writing generated source file: " + path + "/samm-units.js") -Paths.get(path).resolve("samm-units.js") - .toFile() - .newWriter(StandardCharsets.UTF_8.name()) - .withWriter { w -> w << generateJs(quantityKinds, units) } diff --git a/core/esmf-aspect-meta-model-java/buildSrc/main/resources/quantitykinds.sparql b/core/esmf-aspect-meta-model-java/buildSrc/main/resources/quantitykinds.sparql deleted file mode 100644 index 1cfd11d96..000000000 --- a/core/esmf-aspect-meta-model-java/buildSrc/main/resources/quantitykinds.sparql +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (c) 2021 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 samm: -prefix unit: - -select distinct ?quantityKindName ?label -where { - ?quantityKind a unit:QuantityKind . - ?quantityKind samm:name ?quantityKindName . - ?quantityKind samm:preferredName ?preferredName . - bind( str( ?preferredName ) as ?label ) -} -order by ?quantityKindName diff --git a/core/esmf-aspect-meta-model-java/buildSrc/main/resources/units.sparql b/core/esmf-aspect-meta-model-java/buildSrc/main/resources/units.sparql deleted file mode 100644 index ee02d25fe..000000000 --- a/core/esmf-aspect-meta-model-java/buildSrc/main/resources/units.sparql +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) 2021 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 rdf: -prefix rdfs: -prefix samm: -prefix unit: - -select distinct ?unitName ?label ?symbol ?code ?referenceUnitName ?conversionFactor ?quantityKinds -where { - ?unit rdf:type/rdfs:subClassOf* unit:Unit . - ?unit samm:name ?unitName . - optional { - ?unit samm:preferredName ?preferredName . - bind( str( ?preferredName ) as ?label ) - } - optional { - ?unit unit:symbol ?symbol - } - optional { - ?unit unit:commonCode ?code - } - optional { - ?unit unit:referenceUnit ?referenceUnit . - ?referenceUnit samm:name ?referenceUnitName . - ?unit unit:conversionFactor ?conversionFactor . - } - optional { - select ?unitName ( group_concat( ?quantityKindName; separator="," ) as ?quantityKinds ) - where { - ?unit samm:name ?unitName . - ?unit unit:referenceUnit?/unit:quantityKind ?quantityKind . - ?quantityKind samm:name ?quantityKindName . - } - group by ?unitName - } -} -order by ?unitName diff --git a/core/esmf-aspect-meta-model-java/pom.xml b/core/esmf-aspect-meta-model-java/pom.xml index ee74d0deb..321d5e440 100644 --- a/core/esmf-aspect-meta-model-java/pom.xml +++ b/core/esmf-aspect-meta-model-java/pom.xml @@ -28,6 +28,11 @@ ESMF Aspect Meta Model Java jar + + ${project.basedir}/src-gen + ${project.basedir}/src-buildtime + + org.eclipse.esmf @@ -45,6 +50,10 @@ org.eclipse.esmf esmf-aspect-meta-model-types + + org.apache.commons + commons-text + @@ -57,11 +66,6 @@ assertj-core test - - org.mozilla - rhino - test - org.eclipse.esmf esmf-test-resources @@ -92,60 +96,6 @@ true - - org.codehaus.gmaven - groovy-maven-plugin - ${groovy-maven-plugin-version} - - - generate-unit-java - generate-sources - - execute - - - ${project.basedir}/buildSrc/main/groovy/unit2java.groovy - - - - generate-unit-js - generate-resources - - execute - - - ${project.basedir}/buildSrc/main/groovy/unit2js.groovy - - - - - - org.apache.jena - jena-arq - ${jena-version} - - - org.apache.jena - jena-core - ${jena-version} - - - org.eclipse.esmf - esmf-semantic-aspect-meta-model - ${aspect-meta-model-version} - - - com.google.guava - guava - ${guava-version} - - - com.github.javaparser - javaparser-symbol-solver-core - ${javaparser-version} - - - org.apache.maven.plugins @@ -153,7 +103,7 @@ - ${project.basedir}/src-gen + ${generated-sources} @@ -171,22 +121,20 @@ - ${project.basedir}/src-gen/main/java + ${generated-sources}/main/java - add-resource + add-src-buildtime-source initialize - add-resource + add-source - - - ${project.basedir}/src-gen/main/resources - - + + ${build-time-sources}/main/java + @@ -203,6 +151,38 @@ + + + compile-build-time-code + generate-sources + + compile + + + ${build-time-sources} + ${generated-sources} + + + + + + + org.codehaus.mojo + exec-maven-plugin + + + generate-units-and-quantitykinds + process-sources + + java + + + org.eclipse.esmf.buildtime.GenerateUnitsTtl + + ${generated-sources} + + + diff --git a/core/esmf-aspect-meta-model-java/src-buildtime/main/java/org/eclipse/esmf/buildtime/GenerateUnitsTtl.java b/core/esmf-aspect-meta-model-java/src-buildtime/main/java/org/eclipse/esmf/buildtime/GenerateUnitsTtl.java new file mode 100644 index 000000000..a9881e339 --- /dev/null +++ b/core/esmf-aspect-meta-model-java/src-buildtime/main/java/org/eclipse/esmf/buildtime/GenerateUnitsTtl.java @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2024 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.buildtime; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.util.List; +import java.util.Locale; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.esmf.aspectmodel.vocabulary.SAMM; +import org.eclipse.esmf.samm.KnownVersion; + +import com.google.common.collect.Lists; +import com.google.common.collect.Streams; +import org.apache.commons.text.StringEscapeUtils; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.Property; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.Statement; +import org.apache.jena.riot.RDFLanguages; +import org.apache.jena.vocabulary.RDF; + +/** + * Generates Java classes for the Units and QuantityKinds defined in SAMM. + */ +public class GenerateUnitsTtl { + private final Model unitsModel; + + private static final String UNITS_CLASS_TEMPLATE = """ + /* + * Copyright (c) 2024 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; + + import java.util.Arrays; + import java.util.HashMap; + import java.util.List; + import java.util.Locale; + import java.util.Map; + import java.util.Optional; + import java.util.Set; + import java.util.HashSet; + import java.util.Collections; + import java.util.stream.Collectors; + + import org.eclipse.esmf.aspectmodel.urn.AspectModelUrn; + import org.eclipse.esmf.metamodel.QuantityKind; + import org.eclipse.esmf.metamodel.Unit; + import org.eclipse.esmf.metamodel.impl.DefaultUnit; + import org.eclipse.esmf.samm.KnownVersion; + import org.eclipse.esmf.metamodel.loader.MetaModelBaseAttributes; + import org.eclipse.esmf.metamodel.datatypes.LangString; + + /** + * Enumeration of Units as defined in Recommendation 20 by + * the UNECE (United Nations Economic Commission for Europe). + */ + public class Units { + private static final Map UNITS_BY_NAME = new HashMap<>(); + + private Units() { + } + + // ${initMethods} + + /** + * Returns the unit with a given name + */ + public static synchronized Optional fromName( final String name ) { + if ( UNITS_BY_NAME.isEmpty() ) { + // ${initMethodCalls} + } + return Optional.ofNullable( UNITS_BY_NAME.get( name ) ); + } + + /** + * Finds the unit with a given code + */ + public static Optional fromCode( final String code ) { + if ( UNITS_BY_NAME.isEmpty() ) { + fromName( "" ); + } + return UNITS_BY_NAME.values() + .stream() + .filter( unit -> unit.getCode().map( code2 -> code2.equals( code ) ).orElse( false ) ) + .findAny(); + } + + /** + * Finds the units with a given symbol. In most, but not all cases, this set will contain exactly one unit. + */ + public static Set fromSymbol( final String symbol ) { + if ( UNITS_BY_NAME.isEmpty() ) { + fromName( "" ); + } + return UNITS_BY_NAME.values() + .stream() + .flatMap( unit -> unit.getSymbol() + .filter( symbol2 -> symbol2.equals( symbol ) ) + .stream() + .map( symbol2 -> unit ) ) + .collect( Collectors.toSet() ); + } + + /** + * Returns all units of a given quantity kind + */ + public static Set unitsWithQuantityKind( final QuantityKind quantityKind ) { + if ( UNITS_BY_NAME.isEmpty() ) { + fromName( "" ); + } + return UNITS_BY_NAME.values() + .stream() + .filter( unit -> unit.getQuantityKinds().contains( quantityKind ) ) + .collect( Collectors.toSet() ); + } + } + """; + + private static final String QUANTITY_KINDS_CLASS_TEMPLATE = """ + /* + * Copyright (c) 2024 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; + + import java.util.Arrays; + import java.util.Optional; + + import org.eclipse.esmf.aspectmodel.urn.AspectModelUrn; + import org.eclipse.esmf.metamodel.QuantityKind; + import org.eclipse.esmf.metamodel.visitor.AspectVisitor; + import org.eclipse.esmf.samm.KnownVersion; + + /** + * Enumeration of Quantity Kinds as defined in Recommendation 20 + * by the UNECE (United Nations Economic Commission for Europe). + */ + public enum QuantityKinds implements QuantityKind { + // ${joinedQuantityKinds}; + + private final String name; + private final String label; + + QuantityKinds( final String name, final String label ) { + this.name = name; + this.label = label; + } + + /** + * Returns the quantity kind's unique name + */ + @Override + public String getName() { + return name; + } + + /** + * Returns the quantity kind's human-readable name + */ + @Override + public String getLabel() { + return label; + } + + /** + * Returns the quantity kind's human-readable name + */ + @Override + public String toString() { + return getLabel(); + } + + @Override + public Optional getAspectModelUrn() { + return Optional.of( AspectModelUrn.fromUrn( + String.format( "urn:samm:org.eclipse.esmf.samm:unit:%s#%s", KnownVersion.getLatest().toVersionString(), name ) ) ); + } + + @Override + public KnownVersion getMetaModelVersion() { + return KnownVersion.getLatest(); + } + + @Override + public T accept( final AspectVisitor visitor, final C context ) { + return visitor.visitQuantityKind( this, context ); + } + + /** + * Finds the quantity kind with a given name + */ + public static Optional fromName( final String name ) { + return Arrays.stream( QuantityKinds.values() ) + .filter( quantityKind -> quantityKind.getName().equals( name ) ) + .map( QuantityKind.class::cast ) + .findAny(); + } + } + """; + + /* + * args[0]: Path to src-gen directory + */ + public static void main( final String[] args ) { + final String pathToUnitsTtl = "samm/unit/" + KnownVersion.getLatest().toVersionString() + "/units.ttl"; + final Model unitsModel = ModelFactory.createDefaultModel(); + unitsModel.read( GenerateUnitsTtl.class.getClassLoader().getResourceAsStream( pathToUnitsTtl ), "", RDFLanguages.TURTLE.getName() ); + + final String input = args[0]; + final Path targetPackage = Path.of( input ).resolve( "main" ).resolve( "java" ).resolve( "org" ).resolve( "eclipse" ) + .resolve( "esmf" ).resolve( "metamodel" ); + targetPackage.toFile().mkdirs(); + final File unitsFile = targetPackage.resolve( "Units.java" ).toFile(); + final File quantityKindsFile = targetPackage.resolve( "QuantityKinds.java" ).toFile(); + + final GenerateUnitsTtl generator = new GenerateUnitsTtl( unitsModel ); + try { + try ( final OutputStream outputStream = new FileOutputStream( unitsFile ); + final OutputStreamWriter outputStreamWriter = new OutputStreamWriter( outputStream, StandardCharsets.UTF_8 ); + final PrintWriter units = new PrintWriter( outputStreamWriter ) ) { + generator.writeUnitsJava( units ); + } + System.out.println( "Written " + unitsFile ); + try ( final OutputStream outputStream = new FileOutputStream( quantityKindsFile ); + final OutputStreamWriter outputStreamWriter = new OutputStreamWriter( outputStream, StandardCharsets.UTF_8 ); + final PrintWriter quantityKinds = new PrintWriter( outputStreamWriter ) ) { + generator.writeQuantityKindsJava( quantityKinds ); + } + System.out.println( "Written " + quantityKindsFile ); + } catch ( final IOException exception ) { + throw new RuntimeException( "Could not write units file", exception ); + } + } + + public GenerateUnitsTtl( final Model unitsModel ) { + this.unitsModel = unitsModel; + } + + private String toUpperSnakeCase( final String s ) { + return s.replaceAll( "([A-Z])", "_$1" ).toUpperCase().replaceAll( "^_", "" ); + } + + private void writeUnitsJava( final PrintWriter out ) { + final List> declarationSlices = Lists.partition( unitDeclarations(), 100 ); + UNITS_CLASS_TEMPLATE.lines().forEach( line -> { + if ( line.contains( "${initMethods}" ) ) { + printInitMethods( out, declarationSlices ); + } else if ( line.contains( "${initMethodCalls}" ) ) { + for ( int i = 0; i < declarationSlices.size(); i++ ) { + out.println( "init" + i + "();" ); + } + } else { + out.println( line ); + } + } ); + } + + private void printInitMethods( final PrintWriter out, final List> declarationSlices ) { + for ( int i = 0; i < declarationSlices.size(); i++ ) { + final List statements = declarationSlices.get( i ); + out.println( "private static void init" + i + "() {" ); + statements.forEach( out::println ); + out.println( "}" ); + out.println(); + } + } + + private Optional optionalAttributeValue( final Resource resource, final Property property ) { + return Optional.ofNullable( resource.getProperty( property ) ); + } + + private List attributeValues( final Resource resource, final Property property ) { + return Streams.stream( resource.listProperties( property ) ).toList(); + } + + private List unitDeclarations() { + final SAMM samm = new SAMM( KnownVersion.getLatest() ); + + final Function, String> buildDeclaration = optionalValue -> + optionalValue.map( StringEscapeUtils::escapeJava ).map( "Optional.of(\"%s\")"::formatted ).orElse( "Optional.empty()" ); + final Function> buildLangString = statement -> + !"und".equals( Locale.forLanguageTag( statement.getLanguage() ).toLanguageTag() ) + ? Stream.of( "new LangString( \"%s\", Locale.forLanguageTag( \"%s\" ) )" + .formatted( StringEscapeUtils.escapeJava( statement.getString() ), statement.getLanguage() ) ) + : Stream.empty(); + + return Streams.stream( unitsModel.listStatements( null, RDF.type, samm.Unit() ) ).map( Statement::getSubject ).map( unit -> { + final String name = unit.getLocalName(); + final String symbolDeclaration = buildDeclaration.apply( + optionalAttributeValue( unit, samm.symbol() ).map( Statement::getString ) ); + final String commonCodeDeclaration = buildDeclaration.apply( + optionalAttributeValue( unit, samm.commonCode() ).map( Statement::getString ) ); + final String referenceUnitDeclaration = buildDeclaration.apply( + optionalAttributeValue( unit, samm.referenceUnit() ).map( Statement::getResource ).map( Resource::getLocalName ) ); + final String conversionFactorDeclaration = buildDeclaration.apply( + optionalAttributeValue( unit, samm.conversionFactor() ).map( Statement::getString ) ); + final String preferredNames = attributeValues( unit, samm.preferredName() ).stream().flatMap( buildLangString ) + .collect( Collectors.joining( ", ", "Set.of(", ")" ) ); + final String descriptions = attributeValues( unit, samm.description() ).stream().flatMap( buildLangString ) + .collect( Collectors.joining( ", ", "Set.of(", ")" ) ); + final String see = attributeValues( unit, samm.see() ).stream().map( seeValue -> "\"" + seeValue + "\"" ) + .collect( Collectors.joining( ", ", "List.of(", ")" ) ); + final String quantityKindDefs = attributeValues( unit, samm.quantityKind() ).stream() + .map( quantityKind -> "QuantityKinds." + toUpperSnakeCase( quantityKind.getResource().getLocalName() ) ) + .collect( Collectors.joining( ", ", "new HashSet<>(Arrays.asList(", "))" ) ); + final String quantityKinds = quantityKindDefs.contains( "()" ) ? "Collections.emptySet()" : quantityKindDefs; + + final String metaModelBaseAttributes = + "new MetaModelBaseAttributes( AspectModelUrn.fromUrn( \"%s\" ), \"%s\", %s, %s, %s )".formatted( + unit.getURI(), name, preferredNames, descriptions, see ); + final String unitDefinition = "new DefaultUnit( %s, %s, %s, %s, %s, %s )".formatted( metaModelBaseAttributes, symbolDeclaration, + commonCodeDeclaration, referenceUnitDeclaration, conversionFactorDeclaration, quantityKinds ); + return "UNITS_BY_NAME.put( \"%s\", %s );".formatted( name, unitDefinition ); + } ).sorted().toList(); + } + + private List quantityKindDeclarations() { + final SAMM samm = new SAMM( KnownVersion.getLatest() ); + + return Streams.stream( unitsModel.listStatements( null, RDF.type, samm.QuantityKind() ) ).map( Statement::getSubject ) + .map( quantityKind -> { + final String name = quantityKind.getLocalName(); + final String label = attributeValues( quantityKind, samm.preferredName() ).stream().map( Statement::getString ).findAny() + .orElse( "" ); + return "%s( \"%s\", \"%s\" )".formatted( toUpperSnakeCase( name ), name, label ); + } ).toList(); + } + + private void writeQuantityKindsJava( final PrintWriter out ) { + QUANTITY_KINDS_CLASS_TEMPLATE.lines().forEach( line -> { + if ( line.contains( "${joinedQuantityKinds}" ) ) { + out.println( String.join( ",\n", quantityKindDeclarations() ) + ";" ); + } else { + out.println( line ); + } + } ); + } +} diff --git a/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/loader/AttributeValueRetriever.java b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/loader/AttributeValueRetriever.java index 733f79bf0..62d3b42db 100644 --- a/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/loader/AttributeValueRetriever.java +++ b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/loader/AttributeValueRetriever.java @@ -67,7 +67,7 @@ protected Statement attributeValue( final Resource modelElement, final Property * @return the optional statement asserting the value */ protected Optional optionalAttributeValue( final Resource modelElement, final Property attribute ) { - return attributeValues( modelElement, attribute ).stream().sequential().findFirst(); + return attributeValues( modelElement, attribute ).stream().findFirst(); } private boolean isRdfList( final Resource resource ) { diff --git a/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/loader/MetaModelBaseAttributes.java b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/loader/MetaModelBaseAttributes.java index 56b2d578a..0277d897a 100644 --- a/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/loader/MetaModelBaseAttributes.java +++ b/core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/metamodel/loader/MetaModelBaseAttributes.java @@ -50,7 +50,17 @@ public class MetaModelBaseAttributes { private final List see; private final boolean hasSyntheticName; - public MetaModelBaseAttributes( final KnownVersion metaModelVersion, + public MetaModelBaseAttributes( + final AspectModelUrn urn, + final String name, + final Set preferredNames, + final Set descriptions, + final List see ) { + this( KnownVersion.getLatest(), urn, name, preferredNames, descriptions, see, false ); + } + + public MetaModelBaseAttributes( + final KnownVersion metaModelVersion, final AspectModelUrn urn, final String name, final Set preferredNames, 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 10d4212e6..b191ec8da 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 @@ -176,7 +176,7 @@ public QuantityKind findOrCreateQuantityKind( final Resource quantityKindResourc public Unit findOrCreateUnit( final Resource unitResource ) { if ( unit.getNamespace().equals( unitResource.getNameSpace() ) ) { final AspectModelUrn unitUrn = AspectModelUrn.fromUrn( unitResource.getURI() ); - return Units.fromName( unitUrn.getName(), metaModelVersion ).orElseThrow( () -> + return Units.fromName( unitUrn.getName() ).orElseThrow( () -> new AspectLoadingException( "Unit definition for " + unitUrn + " is invalid" ) ); } diff --git a/core/esmf-aspect-meta-model-java/src/test/java/org/eclipse/esmf/metamodel/UnitGenerationTest.java b/core/esmf-aspect-meta-model-java/src/test/java/org/eclipse/esmf/metamodel/UnitGenerationTest.java index 12217dca7..719cc4a89 100644 --- a/core/esmf-aspect-meta-model-java/src/test/java/org/eclipse/esmf/metamodel/UnitGenerationTest.java +++ b/core/esmf-aspect-meta-model-java/src/test/java/org/eclipse/esmf/metamodel/UnitGenerationTest.java @@ -14,17 +14,11 @@ import static org.assertj.core.api.Assertions.assertThat; -import java.io.InputStream; import java.util.Locale; import java.util.Optional; -import java.util.Scanner; import java.util.Set; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; -import org.mozilla.javascript.Context; -import org.mozilla.javascript.Scriptable; -import org.mozilla.javascript.ScriptableObject; public class UnitGenerationTest { @Test @@ -33,7 +27,7 @@ public void testUnitFromName() { final Unit unit = optionalUnit.get(); assertThat( unit.getPreferredName( Locale.ENGLISH ) ).isEqualTo( "degree Celsius" ); - assertThat( unit.getReferenceUnit() ).get().isEqualTo( "kelvin" ); + assertThat( unit.getReferenceUnit().get() ).isEqualTo( "kelvin" ); assertThat( unit.getConversionFactor().get() ).isEqualTo( "1 × K" ); } @@ -61,9 +55,9 @@ public void testUnitFromSymbol() { @Test public void testUnitsWithQuantityKind() { final Set units = Units.unitsWithQuantityKind( QuantityKinds.DISTANCE ); - Assertions.assertThat( units ).containsAnyOf( Units.fromName( "nanometre" ).get(), Units.fromName( "metre" ).get(), + assertThat( units ).containsAnyOf( Units.fromName( "nanometre" ).get(), Units.fromName( "metre" ).get(), Units.fromName( "kilometre" ).get(), Units.fromName( "foot" ).get(), Units.fromName( "lightYear" ).get() ); - Assertions.assertThat( units ).doesNotContain( Units.fromName( "degreeCelsius" ).get(), Units.fromName( "litre" ).get(), + assertThat( units ).doesNotContain( Units.fromName( "degreeCelsius" ).get(), Units.fromName( "litre" ).get(), Units.fromName( "electronvoltPerMetre" ).get() ); } @@ -75,45 +69,9 @@ public void testGeneratedQuantityKinds() { @Test public void testQuantityKindFromName() { final Optional optionalQuantityKind = QuantityKinds.fromName( "distance" ); - assertThat( optionalQuantityKind ).get().isEqualTo( QuantityKinds.DISTANCE ); + assertThat( optionalQuantityKind.get() ).isEqualTo( QuantityKinds.DISTANCE ); final QuantityKind quantityKind = optionalQuantityKind.get(); assertThat( quantityKind.getName() ).isEqualTo( "distance" ); assertThat( quantityKind.getLabel() ).isEqualTo( "distance" ); } - - @Test - public void testJavaScriptUnits() { - final InputStream js = UnitGenerationTest.class.getClassLoader().getResourceAsStream( "samm-units.js" ); - final String sammUnits = new Scanner( js, "UTF-8" ).useDelimiter( "\\A" ).next(); - - final Context context = Context.enter(); - final Scriptable scope = context.initStandardObjects(); - - // Evaluate .js - context.evaluateString( scope, sammUnits, "", 1, null ); - - final ScriptableObject samm = (ScriptableObject) scope.get( "samm", scope ); - assertThat( samm ).isNotNull(); - assertThat( samm ).isNotEqualTo( Scriptable.NOT_FOUND ); - assertThat( Context.toString( samm ) ).isEqualTo( "[object Object]" ); - - final ScriptableObject units = (ScriptableObject) samm.get( "units" ); - assertThat( units ).isNotNull(); - assertThat( units ).isNotEqualTo( Scriptable.NOT_FOUND ); - assertThat( Context.toString( units ) ).isEqualTo( "[object Object]" ); - assertThat( units.size() ).isGreaterThanOrEqualTo( 800 ); - - final ScriptableObject degreeCelsius = (ScriptableObject) units.get( "degreeCelsius" ); - assertThat( degreeCelsius ).isNotNull(); - assertThat( degreeCelsius ).isNotEqualTo( Scriptable.NOT_FOUND ); - assertThat( Context.toString( degreeCelsius ) ).isEqualTo( "[object Object]" ); - assertThat( Context.toString( degreeCelsius.get( "name" ) ) ).isEqualTo( "degreeCelsius" ); - assertThat( Context.toString( degreeCelsius.get( "label" ) ) ).isEqualTo( "degree Celsius" ); - - final ScriptableObject quantityKinds = (ScriptableObject) samm.get( "quantityKinds" ); - assertThat( quantityKinds ).isNotNull(); - assertThat( quantityKinds ).isNotEqualTo( Scriptable.NOT_FOUND ); - - assertThat( quantityKinds.size() ).isGreaterThanOrEqualTo( 80 ); - } } diff --git a/core/esmf-aspect-meta-model-java/src/test/java/org/eclipse/esmf/metamodel/loader/QuantifiableInstantiatorTest.java b/core/esmf-aspect-meta-model-java/src/test/java/org/eclipse/esmf/metamodel/loader/QuantifiableInstantiatorTest.java index 8f7e46348..60fc8ed55 100644 --- a/core/esmf-aspect-meta-model-java/src/test/java/org/eclipse/esmf/metamodel/loader/QuantifiableInstantiatorTest.java +++ b/core/esmf-aspect-meta-model-java/src/test/java/org/eclipse/esmf/metamodel/loader/QuantifiableInstantiatorTest.java @@ -15,6 +15,13 @@ import static org.assertj.core.api.Assertions.assertThat; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Optional; +import java.util.Set; + import org.eclipse.esmf.aspectmodel.urn.AspectModelUrn; import org.eclipse.esmf.characteristic.Duration; import org.eclipse.esmf.characteristic.Measurement; @@ -24,6 +31,8 @@ import org.eclipse.esmf.metamodel.QuantityKinds; import org.eclipse.esmf.metamodel.Scalar; import org.eclipse.esmf.metamodel.Unit; +import org.eclipse.esmf.metamodel.datatypes.LangString; +import org.eclipse.esmf.metamodel.impl.DefaultUnit; import org.eclipse.esmf.samm.KnownVersion; import org.eclipse.esmf.test.TestAspect; import org.eclipse.esmf.test.TestModel; @@ -120,6 +129,6 @@ public void testDurationCharacteristicInstantiationExpectSuccess( final KnownVer final Unit unit = duration.getUnit().get(); assertThat( unit.getName() ).isEqualTo( "kilosecond" ); assertThat( unit.getSymbol().get() ).isEqualTo( "ks" ); - assertThat( unit.getQuantityKinds() ).hasSize( 10 ); + assertThat( unit.getQuantityKinds() ).hasSize( 1 ); } } diff --git a/core/esmf-aspect-meta-model-version-migrator/src/test/java/org/eclipse/esmf/aspectmodel/versionupdate/MigratorServiceLoaderTest.java b/core/esmf-aspect-meta-model-version-migrator/src/test/java/org/eclipse/esmf/aspectmodel/versionupdate/MigratorServiceLoaderTest.java index f904f4003..ec53533e9 100644 --- a/core/esmf-aspect-meta-model-version-migrator/src/test/java/org/eclipse/esmf/aspectmodel/versionupdate/MigratorServiceLoaderTest.java +++ b/core/esmf-aspect-meta-model-version-migrator/src/test/java/org/eclipse/esmf/aspectmodel/versionupdate/MigratorServiceLoaderTest.java @@ -15,7 +15,6 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; public class MigratorServiceLoaderTest { @@ -24,6 +23,6 @@ public class MigratorServiceLoaderTest { @Test public void testLoadService() { assertThat( migratorService.getMigratorFactory().get() ).isInstanceOf( TestMigratorFactory1.class ); - Assertions.assertThat( migratorService.getMigratorFactory().get().createMigrators() ).hasSize( 4 ); + assertThat( migratorService.getMigratorFactory().get().createMigrators() ).hasSize( 4 ); } } diff --git a/core/esmf-aspect-meta-model-version-migrator/src/test/java/org/eclipse/esmf/aspectmodel/versionupdate/MigratorTest.java b/core/esmf-aspect-meta-model-version-migrator/src/test/java/org/eclipse/esmf/aspectmodel/versionupdate/MigratorTest.java index b2773ec07..6b291e7b5 100644 --- a/core/esmf-aspect-meta-model-version-migrator/src/test/java/org/eclipse/esmf/aspectmodel/versionupdate/MigratorTest.java +++ b/core/esmf-aspect-meta-model-version-migrator/src/test/java/org/eclipse/esmf/aspectmodel/versionupdate/MigratorTest.java @@ -34,7 +34,6 @@ import org.apache.jena.rdf.model.RDFNode; import org.apache.jena.rdf.model.Statement; import org.apache.jena.vocabulary.RDF; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -64,8 +63,7 @@ public void testUriRewriting( final KnownVersion metaModelVersion ) { final VersionedModel versionedModel = TestResources.getModelWithoutResolution( TestAspect.ASPECT, metaModelVersion ); final VersionedModel rewrittenModel = migratorService.updateMetaModelVersion( versionedModel ).get(); - Assertions.assertThat( rewrittenModel.getMetaModelVersion() ) - .isEqualTo( VersionNumber.parse( KnownVersion.getLatest().toVersionString() ) ); + assertThat( rewrittenModel.getMetaModelVersion() ).isEqualTo( VersionNumber.parse( KnownVersion.getLatest().toVersionString() ) ); final Model model = rewrittenModel.getRawModel(); assertThat( model.getNsPrefixURI( "samm" ) ).contains( KnownVersion.getLatest().toVersionString() ); diff --git a/core/esmf-aspect-model-aas-generator/pom.xml b/core/esmf-aspect-model-aas-generator/pom.xml index e0454c945..f4fe53349 100644 --- a/core/esmf-aspect-model-aas-generator/pom.xml +++ b/core/esmf-aspect-model-aas-generator/pom.xml @@ -24,19 +24,19 @@ org.eclipse.digitaltwin.aas4j - model + aas4j-model org.eclipse.digitaltwin.aas4j - dataformat-xml + aas4j-dataformat-xml org.eclipse.digitaltwin.aas4j - dataformat-aasx + aas4j-dataformat-aasx org.eclipse.digitaltwin.aas4j - dataformat-json + aas4j-dataformat-json org.apache.poi diff --git a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AasToAspectModelGenerator.java b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AasToAspectModelGenerator.java index ac348f68c..0ae11da20 100644 --- a/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AasToAspectModelGenerator.java +++ b/core/esmf-aspect-model-aas-generator/src/main/java/org/eclipse/esmf/aspectmodel/aas/AasToAspectModelGenerator.java @@ -70,8 +70,8 @@ import org.apache.jena.vocabulary.RDF; import org.apache.jena.vocabulary.XSD; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.eclipse.digitaltwin.aas4j.v3.dataformat.DeserializationException; import org.eclipse.digitaltwin.aas4j.v3.dataformat.aasx.AASXDeserializer; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.DeserializationException; import org.eclipse.digitaltwin.aas4j.v3.dataformat.json.JsonDeserializer; import org.eclipse.digitaltwin.aas4j.v3.dataformat.xml.XmlDeserializer; import org.eclipse.digitaltwin.aas4j.v3.model.AasSubmodelElements; @@ -134,7 +134,7 @@ public static AasToAspectModelGenerator fromAasx( final InputStream inputStream public static AasToAspectModelGenerator fromAasJson( final InputStream inputStream ) { final JsonDeserializer deserializer = new JsonDeserializer(); try { - return fromEnvironment( deserializer.read( inputStream ) ); + return fromEnvironment( deserializer.read( inputStream, Environment.class ) ); } catch ( final DeserializationException exception ) { throw new AspectModelGenerationException( exception ); } diff --git a/core/esmf-aspect-model-aas-generator/src/test/java/org/eclipse/esmf/aspectmodel/aas/AasToAspectModelGeneratorTest.java b/core/esmf-aspect-model-aas-generator/src/test/java/org/eclipse/esmf/aspectmodel/aas/AasToAspectModelGeneratorTest.java index c2611f26c..ab85fc2a9 100644 --- a/core/esmf-aspect-model-aas-generator/src/test/java/org/eclipse/esmf/aspectmodel/aas/AasToAspectModelGeneratorTest.java +++ b/core/esmf-aspect-model-aas-generator/src/test/java/org/eclipse/esmf/aspectmodel/aas/AasToAspectModelGeneratorTest.java @@ -30,7 +30,7 @@ import org.eclipse.esmf.test.TestAspect; import org.eclipse.esmf.test.TestResources; -import org.eclipse.digitaltwin.aas4j.v3.dataformat.DeserializationException; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.DeserializationException; import org.eclipse.digitaltwin.aas4j.v3.dataformat.json.JsonDeserializer; import org.eclipse.digitaltwin.aas4j.v3.dataformat.xml.XmlDeserializer; import org.eclipse.digitaltwin.aas4j.v3.model.Environment; @@ -57,9 +57,8 @@ void testRoundtripConversion( final TestAspect testAspect ) throws Deserializati final Consumer assertForValidator = aspectModelGenerator -> assertThatCode( () -> { final List aspects = aspectModelGenerator.generateAspects(); - assertThat( aspects ).singleElement().satisfies( generatedAspect -> { - assertThat( generatedAspect.getAspectModelUrn().get() ).isEqualTo( aspect.getAspectModelUrn().get() ); - } ); + assertThat( aspects ).singleElement().satisfies( generatedAspect -> + assertThat( generatedAspect.getAspectModelUrn().get() ).isEqualTo( aspect.getAspectModelUrn().get() ) ); } ).doesNotThrowAnyException(); final Environment aasEnvironmentFromXml = new XmlDeserializer().read( @@ -67,7 +66,8 @@ void testRoundtripConversion( final TestAspect testAspect ) throws Deserializati assertForValidator.accept( AasToAspectModelGenerator.fromEnvironment( aasEnvironmentFromXml ) ); final Environment aasEnvironmentFromJson = new JsonDeserializer().read( - new ByteArrayInputStream( new AspectModelAasGenerator().generateAsByteArray( AasFileFormat.JSON, aspect ) ) ); + new ByteArrayInputStream( new AspectModelAasGenerator().generateAsByteArray( AasFileFormat.JSON, aspect ) ), + Environment.class ); assertForValidator.accept( AasToAspectModelGenerator.fromEnvironment( aasEnvironmentFromJson ) ); } @@ -76,9 +76,8 @@ void testGetAspectModelUrnFromSubmodelIdentifier() { // Submodel has an Aspect Model URN as identifier final Environment aasEnvironment = loadEnvironment( "SMTWithAspectModelUrnId.aas.xml" ); final AasToAspectModelGenerator aspectModelGenerator = AasToAspectModelGenerator.fromEnvironment( aasEnvironment ); - assertThat( aspectModelGenerator.generateAspects() ).singleElement().satisfies( aspect -> { - assertThat( aspect.getAspectModelUrn() ).map( AspectModelUrn::toString ).contains( "urn:samm:com.example:1.0.0#Submodel1" ); - } ); + assertThat( aspectModelGenerator.generateAspects() ).singleElement().satisfies( aspect -> + assertThat( aspect.getAspectModelUrn() ).map( AspectModelUrn::toString ).contains( "urn:samm:com.example:1.0.0#Submodel1" ) ); } @Test @@ -86,9 +85,8 @@ void testGetAspectModelUrnFromConceptDescription() { // Submodel has a Concept Description that points to an Aspect Model URN final Environment aasEnvironment = loadEnvironment( "SMTWithAspectModelUrnInConceptDescription.aas.xml" ); final AasToAspectModelGenerator aspectModelGenerator = AasToAspectModelGenerator.fromEnvironment( aasEnvironment ); - assertThat( aspectModelGenerator.generateAspects() ).singleElement().satisfies( aspect -> { - assertThat( aspect.getAspectModelUrn() ).map( AspectModelUrn::toString ).contains( "urn:samm:com.example:1.0.0#Submodel1" ); - } ); + assertThat( aspectModelGenerator.generateAspects() ).singleElement().satisfies( aspect -> + assertThat( aspect.getAspectModelUrn() ).map( AspectModelUrn::toString ).contains( "urn:samm:com.example:1.0.0#Submodel1" ) ); } @Test @@ -97,9 +95,9 @@ void testConstructAspectModelUrn1() { // It has a version and an IRI identifier and an idShort final Environment aasEnvironment = loadEnvironment( "SMTAspectModelUrnInConstruction1.aas.xml" ); final AasToAspectModelGenerator aspectModelGenerator = AasToAspectModelGenerator.fromEnvironment( aasEnvironment ); - assertThat( aspectModelGenerator.generateAspects() ).singleElement().satisfies( aspect -> { - assertThat( aspect.getAspectModelUrn() ).map( AspectModelUrn::toString ).contains( "urn:samm:com.example.www:1.2.3#Submodel1" ); - } ); + assertThat( aspectModelGenerator.generateAspects() ).singleElement().satisfies( aspect -> + assertThat( aspect.getAspectModelUrn() ).map( AspectModelUrn::toString ) + .contains( "urn:samm:com.example.www:1.2.3#Submodel1" ) ); } @Test @@ -108,9 +106,8 @@ void testConstructAspectModelUrn2() { // It has a version and an IRDI identifier and an idShort final Environment aasEnvironment = loadEnvironment( "SMTAspectModelUrnInConstruction2.aas.xml" ); final AasToAspectModelGenerator aspectModelGenerator = AasToAspectModelGenerator.fromEnvironment( aasEnvironment ); - assertThat( aspectModelGenerator.generateAspects() ).singleElement().satisfies( aspect -> { - assertThat( aspect.getAspectModelUrn() ).map( AspectModelUrn::toString ).contains( "urn:samm:com.example:1.2.3#Submodel1" ); - } ); + assertThat( aspectModelGenerator.generateAspects() ).singleElement().satisfies( aspect -> + assertThat( aspect.getAspectModelUrn() ).map( AspectModelUrn::toString ).contains( "urn:samm:com.example:1.2.3#Submodel1" ) ); } @Test @@ -119,9 +116,8 @@ void testConstructAspectModelUrn3() { // It has an IRDI identifier and an idShort, but no version final Environment aasEnvironment = loadEnvironment( "SMTAspectModelUrnInConstruction3.aas.xml" ); final AasToAspectModelGenerator aspectModelGenerator = AasToAspectModelGenerator.fromEnvironment( aasEnvironment ); - assertThat( aspectModelGenerator.generateAspects() ).singleElement().satisfies( aspect -> { - assertThat( aspect.getAspectModelUrn() ).map( AspectModelUrn::toString ).contains( "urn:samm:com.example:1.0.0#Submodel1" ); - } ); + assertThat( aspectModelGenerator.generateAspects() ).singleElement().satisfies( aspect -> + assertThat( aspect.getAspectModelUrn() ).map( AspectModelUrn::toString ).contains( "urn:samm:com.example:1.0.0#Submodel1" ) ); } @Test @@ -130,10 +126,9 @@ void testConstructAspectModelUrn4() { // It has an IRDI identifier, but no idShort and no version final Environment aasEnvironment = loadEnvironment( "SMTAspectModelUrnInConstruction4.aas.xml" ); final AasToAspectModelGenerator aspectModelGenerator = AasToAspectModelGenerator.fromEnvironment( aasEnvironment ); - assertThat( aspectModelGenerator.generateAspects() ).singleElement().satisfies( aspect -> { - assertThat( aspect.getAspectModelUrn() ).map( AspectModelUrn::toString ) - .contains( "urn:samm:com.example:1.0.0#AAAAAA000abf2fd07" ); - } ); + assertThat( aspectModelGenerator.generateAspects() ).singleElement().satisfies( aspect -> + assertThat( aspect.getAspectModelUrn() ).map( AspectModelUrn::toString ) + .contains( "urn:samm:com.example:1.0.0#AAAAAA000abf2fd07" ) ); } private Environment loadEnvironment( final String name ) { diff --git a/core/esmf-aspect-model-aas-generator/src/test/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAasGeneratorTest.java b/core/esmf-aspect-model-aas-generator/src/test/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAasGeneratorTest.java index c1df75b05..fa8b14467 100644 --- a/core/esmf-aspect-model-aas-generator/src/test/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAasGeneratorTest.java +++ b/core/esmf-aspect-model-aas-generator/src/test/java/org/eclipse/esmf/aspectmodel/aas/AspectModelAasGeneratorTest.java @@ -35,7 +35,7 @@ import org.eclipse.esmf.test.TestResources; import com.fasterxml.jackson.databind.JsonNode; -import org.eclipse.digitaltwin.aas4j.v3.dataformat.DeserializationException; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.DeserializationException; import org.eclipse.digitaltwin.aas4j.v3.dataformat.xml.XmlDeserializer; import org.eclipse.digitaltwin.aas4j.v3.model.AbstractLangString; import org.eclipse.digitaltwin.aas4j.v3.model.ConceptDescription; diff --git a/core/esmf-aspect-model-document-generators/pom.xml b/core/esmf-aspect-model-document-generators/pom.xml index c9bde8861..b687c8f5a 100644 --- a/core/esmf-aspect-model-document-generators/pom.xml +++ b/core/esmf-aspect-model-document-generators/pom.xml @@ -107,6 +107,11 @@ json-schema-validator test + + com.fasterxml.jackson.core + jackson-annotations + test + com.jayway.jsonpath json-path diff --git a/core/esmf-aspect-model-document-generators/src/test/java/org/eclipse/esmf/aspectmodel/generator/diagram/AspectModelDiagramGeneratorTest.java b/core/esmf-aspect-model-document-generators/src/test/java/org/eclipse/esmf/aspectmodel/generator/diagram/AspectModelDiagramGeneratorTest.java index cf5c11d3b..90acd6edc 100644 --- a/core/esmf-aspect-model-document-generators/src/test/java/org/eclipse/esmf/aspectmodel/generator/diagram/AspectModelDiagramGeneratorTest.java +++ b/core/esmf-aspect-model-document-generators/src/test/java/org/eclipse/esmf/aspectmodel/generator/diagram/AspectModelDiagramGeneratorTest.java @@ -48,7 +48,7 @@ void testGen( final TestAspect testAspect ) { } @ParameterizedTest - @ValueSource( strings = { "UTF-8", "US-ASCII" } ) + @ValueSource( strings = { "UTF-8", "US-ASCII", "Windows-1252" } ) void generateDiagramsShouldReturnUtf8StringRegardlessOfPlatformEncoding( final String encoding ) { final String platformEncoding = System.getProperty( "file.encoding" ); try { @@ -63,6 +63,7 @@ void generateDiagramsShouldReturnUtf8StringRegardlessOfPlatformEncoding( final S generator.generateDiagram( AspectModelDiagramGenerator.Format.SVG, Locale.ENGLISH, out ); final String svg = out.toString( StandardCharsets.UTF_8 ); assertThat( svg ).contains( "«Aspect»" ); + assertThat( out.toByteArray() ).containsSubsequence( "«Aspect»".getBytes( StandardCharsets.UTF_8 ) ); } ).doesNotThrowAnyException(); } finally { System.setProperty( "file.encoding", platformEncoding ); diff --git a/core/esmf-aspect-model-document-generators/src/test/java/org/eclipse/esmf/aspectmodel/generator/json/AspectModelJsonPayloadGeneratorTest.java b/core/esmf-aspect-model-document-generators/src/test/java/org/eclipse/esmf/aspectmodel/generator/json/AspectModelJsonPayloadGeneratorTest.java index 34e3b7dfb..c9b1e8f36 100644 --- a/core/esmf-aspect-model-document-generators/src/test/java/org/eclipse/esmf/aspectmodel/generator/json/AspectModelJsonPayloadGeneratorTest.java +++ b/core/esmf-aspect-model-document-generators/src/test/java/org/eclipse/esmf/aspectmodel/generator/json/AspectModelJsonPayloadGeneratorTest.java @@ -124,8 +124,6 @@ public class AspectModelJsonPayloadGeneratorTest extends MetaModelVersions { private static DatatypeFactory datatypeFactory; - private final Random random = new Random(); - @BeforeAll static void setup() { try { @@ -415,8 +413,8 @@ public void testGenerateAspectWithDateTimeTypeForRangeConstraints( final KnownVe final String generatedJson = generateJsonForModel( TestAspect.ASPECT_WITH_G_TYPE_FOR_RANGE_CONSTRAINTS, metaModelVersion ); final AspectWithGTypeForRangeConstraints aspectWithGtypeForRangeConstraints = parseJson( generatedJson, AspectWithGTypeForRangeConstraints.class ); - final Pattern dayPattern = Pattern.compile( "---(0[1-9]|[12][0-9]|3[01])(Z|(\\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00))?" ); - final Pattern monthPattern = Pattern.compile( "--(0[1-9]|1[0-2])(Z|(\\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00))?" ); + final Pattern dayPattern = Pattern.compile( "---(0[1-9]|[12][0-9]|3[01])(Z|([+\\-])((0[0-9]|1[0-3]):[0-5][0-9]|14:00))?" ); + final Pattern monthPattern = Pattern.compile( "--(0[1-9]|1[0-2])(Z|([+\\-])((0[0-9]|1[0-3]):[0-5][0-9]|14:00))?" ); assertThat( dayPattern.matcher( aspectWithGtypeForRangeConstraints.getTestPropertyWithGDay().toString() ) ).matches(); assertThat( monthPattern.matcher( aspectWithGtypeForRangeConstraints.getTestPropertyWithGMonth().toString() ) ).matches(); } diff --git a/core/esmf-aspect-model-java-generator/pom.xml b/core/esmf-aspect-model-java-generator/pom.xml index 1c8c3d921..65b8f5117 100644 --- a/core/esmf-aspect-model-java-generator/pom.xml +++ b/core/esmf-aspect-model-java-generator/pom.xml @@ -61,6 +61,10 @@ org.apache.jena jena-core + + com.fasterxml.jackson.core + jackson-databind + 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 3390003eb..3afa5e33c 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 @@ -256,10 +256,10 @@ private String optionalString( final Optional optionalString ) { @Override public String visitUnit( final Unit unit, final StaticCodeGenerationContext context ) { - final Optional unitFromCatalog = Units.fromName( unit.getName(), unit.getMetaModelVersion() ); + final Optional unitFromCatalog = Units.fromName( unit.getName() ); if ( unitFromCatalog.isPresent() ) { context.getCodeGenerationConfig().importTracker().importExplicit( Units.class ); - return "Units.fromName(\"" + unit.getName() + "\", KnownVersion." + unit.getMetaModelVersion() + ")"; + return "Units.fromName(\"" + unit.getName() + "\")"; } context.getCodeGenerationConfig().importTracker().importExplicit( DefaultUnit.class ); @@ -535,7 +535,7 @@ private String getOptionalStaticDeclarationValue( final Type type, final Opt } if ( optionalValue.get() instanceof ScalarValue ) { - return "Optional.of(" + ((ScalarValue) optionalValue.get()).accept( this, context ) + ")"; + return "Optional.of(" + ( (ScalarValue) optionalValue.get() ).accept( this, context ) + ")"; } context.getCodeGenerationConfig().importTracker().importExplicit( AspectModelJavaUtil.getDataTypeClass( type ) ); diff --git a/core/esmf-aspect-model-java-generator/src/test/java/org/eclipse/esmf/aspectmodel/java/StaticMetaModelJavaGeneratorTest.java b/core/esmf-aspect-model-java-generator/src/test/java/org/eclipse/esmf/aspectmodel/java/StaticMetaModelJavaGeneratorTest.java index 24c19d29e..d5ee0e76e 100644 --- a/core/esmf-aspect-model-java-generator/src/test/java/org/eclipse/esmf/aspectmodel/java/StaticMetaModelJavaGeneratorTest.java +++ b/core/esmf-aspect-model-java-generator/src/test/java/org/eclipse/esmf/aspectmodel/java/StaticMetaModelJavaGeneratorTest.java @@ -533,7 +533,7 @@ void testCharacteristicInstantiationForQuantifiableWithUnit( final KnownVersion "new DefaultQuantifiable(MetaModelBaseAttributes.from(KnownVersion." + KnownVersion.getLatest() + "," + " AspectModelUrn.fromUrn(NAMESPACE + \"TestQuantifiable\"), \"TestQuantifiable\")," + " new DefaultScalar(\"http://www.w3.org/2001/XMLSchema#float\", KnownVersion." + KnownVersion.getLatest() - + "), Units.fromName(\"percent\", KnownVersion." + KnownVersion.getLatest() + "))"; + + "), Units.fromName(\"percent\"))"; result.assertConstructorArgumentForProperties( "MetaAspectWithQuantifiableWithUnit", ImmutableMap. builder().put( "TEST_PROPERTY", expectedTestPropertyCharacteristicConstructorCall ).build(), 1 ); diff --git a/core/esmf-aspect-static-meta-model-java/src/main/java/org/eclipse/esmf/staticmetamodel/ComputedProperty.java b/core/esmf-aspect-static-meta-model-java/src/main/java/org/eclipse/esmf/staticmetamodel/ComputedProperty.java index 1125f0788..d92eb16c1 100644 --- a/core/esmf-aspect-static-meta-model-java/src/main/java/org/eclipse/esmf/staticmetamodel/ComputedProperty.java +++ b/core/esmf-aspect-static-meta-model-java/src/main/java/org/eclipse/esmf/staticmetamodel/ComputedProperty.java @@ -22,10 +22,8 @@ /** * Allows ad-hoc definitions of static properties that wrap another property and compute their value using a given function, taking the * original property value as an input. The computed property value also can be of a different type. - *

* A typical example would be a unit conversion, e.g. transforming a property value that is given in {@code kg} into a value that is given * in {@code gram}, by using the function {@code v -> v * 1000}. - *

* Using computation functions that use further input it is also possible to create dynamic computed properties. It is however not * recommended to build functions where the result type is dynamic. * @@ -33,9 +31,9 @@ * @param the type of the computation result */ public class ComputedProperty extends StaticProperty { - private PropertyAccessor accessor; + private final PropertyAccessor accessor; - private Function computation; + private final Function computation; private ComputedProperty( final DefaultProperty wrappedProperty, final PropertyAccessor accessor, final Function computation ) { @@ -86,7 +84,7 @@ public static ComputedProperty of( final DefaultProperty wrapped @Override public Class getPropertyType() { - if ( accessor instanceof StaticProperty staticProperty ) { + if ( accessor instanceof final StaticProperty staticProperty ) { return (Class) staticProperty.getPropertyType(); } return (Class) Object.class; @@ -94,14 +92,14 @@ public Class getPropertyType() { @Override public Class getContainingType() { - if ( accessor instanceof StaticProperty staticProperty ) { + if ( accessor instanceof final StaticProperty staticProperty ) { return staticProperty.getContainingType(); } return (Class) Object.class; } @Override - public R getValue( C object ) { + public R getValue( final C object ) { return computation.apply( accessor.getValue( object ) ); } } diff --git a/core/esmf-aspect-static-meta-model-java/src/main/java/org/eclipse/esmf/staticmetamodel/predicate/PropertyPredicates.java b/core/esmf-aspect-static-meta-model-java/src/main/java/org/eclipse/esmf/staticmetamodel/predicate/PropertyPredicates.java index 841ae3752..ddf440082 100644 --- a/core/esmf-aspect-static-meta-model-java/src/main/java/org/eclipse/esmf/staticmetamodel/predicate/PropertyPredicates.java +++ b/core/esmf-aspect-static-meta-model-java/src/main/java/org/eclipse/esmf/staticmetamodel/predicate/PropertyPredicates.java @@ -9,7 +9,6 @@ /** * Provides type safe {@link Predicate}s on properties allowing convenient and expressive filtering. - * * Property predicates can also be used with {@link PropertyChain}s in order to filter on parent elements using nested properties. * * @see PropertyPredicateBuilder @@ -19,9 +18,9 @@ public final class PropertyPredicates { * Entry point for simple predicates on single valued properties. * * @param property the property to apply the predicate to - * @return the builder * @param the type containing the property * @param the property type + * @return the builder */ public static PropertyPredicateBuilder.SingleBuilder on( final PropertyAccessor property ) { return new PropertyPredicateBuilder.SingleBuilder<>( property ); @@ -31,11 +30,12 @@ public static PropertyPredicateBuilder.SingleBuilder on( final Prop * Entry point for matching predicates on {@link CharSequence} properties. * * @param property the property to apply the predicate to - * @return the builder * @param the type containing the property * @param the property type + * @return the builder */ - public static PropertyPredicateBuilder.CharSequenceBuilder matchOn( final PropertyAccessor property ) { + public static PropertyPredicateBuilder.CharSequenceBuilder matchOn( + final PropertyAccessor property ) { return new PropertyPredicateBuilder.CharSequenceBuilder<>( property ); } @@ -43,9 +43,9 @@ public static PropertyPredicateBuilder.CharSequenceB * Entry point for predicates on {@link Comparable} properties. * * @param property the property to apply the predicate to - * @return the builder * @param the type containing the property * @param the property type + * @return the builder */ public static > PropertyPredicateBuilder.ComparableBuilder compareOn( final PropertyAccessor property ) { @@ -56,9 +56,9 @@ public static > PropertyPredicateBuilder.ComparableBu * Entry point for simple predicates on single valued {@link Optional} properties. * * @param property the property to apply the predicate to - * @return the builder * @param the type containing the property * @param the property type + * @return the builder */ public static , P> PropertyPredicateBuilder.SingleBuilder onOptional( final PropertyAccessor property ) { @@ -69,10 +69,10 @@ public static , P> PropertyPredicateBuilder.SingleBuild * Entry point for predicates on collection valued properties. * * @param property the property to apply the predicate to - * @return the builder * @param the type containing the property * @param the property type * @param

the type contained within the collection + * @return the builder */ public static , P> PropertyPredicateBuilder.CollectionBuilder onCollection( final PropertyAccessor property ) { diff --git a/core/esmf-aspect-static-meta-model-java/src/main/java/org/eclipse/esmf/staticmetamodel/propertychain/ContainerPropertyChain.java b/core/esmf-aspect-static-meta-model-java/src/main/java/org/eclipse/esmf/staticmetamodel/propertychain/ContainerPropertyChain.java index 891817ae5..7515d9201 100644 --- a/core/esmf-aspect-static-meta-model-java/src/main/java/org/eclipse/esmf/staticmetamodel/propertychain/ContainerPropertyChain.java +++ b/core/esmf-aspect-static-meta-model-java/src/main/java/org/eclipse/esmf/staticmetamodel/propertychain/ContainerPropertyChain.java @@ -22,7 +22,6 @@ /** * A {@link PropertyChain} that holds chain elements of type {@link ContainerProperty}, e.g. {@link Optional} or {@link Collection}. - * * The first container type within the chain is the one propagated to the end of the chain, i.e. if somewhere an {@code Optional} appears, * the final property type will also be an optional. The same holds true for {@code Collection}s in between. However, independent from the * collection types that are found within the chain, the final collection type will always be a {@link List}. @@ -41,9 +40,9 @@ public ContainerPropertyChain( final List getContainedType() { - return (getLastProperty() instanceof ContainerProperty container) ? - container.getContainedType() : - (Class) getLastProperty().getPropertyType(); + return ( getLastProperty() instanceof ContainerProperty container ) + ? container.getContainedType() + : (Class) getLastProperty().getPropertyType(); } @Override diff --git a/core/esmf-aspect-static-meta-model-java/src/main/java/org/eclipse/esmf/staticmetamodel/propertychain/OptionalPropertyChainElementAccessor.java b/core/esmf-aspect-static-meta-model-java/src/main/java/org/eclipse/esmf/staticmetamodel/propertychain/OptionalPropertyChainElementAccessor.java index 2b3f2ff43..58d477883 100644 --- a/core/esmf-aspect-static-meta-model-java/src/main/java/org/eclipse/esmf/staticmetamodel/propertychain/OptionalPropertyChainElementAccessor.java +++ b/core/esmf-aspect-static-meta-model-java/src/main/java/org/eclipse/esmf/staticmetamodel/propertychain/OptionalPropertyChainElementAccessor.java @@ -32,7 +32,7 @@ public Class> getHandledElementClass() { public Optional getValue( final Optional currentValue, final StaticProperty property ) { return currentValue.map( v -> { final Object nextValue = property.getValue( v ); - if (nextValue instanceof Optional nextOptional ) { + if ( nextValue instanceof Optional nextOptional ) { return nextOptional.orElse( null ); } diff --git a/core/esmf-aspect-static-meta-model-java/src/main/java/org/eclipse/esmf/staticmetamodel/propertychain/PropertyChain.java b/core/esmf-aspect-static-meta-model-java/src/main/java/org/eclipse/esmf/staticmetamodel/propertychain/PropertyChain.java index 1c219848f..2974e76b2 100644 --- a/core/esmf-aspect-static-meta-model-java/src/main/java/org/eclipse/esmf/staticmetamodel/propertychain/PropertyChain.java +++ b/core/esmf-aspect-static-meta-model-java/src/main/java/org/eclipse/esmf/staticmetamodel/propertychain/PropertyChain.java @@ -33,9 +33,7 @@ /** * Defines a chain of properties to be able to access properties of nested entities as if they were properties of one of the containing - * entities or aspects. - *

- * To build instances of property chains it is recommended to use the type safe builders. + * entities or aspects. To build instances of property chains it is recommended to use the type safe builders. * * @param the type containing the property (this is the containing type of the first chain element) * @param

the type of the property (this is the property type of the last chain element) @@ -56,24 +54,23 @@ public class PropertyChain extends DefaultProperty implements PropertyType lastProperty.getExampleValue(), lastProperty.isOptional(), lastProperty.isNotInPayload(), Optional.ofNullable( lastProperty.getPayloadName() ), lastProperty.isAbstract(), lastProperty.getExtends() ); - this.accessor = getAccessor(); + accessor = getAccessor(); this.properties = Stream.concat( properties.stream(), Stream.of( lastProperty ) ) .map( p -> (StaticProperty) p ) .toList(); - this.chainElementAccessors = PropertyChainElementAccessors.getAllPropertyAccessors(); + chainElementAccessors = PropertyChainElementAccessors.getAllPropertyAccessors(); } /** * Creates a property chain using the given list of properties. - *

* Important: This constructor does not ensure that the chain is valid and thus should only be used in situations where this is * explicitly known. * Prefer to use a builder using {@link #from(StaticProperty)}, {@link #fromOptional(StaticContainerProperty)} (StaticContainerProperty)} * or {@link #fromCollection(StaticContainerProperty)}. * - * @param properties + * @param properties the properties of the chain */ - public PropertyChain( final List> properties ) { + public PropertyChain( final List> properties ) { this( properties.subList( 0, properties.size() - 1 ), (StaticProperty) properties.get( properties.size() - 1 ) ); } @@ -118,9 +115,9 @@ public static > PropertyChainBuilder.CollectionBui } private PropertyAccessor getAccessor() { - return ( C object ) -> { + return ( final C object ) -> { Object currentValue = object; - final Iterator> propertyIterator = PropertyChain.this.properties.iterator(); + final Iterator> propertyIterator = properties.iterator(); while ( currentValue != null && propertyIterator.hasNext() ) { currentValue = getNextValue( currentValue, propertyIterator.next() ); } @@ -138,7 +135,7 @@ private Object getNextValue( final Object currentValue, final StaticProperty findPropertyChainElementAccessor( final Object currentValue ) { - return this.chainElementAccessors.stream() + return chainElementAccessors.stream() .filter( chainElementAccessor -> chainElementAccessor.getHandledElementClass().isAssignableFrom( currentValue.getClass() ) ) .findAny() .orElseGet( PropertyChainElementAccessors::getDefaultAccessor ); diff --git a/core/esmf-aspect-static-meta-model-java/src/main/java/org/eclipse/esmf/staticmetamodel/propertychain/spi/PropertyChainElementAccessor.java b/core/esmf-aspect-static-meta-model-java/src/main/java/org/eclipse/esmf/staticmetamodel/propertychain/spi/PropertyChainElementAccessor.java index 52bde3e9c..428ae2287 100644 --- a/core/esmf-aspect-static-meta-model-java/src/main/java/org/eclipse/esmf/staticmetamodel/propertychain/spi/PropertyChainElementAccessor.java +++ b/core/esmf-aspect-static-meta-model-java/src/main/java/org/eclipse/esmf/staticmetamodel/propertychain/spi/PropertyChainElementAccessor.java @@ -17,11 +17,9 @@ /** * Service Provider Interface (SPI) for classes that can handle specific cases during the resolving of a property chain. - *

- * These are e.g. needed when types within the chain are switched to complex ones like container types ({@code Optional}, {@code Collection} - * or similar). - * - * Application developers can provide custom accessors using this interface and they will be picked up by the property chain implementation. + * These are e.g. needed when types within the chain are switched to complex ones like container types ({@code Optional}, + * {@code Collection} or similar). Application developers can provide custom accessors using this interface and they will be picked up by + * the property chain implementation. * * @param the type of the chain element this accessor is able to handle */ diff --git a/core/esmf-test-resources/pom.xml b/core/esmf-test-resources/pom.xml index b3e68126e..4cc6a4fd3 100644 --- a/core/esmf-test-resources/pom.xml +++ b/core/esmf-test-resources/pom.xml @@ -36,5 +36,9 @@ org.eclipse.esmf esmf-aspect-model-resolver + + com.fasterxml.jackson.core + jackson-databind + diff --git a/core/esmf-test-resources/src/main/java/org/eclipse/esmf/test/TestResources.java b/core/esmf-test-resources/src/main/java/org/eclipse/esmf/test/TestResources.java index e5c01947d..24b5f9890 100644 --- a/core/esmf-test-resources/src/main/java/org/eclipse/esmf/test/TestResources.java +++ b/core/esmf-test-resources/src/main/java/org/eclipse/esmf/test/TestResources.java @@ -39,9 +39,8 @@ public static VersionedModel getModelWithoutResolution( final TestModel model, f model.getUrn().getNamespace(), model.getUrn().getVersion(), model.getName() ); final InputStream inputStream = TestResources.class.getClassLoader().getResourceAsStream( path ); return TurtleLoader.loadTurtle( inputStream ).flatMap( rawModel -> - metaModelResourceResolver - .mergeMetaModelIntoRawModel( rawModel, VersionNumber.parse( knownVersion.toVersionString() ) ) ) - .get(); + metaModelResourceResolver + .mergeMetaModelIntoRawModel( rawModel, VersionNumber.parse( knownVersion.toVersionString() ) ) ).get(); } public static Try getModel( final TestModel model, final KnownVersion knownVersion ) { @@ -51,7 +50,7 @@ public static Try getModel( final TestModel model, final KnownVe } public static Try getPayload( final TestModel model, final KnownVersion knownVersion ) { - final String baseDirectory = "payloads/" + (model instanceof InvalidTestAspect ? "invalid" : "valid"); + final String baseDirectory = "payloads/" + ( model instanceof InvalidTestAspect ? "invalid" : "valid" ); final String modelsRoot = baseDirectory + "/" + knownVersion.toString().toLowerCase(); return Try.of( () -> new ObjectMapper().readTree( Resources.getResource( modelsRoot + "/" + model.getName() + ".json" ) ) ); } diff --git a/esmf-checkstyle.xml b/esmf-checkstyle.xml index e5ac2c627..9aa64538f 100644 --- a/esmf-checkstyle.xml +++ b/esmf-checkstyle.xml @@ -331,7 +331,7 @@ - + diff --git a/pom.xml b/pom.xml index 3333614a1..3e8808ae9 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ org.eclipse.esmf esmf-parent - 11 + 12 esmf-sdk-parent diff --git a/tools/samm-cli/pom.xml b/tools/samm-cli/pom.xml index 6b8709ce1..4e2799014 100644 --- a/tools/samm-cli/pom.xml +++ b/tools/samm-cli/pom.xml @@ -266,6 +266,7 @@ ${native-image-jar} false + false ${skip.maven.shade} @@ -364,6 +365,7 @@ false + false ${skip.maven.shade} @@ -629,6 +631,7 @@ native true true + true @@ -648,9 +651,10 @@ ${main-class} - ${binary-name} + ./${binary-name} - -H:Name=${binary-name} + --verbose + -march=compatibility -H:EnableURLProtocols=http,https --enable-https --no-fallback diff --git a/tools/samm-cli/src/main/java/org/eclipse/esmf/buildtime/Aas4jClassSetup.java b/tools/samm-cli/src/main/java/org/eclipse/esmf/buildtime/Aas4jClassSetup.java index a92c30562..7e61845e9 100644 --- a/tools/samm-cli/src/main/java/org/eclipse/esmf/buildtime/Aas4jClassSetup.java +++ b/tools/samm-cli/src/main/java/org/eclipse/esmf/buildtime/Aas4jClassSetup.java @@ -13,13 +13,13 @@ package org.eclipse.esmf.buildtime; -import static org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper.DEFAULT_IMPLEMENTATION_PACKAGE_NAME; -import static org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper.DEFAULT_IMPLEMENTATION_PREFIX; -import static org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper.JSON_MIXINS_PACKAGE_NAME; -import static org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper.MIXIN_SUFFIX; -import static org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper.MODEL_PACKAGE_NAME; -import static org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper.MODEL_TYPE_SUPERCLASSES; -import static org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper.XML_MIXINS_PACKAGE_NAME; +import static org.eclipse.digitaltwin.aas4j.v3.dataformat.core.internal.util.ReflectionHelper.DEFAULT_IMPLEMENTATION_PACKAGE_NAME; +import static org.eclipse.digitaltwin.aas4j.v3.dataformat.core.internal.util.ReflectionHelper.DEFAULT_IMPLEMENTATION_PREFIX; +import static org.eclipse.digitaltwin.aas4j.v3.dataformat.core.internal.util.ReflectionHelper.JSON_MIXINS_PACKAGE_NAME; +import static org.eclipse.digitaltwin.aas4j.v3.dataformat.core.internal.util.ReflectionHelper.MIXIN_SUFFIX; +import static org.eclipse.digitaltwin.aas4j.v3.dataformat.core.internal.util.ReflectionHelper.MODEL_PACKAGE_NAME; +import static org.eclipse.digitaltwin.aas4j.v3.dataformat.core.internal.util.ReflectionHelper.MODEL_TYPE_SUPERCLASSES; +import static org.eclipse.digitaltwin.aas4j.v3.dataformat.core.internal.util.ReflectionHelper.XML_MIXINS_PACKAGE_NAME; import java.io.File; import java.io.FileOutputStream; @@ -36,18 +36,18 @@ import org.eclipse.esmf.substitution.AdminShellConfig; import org.eclipse.esmf.substitution.ImplementationInfo; -import org.eclipse.esmf.substitution.Target_org_eclipse_digitaltwin_aas4j_v3_dataformat_core_util_ReflectionHelper; +import org.eclipse.esmf.substitution.Target_org_eclipse_digitaltwin_aas4j_v3_dataformat_core_internal_util_ReflectionHelper; import io.github.classgraph.ClassGraph; import io.github.classgraph.ClassInfo; import io.github.classgraph.ClassInfoList; import io.github.classgraph.ScanResult; -import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.internal.util.ReflectionHelper; /** * This class generates the reflection information normally stored by {@link ReflectionHelper} and serializes it into a .properties file. * It is part of the substitution logic for this class, see - * {@link Target_org_eclipse_digitaltwin_aas4j_v3_dataformat_core_util_ReflectionHelper} for more information. + * {@link Target_org_eclipse_digitaltwin_aas4j_v3_dataformat_core_internal_util_ReflectionHelper} for more information. * Note that this class is only supposed to run at build time (via execution from the Maven build) and is not part of the * resulting CLI codebase. Running this class is configured in the pom.xml of the CLI Maven module (via exec-maven-plugin). */ diff --git a/tools/samm-cli/src/main/java/org/eclipse/esmf/nativefeatures/AasReflection.java b/tools/samm-cli/src/main/java/org/eclipse/esmf/nativefeatures/AasReflection.java index 602db8140..b2522508a 100644 --- a/tools/samm-cli/src/main/java/org/eclipse/esmf/nativefeatures/AasReflection.java +++ b/tools/samm-cli/src/main/java/org/eclipse/esmf/nativefeatures/AasReflection.java @@ -17,7 +17,7 @@ import java.util.List; -import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.internal.util.ReflectionHelper; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.hosted.Feature; diff --git a/tools/samm-cli/src/main/java/org/eclipse/esmf/substitution/AdminShellConfig.java b/tools/samm-cli/src/main/java/org/eclipse/esmf/substitution/AdminShellConfig.java index 24ebecb31..1ef4ff01f 100644 --- a/tools/samm-cli/src/main/java/org/eclipse/esmf/substitution/AdminShellConfig.java +++ b/tools/samm-cli/src/main/java/org/eclipse/esmf/substitution/AdminShellConfig.java @@ -24,11 +24,11 @@ import java.util.stream.Collector; import java.util.stream.Collectors; -import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.internal.util.ReflectionHelper; /** * An instance of this class encapsulates the information normally stored by {@link ReflectionHelper}. It is used in its substitution - * class, see {@link Target_org_eclipse_digitaltwin_aas4j_v3_dataformat_core_util_ReflectionHelper} for more information. + * class, see {@link Target_org_eclipse_digitaltwin_aas4j_v3_dataformat_core_internal_util_ReflectionHelper} for more information. * This class provides capabilities to serialize and deserialize its objects to/from a {@link Properties} object; more convenient * serialization (e.g., Java's builtin serialization or Jackson's ObjectMapper) can't be used here due to the limitations of the GraalVM * substitution classes. @@ -58,7 +58,7 @@ private String serialize( final Class clazz ) { } private > String serialize( final C collection, final Function mapper ) { - return collection.stream().map( element -> mapper.apply( element ) ).collect( Collectors.joining( "," ) ); + return collection.stream().map( mapper::apply ).collect( Collectors.joining( "," ) ); } private String serialize( final Map map, final Function keyMapper, final Function valueMapper ) { @@ -96,15 +96,15 @@ private static Class deserializeClass( final String classname ) { private static > C deserializeCollection( final String collection, final Function elementDeserializer, final Collector collector ) { - return Arrays.asList( collection.split( "," ) ).stream() + return Arrays.stream( collection.split( "," ) ) .filter( entry -> !entry.isEmpty() ) - .map( element -> elementDeserializer.apply( element ) ) + .map( elementDeserializer ) .collect( collector ); } private static Map deserializeMap( final String map, final Function keyDeserializer, final Function valueDeserializer ) { - return Arrays.asList( map.split( ";" ) ).stream() + return Arrays.stream( map.split( ";" ) ) .filter( entry -> !entry.isEmpty() ) .map( entry -> { final String[] parts = entry.split( "->" ); diff --git a/tools/samm-cli/src/main/java/org/eclipse/esmf/substitution/ImplementationInfo.java b/tools/samm-cli/src/main/java/org/eclipse/esmf/substitution/ImplementationInfo.java index a017d92b9..c8e1d0060 100644 --- a/tools/samm-cli/src/main/java/org/eclipse/esmf/substitution/ImplementationInfo.java +++ b/tools/samm-cli/src/main/java/org/eclipse/esmf/substitution/ImplementationInfo.java @@ -15,12 +15,12 @@ import java.util.Objects; -import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.internal.util.ReflectionHelper; /** * This is used as a stand-in/replacement for its superclass {@link ReflectionHelper.ImplementationInfo}, which unfortunately can't be * instantiated directly due to its protected constructor. This class is used in the substitution class for {@link ReflectionHelper}, see - * {@link Target_org_eclipse_digitaltwin_aas4j_v3_dataformat_core_util_ReflectionHelper} for more information. + * {@link Target_org_eclipse_digitaltwin_aas4j_v3_dataformat_core_internal_util_ReflectionHelper} for more information. */ public class ImplementationInfo extends ReflectionHelper.ImplementationInfo { public ImplementationInfo( final Class interfaceType, final Class implementationType ) { diff --git a/tools/samm-cli/src/main/java/org/eclipse/esmf/substitution/Target_org_eclipse_digitaltwin_aas4j_v3_dataformat_core_util_ReflectionHelper.java b/tools/samm-cli/src/main/java/org/eclipse/esmf/substitution/Target_org_eclipse_digitaltwin_aas4j_v3_dataformat_core_internal_util_ReflectionHelper.java similarity index 98% rename from tools/samm-cli/src/main/java/org/eclipse/esmf/substitution/Target_org_eclipse_digitaltwin_aas4j_v3_dataformat_core_util_ReflectionHelper.java rename to tools/samm-cli/src/main/java/org/eclipse/esmf/substitution/Target_org_eclipse_digitaltwin_aas4j_v3_dataformat_core_internal_util_ReflectionHelper.java index 3693b66d5..6cd1020be 100644 --- a/tools/samm-cli/src/main/java/org/eclipse/esmf/substitution/Target_org_eclipse_digitaltwin_aas4j_v3_dataformat_core_util_ReflectionHelper.java +++ b/tools/samm-cli/src/main/java/org/eclipse/esmf/substitution/Target_org_eclipse_digitaltwin_aas4j_v3_dataformat_core_internal_util_ReflectionHelper.java @@ -28,7 +28,7 @@ import com.oracle.svm.core.annotate.RecomputeFieldValue; import com.oracle.svm.core.annotate.Substitute; import com.oracle.svm.core.annotate.TargetClass; -import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.internal.util.ReflectionHelper; /** * This is a GraalVM substitution class @@ -58,7 +58,7 @@ "NewClassNamingConvention", "checkstyle:TypeName" } ) -public final class Target_org_eclipse_digitaltwin_aas4j_v3_dataformat_core_util_ReflectionHelper { +public final class Target_org_eclipse_digitaltwin_aas4j_v3_dataformat_core_internal_util_ReflectionHelper { @Alias @RecomputeFieldValue( kind = RecomputeFieldValue.Kind.FromAlias ) private static final String ROOT_PACKAGE_NAME = "org.eclipse.digitaltwin.aas4j.v3"; @@ -137,7 +137,7 @@ public final class Target_org_eclipse_digitaltwin_aas4j_v3_dataformat_core_util_ static { try ( final InputStream input = - Target_org_eclipse_digitaltwin_aas4j_v3_dataformat_core_util_ReflectionHelper.class.getResourceAsStream( + Target_org_eclipse_digitaltwin_aas4j_v3_dataformat_core_internal_util_ReflectionHelper.class.getResourceAsStream( "/adminshell.properties" ) ) { final Properties properties = new Properties(); properties.load( input );