Skip to content

Commit 1031774

Browse files
committed
Add batch model retrieval and file info classes
Introduces FileEntry and FileInformation classes for batch operations. Adds a new endpoint to ModelController for retrieving multiple aspect models in a single request. Updates ModelService to return filename and model content as a tuple, and refactors related test and service logic for improved error handling and data structure support.
1 parent 0c83223 commit 1031774

File tree

6 files changed

+213
-5
lines changed

6 files changed

+213
-5
lines changed

aspect-model-editor-service/src/main/java/org/eclipse/esmf/ame/services/ModelService.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.ArrayList;
2121
import java.util.List;
2222
import java.util.Map;
23+
import java.util.Optional;
2324
import java.util.function.Supplier;
2425

2526
import org.eclipse.esmf.ame.exceptions.CreateFileException;
@@ -46,9 +47,12 @@
4647
import org.eclipse.esmf.aspectmodel.urn.AspectModelUrn;
4748
import org.eclipse.esmf.aspectmodel.validation.services.AspectModelValidator;
4849
import org.eclipse.esmf.metamodel.AspectModel;
50+
import org.eclipse.esmf.metamodel.Namespace;
4951
import org.eclipse.esmf.samm.KnownVersion;
5052

5153
import io.micronaut.http.multipart.CompletedFileUpload;
54+
import io.vavr.Tuple;
55+
import io.vavr.Tuple2;
5256
import jakarta.inject.Singleton;
5357
import org.slf4j.Logger;
5458
import org.slf4j.LoggerFactory;
@@ -74,13 +78,31 @@ public ModelService( final AspectModelValidator aspectModelValidator, final Aspe
7478
this.modelPath = modelPath;
7579
}
7680

77-
public String getModel( final AspectModelUrn aspectModelUrn, final String filePath ) {
81+
public Tuple2<Optional<String>, String> getModel( final AspectModelUrn aspectModelUrn, final String filePath ) {
7882
try {
7983
final AspectModel aspectModel = ( filePath != null ) ?
8084
ModelUtils.loadModelFromFile( modelPath, filePath, aspectModelLoader ) :
8185
loadModelFromUrn( aspectModelUrn );
8286
validateModel( aspectModel );
8387

88+
return aspectModel.files().stream().filter( a -> a.elements().stream().anyMatch( e -> e.urn().equals( aspectModelUrn ) ) )
89+
.findFirst().map( aspectModelFile -> Tuple.of( aspectModelFile.filename(),
90+
AspectSerializer.INSTANCE.aspectModelFileToString( aspectModelFile ) ) )
91+
.orElseThrow( () -> new FileNotFoundException( "Aspect Model not found" ) );
92+
} catch ( final ModelResolutionException e ) {
93+
throw new FileNotFoundException( e.getMessage(), e );
94+
}
95+
}
96+
97+
public String getModelNamespace( final AspectModelUrn aspectModelUrn, final String filePath ) {
98+
try {
99+
final AspectModel aspectModel = ( filePath != null ) ?
100+
ModelUtils.loadModelFromFile( modelPath, filePath, aspectModelLoader ) :
101+
loadModelFromUrn( aspectModelUrn );
102+
validateModel( aspectModel );
103+
104+
final Namespace first = aspectModel.namespaces().getFirst();
105+
84106
return aspectModel.files().stream().filter( a -> a.elements().stream().anyMatch( e -> e.urn().equals( aspectModelUrn ) ) )
85107
.findFirst().map( AspectSerializer.INSTANCE::aspectModelFileToString )
86108
.orElseThrow( () -> new FileNotFoundException( "Aspect Model not found" ) );

aspect-model-editor-service/src/main/java/org/eclipse/esmf/ame/services/PackageService.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.util.zip.ZipOutputStream;
3131

3232
import org.eclipse.esmf.ame.exceptions.CreateFileException;
33+
import org.eclipse.esmf.ame.exceptions.FileHandlingException;
3334
import org.eclipse.esmf.ame.exceptions.FileNotFoundException;
3435
import org.eclipse.esmf.ame.services.models.Version;
3536
import org.eclipse.esmf.ame.services.utils.ModelGroupingUtils;
@@ -43,7 +44,6 @@
4344
import org.eclipse.esmf.aspectmodel.generator.zip.AspectModelNamespacePackageCreator;
4445
import org.eclipse.esmf.aspectmodel.loader.AspectModelLoader;
4546
import org.eclipse.esmf.aspectmodel.resolver.NamespacePackage;
46-
import org.eclipse.esmf.aspectmodel.resolver.exceptions.ModelResolutionException;
4747
import org.eclipse.esmf.aspectmodel.resolver.fs.ModelsRoot;
4848
import org.eclipse.esmf.aspectmodel.resolver.fs.StructuredModelsRoot;
4949
import org.eclipse.esmf.aspectmodel.resolver.modelfile.RawAspectModelFileBuilder;
@@ -96,11 +96,16 @@ public Map<String, List<Version>> importPackage( final CompletedFileUpload zipFi
9696

9797
return new ModelGroupingUtils( aspectModelLoader ).groupModelsByNamespaceAndVersion( savedUris, false );
9898
} catch ( final IOException e ) {
99-
throw new ModelResolutionException( "Could not read from input", e );
99+
throw new FileHandlingException( "Could not read from input", e );
100100
}
101101
}
102102

103103
private AddAspectModelFile createAddChange( final AspectModelFile file, final ModelsRoot modelsRoot ) {
104+
if ( file.sourceModel().isEmpty() ) {
105+
// TODO check why this will not returend ...
106+
throw new FileHandlingException( "Source model is empty for file: " + file );
107+
}
108+
104109
final URI targetLocation = modelsRoot.directoryForNamespace( file.namespaceUrn() ).resolve( file.filename().orElseThrow() ).toUri();
105110

106111
final RawAspectModelFileBuilder builder = RawAspectModelFileBuilder.builder().sourceModel( file.sourceModel() )
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright (c) 2025 Robert Bosch Manufacturing Solutions GmbH
3+
*
4+
* See the AUTHORS file(s) distributed with this work for
5+
* additional 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.ame.services.models;
15+
16+
import io.micronaut.core.annotation.Introspected;
17+
import io.micronaut.serde.annotation.Serdeable;
18+
19+
/**
20+
* Represents a single migration result with success and erros.
21+
*/
22+
@Serdeable
23+
@Introspected
24+
public class FileEntry {
25+
private String absoluteName;
26+
private String fileName;
27+
private String aspectModelUrn;
28+
private String modelVersion;
29+
30+
public FileEntry( final String aspectModelUrn ) {
31+
this.aspectModelUrn = aspectModelUrn;
32+
}
33+
34+
public FileEntry( final String absoluteName, final String fileName, final String aspectModelUrn, final String modelVersion ) {
35+
this.absoluteName = absoluteName;
36+
this.fileName = fileName;
37+
this.aspectModelUrn = aspectModelUrn;
38+
this.modelVersion = modelVersion;
39+
}
40+
41+
public String getAbsoluteName() {
42+
return absoluteName;
43+
}
44+
45+
public void setAbsoluteName( final String absoluteName ) {
46+
this.absoluteName = absoluteName;
47+
}
48+
49+
public String getFileName() {
50+
return fileName;
51+
}
52+
53+
public void setFileName( final String fileName ) {
54+
this.fileName = fileName;
55+
}
56+
57+
public String getAspectModelUrn() {
58+
return aspectModelUrn;
59+
}
60+
61+
public void setAspectModelUrn( final String aspectModelUrn ) {
62+
this.aspectModelUrn = aspectModelUrn;
63+
}
64+
65+
public String getModelVersion() {
66+
return modelVersion;
67+
}
68+
69+
public void setModelVersion( final String modelVersion ) {
70+
this.modelVersion = modelVersion;
71+
}
72+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright (c) 2025 Robert Bosch Manufacturing Solutions GmbH
3+
*
4+
* See the AUTHORS file(s) distributed with this work for
5+
* additional 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.ame.services.models;
15+
16+
import io.micronaut.core.annotation.Introspected;
17+
import io.micronaut.serde.annotation.Serdeable;
18+
19+
/**
20+
* Represents a single migration result with success and erros.
21+
*/
22+
@Serdeable
23+
@Introspected
24+
public class FileInformation {
25+
private String absoluteName;
26+
private String aspectModelUrn;
27+
private String modelVersion;
28+
private String aspectModel;
29+
private String fileName;
30+
31+
public FileInformation( final String absoluteName, final String aspectModelUrn, final String modelVersion, final String aspectModel,
32+
final String fileName ) {
33+
this.absoluteName = absoluteName;
34+
this.aspectModelUrn = aspectModelUrn;
35+
this.modelVersion = modelVersion;
36+
this.aspectModel = aspectModel;
37+
this.fileName = fileName;
38+
}
39+
40+
public String getAbsoluteName() {
41+
return absoluteName;
42+
}
43+
44+
public void setAbsoluteName( final String absoluteName ) {
45+
this.absoluteName = absoluteName;
46+
}
47+
48+
public String getAspectModelUrn() {
49+
return aspectModelUrn;
50+
}
51+
52+
public void setAspectModelUrn( final String aspectModelUrn ) {
53+
this.aspectModelUrn = aspectModelUrn;
54+
}
55+
56+
public String getModelVersion() {
57+
return modelVersion;
58+
}
59+
60+
public void setModelVersion( final String modelVersion ) {
61+
this.modelVersion = modelVersion;
62+
}
63+
64+
public String getAspectModel() {
65+
return aspectModel;
66+
}
67+
68+
public void setAspectModel( final String aspectModel ) {
69+
this.aspectModel = aspectModel;
70+
}
71+
72+
public String getFileName() {
73+
return fileName;
74+
}
75+
76+
public void setFileName( final String fileName ) {
77+
this.fileName = fileName;
78+
}
79+
}

aspect-model-editor-service/src/test/java/org/eclipse/esmf/ame/services/ModelServiceTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ void testDeleteModel() {
8484

8585
@Test
8686
void testGetModel() throws ModelResolutionException {
87-
final String result = modelService.getModel( NAMESPACE.withName( TEST_MODEL_FOR_SERVICE ), TEST_FILEPATH );
87+
final String result = modelService.getModel( NAMESPACE.withName( TEST_MODEL_FOR_SERVICE ), TEST_FILEPATH )._2;
8888
assertTrue( result.contains( "@prefix samm: <urn:samm:org.eclipse.esmf.samm:meta-model:2.2.0#> ." ) );
8989
assertTrue( result.contains( "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> ." ) );
9090
assertTrue( result.contains( "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> ." ) );

aspect-model-editor-web/src/main/java/org/eclipse/esmf/ame/api/ModelController.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import java.net.URI;
1717
import java.net.URISyntaxException;
18+
import java.util.ArrayList;
1819
import java.util.List;
1920
import java.util.Map;
2021
import java.util.Optional;
@@ -24,6 +25,8 @@
2425
import org.eclipse.esmf.ame.exceptions.FileNotFoundException;
2526
import org.eclipse.esmf.ame.exceptions.UriNotDefinedException;
2627
import org.eclipse.esmf.ame.services.ModelService;
28+
import org.eclipse.esmf.ame.services.models.FileEntry;
29+
import org.eclipse.esmf.ame.services.models.FileInformation;
2730
import org.eclipse.esmf.ame.services.models.MigrationResult;
2831
import org.eclipse.esmf.ame.services.models.Version;
2932
import org.eclipse.esmf.ame.utils.ModelUtils;
@@ -43,6 +46,7 @@
4346
import io.micronaut.http.annotation.Produces;
4447
import io.micronaut.http.annotation.QueryValue;
4548
import io.micronaut.http.multipart.CompletedFileUpload;
49+
import io.vavr.Tuple2;
4650
import io.vavr.Value;
4751

4852
/**
@@ -75,7 +79,33 @@ public HttpResponse<String> getModel( @Header( URN ) final Optional<String> urn,
7579
@Header( "file-path" ) final Optional<String> filePath ) {
7680
final AspectModelUrn aspectModelUrn = parseAspectModelUrn( urn );
7781
final String path = filePath.orElse( null );
78-
return HttpResponse.ok( modelService.getModel( aspectModelUrn, path ) );
82+
return HttpResponse.ok( modelService.getModel( aspectModelUrn, path )._2 );
83+
}
84+
85+
/**
86+
* Method used to return multiple turtle files in batch based on a list of Aspect Model URNs.
87+
* Each URN consists of urn:samm:namespace:version#AspectModelElement
88+
*/
89+
@Post( uri = "batch", consumes = MediaType.APPLICATION_JSON )
90+
@Produces( MediaType.APPLICATION_JSON )
91+
public HttpResponse<List<FileInformation>> getModelsBatch( @Body final List<FileEntry> fileEntries ) {
92+
final List<FileInformation> fileInformations = new ArrayList<>();
93+
94+
for ( final FileEntry entry : fileEntries ) {
95+
try {
96+
final AspectModelUrn urn = parseAspectModelUrn( Optional.of( entry.getAspectModelUrn() ) );
97+
final Tuple2<Optional<String>, String> model = modelService.getModel( urn, null );
98+
99+
final FileInformation fileInformation = new FileInformation( entry.getAbsoluteName(), entry.getAspectModelUrn(),
100+
entry.getModelVersion(), model._2, model._1.orElse( "" ) );
101+
fileInformations.add( fileInformation );
102+
} catch ( final Exception e ) {
103+
throw new FileNotFoundException(
104+
String.format( "Failed to retrieve Aspect Model for URN: %s - %s", entry.getAspectModelUrn(), e.getMessage() ) );
105+
}
106+
}
107+
108+
return HttpResponse.ok( fileInformations );
79109
}
80110

81111
/**

0 commit comments

Comments
 (0)