-
Notifications
You must be signed in to change notification settings - Fork 12
SAMM-CLI aas generation: Mapping of Set Characteristics #597
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
188d9bb
6375ef3
9712a7e
cc439d6
94c90f2
0258448
6ca2eba
3d82d41
ab150df
017177f
bd55ea9
15b9e5b
b705d16
59be3cb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,8 @@ | |
package org.eclipse.esmf.aspectmodel.aas; | ||
|
||
import java.nio.charset.StandardCharsets; | ||
import java.security.MessageDigest; | ||
import java.security.NoSuchAlgorithmException; | ||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.HashSet; | ||
|
@@ -105,6 +107,7 @@ public class AspectModelAasVisitor implements AspectVisitor<Environment, Context | |
public static final String ADMIN_SHELL_NAME = "defaultAdminShell"; | ||
public static final String DEFAULT_LOCALE = "en"; | ||
public static final String CONCEPT_DESCRIPTION_CATEGORY = "APPLICATION_CLASS"; | ||
public static final String ALLOWS_ENUMERATION_VALUE_REGEX = "[^a-zA-Z0-9-_]"; | ||
public static final String CONCEPT_DESCRIPTION_DATA_SPECIFICATION_URL = | ||
"https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0"; | ||
|
||
|
@@ -207,7 +210,7 @@ public Environment visitAspect( final Aspect aspect, final Context context ) { | |
final Submodel submodel = usedContext.getSubmodel(); | ||
submodel.setIdShort( aspect.getName() ); | ||
submodel.setId( submodelId ); | ||
submodel.setSemanticId( buildReferenceToConceptDescription( aspect ) ); | ||
submodel.setSemanticId( buildAspectReferenceToGlobalReference( aspect ) ); | ||
submodel.setSupplementalSemanticIds( buildGlobalReferenceForSeeReferences( aspect ) ); | ||
submodel.setDescription( LangStringMapper.TEXT.map( aspect.getDescriptions() ) ); | ||
submodel.setKind( usedContext.getModelingKind() ); | ||
|
@@ -344,19 +347,25 @@ private OperationVariable mapOperationVariable( final Property property, final C | |
} | ||
|
||
private Reference buildReferenceToEnumValue( final Enumeration enumeration, final String value ) { | ||
final String updatedValue; | ||
try { | ||
updatedValue = !value.matches( ALLOWS_ENUMERATION_VALUE_REGEX ) ? transformEnumerationValue( value ) : value; | ||
} catch ( final NoSuchAlgorithmException e ) { | ||
throw new IllegalStateException( e ); | ||
} | ||
final Key key = new DefaultKey.Builder() | ||
.type( KeyTypes.DATA_ELEMENT ) | ||
.value( DEFAULT_MAPPER.determineIdentifierFor( enumeration ) + ":" + value ) | ||
.value( DEFAULT_MAPPER.determineIdentifierFor( enumeration ) + ":" + updatedValue ) | ||
.build(); | ||
return new DefaultReference.Builder().type( ReferenceTypes.MODEL_REFERENCE ).keys( key ).build(); | ||
} | ||
|
||
private Reference buildReferenceToConceptDescription( final Aspect aspect ) { | ||
private Reference buildAspectReferenceToGlobalReference( final Aspect aspect ) { | ||
final Key key = new DefaultKey.Builder() | ||
.type( KeyTypes.CONCEPT_DESCRIPTION ) | ||
.type( KeyTypes.GLOBAL_REFERENCE ) | ||
.value( DEFAULT_MAPPER.determineIdentifierFor( aspect ) ) | ||
.build(); | ||
return new DefaultReference.Builder().type( ReferenceTypes.MODEL_REFERENCE ).keys( key ).build(); | ||
return new DefaultReference.Builder().type( ReferenceTypes.EXTERNAL_REFERENCE ).keys( key ).build(); | ||
} | ||
|
||
private Reference buildReferenceForSeeElement( final String seeReference ) { | ||
|
@@ -555,8 +564,9 @@ private <T extends Collection> Environment visitCollectionProperty( final T coll | |
.displayName( LangStringMapper.NAME.map( property.getPreferredNames() ) ) | ||
.description( LangStringMapper.TEXT.map( property.getDescriptions() ) ) | ||
.value( List.of( decideOnMapping( property, context ) ) ) | ||
.typeValueListElement( AasSubmodelElements.SUBMODEL_ELEMENT ) | ||
.supplementalSemanticIds( buildGlobalReferenceForSeeReferences( collection ) ); | ||
.typeValueListElement( AasSubmodelElements.SUBMODEL_ELEMENT_COLLECTION ) | ||
.supplementalSemanticIds( buildGlobalReferenceForSeeReferences( collection ) ) | ||
.orderRelevant( false ); | ||
|
||
if ( !collection.isAnonymous() ) { | ||
submodelBuilder.semanticId( buildReferenceForCollection( collection.urn().getUrn().toString() ) ); | ||
|
@@ -574,14 +584,15 @@ private <T extends Collection> Environment visitCollectionProperty( final T coll | |
context.getRawPropertyValue() | ||
.filter( ArrayNode.class::isInstance ) | ||
.map( ArrayNode.class::cast ) | ||
.map( arrayNode -> ( Property property ) -> { | ||
.map( arrayNode -> ( final Property property ) -> { | ||
final List<SubmodelElement> values = getValues( collection, property, context, arrayNode ); | ||
return new DefaultSubmodelElementList.Builder() | ||
.idShort( property.getName() ) | ||
.displayName( LangStringMapper.NAME.map( property.getPreferredNames() ) ) | ||
.description( LangStringMapper.TEXT.map( property.getDescriptions() ) ) | ||
.value( values ) | ||
.typeValueListElement( AasSubmodelElements.SUBMODEL_ELEMENT ) | ||
.typeValueListElement( AasSubmodelElements.SUBMODEL_ELEMENT_COLLECTION ) | ||
Yauhenikapl marked this conversation as resolved.
Show resolved
Hide resolved
|
||
.orderRelevant( false ) | ||
.build(); | ||
} ) ) | ||
.orElse( defaultBuilder ); | ||
|
@@ -734,6 +745,32 @@ public Environment visitEnumeration( final Enumeration enumeration, final Contex | |
return context.environment; | ||
} | ||
|
||
/** | ||
* Transforms a given enumValue string to a specific format. | ||
* The transformation is done by removing spaces and special characters | ||
* from the input string, then appending the first 8 characters of the | ||
* sha256 hash of the cleaned string to the provided prefix. | ||
* | ||
* @param enumValue the input string to be transformed | ||
* @return the transformed string in the format "_role[8_characters_of_hash]" | ||
* @throws NoSuchAlgorithmException if the SHA-256 algorithm is not available | ||
*/ | ||
private String transformEnumerationValue( final String enumValue ) throws NoSuchAlgorithmException { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How would the mapping work in the opposite direction with this approach? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think, that I have to add separate method in the opposite direction. Thanks! |
||
final String cleanedEnumValue = enumValue.replaceAll( ALLOWS_ENUMERATION_VALUE_REGEX, "" ); | ||
|
||
final MessageDigest digest = MessageDigest.getInstance( "SHA-256" ); | ||
final byte[] hashBytes = digest.digest( cleanedEnumValue.getBytes( StandardCharsets.UTF_8 ) ); | ||
|
||
final StringBuilder hexString = new StringBuilder(); | ||
for ( final byte b : hashBytes ) { | ||
hexString.append( String.format( "%02x", b ) ); | ||
} | ||
|
||
final String hashPrefix = hexString.substring( 0, 8 ); | ||
|
||
return "_" + cleanedEnumValue + hashPrefix; | ||
} | ||
|
||
@Override | ||
public Environment visitState( final State state, final Context context ) { | ||
// Same handling as with enumerations | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,13 +23,17 @@ | |
public class DefaultPropertyMapper implements PropertyMapper<Property> { | ||
@Override | ||
public Property mapToAasProperty( final Type type, final org.eclipse.esmf.metamodel.Property property, final Context context ) { | ||
return new DefaultProperty.Builder() | ||
.idShort( context.getPropertyShortId() ) | ||
.valueType( AasDataTypeMapper.mapAspectTypeToAasXsdDataType( mapType( type ) ) ) | ||
.displayName( LangStringMapper.NAME.map( property.getPreferredNames() ) ) | ||
.value( context.getPropertyValue( UNKNOWN_EXAMPLE ) ) | ||
.semanticId( buildReferenceToGlobalReference( property ) ) | ||
.build(); | ||
final DefaultProperty defaultProperty = new DefaultProperty(); | ||
defaultProperty.setIdShort( context.getPropertyShortId() ); | ||
defaultProperty.setValueType( AasDataTypeMapper.mapAspectTypeToAasXsdDataType( mapType( type ) ) ); | ||
defaultProperty.setDisplayName( LangStringMapper.NAME.map( property.getPreferredNames() ) ); | ||
defaultProperty.setSemanticId( buildPropertyReferenceToGlobalReference( property ) ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why propertyReference? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you please explain more, because in this method "buildPropertyReferenceToGlobalReference" we building GlobalReference, not property reference? |
||
|
||
if ( !context.getPropertyValue( UNKNOWN_EXAMPLE ).equals( UNKNOWN_EXAMPLE ) ) { | ||
defaultProperty.setValue( context.getPropertyValue( UNKNOWN_EXAMPLE ) ); | ||
} | ||
|
||
return defaultProperty; | ||
} | ||
|
||
private String mapType( final Type type ) { | ||
|
Uh oh!
There was an error while loading. Please reload this page.