Skip to content

Commit 22f7236

Browse files
authored
Enforce SAMM prefix & cleanup ModelGroupingUtils (#101)
Replace vavr Try usage with explicit null-checking for SAMM prefix and throw a clear IllegalStateException when an outdated BAMM definition is detected. Also tidy imports and reformat stream/Optional usage, simplify lambdas and grouping/collection calls, and perform minor refactors for readability. Functional behavior is preserved except that missing SAMM prefixes now produce a descriptive error pointing out legacy BAMM usage.
1 parent fbe4ba4 commit 22f7236

File tree

1 file changed

+62
-87
lines changed

1 file changed

+62
-87
lines changed

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

Lines changed: 62 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@
1616
import java.io.File;
1717
import java.net.URI;
1818
import java.nio.file.Path;
19-
import java.util.*;
19+
import java.util.AbstractMap;
20+
import java.util.Comparator;
21+
import java.util.LinkedHashMap;
22+
import java.util.List;
23+
import java.util.Map;
24+
import java.util.Optional;
2025
import java.util.stream.Collectors;
2126
import java.util.stream.Stream;
2227

23-
import org.apache.jena.rdf.model.*;
24-
import org.apache.jena.vocabulary.RDF;
2528
import org.eclipse.esmf.ame.services.models.Model;
2629
import org.eclipse.esmf.ame.services.models.Version;
2730
import org.eclipse.esmf.aspectmodel.AspectModelFile;
@@ -36,14 +39,16 @@
3639
import org.eclipse.esmf.metamodel.vocabulary.SammNs;
3740
import org.eclipse.esmf.samm.KnownVersion;
3841

39-
import io.vavr.control.Try;
42+
import org.apache.jena.rdf.model.Resource;
43+
import org.apache.jena.rdf.model.Statement;
44+
import org.apache.jena.vocabulary.RDF;
4045

4146
/**
4247
* A utility class for grouping model URIs by namespace and version.
4348
*
4449
* @param aspectModelLoader the loader for aspect models
4550
*/
46-
public record ModelGroupingUtils(AspectModelLoader aspectModelLoader) {
51+
public record ModelGroupingUtils( AspectModelLoader aspectModelLoader ) {
4752
/**
4853
* Constructs a ModelGrouper with the given base model path.
4954
*/
@@ -53,7 +58,7 @@ public record ModelGroupingUtils(AspectModelLoader aspectModelLoader) {
5358
/**
5459
* Groups model URIs by namespace and version, setting the existing field as specified.
5560
*
56-
* @param uriStream a stream of model URIs
61+
* @param uriStream a stream of model URIs
5762
* @param onlyAspectModels get only Aspect Models with Aspects as namespace list.
5863
* @return a map where the keys are namespaces and the values are lists of maps containing versions and their associated models
5964
*/
@@ -64,28 +69,22 @@ public Map<String, List<Version>> groupModelsByNamespaceAndVersion( final Stream
6469
/**
6570
* Groups model URIs by namespace and version, setting the existing field as specified.
6671
*
67-
* @param files a List of model Files
72+
* @param files a List of model Files
6873
* @param onlyAspectModels get only Aspect Models with Aspects as namespace list.
6974
* @return a map where the keys are namespaces and the values are lists of maps containing versions and their associated models
7075
*/
7176
public Map<String, List<Version>> groupModelsByNamespaceAndVersion( final List<File> files, final boolean onlyAspectModels ) {
7277
final List<Model> allModels = loadAndExtractModels( files, onlyAspectModels );
7378
final Map<String, List<Model>> modelsByNamespace = groupByNamespace( allModels );
7479

75-
return modelsByNamespace.entrySet().stream()
76-
.sorted( Map.Entry.comparingByKey() )
77-
.collect( Collectors.toMap(
78-
Map.Entry::getKey,
79-
entry -> groupByVersion( entry.getValue() ),
80-
this::throwOnDuplicateKey,
81-
LinkedHashMap::new ) );
80+
return modelsByNamespace.entrySet().stream().sorted( Map.Entry.comparingByKey() ).collect(
81+
Collectors.toMap( Map.Entry::getKey, entry -> groupByVersion( entry.getValue() ), this::throwOnDuplicateKey,
82+
LinkedHashMap::new ) );
8283
}
8384

8485
private List<Model> loadAndExtractModels( final List<File> files, final boolean onlyAspectModels ) {
85-
return files.stream()
86-
.map( this::loadModelWithVersion )
87-
.flatMap( entry -> extractModelsFromEntry( entry, onlyAspectModels ) )
88-
.toList();
86+
return files.stream().map( this::loadModelWithVersion ).flatMap( entry -> extractModelsFromEntry( entry, onlyAspectModels ) )
87+
.toList();
8988
}
9089

9190
private Map.Entry<RawAspectModelFile, Optional<KnownVersion>> loadModelWithVersion( final File file ) {
@@ -96,123 +95,99 @@ private Map.Entry<RawAspectModelFile, Optional<KnownVersion>> loadModelWithVersi
9695
}
9796

9897
private Optional<KnownVersion> extractMetaModelVersion( final RawAspectModelFile rawFile ) {
99-
return Try.of( () -> rawFile.sourceModel().getNsPrefixMap().get( SammNs.SAMM.getShortForm() ) )
100-
.flatMap( AspectModelUrn::from )
101-
.toJavaOptional()
102-
.map( AspectModelUrn::getVersion )
103-
.flatMap( KnownVersion::fromVersionString );
98+
final String sammPrefix = rawFile.sourceModel().getNsPrefixMap().get( SammNs.SAMM.getShortForm() );
99+
100+
if ( sammPrefix == null ) {
101+
final String bammPrefix = rawFile.sourceModel().getNsPrefixMap().get( "bamm" );
102+
throw new IllegalStateException( String.format(
103+
"The model uses an outdated BAMM definition '%s', which is no longer supported by the Aspect Model Editor. "
104+
+ "Please migrate your model to the current SAMM specification before reloading.",
105+
bammPrefix ) );
106+
}
107+
108+
return AspectModelUrn.from( sammPrefix ).toJavaOptional()
109+
.map( AspectModelUrn::getVersion )
110+
.flatMap( KnownVersion::fromVersionString );
104111
}
105112

106-
private Stream<Model> extractModelsFromEntry(final Map.Entry<RawAspectModelFile, Optional<KnownVersion>> entry, final boolean onlyAspectModels) {
107-
final KnownVersion version = entry.getValue()
108-
.orElseThrow(() -> new IllegalStateException("Meta model version is required"));
113+
private Stream<Model> extractModelsFromEntry( final Map.Entry<RawAspectModelFile, Optional<KnownVersion>> entry,
114+
final boolean onlyAspectModels ) {
115+
final KnownVersion version = entry.getValue().orElseThrow( () -> new IllegalStateException( "Meta model version is required" ) );
109116
final RawAspectModelFile rawFile = entry.getKey();
110117

111-
final String filename = extractFilename(rawFile);
112-
final List<Resource> resources = collectMetaModelResources(version);
113-
final Resource firstNonBlankSubject = findFirstNonBlankSubject(rawFile.sourceModel(), resources, filename);
118+
final String filename = extractFilename( rawFile );
119+
final List<Resource> resources = collectMetaModelResources( version );
120+
final Resource firstNonBlankSubject = findFirstNonBlankSubject( rawFile.sourceModel(), resources, filename );
114121

115-
final Model model = new Model(filename, AspectModelUrn.fromUrn(firstNonBlankSubject.getURI()),
116-
version.toVersionString(), true);
122+
final Model model = new Model( filename, AspectModelUrn.fromUrn( firstNonBlankSubject.getURI() ), version.toVersionString(), true );
117123

118-
return Stream.of(model);
124+
return Stream.of( model );
119125
}
120126

121-
private String extractFilename(final RawAspectModelFile rawFile) {
122-
return rawFile.sourceLocation()
123-
.map(uri -> Path.of(uri).getFileName().toString())
124-
.orElse("unnamed file");
127+
private String extractFilename( final RawAspectModelFile rawFile ) {
128+
return rawFile.sourceLocation().map( uri -> Path.of( uri ).getFileName().toString() ).orElse( "unnamed file" );
125129
}
126130

127-
private List<Resource> collectMetaModelResources(final KnownVersion version) {
128-
final SAMM samm = new SAMM(version);
129-
final SAMMC sammc = new SAMMC(version);
130-
final SAMME samme = new SAMME(version, samm);
131+
private List<Resource> collectMetaModelResources( final KnownVersion version ) {
132+
final SAMM samm = new SAMM( version );
133+
final SAMMC sammc = new SAMMC( version );
134+
final SAMME samme = new SAMME( version, samm );
131135

132136
return Stream.of(
133-
Stream.of(samm.Aspect(), samm.Property(), samm.Operation(), samm.Event(),
134-
samm.Entity(), samm.Value(), samm.Characteristic(), samm.Constraint(),
135-
samm.AbstractEntity(), samm.AbstractProperty()),
136-
samme.allEntities(),
137-
sammc.allCharacteristics(),
138-
sammc.allConstraints(),
139-
sammc.allCollections()
140-
).flatMap(s -> s).toList();
137+
Stream.of( samm.Aspect(), samm.Property(), samm.Operation(), samm.Event(), samm.Entity(), samm.Value(), samm.Characteristic(),
138+
samm.Constraint(), samm.AbstractEntity(), samm.AbstractProperty() ), samme.allEntities(), sammc.allCharacteristics(),
139+
sammc.allConstraints(), sammc.allCollections() ).flatMap( s -> s ).toList();
141140
}
142141

143-
private Resource findFirstNonBlankSubject(final org.apache.jena.rdf.model.Model sourceModel, final List<Resource> resources, final String filename) {
144-
return resources.stream()
145-
.flatMap(resource -> sourceModel.listStatements(null, RDF.type, resource).toList().stream())
146-
.map(Statement::getSubject)
147-
.filter(subject -> !subject.isAnon())
148-
.findFirst()
149-
.orElseThrow(() -> new IllegalStateException("No non-blank subject found in " + filename));
142+
private Resource findFirstNonBlankSubject( final org.apache.jena.rdf.model.Model sourceModel, final List<Resource> resources,
143+
final String filename ) {
144+
return resources.stream().flatMap( resource -> sourceModel.listStatements( null, RDF.type, resource ).toList().stream() )
145+
.map( Statement::getSubject ).filter( subject -> !subject.isAnon() ).findFirst()
146+
.orElseThrow( () -> new IllegalStateException( "No non-blank subject found in " + filename ) );
150147
}
151148

152149
private Map<String, List<Model>> groupByNamespace( final List<Model> models ) {
153-
return models.stream()
154-
.collect( Collectors.groupingBy( model ->
155-
model.aspectModelUrn().getNamespaceMainPart() ) );
150+
return models.stream().collect( Collectors.groupingBy( model -> model.aspectModelUrn().getNamespaceMainPart() ) );
156151
}
157152

158153
private Stream<ModelElement> extractModelElement( final AspectModelFile file, final boolean onlyAspectModels ) {
159154

160-
final Optional<ModelElement> aspectElement = file.aspects().stream()
161-
.map( ModelElement.class::cast )
162-
.findFirst();
155+
final Optional<ModelElement> aspectElement = file.aspects().stream().map( ModelElement.class::cast ).findFirst();
163156

164157
if ( onlyAspectModels ) {
165158
return aspectElement.stream();
166159
}
167160

168-
return aspectElement
169-
.or( () -> findFirstNonAnonymousElement( file ) )
170-
.stream();
161+
return aspectElement.or( () -> findFirstNonAnonymousElement( file ) ).stream();
171162
}
172163

173164
private Optional<ModelElement> findFirstNonAnonymousElement( final AspectModelFile file ) {
174-
return file.elements().stream()
175-
.filter( element -> !element.isAnonymous() )
176-
.findAny();
165+
return file.elements().stream().filter( element -> !element.isAnonymous() ).findAny();
177166
}
178167

179168
private List<Version> groupByVersion( final List<Model> models ) {
180169
final Map<AspectModelUrn, Model> uniqueModels = removeDuplicateModels( models );
181170
final Map<String, List<Model>> modelsByVersion = groupModelsByVersionString( uniqueModels );
182171

183-
return modelsByVersion.entrySet().stream()
184-
.sorted( Map.Entry.comparingByKey() )
185-
.map( this::createVersionEntry )
186-
.toList();
172+
return modelsByVersion.entrySet().stream().sorted( Map.Entry.comparingByKey() ).map( this::createVersionEntry ).toList();
187173
}
188174

189175
private Map<AspectModelUrn, Model> removeDuplicateModels( final List<Model> models ) {
190176
return models.stream()
191-
.collect( Collectors.toMap(
192-
Model::aspectModelUrn,
193-
model -> model,
194-
( existing, duplicate ) -> existing,
195-
LinkedHashMap::new ) );
177+
.collect( Collectors.toMap( Model::aspectModelUrn, model -> model, ( existing, duplicate ) -> existing, LinkedHashMap::new ) );
196178
}
197179

198-
private Map<String, List<Model>> groupModelsByVersionString(
199-
final Map<AspectModelUrn, Model> uniqueModels ) {
180+
private Map<String, List<Model>> groupModelsByVersionString( final Map<AspectModelUrn, Model> uniqueModels ) {
200181

201-
return uniqueModels.values().stream()
202-
.collect( Collectors.groupingBy( model ->
203-
model.aspectModelUrn().getVersion() ) );
182+
return uniqueModels.values().stream().collect( Collectors.groupingBy( model -> model.aspectModelUrn().getVersion() ) );
204183
}
205184

206185
private Version createVersionEntry( final Map.Entry<String, List<Model>> entry ) {
207-
final List<Model> sortedModels = entry.getValue().stream()
208-
.sorted( Comparator.comparing( Model::model ) )
209-
.toList();
186+
final List<Model> sortedModels = entry.getValue().stream().sorted( Comparator.comparing( Model::model ) ).toList();
210187
return new Version( entry.getKey(), sortedModels );
211188
}
212189

213190
private <T> T throwOnDuplicateKey( final T v1, final T v2 ) {
214-
throw new RuntimeException(
215-
String.format( "Duplicate key for values %s and %s", v1, v2 ) );
191+
throw new RuntimeException( String.format( "Duplicate key for values %s and %s", v1, v2 ) );
216192
}
217-
218193
}

0 commit comments

Comments
 (0)