Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
import org.eclipse.digitaltwin.aas4j.v3.model.AssetAdministrationShell;
import org.eclipse.digitaltwin.aas4j.v3.model.ConceptDescription;
import org.eclipse.digitaltwin.aas4j.v3.model.DataSpecificationIec61360;
import org.eclipse.digitaltwin.aas4j.v3.model.DataTypeDefXsd;
import org.eclipse.digitaltwin.aas4j.v3.model.DataTypeIec61360;
import org.eclipse.digitaltwin.aas4j.v3.model.EmbeddedDataSpecification;
import org.eclipse.digitaltwin.aas4j.v3.model.Environment;
Expand All @@ -72,6 +73,7 @@
import org.eclipse.digitaltwin.aas4j.v3.model.ModellingKind;
import org.eclipse.digitaltwin.aas4j.v3.model.Operation;
import org.eclipse.digitaltwin.aas4j.v3.model.OperationVariable;
import org.eclipse.digitaltwin.aas4j.v3.model.Qualifier;
import org.eclipse.digitaltwin.aas4j.v3.model.Reference;
import org.eclipse.digitaltwin.aas4j.v3.model.ReferenceTypes;
import org.eclipse.digitaltwin.aas4j.v3.model.Submodel;
Expand All @@ -92,6 +94,7 @@
import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultOperation;
import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultOperationVariable;
import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultProperty;
import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultQualifier;
import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultReference;
import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultSubmodel;
import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultSubmodelElementCollection;
Expand All @@ -111,6 +114,9 @@ public class AspectModelAasVisitor implements AspectVisitor<Environment, Context
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";
public static final String SMT_CARDINALITY_SEMANTIC_ID_URL = "https://admin-shell.io/SubmodelTemplates/Cardinality/1/0";
public static final String SMT_CARDINALITY_QUALIFIER_TYPE = "SMT/Cardinality";
public static final String SMT_CARDINALITY_ZERO_TO_ONE = "ZeroToOne";

private static final Pattern IRDI_BARE_PATTERN = Pattern.compile(
"^\\d{4}-\\d+(?:%23\\d{2}|#\\d{2})-[A-Za-z0-9-]+(?:%23\\d{3}|#\\d{3})$"
Expand Down Expand Up @@ -335,6 +341,12 @@ private Optional<SubmodelElement> mapText( final Property property, final Contex
final SubmodelElement element = context.getPropertyResult();
element.setSupplementalSemanticIds( updateGlobalReferenceWithSeeReferences( element, property ) );

if ( property.isOptional() ) {
final List<Qualifier> qualifiers = new ArrayList<>( element.getQualifiers() );
qualifiers.add( buildZeroToOneCardinalityQualifier() );
element.setQualifiers( qualifiers );
}

if ( !property.getPayloadName().isEmpty()
&& !( element instanceof SubmodelElementList )
&& !( element instanceof SubmodelElementCollection ) ) {
Expand Down Expand Up @@ -458,6 +470,23 @@ private Reference buildReferenceForCollection( final String submodelId ) {
.build();
}

private Qualifier buildZeroToOneCardinalityQualifier() {
final Key key = new DefaultKey.Builder()
.type( KeyTypes.GLOBAL_REFERENCE )
.value( SMT_CARDINALITY_SEMANTIC_ID_URL )
.build();
final Reference semanticId = new DefaultReference.Builder()
.type( ReferenceTypes.EXTERNAL_REFERENCE )
.keys( key )
.build();
return new DefaultQualifier.Builder()
.type( SMT_CARDINALITY_QUALIFIER_TYPE )
.valueType( DataTypeDefXsd.STRING )
.value( SMT_CARDINALITY_ZERO_TO_ONE )
.semanticId( semanticId )
.build();
}

private void createConceptDescription( final Property property, final Context context ) {
if ( property.getCharacteristic().isEmpty() ) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,24 @@ void testGenerateAasxFromBammWithConstraint() throws DeserializationException {
checkDataSpecificationIec61360( semanticIds, env );
}

@Test
void testOptionalPropertyHasZeroToOneCardinalityQualifier() throws DeserializationException {
final Environment env = getAssetAdministrationShellFromAspect( TestAspect.ASPECT_WITH_OPTIONAL_PROPERTY );
final SubmodelElement element = env.getSubmodels().get( 0 ).getSubmodelElements().get( 0 );
assertThat( element.getQualifiers() )
.hasSize( 1 )
.first()
.satisfies( qualifier -> {
assertThat( qualifier.getType() ).isEqualTo( AspectModelAasVisitor.SMT_CARDINALITY_QUALIFIER_TYPE );
assertThat( qualifier.getValue() ).isEqualTo( AspectModelAasVisitor.SMT_CARDINALITY_ZERO_TO_ONE );
assertThat( qualifier.getValueType() ).isEqualTo( DataTypeDefXsd.STRING );
assertThat( qualifier.getSemanticId().getKeys() )
.singleElement()
.satisfies( key -> assertThat( key.getValue() )
.isEqualTo( AspectModelAasVisitor.SMT_CARDINALITY_SEMANTIC_ID_URL ) );
} );
}

@Test
void testGenerateAasxFromAspectModelWithRecursivePropertyWithOptional() throws DeserializationException {
final Environment env = getAssetAdministrationShellFromAspect( TestAspect.ASPECT_WITH_RECURSIVE_PROPERTY_WITH_OPTIONAL );
Expand Down
Loading