Skip to content

Commit

Permalink
Merge pull request #643 from bci-oss/625-move-element
Browse files Browse the repository at this point in the history
Add Aspect Model change/refactoring operations
  • Loading branch information
atextor authored Aug 14, 2024
2 parents 252bc6c + a6f60c2 commit 71587cd
Show file tree
Hide file tree
Showing 94 changed files with 4,198 additions and 558 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import org.eclipse.esmf.metamodel.ModelElement;
import org.eclipse.esmf.metamodel.ModelElementGroup;
import org.eclipse.esmf.metamodel.Namespace;

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

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

Optional<URI> sourceLocation();

default Namespace namespace() {
throw new UnsupportedOperationException( "Uninitialized Aspect Model" );
}

@Override
default List<ModelElement> elements() {
throw new UnsupportedOperationException( "Uninitialized Aspect Model" );
}

// boolean isAutoMigrated();
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ public String getNamespace() {
return getUri() + "#";
}

@SuppressWarnings( "checkstyle:MethodName" )
public Resource Namespace() {
return resource( "Namespace" );
}

public Property listType() {
return property( "listType" );
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2024 Robert Bosch Manufacturing Solutions GmbH
*
* See the AUTHORS file(s) distributed with this work for additional
* information regarding authorship.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* SPDX-License-Identifier: MPL-2.0
*/

package org.eclipse.esmf.metamodel.vocabulary;

public class SimpleRdfNamespace implements RdfNamespace {
private final String shortForm;
private final String uri;

public SimpleRdfNamespace( final String shortForm, final String uri ) {
this.shortForm = shortForm;
this.uri = uri;
}

@Override
public String getShortForm() {
return shortForm;
}

@Override
public String getUri() {
return uri;
}
}
10 changes: 10 additions & 0 deletions core/esmf-aspect-meta-model-java/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>io.soabase.record-builder</groupId>
<artifactId>record-builder-processor</artifactId>
<scope>provided</scope>
</dependency>

<!-- Test dependencies -->
<dependency>
Expand Down Expand Up @@ -153,6 +158,11 @@
<artifactId>lombok</artifactId>
<version>${lombok-version}</version>
</path>
<path>
<groupId>io.soabase.record-builder</groupId>
<artifactId>record-builder-processor</artifactId>
<version>${record-builder-version}</version>
</path>
</annotationProcessorPaths>
</configuration>
<executions>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
* Copyright (c) 2024 Robert Bosch Manufacturing Solutions GmbH
*
* See the AUTHORS file(s) distributed with this work for additional
* information regarding authorship.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* SPDX-License-Identifier: MPL-2.0
*/

package org.eclipse.esmf.aspectmodel;

import static java.util.stream.Collectors.toSet;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Stream;

import org.eclipse.esmf.aspectmodel.resolver.services.TurtleLoader;
import org.eclipse.esmf.aspectmodel.urn.AspectModelUrn;
import org.eclipse.esmf.aspectmodel.urn.ElementType;
import org.eclipse.esmf.metamodel.vocabulary.SammNs;

import com.google.common.collect.Streams;
import org.apache.jena.rdf.model.Literal;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.Property;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.rdf.model.Statement;
import org.apache.jena.vocabulary.RDF;
import org.apache.jena.vocabulary.XSD;

public class RdfUtil {
public static Model getModelElementDefinition( final Resource element ) {
final Model result = ModelFactory.createDefaultModel();
element.getModel().listStatements( element, null, (RDFNode) null ).toList().forEach( statement -> {
final Resource subject = statement.getSubject();
final Resource newSubject = subject.isAnon()
? result.createResource( subject.getId() )
: result.createResource( subject.getURI() );
final Property newPredicate = result.createProperty( statement.getPredicate().getURI() );
final RDFNode newObject;
if ( statement.getObject().isURIResource() ) {
newObject = result.createResource( statement.getObject().asResource().getURI() );
} else if ( statement.getObject().isLiteral() ) {
newObject = statement.getObject();
} else if ( statement.getObject().isAnon() ) {
newObject = result.createResource( statement.getObject().asResource().getId() );
result.add( getModelElementDefinition( statement.getObject().asResource() ) );
} else {
newObject = statement.getObject();
}
result.add( newSubject, newPredicate, newObject );
} );
return result;
}

public static Set<AspectModelUrn> getAllUrnsInModel( final Model model ) {
return Streams.stream( model.listStatements().mapWith( statement -> {
final Stream<String> subjectUri = statement.getSubject().isURIResource()
? Stream.of( statement.getSubject().getURI() )
: Stream.empty();
final Stream<String> propertyUri = Stream.of( statement.getPredicate().getURI() );
final Stream<String> objectUri = statement.getObject().isURIResource()
? Stream.of( statement.getObject().asResource().getURI() )
: Stream.empty();

return Stream.of( subjectUri, propertyUri, objectUri )
.flatMap( Function.identity() )
.flatMap( urn -> AspectModelUrn.from( urn ).toJavaOptional().stream() );
} ) ).flatMap( Function.identity() ).collect( toSet() );
}

public static void cleanPrefixes( final Model model ) {
final Map<String, String> originalPrefixMap = new HashMap<>( model.getNsPrefixMap() );
model.clearNsPrefixMap();
// SAMM prefixes
getAllUrnsInModel( model ).forEach( urn -> {
switch ( urn.getElementType() ) {
case META_MODEL -> model.setNsPrefix( SammNs.SAMM.getShortForm(), SammNs.SAMM.getNamespace() );
case CHARACTERISTIC -> model.setNsPrefix( SammNs.SAMMC.getShortForm(), SammNs.SAMMC.getNamespace() );
case ENTITY -> model.setNsPrefix( SammNs.SAMME.getShortForm(), SammNs.SAMME.getNamespace() );
case UNIT -> model.setNsPrefix( SammNs.UNIT.getShortForm(), SammNs.UNIT.getNamespace() );
default -> {
// nothing to do
}
}
} );
// XSD
Stream.concat(
Streams.stream( model.listObjects() )
.filter( RDFNode::isLiteral )
.map( RDFNode::asLiteral )
.map( Literal::getDatatypeURI )
.filter( type -> type.startsWith( XSD.NS ) )
.filter( type -> !type.equals( XSD.xstring.getURI() ) ),
Streams.stream( model.listObjects() )
.filter( RDFNode::isURIResource )
.map( RDFNode::asResource )
.map( Resource::getURI )
.filter( type -> type.startsWith( XSD.NS ) ) )
.findAny()
.ifPresent( resource -> model.setNsPrefix( "xsd", XSD.NS ) );
// Empty (namespace) prefix
Streams.stream( model.listStatements( null, RDF.type, (RDFNode) null ) )
.map( Statement::getSubject )
.filter( Resource::isURIResource )
.map( Resource::getURI )
.map( AspectModelUrn::fromUrn )
.findAny()
.ifPresent( urn -> model.setNsPrefix( "", urn.getUrnPrefix() ) );
// Add back custom prefixes not already covered:
// - if the prefix or URI is not set already
// - it's not XSD (no need to add it here if it's not added above)
// - if it's a SAMM URN, it's a regular namespace (not a meta model namespace)
originalPrefixMap.forEach( ( prefix, uri ) -> {
if ( !model.getNsPrefixMap().containsKey( prefix )
&& !model.getNsPrefixMap().containsValue( uri )
&& !uri.equals( XSD.NS )
&& ( !uri.startsWith( "urn:samm:" ) || AspectModelUrn.fromUrn( uri + "x" ).getElementType() == ElementType.NONE )
) {
model.setNsPrefix( prefix, uri );
}
} );
}

/**
* Convenience method to load an RDF/Turtle model from its String representation
*
* @param ttlRepresentation the RDF/Turtle representation of the model
* @return the parsed model
*/
public static Model createModel( final String ttlRepresentation ) {
return TurtleLoader.loadTurtle( ttlRepresentation ).get();
}
}
Loading

0 comments on commit 71587cd

Please sign in to comment.