Skip to content

Commit a31752d

Browse files
committed
Merge branch 'main' into 2.9.x
2 parents 754df89 + 76417ce commit a31752d

File tree

202 files changed

+3499
-1712
lines changed

Some content is hidden

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

202 files changed

+3499
-1712
lines changed

CONTRIBUTING.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Model (SAMM) and supports its use.
1515
# Contributing Source Code (using GitHub)
1616

1717
* We use this GitHub repository to track issues and feature requests.
18-
* For general discussions of the ESMF, modeling questions etc. we use the [community forum](https://www.eclipse.org/forums/index.php/f/617/).
18+
* For general discussions of the ESMF, modeling questions etc. we use the [ESMF Chat](https://chat.eclipse.org/#/room/#eclipse-semantic-modeling-framework:matrix.eclipse.org).
1919
* For discussions specific to development, the preferred way is the [developer mailing list](https://accounts.eclipse.org/mailing-list/esmf-dev).
2020

2121
## Architecture Decision Records

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ To build the documentation locally, please check out and follow the instructions
4747
Are you having trouble with ESMF SDK? We want to help!
4848

4949
* Check the [ESMF SDK developer documentation](https://eclipse-esmf.github.io/esmf-developer-guide/index.html)
50-
* Ask a question the [community forum](https://www.eclipse.org/forums/index.php/f/617/).
50+
* Ask a question in the [ESMF Chat ](https://chat.eclipse.org/#/room/#eclipse-semantic-modeling-framework:matrix.eclipse.org).
5151
* Check the SAMM [specification](https://eclipse-esmf.github.io/samm-specification/snapshot/index.html)
5252
* Having issues with the ESMF SDK? Open a [GitHub issue](https://github.com/eclipse-esmf/esmf-sdk/issues).
5353

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

+34
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,53 @@
2323

2424
import org.apache.jena.rdf.model.Model;
2525

26+
/**
27+
* An AspectModelFile is the abstraction of one "code unit". When its source location is in a file system, the
28+
* AspectModelFile corresponds to one file, but this does not have to be the case: An AspectModelFile could also
29+
* exist in memory, or purely virtually (e.g., as an abstraction of a sub-graph in a triple store).
30+
*/
2631
public interface AspectModelFile extends ModelElementGroup {
32+
/**
33+
* The RDF model with the contents of this AspectModelFile
34+
*
35+
* @return the model
36+
*/
2737
Model sourceModel();
2838

39+
/**
40+
* The list of Strings that are contained as a comment block at the start of the file. This is often used
41+
* for copyright and license information.
42+
*
43+
* @return the header comment
44+
*/
2945
default List<String> headerComment() {
3046
return List.of();
3147
}
3248

49+
/**
50+
* The URI that denominates the source location, if present. It can be a file:// or https:// URL, but it
51+
* could for example also be an Aspect Model URN, if it refers to a file that is part of the SAMM specification.
52+
* Generally, this should be the physical location, not a logical identifier, in other words, where was this
53+
* AspectModelFile loaded from.
54+
*
55+
* @return the source location
56+
*/
3357
Optional<URI> sourceLocation();
3458

59+
/**
60+
* Returns the {@link Namespace} this AspectModelFile is a part of
61+
*
62+
* @return the namespace
63+
*/
3564
default Namespace namespace() {
3665
throw new UnsupportedOperationException( "Uninitialized Aspect Model" );
3766
}
3867

68+
/**
69+
* Lists the model elements that are contained in this AspectModelFile
70+
*
71+
* @return the model elements
72+
*/
3973
@Override
4074
default List<ModelElement> elements() {
4175
throw new UnsupportedOperationException( "Uninitialized Aspect Model" );

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

+14-16
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import java.io.ByteArrayOutputStream;
1818
import java.io.File;
1919
import java.io.FileInputStream;
20-
import java.io.FileNotFoundException;
2120
import java.io.IOException;
2221
import java.io.InputStream;
2322
import java.net.URI;
@@ -209,14 +208,14 @@ public AspectModel load( final InputStream inputStream ) {
209208
*/
210209
public AspectModel loadNamespacePackage( final File namespacePackage ) {
211210
if ( !namespacePackage.exists() || !namespacePackage.isFile() ) {
212-
throw new RuntimeException( new FileNotFoundException( "The specified file does not exist or is not a file." ) );
211+
throw new ModelResolutionException( "The specified file does not exist or is not a file." );
213212
}
214213

215214
try ( final InputStream inputStream = new FileInputStream( namespacePackage ) ) {
216215
return loadNamespacePackage( inputStream );
217-
} catch ( final IOException e ) {
218-
LOG.error( "Error reading the file: {}", namespacePackage.getAbsolutePath(), e );
219-
throw new RuntimeException( "Error reading the file: " + namespacePackage.getAbsolutePath(), e );
216+
} catch ( final IOException exception ) {
217+
LOG.error( "Error reading the file: {}", namespacePackage.getAbsolutePath(), exception );
218+
throw new ModelResolutionException( "Error reading the file: " + namespacePackage.getAbsolutePath(), exception );
220219
}
221220
}
222221

@@ -228,12 +227,13 @@ public AspectModel loadNamespacePackage( final File namespacePackage ) {
228227
*/
229228
public AspectModel loadNamespacePackage( final InputStream inputStream ) {
230229
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
230+
final boolean hasAspectModelsFolder;
231231
try {
232232
inputStream.transferTo( baos );
233-
} catch ( final IOException e ) {
234-
throw new RuntimeException( e );
233+
hasAspectModelsFolder = containsFolderInNamespacePackage( new ByteArrayInputStream( baos.toByteArray() ) );
234+
} catch ( final IOException exception ) {
235+
throw new ModelResolutionException( "Could not read from input", exception );
235236
}
236-
final boolean hasAspectModelsFolder = containsFolderInNamespacePackage( new ByteArrayInputStream( baos.toByteArray() ) );
237237
return loadNamespacePackageFromStream( new ByteArrayInputStream( baos.toByteArray() ), hasAspectModelsFolder );
238238
}
239239

@@ -245,8 +245,8 @@ private AspectModel loadNamespacePackageFromStream( final InputStream inputStrea
245245

246246
while ( ( entry = zis.getNextEntry() ) != null ) {
247247
final boolean isRelevantEntry =
248-
( hasAspectModelsFolder && entry.getName().contains( String.format( "%s/", ASPECT_MODELS_FOLDER ) ) && entry.getName()
249-
.endsWith( ".ttl" ) )
248+
( hasAspectModelsFolder && entry.getName().contains( String.format( "%s/", ASPECT_MODELS_FOLDER ) )
249+
&& entry.getName().endsWith( ".ttl" ) )
250250
|| ( !hasAspectModelsFolder && entry.getName().endsWith( ".ttl" ) );
251251

252252
if ( isRelevantEntry ) {
@@ -256,26 +256,24 @@ private AspectModel loadNamespacePackageFromStream( final InputStream inputStrea
256256
}
257257

258258
zis.closeEntry();
259-
} catch ( final IOException e ) {
260-
LOG.error( "Error reading the Archive input stream", e );
261-
throw new RuntimeException( "Error reading the Archive input stream", e );
259+
} catch ( final IOException exception ) {
260+
LOG.error( "Error reading the Archive input stream", exception );
261+
throw new ModelResolutionException( "Error reading the Archive input stream", exception );
262262
}
263263

264264
final LoaderContext loaderContext = new LoaderContext();
265265
resolve( aspectModelFiles, loaderContext );
266266
return loadAspectModelFiles( loaderContext.loadedFiles() );
267267
}
268268

269-
private boolean containsFolderInNamespacePackage( final InputStream inputStream ) {
269+
private boolean containsFolderInNamespacePackage( final InputStream inputStream ) throws IOException {
270270
try ( final ZipInputStream zis = new ZipInputStream( inputStream ) ) {
271271
ZipEntry entry;
272272
while ( ( entry = zis.getNextEntry() ) != null ) {
273273
if ( entry.isDirectory() && entry.getName().contains( String.format( "%s/", ASPECT_MODELS_FOLDER ) ) ) {
274274
return true;
275275
}
276276
}
277-
} catch ( final IOException e ) {
278-
throw new RuntimeException( e );
279277
}
280278
return false;
281279
}

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@
8383
import org.apache.jena.vocabulary.RDF;
8484
import org.apache.jena.vocabulary.RDFS;
8585

86+
/**
87+
* Used as part of the loading process in the {@link AspectModelLoader}, it creates instance for the the {@link ModelElement}s
88+
* in an AspectModel.
89+
*/
8690
public class ModelElementFactory extends AttributeValueRetriever {
8791
private final Model model;
8892
private final Map<Resource, Instantiator<?>> instantiators = new HashMap<>();
@@ -351,7 +355,7 @@ private static Resource getModelElementType( final Resource modelElement ) {
351355
return getModelElementType( superElement );
352356
}
353357

354-
public AspectModelFile getSourceLocation( Resource modelElement ) {
358+
public AspectModelFile getSourceLocation( final Resource modelElement ) {
355359
return sourceLocator.apply( modelElement );
356360
}
357361
}

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

+27-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@
2222
import java.net.http.HttpRequest;
2323
import java.net.http.HttpResponse;
2424
import java.time.Duration;
25+
import java.util.Map;
2526
import java.util.Optional;
27+
import java.util.stream.Stream;
2628

2729
import org.eclipse.esmf.aspectmodel.resolver.exceptions.ModelResolutionException;
2830

@@ -48,9 +50,10 @@ public Download() {
4850
* Download the file and return the contents as byte array
4951
*
5052
* @param fileUrl the URL
53+
* @param headers list of additional headers to set
5154
* @return the file contents
5255
*/
53-
public byte[] downloadFile( final URL fileUrl ) {
56+
public byte[] downloadFile( final URL fileUrl, final Map<String, String> headers ) {
5457
try {
5558
final HttpClient.Builder clientBuilder = HttpClient.newBuilder()
5659
.version( HttpClient.Version.HTTP_1_1 )
@@ -59,14 +62,31 @@ public byte[] downloadFile( final URL fileUrl ) {
5962
Optional.ofNullable( proxyConfig.proxy() ).ifPresent( clientBuilder::proxy );
6063
Optional.ofNullable( proxyConfig.authenticator() ).ifPresent( clientBuilder::authenticator );
6164
final HttpClient client = clientBuilder.build();
62-
final HttpRequest request = HttpRequest.newBuilder().uri( fileUrl.toURI() ).build();
65+
final String[] headersArray = headers.entrySet().stream()
66+
.flatMap( entry -> Stream.of( entry.getKey(), entry.getValue() ) )
67+
.toList()
68+
.toArray( new String[0] );
69+
final HttpRequest request = HttpRequest.newBuilder()
70+
.uri( fileUrl.toURI() )
71+
.headers( headersArray )
72+
.build();
6373
final HttpResponse<byte[]> response = client.send( request, HttpResponse.BodyHandlers.ofByteArray() );
6474
return response.body();
6575
} catch ( final InterruptedException | URISyntaxException | IOException exception ) {
6676
throw new ModelResolutionException( "Could not retrieve " + fileUrl, exception );
6777
}
6878
}
6979

80+
/**
81+
* Download the file and return the contents as byte array
82+
*
83+
* @param fileUrl the URL
84+
* @return the file contents
85+
*/
86+
public byte[] downloadFile( final URL fileUrl ) {
87+
return downloadFile( fileUrl, Map.of() );
88+
}
89+
7090
/**
7191
* Download the file and write it to the file system
7292
*
@@ -75,8 +95,12 @@ public byte[] downloadFile( final URL fileUrl ) {
7595
* @return the file written
7696
*/
7797
public File downloadFile( final URL fileUrl, final File outputFile ) {
98+
return downloadFile( fileUrl, Map.of(), outputFile );
99+
}
100+
101+
public File downloadFile( final URL fileUrl, final Map<String, String> headers, final File outputFile ) {
78102
try ( final FileOutputStream outputStream = new FileOutputStream( outputFile ) ) {
79-
final byte[] fileContent = downloadFile( fileUrl );
103+
final byte[] fileContent = downloadFile( fileUrl, headers );
80104
outputStream.write( fileContent );
81105
} catch ( final IOException exception ) {
82106
throw new ModelResolutionException( "Could not write file " + outputFile, exception );

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

+4-2
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,10 @@ public String refType() {
4949
}
5050

5151
public URL zipLocation() {
52-
final String url = "https://%s/%s/%s/archive/refs/%s/%s.zip".formatted(
53-
host(), owner(), repository(), branchOrTag().refType(), branchOrTag().name() );
52+
// See https://docs.github.com/en/rest/repos/contents?apiVersion=2022-11-28#download-a-repository-archive-zip
53+
// General URL structure: https://api.github.com/repos/OWNER/REPO/zipball/REF
54+
final String theHost = host().equals( "github.com" ) ? "api.github.com" : host();
55+
final String url = "https://%s/repos/%s/%s/zipball/%s".formatted( theHost, owner(), repository(), branchOrTag().name() );
5456
try {
5557
return new URL( url );
5658
} catch ( final MalformedURLException exception ) {

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

+4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ public record ProxyConfig(
3232

3333
public static final ProxyConfig NO_PROXY = new ProxyConfig( null, null );
3434

35+
public static ProxyConfig from( final String host, final int port ) {
36+
return new ProxyConfig( ProxySelector.of( new InetSocketAddress( host, port ) ), null );
37+
}
38+
3539
public static ProxyConfig detectProxySettings() {
3640
final String envProxy = System.getenv( "http_proxy" );
3741
if ( envProxy != null && System.getProperty( "http.proxyHost" ) == null ) {

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

+11-3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
import org.eclipse.esmf.aspectmodel.resolver.exceptions.ModelResolutionException;
2828
import org.eclipse.esmf.aspectmodel.urn.AspectModelUrn;
2929

30+
import org.slf4j.Logger;
31+
import org.slf4j.LoggerFactory;
32+
3033
/**
3134
* Represents the root directory of the directory hierarchy in which Aspect Models are organized.
3235
* The directory is assumed to contain a file system hierarchy as follows: {@code N/V/X.ttl} where N is the namespace,
@@ -43,6 +46,8 @@
4346
* </pre>
4447
*/
4548
public class StructuredModelsRoot extends ModelsRoot {
49+
private static final Logger LOG = LoggerFactory.getLogger( StructuredModelsRoot.class );
50+
4651
public StructuredModelsRoot( final Path path ) {
4752
super( path );
4853
}
@@ -83,8 +88,11 @@ public Stream<URI> namespaceContents( final AspectModelUrn namespace ) {
8388
.resolve( namespace.getNamespaceMainPart() )
8489
.resolve( namespace.getVersion() )
8590
.toFile();
86-
return Arrays.stream( Objects.requireNonNull( namespaceDirectory.listFiles( file ->
87-
file.getName().endsWith( ".ttl" ) ) ) )
88-
.map( File::toURI );
91+
final File[] files = namespaceDirectory.listFiles( file -> file.getName().endsWith( ".ttl" ) );
92+
if ( files == null ) {
93+
LOG.debug( "Supposed models root {} does not contain any .ttl files", namespaceDirectory );
94+
return Stream.empty();
95+
}
96+
return Arrays.stream( Objects.requireNonNull( files ) ).map( File::toURI );
8997
}
9098
}

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

+9
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,15 @@
2323
import org.apache.jena.rdf.model.Model;
2424
import org.apache.jena.rdf.model.ModelFactory;
2525

26+
/**
27+
* An implementation of an {@link AspectModelFile} that knows about the RDF model content and source location, but has not
28+
* instantiated the model elements yet. Calling {@link #elements()} on this file will throw an exception. It is intended
29+
* to represent the intermediary result of loading an Aspect Model file, possibly from a remote location.
30+
*
31+
* @param sourceModel the source RDF model
32+
* @param headerComment the header comment
33+
* @param sourceLocation the source location
34+
*/
2635
@SuppressWarnings( "OptionalUsedAsFieldOrParameterType" )
2736
@RecordBuilder
2837
public record RawAspectModelFile(

core/esmf-aspect-model-aas-generator/pom.xml

+27
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222
<groupId>org.eclipse.esmf</groupId>
2323
<artifactId>esmf-aspect-meta-model-java</artifactId>
2424
</dependency>
25+
<dependency>
26+
<groupId>org.eclipse.esmf</groupId>
27+
<artifactId>esmf-aspect-model-generator</artifactId>
28+
</dependency>
2529
<dependency>
2630
<groupId>org.eclipse.digitaltwin.aas4j</groupId>
2731
<artifactId>aas4j-model</artifactId>
@@ -42,6 +46,11 @@
4246
<groupId>org.apache.poi</groupId>
4347
<artifactId>poi</artifactId>
4448
</dependency>
49+
<dependency>
50+
<groupId>io.soabase.record-builder</groupId>
51+
<artifactId>record-builder-processor</artifactId>
52+
<scope>provided</scope>
53+
</dependency>
4554

4655
<dependency>
4756
<groupId>org.eclipse.esmf</groupId>
@@ -59,4 +68,22 @@
5968
<scope>test</scope>
6069
</dependency>
6170
</dependencies>
71+
72+
<build>
73+
<plugins>
74+
<plugin>
75+
<groupId>org.apache.maven.plugins</groupId>
76+
<artifactId>maven-compiler-plugin</artifactId>
77+
<configuration>
78+
<annotationProcessorPaths>
79+
<path>
80+
<groupId>io.soabase.record-builder</groupId>
81+
<artifactId>record-builder-processor</artifactId>
82+
<version>${record-builder-version}</version>
83+
</path>
84+
</annotationProcessorPaths>
85+
</configuration>
86+
</plugin>
87+
</plugins>
88+
</build>
6289
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Copyright (c) 2024 Robert Bosch Manufacturing Solutions GmbH
3+
*
4+
* See the AUTHORS file(s) distributed with this work for additional
5+
* information regarding authorship.
6+
*
7+
* This Source Code Form is subject to the terms of the Mozilla Public
8+
* License, v. 2.0. If a copy of the MPL was not distributed with this
9+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
10+
*
11+
* SPDX-License-Identifier: MPL-2.0
12+
*/
13+
14+
package org.eclipse.esmf.aspectmodel.aas;
15+
16+
import org.eclipse.esmf.aspectmodel.generator.BinaryArtifact;
17+
18+
public class AasArtifact extends BinaryArtifact {
19+
public AasArtifact( final String id, final byte[] content ) {
20+
super( id, content );
21+
}
22+
}

0 commit comments

Comments
 (0)