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

Commit 41daa48

Browse files
committed
Merge branch 'feature/aml' of https://jira.iais.fraunhofer.de/stash/scm/ear/aas-serializer into feature/aml
2 parents 2b54799 + 05e771a commit 41daa48

83 files changed

Lines changed: 20449 additions & 14296 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

dataformat-aml/pom.xml

Lines changed: 53 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -13,64 +13,55 @@
1313
<dependency>
1414
<groupId>io.admin-shell.aas</groupId>
1515
<artifactId>model</artifactId>
16-
<version>${model.version}</version>
16+
<version>${revision}</version>
1717
<scope>compile</scope>
1818
</dependency>
1919
<dependency>
2020
<groupId>io.admin-shell.aas</groupId>
2121
<artifactId>dataformat-core</artifactId>
22-
<version>${model.version}</version>
22+
<version>${revision}</version>
2323
<scope>compile</scope>
2424
</dependency>
2525
<dependency>
26-
<groupId>com.fasterxml.jackson.core</groupId>
27-
<artifactId>jackson-annotations</artifactId>
28-
<version>${jackson.version}</version>
29-
<scope>compile</scope>
26+
<groupId>com.google.guava</groupId>
27+
<artifactId>guava</artifactId>
28+
<version>30.1.1-jre</version>
3029
</dependency>
3130
<dependency>
32-
<groupId>com.fasterxml.jackson.core</groupId>
33-
<artifactId>jackson-databind</artifactId>
34-
<version>${jackson.version}</version>
31+
<groupId>org.slf4j</groupId>
32+
<artifactId>slf4j-api</artifactId>
33+
<version>${slf4j.version}</version>
3534
</dependency>
3635
<dependency>
37-
<groupId>com.fasterxml.jackson.dataformat</groupId>
38-
<artifactId>jackson-dataformat-xml</artifactId>
39-
<version>${jackson.version}</version>
36+
<groupId>javax.xml.bind</groupId>
37+
<artifactId>jaxb-api</artifactId>
38+
<version>${jaxb.version}</version>
4039
</dependency>
4140
<dependency>
42-
<groupId>ma.glasnost.orika</groupId>
43-
<artifactId>orika-core</artifactId>
44-
<version>${orika.version}</version>
41+
<groupId>org.eclipse.persistence</groupId>
42+
<artifactId>org.eclipse.persistence.moxy</artifactId>
43+
<version>${moxy.version}</version>
4544
</dependency>
46-
<dependency>
47-
<groupId>org.slf4j</groupId>
48-
<artifactId>slf4j-api</artifactId>
49-
<version>${slf4j.version}</version>
50-
</dependency>
5145
<dependency>
5246
<groupId>junit</groupId>
5347
<artifactId>junit</artifactId>
5448
<version>${junit.version}</version>
5549
<scope>test</scope>
56-
</dependency>
50+
</dependency>
5751
<dependency>
5852
<groupId>org.skyscreamer</groupId>
5953
<artifactId>jsonassert</artifactId>
6054
<version>${jsonassert.version}</version>
6155
<scope>test</scope>
62-
</dependency>
56+
</dependency>
57+
<dependency>
58+
<groupId>net.codesup.util</groupId>
59+
<artifactId>jaxb2-rich-contract-plugin</artifactId>
60+
<version>${jaxb-rich-contract.version}</version>
61+
</dependency>
6362
</dependencies>
6463
<build>
6564
<plugins>
66-
<plugin>
67-
<groupId>org.apache.maven.plugins</groupId>
68-
<artifactId>maven-compiler-plugin</artifactId>
69-
<configuration>
70-
<source>11</source>
71-
<target>11</target>
72-
</configuration>
73-
</plugin>
7465
<plugin>
7566
<groupId>org.codehaus.mojo</groupId>
7667
<artifactId>flatten-maven-plugin</artifactId>
@@ -95,6 +86,38 @@
9586
</execution>
9687
</executions>
9788
</plugin>
89+
<plugin>
90+
<groupId>org.apache.cxf</groupId>
91+
<artifactId>cxf-xjc-plugin</artifactId>
92+
<version>${plugin.cxf.version}</version>
93+
<configuration>
94+
<extensions>
95+
<extension>net.codesup.util:jaxb2-rich-contract-plugin:${jaxb-rich-contract.version}</extension>
96+
</extensions>
97+
</configuration>
98+
<executions>
99+
<execution>
100+
<id>generate-caex-classes</id>
101+
<phase>generate-sources</phase>
102+
<goals>
103+
<goal>xsdtojava</goal>
104+
</goals>
105+
<configuration>
106+
<sourceRoot>${basedir}/target/generated-sources/src</sourceRoot>
107+
<xsdOptions>
108+
<xsdOption>
109+
<xsd>${basedir}/src/main/resources/CAEX_ClassModel_V2.15.xsd</xsd>
110+
<packagename>io.adminshell.aas.v3.dataformat.aml.model.caex</packagename>
111+
<extensionArgs>
112+
<extensionArg>-Xfluent-builder</extensionArg>
113+
<extensionArg>-Ximmutable</extensionArg>
114+
</extensionArgs>
115+
</xsdOption>
116+
</xsdOptions>
117+
</configuration>
118+
</execution>
119+
</executions>
120+
</plugin>
98121
</plugins>
99122
</build>
100123
<repositories>
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
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.header.AutomationMLVersion;
19+
import io.adminshell.aas.v3.dataformat.aml.header.WriterHeader;
20+
import io.adminshell.aas.v3.dataformat.aml.mapper.AssetAdministrationShellEnvironmentMapper;
21+
import io.adminshell.aas.v3.dataformat.aml.mapper.ConstraintCollectionMapper;
22+
import io.adminshell.aas.v3.dataformat.aml.mapper.DataSpecificationContentMapper;
23+
import io.adminshell.aas.v3.dataformat.aml.mapper.DataSpecificationIEC61360Mapper;
24+
import io.adminshell.aas.v3.dataformat.aml.mapper.DefaultCollectionMapper;
25+
import io.adminshell.aas.v3.dataformat.aml.mapper.DefaultMapper;
26+
import io.adminshell.aas.v3.dataformat.aml.mapper.EmbeddedDataSpecificationCollectionMapper;
27+
import io.adminshell.aas.v3.dataformat.aml.mapper.FileMapper;
28+
import io.adminshell.aas.v3.dataformat.aml.mapper.LangStringCollectionMapper;
29+
import io.adminshell.aas.v3.dataformat.aml.mapper.MappingException;
30+
import io.adminshell.aas.v3.dataformat.aml.mapper.OperationVariableCollectionMapper;
31+
import io.adminshell.aas.v3.dataformat.aml.mapper.OperationVariableMapper;
32+
import io.adminshell.aas.v3.dataformat.aml.mapper.QualifierMapper;
33+
import io.adminshell.aas.v3.dataformat.aml.mapper.ReferenceCollectionMapper;
34+
import io.adminshell.aas.v3.dataformat.aml.mapper.ReferenceElementMapper;
35+
import io.adminshell.aas.v3.dataformat.aml.mapper.ReferenceMapper;
36+
import io.adminshell.aas.v3.dataformat.aml.mapper.RelationshipElementMapper;
37+
import io.adminshell.aas.v3.dataformat.aml.mapper.SubmodelCollectionMapper;
38+
import io.adminshell.aas.v3.dataformat.aml.mapper.SubmodelMapper;
39+
import io.adminshell.aas.v3.dataformat.aml.model.caex.CAEXFile;
40+
import io.adminshell.aas.v3.model.AssetAdministrationShellEnvironment;
41+
import io.adminshell.aas.v3.model.LangString;
42+
import io.adminshell.aas.v3.model.Referable;
43+
import java.util.List;
44+
import org.slf4j.LoggerFactory;
45+
46+
public class AasToAmlMapper {
47+
48+
public static final String DEFAULT_SCHEMA_VERSION = "2.15";
49+
public static final String DEFAULT_AML_VERSION = "2.0";
50+
public static final String DEFAULT_FILENAME = "AssetAdministrationShellEnvironment.aml";
51+
private static final org.slf4j.Logger log = LoggerFactory.getLogger(AasToAmlMapper.class);
52+
private static final String DEFAULT_LANGUAGE = "EN";
53+
private CAEXFile result;
54+
55+
public CAEXFile map(AssetAdministrationShellEnvironment env) throws MappingException {
56+
return map(env, DEFAULT_SCHEMA_VERSION, DEFAULT_FILENAME);
57+
}
58+
59+
public CAEXFile map(AssetAdministrationShellEnvironment env, String schemaVersion, String filename) throws MappingException {
60+
AbstractClassNamingStrategy classNamingStrategy = new NumberingClassNamingStrategy();
61+
classNamingStrategy.registerCustomNaming(LangString.class, x -> "aml-lang=" + x.getLanguage());
62+
PropertyNamingStrategy propertyNamingStrategy = new PropertyNamingStrategy();
63+
propertyNamingStrategy.registerCustomNaming(Referable.class, "descriptions", "description");
64+
MappingProvider mappingProvider = new MappingProvider(
65+
new DefaultMapper(),
66+
new DefaultCollectionMapper(),
67+
List.of(
68+
new AssetAdministrationShellEnvironmentMapper(),
69+
new SubmodelCollectionMapper(),
70+
new LangStringCollectionMapper(),
71+
new ReferenceMapper(),
72+
new OperationVariableMapper(),
73+
new OperationVariableCollectionMapper(),
74+
new ReferenceCollectionMapper(),
75+
new ConstraintCollectionMapper(),
76+
new QualifierMapper(),
77+
new FileMapper(),
78+
new SubmodelMapper(),
79+
new EmbeddedDataSpecificationCollectionMapper(),
80+
new DataSpecificationContentMapper(),
81+
new ReferenceElementMapper(),
82+
new RelationshipElementMapper(),
83+
new DataSpecificationIEC61360Mapper()),
84+
classNamingStrategy,
85+
propertyNamingStrategy
86+
);
87+
// FIX
88+
// ReferenceElement and RelationshipElement reference other Referables.
89+
// Each such reference is represented as an InternalLink in AML.
90+
// InternalLinks require target to be an interface but AAS AML serialization
91+
// does not define creation of such interfaces. Therefore, we do a preprocessing
92+
// step to identify all Referable which are targeted by such a reference
93+
// to later add a generic interface to them upon serialization
94+
95+
// NOTE
96+
// This has implications on ID generator and requires additional lookup table
97+
// 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"));
102+
WriterHeader writerHeader = new WriterHeader();
103+
writerHeader.setName("foo");
104+
writerHeader.setId("bar");
105+
context.getFileBuilder().withAdditionalInformation(writerHeader.wrap());
106+
context.map(env);
107+
return context.getFileBuilder().build();
108+
}
109+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
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 com.google.common.reflect.TypeToken;
19+
import io.adminshell.aas.v3.dataformat.aml.util.TypeUtils;
20+
import io.adminshell.aas.v3.model.LangString;
21+
import io.adminshell.aas.v3.model.Referable;
22+
import java.lang.reflect.Type;
23+
import java.util.ArrayList;
24+
import java.util.HashMap;
25+
import java.util.List;
26+
import java.util.Map;
27+
import java.util.Objects;
28+
import java.util.Optional;
29+
import java.util.function.BiFunction;
30+
import java.util.function.Function;
31+
32+
public abstract class AbstractClassNamingStrategy implements NamingStrategy {
33+
34+
protected final boolean preferIdShort;
35+
protected Map<Object, String> cache = new HashMap<>();
36+
protected List<TypeSafeFunction> customNamings = new ArrayList<>();
37+
38+
private class TypeSafeFunction<T> {
39+
40+
public TypeSafeFunction(Class<T> inputType, BiFunction<T, String, String> provider) {
41+
this.inputType = TypeToken.of(inputType);
42+
this.provider = provider;
43+
}
44+
TypeToken inputType;
45+
BiFunction<T, String, String> provider;
46+
}
47+
48+
public <T> void registerCustomNaming(Class<T> type, Function<T, String> provider) {
49+
customNamings.add(new TypeSafeFunction(type, (x, y) -> provider.apply((T) x)));
50+
}
51+
52+
public <T> void registerCustomNaming(Class<T> type, BiFunction<T, String, String> provider) {
53+
customNamings.add(new TypeSafeFunction(type, provider));
54+
}
55+
56+
private Optional<TypeSafeFunction> getCustomNaming(Type type) {
57+
return customNamings.stream()
58+
.filter(x -> x.inputType.isSupertypeOf(type))
59+
.sorted((x, y) -> Objects.compare(x.inputType, y.inputType, new TypeUtils.TypeTokenComparator()))
60+
.findFirst();
61+
}
62+
63+
protected AbstractClassNamingStrategy() {
64+
this(true);
65+
}
66+
67+
protected AbstractClassNamingStrategy(boolean preferIdShort) {
68+
this.preferIdShort = preferIdShort;
69+
}
70+
71+
public String getName(Type type, Object obj, String property) {
72+
if (cache.containsKey(obj)) {
73+
return cache.get(obj);
74+
}
75+
String result = null;
76+
if (preferIdShort && Referable.class.isAssignableFrom(obj.getClass())) {
77+
Referable referable = (Referable) obj;
78+
if (referable.getIdShort() != null && !referable.getIdShort().isEmpty()) {
79+
result = referable.getIdShort();
80+
}
81+
}
82+
if (result == null) {
83+
Optional<TypeSafeFunction> customNaming = getCustomNaming(type);
84+
if (customNaming.isPresent()) {
85+
result = customNaming.get().provider.apply(obj, property).toString();
86+
}
87+
}
88+
if (result == null) {
89+
result = generateName(obj);
90+
}
91+
cache.put(obj, result);
92+
return result;
93+
}
94+
95+
protected abstract String generateName(Object obj);
96+
}

0 commit comments

Comments
 (0)