diff --git a/.gitignore b/.gitignore index 8079db5e..90edc16a 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,5 @@ local.properties **.flattened-pom.xml nbactions.xml testJsonSerialization.json +dataformat-uanodeset/jsonExpected.json +dataformat-uanodeset/jsonActual.json diff --git a/dataformat-core/src/main/java/io/adminshell/aas/v3/dataformat/core/util/AasUtils.java b/dataformat-core/src/main/java/io/adminshell/aas/v3/dataformat/core/util/AasUtils.java index 4c0a83cd..700e3b48 100644 --- a/dataformat-core/src/main/java/io/adminshell/aas/v3/dataformat/core/util/AasUtils.java +++ b/dataformat-core/src/main/java/io/adminshell/aas/v3/dataformat/core/util/AasUtils.java @@ -513,6 +513,11 @@ public static T resolve(Reference reference, AssetAdminist int i = reference.getKeys().size() - 1; if (type != null) { Class actualType = keyTypeToClass(reference.getKeys().get(i).getType()); + if (actualType == null) { + log.warn("reference {} could not be resolved as key type has no known class.", + asString(reference)); + return null; + } if (!type.isAssignableFrom(actualType)) { log.warn("reference {} could not be resolved as target type is not assignable from actual type (target: {}, actual: {})", asString(reference), type.getName(), actualType.getName()); diff --git a/dataformat-uanodeset/nodeset/i4aas/Opc.Ua.I4AAS_V3Draft.NodeSet2.csv b/dataformat-uanodeset/nodeset/i4aas/Opc.Ua.I4AAS_V3Draft.NodeSet2.csv index 14685166..1826160c 100644 --- a/dataformat-uanodeset/nodeset/i4aas/Opc.Ua.I4AAS_V3Draft.NodeSet2.csv +++ b/dataformat-uanodeset/nodeset/i4aas/Opc.Ua.I4AAS_V3Draft.NodeSet2.csv @@ -91,6 +91,7 @@ AASIdentifiableType_Identification,5037,Object AASKeyDataType_Encoding_DefaultBinary,5038,Object AASKeyDataType_Encoding_DefaultXml,5039,Object AASKeyDataType_Encoding_DefaultJson,5040,Object +AASOperationType_InputVariable,5041,Object AASOrderedSubmodelElementCollectionType_SubmodelElement,5042,Object AASCustomConceptDescriptionType_DataSpecification,5043,Object AASIrdiConceptDescriptionType_IsCaseOf,5044,Object @@ -100,6 +101,8 @@ AASEnvironmentType_AAS_AssetInformation_BillOfMaterial,5047,Object AASCustomConceptDescriptionType_IsCaseOf,5048,Object AASAssetInformationType_SpecificAssetId,5049,Object AASAssetAdministrationShellType_AssetInformation_SpecificAssetId,5050,Object +AASOperationType_OutputVariable,5051,Object +AASOperationType_InOutputVariable,5052,Object AASEnvironmentType_AAS_Identification,5101,Object AASEnvironmentType_Asset,5103,Object AASEnvironmentType_Asset_Administration,5150,Object diff --git a/dataformat-uanodeset/nodeset/i4aas/Opc.Ua.I4AAS_V3Draft.NodeSet2.xml b/dataformat-uanodeset/nodeset/i4aas/Opc.Ua.I4AAS_V3Draft.NodeSet2.xml index a83e14f1..a3586032 100644 --- a/dataformat-uanodeset/nodeset/i4aas/Opc.Ua.I4AAS_V3Draft.NodeSet2.xml +++ b/dataformat-uanodeset/nodeset/i4aas/Opc.Ua.I4AAS_V3Draft.NodeSet2.xml @@ -46,7 +46,7 @@ - + @@ -1750,7 +1750,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1036 ns=1;i=1031 - i=78 + i=80 @@ -1770,7 +1770,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c Category ns=1;i=5362 - i=78 + i=80 i=68 @@ -1779,7 +1779,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1036 ns=1;i=5362 - i=78 + i=80 @@ -1808,7 +1808,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c Qualifier ns=1;i=1037 - i=78 + i=80 ns=1;i=5362 @@ -1833,8 +1833,8 @@ Note: In an object oriented view, an instance denotes an object of a template (c SpecificAssetId ns=1;i=1039 - i=78 ns=1;i=1031 + i=80 @@ -2193,8 +2193,8 @@ Note: In an object oriented view, an instance denotes an object of a template (c Category ns=1;i=1003 - i=78 i=68 + i=80 @@ -2202,6 +2202,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1003 ns=1;i=5036 + ns=1;i=1034 ns=1;i=5037 @@ -2210,7 +2211,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1030 ns=1;i=1007 - i=78 + i=80 @@ -2280,15 +2281,15 @@ Note: In an object oriented view, an instance denotes an object of a template (c BillOfMaterial ns=1;i=1036 - i=78 ns=1;i=5156 + i=80 SpecificAssetId ns=1;i=1039 - i=78 + i=80 ns=1;i=5156 @@ -2297,7 +2298,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1036 ns=1;i=1002 - i=78 + i=80 @@ -2321,8 +2322,8 @@ Note: In an object oriented view, an instance denotes an object of a template (c Submodel ns=1;i=1036 - i=78 ns=1;i=1002 + i=80 @@ -2339,7 +2340,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1036 ns=1;i=1005 - i=78 + i=80 @@ -2370,7 +2371,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c Category ns=1;i=5010 - i=78 + i=80 i=68 @@ -2379,7 +2380,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1036 ns=1;i=5010 - i=78 + i=80 @@ -2397,7 +2398,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c Qualifier ns=1;i=1037 - i=78 + i=80 ns=1;i=5010 @@ -2406,7 +2407,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1036 ns=1;i=1006 - i=78 + i=80 @@ -2424,8 +2425,8 @@ Note: In an object oriented view, an instance denotes an object of a template (c Qualifier ns=1;i=1037 - i=78 ns=1;i=1006 + i=80 @@ -2433,27 +2434,18 @@ Note: In an object oriented view, an instance denotes an object of a template (c https://reference.opcfoundation.org/v104/I4AAS/v100/docs/6.8.1 ns=1;i=1003 - ns=1;i=6126 ns=1;i=5011 ns=1;i=1033 ns=1;i=6013 ns=1;i=5031 - - Category - - ns=1;i=1009 - i=78 - i=68 - - DataSpecification ns=1;i=1036 ns=1;i=1009 - i=78 + i=80 @@ -2471,8 +2463,8 @@ Note: In an object oriented view, an instance denotes an object of a template (c Qualifier ns=1;i=1037 - i=78 ns=1;i=1009 + i=80 @@ -2594,8 +2586,8 @@ Note: In an object oriented view, an instance denotes an object of a template (c Statement ns=1;i=1038 - i=78 ns=1;i=1022 + i=80 @@ -3074,9 +3066,28 @@ Note: In an object oriented view, an instance denotes an object of a template (c https://reference.opcfoundation.org/v104/I4AAS/v100/docs/6.8.7 ns=1;i=1009 + ns=1;i=5052 + ns=1;i=5041 ns=1;i=7001 + ns=1;i=5051 + + InOutputVariable + + ns=1;i=1038 + i=80 + ns=1;i=1015 + + + + InputVariable + + ns=1;i=1038 + i=80 + ns=1;i=1015 + + Operation @@ -3084,6 +3095,14 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1015 + + OutputVariable + + ns=1;i=1038 + i=80 + ns=1;i=1015 + + AASPropertyType https://reference.opcfoundation.org/v104/I4AAS/v100/docs/6.8.5 @@ -3248,7 +3267,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1038 ns=1;i=1019 - i=78 + i=80 @@ -3276,7 +3295,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c Category ns=1;i=5012 - i=78 + i=80 i=68 @@ -3285,7 +3304,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1036 ns=1;i=5012 - i=78 + i=80 @@ -3303,7 +3322,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c Qualifier ns=1;i=1037 - i=78 + i=80 ns=1;i=5012 @@ -3342,7 +3361,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c Category ns=1;i=5042 - i=78 + i=80 i=68 @@ -3351,7 +3370,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1036 ns=1;i=5042 - i=78 + i=80 @@ -3369,7 +3388,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c Qualifier ns=1;i=1037 - i=78 + i=80 ns=1;i=5042 @@ -3403,8 +3422,8 @@ Note: In an object oriented view, an instance denotes an object of a template (c Category ns=1;i=1033 - i=78 i=68 + i=80 @@ -3424,6 +3443,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1027 ns=1;i=1033 ns=1;i=5034 + ns=1;i=1007 @@ -3431,7 +3451,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1030 ns=1;i=1034 - i=78 + i=80 @@ -3484,15 +3504,15 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1030 ns=1;i=1026 - i=78 + i=80 Category ns=1;i=1026 - i=78 i=68 + i=80 @@ -3500,7 +3520,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1036 ns=1;i=1026 - i=78 + i=80 @@ -3540,7 +3560,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1036 ns=1;i=1026 - i=78 + i=80 @@ -3561,15 +3581,15 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1030 ns=1;i=1024 - i=78 + i=80 Category ns=1;i=1024 - i=78 i=68 + i=80 @@ -3577,7 +3597,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1036 ns=1;i=1024 - i=78 + i=80 @@ -3617,7 +3637,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1036 ns=1;i=1024 - i=78 + i=80 @@ -3638,15 +3658,15 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1030 ns=1;i=1025 - i=78 + i=80 Category ns=1;i=1025 - i=78 i=68 + i=80 @@ -3654,7 +3674,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1036 ns=1;i=1025 - i=78 + i=80 @@ -3694,7 +3714,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1036 ns=1;i=1025 - i=78 + i=80 @@ -3725,7 +3745,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1030 ns=1;i=5002 - i=78 + i=80 @@ -3751,15 +3771,15 @@ Note: In an object oriented view, an instance denotes an object of a template (c BillOfMaterial ns=1;i=1036 - i=78 ns=1;i=5610 + i=80 SpecificAssetId ns=1;i=1039 - i=78 + i=80 ns=1;i=5610 @@ -3767,7 +3787,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c Category ns=1;i=5002 - i=78 + i=80 i=68 @@ -3776,7 +3796,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1036 ns=1;i=5002 - i=78 + i=80 @@ -3815,7 +3835,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c Submodel ns=1;i=1036 - i=78 + i=80 ns=1;i=5002 @@ -3836,14 +3856,14 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1030 ns=1;i=5103 - i=78 + i=80 Category ns=1;i=5103 - i=78 + i=80 i=68 @@ -3852,7 +3872,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1036 ns=1;i=5103 - i=78 + i=80 @@ -3906,14 +3926,14 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1030 ns=1;i=5152 - i=78 + i=80 Category ns=1;i=5152 - i=78 + i=80 i=68 @@ -3922,7 +3942,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1036 ns=1;i=5152 - i=78 + i=80 @@ -3972,7 +3992,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c Qualifier ns=1;i=1037 - i=78 + i=80 ns=1;i=5152 @@ -4113,7 +4133,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c Category ns=1;i=5615 - i=78 + i=80 i=68 @@ -4122,7 +4142,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c ns=1;i=1036 ns=1;i=5615 - i=78 + i=80 @@ -4140,7 +4160,7 @@ Note: In an object oriented view, an instance denotes an object of a template (c Qualifier ns=1;i=1037 - i=78 + i=80 ns=1;i=5615 diff --git a/dataformat-uanodeset/pom.xml b/dataformat-uanodeset/pom.xml index d42991cb..0b8f0249 100644 --- a/dataformat-uanodeset/pom.xml +++ b/dataformat-uanodeset/pom.xml @@ -24,6 +24,24 @@ tests test + + io.admin-shell.aas + dataformat-json + ${revision} + test + + + io.admin-shell.aas + validator + ${revision} + test + + + org.skyscreamer + jsonassert + ${jsonassert.version} + test + javax.xml.bind jaxb-api diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/AssetAdministrationShellMapper.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/AssetAdministrationShellMapper.java index 1f131195..2b2e2c0a 100644 --- a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/AssetAdministrationShellMapper.java +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/AssetAdministrationShellMapper.java @@ -23,7 +23,8 @@ import io.adminshell.aas.v3.model.AssetAdministrationShell; import io.adminshell.aas.v3.model.AssetInformation; -public class AssetAdministrationShellMapper extends IdentifiableMapper implements HasDataSpecificationMapper { +public class AssetAdministrationShellMapper extends IdentifiableMapper + implements HasDataSpecificationMapper { public AssetAdministrationShellMapper(AssetAdministrationShell src, MappingContext ctx) { super(src, ctx); @@ -47,14 +48,15 @@ protected void mapAndAttachChildren() { private void mapAsset() { AssetInformation assetInformation = source.getAssetInformation(); - if (assetInformation != null) { + if (assetInformation != null) { UAObject uaAsset = new AssetInformationMapper(assetInformation, ctx).map(); attachAsComponent(target, uaAsset); } } private void mapSubmodels() { - UAObject smFolder = createReferenceList(AAS_SUBMODELREFERENCES_LIST_BROWSENAME); + UAObject smFolder = source.getSubmodels().isEmpty() ? null + : createReferenceList(AAS_SUBMODELREFERENCES_LIST_BROWSENAME); List submodels = source.getSubmodels(); for (int i = 0; i < submodels.size(); i++) { io.adminshell.aas.v3.model.Reference reference = submodels.get(i); diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/AssetInformationMapper.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/AssetInformationMapper.java index 610030db..6013e91e 100644 --- a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/AssetInformationMapper.java +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/AssetInformationMapper.java @@ -55,8 +55,8 @@ protected void mapAndAttachChildren() { attachAsComponent(target, uaIdentification); } - UAObject uaBomList = createReferenceList(ASSETINFO_BILL_OF_MATERIAL_BROWSENAME); List billOfMaterials = source.getBillOfMaterials(); + UAObject uaBomList = billOfMaterials.isEmpty() ? null : createReferenceList(ASSETINFO_BILL_OF_MATERIAL_BROWSENAME); for (int i = 0; i < billOfMaterials.size(); i++) { Reference reference = billOfMaterials.get(i); UAObject uaBomListEntry = new ReferenceMapper(reference, ctx, ASSETINFO_BILL_OF_MATERIAL_BROWSENAME + "_" + i).map(); @@ -70,7 +70,7 @@ protected void mapAndAttachChildren() { attachAsComponent(target, uaThumbnail); } - UAObject folder = createIdentifierKeyValuePairList(ASSETINFO_SPECIFIC_ASSET_ID_BROWSENAME); + UAObject folder = source.getSpecificAssetIds().isEmpty() ? null : createIdentifierKeyValuePairList(ASSETINFO_SPECIFIC_ASSET_ID_BROWSENAME); for (IdentifierKeyValuePair identifierKeyValuePair : source.getSpecificAssetIds()) { UAObject uaIdKVP = new IdentifierKeyValuePairMapper(identifierKeyValuePair, ctx).map(); attachAsComponent(folder, uaIdKVP); diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/ConceptDescriptionMapper.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/ConceptDescriptionMapper.java index 6411d5c5..ed2b2e84 100644 --- a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/ConceptDescriptionMapper.java +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/ConceptDescriptionMapper.java @@ -23,7 +23,8 @@ import io.adminshell.aas.v3.model.IdentifierType; import io.adminshell.aas.v3.model.Reference; -public class ConceptDescriptionMapper extends IdentifiableMapper implements HasDataSpecificationMapper { +public class ConceptDescriptionMapper extends IdentifiableMapper + implements HasDataSpecificationMapper { public ConceptDescriptionMapper(ConceptDescription src, MappingContext ctx) { super(src, ctx); @@ -43,12 +44,12 @@ protected UAObject createTargetObject() { } else if (IdentifierType.CUSTOM == idType) { addTypeReference(I4AASIdentifier.AASCustomConceptDescriptionType); } - if (identification.getIdentifier() != null) { - //conflict: I4AAS says idshort, OPC UA says value - target.setBrowseName(createModelBrowseName(identification.getIdentifier())); - } +// if (identification.getIdentifier() != null) { +// // TODO: I4AAS says idshort, OPC UA says value. Currently there is no mapping target for IdShort of ConceptDescription +// target.setBrowseName(createModelBrowseName(identification.getIdentifier())); +// } } - + return target; } @@ -58,12 +59,11 @@ protected void mapAndAttachChildren() { mapDataSpecification(source, target, ctx); - UAObject createFolder = createReferenceList("IsCaseOf"); + UAObject createFolder = source.getIsCaseOfs().isEmpty() ? null : createReferenceList("IsCaseOf"); for (Reference reference : source.getIsCaseOfs()) { UAObject uaRef = new ReferenceMapper(reference, ctx, reference.getKeys().get(0).getValue()).map(); attachAsComponent(createFolder, uaRef); } } - } diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/HasDataSpecificationMapper.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/HasDataSpecificationMapper.java index 368b7506..49b79433 100644 --- a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/HasDataSpecificationMapper.java +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/HasDataSpecificationMapper.java @@ -31,8 +31,9 @@ public interface HasDataSpecificationMapper { public default void mapDataSpecification(HasDataSpecification source, UAObject target, MappingContext ctx) { - UAObject folder = I4AASMapper.createFolder(target, I4AASConstants.DATASPECIFICATION_BROWSENAME, ctx, - I4AASIdentifier.AASReferenceList); + UAObject folder = source.getEmbeddedDataSpecifications().isEmpty() ? null + : I4AASMapper.createFolder(target, I4AASConstants.DATASPECIFICATION_BROWSENAME, ctx, + I4AASIdentifier.AASReferenceList); List embeddedDataSpecifications = source.getEmbeddedDataSpecifications(); for (int i = 0; i < embeddedDataSpecifications.size(); i++) { diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/I4AASEnumMapper.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/I4AASEnumMapper.java index e748b07c..0db6c945 100644 --- a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/I4AASEnumMapper.java +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/I4AASEnumMapper.java @@ -85,6 +85,9 @@ protected String deriveDefaultName() { if (source instanceof io.adminshell.aas.v3.model.IdentifierType) { return IDENTIFICATION_IDTYPE_BROWSENAME; } + if (source instanceof io.adminshell.aas.v3.model.DataTypeIEC61360) { + return IDENTIFICATION_DATATYPE_BROWSENAME; + } return source.getClass().getSimpleName(); } diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/I4AASMapper.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/I4AASMapper.java index cbce55c3..bef31ed5 100644 --- a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/I4AASMapper.java +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/I4AASMapper.java @@ -15,6 +15,8 @@ */ package io.adminshell.aas.v3.dataformat.i4aas.mappers; +import java.util.List; + import org.opcfoundation.ua._2011._03.uanodeset.ListOfReferences; import org.opcfoundation.ua._2011._03.uanodeset.LocalizedText; import org.opcfoundation.ua._2011._03.uanodeset.Reference; @@ -23,19 +25,24 @@ import org.opcfoundation.ua._2011._03.uanodeset.UAObject; import org.opcfoundation.ua._2011._03.uanodeset.UAVariable; +import com.google.common.base.Strings; + import io.adminshell.aas.v3.dataformat.i4aas.mappers.utils.BasicIdentifier; import io.adminshell.aas.v3.dataformat.i4aas.mappers.utils.I4AASConstants; import io.adminshell.aas.v3.dataformat.i4aas.mappers.utils.I4AASIdentifier; import io.adminshell.aas.v3.dataformat.i4aas.mappers.utils.UaIdentifier; import io.adminshell.aas.v3.model.LangString; +import io.adminshell.aas.v3.model.Referable; /** - * Generic base class used for all mapper implementation. + * Generic base class used for all mapper implementation. * * @param mapping source * @param mapping target */ -public abstract class I4AASMapper implements I4AASConstants{ +public abstract class I4AASMapper implements I4AASConstants { + + public static boolean CHECK_NS_INTERN_REFERENCES_ATTACHED = false; protected MappingContext ctx; protected SOURCE source; @@ -57,16 +64,37 @@ public final TARGET map() { target = createTargetObject(); addToNodeset(); mapAndAttachChildren(); + if (CHECK_NS_INTERN_REFERENCES_ATTACHED) { + checkChildrenAttached(); + } return target; } + private void checkChildrenAttached() { + target.getReferences().getReference().forEach(ref -> { + if (ref.getValue().startsWith("ns=" + ctx.getModelNsIndex())) { + List uaObjectOrUAVariableOrUAMethod = ctx.getNodeSet().getUAObjectOrUAVariableOrUAMethod(); + boolean found = false; + for (UANode uaNode : uaObjectOrUAVariableOrUAMethod) { + found = found || uaNode.getNodeId().equals(ref.getValue()); + } + if (!found) { + throw new IllegalStateException( + String.format("parent %s misses child %s", target.getNodeId(), ref.getValue())); + } + } + }); + } + /** - * @return return the object filled with attributes directly bound to the target. + * @return return the object filled with attributes directly bound to the + * target. */ protected abstract TARGET createTargetObject(); /** - * action to be called when the children objects must be mapped and attached to the target. + * action to be called when the children objects must be mapped and attached to + * the target. */ protected abstract void mapAndAttachChildren(); @@ -92,12 +120,14 @@ private static final void addTypeReferenceFor(UANode anyNode, BasicIdentifier id } ListOfReferences references = anyNode.getReferences(); if (idForType instanceof I4AASIdentifier) { - references.getReference().add(Reference.builder().withReferenceType(UaIdentifier.HasTypeDefinition.getName()) - .withValue(ctx.getI4aasNodeIdAsString((I4AASIdentifier) idForType)).build()); + references.getReference() + .add(Reference.builder().withReferenceType(UaIdentifier.HasTypeDefinition.getName()) + .withValue(ctx.getI4aasNodeIdAsString((I4AASIdentifier) idForType)).build()); } if (idForType instanceof UaIdentifier) { - references.getReference().add(Reference.builder().withReferenceType(UaIdentifier.HasTypeDefinition.getName()) - .withValue(ctx.getUaBaseNodeIdAsString((UaIdentifier) idForType)).build()); + references.getReference() + .add(Reference.builder().withReferenceType(UaIdentifier.HasTypeDefinition.getName()) + .withValue(ctx.getUaBaseNodeIdAsString((UaIdentifier) idForType)).build()); } } @@ -108,11 +138,18 @@ protected static final LocalizedText createLocalizedText(String value) { protected final String createBrowseName(String name, int namespaceIndx) { return namespaceIndx + ":" + name; } - + protected final String createModelBrowseName(String name) { return ctx.getModelNsIndex() + ":" + name; } - + + protected final String createModelBrowseName(Referable ref) { + if (ref != null && !Strings.isNullOrEmpty(ref.getIdShort())) { + return ctx.getModelNsIndex() + ":" + ref.getIdShort(); + } + throw new IllegalArgumentException("Referable is null or does not contain a valid IdShort."); + } + protected final String createI4AASBrowseName(String name) { return ctx.getI4aasNsIndex() + ":" + name; } @@ -125,7 +162,8 @@ private static final String createI4AASBrowseName(String name, MappingContext ct return ctx.getI4aasNsIndex() + ":" + name; } - public static final UAObject createFolder(UAObject target, String folderName, MappingContext ctx, BasicIdentifier folderSubtype) { + public static final UAObject createFolder(UAObject target, String folderName, MappingContext ctx, + BasicIdentifier folderSubtype) { UAObject folder = UAObject.builder().withNodeId(ctx.newModelNodeIdAsString()) .withBrowseName(createI4AASBrowseName(folderName, ctx)).withDisplayName(createLocalizedText(folderName)) .build(); @@ -134,18 +172,17 @@ public static final UAObject createFolder(UAObject target, String folderName, Ma attachAsComponent((UAObject) target, folder); return folder; } - public final UAObject createReferenceList(String folderName) { return createFolder((UAObject) target, folderName, ctx, I4AASIdentifier.AASReferenceList); } - public final UAObject createSubmodelElementList(String folderName){ - return createFolder((UAObject)target, folderName, ctx, I4AASIdentifier.AASSubmodelElementList); + public final UAObject createSubmodelElementList(String folderName) { + return createFolder((UAObject) target, folderName, ctx, I4AASIdentifier.AASSubmodelElementList); } public final UAObject createIdentifierKeyValuePairList(String folderName) { - return createFolder((UAObject)target, folderName, ctx, I4AASIdentifier.AASIdentifierKeyValuePairList); + return createFolder((UAObject) target, folderName, ctx, I4AASIdentifier.AASIdentifierKeyValuePairList); } protected static void attachAsType(UAInstance parent, UAInstance child, BasicIdentifier typeId) { @@ -167,8 +204,8 @@ protected static final void attachAsProperty(UAObject parent, UAVariable child) child.setParentNodeId(parent.getNodeId()); attachAsType(parent, child, UaIdentifier.HasProperty); } - - protected static final void attachAsComponent(UAObject parent, UAObject child) { + + protected static final void attachAsComponent(UAObject parent, UAInstance child) { child.setParentNodeId(parent.getNodeId()); attachAsType(parent, child, UaIdentifier.HasComponent); } @@ -177,11 +214,11 @@ protected static final void attachAsOrderedComponent(UAObject parent, UAObject c child.setParentNodeId(parent.getNodeId()); attachAsType(parent, child, UaIdentifier.HasOrderedComponent); } - + protected static final void attachAsDictionaryEntry(UAObject parent, UAObject child) { attachAsType(parent, child, UaIdentifier.HasDictionaryEntry); } - + protected static final void attachAsAddIn(UAObject parent, UAObject child) { attachAsType(parent, child, UaIdentifier.HasAddIn); } diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/IdentifiableMapper.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/IdentifiableMapper.java index 33cdc713..bf7e370f 100644 --- a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/IdentifiableMapper.java +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/IdentifiableMapper.java @@ -61,13 +61,13 @@ private void mapIdentification() { UAVariable mappedEnum = new I4AASEnumMapper(sourceIdType, ctx).map(); attachAsProperty(uaObject, mappedEnum); } - - ctx.addIdentifierUaObject(source.getIdentification(), target); } private void mapAdministration() { - UAObject uaAdministration = new AdministrationMapper(source.getAdministration(), ctx).map(); - attachAsComponent(target, uaAdministration); + if (source.getAdministration() != null) { + UAObject uaAdministration = new AdministrationMapper(source.getAdministration(), ctx).map(); + attachAsComponent(target, uaAdministration); + } } } diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/MappingContext.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/MappingContext.java index c59532f9..71ca4af1 100644 --- a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/MappingContext.java +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/MappingContext.java @@ -33,12 +33,14 @@ import org.opcfoundation.ua._2011._03.uanodeset.UAObject; import org.opcfoundation.ua._2011._03.uanodeset.UriTable; +import io.adminshell.aas.v3.dataformat.core.util.AasUtils; import io.adminshell.aas.v3.dataformat.i4aas.mappers.utils.I4AASConstants; import io.adminshell.aas.v3.dataformat.i4aas.mappers.utils.I4AASIdentifier; import io.adminshell.aas.v3.dataformat.i4aas.mappers.utils.I4AASUtils; import io.adminshell.aas.v3.dataformat.i4aas.mappers.utils.UaIdentifier; import io.adminshell.aas.v3.model.AssetAdministrationShellEnvironment; import io.adminshell.aas.v3.model.Identifier; +import io.adminshell.aas.v3.model.Referable; import io.adminshell.aas.v3.model.Reference; public class MappingContext { @@ -157,47 +159,39 @@ public int getI4aasNsIndex() { return i4aasNsIndex; } - private Map sourceIdentifierToTargetIdentifier = new HashMap<>(); + private Map sourceReferableToTargetIdentifier = new HashMap<>(); private Map targetReferenceToSourceReference = new HashMap<>(); - public void addIdentifierUaObject(Identifier identifier, UAObject identifiable) { - sourceIdentifierToTargetIdentifier.put(identifier, identifiable); + public void registerReferableMapped(Referable sourceReferable, UAObject targetReferable) { + sourceReferableToTargetIdentifier.put(sourceReferable, targetReferable); + // try a local, native UA reference binding for (Entry entry : targetReferenceToSourceReference.entrySet()) { - if (match(identifier, entry.getValue())) { - I4AASMapper.attachAsAddIn(entry.getKey(), identifiable); + Referable resolve = AasUtils.resolve(entry.getValue(), aasEnvironment); + if (sourceReferable.equals(resolve)) { + I4AASMapper.attachAsAddIn(entry.getKey(), targetReferable); } } } - public void addAASReferenceType(UAObject reference, Reference source) { - targetReferenceToSourceReference.put(reference, source); + public void registerReferenceMapped(UAObject targetReference, Reference sourceReference) { + targetReferenceToSourceReference.put(targetReference, sourceReference); + // try a local, native UA reference binding - UAObject targetNodeForReference = getTargetNodeForReference(source); - if (targetNodeForReference != null) { - I4AASMapper.attachAsAddIn(reference, targetNodeForReference); + Referable resolve = AasUtils.resolve(sourceReference, aasEnvironment); + if (resolve != null) { + UAObject uaObject = sourceReferableToTargetIdentifier.get(resolve); + if (uaObject != null) { + I4AASMapper.attachAsAddIn(targetReference, uaObject); + } } } public final UAObject getTargetNodeForReference(Reference semanticId) { - for (Entry entry : sourceIdentifierToTargetIdentifier.entrySet()) { - if (match(entry.getKey(), semanticId)) { - return entry.getValue(); - } - } - return null; - } - - private boolean match(Identifier identifier, Reference reference) { - try { - String firstReferenceEntry = reference.getKeys().get(0).getValue(); - return firstReferenceEntry.equals(identifier.getIdentifier()); - } catch (NullPointerException npe) { - return false; - } + Referable resolve = AasUtils.resolve(semanticId, aasEnvironment); + return sourceReferableToTargetIdentifier.get(resolve); } - public void setAddMissingSemanticIdsToDictionary(boolean addMissingSemanticIdsToDictionary) { this.addMissingSemanticIdsToDictionary = addMissingSemanticIdsToDictionary; } diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/QualifiableMapper.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/QualifiableMapper.java index 92c705e4..28f59ab7 100644 --- a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/QualifiableMapper.java +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/QualifiableMapper.java @@ -29,13 +29,16 @@ public interface QualifiableMapper { public default void mapQualifiable(Qualifiable source, UAObject target, MappingContext ctx) { - UAObject folder = I4AASMapper.createFolder(target, I4AASConstants.QUALIFIABLE_BROWSENAME, ctx, I4AASIdentifier.AASQualifierList); + UAObject folder = source.getQualifiers().isEmpty() ? null + : I4AASMapper.createFolder(target, I4AASConstants.QUALIFIABLE_BROWSENAME, ctx, + I4AASIdentifier.AASQualifierList); List qualifiers = source.getQualifiers(); for (int i = 0; i < qualifiers.size(); i++) { Constraint constraint = qualifiers.get(i); if (constraint instanceof Qualifier) { - UAObject uaQualifier = new QualifierMapper((Qualifier) constraint, ctx, "Qualifier_" + i, ctx.getModelNsIndex()).map(); + UAObject uaQualifier = new QualifierMapper((Qualifier) constraint, ctx, "Qualifier_" + i, + ctx.getModelNsIndex()).map(); I4AASMapper.attachAsComponent(folder, uaQualifier); } } diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/QualifierMapper.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/QualifierMapper.java index 387dca39..07848cb0 100644 --- a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/QualifierMapper.java +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/QualifierMapper.java @@ -18,6 +18,7 @@ import org.opcfoundation.ua._2011._03.uanodeset.UAObject; import org.opcfoundation.ua._2011._03.uanodeset.UAVariable; +import io.adminshell.aas.v3.dataformat.i4aas.mappers.sme.MimeTypeMapper; import io.adminshell.aas.v3.dataformat.i4aas.mappers.sme.ValueTypeMapper; import io.adminshell.aas.v3.dataformat.i4aas.mappers.utils.I4AASIdentifier; import io.adminshell.aas.v3.model.Qualifier; @@ -50,9 +51,8 @@ protected void mapAndAttachChildren() { attachAsComponent(target, map); } - String type = source.getType(); - if (type != null) { - UAVariable map = new StringPropertyMapper("Type", type, ctx, ctx.getI4aasNsIndex()).map(); + if (source.getType() != null) { + UAVariable map = new QualifierTypeMapper(source.getType(), ctx).map(); attachAsProperty(target, map); } diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/QualifierTypeMapper.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/QualifierTypeMapper.java new file mode 100644 index 00000000..79743d78 --- /dev/null +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/QualifierTypeMapper.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021 Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e. V. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.adminshell.aas.v3.dataformat.i4aas.mappers; + +import javax.xml.bind.JAXBElement; + +import org.opcfoundation.ua._2008._02.types.ObjectFactory; +import org.opcfoundation.ua._2011._03.uanodeset.UAVariable; + +import io.adminshell.aas.v3.dataformat.i4aas.mappers.utils.I4AASIdentifier; +import io.adminshell.aas.v3.dataformat.i4aas.mappers.utils.UaIdentifier; + +public class QualifierTypeMapper extends I4AASMapper { + + + public QualifierTypeMapper(String src, MappingContext ctx) { + super(src, ctx); + } + + @Override + protected UAVariable createTargetObject() { + JAXBElement idStringValue = new ObjectFactory().createString(source); + org.opcfoundation.ua._2011._03.uanodeset.UAVariable.Builder idVarBuilder = UAVariable.builder() + .withValue().withAny(idStringValue).end().withDisplayName(createLocalizedText(QUALIFIER_TYPE_BROWSENAME)) + .withDataType(I4AASIdentifier.AASQualifierDataType.getName()).withNodeId(ctx.newModelNodeIdAsString()) + .withBrowseName(createI4AASBrowseName(QUALIFIER_TYPE_BROWSENAME)).withAccessLevel(3L); + target = idVarBuilder.build(); + addTypeReferenceFor(target, UaIdentifier.PropertyType); + return target; + } + + @Override + protected void mapAndAttachChildren() { + } + +} diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/ReferableMapper.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/ReferableMapper.java index be273039..2c6bfd42 100644 --- a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/ReferableMapper.java +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/ReferableMapper.java @@ -31,24 +31,26 @@ public ReferableMapper(T src, MappingContext ctx) { @Override protected UAObject createTargetObject() { target = UAObject.builder().withNodeId(ctx.newModelNodeIdAsString()) - .withBrowseName(createModelBrowseName(source.getIdShort())) + .withBrowseName(createModelBrowseName(source)) .withDisplayName(I4AASUtils.createDisplayName(source)).build(); return target; } @Override protected void mapAndAttachChildren() { - - String category = source.getCategory() == null ? "" : source.getCategory(); - UAVariable categoryProperty = new StringPropertyMapper(CATEGORY_BROWSENAME, category, ctx, ctx.getI4aasNsIndex()).map(); - attachAsProperty(target, categoryProperty); - + if (source.getCategory() != null) { + UAVariable categoryProperty = new StringPropertyMapper(CATEGORY_BROWSENAME, source.getCategory(), ctx, + ctx.getI4aasNsIndex()).map(); + attachAsProperty(target, categoryProperty); + } + for (LangString description : source.getDescriptions()) { target.getDescription().add(mapLangString(description)); } for (LangString displayName : source.getDisplayNames()) { target.getDisplayName().add(mapLangString(displayName)); } + ctx.registerReferableMapped(source, target); } } diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/ReferenceMapper.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/ReferenceMapper.java index 5c1090d0..02822e4c 100644 --- a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/ReferenceMapper.java +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/ReferenceMapper.java @@ -50,7 +50,6 @@ protected UAObject createTargetObject() { target = UAObject.builder().withNodeId(ctx.newModelNodeIdAsString()).withBrowseName(createI4AASBrowseName(browseName)) .withDisplayName(createLocalizedText(browseName)).build(); addTypeReference(I4AASIdentifier.AASReferenceType); - ctx.addAASReferenceType(target, source); return target; } @@ -89,6 +88,7 @@ protected void mapAndAttachChildren() { } UAKeyVariable.getValue().setAny(extensionObjectFactory.createListOfExtensionObject(listOfExtensions)); } + ctx.registerReferenceMapped(target, source); } } diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/sme/AnnotatedRelationshipElementMapper.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/sme/AnnotatedRelationshipElementMapper.java index 733c4a51..34d31dd4 100644 --- a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/sme/AnnotatedRelationshipElementMapper.java +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/sme/AnnotatedRelationshipElementMapper.java @@ -38,11 +38,11 @@ protected UAObject createTargetObject() { addTypeReference(I4AASIdentifier.AASAnnotatedRelationshipElementType); return target; } - + @Override protected void mapAndAttachChildren() { super.mapAndAttachChildren(); - UAObject createFolder = createSubmodelElementList("Annotation"); + UAObject createFolder = source.getAnnotations().isEmpty() ? null : createSubmodelElementList("Annotation"); List annotations = source.getAnnotations(); for (DataElement dataElement : annotations) { UAObject uaDataElement = SubmodelElementMappers.getMapper(dataElement, ctx).map(); diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/sme/EntityMapper.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/sme/EntityMapper.java index 2277f473..11043d0c 100644 --- a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/sme/EntityMapper.java +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/sme/EntityMapper.java @@ -52,20 +52,20 @@ protected void mapAndAttachChildren() { UAVariable map = new I4AASEnumMapper(entityType, ctx).map(); attachAsProperty(target, map); } - + Reference globalAssetId = source.getGlobalAssetId(); if (globalAssetId != null) { UAObject uaIdentification = new ReferenceMapper(globalAssetId, ctx, "GlobalAssetId").map(); attachAsComponent(target, uaIdentification); } - + IdentifierKeyValuePair specificAssetId = source.getSpecificAssetId(); if (specificAssetId != null) { UAObject map = new IdentifierKeyValuePairMapper(specificAssetId, ctx).map(); attachAsComponent(target, map); } - - UAObject createFolder = createSubmodelElementList("Statement"); + + UAObject createFolder = source.getStatements().isEmpty() ? null : createSubmodelElementList("Statement"); List statements = source.getStatements(); for (SubmodelElement submodelElement : statements) { UAObject map = SubmodelElementMappers.getMapper(submodelElement, ctx).map(); diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/sme/OperationMapper.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/sme/OperationMapper.java index b354098e..374baa44 100644 --- a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/sme/OperationMapper.java +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/sme/OperationMapper.java @@ -15,29 +15,65 @@ */ package io.adminshell.aas.v3.dataformat.i4aas.mappers.sme; +import org.opcfoundation.ua._2011._03.uanodeset.UAMethod; import org.opcfoundation.ua._2011._03.uanodeset.UAObject; import io.adminshell.aas.v3.dataformat.i4aas.mappers.MappingContext; import io.adminshell.aas.v3.dataformat.i4aas.mappers.utils.I4AASIdentifier; import io.adminshell.aas.v3.model.Operation; +import io.adminshell.aas.v3.model.OperationVariable; +import io.adminshell.aas.v3.model.SubmodelElement; public class OperationMapper extends SubmodelElementMapper { public OperationMapper(Operation src, MappingContext ctx) { super(src, ctx); } - + @Override protected UAObject createTargetObject() { super.createTargetObject(); addTypeReference(I4AASIdentifier.AASOperationType); return target; } - + @Override protected void mapAndAttachChildren() { super.mapAndAttachChildren(); - //not applicable for I4AAS + + if (!source.getInputVariables().isEmpty()) { + UAObject folder = createSubmodelElementList("InputVariable"); + for (OperationVariable operationVariable : source.getInputVariables()) { + SubmodelElement value = operationVariable.getValue(); + UAObject mappedVariable = SubmodelElementMappers.getMapper(value, ctx).map(); + attachAsComponent(folder, mappedVariable); + } + } + + if (!source.getOutputVariables().isEmpty()) { + UAObject folder = createSubmodelElementList("OutputVariable"); + for (OperationVariable operationVariable : source.getOutputVariables()) { + SubmodelElement value = operationVariable.getValue(); + UAObject mappedVariable = SubmodelElementMappers.getMapper(value, ctx).map(); + attachAsComponent(folder, mappedVariable); + } + } + + if (!source.getInoutputVariables().isEmpty()) { + UAObject folder = createSubmodelElementList("InOutputVariable"); + for (OperationVariable operationVariable : source.getInoutputVariables()) { + SubmodelElement value = operationVariable.getValue(); + UAObject mappedVariable = SubmodelElementMappers.getMapper(value, ctx).map(); + attachAsComponent(folder, mappedVariable); + } + } + + UAMethod operation = UAMethod.builder().withBrowseName(createI4AASBrowseName("Operation")) + .addDisplayName(createLocalizedText("Operation")) + .withMethodDeclarationId(ctx.getI4aasNodeIdAsString(I4AASIdentifier.AASOperationType_Operation)) + .withNodeId(ctx.newModelNodeIdAsString()).build(); + this.addToNodeset(operation); + attachAsComponent(target, operation); } } diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/sme/ValueTypeMapper.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/sme/ValueTypeMapper.java index 355af10c..50299661 100644 --- a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/sme/ValueTypeMapper.java +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/sme/ValueTypeMapper.java @@ -41,6 +41,7 @@ public class ValueTypeMapper extends I4AASMapper { staticMap.put("float", AASValueTypeDataType.FLOAT_9); staticMap.put("double", AASValueTypeDataType.DOUBLE_10); staticMap.put("long", AASValueTypeDataType.INT_64_7); + staticMap.put("http://www.w3.org/2001/XMLSchema#int", AASValueTypeDataType.INT_32_5); //to be extended } diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/utils/I4AASConstants.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/utils/I4AASConstants.java index 894dced8..800dc4dc 100644 --- a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/utils/I4AASConstants.java +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/utils/I4AASConstants.java @@ -34,6 +34,7 @@ public interface I4AASConstants { public static final String IDENTIFICATION_BROWSENAME = "Identification"; public static final String IDENTIFICATION_ID_BROWSENAME = "Id"; public static final String IDENTIFICATION_IDTYPE_BROWSENAME = "IdType"; + public static final String IDENTIFICATION_DATATYPE_BROWSENAME = "DataType"; public static final String ADMINISTRATION_BROWSENAME = "Administration"; public static final String ADMINISTRATION_REVISION_BROWSENAME = "Revision"; @@ -69,6 +70,7 @@ public interface I4AASConstants { public static final String IKVP_VALUE_BROWSENAME = "Value"; public static final String MIME_TYPE_BROWSENAME = "MimeType"; + public static final String QUALIFIER_TYPE_BROWSENAME = "Type"; } diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/utils/I4AASIdentifier.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/utils/I4AASIdentifier.java index 6bf231b5..e3f1f310 100644 --- a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/utils/I4AASIdentifier.java +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/utils/I4AASIdentifier.java @@ -70,9 +70,14 @@ public enum I4AASIdentifier implements BasicIdentifier { AASPropertyValueDataType("AASPropertyValueDataType", 3014), AASModelingKindDataType("AASModelingKindDataType", 3015), AASMimeDataType("AASMimeDataType", 3016), - AASKeyDataType_Encoding_DefaultXml("AASKeyDataType_Encoding_DefaultXml",5039); - -; + AASKeyDataType_Encoding_DefaultXml("AASKeyDataType_Encoding_DefaultXml",5039), + AASOperationType_Operation("AASOperationType_Operation",7001), + AASFileType_File_Close("AASFileType_File_Close",7008), + AASFileType_File_GetPosition("AASFileType_File_GetPosition",7009), + AASFileType_File_Open("AASFileType_File_Open",7010), + AASFileType_File_Read("AASFileType_File_Read",7011), + AASFileType_File_SetPosition("AASFileType_File_SetPosition",7012), + AASFileType_File_Write("AASFileType_File_Write",7013); private String name; private Integer id; diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/utils/I4AASUtils.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/utils/I4AASUtils.java index 9b8b480e..e8ba0f9f 100644 --- a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/utils/I4AASUtils.java +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/mappers/utils/I4AASUtils.java @@ -44,4 +44,20 @@ public static LocalizedText createDisplayName(Referable ref) { } } + public static String parseDisplayName(Referable ref, String rawstring) { + if (rawstring == null) { + return null; + } + if (ref instanceof Submodel && rawstring.startsWith(I4AASConstants.SM_DISPLAYNAME_PREFIX)) { + return rawstring.substring(I4AASConstants.SM_DISPLAYNAME_PREFIX.length()); + } else if (ref instanceof AssetAdministrationShell + && rawstring.startsWith(I4AASConstants.AAS_DISPLAYNAME_PREFIX)) { + return rawstring.substring(I4AASConstants.AAS_DISPLAYNAME_PREFIX.length()); + } else if (ref instanceof Asset && rawstring.startsWith(I4AASConstants.ASSET_DISPLAYNAME_PREFIX)) { + return rawstring.substring(I4AASConstants.ASSET_DISPLAYNAME_PREFIX.length()); + } else { + return rawstring; + } + } + } diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/parsers/ParserUtils.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/parsers/ParserUtils.java index d8ae2f9a..33c8dd3c 100644 --- a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/parsers/ParserUtils.java +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/parsers/ParserUtils.java @@ -94,8 +94,8 @@ public static List extractValueAsLangString(UAVariable nodeVariable) List localizedTexts = ((ListOfLocalizedText) anyJaxbElement.getValue()) .getLocalizedText(); for (LocalizedText localizedText : localizedTexts) { - LangString langString = new LangString(localizedText.getLocale().getValue(), - localizedText.getText().getValue()); + LangString langString = new LangString(localizedText.getText().getValue(), + localizedText.getLocale().getValue()); result.add(langString); } } else if (anyJaxbElement.getValue() != null) { diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/parsers/PropertyParser.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/parsers/PropertyParser.java index bc1b78b1..a203290b 100644 --- a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/parsers/PropertyParser.java +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/parsers/PropertyParser.java @@ -15,6 +15,7 @@ */ package io.adminshell.aas.v3.dataformat.i4aas.parsers; +import io.adminshell.aas.v3.model.AssetKind; import io.adminshell.aas.v3.model.Property; import io.adminshell.aas.v3.model.Reference; import io.adminshell.aas.v3.model.impl.DefaultProperty; @@ -45,8 +46,9 @@ protected void parseAndAttachChildren() { }); }); - source.getI4AASComponent("ValueType").ifPresent(p -> { - target.setValueType(ParserUtils.extractValueAsString(p.getNodeVariable())); + source.getI4AASProperty("ValueType").ifPresent(p -> { + String parse = new ValueTypeParser(p, ctx).parse(); + target.setValueType(parse); }); } diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/parsers/QualifierParser.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/parsers/QualifierParser.java index 1b5fa6aa..c961f740 100644 --- a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/parsers/QualifierParser.java +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/parsers/QualifierParser.java @@ -50,7 +50,7 @@ protected void parseAndAttachChildren() { }); source.getI4AASProperty("ValueType").ifPresent(p -> { - String parse = ParserUtils.extractValueAsString(p.getNodeVariable()); + String parse = new ValueTypeParser(p, ctx).parse(); target.setValueType(parse); }); } diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/parsers/RangeParser.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/parsers/RangeParser.java index ccfc8744..0da29a1c 100644 --- a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/parsers/RangeParser.java +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/parsers/RangeParser.java @@ -44,7 +44,7 @@ protected void parseAndAttachChildren() { }); source.getI4AASProperty("ValueType").ifPresent(p -> { - String parse = ParserUtils.extractValueAsString(p.getNodeVariable()); + String parse = new ValueTypeParser(p, ctx).parse(); target.setValueType(parse); }); } diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/parsers/ReferableParser.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/parsers/ReferableParser.java index ade15ffd..0b2e016c 100644 --- a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/parsers/ReferableParser.java +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/parsers/ReferableParser.java @@ -22,6 +22,8 @@ import org.opcfoundation.ua._2011._03.uanodeset.UAVariable; import io.adminshell.aas.v3.dataformat.i4aas.mappers.utils.I4AASIdentifier; +import io.adminshell.aas.v3.dataformat.i4aas.mappers.utils.I4AASUtils; +import io.adminshell.aas.v3.model.Asset; import io.adminshell.aas.v3.model.ConceptDescription; import io.adminshell.aas.v3.model.Constraint; import io.adminshell.aas.v3.model.EmbeddedDataSpecification; @@ -48,12 +50,13 @@ protected void parseAndAttachChildren() { target.setIdShort(source.getBrowseNameStringPart()); for (LocalizedText localizedText : source.getDescription()) { - LangString langString = new LangString(localizedText.getLocale(), localizedText.getValue()); + LangString langString = new LangString(localizedText.getValue(), localizedText.getLocale()); target.getDescriptions().add(langString); } for (LocalizedText localizedText : source.getDisplayName()) { - LangString langString = new LangString(localizedText.getLocale(), localizedText.getValue()); + String displayName = I4AASUtils.parseDisplayName(target, localizedText.getValue()); + LangString langString = new LangString(displayName, localizedText.getLocale()); target.getDisplayNames().add(langString); } @@ -81,6 +84,7 @@ protected void parseAndAttachChildren() { } private void parseSemantics(HasSemantics target) { + //TODO I4AAS currently lacks with handling of KeyElements within ConceptDescriptions source.getAASDictionaryEntry().ifPresent(p -> { ConceptDescription cd = new ConceptDescriptionParser(p, ctx).parse(); Identifier identification = cd.getIdentification(); diff --git a/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/parsers/ValueTypeParser.java b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/parsers/ValueTypeParser.java new file mode 100644 index 00000000..394b2ed0 --- /dev/null +++ b/dataformat-uanodeset/src/main/java/io/adminshell/aas/v3/dataformat/i4aas/parsers/ValueTypeParser.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021 Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e. V. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.adminshell.aas.v3.dataformat.i4aas.parsers; + +import java.util.Map; +import java.util.TreeMap; + +import org.opcfoundation.ua.i4aas.v3.types.AASValueTypeDataType; + +public class ValueTypeParser extends I4AASParser { + + private static Map staticMap = new TreeMap<>(); + static { + staticMap.put(AASValueTypeDataType.INT_32_5,"integer"); + staticMap.put(AASValueTypeDataType.LOCALIZED_TEXT_14,"langstring"); + staticMap.put(AASValueTypeDataType.STRING_11,"string"); + staticMap.put(AASValueTypeDataType.BOOLEAN_0,"boolean"); + staticMap.put(AASValueTypeDataType.FLOAT_9,"float"); + staticMap.put(AASValueTypeDataType.DOUBLE_10,"double"); + staticMap.put(AASValueTypeDataType.INT_64_7,"long"); + //to be extended + } + + public ValueTypeParser(UANodeWrapper src, ParserContext ctx) { + super(src, ctx); + } + + @Override + protected String createTargetObject() { + Integer enumIdx = ParserUtils.extractValueAsInteger(source.getNodeVariable()); + AASValueTypeDataType aasValueTypeDataType = AASValueTypeDataType.values()[enumIdx]; + return staticMap.get(aasValueTypeDataType); + } + + @Override + protected void parseAndAttachChildren() { + } + +} diff --git a/dataformat-uanodeset/src/test/java/io/adminshell/aas/v3/dataformat/i4aas/AASExamples.java b/dataformat-uanodeset/src/test/java/io/adminshell/aas/v3/dataformat/i4aas/AASExamples.java index 93724f73..2d1ee4f5 100644 --- a/dataformat-uanodeset/src/test/java/io/adminshell/aas/v3/dataformat/i4aas/AASExamples.java +++ b/dataformat-uanodeset/src/test/java/io/adminshell/aas/v3/dataformat/i4aas/AASExamples.java @@ -66,7 +66,7 @@ private AASExamples() { .build()) .dataSpecificationContent(new DefaultDataSpecificationIEC61360.Builder() .dataType(DataTypeIEC61360.BOOLEAN) - .definition(new LangString("en", "mydefinition")).symbol("iec61360_symbol") + .definition(new LangString("mydefinition", "en")).symbol("iec61360_symbol") .build()) .build()) .build()) diff --git a/dataformat-uanodeset/src/test/java/io/adminshell/aas/v3/dataformat/i4aas/IntegrationTests.java b/dataformat-uanodeset/src/test/java/io/adminshell/aas/v3/dataformat/i4aas/IntegrationTests.java index 039b556a..29d7f9ec 100644 --- a/dataformat-uanodeset/src/test/java/io/adminshell/aas/v3/dataformat/i4aas/IntegrationTests.java +++ b/dataformat-uanodeset/src/test/java/io/adminshell/aas/v3/dataformat/i4aas/IntegrationTests.java @@ -15,17 +15,30 @@ */ package io.adminshell.aas.v3.dataformat.i4aas; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.List; +import org.apache.jena.graph.Graph; +import org.apache.jena.shacl.ValidationReport; +import org.apache.jena.shacl.validation.ReportEntry; +import org.json.JSONException; import org.junit.Assert; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; +import org.skyscreamer.jsonassert.JSONAssert; +import org.skyscreamer.jsonassert.JSONCompareMode; import io.adminshell.aas.v3.dataformat.DeserializationException; import io.adminshell.aas.v3.dataformat.SerializationException; import io.adminshell.aas.v3.dataformat.core.AASFull; +import io.adminshell.aas.v3.dataformat.core.AASSimple; import io.adminshell.aas.v3.dataformat.i4aas.mappers.MappingContext; +import io.adminshell.aas.v3.dataformat.json.JsonSerializer; import io.adminshell.aas.v3.model.Asset; import io.adminshell.aas.v3.model.AssetAdministrationShell; import io.adminshell.aas.v3.model.AssetAdministrationShellEnvironment; @@ -35,6 +48,7 @@ import io.adminshell.aas.v3.model.ConceptDescription; import io.adminshell.aas.v3.model.IdentifierKeyValuePair; import io.adminshell.aas.v3.model.IdentifierType; +import io.adminshell.aas.v3.model.KeyElements; import io.adminshell.aas.v3.model.KeyType; import io.adminshell.aas.v3.model.LangString; import io.adminshell.aas.v3.model.MultiLanguageProperty; @@ -54,6 +68,8 @@ import io.adminshell.aas.v3.model.impl.DefaultReference; import io.adminshell.aas.v3.model.impl.DefaultSubmodel; import io.adminshell.aas.v3.model.impl.DefaultSubmodelElementCollection; +import io.adminshell.aas.v3.model.validator.ShaclValidator; +import io.adminshell.aas.v3.model.validator.ValidationException; public class IntegrationTests { @@ -75,9 +91,14 @@ public void before() { // test frame model env = new DefaultAssetAdministrationShellEnvironment(); aas = new DefaultAssetAdministrationShell(); + aas.setIdShort("aas"); asset = new DefaultAsset(); + asset.setIdShort("asset"); sm = new DefaultSubmodel(); + sm.setIdShort("sm"); cd = new DefaultConceptDescription(); + cd.setIdShort("cd"); + cd.setIdentification(new DefaultIdentifier.Builder().identifier("mycd").idType(IdentifierType.CUSTOM).build()); env.getAssetAdministrationShells().add(aas); env.getAssets().add(asset); env.getSubmodels().add(sm); @@ -92,8 +113,8 @@ public void testBlobWithSemantics() throws SerializationException, Deserializati blob.setValue("testvalue".getBytes()); blob.setIdShort("testblob"); - blob.setSemanticId(new DefaultReference.Builder() - .key(new DefaultKey.Builder().value("mySemanticId").idType(KeyType.CUSTOM).build()).build()); + blob.setSemanticId(new DefaultReference.Builder().key(new DefaultKey.Builder().value("mySemanticId") + .type(KeyElements.CONCEPT_DESCRIPTION).idType(KeyType.CUSTOM).build()).build()); sm.getSubmodelElements().add(blob); @@ -117,8 +138,8 @@ public void testMultiLanguageProperty() throws SerializationException, Deseriali defaultMultiLanguageProperty.setIdShort("mymultilang"); List values = new ArrayList<>(); - values.add(new LangString("de", "delang")); - values.add(new LangString("en", "enlang")); + values.add(new LangString("delang", "de")); + values.add(new LangString("enlang", "en")); defaultMultiLanguageProperty.setValues(values); sm.getSubmodelElements().add(defaultMultiLanguageProperty); @@ -190,8 +211,8 @@ public void testAssetInformation() throws SerializationException, Deserializatio public void testConceptDescription() throws SerializationException, DeserializationException { // ARRANGE cd.setIdentification(new DefaultIdentifier.Builder().identifier("myCD").idType(IdentifierType.CUSTOM).build()); - cd.getIsCaseOfs().add(new DefaultReference.Builder() - .key(new DefaultKey.Builder().value("myCaseOfRef").idType(KeyType.CUSTOM).build()).build()); + cd.getIsCaseOfs().add(new DefaultReference.Builder().key(new DefaultKey.Builder().value("myCaseOfRef") + .type(KeyElements.CONCEPT_DESCRIPTION).idType(KeyType.CUSTOM).build()).build()); // ACT AssetAdministrationShellEnvironment result = inAndOut(); @@ -204,14 +225,17 @@ public void testConceptDescription() throws SerializationException, Deserializat } @Test - public void testAASFull() throws SerializationException, DeserializationException { + public void testAASFull() + throws SerializationException, DeserializationException, ValidationException, IOException { // ARRANGE + ShaclValidator.getInstance().validate(AASFull.ENVIRONMENT); + Assert.assertEquals(4, AASFull.ENVIRONMENT.getAssetAdministrationShells().size()); Assert.assertEquals(7, AASFull.ENVIRONMENT.getSubmodels().size()); Assert.assertEquals(4, AASFull.ENVIRONMENT.getConceptDescriptions().size()); // ACT - serializer = new I4AASSerializer(false); //false = do not add semanticIds automaitcally to concept description + serializer = new I4AASSerializer(false); // false = do not add semanticIds automaitcally to concept description deserializer = new I4AASDeserializer(); AssetAdministrationShellEnvironment result = deserializer.read(serializer.write(AASFull.ENVIRONMENT)); @@ -219,6 +243,32 @@ public void testAASFull() throws SerializationException, DeserializationExceptio Assert.assertEquals(4, result.getAssetAdministrationShells().size()); Assert.assertEquals(7, result.getSubmodels().size()); Assert.assertEquals(4, result.getConceptDescriptions().size()); + ValidationReport validateGetReport = ShaclValidator.getInstance().validateGetReport(result); + for (ReportEntry reportEntry : validateGetReport.getEntries()) { + if ("".equals(reportEntry.resultPath().toString())) { + //observed currently not supported + continue; + } + Assert.fail(reportEntry.toString()); + } + } + + @Test + @Ignore(value = "highly dependent on other json dependencies, just used for manual comparison if json serializer is seen as complete reference implementation") + public void testAASFullwithJsonCompare() + throws SerializationException, DeserializationException, JSONException, IOException { + // ARRANGE + String expected = new JsonSerializer().write(AASFull.ENVIRONMENT); + Files.writeString(Paths.get("./jsonExpected.json"), expected, StandardOpenOption.CREATE, + StandardOpenOption.TRUNCATE_EXISTING); + + AssetAdministrationShellEnvironment result = deserializer.read(serializer.write(AASFull.ENVIRONMENT)); + + String actual = new JsonSerializer().write(result); + Files.writeString(Paths.get("./jsonActual.json"), actual, StandardOpenOption.CREATE, + StandardOpenOption.TRUNCATE_EXISTING); + + JSONAssert.assertEquals(expected, actual, JSONCompareMode.LENIENT); } public AssetAdministrationShellEnvironment inAndOut() throws SerializationException, DeserializationException { diff --git a/dataformat-uanodeset/src/test/java/io/adminshell/aas/v3/dataformat/i4aas/SerializerTest.java b/dataformat-uanodeset/src/test/java/io/adminshell/aas/v3/dataformat/i4aas/SerializerTest.java index ca525ece..d1c564f3 100644 --- a/dataformat-uanodeset/src/test/java/io/adminshell/aas/v3/dataformat/i4aas/SerializerTest.java +++ b/dataformat-uanodeset/src/test/java/io/adminshell/aas/v3/dataformat/i4aas/SerializerTest.java @@ -29,6 +29,7 @@ import io.adminshell.aas.v3.dataformat.SerializationException; import io.adminshell.aas.v3.dataformat.core.AASFull; import io.adminshell.aas.v3.dataformat.core.AASSimple; +import io.adminshell.aas.v3.dataformat.i4aas.mappers.I4AASMapper; import io.adminshell.aas.v3.dataformat.i4aas.mappers.MappingContext; import io.adminshell.aas.v3.model.impl.DefaultAssetAdministrationShellEnvironment; @@ -37,6 +38,7 @@ public class SerializerTest { @BeforeClass public static void before() { MappingContext.setModelNamespaceNamingStrategy(nodeset -> "http://example.org/SerializerTest"); + I4AASMapper.CHECK_NS_INTERN_REFERENCES_ATTACHED = true; } @Test