Skip to content

Commit 2bb9f3b

Browse files
authored
Merge branch 'main' into chris-volk-samm-cli-list-of-commands
2 parents fe0344f + 71587cd commit 2bb9f3b

File tree

98 files changed

+4256
-578
lines changed

Some content is hidden

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

98 files changed

+4256
-578
lines changed

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import org.eclipse.esmf.metamodel.ModelElement;
2121
import org.eclipse.esmf.metamodel.ModelElementGroup;
22+
import org.eclipse.esmf.metamodel.Namespace;
2223

2324
import org.apache.jena.rdf.model.Model;
2425

@@ -31,10 +32,12 @@ default List<String> headerComment() {
3132

3233
Optional<URI> sourceLocation();
3334

35+
default Namespace namespace() {
36+
throw new UnsupportedOperationException( "Uninitialized Aspect Model" );
37+
}
38+
3439
@Override
3540
default List<ModelElement> elements() {
3641
throw new UnsupportedOperationException( "Uninitialized Aspect Model" );
3742
}
38-
39-
// boolean isAutoMigrated();
4043
}

core/esmf-aspect-meta-model-interface/src/main/java/org/eclipse/esmf/metamodel/vocabulary/SAMM.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ public String getNamespace() {
5050
return getUri() + "#";
5151
}
5252

53+
@SuppressWarnings( "checkstyle:MethodName" )
54+
public Resource Namespace() {
55+
return resource( "Namespace" );
56+
}
57+
5358
public Property listType() {
5459
return property( "listType" );
5560
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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.metamodel.vocabulary;
15+
16+
public class SimpleRdfNamespace implements RdfNamespace {
17+
private final String shortForm;
18+
private final String uri;
19+
20+
public SimpleRdfNamespace( final String shortForm, final String uri ) {
21+
this.shortForm = shortForm;
22+
this.uri = uri;
23+
}
24+
25+
@Override
26+
public String getShortForm() {
27+
return shortForm;
28+
}
29+
30+
@Override
31+
public String getUri() {
32+
return uri;
33+
}
34+
}

core/esmf-aspect-meta-model-java/pom.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@
5858
<groupId>com.google.guava</groupId>
5959
<artifactId>guava</artifactId>
6060
</dependency>
61+
<dependency>
62+
<groupId>io.soabase.record-builder</groupId>
63+
<artifactId>record-builder-processor</artifactId>
64+
<scope>provided</scope>
65+
</dependency>
6166

6267
<!-- Test dependencies -->
6368
<dependency>
@@ -153,6 +158,11 @@
153158
<artifactId>lombok</artifactId>
154159
<version>${lombok-version}</version>
155160
</path>
161+
<path>
162+
<groupId>io.soabase.record-builder</groupId>
163+
<artifactId>record-builder-processor</artifactId>
164+
<version>${record-builder-version}</version>
165+
</path>
156166
</annotationProcessorPaths>
157167
</configuration>
158168
<executions>
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
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;
15+
16+
import static java.util.stream.Collectors.toSet;
17+
18+
import java.util.HashMap;
19+
import java.util.Map;
20+
import java.util.Set;
21+
import java.util.function.Function;
22+
import java.util.stream.Stream;
23+
24+
import org.eclipse.esmf.aspectmodel.resolver.services.TurtleLoader;
25+
import org.eclipse.esmf.aspectmodel.urn.AspectModelUrn;
26+
import org.eclipse.esmf.aspectmodel.urn.ElementType;
27+
import org.eclipse.esmf.metamodel.vocabulary.SammNs;
28+
29+
import com.google.common.collect.Streams;
30+
import org.apache.jena.rdf.model.Literal;
31+
import org.apache.jena.rdf.model.Model;
32+
import org.apache.jena.rdf.model.ModelFactory;
33+
import org.apache.jena.rdf.model.Property;
34+
import org.apache.jena.rdf.model.RDFNode;
35+
import org.apache.jena.rdf.model.Resource;
36+
import org.apache.jena.rdf.model.Statement;
37+
import org.apache.jena.vocabulary.RDF;
38+
import org.apache.jena.vocabulary.XSD;
39+
40+
public class RdfUtil {
41+
public static Model getModelElementDefinition( final Resource element ) {
42+
final Model result = ModelFactory.createDefaultModel();
43+
element.getModel().listStatements( element, null, (RDFNode) null ).toList().forEach( statement -> {
44+
final Resource subject = statement.getSubject();
45+
final Resource newSubject = subject.isAnon()
46+
? result.createResource( subject.getId() )
47+
: result.createResource( subject.getURI() );
48+
final Property newPredicate = result.createProperty( statement.getPredicate().getURI() );
49+
final RDFNode newObject;
50+
if ( statement.getObject().isURIResource() ) {
51+
newObject = result.createResource( statement.getObject().asResource().getURI() );
52+
} else if ( statement.getObject().isLiteral() ) {
53+
newObject = statement.getObject();
54+
} else if ( statement.getObject().isAnon() ) {
55+
newObject = result.createResource( statement.getObject().asResource().getId() );
56+
result.add( getModelElementDefinition( statement.getObject().asResource() ) );
57+
} else {
58+
newObject = statement.getObject();
59+
}
60+
result.add( newSubject, newPredicate, newObject );
61+
} );
62+
return result;
63+
}
64+
65+
public static Set<AspectModelUrn> getAllUrnsInModel( final Model model ) {
66+
return Streams.stream( model.listStatements().mapWith( statement -> {
67+
final Stream<String> subjectUri = statement.getSubject().isURIResource()
68+
? Stream.of( statement.getSubject().getURI() )
69+
: Stream.empty();
70+
final Stream<String> propertyUri = Stream.of( statement.getPredicate().getURI() );
71+
final Stream<String> objectUri = statement.getObject().isURIResource()
72+
? Stream.of( statement.getObject().asResource().getURI() )
73+
: Stream.empty();
74+
75+
return Stream.of( subjectUri, propertyUri, objectUri )
76+
.flatMap( Function.identity() )
77+
.flatMap( urn -> AspectModelUrn.from( urn ).toJavaOptional().stream() );
78+
} ) ).flatMap( Function.identity() ).collect( toSet() );
79+
}
80+
81+
public static void cleanPrefixes( final Model model ) {
82+
final Map<String, String> originalPrefixMap = new HashMap<>( model.getNsPrefixMap() );
83+
model.clearNsPrefixMap();
84+
// SAMM prefixes
85+
getAllUrnsInModel( model ).forEach( urn -> {
86+
switch ( urn.getElementType() ) {
87+
case META_MODEL -> model.setNsPrefix( SammNs.SAMM.getShortForm(), SammNs.SAMM.getNamespace() );
88+
case CHARACTERISTIC -> model.setNsPrefix( SammNs.SAMMC.getShortForm(), SammNs.SAMMC.getNamespace() );
89+
case ENTITY -> model.setNsPrefix( SammNs.SAMME.getShortForm(), SammNs.SAMME.getNamespace() );
90+
case UNIT -> model.setNsPrefix( SammNs.UNIT.getShortForm(), SammNs.UNIT.getNamespace() );
91+
default -> {
92+
// nothing to do
93+
}
94+
}
95+
} );
96+
// XSD
97+
Stream.concat(
98+
Streams.stream( model.listObjects() )
99+
.filter( RDFNode::isLiteral )
100+
.map( RDFNode::asLiteral )
101+
.map( Literal::getDatatypeURI )
102+
.filter( type -> type.startsWith( XSD.NS ) )
103+
.filter( type -> !type.equals( XSD.xstring.getURI() ) ),
104+
Streams.stream( model.listObjects() )
105+
.filter( RDFNode::isURIResource )
106+
.map( RDFNode::asResource )
107+
.map( Resource::getURI )
108+
.filter( type -> type.startsWith( XSD.NS ) ) )
109+
.findAny()
110+
.ifPresent( resource -> model.setNsPrefix( "xsd", XSD.NS ) );
111+
// Empty (namespace) prefix
112+
Streams.stream( model.listStatements( null, RDF.type, (RDFNode) null ) )
113+
.map( Statement::getSubject )
114+
.filter( Resource::isURIResource )
115+
.map( Resource::getURI )
116+
.map( AspectModelUrn::fromUrn )
117+
.findAny()
118+
.ifPresent( urn -> model.setNsPrefix( "", urn.getUrnPrefix() ) );
119+
// Add back custom prefixes not already covered:
120+
// - if the prefix or URI is not set already
121+
// - it's not XSD (no need to add it here if it's not added above)
122+
// - if it's a SAMM URN, it's a regular namespace (not a meta model namespace)
123+
originalPrefixMap.forEach( ( prefix, uri ) -> {
124+
if ( !model.getNsPrefixMap().containsKey( prefix )
125+
&& !model.getNsPrefixMap().containsValue( uri )
126+
&& !uri.equals( XSD.NS )
127+
&& ( !uri.startsWith( "urn:samm:" ) || AspectModelUrn.fromUrn( uri + "x" ).getElementType() == ElementType.NONE )
128+
) {
129+
model.setNsPrefix( prefix, uri );
130+
}
131+
} );
132+
}
133+
134+
/**
135+
* Convenience method to load an RDF/Turtle model from its String representation
136+
*
137+
* @param ttlRepresentation the RDF/Turtle representation of the model
138+
* @return the parsed model
139+
*/
140+
public static Model createModel( final String ttlRepresentation ) {
141+
return TurtleLoader.loadTurtle( ttlRepresentation ).get();
142+
}
143+
}

0 commit comments

Comments
 (0)