Skip to content
This repository was archived by the owner on Feb 15, 2024. It is now read-only.

Commit d05d035

Browse files
committed
- now serializing AssetInformation.specificAssetId (using custom format as current AML serialization specification does not cover attribute introduces in model v3.0)
- added unit tests for simple example (serialization does currently loose information as as current AML serialization specification does not cover attribute introduces in model v3.0)
1 parent dd9afc7 commit d05d035

8 files changed

Lines changed: 2210 additions & 30 deletions

File tree

dataformat-aml/src/main/java/io/adminshell/aas/v3/dataformat/aml/deserialization/Aml2AasMapper.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@
2525
import io.adminshell.aas.v3.dataformat.mapping.MappingException;
2626
import io.adminshell.aas.v3.dataformat.mapping.MappingProvider;
2727
import io.adminshell.aas.v3.model.AssetAdministrationShellEnvironment;
28+
import io.adminshell.aas.v3.model.AssetInformation;
2829
import io.adminshell.aas.v3.model.Identifiable;
2930
import io.adminshell.aas.v3.model.MultiLanguageProperty;
3031
import io.adminshell.aas.v3.model.Referable;
3132
import io.adminshell.aas.v3.model.Qualifiable;
3233

33-
3434
import java.util.List;
3535

3636
/**
@@ -64,8 +64,8 @@ public AssetAdministrationShellEnvironment map(CAEXFile aml) throws MappingExcep
6464
mappingProvider.register(new LangStringCollectionMapper());
6565
mappingProvider.register(new RelationshipElementMapper());
6666
mappingProvider.register(new ReferenceElementMapper());
67-
mappingProvider.register(new ReferableMapper<Referable>());
68-
mappingProvider.register(new IdentifiableMapper<Identifiable>());
67+
mappingProvider.register(new ReferableMapper<>());
68+
mappingProvider.register(new IdentifiableMapper<>());
6969
mappingProvider.register(new ConstraintCollectionMapper());
7070
mappingProvider.register(new QualifierMapper());
7171
mappingProvider.register(new OperationCollectionMapper());
@@ -77,12 +77,15 @@ public AssetAdministrationShellEnvironment map(CAEXFile aml) throws MappingExcep
7777
mappingProvider.register(new EmbeddedDataSpecificationCollectionMapper());
7878
mappingProvider.register(new DataSpecificationIEC61360Mapper());
7979
mappingProvider.register(new EnumDataTypeIEC61360Mapper());
80+
mappingProvider.register(new IdentifierKeyValuePairCollectionMapper());
81+
8082
AbstractClassNamingStrategy classNamingStrategy = new NumberingClassNamingStrategy();
8183

8284
PropertyNamingStrategy propertyNamingStrategy = new PropertyNamingStrategy();
8385
propertyNamingStrategy.registerCustomNaming(Referable.class, "descriptions", "description");
8486
propertyNamingStrategy.registerCustomNaming(MultiLanguageProperty.class, "values", "value");
85-
propertyNamingStrategy.registerCustomNaming(Qualifiable.class, "qualifiers", "qualifier","qualifier");
87+
propertyNamingStrategy.registerCustomNaming(Qualifiable.class, "qualifiers", "qualifier", "qualifier");
88+
propertyNamingStrategy.registerCustomNaming(AssetInformation.class, "specificAssetIds", "specificAssetId");
8689
MappingContext context = new MappingContext(mappingProvider, classNamingStrategy, propertyNamingStrategy, config.getTypeFactory());
8790
context.setDocumentInfo(AmlDocumentInfo.fromFile(aml));
8891
AssetAdministrationShellEnvironment result = context.map(AssetAdministrationShellEnvironment.class, parser);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Copyright (c) 2021 Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e. V.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.adminshell.aas.v3.dataformat.aml.deserialization.mappers;
17+
18+
import io.adminshell.aas.v3.dataformat.aml.deserialization.AmlParser;
19+
import io.adminshell.aas.v3.dataformat.aml.deserialization.DefaultMapper;
20+
import io.adminshell.aas.v3.dataformat.aml.deserialization.MappingContext;
21+
import io.adminshell.aas.v3.dataformat.aml.model.caex.AttributeType;
22+
import io.adminshell.aas.v3.dataformat.aml.model.caex.CAEXObject;
23+
import io.adminshell.aas.v3.dataformat.core.util.AasUtils;
24+
import io.adminshell.aas.v3.dataformat.mapping.MappingException;
25+
import io.adminshell.aas.v3.model.IdentifierKeyValuePair;
26+
import java.beans.PropertyDescriptor;
27+
28+
import java.lang.reflect.InvocationTargetException;
29+
import java.util.ArrayList;
30+
import java.util.Collection;
31+
import java.util.List;
32+
import java.util.logging.Level;
33+
import java.util.logging.Logger;
34+
35+
public class IdentifierKeyValuePairCollectionMapper extends DefaultMapper<Collection<IdentifierKeyValuePair>> {
36+
37+
@Override
38+
protected Collection mapCollectionValueProperty(AmlParser parser, MappingContext context) throws MappingException {
39+
Collection result = new ArrayList<>();
40+
CAEXObject current = parser.getCurrent();
41+
AttributeType parent = findAttribute(current, context.getProperty(), context);
42+
if (parent == null) {
43+
return result;
44+
}
45+
List<AttributeType> attributes = findAttributes(parent, x -> x.getName().startsWith("specificAssetId"));
46+
for (AttributeType attribute : attributes) {
47+
parser.setCurrent(attribute);
48+
try {
49+
IdentifierKeyValuePair element = context.getTypeFactory().newInstance(IdentifierKeyValuePair.class);
50+
for (PropertyDescriptor property : AasUtils.getAasProperties(IdentifierKeyValuePair.class)) {
51+
Object propertyValue = context
52+
.with(element)
53+
.with(property)
54+
.withoutType()
55+
.map(property.getReadMethod().getGenericReturnType(), parser);
56+
if (propertyValue != null) {
57+
try {
58+
property.getWriteMethod().invoke(element, propertyValue);
59+
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
60+
throw new MappingException(String.format("error setting property value for property %s", property.getName()), ex);
61+
}
62+
}
63+
}
64+
parser.setCurrent(attribute);
65+
result.add(element);
66+
} catch (NoSuchMethodException ex) {
67+
Logger.getLogger(IdentifierKeyValuePairCollectionMapper.class.getName()).log(Level.SEVERE, null, ex);
68+
} catch (InstantiationException ex) {
69+
Logger.getLogger(IdentifierKeyValuePairCollectionMapper.class.getName()).log(Level.SEVERE, null, ex);
70+
} catch (IllegalAccessException ex) {
71+
Logger.getLogger(IdentifierKeyValuePairCollectionMapper.class.getName()).log(Level.SEVERE, null, ex);
72+
} catch (IllegalArgumentException ex) {
73+
Logger.getLogger(IdentifierKeyValuePairCollectionMapper.class.getName()).log(Level.SEVERE, null, ex);
74+
} catch (InvocationTargetException ex) {
75+
Logger.getLogger(IdentifierKeyValuePairCollectionMapper.class.getName()).log(Level.SEVERE, null, ex);
76+
}
77+
}
78+
parser.setCurrent(parent);
79+
return result;
80+
}
81+
82+
}

dataformat-aml/src/main/java/io/adminshell/aas/v3/dataformat/aml/serialization/AasToAmlMapper.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import io.adminshell.aas.v3.dataformat.aml.serialization.mappers.ViewMapper;
3939
import io.adminshell.aas.v3.dataformat.aml.model.caex.CAEXFile;
4040
import io.adminshell.aas.v3.dataformat.aml.serialization.mappers.ConceptDescriptionMapper;
41+
import io.adminshell.aas.v3.dataformat.aml.serialization.mappers.IdentifierKeyValuePairCollectionMapper;
4142
import io.adminshell.aas.v3.dataformat.aml.serialization.mappers.PropertyMapper;
4243
import io.adminshell.aas.v3.dataformat.aml.serialization.mappers.RangeMapper;
4344
import io.adminshell.aas.v3.dataformat.aml.serialization.mappers.ReferenceMapper;
@@ -99,6 +100,7 @@ public CAEXFile map(AssetAdministrationShellEnvironment env, AmlSerializationCon
99100
mappingProvider.register(new PropertyMapper());
100101
mappingProvider.register(new RangeMapper());
101102
mappingProvider.register(new ConceptDescriptionMapper());
103+
mappingProvider.register(new IdentifierKeyValuePairCollectionMapper());
102104
MappingContext context = new MappingContext(
103105
mappingProvider,
104106
classNamingStrategy,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright (c) 2021 Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e. V.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.adminshell.aas.v3.dataformat.aml.serialization.mappers;
17+
18+
import io.adminshell.aas.v3.dataformat.aml.serialization.DefaultMapper;
19+
import io.adminshell.aas.v3.dataformat.aml.serialization.AmlGenerator;
20+
import io.adminshell.aas.v3.dataformat.aml.serialization.MappingContext;
21+
import io.adminshell.aas.v3.dataformat.aml.model.caex.AttributeType;
22+
import io.adminshell.aas.v3.dataformat.core.util.AasUtils;
23+
import io.adminshell.aas.v3.dataformat.mapping.MappingException;
24+
import io.adminshell.aas.v3.model.AssetInformation;
25+
import io.adminshell.aas.v3.model.IdentifierKeyValuePair;
26+
import java.beans.PropertyDescriptor;
27+
import java.lang.reflect.InvocationTargetException;
28+
import java.util.ArrayList;
29+
import java.util.Collection;
30+
import java.util.List;
31+
32+
public class IdentifierKeyValuePairCollectionMapper extends DefaultMapper<Collection<IdentifierKeyValuePair>> {
33+
34+
private static final String ATTRIBUTE_NAME = "specificAssetId";
35+
36+
@Override
37+
public void map(Collection<IdentifierKeyValuePair> value, AmlGenerator generator, MappingContext context) throws MappingException {
38+
if (value == null || context == null || value.isEmpty()) {
39+
return;
40+
}
41+
AttributeType.Builder wrapperBuilder = AttributeType.builder()
42+
.withName(ATTRIBUTE_NAME)
43+
.withRefSemantic(generator.refSemantic(AssetInformation.class, ATTRIBUTE_NAME));
44+
List<AttributeType> attributes = new ArrayList<>();
45+
for (IdentifierKeyValuePair element : value) {
46+
AttributeType.Builder builder = AttributeType.builder()
47+
.withName(ATTRIBUTE_NAME + (value.size() > 1 ? "_" + (attributes.size() + 1) : ""));
48+
for (PropertyDescriptor property : AasUtils.getAasProperties(element.getClass())) {
49+
if (!skipProperty(property)) {
50+
context.with(property)
51+
.map(property.getReadMethod().getGenericReturnType(),
52+
getElemenetPropertyValue(element, property, context),
53+
generator.with(builder));
54+
}
55+
}
56+
attributes.add(builder.build());
57+
}
58+
attributes.forEach(x -> wrapperBuilder.addAttribute(x));
59+
generator.add(wrapperBuilder.build());
60+
}
61+
62+
protected Object getElemenetPropertyValue(IdentifierKeyValuePair elemenet, PropertyDescriptor property, MappingContext context) throws MappingException {
63+
try {
64+
return property.getReadMethod().invoke(elemenet);
65+
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
66+
throw new MappingException("failed to get property value for property " + property.getName(), ex);
67+
}
68+
}
69+
}

dataformat-aml/src/test/java/io/adminshell/aas/v3/dataformat/aml/deserialize/AmlDeserializerTest.java

Lines changed: 56 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818
import io.adminshell.aas.v3.dataformat.DeserializationException;
1919
import io.adminshell.aas.v3.dataformat.aml.AmlDeserializer;
2020
import io.adminshell.aas.v3.dataformat.aml.fixtures.FullExample;
21+
import io.adminshell.aas.v3.dataformat.aml.fixtures.SimpleExample;
2122
import io.adminshell.aas.v3.dataformat.core.AASFull;
23+
import io.adminshell.aas.v3.dataformat.core.AASSimple;
2224
import io.adminshell.aas.v3.model.*;
2325

2426
import java.io.FileNotFoundException;
@@ -27,7 +29,6 @@
2729
import java.util.List;
2830
import java.util.stream.Collectors;
2931

30-
import org.junit.Before;
3132
import org.junit.Test;
3233

3334
import static org.junit.Assert.assertEquals;
@@ -36,18 +37,29 @@ public class AmlDeserializerTest {
3637

3738
private final AmlDeserializer deserializer = new AmlDeserializer();
3839

39-
private AssetAdministrationShellEnvironment actual;
40-
private AssetAdministrationShellEnvironment expected;
40+
@Test
41+
public void testSAPFullExample() throws FileNotFoundException, DeserializationException {
42+
AssetAdministrationShellEnvironment actual = deserializer.read(FullExample.FILE);
43+
AssetAdministrationShellEnvironment expected = AASFull.createEnvironment();
44+
//some changes on the Full Example environment are necessary because there are some constructs inside which are
45+
//not possible with AML due to the mapping specifications
4146

42-
@Before
43-
public void init() throws FileNotFoundException, DeserializationException {
44-
actual = deserializer.read(FullExample.FILE);
45-
expected = AASFull.createEnvironment();
47+
//remove asset administration shells with no submodels
48+
adaptAssetAdministrationShells(expected);
49+
//remove leveltypes and valuelists from embedded dataspecification
50+
adaptConceptDescriptions(expected);
51+
//remove non referenced submodels
52+
adaptSubmodels(expected);
53+
//swap the idx of two submodels because assertEquals checks also the order of the elements
54+
swapSubmodelIdx(actual, 0, 2);
55+
assertEquals(expected, actual);
4656
}
4757

4858
@Test
49-
public void testSAPFullExample() {
50-
//some changes on the Full Example environment are necessary because there are some constructs inside which are
59+
public void testSAPSimpleExample() throws FileNotFoundException, DeserializationException {
60+
AssetAdministrationShellEnvironment actual = deserializer.read(SimpleExample.FILE);
61+
AssetAdministrationShellEnvironment expected = AASSimple.createEnvironment();
62+
//some changes on the Simple Example environment are necessary because there are some constructs inside which are
5163
//not possible with AML due to the mapping specifications
5264

5365
//remove asset administration shells with no submodels
@@ -57,64 +69,82 @@ public void testSAPFullExample() {
5769
//remove non referenced submodels
5870
adaptSubmodels(expected);
5971
//swap the idx of two submodels because assertEquals checks also the order of the elements
60-
swapSubmodelIdx(actual,0,2);
72+
swapSubmodelIdx(expected, 1, 2);
73+
// remove assets as they are not part of the current AML specification
74+
removeAssets(expected);
75+
adaptAssetInformation(expected);
6176
assertEquals(expected, actual);
6277
}
6378

6479
@Test
65-
public void testSubmodels() {
80+
public void testSubmodels() throws FileNotFoundException, DeserializationException {
81+
AssetAdministrationShellEnvironment actual = deserializer.read(FullExample.FILE);
82+
AssetAdministrationShellEnvironment expected = AASFull.createEnvironment();
6683
adaptSubmodels(expected);
67-
swapSubmodelIdx(actual, 0,2);
68-
assertEquals(expected.getSubmodels(),actual.getSubmodels());
84+
swapSubmodelIdx(actual, 0, 2);
85+
assertEquals(expected.getSubmodels(), actual.getSubmodels());
6986
}
7087

71-
private void swapSubmodelIdx(AssetAdministrationShellEnvironment env, int idxSrc, int idxDest){
72-
Collections.swap(env.getSubmodels(),idxSrc,idxDest);
88+
private void swapSubmodelIdx(AssetAdministrationShellEnvironment env, int idxSrc, int idxDest) {
89+
Collections.swap(env.getSubmodels(), idxSrc, idxDest);
90+
}
91+
92+
private void adaptAssetInformation(AssetAdministrationShellEnvironment env) {
93+
// remove thumbnail as it is not defined in current AML specification
94+
env.getAssetAdministrationShells().forEach(x -> x.getAssetInformation().setDefaultThumbnail(null));
7395
}
7496

7597
private void adaptSubmodels(AssetAdministrationShellEnvironment env) {
7698
//non referenced submodels are not considered in AML
7799
List<String> submodelIds = new ArrayList<>();
78100
env.getAssetAdministrationShells().stream().forEach(
79101
x -> x.getSubmodels().stream()
80-
.forEach(y -> y.getKeys().stream().forEach(z ->submodelIds.add(z.getValue()))));
102+
.forEach(y -> y.getKeys().stream().forEach(z -> submodelIds.add(z.getValue()))));
81103

82104
List<Submodel> referencedSubmodels = env.getSubmodels().stream().filter(x -> submodelIds.contains(x.getIdentification().getIdentifier())).collect(Collectors.toList());
83105
env.setSubmodels(referencedSubmodels);
84106
}
85107

108+
private void removeAssets(AssetAdministrationShellEnvironment env) {
109+
env.getAssets().clear();
110+
}
111+
86112
@Test
87-
public void testAssetAdministrationShells() {
113+
public void testAssetAdministrationShells() throws FileNotFoundException, DeserializationException {
114+
AssetAdministrationShellEnvironment actual = deserializer.read(FullExample.FILE);
115+
AssetAdministrationShellEnvironment expected = AASFull.createEnvironment();
88116
adaptAssetAdministrationShells(expected);
89117
assertEquals(expected.getAssetAdministrationShells(), actual.getAssetAdministrationShells());
90118
}
91119

92-
private void adaptAssetAdministrationShells(AssetAdministrationShellEnvironment env){
120+
private void adaptAssetAdministrationShells(AssetAdministrationShellEnvironment env) {
93121
//Need to remove Asset Administration Shell which have no Submodels
94122
//they are not considered in AML due to the specification
95123
List<AssetAdministrationShell> nonEmptyShells = new ArrayList<>();
96-
for(AssetAdministrationShell aas : env.getAssetAdministrationShells()){
97-
if(aas.getSubmodels() != null && aas.getSubmodels().size() > 0){
124+
for (AssetAdministrationShell aas : env.getAssetAdministrationShells()) {
125+
if (aas.getSubmodels() != null && aas.getSubmodels().size() > 0) {
98126
nonEmptyShells.add(aas);
99127
}
100128
}
101129
env.setAssetAdministrationShells(nonEmptyShells);
102130
}
103131

104132
@Test
105-
public void testConceptDescriptions() {
133+
public void testConceptDescriptions() throws FileNotFoundException, DeserializationException {
134+
AssetAdministrationShellEnvironment actual = deserializer.read(FullExample.FILE);
135+
AssetAdministrationShellEnvironment expected = AASFull.createEnvironment();
106136
//Need to remove Level Types and Value Lists from embedded dataspecification
107137
//they are not considered in AML due to the specification
108138
adaptConceptDescriptions(expected);
109139
assertEquals(expected.getConceptDescriptions(), actual.getConceptDescriptions());
110140
}
111141

112-
private void adaptConceptDescriptions(AssetAdministrationShellEnvironment env){
142+
private void adaptConceptDescriptions(AssetAdministrationShellEnvironment env) {
113143
List<ConceptDescription> expectedConceptDescriptions = env.getConceptDescriptions();
114-
for(ConceptDescription c : expectedConceptDescriptions){
115-
for(EmbeddedDataSpecification embeddedDataSpecification : c.getEmbeddedDataSpecifications()){
116-
((DataSpecificationIEC61360)embeddedDataSpecification.getDataSpecificationContent()).setLevelTypes(new ArrayList<>());
117-
((DataSpecificationIEC61360)embeddedDataSpecification.getDataSpecificationContent()).setValueList(null);
144+
for (ConceptDescription c : expectedConceptDescriptions) {
145+
for (EmbeddedDataSpecification embeddedDataSpecification : c.getEmbeddedDataSpecifications()) {
146+
((DataSpecificationIEC61360) embeddedDataSpecification.getDataSpecificationContent()).setLevelTypes(new ArrayList<>());
147+
((DataSpecificationIEC61360) embeddedDataSpecification.getDataSpecificationContent()).setValueList(null);
118148
}
119149
}
120150

0 commit comments

Comments
 (0)