diff --git a/aspect-model-editor-service/pom.xml b/aspect-model-editor-service/pom.xml
index 1199ded8..ffdbc08e 100644
--- a/aspect-model-editor-service/pom.xml
+++ b/aspect-model-editor-service/pom.xml
@@ -39,10 +39,6 @@
org.eclipse.esmf
esmf-native-support
-
- org.apache.commons
- commons-compress
-
diff --git a/aspect-model-editor-service/src/main/java/org/eclipse/esmf/ame/services/ModelService.java b/aspect-model-editor-service/src/main/java/org/eclipse/esmf/ame/services/ModelService.java
index 7e48a448..728f30a3 100644
--- a/aspect-model-editor-service/src/main/java/org/eclipse/esmf/ame/services/ModelService.java
+++ b/aspect-model-editor-service/src/main/java/org/eclipse/esmf/ame/services/ModelService.java
@@ -16,6 +16,7 @@
import java.io.File;
import java.io.IOException;
import java.net.URI;
+import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
@@ -85,9 +86,8 @@ public AspectModelResult getModel( final AspectModelUrn aspectModelUrn, final @N
loadModelFromUrn( aspectModelUrn );
validateModel( aspectModel );
- return aspectModel.files().stream().filter( a -> a.elements().stream().anyMatch(
- e -> ( e instanceof DefaultScalarValue && ( (DefaultScalarValue) e ).getType()
- .equals( new DefaultScalar( aspectModelUrn.toString() ) ) ) || e.urn().equals( aspectModelUrn ) ) ).findFirst()
+ return aspectModel.files().stream().filter( file -> containsElement( file, aspectModelUrn ) )
+ .filter( aspectModelFile -> aspectModelFile.sourceLocation().isPresent() ).filter( this::hasValidCasing ).findFirst()
.map( aspectModelFile -> new AspectModelResult( aspectModelFile.filename(),
AspectSerializer.INSTANCE.aspectModelFileToString( aspectModelFile ) ) )
.orElseThrow( () -> new FileNotFoundException( "Aspect Model not found" ) );
@@ -96,6 +96,29 @@ public AspectModelResult getModel( final AspectModelUrn aspectModelUrn, final @N
}
}
+ private boolean containsElement( final AspectModelFile file, final AspectModelUrn aspectModelUrn ) {
+ return file.elements().stream().anyMatch( e -> ( e instanceof DefaultScalarValue && ( (DefaultScalarValue) e ).getType()
+ .equals( new DefaultScalar( aspectModelUrn.toString() ) ) ) || e.urn().equals( aspectModelUrn ) );
+ }
+
+ private boolean hasValidCasing( final AspectModelFile aspectModelFile ) {
+ try {
+ final URI sourceLocation = aspectModelFile.sourceLocation().orElseThrow( () -> new IOException( "Source location not present" ) );
+ final Path file = Path.of( sourceLocation );
+
+ if ( !Files.exists( file ) ) {
+ return false;
+ }
+
+ final Path realPath = file.toRealPath();
+ final Path providedPath = file.toAbsolutePath().normalize();
+
+ return realPath.getFileName().toString().equals( providedPath.getFileName().toString() );
+ } catch ( final IOException e ) {
+ return false;
+ }
+ }
+
private AspectModel loadModelFromUrn( final AspectModelUrn aspectModelUrn ) {
final Supplier aspectModelSupplier = ModelUtils.getAspectModelSupplier( aspectModelUrn, aspectModelLoader );
return aspectModelSupplier.get();
@@ -254,8 +277,7 @@ public boolean checkElementExists( final AspectModelUrn aspectModelUrn, final St
try {
System.out.println( loadModelFromUrn( aspectModelUrn ).files() );
- return loadModelFromUrn( aspectModelUrn ).files().stream()
- .anyMatch( f -> !fileName.equals( f.filename().orElse( "" ) ) );
+ return loadModelFromUrn( aspectModelUrn ).files().stream().anyMatch( f -> !fileName.equals( f.filename().orElse( "" ) ) );
} catch ( final ModelResolutionException e ) {
return false;
}
diff --git a/aspect-model-editor-service/src/main/java/org/eclipse/esmf/ame/services/utils/ModelGroupingUtils.java b/aspect-model-editor-service/src/main/java/org/eclipse/esmf/ame/services/utils/ModelGroupingUtils.java
index 6f239949..cabeccae 100644
--- a/aspect-model-editor-service/src/main/java/org/eclipse/esmf/ame/services/utils/ModelGroupingUtils.java
+++ b/aspect-model-editor-service/src/main/java/org/eclipse/esmf/ame/services/utils/ModelGroupingUtils.java
@@ -15,23 +15,24 @@
import java.io.File;
import java.net.URI;
-import java.util.AbstractMap;
-import java.util.Comparator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
+import java.nio.file.Path;
+import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import org.apache.jena.rdf.model.*;
+import org.apache.jena.vocabulary.RDF;
import org.eclipse.esmf.ame.services.models.Model;
import org.eclipse.esmf.ame.services.models.Version;
import org.eclipse.esmf.aspectmodel.AspectModelFile;
import org.eclipse.esmf.aspectmodel.loader.AspectModelLoader;
import org.eclipse.esmf.aspectmodel.resolver.AspectModelFileLoader;
+import org.eclipse.esmf.aspectmodel.resolver.modelfile.RawAspectModelFile;
import org.eclipse.esmf.aspectmodel.urn.AspectModelUrn;
-import org.eclipse.esmf.metamodel.AspectModel;
import org.eclipse.esmf.metamodel.ModelElement;
+import org.eclipse.esmf.metamodel.vocabulary.SAMM;
+import org.eclipse.esmf.metamodel.vocabulary.SAMMC;
+import org.eclipse.esmf.metamodel.vocabulary.SAMME;
import org.eclipse.esmf.metamodel.vocabulary.SammNs;
import org.eclipse.esmf.samm.KnownVersion;
@@ -42,7 +43,7 @@
*
* @param aspectModelLoader the loader for aspect models
*/
-public record ModelGroupingUtils( AspectModelLoader aspectModelLoader ) {
+public record ModelGroupingUtils(AspectModelLoader aspectModelLoader) {
/**
* Constructs a ModelGrouper with the given base model path.
*/
@@ -52,7 +53,7 @@ public record ModelGroupingUtils( AspectModelLoader aspectModelLoader ) {
/**
* Groups model URIs by namespace and version, setting the existing field as specified.
*
- * @param uriStream a stream of model URIs
+ * @param uriStream a stream of model URIs
* @param onlyAspectModels get only Aspect Models with Aspects as namespace list.
* @return a map where the keys are namespaces and the values are lists of maps containing versions and their associated models
*/
@@ -63,48 +64,155 @@ public Map> groupModelsByNamespaceAndVersion( final Stream
/**
* Groups model URIs by namespace and version, setting the existing field as specified.
*
- * @param files a List of model Files
+ * @param files a List of model Files
* @param onlyAspectModels get only Aspect Models with Aspects as namespace list.
* @return a map where the keys are namespaces and the values are lists of maps containing versions and their associated models
*/
public Map> groupModelsByNamespaceAndVersion( final List files, final boolean onlyAspectModels ) {
- return files.stream().map( file -> {
- final Optional metaModelVersionFromFile = Try.of(
- () -> AspectModelFileLoader.load( file ).sourceModel().getNsPrefixMap().get( SammNs.SAMM.getShortForm() ) )
- .flatMap( AspectModelUrn::from ).toJavaOptional().map( AspectModelUrn::getVersion )
- .flatMap( KnownVersion::fromVersionString );
- final AspectModel loadedModel = aspectModelLoader.load( file );
- return new AbstractMap.SimpleEntry<>( loadedModel, metaModelVersionFromFile );
- } ).flatMap(
- entry -> entry.getKey().files().stream().flatMap( file -> extractModelElement( file, onlyAspectModels ) ).map( modelElement -> {
- assert entry.getValue().orElse( null ) != null;
- return createModel( modelElement, entry.getValue().orElse( null ) );
- } ) ).collect( Collectors.groupingBy( model -> model.aspectModelUrn().getNamespaceMainPart() ) ).entrySet().stream()
- .sorted( Map.Entry.comparingByKey() )
- .collect( Collectors.toMap( Map.Entry::getKey, entry -> groupByVersion( entry.getValue() ), ( v1, v2 ) -> {
- throw new RuntimeException( String.format( "Duplicate key for values %s and %s", v1, v2 ) );
- }, LinkedHashMap::new ) );
+ final List allModels = loadAndExtractModels( files, onlyAspectModels );
+ final Map> modelsByNamespace = groupByNamespace( allModels );
+
+ return modelsByNamespace.entrySet().stream()
+ .sorted( Map.Entry.comparingByKey() )
+ .collect( Collectors.toMap(
+ Map.Entry::getKey,
+ entry -> groupByVersion( entry.getValue() ),
+ this::throwOnDuplicateKey,
+ LinkedHashMap::new ) );
+ }
+
+ private List loadAndExtractModels( final List files, final boolean onlyAspectModels ) {
+ return files.stream()
+ .map( this::loadModelWithVersion )
+ .flatMap( entry -> extractModelsFromEntry( entry, onlyAspectModels ) )
+ .toList();
+ }
+
+ private Map.Entry> loadModelWithVersion( final File file ) {
+ final RawAspectModelFile rawFile = AspectModelFileLoader.load( file );
+ final Optional metaModelVersion = extractMetaModelVersion( rawFile );
+
+ return new AbstractMap.SimpleEntry<>( rawFile, metaModelVersion );
+ }
+
+ private Optional extractMetaModelVersion( final RawAspectModelFile rawFile ) {
+ return Try.of( () -> rawFile.sourceModel().getNsPrefixMap().get( SammNs.SAMM.getShortForm() ) )
+ .flatMap( AspectModelUrn::from )
+ .toJavaOptional()
+ .map( AspectModelUrn::getVersion )
+ .flatMap( KnownVersion::fromVersionString );
+ }
+
+ private Stream extractModelsFromEntry(final Map.Entry> entry, final boolean onlyAspectModels) {
+ final KnownVersion version = entry.getValue()
+ .orElseThrow(() -> new IllegalStateException("Meta model version is required"));
+ final RawAspectModelFile rawFile = entry.getKey();
+
+ final String filename = extractFilename(rawFile);
+ final List resources = collectMetaModelResources(version);
+ final Resource firstNonBlankSubject = findFirstNonBlankSubject(rawFile.sourceModel(), resources, filename);
+
+ final Model model = new Model(filename, AspectModelUrn.fromUrn(firstNonBlankSubject.getURI()),
+ version.toVersionString(), true);
+
+ return Stream.of(model);
+ }
+
+ private String extractFilename(final RawAspectModelFile rawFile) {
+ return rawFile.sourceLocation()
+ .map(uri -> Path.of(uri).getFileName().toString())
+ .orElse("unnamed file");
+ }
+
+ private List collectMetaModelResources(final KnownVersion version) {
+ final SAMM samm = new SAMM(version);
+ final SAMMC sammc = new SAMMC(version);
+ final SAMME samme = new SAMME(version, samm);
+
+ return Stream.of(
+ Stream.of(samm.Aspect(), samm.Property(), samm.Operation(), samm.Event(),
+ samm.Entity(), samm.Value(), samm.Characteristic(), samm.Constraint(),
+ samm.AbstractEntity(), samm.AbstractProperty()),
+ samme.allEntities(),
+ sammc.allCharacteristics(),
+ sammc.allConstraints(),
+ sammc.allCollections()
+ ).flatMap(s -> s).toList();
+ }
+
+ private Resource findFirstNonBlankSubject(final org.apache.jena.rdf.model.Model sourceModel, final List resources, final String filename) {
+ return resources.stream()
+ .flatMap(resource -> sourceModel.listStatements(null, RDF.type, resource).toList().stream())
+ .map(Statement::getSubject)
+ .filter(subject -> !subject.isAnon())
+ .findFirst()
+ .orElseThrow(() -> new IllegalStateException("No non-blank subject found in " + filename));
+ }
+
+ private Map> groupByNamespace( final List models ) {
+ return models.stream()
+ .collect( Collectors.groupingBy( model ->
+ model.aspectModelUrn().getNamespaceMainPart() ) );
}
private Stream extractModelElement( final AspectModelFile file, final boolean onlyAspectModels ) {
+
+ final Optional aspectElement = file.aspects().stream()
+ .map( ModelElement.class::cast )
+ .findFirst();
+
if ( onlyAspectModels ) {
- return file.aspects().stream().map( ModelElement.class::cast ).findFirst().stream();
+ return aspectElement.stream();
}
- return file.aspects().stream().map( ModelElement.class::cast ).findFirst()
- .or( () -> file.elements().stream().filter( element -> !element.isAnonymous() ).findAny() ).stream();
+ return aspectElement
+ .or( () -> findFirstNonAnonymousElement( file ) )
+ .stream();
}
- private Model createModel( final ModelElement element, final KnownVersion version ) {
- final String filename = element.getSourceFile().filename().orElse( "unnamed file" );
- return new Model( filename, element.urn(), version.toVersionString(), true );
+ private Optional findFirstNonAnonymousElement( final AspectModelFile file ) {
+ return file.elements().stream()
+ .filter( element -> !element.isAnonymous() )
+ .findAny();
}
private List groupByVersion( final List models ) {
+ final Map uniqueModels = removeDuplicateModels( models );
+ final Map> modelsByVersion = groupModelsByVersionString( uniqueModels );
+
+ return modelsByVersion.entrySet().stream()
+ .sorted( Map.Entry.comparingByKey() )
+ .map( this::createVersionEntry )
+ .toList();
+ }
+
+ private Map removeDuplicateModels( final List models ) {
return models.stream()
- .collect( Collectors.toMap( Model::aspectModelUrn, model -> model, ( existing, duplicate ) -> existing, LinkedHashMap::new ) )
- .values().stream().collect( Collectors.groupingBy( model -> model.aspectModelUrn().getVersion() ) ).entrySet().stream()
- .sorted( Map.Entry.comparingByKey() ).map( entry -> new Version( entry.getKey(),
- entry.getValue().stream().sorted( Comparator.comparing( Model::model ) ).toList() ) ).toList();
+ .collect( Collectors.toMap(
+ Model::aspectModelUrn,
+ model -> model,
+ ( existing, duplicate ) -> existing,
+ LinkedHashMap::new ) );
}
+
+ private Map> groupModelsByVersionString(
+ final Map uniqueModels ) {
+
+ return uniqueModels.values().stream()
+ .collect( Collectors.groupingBy( model ->
+ model.aspectModelUrn().getVersion() ) );
+ }
+
+ private Version createVersionEntry( final Map.Entry> entry ) {
+ final List sortedModels = entry.getValue().stream()
+ .sorted( Comparator.comparing( Model::model ) )
+ .toList();
+ return new Version( entry.getKey(), sortedModels );
+ }
+
+ private T throwOnDuplicateKey( final T v1, final T v2 ) {
+ throw new RuntimeException(
+ String.format( "Duplicate key for values %s and %s", v1, v2 ) );
+ }
+
}
diff --git a/aspect-model-editor-service/src/main/java/org/eclipse/esmf/ame/services/utils/ModelUtils.java b/aspect-model-editor-service/src/main/java/org/eclipse/esmf/ame/services/utils/ModelUtils.java
index edc734f9..f31678b3 100644
--- a/aspect-model-editor-service/src/main/java/org/eclipse/esmf/ame/services/utils/ModelUtils.java
+++ b/aspect-model-editor-service/src/main/java/org/eclipse/esmf/ame/services/utils/ModelUtils.java
@@ -233,7 +233,7 @@ public AspectModel get() {
* @return the loaded {@link AspectModel}
*/
public static AspectModel loadModelFromFile( final Path modelPath, final String filePath, final AspectModelLoader aspectModelLoader ) {
- final Path path = Paths.get( filePath ).normalize();
+ final Path path = Paths.get( filePath.replace( ":", File.separator ) ).normalize();
final String[] pathParts = StreamSupport.stream( path.spliterator(), false ).map( Path::toString ).toArray( String[]::new );
final Path aspectModelPath = constructModelPath( modelPath, pathParts[0], pathParts[1], pathParts[2] );
return aspectModelLoader.load( aspectModelPath.toFile() );
diff --git a/aspect-model-editor-web/pom.xml b/aspect-model-editor-web/pom.xml
index 0582862e..6039d642 100644
--- a/aspect-model-editor-web/pom.xml
+++ b/aspect-model-editor-web/pom.xml
@@ -52,10 +52,6 @@
-
- org.apache.velocity
- velocity-engine-core
-
io.micronaut
micronaut-http-client
diff --git a/aspect-model-editor-web/src/main/java/org/eclipse/esmf/ame/api/ModelController.java b/aspect-model-editor-web/src/main/java/org/eclipse/esmf/ame/api/ModelController.java
index d705f235..13b0b9f3 100644
--- a/aspect-model-editor-web/src/main/java/org/eclipse/esmf/ame/api/ModelController.java
+++ b/aspect-model-editor-web/src/main/java/org/eclipse/esmf/ame/api/ModelController.java
@@ -75,11 +75,9 @@ private AspectModelUrn parseAspectModelUrn( final Optional urn ) {
*/
@Get()
@Produces( MediaTypeExtension.TEXT_TURTLE_VALUE )
- public HttpResponse getModel( @Header( URN ) final Optional urn,
- @Header( "file-path" ) final Optional filePath ) {
+ public HttpResponse getModel( @Header( URN ) final Optional urn ) {
final AspectModelUrn aspectModelUrn = parseAspectModelUrn( urn );
- final String path = filePath.orElse( null );
- return HttpResponse.ok( modelService.getModel( aspectModelUrn, path ).content() );
+ return HttpResponse.ok( modelService.getModel( aspectModelUrn, null ).content() );
}
/**
@@ -93,8 +91,7 @@ public HttpResponse getModel( @Header( URN ) final Optional urn,
* @return True if the element exists in a different file, false otherwise
*/
@Get( uri = "check-element", consumes = MediaType.APPLICATION_JSON )
- public HttpResponse checkElementExists( @Header( URN ) final Optional urn,
- @QueryValue() final String fileName ) {
+ public HttpResponse checkElementExists( @Header( URN ) final Optional urn, @QueryValue() final String fileName ) {
final AspectModelUrn aspectModelUrn = parseAspectModelUrn( urn );
return HttpResponse.ok( modelService.checkElementExists( aspectModelUrn, fileName ) );
}
@@ -111,7 +108,7 @@ public HttpResponse> getModelsBatch( @Body final List
- 2.11.1
+ 2.13.0
4.7.6
@@ -84,13 +84,9 @@
24.1.2
3.0.2
6.0.0
- 3.12.0
0.9.23
- 1.3
2.17.2
2.17.2
- 1.26.0
- 2.4
1.5.0
@@ -322,11 +318,6 @@
${jakarta-version}
provided
-
- org.apache.commons
- commons-exec
- ${commons-exec-version}
-
commons-codec
commons-codec
@@ -348,16 +339,6 @@
jackson-core
${jackson-core-version}
-
- org.apache.commons
- commons-compress
- ${commons-compress-version}
-
-
- org.apache.velocity
- velocity-engine-core
- ${velocity-version}
-
org.graphper
graph-support-core