diff --git a/core/common/boot/src/main/java/org/eclipse/edc/boot/system/injection/InjectionContainer.java b/core/common/boot/src/main/java/org/eclipse/edc/boot/system/injection/InjectionContainer.java index ff0e4361350..db4da9059f7 100644 --- a/core/common/boot/src/main/java/org/eclipse/edc/boot/system/injection/InjectionContainer.java +++ b/core/common/boot/src/main/java/org/eclipse/edc/boot/system/injection/InjectionContainer.java @@ -50,8 +50,8 @@ public List getServiceProviders() { @Override public String toString() { return getClass().getSimpleName() + "{" + - "injectionTarget=" + injectionTarget + - '}'; + "injectionTarget=" + injectionTarget + + '}'; } } diff --git a/core/common/lib/transform-lib/src/main/java/org/eclipse/edc/transform/transformer/edc/from/JsonObjectFromDataAddressTransformer.java b/core/common/lib/transform-lib/src/main/java/org/eclipse/edc/transform/transformer/edc/from/JsonObjectFromDataAddressTransformer.java index 6a40e87aa22..d982d1d98c5 100644 --- a/core/common/lib/transform-lib/src/main/java/org/eclipse/edc/transform/transformer/edc/from/JsonObjectFromDataAddressTransformer.java +++ b/core/common/lib/transform-lib/src/main/java/org/eclipse/edc/transform/transformer/edc/from/JsonObjectFromDataAddressTransformer.java @@ -17,6 +17,7 @@ import jakarta.json.JsonBuilderFactory; import jakarta.json.JsonObject; import org.eclipse.edc.jsonld.spi.transformer.AbstractJsonLdTransformer; +import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.spi.types.domain.DataAddress; import org.eclipse.edc.transform.spi.TransformerContext; import org.jetbrains.annotations.NotNull; @@ -28,10 +29,14 @@ public class JsonObjectFromDataAddressTransformer extends AbstractJsonLdTransformer { private final JsonBuilderFactory jsonBuilderFactory; + private final TypeManager typeManager; + private final String typeContext; - public JsonObjectFromDataAddressTransformer(JsonBuilderFactory jsonBuilderFactory) { + public JsonObjectFromDataAddressTransformer(JsonBuilderFactory jsonBuilderFactory, TypeManager mapper, String typeContext) { super(DataAddress.class, JsonObject.class); this.jsonBuilderFactory = jsonBuilderFactory; + this.typeManager = mapper; + this.typeContext = typeContext; } @Override @@ -40,7 +45,7 @@ public JsonObjectFromDataAddressTransformer(JsonBuilderFactory jsonBuilderFactor builder.add(TYPE, EDC_NAMESPACE + "DataAddress"); - dataAddress.getProperties().forEach((key, value) -> builder.add(key, (String) value)); // TODO: handle different types + transformProperties(dataAddress.getProperties(), builder, typeManager.getMapper(typeContext), context); return builder.build(); } diff --git a/core/common/lib/transform-lib/src/main/java/org/eclipse/edc/transform/transformer/edc/to/JsonObjectToDataAddressTransformer.java b/core/common/lib/transform-lib/src/main/java/org/eclipse/edc/transform/transformer/edc/to/JsonObjectToDataAddressTransformer.java index 778ea97a29c..c1b81b5e377 100644 --- a/core/common/lib/transform-lib/src/main/java/org/eclipse/edc/transform/transformer/edc/to/JsonObjectToDataAddressTransformer.java +++ b/core/common/lib/transform-lib/src/main/java/org/eclipse/edc/transform/transformer/edc/to/JsonObjectToDataAddressTransformer.java @@ -14,7 +14,6 @@ package org.eclipse.edc.transform.transformer.edc.to; -import jakarta.json.JsonArray; import jakarta.json.JsonObject; import jakarta.json.JsonValue; import org.eclipse.edc.jsonld.spi.transformer.AbstractJsonLdTransformer; @@ -23,7 +22,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import static jakarta.json.JsonValue.ValueType.STRING; import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; @@ -47,23 +45,15 @@ public JsonObjectToDataAddressTransformer() { } private void transformProperties(String key, JsonValue jsonValue, DataAddress.Builder builder, TransformerContext context) { - if ((PROPERTIES_KEY).equals(key) && jsonValue instanceof JsonArray) { - var props = jsonValue.asJsonArray().getJsonObject(0); - visitProperties(props, (k, val) -> transformProperties(k, val, builder, context)); + var firstValue = returnJsonObject(jsonValue, context, key, true); + + if (firstValue != null && key.equals(PROPERTIES_KEY)) { + visitProperties(firstValue, (k, val) -> transformProperties(k, val, builder, context)); } else { - var object = transformGenericProperty(jsonValue, context); - if (object instanceof String) { - builder.property(key, object.toString()); - } else { - context.problem() - .unexpectedType() - .type("property") - .property(key) - .actual(object == null ? "null" : object.toString()) - .expected(STRING) - .report(); - } + builder.property(key, transformGenericProperty(jsonValue, context)); } } + + } diff --git a/core/common/lib/transform-lib/src/test/java/org/eclipse/edc/transform/transformer/edc/to/JsonObjectToDataAddressTransformerTest.java b/core/common/lib/transform-lib/src/test/java/org/eclipse/edc/transform/transformer/edc/to/JsonObjectToDataAddressTransformerTest.java index db9e8370754..c61045891ef 100644 --- a/core/common/lib/transform-lib/src/test/java/org/eclipse/edc/transform/transformer/edc/to/JsonObjectToDataAddressTransformerTest.java +++ b/core/common/lib/transform-lib/src/test/java/org/eclipse/edc/transform/transformer/edc/to/JsonObjectToDataAddressTransformerTest.java @@ -16,7 +16,6 @@ import jakarta.json.JsonObject; import jakarta.json.JsonObjectBuilder; -import jakarta.json.JsonValue; import org.eclipse.edc.jsonld.TitaniumJsonLd; import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.jsonld.util.JacksonJsonLd; @@ -28,10 +27,17 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.util.List; +import java.util.Map; + +import static jakarta.json.Json.createArrayBuilder; import static jakarta.json.Json.createObjectBuilder; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.InstanceOfAssertFactories.LIST; +import static org.assertj.core.api.InstanceOfAssertFactories.MAP; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.CONTEXT; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VALUE; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VOCAB; import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; import static org.eclipse.edc.spi.constants.CoreConstants.EDC_PREFIX; @@ -39,9 +45,11 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; + class JsonObjectToDataAddressTransformerTest { private static final int CUSTOM_PAYLOAD_AGE = 34; private static final String CUSTOM_PAYLOAD_NAME = "max"; @@ -87,33 +95,90 @@ void transform_withCustomProps() { assertThat(dataAddress).isNotNull(); assertThat(dataAddress.getType()).isEqualTo(TEST_TYPE); assertThat(dataAddress.getStringProperty(EDC_NAMESPACE + "my-test-prop")).isEqualTo("some-test-value"); + assertThat(dataAddress.getProperties()).hasSize(3); } @Test - void transform_withComplexCustomProps_shouldReportProblem() { - when(transformerContext.transform(isA(JsonValue.class), eq(Payload.class))).thenReturn(new Payload(CUSTOM_PAYLOAD_NAME, CUSTOM_PAYLOAD_AGE)); + void transform_withNestedJson() { var json = createDataAddress() .add(EDC_NAMESPACE + "properties", createObjectBuilder() - .add("payload", createPayloadBuilder().build()) + .add("payload", createObjectBuilder() + .add("sabesxopaulovem", createPayloadBuilder().build()) + .add("arrayInPayload", createArrayBuilder().add("innerValue1").add("innerValue2").build()).build()) .build()) .build(); var dataAddress = transformer.transform(expand(json), transformerContext); assertThat(dataAddress).isNotNull(); - assertThat(dataAddress.getType()).isEqualTo(TEST_TYPE); - assertThat(dataAddress.getKeyName()).isEqualTo(TEST_KEY_NAME); - assertThat(dataAddress.getProperties()).hasSize(2); + assertThat(dataAddress.getProperty(EDC_NAMESPACE + "payload")) + .isNotNull() + .asInstanceOf(MAP) + .hasSize(2) + .hasEntrySatisfying(EDC_NAMESPACE + "sabesxopaulovem", + v -> assertThat(v).asInstanceOf(LIST).first().asInstanceOf(MAP) + .hasSize(3) + .containsEntry(EDC_NAMESPACE + "name", List.of(Map.of(VALUE, CUSTOM_PAYLOAD_NAME))) + .containsEntry(EDC_NAMESPACE + "age", List.of(Map.of(VALUE, CUSTOM_PAYLOAD_AGE)))) + .hasEntrySatisfying(EDC_NAMESPACE + "arrayInPayload", + v -> assertThat(v).asInstanceOf(LIST) + .hasSize(2) + .containsExactly(Map.of(VALUE, "innerValue1"), Map.of(VALUE, "innerValue2"))); + verify(transformerContext, never()).reportProblem(any()); + } + + @Test + void transform_withArrayProperty() { + var json = createDataAddress() + .add(EDC_NAMESPACE + "properties", createObjectBuilder() + .add("array", createArrayBuilder().add("string1").add("string2").build()) + .build()) + .build(); - verify(transformerContext).reportProblem(any()); + var dataAddress = transformer.transform(expand(json), transformerContext); + + assertThat(dataAddress).isNotNull(); + assertThat(dataAddress.getProperty(EDC_NAMESPACE + "array")) + .isNotNull() + .isEqualTo(List.of("string1", "string2")); + verify(transformerContext, never()).reportProblem(any()); + } + + @Test + void transform_withArrayOfObjects() { + var json = createDataAddress() + .add(EDC_NAMESPACE + "properties", createObjectBuilder() + .add("arrayOfObjects", createArrayBuilder() + .add(createObjectBuilder().add("name", CUSTOM_PAYLOAD_NAME).build()) + .add(createObjectBuilder().add("age", CUSTOM_PAYLOAD_AGE).build()) + .build()) + .build()) + .build(); + + var dataAddress = transformer.transform(expand(json), transformerContext); + + assertThat(dataAddress).isNotNull(); + assertThat(dataAddress.getProperty(EDC_NAMESPACE + "arrayOfObjects")) + .isNotNull() + .asInstanceOf(LIST) + .hasSize(2) + .satisfies(list -> { + assertThat(list.get(0)).asInstanceOf(MAP) + .hasSize(1) + .containsEntry(EDC_NAMESPACE + "name", List.of(Map.of(VALUE, CUSTOM_PAYLOAD_NAME))); + assertThat(list.get(1)).asInstanceOf(MAP) + .hasSize(1) + .containsEntry(EDC_NAMESPACE + "age", List.of(Map.of(VALUE, CUSTOM_PAYLOAD_AGE))); + }); + verify(transformerContext, never()).reportProblem(any()); } private JsonObjectBuilder createDataAddress() { return createObjectBuilder() .add(CONTEXT, createContextBuilder().build()) .add(TYPE, EDC_NAMESPACE + "DataAddress") - .add(EDC_NAMESPACE + DataAddress.EDC_DATA_ADDRESS_TYPE_PROPERTY, TEST_TYPE) - .add(EDC_NAMESPACE + DataAddress.EDC_DATA_ADDRESS_KEY_NAME, TEST_KEY_NAME); + .add(DataAddress.EDC_DATA_ADDRESS_TYPE_PROPERTY, TEST_TYPE) + .add(DataAddress.EDC_DATA_ADDRESS_KEY_NAME, TEST_KEY_NAME); } private JsonObjectBuilder createContextBuilder() { @@ -132,7 +197,4 @@ private JsonObjectBuilder createPayloadBuilder() { private JsonObject expand(JsonObject jsonObject) { return jsonLd.expand(jsonObject).orElseThrow(f -> new AssertionError(f.getFailureDetail())); } - - private record Payload(String name, int age) { - } } diff --git a/data-protocols/dsp/dsp-lib/dsp-transfer-process-lib/dsp-transfer-process-transform-lib/src/test/java/org/eclipse/edc/protocol/dsp/transferprocess/transform/from/JsonObjectFromDataAddressTransformerTest.java b/data-protocols/dsp/dsp-lib/dsp-transfer-process-lib/dsp-transfer-process-transform-lib/src/test/java/org/eclipse/edc/protocol/dsp/transferprocess/transform/from/JsonObjectFromDataAddressTransformerTest.java index 38e2f73dfbb..261034da81e 100644 --- a/data-protocols/dsp/dsp-lib/dsp-transfer-process-lib/dsp-transfer-process-transform-lib/src/test/java/org/eclipse/edc/protocol/dsp/transferprocess/transform/from/JsonObjectFromDataAddressTransformerTest.java +++ b/data-protocols/dsp/dsp-lib/dsp-transfer-process-lib/dsp-transfer-process-transform-lib/src/test/java/org/eclipse/edc/protocol/dsp/transferprocess/transform/from/JsonObjectFromDataAddressTransformerTest.java @@ -15,20 +15,33 @@ package org.eclipse.edc.protocol.dsp.transferprocess.transform.from; import jakarta.json.Json; +import jakarta.json.JsonArrayBuilder; import jakarta.json.JsonBuilderFactory; +import jakarta.json.JsonObjectBuilder; +import org.eclipse.edc.jsonld.util.JacksonJsonLd; +import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.spi.types.domain.DataAddress; +import org.eclipse.edc.transform.spi.ProblemBuilder; import org.eclipse.edc.transform.spi.TransformerContext; import org.eclipse.edc.transform.transformer.edc.from.JsonObjectFromDataAddressTransformer; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; +import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.edc.spi.types.domain.DataAddress.EDC_DATA_ADDRESS_KEY_NAME; +import static org.eclipse.edc.spi.types.domain.DataAddress.EDC_DATA_ADDRESS_TYPE_PROPERTY; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.contains; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; class JsonObjectFromDataAddressTransformerTest { @@ -38,32 +51,93 @@ class JsonObjectFromDataAddressTransformerTest { private final String key = "testKey"; private final JsonBuilderFactory jsonFactory = Json.createBuilderFactory(Map.of()); private final TransformerContext context = mock(TransformerContext.class); + private final TypeManager typeManager = mock(); private JsonObjectFromDataAddressTransformer transformer; @BeforeEach void setUp() { - transformer = new JsonObjectFromDataAddressTransformer(jsonFactory); + transformer = new JsonObjectFromDataAddressTransformer(jsonFactory, typeManager, "test"); + when(typeManager.getMapper("test")).thenReturn(JacksonJsonLd.createObjectMapper()); } @Test void transform() { + var innerDataAddress = DataAddress.Builder.newInstance() + .property(EDC_DATA_ADDRESS_TYPE_PROPERTY, "type") + .build(); var message = DataAddress.Builder.newInstance() .type(type) .keyName(key) - .property(TEST_KEY, TEST_VALUE) + .property("string", "test") + .property("integer", 123) + .property("whatAboutDouble", 123.456) + .property("nestedDataAddress", innerDataAddress) + .property("nestedJsonObject", Map.of("key", Map.of("testKey", "testValue"))) + .property("jsonArray", List.of("string1", "string2")) + .property("arrayOfObjects", List.of( + Map.of("key1", "value1"), + Map.of("key2", "value2"))) + .property("nestedJsonObjectWithArray", Map.of( + "key", List.of("value1", "value2"), + "anotherKey", List.of("value3", "value4"))) .build(); - var result = transformer.transform(message, context); + var expectedJson = jsonObject() + .add(TYPE, EDC_NAMESPACE + "DataAddress") + .add(EDC_DATA_ADDRESS_TYPE_PROPERTY, type) + .add(EDC_DATA_ADDRESS_KEY_NAME, key) + .add("string", "test") + .add("integer", 123) + .add("whatAboutDouble", 123.456) + .add("nestedDataAddress", + jsonObject() + .add("properties", jsonObject().add(EDC_DATA_ADDRESS_TYPE_PROPERTY, "type"))) + .add("nestedJsonObject", + jsonObject() + .add("key", jsonObject().add("testKey", "testValue"))) + .add("jsonArray", + jsonArray() + .add("string1").add("string2")) + .add("arrayOfObjects", + jsonArray() + .add(jsonObject().add("key1", "value1")) + .add(jsonObject().add("key2", "value2"))) + .add("nestedJsonObjectWithArray", + jsonObject() + .add("key", jsonArray().add("value1").add("value2")) + .add("anotherKey", jsonArray().add("value3").add("value4"))) + .build(); - assertThat(result).isNotNull(); - assertThat(result.getJsonString(TEST_KEY).getString()).isEqualTo(TEST_VALUE); - assertThat(result.getJsonString(DataAddress.EDC_DATA_ADDRESS_TYPE_PROPERTY).getString()).isEqualTo(type); - assertThat(result.getJsonString(DataAddress.EDC_DATA_ADDRESS_KEY_NAME).getString()).isEqualTo(key); + var result = transformer.transform(message, context); + assertThat(result).usingRecursiveAssertion().isEqualTo(expectedJson); verify(context, never()).reportProblem(anyString()); } + @Test + void transform_DataAddressWithCyclicReference() { + when(context.problem()).thenReturn(new ProblemBuilder(context)); + var innerDataAddress = new LinkedHashMap(); + innerDataAddress.put(EDC_DATA_ADDRESS_TYPE_PROPERTY, "type"); + + var rootDataAddress = DataAddress.Builder.newInstance() + .type(type) + .keyName(key) + .property("nestedDataAddress", innerDataAddress) + .build(); + + innerDataAddress.put("cycle", rootDataAddress); + + var result = transformer.transform(rootDataAddress, context); + + assertThat(result) + .isNotNull() + .doesNotContainKey("nestedDataAddress"); + + verify(context).reportProblem(contains("Infinite recursion (StackOverflowError)")); + } + @Test void transform_withNamespace() { var schema = "https://some.custom.org/schema/"; @@ -78,4 +152,13 @@ void transform_withNamespace() { assertThat(result.getJsonString(schema + TEST_KEY).getString()).isEqualTo(TEST_VALUE); verify(context, never()).reportProblem(anyString()); } + + private JsonObjectBuilder jsonObject() { + return jsonFactory.createObjectBuilder(); + + } + + private JsonArrayBuilder jsonArray() { + return jsonFactory.createArrayBuilder(); + } } diff --git a/extensions/common/api/management-api-configuration/src/main/java/org/eclipse/edc/connector/api/management/configuration/ManagementApiConfigurationExtension.java b/extensions/common/api/management-api-configuration/src/main/java/org/eclipse/edc/connector/api/management/configuration/ManagementApiConfigurationExtension.java index 2676022cb3e..0440b144330 100644 --- a/extensions/common/api/management-api-configuration/src/main/java/org/eclipse/edc/connector/api/management/configuration/ManagementApiConfigurationExtension.java +++ b/extensions/common/api/management-api-configuration/src/main/java/org/eclipse/edc/connector/api/management/configuration/ManagementApiConfigurationExtension.java @@ -140,7 +140,7 @@ public void initialize(ServiceExtensionContext context) { var factory = Json.createBuilderFactory(Map.of()); managementApiTransformerRegistry.register(new JsonObjectFromContractAgreementTransformer(factory)); - managementApiTransformerRegistry.register(new JsonObjectFromDataAddressTransformer(factory)); + managementApiTransformerRegistry.register(new JsonObjectFromDataAddressTransformer(factory, typeManager, JSON_LD)); managementApiTransformerRegistry.register(new JsonObjectFromAssetTransformer(factory, typeManager, JSON_LD)); managementApiTransformerRegistry.register(new JsonObjectFromPolicyTransformer(factory, participantIdMapper)); managementApiTransformerRegistry.register(new JsonObjectFromQuerySpecTransformer(factory)); diff --git a/extensions/data-plane-selector/data-plane-selector-client/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtension.java b/extensions/data-plane-selector/data-plane-selector-client/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtension.java index d9478534926..908e2043389 100644 --- a/extensions/data-plane-selector/data-plane-selector-client/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtension.java +++ b/extensions/data-plane-selector/data-plane-selector-client/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtension.java @@ -67,7 +67,7 @@ public String name() { public void initialize(ServiceExtensionContext context) { var builderFactory = Json.createBuilderFactory(emptyMap()); typeTransformerRegistry.register(new JsonObjectFromDataPlaneInstanceTransformer(builderFactory, typeManager, JSON_LD)); - typeTransformerRegistry.register(new JsonObjectFromDataAddressTransformer(builderFactory)); + typeTransformerRegistry.register(new JsonObjectFromDataAddressTransformer(builderFactory, typeManager, JSON_LD)); typeTransformerRegistry.register(new JsonObjectToDataPlaneInstanceTransformer()); typeTransformerRegistry.register(new JsonObjectToDataAddressTransformer()); typeTransformerRegistry.register(new JsonValueToGenericTypeTransformer(typeManager, JSON_LD)); diff --git a/spi/common/core-spi/src/main/java/org/eclipse/edc/spi/types/domain/DataAddress.java b/spi/common/core-spi/src/main/java/org/eclipse/edc/spi/types/domain/DataAddress.java index df916bb696b..d18cfa0462d 100644 --- a/spi/common/core-spi/src/main/java/org/eclipse/edc/spi/types/domain/DataAddress.java +++ b/spi/common/core-spi/src/main/java/org/eclipse/edc/spi/types/domain/DataAddress.java @@ -44,7 +44,7 @@ public class DataAddress { public static final String SIMPLE_KEY_NAME = "keyName"; public static final String EDC_DATA_ADDRESS_TYPE = EDC_NAMESPACE + "DataAddress"; public static final String EDC_DATA_ADDRESS_TYPE_PROPERTY = EDC_NAMESPACE + SIMPLE_TYPE; - public static final String EDC_DATA_ADDRESS_KEY_NAME = EDC_NAMESPACE + "keyName"; + public static final String EDC_DATA_ADDRESS_KEY_NAME = EDC_NAMESPACE + SIMPLE_KEY_NAME; public static final String EDC_DATA_ADDRESS_SECRET = EDC_NAMESPACE + "secret"; protected final Map properties = new HashMap<>(); @@ -70,13 +70,18 @@ public String getStringProperty(String key) { @Nullable public String getStringProperty(String key, String defaultValue) { - var value = Optional.ofNullable(properties.get(EDC_NAMESPACE + key)).orElseGet(() -> properties.get(key)); + var value = getProperty(key); if (value != null) { return (String) value; } return defaultValue; } + @Nullable + public Object getProperty(String key) { + return Optional.ofNullable(properties.get(EDC_NAMESPACE + key)).orElseGet(() -> properties.get(key)); + } + public Map getProperties() { return properties; } diff --git a/spi/common/core-spi/src/test/java/org/eclipse/edc/spi/types/domain/DataAddressTest.java b/spi/common/core-spi/src/test/java/org/eclipse/edc/spi/types/domain/DataAddressTest.java index d718cf7d60b..f0d555b3875 100644 --- a/spi/common/core-spi/src/test/java/org/eclipse/edc/spi/types/domain/DataAddressTest.java +++ b/spi/common/core-spi/src/test/java/org/eclipse/edc/spi/types/domain/DataAddressTest.java @@ -19,11 +19,13 @@ import java.io.IOException; import java.io.StringWriter; +import java.util.List; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatNullPointerException; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.edc.spi.types.domain.DataAddress.EDC_DATA_ADDRESS_TYPE_PROPERTY; class DataAddressTest { @@ -46,6 +48,32 @@ void verifyDeserialization() throws IOException { assertThat(deserialized.getStringProperty("foo")).isEqualTo("bar"); } + @Test + void verifyDeserializationWithComplexAttribute() throws IOException { + + var mapper = new JacksonTypeManager().getMapper(); + var dataAddress = DataAddress.Builder.newInstance() + .type("test") + .keyName("somekey") + .property("foo", "bar") + .property("complexJsonObject", DataAddress.Builder.newInstance().property(EDC_DATA_ADDRESS_TYPE_PROPERTY, "AmazonS3").build()) + .property("complexJsonArray", List.of("string1", "string2")) + .build(); + var writer = new StringWriter(); + mapper.writeValue(writer, dataAddress); + var deserialized = mapper.readValue(writer.toString(), DataAddress.class); + var jsonObject = mapper.convertValue(dataAddress.getProperty("complexJsonObject"), DataAddress.class); + var jsonArray = mapper.convertValue(dataAddress.getProperty("complexJsonArray"), List.class); + assertThat(deserialized) + .isNotNull(); + assertThat(jsonObject) + .isNotNull() + .usingRecursiveComparison().isEqualTo(dataAddress.getProperty("complexJsonObject")); + assertThat(jsonArray) + .isNotNull() + .usingRecursiveComparison().isEqualTo(dataAddress.getProperty("complexJsonArray")); + } + @Test void verifyNoTypeThrowsException() { assertThatNullPointerException().isThrownBy(() -> DataAddress.Builder.newInstance() diff --git a/system-tests/management-api/management-api-test-runner/src/test/java/org/eclipse/edc/test/e2e/managementapi/AssetApiEndToEndTest.java b/system-tests/management-api/management-api-test-runner/src/test/java/org/eclipse/edc/test/e2e/managementapi/AssetApiEndToEndTest.java index abc2ca1330b..7ca023eaa90 100644 --- a/system-tests/management-api/management-api-test-runner/src/test/java/org/eclipse/edc/test/e2e/managementapi/AssetApiEndToEndTest.java +++ b/system-tests/management-api/management-api-test-runner/src/test/java/org/eclipse/edc/test/e2e/managementapi/AssetApiEndToEndTest.java @@ -29,14 +29,18 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.RegisterExtension; +import java.util.List; +import java.util.Map; import java.util.UUID; import static jakarta.json.Json.createArrayBuilder; import static jakarta.json.Json.createObjectBuilder; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.InstanceOfAssertFactories.MAP; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.CONTEXT; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VALUE; import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; import static org.eclipse.edc.spi.constants.CoreConstants.EDC_PREFIX; import static org.eclipse.edc.spi.query.Criterion.criterion; @@ -74,6 +78,11 @@ void getAssetById(ManagementEndToEndTestContext context, AssetIndex assetIndex) .containsEntry("version", "0.4.2"); assertThat(body.getMap("'dataAddress'")) .containsEntry("type", "addressType"); + assertThat(body.getMap("'dataAddress'.'complex'")) + .containsEntry("simple", "value") + .containsKey("nested"); + assertThat(body.getMap("'dataAddress'.'complex'.'nested'")) + .containsEntry("innerValue", "value"); } @Test @@ -90,6 +99,11 @@ void createAsset_shouldBeStored(ManagementEndToEndTestContext context, AssetInde .add("dataAddress", createObjectBuilder() .add(TYPE, "DataAddress") .add("type", "test-type") + .add("complex", createObjectBuilder() + .add("simple", "value") + .add("nested", createObjectBuilder() + .add("innerValue", "value")) + .build()) .build()) .build(); @@ -106,6 +120,10 @@ void createAsset_shouldBeStored(ManagementEndToEndTestContext context, AssetInde assertThat(asset).isNotNull(); assertThat(asset.isCatalog()).isTrue(); assertThat(asset.getPrivateProperty(EDC_NAMESPACE + "anotherProp")).isEqualTo("anotherVal"); + assertThat(asset.getDataAddress().getProperty("complex")) + .asInstanceOf(MAP) + .containsEntry(EDC_NAMESPACE + "simple", List.of(Map.of(VALUE, "value"))) + .containsEntry(EDC_NAMESPACE + "nested", List.of(Map.of(EDC_NAMESPACE + "innerValue", List.of(Map.of(VALUE, "value"))))); } @Test @@ -365,7 +383,8 @@ void updateAsset(ManagementEndToEndTestContext context, AssetIndex assetIndex) { .add("properties", createPropertiesBuilder() .add("some-new-property", "some-new-value").build()) .add("dataAddress", createObjectBuilder() - .add("type", "addressType")) + .add("type", "addressType") + .add("complex", createObjectBuilder().add("nested", "value").build())) .build(); context.baseRequest() @@ -381,10 +400,17 @@ void updateAsset(ManagementEndToEndTestContext context, AssetIndex assetIndex) { assertThat(dbAsset).isNotNull(); assertThat(dbAsset.getProperties()).containsEntry(EDC_NAMESPACE + "some-new-property", "some-new-value"); assertThat(dbAsset.getDataAddress().getType()).isEqualTo("addressType"); + assertThat(dbAsset.getDataAddress().getProperty(EDC_NAMESPACE + "complex")) + .asInstanceOf(MAP) + .containsEntry(EDC_NAMESPACE + "nested", List.of(Map.of(VALUE, "value"))); } private DataAddress.Builder createDataAddress() { - return DataAddress.Builder.newInstance().type("test-type"); + return DataAddress.Builder.newInstance().type("test-type") + .property(EDC_NAMESPACE + "complex", Map.of( + EDC_NAMESPACE + "simple", "value", + EDC_NAMESPACE + "nested", Map.of(EDC_NAMESPACE + "innerValue", "value") + )); } private Asset.Builder createAsset() {