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] getUsedMetaModelVersions returns 0 for BAMM models #436

Closed shijinrajbosch closed 1 year ago

shijinrajbosch commented 1 year ago

Describe the bug No backward compatibility support available for BAMM model org.eclipse.esmf.aspectmodel.VersionNumber esmf-aspect-model-starter 2.3.1 & 2.3.2

BAMM VersionNumber method is available in old SDK - sds-aspect-model-starter 2.1.3.

Where Class : AspectMetaModelResourceResolver Method : public Set getUsedMetaModelVersions(Model model)

In sds-aspect-model-starter 2.1.3, io.openmanufacturing.sds.aspectmodel.resolver.services.SdsAspectMetaModelResourceResolver.getUsedMetaModelVersions - this is handling "bamm" models.

/**
 * Returns the set of meta model versions referenced in the model
 *
 * @param model an Aspect model
 * @return the set of meta model versions
 */
@Override
public Set<VersionNumber> getUsedMetaModelVersions( final Model model ) {
   final String bammUrnStart = String.format( "%s:%s",
         AspectModelUrn.VALID_PROTOCOL, AspectModelUrn.VALID_NAMESPACE_IDENTIFIER );
   return model.listObjects()
         .toList()
         .stream()
         .filter( RDFNode::isURIResource )
         .map( RDFNode::asResource )
         .map( Resource::getURI )
         .filter( uri -> uri.startsWith( bammUrnStart ) )
         .flatMap( uri -> AspectModelUrn.from( uri ).toJavaStream() )
         .filter( urn -> (urn.getElementType().equals( ElementType.META_MODEL ) || urn.getElementType().equals( ElementType.CHARACTERISTIC )) )
         .map( AspectModelUrn::getVersion )
         .map( VersionNumber::parse )
         .collect( Collectors.toSet() );
}

In esmf-aspect-model-starter 2.3.1 and 2.3.2 org.eclipse.esmf.aspectmodel.resolver.services.SammAspectMetaModelResourceResolver.getUsedMetaModelVersions method is only handling for "samm". Hence it is throwing MissingMetaModelVersionException from org.eclipse.esmf.aspectmodel.resolver.AspectMetaModelResourceResolver.getMetaModelVersion method.

/**
 * Returns the set of meta model versions referenced in the model
 *
 * @param model an Aspect model
 * @return the set of meta model versions
 */
@Override
public Set<VersionNumber> getUsedMetaModelVersions( final Model model ) {
   final String sammUrnStart = String.format( "%s:%s", AspectModelUrn.VALID_PROTOCOL, AspectModelUrn.VALID_NAMESPACE_IDENTIFIER );
   return model.listObjects()
         .toList()
         .stream()
         .filter( RDFNode::isURIResource )
         .map( RDFNode::asResource )
         .map( Resource::getURI )
         .filter( uri -> uri.startsWith( sammUrnStart ) )
         .flatMap( uri -> AspectModelUrn.from( uri ).toJavaStream() )
         .filter( urn -> (urn.getElementType().equals( ElementType.META_MODEL ) || urn.getElementType().equals( ElementType.CHARACTERISTIC )) )
         .map( AspectModelUrn::getVersion )
         .map( VersionNumber::parse )
         .collect( Collectors.toSet() );
}

Edit by @atextor: Replaced screenshots of code with formatted source code & added deep links to corresponding code sections.

atextor commented 1 year ago

Hi @shijinrajbosch, the getUsedMetaModelVersions() method is used inside the Aspect Model resolver to handle Aspect Models that (accidentally or intentionally) refer to multiple meta model versions at the same time, for example, by using SAMM 2.0.0 and SAMM 2.1.0. Calling this method from code using the esmf-sdk should not be necessary; please refer to Loading an Aspect Model to work on the RDF Level.

If you still would want to have the logic of this method changed, we'd need to clarify how it's supposed to work. The current approach for loading BAMM-based models is that the model as a whole is first translated to SAMM, then the regular resolution mechanism is used. This means that in the moment the number of used meta model versions is determined, there is no BAMM left any more in the model. Let's assume we change the method to count both BAMM and SAMM versions, and a model is loaded that refers to BAMM 2.0.0 and SAMM 2.0.0. This would return Set.of("2.0.0"), i.e., only one version. IMO there is no logical way this can be changed and have it return sane results, because we're counting versions of one (i.e. SAMM) meta model, not versions of multiple meta models (SAMM and BAMM). Can you explain the use case where you have the need for directly calling this method and can not instead use the regular Aspect Model resolution process, possibly by implementing a custom model resolution strategy?

shijinrajbosch commented 1 year ago

Many thanks @atextor . We have solved using updating the ESMF SDK to latest version and refactoring the semantic-hub code (with your help :) ).