diff --git a/core/common/lib/query-lib/src/main/java/org/eclipse/edc/query/EqualOperatorPredicate.java b/core/common/lib/query-lib/src/main/java/org/eclipse/edc/query/EqualOperatorPredicate.java index 91dde9fb617..58293ec5e9e 100644 --- a/core/common/lib/query-lib/src/main/java/org/eclipse/edc/query/EqualOperatorPredicate.java +++ b/core/common/lib/query-lib/src/main/java/org/eclipse/edc/query/EqualOperatorPredicate.java @@ -19,6 +19,8 @@ import java.util.List; import java.util.Objects; +import static java.util.Optional.ofNullable; + public class EqualOperatorPredicate implements OperatorPredicate { @Override @@ -42,8 +44,13 @@ public boolean test(Object property, Object operandRight) { if (property instanceof List list) { return list.stream().anyMatch(it -> Objects.equals(it, operandRight)); + } else if (property instanceof Boolean booleanProperty) { + return ofNullable(operandRight) + .map(Object::toString) + .map(Boolean::parseBoolean) + .map(booleanOperand -> booleanOperand == booleanProperty) + .orElse(false); } - return Objects.equals(property, operandRight); } } diff --git a/core/common/lib/query-lib/src/test/java/org/eclipse/edc/query/EqualOperatorPredicateTest.java b/core/common/lib/query-lib/src/test/java/org/eclipse/edc/query/EqualOperatorPredicateTest.java index 5e5bebc1024..68d31d9e837 100644 --- a/core/common/lib/query-lib/src/test/java/org/eclipse/edc/query/EqualOperatorPredicateTest.java +++ b/core/common/lib/query-lib/src/test/java/org/eclipse/edc/query/EqualOperatorPredicateTest.java @@ -56,6 +56,17 @@ void shouldMatchPredicate_whenObjectIsList() { assertThat(predicate.test(List.of("one", "two"), "three")).isFalse(); } + @Test + void shouldCheckName_whenPropertyIsBoolean() { + assertThat(predicate.test(Boolean.TRUE, "ENTRY2")).isFalse(); + assertThat(predicate.test(Boolean.TRUE, "true")).isTrue(); + assertThat(predicate.test(Boolean.TRUE, true)).isTrue(); + assertThat(predicate.test(Boolean.TRUE, false)).isFalse(); + assertThat(predicate.test(Boolean.TRUE, null)).isFalse(); + assertThat(predicate.test(Boolean.TRUE, "false")).isFalse(); + assertThat(predicate.test(true, false)).isFalse(); + } + public enum TestEnum { ENTRY1, ENTRY2 } diff --git a/core/common/lib/query-lib/src/test/java/org/eclipse/edc/query/NotEqualOperatorPredicateTest.java b/core/common/lib/query-lib/src/test/java/org/eclipse/edc/query/NotEqualOperatorPredicateTest.java index 7db9a916d91..6e97024b7ba 100644 --- a/core/common/lib/query-lib/src/test/java/org/eclipse/edc/query/NotEqualOperatorPredicateTest.java +++ b/core/common/lib/query-lib/src/test/java/org/eclipse/edc/query/NotEqualOperatorPredicateTest.java @@ -56,6 +56,17 @@ void shouldMatchPredicate_whenObjectIsList() { assertThat(predicate.test(List.of("one", "two"), "three")).isTrue(); } + @Test + void shouldCheckName_whenPropertyIsBoolean() { + assertThat(predicate.test(Boolean.TRUE, "ENTRY2")).isTrue(); + assertThat(predicate.test(Boolean.TRUE, "true")).isFalse(); + assertThat(predicate.test(Boolean.TRUE, true)).isFalse(); + assertThat(predicate.test(Boolean.TRUE, false)).isTrue(); + assertThat(predicate.test(Boolean.TRUE, "false")).isTrue(); + assertThat(predicate.test(Boolean.TRUE, null)).isTrue(); + assertThat(predicate.test(true, false)).isTrue(); + } + public enum TestEnum { ENTRY1, ENTRY2 } diff --git a/core/control-plane/control-plane-transform/src/main/java/org/eclipse/edc/connector/controlplane/transform/edc/from/JsonObjectFromAssetTransformer.java b/core/control-plane/control-plane-transform/src/main/java/org/eclipse/edc/connector/controlplane/transform/edc/from/JsonObjectFromAssetTransformer.java index b73c5fd7761..c08a75b59bc 100644 --- a/core/control-plane/control-plane-transform/src/main/java/org/eclipse/edc/connector/controlplane/transform/edc/from/JsonObjectFromAssetTransformer.java +++ b/core/control-plane/control-plane-transform/src/main/java/org/eclipse/edc/connector/controlplane/transform/edc/from/JsonObjectFromAssetTransformer.java @@ -23,6 +23,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import static org.eclipse.edc.connector.controlplane.asset.spi.domain.Asset.EDC_CATALOG_ASSET_TYPE; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; @@ -52,6 +53,10 @@ public JsonObjectFromAssetTransformer(JsonBuilderFactory jsonFactory, ObjectMapp builder.add(Asset.EDC_ASSET_PRIVATE_PROPERTIES, privatePropBuilder); } + if (asset.isCatalog()) { + builder.add(TYPE, EDC_CATALOG_ASSET_TYPE); + } + if (asset.getDataAddress() != null) { builder.add(Asset.EDC_ASSET_DATA_ADDRESS, context.transform(asset.getDataAddress(), JsonObject.class)); } diff --git a/core/control-plane/control-plane-transform/src/main/java/org/eclipse/edc/connector/controlplane/transform/edc/to/JsonObjectToAssetTransformer.java b/core/control-plane/control-plane-transform/src/main/java/org/eclipse/edc/connector/controlplane/transform/edc/to/JsonObjectToAssetTransformer.java index 73138f2fbf1..a079e427674 100644 --- a/core/control-plane/control-plane-transform/src/main/java/org/eclipse/edc/connector/controlplane/transform/edc/to/JsonObjectToAssetTransformer.java +++ b/core/control-plane/control-plane-transform/src/main/java/org/eclipse/edc/connector/controlplane/transform/edc/to/JsonObjectToAssetTransformer.java @@ -28,6 +28,8 @@ import static org.eclipse.edc.connector.controlplane.asset.spi.domain.Asset.EDC_ASSET_DATA_ADDRESS; import static org.eclipse.edc.connector.controlplane.asset.spi.domain.Asset.EDC_ASSET_PRIVATE_PROPERTIES; import static org.eclipse.edc.connector.controlplane.asset.spi.domain.Asset.EDC_ASSET_PROPERTIES; +import static org.eclipse.edc.connector.controlplane.asset.spi.domain.Asset.EDC_CATALOG_ASSET_TYPE; +import static org.eclipse.edc.jsonld.spi.TypeUtil.nodeType; /** * Converts from an {@link Asset} as a {@link JsonObject} in JSON-LD expanded form to an {@link Asset}. @@ -43,12 +45,20 @@ public JsonObjectToAssetTransformer() { .id(nodeId(jsonObject)); visitProperties(jsonObject, key -> switch (key) { - case EDC_ASSET_PROPERTIES -> value -> visitProperties(value.asJsonArray().getJsonObject(0), property(context, builder)); - case EDC_ASSET_PRIVATE_PROPERTIES -> value -> visitProperties(value.asJsonArray().getJsonObject(0), privateProperty(context, builder)); - case EDC_ASSET_DATA_ADDRESS -> value -> builder.dataAddress(transformObject(value, DataAddress.class, context)); + case EDC_ASSET_PROPERTIES -> + value -> visitProperties(value.asJsonArray().getJsonObject(0), property(context, builder)); + case EDC_ASSET_PRIVATE_PROPERTIES -> + value -> visitProperties(value.asJsonArray().getJsonObject(0), privateProperty(context, builder)); + case EDC_ASSET_DATA_ADDRESS -> + value -> builder.dataAddress(transformObject(value, DataAddress.class, context)); default -> doNothing(); }); + // the asset is a Catalog Asset, i.e. it links to another catalog + if (EDC_CATALOG_ASSET_TYPE.equals(nodeType(jsonObject))) { + builder.property(Asset.PROPERTY_IS_CATALOG, true); + } + return builderResult(builder::build, context); } diff --git a/core/control-plane/control-plane-transform/src/test/java/org/eclipse/edc/connector/controlplane/transform/edc/from/JsonObjectFromAssetTransformerTest.java b/core/control-plane/control-plane-transform/src/test/java/org/eclipse/edc/connector/controlplane/transform/edc/from/JsonObjectFromAssetTransformerTest.java index 1be7bdcdd3d..1b402b2aa2a 100644 --- a/core/control-plane/control-plane-transform/src/test/java/org/eclipse/edc/connector/controlplane/transform/edc/from/JsonObjectFromAssetTransformerTest.java +++ b/core/control-plane/control-plane-transform/src/test/java/org/eclipse/edc/connector/controlplane/transform/edc/from/JsonObjectFromAssetTransformerTest.java @@ -32,6 +32,8 @@ import static org.eclipse.edc.connector.controlplane.asset.spi.domain.Asset.EDC_ASSET_DATA_ADDRESS; import static org.eclipse.edc.connector.controlplane.asset.spi.domain.Asset.EDC_ASSET_PRIVATE_PROPERTIES; import static org.eclipse.edc.connector.controlplane.asset.spi.domain.Asset.EDC_ASSET_PROPERTIES; +import static org.eclipse.edc.connector.controlplane.asset.spi.domain.Asset.EDC_CATALOG_ASSET_TYPE; +import static org.eclipse.edc.connector.controlplane.asset.spi.domain.Asset.PROPERTY_IS_CATALOG; 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; @@ -132,6 +134,24 @@ void transform_customProperties_withCustomObject() { assertThat(jsonObject.getJsonObject(EDC_ASSET_PROPERTIES).getJsonObject("https://foo.bar.org/schema/payload")).isInstanceOf(JsonObject.class); } + @Test + void transform_shouldSetType_whenAssetIsCatalog() { + when(context.transform(isA(DataAddress.class), eq(JsonObject.class))) + .thenReturn(createObjectBuilder() + .add(EDC_DATA_ADDRESS_TYPE_PROPERTY, value("address-type")) + .build()); + var dataAddress = DataAddress.Builder.newInstance().type("address-type").build(); + var asset = createAssetBuilder() + .dataAddress(dataAddress) + .property(PROPERTY_IS_CATALOG, true) + .build(); + + var jsonObject = transformer.transform(asset, context); + + assertThat(jsonObject).isNotNull(); + assertThat(jsonObject.getString(TYPE)).isEqualTo(EDC_CATALOG_ASSET_TYPE); + } + private Asset.Builder createAssetBuilder() { return Asset.Builder.newInstance() .id(TEST_ASSET_ID) diff --git a/core/control-plane/control-plane-transform/src/test/java/org/eclipse/edc/connector/controlplane/transform/edc/to/JsonObjectToAssetTransformerTest.java b/core/control-plane/control-plane-transform/src/test/java/org/eclipse/edc/connector/controlplane/transform/edc/to/JsonObjectToAssetTransformerTest.java index 24bf0690b89..09c16f2992c 100644 --- a/core/control-plane/control-plane-transform/src/test/java/org/eclipse/edc/connector/controlplane/transform/edc/to/JsonObjectToAssetTransformerTest.java +++ b/core/control-plane/control-plane-transform/src/test/java/org/eclipse/edc/connector/controlplane/transform/edc/to/JsonObjectToAssetTransformerTest.java @@ -34,7 +34,9 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.InstanceOfAssertFactories.map; import static org.eclipse.edc.connector.controlplane.asset.spi.domain.Asset.EDC_ASSET_PRIVATE_PROPERTIES; +import static org.eclipse.edc.connector.controlplane.asset.spi.domain.Asset.EDC_ASSET_PROPERTIES; import static org.eclipse.edc.connector.controlplane.asset.spi.domain.Asset.EDC_ASSET_TYPE; +import static org.eclipse.edc.connector.controlplane.asset.spi.domain.Asset.EDC_CATALOG_ASSET_TYPE; import static org.eclipse.edc.connector.controlplane.asset.spi.domain.Asset.PROPERTY_CONTENT_TYPE; import static org.eclipse.edc.connector.controlplane.asset.spi.domain.Asset.PROPERTY_DESCRIPTION; import static org.eclipse.edc.connector.controlplane.asset.spi.domain.Asset.PROPERTY_ID; @@ -199,6 +201,22 @@ void shouldExcludeProperties_whenDefinedAtTheRootLevel() { .asInstanceOf(map(String.class, Object.class)).doesNotContainKey(EDC_NAMESPACE + "thisShouldBeIgnored"); } + @Test + void shouldSetProperty_whenTypeIsCatalog() { + var jsonObj = jsonFactory.createObjectBuilder() + .add(CONTEXT, createContextBuilder().build()) + .add(TYPE, EDC_CATALOG_ASSET_TYPE) + .add(ID, TEST_ASSET_ID) + .add(EDC_ASSET_PROPERTIES, createPropertiesBuilder().build()) + .build(); + + var asset = typeTransformerRegistry.transform(TestInput.getExpanded(jsonObj), Asset.class); + + assertThat(asset).withFailMessage(asset::getFailureDetail).isSucceeded(); + assertThat(asset).isSucceeded() + .satisfies(a -> assertThat(a.isCatalog()).isTrue()); + } + private JsonObjectBuilder createPayloadBuilder() { return jsonFactory.createObjectBuilder() .add(TYPE, "customPayload") diff --git a/docs/developer/management-domains/management-domains.md b/docs/developer/management-domains/management-domains.md index ad875e25755..1a5e9ea80e2 100644 --- a/docs/developer/management-domains/management-domains.md +++ b/docs/developer/management-domains/management-domains.md @@ -172,7 +172,7 @@ The following implementation work will be done to support Management Domains. The following changes will be made: - A boolean subtype field will be introduced on `Asset` to indicate if it is a catalog. This field will be set to `true` - when an optional `@type` property is set to `dcat:Catalog` when an asset is created in the Management API. + when an optional `@type` property is set to `edc:CatalogAsset` when an asset is created in the Management API. - The Management API will be updated in a backward-compatible way to handle optionally specifying the `@type` property on `Asset`. - `Catalog` will extend `Dataset`. diff --git a/spi/control-plane/asset-spi/src/main/java/org/eclipse/edc/connector/controlplane/asset/spi/domain/Asset.java b/spi/control-plane/asset-spi/src/main/java/org/eclipse/edc/connector/controlplane/asset/spi/domain/Asset.java index 2bab3b837ff..10685c28790 100644 --- a/spi/control-plane/asset-spi/src/main/java/org/eclipse/edc/connector/controlplane/asset/spi/domain/Asset.java +++ b/spi/control-plane/asset-spi/src/main/java/org/eclipse/edc/connector/controlplane/asset/spi/domain/Asset.java @@ -41,14 +41,15 @@ public class Asset extends Entity { public static final String PROPERTY_DESCRIPTION = EDC_NAMESPACE + "description"; public static final String PROPERTY_VERSION = EDC_NAMESPACE + "version"; public static final String PROPERTY_CONTENT_TYPE = EDC_NAMESPACE + "contenttype"; + public static final String PROPERTY_IS_CATALOG = EDC_NAMESPACE + "isCatalog"; public static final String EDC_ASSET_TYPE = EDC_NAMESPACE + "Asset"; + public static final String EDC_CATALOG_ASSET_TYPE = EDC_NAMESPACE + "CatalogAsset"; public static final String EDC_ASSET_PROPERTIES = EDC_NAMESPACE + "properties"; public static final String EDC_ASSET_PRIVATE_PROPERTIES = EDC_NAMESPACE + "privateProperties"; public static final String EDC_ASSET_DATA_ADDRESS = EDC_NAMESPACE + "dataAddress"; - - private DataAddress dataAddress; private final Map properties = new HashMap<>(); private final Map privateProperties = new HashMap<>(); + private DataAddress dataAddress; private Asset() { } @@ -79,6 +80,13 @@ public String getContentType() { return ofNullable(getPropertyAsString(PROPERTY_CONTENT_TYPE)).orElse(getPropertyAsString("contenttype")); } + @JsonIgnore + public boolean isCatalog() { + return ofNullable(getPropertyAsString(PROPERTY_IS_CATALOG)) + .map(Boolean::parseBoolean) + .orElse(false); + } + public Map getProperties() { return properties; } @@ -101,11 +109,6 @@ public Object getPrivateProperty(String key) { return privateProperties.get(key); } - private String getPropertyAsString(String key) { - var val = getProperty(key); - return val != null ? val.toString() : null; - } - public DataAddress getDataAddress() { return dataAddress; } @@ -129,6 +132,11 @@ public boolean hasDuplicatePropertyKeys() { return true; } + private String getPropertyAsString(String key) { + var val = getProperty(key); + return val != null ? val.toString() : null; + } + @JsonPOJOBuilder(withPrefix = "") public static class Builder extends Entity.Builder { @@ -159,6 +167,17 @@ public Builder self() { return this; } + @Override + public Asset build() { + super.build(); + + if (entity.getId() == null) { + id(UUID.randomUUID().toString()); + } + + return entity; + } + public Builder name(String title) { entity.properties.put(PROPERTY_NAME, title); return self(); @@ -205,17 +224,6 @@ public Builder privateProperty(String key, Object value) { entity.privateProperties.put(key, value); return self(); } - - @Override - public Asset build() { - super.build(); - - if (entity.getId() == null) { - id(UUID.randomUUID().toString()); - } - - return entity; - } } } diff --git a/spi/control-plane/asset-spi/src/test/java/org/eclipse/edc/connector/controlplane/asset/spi/domain/AssetTest.java b/spi/control-plane/asset-spi/src/test/java/org/eclipse/edc/connector/controlplane/asset/spi/domain/AssetTest.java index 18131a0d617..05e17bb547a 100644 --- a/spi/control-plane/asset-spi/src/test/java/org/eclipse/edc/connector/controlplane/asset/spi/domain/AssetTest.java +++ b/spi/control-plane/asset-spi/src/test/java/org/eclipse/edc/connector/controlplane/asset/spi/domain/AssetTest.java @@ -79,4 +79,34 @@ void getNamedProperty_whenNotPresent_shouldReturnNull() { assertThat(asset.getName()).isNull(); assertThat(asset.getVersion()).isNull(); } + + @Test + void isCatalog_whenNotPresent_shouldReturnFalse() { + var asset = Asset.Builder.newInstance().build(); + assertThat(asset.isCatalog()).isFalse(); + } + + @Test + void isCatalog_whenFalse_shouldReturnFalse() { + var asset = Asset.Builder.newInstance().property(Asset.PROPERTY_IS_CATALOG, "false").build(); + assertThat(asset.isCatalog()).isFalse(); + + var asset2 = Asset.Builder.newInstance().property(Asset.PROPERTY_IS_CATALOG, false).build(); + assertThat(asset2.isCatalog()).isFalse(); + } + + @Test + void isCatalog_whenTrue_shouldReturnTrue() { + var asset = Asset.Builder.newInstance().property(Asset.PROPERTY_IS_CATALOG, "true").build(); + assertThat(asset.isCatalog()).isTrue(); + + var asset2 = Asset.Builder.newInstance().property(Asset.PROPERTY_IS_CATALOG, true).build(); + assertThat(asset2.isCatalog()).isTrue(); + } + + @Test + void isCatalog_whenInvalidValid_shoudReturnFalse() { + var asset = Asset.Builder.newInstance().property(Asset.PROPERTY_IS_CATALOG, "foobar").build(); + assertThat(asset.isCatalog()).isFalse(); + } } diff --git a/spi/control-plane/asset-spi/src/testFixtures/java/org/eclipse/edc/connector/controlplane/asset/spi/testfixtures/AssetIndexTestBase.java b/spi/control-plane/asset-spi/src/testFixtures/java/org/eclipse/edc/connector/controlplane/asset/spi/testfixtures/AssetIndexTestBase.java index 31bd1207a4d..f45ecabfb44 100644 --- a/spi/control-plane/asset-spi/src/testFixtures/java/org/eclipse/edc/connector/controlplane/asset/spi/testfixtures/AssetIndexTestBase.java +++ b/spi/control-plane/asset-spi/src/testFixtures/java/org/eclipse/edc/connector/controlplane/asset/spi/testfixtures/AssetIndexTestBase.java @@ -143,6 +143,20 @@ void shouldFail_whenAssetAlreadyExists() { .usingRecursiveFieldByFieldElementComparator() .contains(asset); } + + @Test + void shouldCreate_withPrivateProperty() { + var asset = createAssetBuilder("test-asset").privateProperty("prop1", "val1") + .property(Asset.PROPERTY_IS_CATALOG, true) + .build(); + + assertThat(getAssetIndex().create(asset).succeeded()).isTrue(); + var assetFound = getAssetIndex().findById("test-asset"); + + assertThat(assetFound).isNotNull(); + assertThat(assetFound.isCatalog()).isTrue(); + + } } @Nested 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 cd00144b7c6..4e492b92560 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 @@ -15,6 +15,7 @@ package org.eclipse.edc.test.e2e.managementapi; import io.restassured.http.ContentType; +import jakarta.json.JsonArray; import jakarta.json.JsonObjectBuilder; import org.eclipse.edc.connector.controlplane.asset.spi.domain.Asset; import org.eclipse.edc.connector.controlplane.asset.spi.index.AssetIndex; @@ -44,16 +45,6 @@ */ public class AssetApiEndToEndTest { - @Nested - @EndToEndTest - @ExtendWith(ManagementEndToEndExtension.InMemory.class) - class InMemory extends Tests { } - - @Nested - @PostgresqlIntegrationTest - @ExtendWith(ManagementEndToEndExtension.Postgres.class) - class Postgres extends Tests { } - abstract static class Tests { @Test @@ -89,7 +80,10 @@ void createAsset_shouldBeStored(ManagementEndToEndTestContext context, AssetInde .add(CONTEXT, createObjectBuilder().add(EDC_PREFIX, EDC_NAMESPACE)) .add(TYPE, "Asset") .add(ID, id) - .add("properties", createPropertiesBuilder().build()) + .add("properties", createPropertiesBuilder().add("isCatalog", "true").build()) + .add("privateProperties", createObjectBuilder() + .add("anotherProp", "anotherVal") + .build()) .add("dataAddress", createObjectBuilder() .add(TYPE, "DataAddress") .add("type", "test-type") @@ -105,7 +99,10 @@ void createAsset_shouldBeStored(ManagementEndToEndTestContext context, AssetInde .statusCode(200) .body(ID, is(id)); - assertThat(assetIndex.findById(id)).isNotNull(); + var asset = assetIndex.findById(id); + assertThat(asset).isNotNull(); + assertThat(asset.isCatalog()).isTrue(); + assertThat(asset.getPrivateProperty(EDC_NAMESPACE + "anotherProp")).isEqualTo("anotherVal"); } @Test @@ -165,6 +162,78 @@ void createAsset_withoutPrefix_shouldAddEdcNamespace(ManagementEndToEndTestConte .allMatch(key -> key.startsWith(EDC_NAMESPACE)); } + @Test + void createAsset_whenCatalogAsset_shouldSetProperty(ManagementEndToEndTestContext context, AssetIndex assetIndex) { + var id = UUID.randomUUID().toString(); + var assetJson = createObjectBuilder() + .add(CONTEXT, createObjectBuilder() + .add(EDC_PREFIX, EDC_NAMESPACE)) + .add(TYPE, "CatalogAsset") + .add(ID, id) + .add("properties", createPropertiesBuilder().build()) + .add("dataAddress", createObjectBuilder() + .add(TYPE, "DataAddress") + .add("type", "test-type") + .build()) + .build(); + + context.baseRequest() + .contentType(ContentType.JSON) + .body(assetJson) + .post("/v3/assets") + .then() + .log().ifError() + .statusCode(200) + .body(ID, is(id)); + + var asset = assetIndex.findById(id); + assertThat(asset).isNotNull(); + assertThat(asset.isCatalog()).isTrue(); + } + + + @Test + void createAsset_whenCatalogInPrivateProps_shouldReturnCatalogType(ManagementEndToEndTestContext context, AssetIndex index) { + var id = UUID.randomUUID().toString(); + var assetJson = createObjectBuilder() + .add(CONTEXT, createObjectBuilder().add(EDC_PREFIX, EDC_NAMESPACE)) + .add(TYPE, "Asset") + .add(ID, id) + .add("properties", createPropertiesBuilder().add("isCatalog", "true").build()) + .add("dataAddress", createObjectBuilder() + .add(TYPE, "DataAddress") + .add("type", "test-type") + .build()) + .build(); + + // create the asset + context.baseRequest() + .contentType(ContentType.JSON) + .body(assetJson) + .post("/v3/assets") + .then() + .log().ifError() + .statusCode(200) + .body(ID, is(id)); + + // verify the property was set + var asset = index.findById(id); + assertThat(asset.isCatalog()).isTrue(); + + // query the asset, assert that @type: CatalogAsset + var assets = context.baseRequest() + .contentType(ContentType.JSON) + .body(context.query(criterion("id", "=", id))) + .post("/v3/assets/request") + .then() + .log().ifError() + .statusCode(200) + .extract().body().as(JsonArray.class); + + assertThat(assets).isNotNull().hasSize(1); + assertThat(Asset.EDC_CATALOG_ASSET_TYPE).contains(assets.get(0).asJsonObject().getString(TYPE)); + } + @Test void queryAsset_byContentType(ManagementEndToEndTestContext context, AssetIndex assetIndex) { //insert one asset into the index @@ -255,6 +324,32 @@ void queryAsset_byCustomComplexProperty(ManagementEndToEndTestContext context) { .body("size()", is(1)); } + @Test + void queryAsset_byCatalogProperty(ManagementEndToEndTestContext context, AssetIndex assetIndex) { + var id = UUID.randomUUID().toString(); + assetIndex.create(Asset.Builder.newInstance() + .property(Asset.PROPERTY_IS_CATALOG, true) + .id(id) + .contentType("application/octet-stream") + .dataAddress(createDataAddress().build()) + .build()); + + var assets = context.baseRequest() + .contentType(ContentType.JSON) + .body(context.query( + criterion(EDC_NAMESPACE + "isCatalog", "=", "true"), + criterion("id", "=", id))) + .post("/v3/assets/request") + .then() + .log().ifError() + .statusCode(200) + .extract().body().as(JsonArray.class); + + assertThat(assets).isNotNull().hasSize(1); + assertThat(Asset.EDC_CATALOG_ASSET_TYPE).contains(assets.get(0).asJsonObject().getString(TYPE)); + + } + @Test void updateAsset(ManagementEndToEndTestContext context, AssetIndex assetIndex) { var asset = createAsset().build(); @@ -309,4 +404,16 @@ private JsonObjectBuilder createPropertiesBuilder() { } + @Nested + @EndToEndTest + @ExtendWith(ManagementEndToEndExtension.InMemory.class) + class InMemory extends Tests { + } + + @Nested + @PostgresqlIntegrationTest + @ExtendWith(ManagementEndToEndExtension.Postgres.class) + class Postgres extends Tests { + } + }