eclipse-esmf / esmf-sdk

Load Aspect Models and their artifacts as Java code; share components to realize SAMM as code
https://eclipse-esmf.github.io/esmf-developer-guide/index.html
Mozilla Public License 2.0
25 stars 12 forks source link

[BUG] Generated JSON Schema differs between esmf-sdk 2.1.3 and 2.2.3 #439

Closed shijinrajbosch closed 1 year ago

shijinrajbosch commented 1 year ago

Describe the bug Describe the bug Test case works with sds-aspect-model-starter 2.1.3 & esmf-aspect-model-starter 2.2.3 and failing with - esmf-aspect-model-starter 2.3.1 & 2.3.2

Test class : org.eclipse.tractusx.semantics.hub.ModelsApiTest Test method : testGenerateJsonSchemaExpectSuccess()

Semantic-hub Github : https://github.com/bci-oss/sldt-semantic-hub.git (for esmf-aspect-model-starter 2.3.1) Branch - bug/SAMM_BAMM_support

Semantic-hub Github : https://github.com/bci-oss/sldt-semantic-hub.git (for esmf-aspect-model-starter 2.3.2) Branch - SAMM_BAMM_Support-ESMF_SDK_2.3.2

Where Test class : org.eclipse.tractusx.semantics.hub.ModelsApiTest Test method : testGenerateJsonSchemaExpectSuccess()

java.lang.AssertionError: components.schemas Expected: urn_samm_org.eclipse.esmf.samm_characteristic_2.0.0_Boolean but none found ; properties.moving.$ref Expected: #/components/schemas/urn_samm_org.eclipse.esmf.samm_characteristic_2.0.0_Boolean got: #/components/schemas/urn_samm_org.eclipse.esmf.samm_characteristic_2.1.0_Boolean

Additional context

String urnPrefix = "urn:samm:org.eclipse.tractusx.model.status.transition:2.0.0#";

Model model = find model from fuseki data base using the org.eclipse.esmf.aspectmodel.urn.AspectModelUrn . The model created in apache fuseki database is here

String modelDefinition = model.toString()


String urnPrefix = "urn:samm:org.eclipse.tractusx.model.status.transition:2.0.0#";

private static final String AUXILIARY_NAMESPACE = "urn:bamm:io.openmanufacturing:aspect-model:aux#";

private static org.apache.jena.query.ParameterizedSparqlString create( final String query ) {
      final org.apache.jena.query.ParameterizedSparqlString pss = new ParameterizedSparqlString();
      pss.setCommandText( query );
      pss.setNsPrefix( "aux", AUXILIARY_NAMESPACE );
      return pss;
   }

private static final String CONSTRUCT_BY_URN_QUERY =
         "CONSTRUCT {\n"
               + " ?s ?p ?o .\n"
               + "} WHERE {\n"
               + "    bind( ns: as ?aspect )\n"
               + "    ?aspect (<>|!<>)* ?s .\n"
               + "    ?otherAspect (<>|!<>)* ?s .\n"
               + "    ?s ?p ?o .\n"
               + "}";

public static org.apache.jena.query.Query buildFindByUrnConstructQuery( final AspectModelUrn urn ) {
      final org.apache.jena.query.ParameterizedSparqlString pss = create( CONSTRUCT_BY_URN_QUERY );
      pss.setNsPrefix( "ns", urn.getUrn().toString() );
      return pss.asQuery();
   }

private org.apache.jena.rdf.model.Model findJenaModelByUrn( final AspectModelUrn urn ) {
      final org.apache.jena.query.Query constructQuery = buildFindByUrnConstructQuery( urn );
      try ( final org.apache.jena.rdfconnection.RDFConnection rdfConnection = rdfConnectionRemoteBuilder.build() ) {
         return rdfConnection.queryConstruct( constructQuery );
      }
   }

public String getModelDefinition( final AspectModelUrn urn ) {
      Model jenaModelByUrn = findJenaModelByUrn( urn );
      if ( jenaModelByUrn == null ) {
         throw new AspectModelNotFoundException( urn );
      }
      StringWriter out = new StringWriter();
      jenaModelByUrn.write( out, "TURTLE" );
      return out.toString();
   }

Try<VersionedModel> loadSammModel( String ttl ) {
      InputStream targetStream = new ByteArrayInputStream( ttl.getBytes() );
      Try<Model> model = TurtleLoader.loadTurtle( targetStream );

      StaticResolutionStrategy resolutionStrategy = new StaticResolutionStrategy( model );
      org.eclipse.esmf.aspectmodel.resolver.AspectModelResolver resolver = new AspectModelResolver();
      Try<VersionedModel> versionedModel = resolver.resolveAspectModel( resolutionStrategy, resolutionStrategy.getAspectModelUrn() );

      if ( resolutionStrategy.getResolvementCounter() > 1 ) {
         return Try.failure( new ResolutionException( "The definition must be self contained!" ) );
      }
      return versionedModel;
   }

---------------------------------------------
import java.util.List;
import java.util.Optional;

import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.rdf.model.StmtIterator;
import org.apache.jena.vocabulary.RDF;
import org.eclipse.esmf.aspectmodel.resolver.AbstractResolutionStrategy;
import org.eclipse.esmf.aspectmodel.urn.AspectModelUrn;
import org.eclipse.esmf.aspectmodel.vocabulary.SAMM;
import org.eclipse.esmf.samm.KnownVersion;

import io.vavr.NotImplementedError;
import io.vavr.control.Try;

public class StaticResolutionStrategy extends AbstractResolutionStrategy {
   private int counter;
   private final Try<Model> model;

   public StaticResolutionStrategy( Try<Model> model ) {
      this.model = model;
   }

   @Override
   public Try<Model> apply( AspectModelUrn t ) {
      counter++;
      return this.model;
   }

   public int getResolvementCounter() {
      return counter;
   }

   public AspectModelUrn getAspectModelUrn() {
      final Optional<StmtIterator> stmtIterator = getStmtIterator();

      final String aspectModelUrn = stmtIterator.orElseThrow(
                  () -> new NotImplementedError( "AspectModelUrn cannot be found." ) )
            .next().getSubject().getURI();

      return AspectModelUrn.fromUrn( aspectModelUrn );
   }

   private Optional<StmtIterator> getStmtIterator() {
      for ( final KnownVersion version : KnownVersion.getVersions() ) {
         final SAMM samm = new SAMM( version );
         final List<Resource> resources = List.of( samm.Aspect(), samm.Property(), samm.Entity(), samm.Characteristic() );
         final Optional<StmtIterator> stmtIterator = resources.stream().filter(
                     resource -> model.get().listStatements( null, RDF.type, resource ).hasNext() ).findFirst()
               .map( resource -> model.get().listStatements( null, RDF.type, resource ) );
         if ( stmtIterator.isPresent() ) {
            return stmtIterator;
         }
      }
      return Optional.empty();
   }
}

--------------------------------------

String modelDefinition = getModelDefinition( org.eclipse.esmf.aspectmodel.urn.AspectModelUrn.fromUrn( urn ) );

Try<org.eclipse.esmf.aspectmodel.resolver.services.VersionedModel> versionedModel =
            loadSammModel( modelDefinition );

Try<List<org.eclipse.esmf.metamodel.Aspect>> aspect = org.eclipse.esmf.metamodel.loader.AspectModelLoader.getAspects( versionedModel.get() );   

org.eclipse.esmf.metamodel.Aspect aspect = aspect.get().get( 0 );

org.eclipse.esmf.aspectmodel.generator.jsonschema.AspectModelJsonSchemaGenerator jsonSchemaGenerator = new AspectModelJsonSchemaGenerator();

com.fasterxml.jackson.databind.JsonNode json = = jsonSchemaGenerator.apply( aspect, Locale.ENGLISH );

String result = json.toString();

Please find the actual.json and Expected.json for your reference.

actual.json expected.json

atextor commented 1 year ago

Hi @shijinrajbosch, the issue described here is almost completely identical to #438, with the sole exception that here the JSON Schema generation is called, while in the other issue the OpenAPI specification generation is called. However, the context and the source of problem, as well as the suggested way to address it, is identical. Please refer to my comment in the other issue.

I'm closing this issue since the JSON Schema generation works as intended.

shijinrajbosch commented 1 year ago

Many thanks @atextor for the clarifications, help and support.