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

Commit 2ef64f3

Browse files
committed
refactoring AML serializer
1 parent d9347f1 commit 2ef64f3

37 files changed

Lines changed: 3200 additions & 330 deletions

dataformat-aml/pom.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,18 @@
5959
<artifactId>jaxb2-rich-contract-plugin</artifactId>
6060
<version>${jaxb-rich-contract.version}</version>
6161
</dependency>
62+
<dependency>
63+
<groupId>org.xmlunit</groupId>
64+
<artifactId>xmlunit-core</artifactId>
65+
<version>${xmlunit.version}</version>
66+
<scope>test</scope>
67+
</dependency>
68+
<dependency>
69+
<groupId>org.xmlunit</groupId>
70+
<artifactId>xmlunit-matchers</artifactId>
71+
<version>${xmlunit.version}</version>
72+
<scope>test</scope>
73+
</dependency>
6274
</dependencies>
6375
<build>
6476
<plugins>

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

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ public class AasToAmlMapper {
5151
private static final org.slf4j.Logger log = LoggerFactory.getLogger(AasToAmlMapper.class);
5252
private static final String DEFAULT_LANGUAGE = "EN";
5353
private CAEXFile result;
54+
private final AmlSerializationConfig config;
55+
56+
public AasToAmlMapper(AmlSerializationConfig config) {
57+
this.config = config;
58+
}
5459

5560
public CAEXFile map(AssetAdministrationShellEnvironment env) throws MappingException {
5661
return map(env, DEFAULT_SCHEMA_VERSION, DEFAULT_FILENAME);
@@ -95,15 +100,17 @@ public CAEXFile map(AssetAdministrationShellEnvironment env, String schemaVersio
95100
// NOTE
96101
// This has implications on ID generator and requires additional lookup table
97102
// for Referable --> AML ID of ExternalInterface
98-
MappingContext context = new MappingContext(mappingProvider, env);
99-
context.getFileBuilder().withSchemaVersion(schemaVersion);
100-
context.getFileBuilder().withFileName(filename);
101-
context.getFileBuilder().withAdditionalInformation(new AutomationMLVersion("2.0"));
103+
MappingContext context = new MappingContext(mappingProvider, config.getIdGenerator(), env);
102104
WriterHeader writerHeader = new WriterHeader();
103105
writerHeader.setName("foo");
104106
writerHeader.setId("bar");
105-
context.getFileBuilder().withAdditionalInformation(writerHeader.wrap());
106-
context.map(env);
107-
return context.getFileBuilder().build();
107+
CAEXFile.Builder builder = CAEXFile.builder()
108+
.withSchemaVersion(schemaVersion)
109+
.withFileName(filename)
110+
.addAdditionalInformation(new AutomationMLVersion("2.0"))
111+
.addAdditionalInformation(writerHeader.wrap());
112+
AmlGenerator generator = new AmlGenerator(builder);
113+
context.map(env, generator);
114+
return builder.build();
108115
}
109116
}
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
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;
17+
18+
import io.adminshell.aas.v3.dataformat.aml.model.caex.AttributeType;
19+
import io.adminshell.aas.v3.dataformat.aml.model.caex.CAEXFile;
20+
import io.adminshell.aas.v3.dataformat.aml.model.caex.CAEXObject;
21+
import io.adminshell.aas.v3.dataformat.aml.model.caex.InternalElementType;
22+
import io.adminshell.aas.v3.dataformat.aml.model.caex.RoleClassType;
23+
import io.adminshell.aas.v3.dataformat.aml.model.caex.SystemUnitClassType;
24+
import io.adminshell.aas.v3.model.Referable;
25+
import java.util.List;
26+
import org.slf4j.Logger;
27+
import org.slf4j.LoggerFactory;
28+
29+
public class AmlGenerator {
30+
31+
private static final Logger log = LoggerFactory.getLogger(AmlGenerator.class);
32+
private CAEXObject.Builder current;
33+
private CAEXFile.Builder fileBuilder;
34+
35+
public AmlGenerator() {
36+
this.fileBuilder = CAEXFile.builder();
37+
}
38+
39+
public AmlGenerator(CAEXFile.Builder fileBuilder) {
40+
this.fileBuilder = fileBuilder;
41+
}
42+
43+
private AmlGenerator(CAEXFile.Builder fileBuilder, CAEXObject.Builder current) {
44+
this.fileBuilder = fileBuilder;
45+
this.current = current;
46+
}
47+
48+
public AmlGenerator with(CAEXObject.Builder current) {
49+
return new AmlGenerator(fileBuilder, current);
50+
}
51+
52+
public void addAdditionalInformation(List<Object> additionalInformation) {
53+
fileBuilder.addAdditionalInformation(additionalInformation);
54+
}
55+
56+
public void addAttribute(AttributeType attribute) {
57+
if (attribute == null) {
58+
return;
59+
}
60+
if (AttributeType.Builder.class.isAssignableFrom(current.getClass())) {
61+
AttributeType.Builder builder = (AttributeType.Builder) current;
62+
builder.addAttribute(attribute);
63+
} else if (InternalElementType.Builder.class.isAssignableFrom(current.getClass())) {
64+
InternalElementType.Builder builder = (InternalElementType.Builder) current;
65+
builder.addAttribute(attribute);
66+
} else {
67+
log.warn("adding attribute failed because no parent builder defined");
68+
}
69+
}
70+
71+
public void addInternalLink(SystemUnitClassType.InternalLink internalLink) {
72+
if (internalLink == null) {
73+
return;
74+
}
75+
if (InternalElementType.Builder.class.isAssignableFrom(current.getClass())) {
76+
InternalElementType.Builder builder = (InternalElementType.Builder) current;
77+
builder.addInternalLink(internalLink);
78+
} else {
79+
log.warn("adding internal link failed because no parent builder defined");
80+
}
81+
}
82+
83+
public void addExternalInterface(RoleClassType.ExternalInterface externalInterface) {
84+
if (externalInterface == null) {
85+
return;
86+
}
87+
if (InternalElementType.Builder.class.isAssignableFrom(current.getClass())) {
88+
InternalElementType.Builder builder = (InternalElementType.Builder) current;
89+
builder.addExternalInterface(externalInterface);
90+
} else {
91+
log.warn("adding external interface failed because no parent builder defined");
92+
}
93+
}
94+
95+
public void addSystemUnitClassLib(CAEXFile.SystemUnitClassLib systemUnitClassLib) {
96+
if (systemUnitClassLib == null) {
97+
return;
98+
}
99+
if (fileBuilder != null) {
100+
fileBuilder = fileBuilder.addSystemUnitClassLib(systemUnitClassLib);
101+
}
102+
}
103+
104+
public void addInstanceHierarchy(CAEXFile.InstanceHierarchy instanceHierarchy) {
105+
if (instanceHierarchy == null) {
106+
return;
107+
}
108+
if (fileBuilder != null) {
109+
fileBuilder = fileBuilder.addInstanceHierarchy(instanceHierarchy);
110+
}
111+
}
112+
113+
public void addInternalElement(InternalElementType internalElement) {
114+
if (internalElement == null) {
115+
return;
116+
}
117+
if (InternalElementType.Builder.class.isAssignableFrom(current.getClass())) {
118+
InternalElementType.Builder builder = (InternalElementType.Builder) current;
119+
builder.addInternalElement(internalElement);
120+
} else if (CAEXFile.InstanceHierarchy.Builder.class.isAssignableFrom(current.getClass())) {
121+
CAEXFile.InstanceHierarchy.Builder builder = (CAEXFile.InstanceHierarchy.Builder) current;
122+
builder.addInternalElement(internalElement);
123+
} else {
124+
log.warn("adding internalElement failed because no parent builder defined");
125+
}
126+
}
127+
128+
public void appendReferenceTargetInterfaceIfRequired(Object obj, MappingContext context) {
129+
RoleClassType.ExternalInterface referenceTargetInterface = getReferenceTargetInterface(obj, context);
130+
if (referenceTargetInterface != null) {
131+
addExternalInterface(referenceTargetInterface);
132+
}
133+
}
134+
135+
public RoleClassType.ExternalInterface getReferenceTargetInterface(Object obj, MappingContext context) {
136+
RoleClassType.ExternalInterface result = null;
137+
if (obj != null && Referable.class.isAssignableFrom(obj.getClass())) {
138+
Referable referable = (Referable) obj;
139+
if (context.isTargetOfInternalLink(referable)) {
140+
result = RoleClassType.ExternalInterface.builder()
141+
.withID(context.generateId())
142+
.withName("externalReferenceTarget")
143+
.withRefBaseClassPath("AutomationMLInterfaceClassLib/AutomationMLBaseInterface")
144+
.build();
145+
}
146+
}
147+
return result;
148+
}
149+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
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;
17+
18+
import java.util.ArrayList;
19+
import java.util.Arrays;
20+
import java.util.List;
21+
22+
public class AmlSerializationConfig {
23+
24+
private final boolean includeLibraries;
25+
private final IdGenerator idGenerator;
26+
private final List<Object> additionalInformation;
27+
public static final AmlSerializationConfig DEFAULT = new Builder().build();
28+
29+
public static Builder builder() {
30+
return new Builder();
31+
}
32+
33+
private AmlSerializationConfig(boolean includeLibraries, IdGenerator idGenerator, List<Object> additionalInformation) {
34+
this.includeLibraries = includeLibraries;
35+
this.idGenerator = idGenerator;
36+
this.additionalInformation = additionalInformation;
37+
}
38+
39+
public boolean isIncludeLibraries() {
40+
return includeLibraries;
41+
}
42+
43+
public IdGenerator getIdGenerator() {
44+
return idGenerator;
45+
}
46+
47+
public List<Object> getAdditionalInformation() {
48+
return additionalInformation;
49+
}
50+
51+
public static class Builder {
52+
53+
private boolean includeLibraries = true;
54+
private IdGenerator idGenerator = new UuidGenerator();
55+
private List<Object> additionalInformation = new ArrayList<>();
56+
57+
public AmlSerializationConfig build() {
58+
return new AmlSerializationConfig(includeLibraries, idGenerator, additionalInformation);
59+
}
60+
61+
public Builder includeLibraries() {
62+
this.includeLibraries = true;
63+
return this;
64+
}
65+
66+
public Builder excludeLibraries() {
67+
this.includeLibraries = true;
68+
return this;
69+
}
70+
71+
public Builder idGenerator(IdGenerator idGenerator) {
72+
this.idGenerator = idGenerator;
73+
return this;
74+
}
75+
76+
public Builder additionalInformation(Object... values) {
77+
this.additionalInformation.addAll(Arrays.asList(values));
78+
return this;
79+
}
80+
}
81+
}

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

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,26 +35,20 @@ public class AmlSerializer implements Serializer {
3535

3636
private static final String AAS_LIB_SOURCE = "/AssetAdministrationShellLib.aml";
3737
private static final Logger log = LoggerFactory.getLogger(AmlSerializer.class);
38-
private AasToAmlMapper mapper = new AasToAmlMapper();
39-
40-
private boolean enableClassLibs = false;
4138

4239
public AmlSerializer() {
4340
}
4441

45-
public AmlSerializer(boolean enableClassLibs) {
46-
this.enableClassLibs = enableClassLibs;
47-
}
48-
4942
@Override
5043
public String write(AssetAdministrationShellEnvironment aasEnvironment) throws SerializationException {
51-
return write(aasEnvironment, true);
44+
return write(aasEnvironment, AmlSerializationConfig.DEFAULT);
5245
}
5346

54-
public String write(AssetAdministrationShellEnvironment aasEnvironment, boolean withLibraries) throws SerializationException {
47+
public String write(AssetAdministrationShellEnvironment aasEnvironment, AmlSerializationConfig config) throws SerializationException {
48+
AasToAmlMapper mapper = new AasToAmlMapper(config);
5549
try {
5650
CAEXFile aml = mapper.map(aasEnvironment);
57-
if (withLibraries) {
51+
if (config.isIncludeLibraries()) {
5852
aml = addAASLibrary(aml);
5953
}
6054
Marshaller marshaller = JAXBContextFactory.createContext(
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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;
17+
18+
public interface IdGenerator {
19+
20+
public String generateId();
21+
}

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

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,35 +17,35 @@
1717

1818
import java.util.HashMap;
1919
import java.util.Map;
20-
import java.util.UUID;
2120

2221
public class IdentityProvider {
2322

24-
private Map<Object, String> ids = new HashMap<>();
23+
private final Map<Object, String> cache;
24+
private final IdGenerator idGenerator;
2525

26-
public String getId(Object obj) {
27-
// if (ids.containsKey(obj)) {
28-
// return ids.get(obj);
29-
// }
30-
String result = generateId();
31-
// ids.put(obj, result);
32-
return result;
26+
public IdentityProvider(IdGenerator idGenerator) {
27+
this.cache = new HashMap<>();
28+
this.idGenerator = idGenerator;
3329
}
3430

3531
public String getCachedId(Object obj) {
36-
if (ids.containsKey(obj)) {
37-
return ids.get(obj);
32+
if (cache.containsKey(obj)) {
33+
return cache.get(obj);
3834
}
3935
String result = generateId();
40-
ids.put(obj, result);
36+
cache.put(obj, result);
4137
return result;
4238
}
4339

4440
public String generateId() {
4541
String result = null;
4642
do {
47-
result = UUID.randomUUID().toString();
48-
} while (ids.entrySet().contains(result));
43+
result = idGenerator.generateId();
44+
} while (cache.values().contains(result));
4945
return result;
5046
}
47+
48+
public IdGenerator getIdGenerator() {
49+
return idGenerator;
50+
}
5151
}

0 commit comments

Comments
 (0)