Skip to content

Commit dd83ee4

Browse files
committed
Merge branch 'main' into 2.9.x
2 parents 10ff466 + 937c862 commit dd83ee4

File tree

79 files changed

+1204
-313
lines changed

Some content is hidden

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

79 files changed

+1204
-313
lines changed

.github/workflows/pull-request-check.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ jobs:
1616
steps:
1717
- name: Checkout repository
1818
uses: actions/checkout@v4
19+
with:
20+
submodules: recursive
1921

2022
- name: Check code style
2123
if: matrix.os == 'ubuntu-20.04'

.github/workflows/release-workflow.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ jobs:
1212
steps:
1313
- name: Checkout
1414
uses: actions/checkout@v4
15+
with:
16+
submodules: recursive
1517

1618
# Required for Maven
1719
- name: Set up JDK 17
@@ -51,6 +53,8 @@ jobs:
5153
steps:
5254
- name: Checkout
5355
uses: actions/checkout@v4
56+
with:
57+
submodules: recursive
5458

5559
# Even though the build itself is done using the GraalVM JDK
5660
# (see below), we use the setup-java action to have GPG configured
@@ -146,6 +150,8 @@ jobs:
146150
steps:
147151
- name: Checkout
148152
uses: actions/checkout@v4
153+
with:
154+
submodules: recursive
149155

150156
- name: Setup JDK
151157
uses: graalvm/setup-graalvm@2f25c0caae5b220866f732832d5e3e29ff493338 # v1.2.1
@@ -219,6 +225,8 @@ jobs:
219225
steps:
220226
- name: Checkout
221227
uses: actions/checkout@v4
228+
with:
229+
submodules: recursive
222230

223231
- name: Setup JDK
224232
uses: graalvm/setup-graalvm@2f25c0caae5b220866f732832d5e3e29ff493338 # v1.2.1
@@ -363,7 +371,7 @@ jobs:
363371
comment-template: |
364372
Release {release_link} addresses this.
365373
366-
# Sign SAML-CLI Windows executable
374+
# Sign SAMM-CLI Windows executable
367375
- name: Get Artifact ID (Windows)
368376
shell: bash
369377
run: |

.gitmodules

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[submodule "core/esmf-aspect-model-aas-generator/src/test/resources/submodel-templates"]
2+
path = core/esmf-aspect-model-aas-generator/src/test/resources/submodel-templates
3+
url = https://github.com/admin-shell-io/submodel-templates.git
4+
branch = main

core/esmf-aspect-meta-model-interface/src/main/java/org/eclipse/esmf/aspectmodel/AspectModelFile.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,18 @@ default List<String> headerComment() {
4646
return List.of();
4747
}
4848

49+
/**
50+
* Returns the SPDX license identifier for this file, if one exists
51+
*
52+
* @return the SPDX identifier
53+
*/
54+
default Optional<String> spdxLicenseIdentifier() {
55+
return headerComment().stream()
56+
.filter( line -> line.startsWith( "SPDX-License-Identifier:" ) )
57+
.map( line -> line.split( ":" )[1].trim() )
58+
.findFirst();
59+
}
60+
4961
/**
5062
* The URI that denominates the source location, if present. It can be a file:// or https:// URL, but it
5163
* could for example also be an Aspect Model URN, if it refers to a file that is part of the SAMM specification.

core/esmf-aspect-meta-model-interface/src/main/java/org/eclipse/esmf/aspectmodel/MissingMetaModelVersionException.java

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

1414
package org.eclipse.esmf.aspectmodel;
1515

16+
@Deprecated( forRemoval = true )
1617
public class MissingMetaModelVersionException extends RuntimeException {
1718
private static final long serialVersionUID = -6978063564517733205L;
1819
}

core/esmf-aspect-meta-model-interface/src/main/java/org/eclipse/esmf/aspectmodel/MultipleMetaModelVersionsException.java

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

1414
package org.eclipse.esmf.aspectmodel;
1515

16+
@Deprecated( forRemoval = true )
1617
public class MultipleMetaModelVersionsException extends RuntimeException {
1718
private static final long serialVersionUID = -592452975353816247L;
1819
}

core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/aspectmodel/loader/AspectModelLoader.java

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import java.util.ArrayList;
2626
import java.util.Collection;
2727
import java.util.Deque;
28-
import java.util.HashMap;
2928
import java.util.HashSet;
3029
import java.util.List;
3130
import java.util.Map;
@@ -37,6 +36,7 @@
3736
import java.util.zip.ZipEntry;
3837
import java.util.zip.ZipInputStream;
3938

39+
import org.eclipse.esmf.aspectmodel.AspectLoadingException;
4040
import org.eclipse.esmf.aspectmodel.AspectModelFile;
4141
import org.eclipse.esmf.aspectmodel.RdfUtil;
4242
import org.eclipse.esmf.aspectmodel.resolver.AspectModelFileLoader;
@@ -208,14 +208,14 @@ public AspectModel load( final InputStream inputStream ) {
208208
*/
209209
public AspectModel loadNamespacePackage( final File namespacePackage ) {
210210
if ( !namespacePackage.exists() || !namespacePackage.isFile() ) {
211-
throw new ModelResolutionException( "The specified file does not exist or is not a file." );
211+
throw new AspectLoadingException( "The specified file does not exist or is not a file." );
212212
}
213213

214214
try ( final InputStream inputStream = new FileInputStream( namespacePackage ) ) {
215215
return loadNamespacePackage( inputStream );
216216
} catch ( final IOException exception ) {
217217
LOG.error( "Error reading the file: {}", namespacePackage.getAbsolutePath(), exception );
218-
throw new ModelResolutionException( "Error reading the file: " + namespacePackage.getAbsolutePath(), exception );
218+
throw new AspectLoadingException( "Error reading the file: " + namespacePackage.getAbsolutePath(), exception );
219219
}
220220
}
221221

@@ -232,7 +232,7 @@ public AspectModel loadNamespacePackage( final InputStream inputStream ) {
232232
inputStream.transferTo( baos );
233233
hasAspectModelsFolder = containsFolderInNamespacePackage( new ByteArrayInputStream( baos.toByteArray() ) );
234234
} catch ( final IOException exception ) {
235-
throw new ModelResolutionException( "Could not read from input", exception );
235+
throw new AspectLoadingException( "Could not read from input", exception );
236236
}
237237
return loadNamespacePackageFromStream( new ByteArrayInputStream( baos.toByteArray() ), hasAspectModelsFolder );
238238
}
@@ -258,7 +258,7 @@ private AspectModel loadNamespacePackageFromStream( final InputStream inputStrea
258258
zis.closeEntry();
259259
} catch ( final IOException exception ) {
260260
LOG.error( "Error reading the Archive input stream", exception );
261-
throw new ModelResolutionException( "Error reading the Archive input stream", exception );
261+
throw new AspectLoadingException( "Error reading the Archive input stream", exception );
262262
}
263263

264264
final LoaderContext loaderContext = new LoaderContext();
@@ -336,13 +336,14 @@ private Optional<AspectModelFile> applyResolutionStrategy( final String urn ) {
336336
}
337337
final AspectModelFile resolutionResult = resolutionStrategy.apply( aspectModelUrn, this );
338338
if ( !containsType( resolutionResult.sourceModel(), urn ) ) {
339-
throw new ModelResolutionException(
339+
throw new AspectLoadingException(
340340
"Resolution strategy returned a model which does not contain element definition for " + urn );
341341
}
342342
return Optional.of( resolutionResult );
343-
} catch ( final UrnSyntaxException e ) {
343+
} catch ( final UrnSyntaxException exception ) {
344+
// This happens if the URN to load is no actual URN.
344345
// If it's no valid Aspect Model URN but some other URI (e.g., a samm:see value), there is nothing
345-
// to resolve, so we return just an empty model
346+
// to resolve, so we return just an empty model.
346347
return Optional.empty();
347348
}
348349
}
@@ -379,6 +380,7 @@ private void resolve( final List<AspectModelFile> inputFiles, final LoaderContex
379380
context.unresolvedFiles().push( aspectModelFile );
380381
}
381382

383+
final List<ModelResolutionException.LoadingFailure> loadingFailures = new ArrayList<>();
382384
while ( !context.unresolvedFiles().isEmpty() || !context.unresolvedUrns().isEmpty() ) {
383385
if ( !context.unresolvedFiles().isEmpty() ) {
384386
final AspectModelFile modelFile = context.unresolvedFiles().pop();
@@ -389,11 +391,25 @@ private void resolve( final List<AspectModelFile> inputFiles, final LoaderContex
389391
}
390392

391393
while ( !context.unresolvedUrns().isEmpty() ) {
392-
applyResolutionStrategy( context.unresolvedUrns().pop() )
393-
.map( this::migrate )
394-
.ifPresent( resolvedFile -> markModelFileAsLoaded( resolvedFile, context ) );
394+
try {
395+
applyResolutionStrategy( context.unresolvedUrns().pop() )
396+
.map( this::migrate )
397+
.ifPresent( resolvedFile -> markModelFileAsLoaded( resolvedFile, context ) );
398+
} catch ( final ModelResolutionException exception ) {
399+
// If one element can not be resolved, collect its cause and continue, so that
400+
// we can create an comprehensive overview of all elements that can not be resolved
401+
if ( exception.getCheckedLocations().isEmpty() ) {
402+
throw exception;
403+
} else {
404+
loadingFailures.addAll( exception.getCheckedLocations() );
405+
}
406+
}
395407
}
396408
}
409+
410+
if ( !loadingFailures.isEmpty() ) {
411+
throw new ModelResolutionException( loadingFailures );
412+
}
397413
}
398414

399415
/**
@@ -442,7 +458,6 @@ public AspectModel loadAspectModelFiles( final Collection<AspectModelFile> input
442458

443459
final List<ModelElement> elements = new ArrayList<>();
444460
final List<AspectModelFile> files = new ArrayList<>();
445-
final Map<AspectModelFile, MetaModelBaseAttributes> namespaceDefinitions = new HashMap<>();
446461
for ( final AspectModelFile file : inputFiles ) {
447462
final DefaultAspectModelFile aspectModelFile = new DefaultAspectModelFile( file.sourceModel(), file.headerComment(),
448463
file.sourceLocation() );
@@ -465,6 +480,13 @@ public AspectModel loadAspectModelFiles( final Collection<AspectModelFile> input
465480
.filter( modelElement -> modelElement.is( Aspect.class ) )
466481
.findFirst()
467482
.ifPresent( aspect -> mergedModel.setNsPrefix( "", aspect.urn().getUrnPrefix() ) );
483+
for ( AspectModelFile file : files ) {
484+
if ( file.aspects().size() > 1 ) {
485+
throw new AspectLoadingException(
486+
"Aspect model file " + file.sourceLocation().map( location -> location + " " ).orElse( "" ) + "contains " + file.aspects()
487+
.size() + " aspects, but may only contain one." );
488+
}
489+
}
468490
return new DefaultAspectModel( files, mergedModel, elements );
469491
}
470492

core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/aspectmodel/loader/AttributeValueRetriever.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ private boolean isRdfList( final Resource resource ) {
7171

7272
/**
7373
* Returns the values of n-ary attributes on a model element (or its super elements), or if a given attribute is an rdf:List, the list
74-
* elements. The list will be ordered by precedence, e.g., if a Property is present on both the current element and it's superelement,
74+
* elements. The list will be ordered by precedence, e.g., if a Property is present on both the current element and its superelement,
7575
* the assertion on the current element will be on a lower list index. Duplicate attribute assertions are removed and only the assertion
7676
* with the highest precedence will be returned (bottom-most in the inheritance tree), this includes multiple assertions for the same
7777
* attribute with rdf:langString values with the same language tag. For example:

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@
1717
import java.util.Map;
1818
import java.util.Optional;
1919

20+
import org.eclipse.esmf.aspectmodel.AspectLoadingException;
2021
import org.eclipse.esmf.aspectmodel.loader.DefaultPropertyWrapper;
2122
import org.eclipse.esmf.aspectmodel.loader.Instantiator;
2223
import org.eclipse.esmf.aspectmodel.loader.MetaModelBaseAttributes;
2324
import org.eclipse.esmf.aspectmodel.loader.ModelElementFactory;
24-
import org.eclipse.esmf.aspectmodel.resolver.exceptions.InvalidModelException;
2525
import org.eclipse.esmf.metamodel.Characteristic;
2626
import org.eclipse.esmf.metamodel.Property;
2727
import org.eclipse.esmf.metamodel.Scalar;
@@ -81,7 +81,7 @@ public Property apply( final Resource property ) {
8181
.flatMap( statement -> characteristic.getDataType()
8282
.map( type -> {
8383
if ( !type.is( Scalar.class ) ) {
84-
throw new InvalidModelException( "Type of example value on Property " + property + " has incorrect type" );
84+
throw new AspectLoadingException( "Type of example value on Property " + property + " has incorrect type" );
8585
}
8686
return type.as( Scalar.class );
8787
} )

core/esmf-aspect-meta-model-java/src/main/java/org/eclipse/esmf/aspectmodel/resolver/AspectModelFileLoader.java

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,25 @@
1515

1616
import static org.apache.commons.lang3.StringUtils.isBlank;
1717

18-
import java.io.BufferedReader;
1918
import java.io.ByteArrayInputStream;
2019
import java.io.File;
2120
import java.io.FileInputStream;
2221
import java.io.FileNotFoundException;
2322
import java.io.IOException;
2423
import java.io.InputStream;
25-
import java.io.InputStreamReader;
2624
import java.net.MalformedURLException;
2725
import java.net.URI;
2826
import java.net.URISyntaxException;
2927
import java.net.URL;
28+
import java.nio.ByteBuffer;
29+
import java.nio.CharBuffer;
30+
import java.nio.charset.CharsetDecoder;
31+
import java.nio.charset.MalformedInputException;
3032
import java.nio.charset.StandardCharsets;
33+
import java.nio.charset.UnmappableCharacterException;
3134
import java.nio.file.Paths;
3235
import java.util.List;
3336
import java.util.Optional;
34-
import java.util.stream.Collectors;
3537

3638
import org.eclipse.esmf.aspectmodel.AspectModelFile;
3739
import org.eclipse.esmf.aspectmodel.loader.AspectModelLoader;
@@ -53,6 +55,11 @@ public static RawAspectModelFile load( final File file ) {
5355
try {
5456
final RawAspectModelFile fromString = load( content( new FileInputStream( file ) ) );
5557
return new RawAspectModelFile( fromString.sourceModel(), fromString.headerComment(), Optional.of( file.toURI() ) );
58+
} catch ( final ModelResolutionException exception ) {
59+
if ( exception.getMessage().startsWith( "Encountered invalid encoding" ) ) {
60+
throw new ModelResolutionException( "Encountered invalid encoding in input file " + file, exception.getCause() );
61+
}
62+
throw exception;
5663
} catch ( final FileNotFoundException exception ) {
5764
throw new ModelResolutionException( "File not found: " + file, exception );
5865
}
@@ -70,8 +77,16 @@ public static RawAspectModelFile load( final String rdfTurtle ) {
7077
}
7178

7279
private static String content( final InputStream inputStream ) {
73-
return new BufferedReader( new InputStreamReader( inputStream, StandardCharsets.UTF_8 ) ).lines()
74-
.collect( Collectors.joining( "\n" ) );
80+
try {
81+
final byte[] bytes = inputStream.readAllBytes();
82+
final CharsetDecoder charsetDecoder = StandardCharsets.UTF_8.newDecoder();
83+
final CharBuffer decodedCharBuffer = charsetDecoder.decode( ByteBuffer.wrap( bytes ) );
84+
return new String( bytes, StandardCharsets.UTF_8 );
85+
} catch ( final MalformedInputException | UnmappableCharacterException exception ) {
86+
throw new ModelResolutionException( "Encountered invalid encoding in input" );
87+
} catch ( final IOException exception ) {
88+
throw new RuntimeException( exception );
89+
}
7590
}
7691

7792
private static List<String> headerComment( final String content ) {

0 commit comments

Comments
 (0)