diff --git a/dataformat-core/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/core/Examples.java b/dataformat-core/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/core/Examples.java index d8bc3ef3b..4a0fc95f8 100644 --- a/dataformat-core/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/core/Examples.java +++ b/dataformat-core/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/core/Examples.java @@ -17,15 +17,23 @@ import org.eclipse.digitaltwin.aas4j.v3.model.AssetKind; import org.eclipse.digitaltwin.aas4j.v3.model.DataTypeDefXsd; +import org.eclipse.digitaltwin.aas4j.v3.model.DataTypeIec61360; +import org.eclipse.digitaltwin.aas4j.v3.model.DefaultDummyDataSpecification; import org.eclipse.digitaltwin.aas4j.v3.model.Environment; import org.eclipse.digitaltwin.aas4j.v3.model.KeyTypes; import org.eclipse.digitaltwin.aas4j.v3.model.ReferenceTypes; import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultAssetAdministrationShell; import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultAssetInformation; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultDataSpecificationIec61360; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultEmbeddedDataSpecification; import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultEnvironment; import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultExtension; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultFile; import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultKey; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultLangStringDefinitionTypeIec61360; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultLangStringNameType; import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultReference; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultSubmodel; public class Examples { @@ -77,4 +85,57 @@ public class Examples { .build()) .build()) .build(); + + + public static final Environment ENVIRONMENT_WITH_DUMMYDATASPEC = new DefaultEnvironment.Builder() + .submodels( + new DefaultSubmodel.Builder() + .id("urn:test") + .submodelElements(new DefaultFile.Builder() + .idShort("myIdShort").value("FileValue") + .build()) + .embeddedDataSpecifications( + new DefaultEmbeddedDataSpecification.Builder() + .dataSpecificationContent( + new DefaultDummyDataSpecification.Builder() + .name(new DefaultLangStringNameType.Builder() + .language("en").text("myName").build()) + .text("myText") + .pages(42) + .build()) + .dataSpecification( + new DefaultReference.Builder() + .type(ReferenceTypes.EXTERNAL_REFERENCE) + .keys( + new DefaultKey.Builder() + .type(KeyTypes.GLOBAL_REFERENCE) + .value("https://admin-shell.io/aas/3/0/CustomDataSpecification") + .build() + ) + .build() + ) + .build()) + .embeddedDataSpecifications( + new DefaultEmbeddedDataSpecification.Builder().dataSpecificationContent( + new DefaultDataSpecificationIec61360.Builder() + .dataType(DataTypeIec61360.BLOB) + .definition(new DefaultLangStringDefinitionTypeIec61360.Builder() + .language("en").text("myDefinition") + .build()) + .build() + ) + .dataSpecification( + new DefaultReference.Builder() + .type(ReferenceTypes.EXTERNAL_REFERENCE) + .keys( + new DefaultKey.Builder() + .type(KeyTypes.GLOBAL_REFERENCE) + .value("https://admin-shell.io/aas/3/0/RC02/DataSpecificationIec61360") + .build() + ) + .build() + ) + .build()) + .build() + ).build(); } diff --git a/dataformat-core/src/test/java/org/eclipse/digitaltwin/aas4j/v3/model/DefaultDummyDataSpecification.java b/dataformat-core/src/test/java/org/eclipse/digitaltwin/aas4j/v3/model/DefaultDummyDataSpecification.java new file mode 100644 index 000000000..8bd13c738 --- /dev/null +++ b/dataformat-core/src/test/java/org/eclipse/digitaltwin/aas4j/v3/model/DefaultDummyDataSpecification.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2023 SAP SE or an SAP affiliate company. + * + * 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 org.eclipse.digitaltwin.aas4j.v3.model; + +import java.util.Objects; + +/** + * This interface is needed to test the serialization/deserialization of a custom data specification content. + * See: https://github.com/eclipse-aas4j/aas4j/issues/196 + */ +public class DefaultDummyDataSpecification implements DummyDataSpecification { + private LangStringNameType name; + private String text; + private int pages; + + public LangStringNameType getName() { + return name; + } + + public void setName(LangStringNameType name) { + this.name = name; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public int getPages() { + return pages; + }; + public void setPages(int pages) { + this.pages = pages; + } + + @Override + public int hashCode() { + return Objects.hash(this.name, this.text, this.pages); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (obj == null) { + return false; + } else if (this.getClass() != obj.getClass()) { + return false; + } else { + DefaultDummyDataSpecification other = (DefaultDummyDataSpecification) obj; + return Objects.equals(this.name, other.name) && + Objects.equals(this.text, other.text) && + Objects.equals(this.pages, other.pages); + } + } + + /** + * This builder class can be used to construct a DefaultCustomDataSpecificationContent. + */ + public static class Builder extends DummyDataSpecificationBuilder { + + @Override + protected DefaultDummyDataSpecification.Builder getSelf() { + return this; + } + + @Override + protected DefaultDummyDataSpecification newBuildingInstance() { + return new DefaultDummyDataSpecification(); + } + } +} diff --git a/dataformat-core/src/test/java/org/eclipse/digitaltwin/aas4j/v3/model/DummyDataSpecification.java b/dataformat-core/src/test/java/org/eclipse/digitaltwin/aas4j/v3/model/DummyDataSpecification.java new file mode 100644 index 000000000..349ea00e5 --- /dev/null +++ b/dataformat-core/src/test/java/org/eclipse/digitaltwin/aas4j/v3/model/DummyDataSpecification.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2023 SAP SE or an SAP affiliate company. + * + * 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 org.eclipse.digitaltwin.aas4j.v3.model; + +/** + * This interface is needed to test the serialization/deserialization of a custom data specification content. + * See: https://github.com/eclipse-aas4j/aas4j/issues/196 + */ +public interface DummyDataSpecification extends CustomDataSpecification { + + LangStringNameType getName(); + + void setName(LangStringNameType name); + + + String getText(); + + void setText(String text); + + + int getPages(); + + void setPages(int pages); +} diff --git a/dataformat-core/src/test/java/org/eclipse/digitaltwin/aas4j/v3/model/DummyDataSpecificationBuilder.java b/dataformat-core/src/test/java/org/eclipse/digitaltwin/aas4j/v3/model/DummyDataSpecificationBuilder.java new file mode 100644 index 000000000..490ae42f7 --- /dev/null +++ b/dataformat-core/src/test/java/org/eclipse/digitaltwin/aas4j/v3/model/DummyDataSpecificationBuilder.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2023 SAP SE or an SAP affiliate company. + * + * 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 org.eclipse.digitaltwin.aas4j.v3.model; + +import org.eclipse.digitaltwin.aas4j.v3.model.builder.ExtendableBuilder; + +/** + * This interface is needed to test the serialization/deserialization of a custom data specification content. + * + * See: https://github.com/eclipse-aas4j/aas4j/issues/196 + */ +public abstract class DummyDataSpecificationBuilder> extends ExtendableBuilder { + + public B name(LangStringNameType name) { + getBuildingInstance().setName(name); + return getSelf(); + } + + public B text(String text) { + getBuildingInstance().setText(text); + return getSelf(); + } + + public B pages(int pages) { + getBuildingInstance().setPages(pages); + return getSelf(); + } +} \ No newline at end of file diff --git a/dataformat-json/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonSerializerTest.java b/dataformat-json/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonSerializerTest.java index bc4597532..dfd22388a 100644 --- a/dataformat-json/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonSerializerTest.java +++ b/dataformat-json/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonSerializerTest.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e. V. + * Copyright (C) 2023 SAP SE or an SAP affiliate company. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,10 +19,14 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.DeserializationException; import org.eclipse.digitaltwin.aas4j.v3.dataformat.SerializationException; import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.AASSimple; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper; import org.eclipse.digitaltwin.aas4j.v3.dataformat.json.util.ExampleData; import org.eclipse.digitaltwin.aas4j.v3.dataformat.json.util.Examples; +import org.eclipse.digitaltwin.aas4j.v3.model.DataSpecificationContent; +import org.eclipse.digitaltwin.aas4j.v3.model.DefaultDummyDataSpecification; import org.eclipse.digitaltwin.aas4j.v3.model.Environment; import org.eclipse.digitaltwin.aas4j.v3.model.Referable; import org.json.JSONException; @@ -40,6 +45,7 @@ import java.util.Set; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; public class JsonSerializerTest { @@ -91,6 +97,33 @@ public void testSerializeEmptyReferableList() throws SerializationException { assertEquals("[]", serialized); } + /** + * This test ensures that future DataSpecificationContents can be added without adjustments in the code. + * + * @throws SerializationException + * @throws DeserializationException + */ + @Test + public void testSerializeCustomDataSpecification() throws SerializationException, DeserializationException { + JsonSerializer serializer = new JsonSerializer(); + JsonDeserializer deserializer = new JsonDeserializer(); + + // This is the only way to make the serialization to work. + Set> subtypes = ReflectionHelper.SUBTYPES.get(DataSpecificationContent.class); + subtypes.add(DefaultDummyDataSpecification.class); + + Environment origin = org.eclipse.digitaltwin.aas4j.v3.dataformat.core.Examples.ENVIRONMENT_WITH_DUMMYDATASPEC ; + + String jsonString = serializer.write(origin); + assertNotNull(jsonString); + + Environment copy = deserializer.read(jsonString); + assertNotNull(copy); + + assertTrue(origin.equals(copy)); + } + + private void validateAndCompare(ExampleData exampleData) throws IOException, SerializationException, JSONException { String expected = exampleData.fileContent(); String actual = new JsonSerializer().write(exampleData.getModel()); diff --git a/dataformat-xml/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/deserialization/EmbeddedDataSpecificationsDeserializer.java b/dataformat-xml/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/deserialization/EmbeddedDataSpecificationsDeserializer.java index 7aa3b263b..ea0b54ff6 100644 --- a/dataformat-xml/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/deserialization/EmbeddedDataSpecificationsDeserializer.java +++ b/dataformat-xml/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/deserialization/EmbeddedDataSpecificationsDeserializer.java @@ -16,22 +16,22 @@ package org.eclipse.digitaltwin.aas4j.v3.dataformat.xml.deserialization; import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; -import org.eclipse.digitaltwin.aas4j.v3.model.DataSpecificationIec61360; -import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultDataSpecificationIec61360; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper; +import org.eclipse.digitaltwin.aas4j.v3.model.DataSpecificationContent; import java.io.IOException; +import java.util.Iterator; +import java.util.Set; -public class EmbeddedDataSpecificationsDeserializer extends JsonDeserializer { +public class EmbeddedDataSpecificationsDeserializer extends JsonDeserializer { - private static final String PROP_DATA_SPECIFICATION_CONTENT = "dataSpecificationIec61360"; @Override - public DataSpecificationIec61360 deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException, JsonProcessingException { + public DataSpecificationContent deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException { ObjectNode node = DeserializationHelper.getRootObjectNode(parser); if (node == null) { return null; @@ -41,13 +41,23 @@ public DataSpecificationIec61360 deserialize(JsonParser parser, DeserializationC } - private DataSpecificationIec61360 createEmbeddedDataSpecificationsFromContent(JsonParser parser, JsonNode node) throws IOException { - JsonNode nodeContent = node.get(PROP_DATA_SPECIFICATION_CONTENT); - return createDefaultDataSpecificationIec61360FromNode(parser, nodeContent); - } - - private DataSpecificationIec61360 createDefaultDataSpecificationIec61360FromNode(JsonParser parser, JsonNode nodeContent) throws IOException { - return DeserializationHelper.createInstanceFromNode(parser, nodeContent, DefaultDataSpecificationIec61360.class); + private DataSpecificationContent createEmbeddedDataSpecificationsFromContent(JsonParser parser, JsonNode node) throws IOException { + String class_name = node.fieldNames().next(); + Set> subtypes = ReflectionHelper.SUBTYPES.get(DataSpecificationContent.class); + Iterator> iter = subtypes.iterator(); + while (iter.hasNext()) { + Class clazz = iter.next(); + if (clazz.getSimpleName().toLowerCase().contains(class_name.toLowerCase())) { + try { + JsonNode nodeContent = node.get(class_name); + return (DataSpecificationContent) DeserializationHelper.createInstanceFromNode(parser, nodeContent, clazz); + } catch (Exception e) { + // do nothing and try next in list + } + } + }; + + throw new IOException("Was expecting a known subclass of DataSpecificationContent but found " + class_name); } } diff --git a/dataformat-xml/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/serialization/EmbeddedDataSpecificationSerializer.java b/dataformat-xml/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/serialization/EmbeddedDataSpecificationSerializer.java index cfad82bb1..b70aaf051 100644 --- a/dataformat-xml/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/serialization/EmbeddedDataSpecificationSerializer.java +++ b/dataformat-xml/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/serialization/EmbeddedDataSpecificationSerializer.java @@ -20,7 +20,8 @@ import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; -import org.eclipse.digitaltwin.aas4j.v3.model.DataSpecificationIec61360; +import com.google.common.base.CaseFormat; +import org.eclipse.digitaltwin.aas4j.v3.model.DataSpecificationContent; import java.io.IOException; @@ -30,22 +31,30 @@ * of a reference. Uses DataSpecificationManager to resolve java type to * reference. */ -public class EmbeddedDataSpecificationSerializer extends JsonSerializer { +public class EmbeddedDataSpecificationSerializer extends JsonSerializer { @Override - public void serialize(DataSpecificationIec61360 data, JsonGenerator generator, SerializerProvider provider) + public void serialize(DataSpecificationContent data, JsonGenerator generator, SerializerProvider provider) throws IOException { if (data == null) { return; } + String class_name = "dataSpecification"; // default + try { + // known limitation: Only one interface must be implemented by the class, and the name of this interface must match exactly to the name of the DataSpecification + class_name = data.getClass().getInterfaces()[0].getSimpleName(); + } catch (Exception e) { + // do nothing and continue with the default + } + class_name = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, class_name); generator.writeStartObject(); - generator.writeObjectField("dataSpecificationIec61360", data); + generator.writeObjectField(class_name, data); generator.writeEndObject(); } @Override - public void serializeWithType(DataSpecificationIec61360 data, JsonGenerator generator, SerializerProvider provider, + public void serializeWithType(DataSpecificationContent data, JsonGenerator generator, SerializerProvider provider, TypeSerializer typedSerializer) throws IOException, JsonProcessingException { serialize(data, generator, provider); } diff --git a/dataformat-xml/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/XmlSerializerTest.java b/dataformat-xml/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/XmlSerializerTest.java index aaa6b2e13..469a163df 100644 --- a/dataformat-xml/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/XmlSerializerTest.java +++ b/dataformat-xml/src/test/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/xml/XmlSerializerTest.java @@ -17,14 +17,18 @@ package org.eclipse.digitaltwin.aas4j.v3.dataformat.xml; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.DeserializationException; import org.eclipse.digitaltwin.aas4j.v3.dataformat.SerializationException; import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.AASFull; import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.AASSimple; import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.Examples; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper; import org.eclipse.digitaltwin.aas4j.v3.dataformat.xml.internal.AasXmlNamespaceContext; import org.eclipse.digitaltwin.aas4j.v3.model.AssetKind; import org.eclipse.digitaltwin.aas4j.v3.model.ConceptDescription; +import org.eclipse.digitaltwin.aas4j.v3.model.DataSpecificationContent; import org.eclipse.digitaltwin.aas4j.v3.model.DataTypeDefXsd; +import org.eclipse.digitaltwin.aas4j.v3.model.DefaultDummyDataSpecification; import org.eclipse.digitaltwin.aas4j.v3.model.Environment; import org.eclipse.digitaltwin.aas4j.v3.model.Submodel; import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultAssetAdministrationShell; @@ -54,6 +58,7 @@ import java.util.Set; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -186,6 +191,32 @@ public void serializeAASWithExtensionMaximal() throws SerializationException, SA } + /** + * This test ensures that future DataSpecificationContents can be added without adjustments in the code. + * + * @throws SerializationException + * @throws DeserializationException + */ + @Test + public void testSerializeCustomDataSpecification() throws SerializationException, DeserializationException, SAXException { + XmlSerializer serializer = new XmlSerializer(); + XmlDeserializer deserializer = new XmlDeserializer(); + + // This is the only way to make the serialization to work. + Set> subtypes = ReflectionHelper.SUBTYPES.get(DataSpecificationContent.class); + subtypes.add(DefaultDummyDataSpecification.class); + + String xmlString = serializer.write(Examples.ENVIRONMENT_WITH_DUMMYDATASPEC); + assertNotNull(xmlString); + + validateAgainstXsdSchema(xmlString); + + Environment copy = deserializer.read(xmlString); + assertNotNull(copy); + + assertTrue(Examples.ENVIRONMENT_WITH_DUMMYDATASPEC.equals(copy)); + } + private Set validateAgainstXsdSchema(String xml) throws SAXException { return new XmlSchemaValidator().validateSchema(xml); } diff --git a/model/src/main/java/org/eclipse/digitaltwin/aas4j/v3/model/CustomDataSpecification.java b/model/src/main/java/org/eclipse/digitaltwin/aas4j/v3/model/CustomDataSpecification.java new file mode 100644 index 000000000..a9a3eacd5 --- /dev/null +++ b/model/src/main/java/org/eclipse/digitaltwin/aas4j/v3/model/CustomDataSpecification.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2023 SAP SE or an SAP affiliate company. + * + * 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 org.eclipse.digitaltwin.aas4j.v3.model; + +/** + * This interface is needed to test the serialization/deserialization of a custom data specification content. + * See: https://github.com/eclipse-aas4j/aas4j/issues/196 + */ +public interface CustomDataSpecification extends DataSpecificationContent { + +} \ No newline at end of file diff --git a/model/src/main/java/org/eclipse/digitaltwin/aas4j/v3/model/DataSpecificationContent.java b/model/src/main/java/org/eclipse/digitaltwin/aas4j/v3/model/DataSpecificationContent.java index 7fd9aaeec..1fb8d800d 100644 --- a/model/src/main/java/org/eclipse/digitaltwin/aas4j/v3/model/DataSpecificationContent.java +++ b/model/src/main/java/org/eclipse/digitaltwin/aas4j/v3/model/DataSpecificationContent.java @@ -25,7 +25,8 @@ * and meta information about the template itself. */ @KnownSubtypes({ - @KnownSubtypes.Type(value = DataSpecificationIec61360.class) + @KnownSubtypes.Type(value = DataSpecificationIec61360.class), + @KnownSubtypes.Type(value = CustomDataSpecification.class) }) public interface DataSpecificationContent {