Skip to content

Commit

Permalink
Makes Value Only of SubmodelElementCollection conform standard (eclip…
Browse files Browse the repository at this point in the history
…se-basyx#357)

* Makes Value Only of SubmodelElementCollection conform standard

* Changes internal use to HashMap for better Performance

* Adapts JSON
  • Loading branch information
FriedJannik authored Jul 31, 2024
1 parent 8bbe124 commit 2aa37f2
Show file tree
Hide file tree
Showing 16 changed files with 121 additions and 136 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public class TestAasEnvironmentHTTP {
private static final String XML_ENV_PATH = "testEnvironment.xml";
private static final String WRONGEXT_ENV_PATH = "testEnvironment.txt";
private static final String JSON_OPERATIONALDATA_ENV_PATH = "operationalDataEnvironment.json";
private static final String BASIC_EVENT_VALUE_ONLY = "BasicEventValueOnly.json";
private static final String AASENVIRONMENT_VALUE_ONLY_JSON = "AASEnvironmentValueOnly.json";

private static ConfigurableApplicationContext appContext;
private static SubmodelRepository submodelRepo;
Expand Down Expand Up @@ -114,7 +114,7 @@ public void testAASEnvironmentSerialization_ValueOnly() throws FileNotFoundExcep
response = executeGetOnURL(getOperationalDataValueOnlyURL(), JSON_MIMETYPE);
assertEquals(HttpStatus.OK.value(), response.getCode());

BaSyxHttpTestUtils.assertSameJSONContent(BaSyxHttpTestUtils.readJSONStringFromClasspath(BASIC_EVENT_VALUE_ONLY), BaSyxHttpTestUtils.getResponseAsString(response));
BaSyxHttpTestUtils.assertSameJSONContent(BaSyxHttpTestUtils.readJSONStringFromClasspath(AASENVIRONMENT_VALUE_ONLY_JSON), BaSyxHttpTestUtils.getResponseAsString(response));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"ObserveValueUpdates": {
"observed": {
"type": "ExternalReference",
"keys": [
{
"type": "Submodel",
"value": "www.example.com/ids/sm/2222_8041_1042_8057"
}
]
}
},
"ViaMqtt": {
"L1": "290.6217782649107",
"L2": "282.4599521889145",
"L3": "272.2067133660983",
"Active_Power_All": "104308.59396737856"
},
"AnnotationBottom": "",
"ViaOpcUa": {
"L1": "299.53634421194454",
"L2": "296.55226321871635",
"L3": "290.9149535087691",
"Active_Power_All": "109456.23941992565"
},
"ViaModbus": {
"L1": "160.26637",
"L2": "160.44434",
"L3": "163.39528",
"Active_Power_All": "59738.68"
},
"ViaHTTP": {
"L1": "291.4213289500366",
"L2": "296.869547091201",
"L3": "299.65015492058336",
"Active_Power_All": "109572.7967447997"
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ public void getSubmodelElementCollectionValue() {
public void setSubmodelElementCollectionValue() {
DefaultSubmodelElementCollection submodelElementCollection = getDefaultSubmodelElementCollection();
ConnectedSubmodelElementCollection connectedSubmodelElementCollection = getConnectedSubmodelElementCollection(submodelElementCollection);
submodelElementCollection.getValue().add(getDefaultMultiLanguageProperty());
submodelElementCollection.getValue().add(getDefaultMultiLanguageProperty("newMLP"));
SubmodelElementCollectionValueMapper valueMapper = new SubmodelElementCollectionValueMapper(submodelElementCollection);
connectedSubmodelElementCollection.setValue(valueMapper.getValue());
assertEquals(2, connectedSubmodelElementCollection.getValue().getValue().size());
Expand Down Expand Up @@ -445,6 +445,10 @@ private DefaultMultiLanguageProperty getDefaultMultiLanguageProperty() {
return new DefaultMultiLanguageProperty.Builder().idShort(SUBMODEL_ELEMENT_ID_SHORT).value(Arrays.asList(new DefaultLangStringTextType.Builder().text(EXPECTED_STRING).language("de").build())).build();
}

private DefaultMultiLanguageProperty getDefaultMultiLanguageProperty(String idShort) {
return new DefaultMultiLanguageProperty.Builder().idShort(idShort).value(Arrays.asList(new DefaultLangStringTextType.Builder().text(EXPECTED_STRING).language("de").build())).build();
}

private ConnectedMultiLanguageProperty getConnectedMultiLanguageProperty(DefaultMultiLanguageProperty property) {
Submodel sm = createSubmodel(property);
return new ConnectedMultiLanguageProperty(getSubmodelServiceUrl(Base64UrlEncodedIdentifier.encodeIdentifier(sm.getId())), SUBMODEL_ELEMENT_ID_SHORT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,13 @@

package org.eclipse.digitaltwin.basyx.deserialization.factory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.digitaltwin.basyx.submodelservice.value.SubmodelElementCollectionValue;
import org.eclipse.digitaltwin.basyx.submodelservice.value.SubmodelElementValue;
import org.eclipse.digitaltwin.basyx.submodelservice.value.ValueOnly;

import com.fasterxml.jackson.core.JsonProcessingException;
Expand Down Expand Up @@ -61,7 +65,13 @@ public SubmodelElementCollectionValueDeserializationFactory(ObjectMapper objectM
*
*/
public SubmodelElementCollectionValue create() throws JsonProcessingException {
List<ValueOnly> valueOnlies = objectMapper.readValue(node.toString(), new TypeReference<List<ValueOnly>>() {});
Map<String, Object> map = objectMapper.readValue(node.toString(), new TypeReference<Map<String, Object>>() {});
Map<String,SubmodelElementValue> valueOnlies = new HashMap<>();

for (Map.Entry<String, Object> entry : map.entrySet()) {
SubmodelElementValue submodelElementValue = objectMapper.convertValue(entry.getValue(), SubmodelElementValue.class);
valueOnlies.put(entry.getKey(), submodelElementValue);
}

return new SubmodelElementCollectionValue(valueOnlies);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,12 @@ public SubmodelElementValue create(ObjectMapper mapper, JsonNode node) throws Js
return mapper.convertValue(node, RelationshipElementValue.class);
} else if (isTypeOfAnnotatedRelationshipElementValue(node)) {
return mapper.convertValue(node, AnnotatedRelationshipElementValue.class);
} else if (isTypeOfBasicEventValue(node)) {
return mapper.convertValue(node, BasicEventValue.class);
} else if (isTypeOfSubmodelElementListValue(node)) {
return new SubmodelElementListValueDeserializationFactory(mapper, node).create();
} else if (isTypeOfSubmodelElementCollectionValue(node)) {
return new SubmodelElementCollectionValueDeserializationFactory(mapper, node).create();
} else if (isTypeOfBasicEventValue(node)) {
return mapper.convertValue(node, BasicEventValue.class);
}

throw new SubmodelElementValueDeserializationException();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;

Expand Down Expand Up @@ -90,7 +92,7 @@ public static boolean isTypeOfAnnotatedRelationshipElementValue(JsonNode node) {
}

public static boolean isTypeOfSubmodelElementCollectionValue(JsonNode node) {
return node.isArray() && hasStructureOfSubmodelElementCollectionValue(node);
return node.isObject() && hasStructureOfSubmodelElementCollectionValue(node);
}

public static boolean isTypeOfSubmodelElementListValue(JsonNode node) {
Expand Down Expand Up @@ -161,9 +163,12 @@ private static boolean hasStructureOfMultiLanguagePropertyValue(JsonNode node) {
}

private static boolean hasStructureOfSubmodelElementCollectionValue(JsonNode node) {
for (JsonNode element : node) {
if (!isValidValueOnly(element))
Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
while (fields.hasNext()) {
Map.Entry<String, JsonNode> field = fields.next();
if (!isInstanceOfSubmodelElementValue(field.getValue())) {
return false;
}
}

return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@
package org.eclipse.digitaltwin.basyx.serialization;

import java.io.IOException;
import java.util.Map;

import org.eclipse.digitaltwin.basyx.submodelservice.value.SubmodelElementCollectionValue;
import org.eclipse.digitaltwin.basyx.submodelservice.value.SubmodelElementValue;
import org.eclipse.digitaltwin.basyx.submodelservice.value.ValueOnly;

import com.fasterxml.jackson.core.JsonGenerator;
Expand All @@ -45,13 +47,13 @@ public class SubmodelElementCollectionValueSerializer extends JsonSerializer<Sub

@Override
public void serialize(SubmodelElementCollectionValue value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeStartArray();
gen.writeStartObject();

for (ValueOnly valueOnly : value.getValue()) {
gen.writeObject(valueOnly);
for (Map.Entry<String, SubmodelElementValue> valueOnly : value.getValue().entrySet()) {
gen.writeObjectField(valueOnly.getKey(),valueOnly.getValue());
}

gen.writeEndArray();
gen.writeEndObject();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
package org.eclipse.digitaltwin.basyx.submodelservice.value;

import java.util.List;
import java.util.Map;

import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElementCollection;

Expand All @@ -35,18 +36,18 @@
*
*/
public class SubmodelElementCollectionValue implements SubmodelElementValue {
private List<ValueOnly> value;
private Map<String,SubmodelElementValue> value;

@SuppressWarnings("unused")
private SubmodelElementCollectionValue() {
super();
}

public SubmodelElementCollectionValue(List<ValueOnly> value) {
public SubmodelElementCollectionValue(Map<String,SubmodelElementValue> value) {
this.value = value;
}

public List<ValueOnly> getValue() {
public Map<String,SubmodelElementValue> getValue() {
return value;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@

import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElementCollection;
import org.eclipse.digitaltwin.basyx.submodelservice.value.SubmodelElementCollectionValue;
import org.eclipse.digitaltwin.basyx.submodelservice.value.ValueOnly;

import java.util.stream.Collectors;

/**
* Maps {@link SubmodelElementCollection} value to {@link SubmodelElementCollectionValue}
Expand All @@ -44,7 +47,7 @@ public SubmodelElementCollectionValueMapper(SubmodelElementCollection submodelEl

@Override
public SubmodelElementCollectionValue getValue() {
return new SubmodelElementCollectionValue(ValueMapperUtil.createValueOnlyCollection(submodelElementCollection.getValue()));
return new SubmodelElementCollectionValue(ValueMapperUtil.createValueOnlyCollection(submodelElementCollection.getValue()).stream().collect(Collectors.toMap(ValueOnly::getIdShort, ValueOnly::getSubmodelElementValue)));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,10 @@ public static List<ValueOnly> createValueOnlyCollection(Collection<SubmodelEleme
public static void setValueOfSubmodelElementWithValueOnly(Collection<SubmodelElement> submodelElements, List<ValueOnly> valueOnlies) {
submodelElements.stream().forEach(submodelElement -> setValue(submodelElement, ValueMapperUtil.getSubmodelElementValue(submodelElement, valueOnlies)));
}

public static void setValueOfSubmodelElementWithValueOnly(Collection<SubmodelElement> submodelElements, Map<String,SubmodelElementValue> valueOnlies) {
submodelElements.stream().forEach(submodelElement -> setValue(submodelElement, valueOnlies.get(submodelElement.getIdShort())));
}

/**
* Updates the value of {@link SubmodelElement} with its corresponding {@link SubmodelElementValue}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@
package org.eclipse.digitaltwin.basyx.submodelservice.value;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.eclipse.digitaltwin.aas4j.v3.model.AnnotatedRelationshipElement;
Expand Down Expand Up @@ -349,8 +351,9 @@ public void mappedGetSubmodelElementCollectionValue() {
@Test
public void mappedSetSubmodelElementCollectionValue() {
SubmodelElementCollection submodelElementCollection = SubmodelServiceHelper.createSubmodelElementCollection();

SubmodelElementCollectionValue submodelElementCollectionValue = new SubmodelElementCollectionValue(submodelElementCollectionValueOnlies);
Map<String, SubmodelElementValue> map = submodelElementCollectionValueOnlies.stream()
.collect(Collectors.toMap(ValueOnly::getIdShort, ValueOnly::getSubmodelElementValue));
SubmodelElementCollectionValue submodelElementCollectionValue = new SubmodelElementCollectionValue(map);

setSubmodelElementCollectionValue(submodelElementCollection, submodelElementCollectionValue);

Expand Down Expand Up @@ -546,14 +549,7 @@ private static void assertValuesAreEqual(Entity expected, EntityValueMapper file
}

private void assertValuesAreEqual(SubmodelElementCollection expected, SubmodelElementCollectionValue actual) {

assertEquals(getSubmodelElementAtIndex(expected, 0).getIdShort(), getValueOnlyAtIndex(actual, 0).getIdShort());
assertEquals(getSubmodelElementAtIndex(expected, 1).getIdShort(), getValueOnlyAtIndex(actual, 1).getIdShort());

assertEquals(((File) getSubmodelElementAtIndex(expected, 0)).getContentType(), ((FileBlobValue) getValueOnlyAtIndex(actual, 0).getSubmodelElementValue()).getContentType());
assertEquals(((File) getSubmodelElementAtIndex(expected, 0)).getValue(), ((FileBlobValue) getValueOnlyAtIndex(actual, 0).getSubmodelElementValue()).getValue());

assertEquals(((Property) getSubmodelElementAtIndex(expected, 1)).getValue(), ((PropertyValue) getValueOnlyAtIndex(actual, 1).getSubmodelElementValue()).getValue());
assertTrue(expected.getValue().stream().allMatch(sme -> actual.getValue().containsKey(sme.getIdShort())));
}

private void assertValuesAreEqual(SubmodelElementList expected, SubmodelElementListValue actual) {
Expand Down Expand Up @@ -662,11 +658,6 @@ private SubmodelElement getSubmodelElementAtIndex(SubmodelElementList submodelEl
.get(index);
}

private ValueOnly getValueOnlyAtIndex(SubmodelElementCollectionValue submodelElementCollectionValue, int index) {
return submodelElementCollectionValue.getValue()
.get(index);
}

private SubmodelElementValue getSubmodelElementValueAtIndex(SubmodelElementListValue submodelElementListValue, int index) {
return submodelElementListValue.getSubmodelElementValues()
.get(index);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,13 @@
"new_SimpleList": [
"new_4370"
],
"new_SubmodelElementCollection": [
{
"new_FileData": {
"contentType": "application/json",
"value": "new_testFile.json"
}
"new_SubmodelElementCollection": {
"new_FileData": {
"contentType": "application/json",
"value": "new_testFile.json"
},
{
"new_MaxRotationSpeed": "new_5000"
}
],
"new_MaxRotationSpeed": "new_5000"
},
"new_BlobData": {
"contentType": "application/xml",
"value": "Test content of XML file"
Expand Down Expand Up @@ -62,11 +58,9 @@
}
]
},
"new_SimpleCollection": [
{
"new_MyFirstSubmodelElement": "new_4370"
}
],
"new_SimpleCollection": {
"new_MyFirstSubmodelElement": "new_4370"
},
"new_FileData": {
"contentType": "application/json",
"value": "new_testFile.json"
Expand Down
Loading

0 comments on commit 2aa37f2

Please sign in to comment.