diff --git a/extensions/wrapper/client/src/test/java/de/sovity/edc/client/ContractDefinitionPageApiServiceTest.java b/extensions/wrapper/client/src/test/java/de/sovity/edc/client/ContractDefinitionPageApiServiceTest.java new file mode 100644 index 000000000..3f266131a --- /dev/null +++ b/extensions/wrapper/client/src/test/java/de/sovity/edc/client/ContractDefinitionPageApiServiceTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.client; + +import org.eclipse.edc.connector.spi.contractdefinition.ContractDefinitionService; +import org.eclipse.edc.junit.annotations.ApiTest; +import org.eclipse.edc.junit.extensions.EdcExtension; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import static de.sovity.edc.client.ContractDefinitionTestUtils.createContractDefinition; + +import java.text.ParseException; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +@ApiTest +@ExtendWith(EdcExtension.class) +class ContractDefinitionPageApiServiceTest { + + @BeforeEach + void setUp(EdcExtension extension) { + extension.setConfiguration(TestUtils.createConfiguration(Map.of())); + } + + @Test + void startContractDefinition(ContractDefinitionService contractDefinitionService) throws ParseException { + var client = TestUtils.edcClient(); + + // arrange + createContractDefinition(contractDefinitionService); + + + // act + var result = client.uiApi().contractDefinitionPage(); + + // Get the contract definition + var contractDefinitions = result.getContractDefinitions(); + + // assert + var contractDefinition = contractDefinitions.get(0); + assertThat(contractDefinition.getContractDefinitionId()).isEqualTo(ContractDefinitionTestUtils.CONTRACT_DEFINITION_ID); + assertThat(contractDefinition.getContractPolicyId()).isEqualTo(ContractDefinitionTestUtils.CONTRACT_POLICY_ID); + assertThat(contractDefinition.getAccessPolicyId()).isEqualTo(ContractDefinitionTestUtils.ACCESS_POLICY_ID); + } + + +} diff --git a/extensions/wrapper/client/src/test/java/de/sovity/edc/client/ContractDefinitionTestUtils.java b/extensions/wrapper/client/src/test/java/de/sovity/edc/client/ContractDefinitionTestUtils.java new file mode 100644 index 000000000..8c2f23e89 --- /dev/null +++ b/extensions/wrapper/client/src/test/java/de/sovity/edc/client/ContractDefinitionTestUtils.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2022 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.client; + +import org.eclipse.edc.connector.contract.spi.types.offer.ContractDefinition; +import org.eclipse.edc.connector.spi.contractdefinition.ContractDefinitionService; +import org.eclipse.edc.spi.asset.AssetSelectorExpression; +import org.eclipse.edc.spi.query.Criterion; +import org.jetbrains.annotations.NotNull; +import java.text.ParseException; +import java.util.Arrays; + +public class ContractDefinitionTestUtils { + + public static final String CONTRACT_DEFINITION_ID = "contract-definition:eb934d1f-6582-4bab-85e6-af19a76f7e2b"; + + public static final String CONTRACT_POLICY_ID = "contract-policy:f52a5d30-6356-4a55-a75a-3c45d7a88c3e"; + + public static final String ACCESS_POLICY_ID = "access-policy:eb934d1f-6582-4bab-85e6-af19a76f7e2b"; + + @NotNull + public static void createContractDefinition(ContractDefinitionService contractDefinitionService) throws ParseException { + + // Create an AssetSelectorExpression + AssetSelectorExpression selectorExpression = AssetSelectorExpression.Builder.newInstance() + .criteria(Arrays.asList( + new Criterion("criteria1", "=", "value1"), + new Criterion("criteria2", "=", "value2") + )) + .build(); + + var definition = ContractDefinition.Builder.newInstance() + .id(CONTRACT_DEFINITION_ID) + .contractPolicyId(CONTRACT_POLICY_ID) + .accessPolicyId(ACCESS_POLICY_ID) + .validity(10000L) + .selectorExpression(selectorExpression) + .build(); + + contractDefinitionService.create(definition); + + + } + + +} diff --git a/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/WrapperExtension.java b/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/WrapperExtension.java index f4cb78a58..de636cc69 100644 --- a/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/WrapperExtension.java +++ b/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/WrapperExtension.java @@ -89,7 +89,7 @@ public void initialize(ServiceExtensionContext context) { policyEngine, transferProcessService, transferProcessStore, - (org.eclipse.edc.connector.contract.spi.offer.ContractDefinitionService) contractDefinitionService + contractDefinitionService ); wrapperExtensionContext.jaxRsResources().forEach(resource -> diff --git a/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/WrapperExtensionContextBuilder.java b/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/WrapperExtensionContextBuilder.java index 4d5f333d6..c31a74647 100644 --- a/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/WrapperExtensionContextBuilder.java +++ b/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/WrapperExtensionContextBuilder.java @@ -25,6 +25,7 @@ import de.sovity.edc.ext.wrapper.api.ui.pages.contracts.services.TransferProcessStateService; import de.sovity.edc.ext.wrapper.api.ui.pages.contracts.services.TransferRequestBuilder; import de.sovity.edc.ext.wrapper.api.ui.pages.contracts.services.utils.ContractAgreementUtils; +import de.sovity.edc.ext.wrapper.api.ui.pages.contracts.services.utils.ContractDefinitionUtils; import de.sovity.edc.ext.wrapper.api.ui.pages.contracts.services.utils.ContractNegotiationUtils; import de.sovity.edc.ext.wrapper.api.ui.pages.contracts.services.utils.TransformerRegistryUtils; import de.sovity.edc.ext.wrapper.api.ui.pages.transferhistory.TransferHistoryPageApiService; @@ -41,6 +42,7 @@ import org.eclipse.edc.connector.policy.spi.store.PolicyDefinitionStore; import org.eclipse.edc.connector.spi.asset.AssetService; import org.eclipse.edc.connector.spi.contractagreement.ContractAgreementService; +import org.eclipse.edc.connector.spi.contractdefinition.ContractDefinitionService; import org.eclipse.edc.connector.spi.contractnegotiation.ContractNegotiationService; import org.eclipse.edc.connector.spi.transferprocess.TransferProcessService; import org.eclipse.edc.connector.transfer.spi.store.TransferProcessStore; @@ -74,8 +76,8 @@ public static WrapperExtensionContext buildContext( PolicyDefinitionStore policyDefinitionStore, PolicyEngine policyEngine, TransferProcessService transferProcessService, - TransferProcessStore transferProcessStore - ) { + TransferProcessStore transferProcessStore, + ContractDefinitionService contractDefinitionService) { // UI API var transferProcessStateService = new TransferProcessStateService(); var contractAgreementPageCardBuilder = new ContractAgreementPageCardBuilder( @@ -92,8 +94,8 @@ public static WrapperExtensionContext buildContext( var transferHistoryPageApiService = new TransferHistoryPageApiService(assetService, contractAgreementService, contractNegotiationStore, transferProcessService, transferProcessStateService); var transferHistoryPageAssetFetcherService = new TransferHistoryPageAssetFetcherService(assetService, transferProcessService); - var transferHistoryPageApiService = new TransferHistoryPageApiService(); - var contractDefinitionApiService = new ContractDefinitionApiService(); + var contractDefinitionUtils = new ContractDefinitionUtils(); + var contractDefinitionApiService = new ContractDefinitionApiService(contractDefinitionService,contractDefinitionUtils); var transformerRegistryUtils = new TransformerRegistryUtils(dtoTransformerRegistry); var contractNegotiationUtils = new ContractNegotiationUtils(contractNegotiationService); var contractAgreementUtils = new ContractAgreementUtils(contractAgreementService); @@ -111,9 +113,10 @@ public static WrapperExtensionContext buildContext( var uiResource = new UiResource( contractAgreementApiService, contractAgreementTransferApiService, + contractDefinitionApiService, transferHistoryPageApiService, transferHistoryPageAssetFetcherService - contractDefinitionApiService + ); // Use Case API diff --git a/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/api/ui/UiResource.java b/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/api/ui/UiResource.java index 67ba49881..93f86395a 100644 --- a/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/api/ui/UiResource.java +++ b/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/api/ui/UiResource.java @@ -26,11 +26,7 @@ import de.sovity.edc.ext.wrapper.api.ui.pages.transferhistory.TransferHistoryPageAssetFetcherService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.Produces; +import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; import lombok.RequiredArgsConstructor; import org.eclipse.edc.api.model.IdResponseDto; @@ -84,7 +80,7 @@ public AssetDto getTransferProcessAsset(@PathParam("transferProcessId") String t @GET @Path("pages/contract-definition-page") @Produces(MediaType.APPLICATION_JSON) - public ContractDefinitionPage contractDefinitionPageEndpoint() { + public ContractDefinitionPage contractDefinitionPage() { return new ContractDefinitionPage(contractDefinitionApiService.getContractDefinitions()); } } diff --git a/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/api/ui/model/ContractDefinitionEntry.java b/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/api/ui/model/ContractDefinitionEntry.java index d2e66a9a7..63b92faed 100644 --- a/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/api/ui/model/ContractDefinitionEntry.java +++ b/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/api/ui/model/ContractDefinitionEntry.java @@ -16,7 +16,6 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import org.eclipse.edc.spi.query.Criterion; import java.util.List; @@ -31,7 +30,7 @@ public class ContractDefinitionEntry { private String contractPolicyId; @Schema(description = "Criteria for the contract", requiredMode = Schema.RequiredMode.REQUIRED) - private List criteria; + private List criteria; @Schema(description = "Contract Definition ID", requiredMode = Schema.RequiredMode.REQUIRED) private String contractDefinitionId; diff --git a/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/api/ui/model/CriterionDto.java b/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/api/ui/model/CriterionDto.java new file mode 100644 index 000000000..ebee32728 --- /dev/null +++ b/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/api/ui/model/CriterionDto.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.ext.wrapper.api.ui.model; + + +import lombok.Getter; +import lombok.Setter; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; + + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class CriterionDto { + private String operandLeft; + private String operator; + private String operatorRight; + private String[] operatorRightArray; + private CriterionType type; + + public static CriterionDto forString(String operandLeft, String operator, String operatorRight) { + return new CriterionDto(operandLeft, operator, operatorRight, null, CriterionType.STRING); + } + + public static CriterionDto forStringArray(String operandLeft, String operator, String[] operatorRightArray) { + return new CriterionDto(operandLeft, operator, null, operatorRightArray, CriterionType.STRING_ARRAY); + } + + public static CriterionDto forJson(String operandLeft, String operator, String operatorRight) { + return new CriterionDto(operandLeft, operator, operatorRight, null, CriterionType.JSON); + } + +} + +enum CriterionType { + STRING, STRING_ARRAY, JSON +} diff --git a/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/api/ui/pages/contracts/ContractDefinitionApiService.java b/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/api/ui/pages/contracts/ContractDefinitionApiService.java index 7e641c168..9ede08aad 100644 --- a/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/api/ui/pages/contracts/ContractDefinitionApiService.java +++ b/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/api/ui/pages/contracts/ContractDefinitionApiService.java @@ -15,48 +15,36 @@ package de.sovity.edc.ext.wrapper.api.ui.pages.contracts; import de.sovity.edc.ext.wrapper.api.ui.model.ContractDefinitionEntry; -import de.sovity.edc.ext.wrapper.api.ui.pages.contracts.services.ContractAgreementData; +import de.sovity.edc.ext.wrapper.api.ui.pages.contracts.services.utils.ContractDefinitionUtils; import lombok.RequiredArgsConstructor; -import org.eclipse.edc.connector.contract.spi.negotiation.store.ContractNegotiationStore; -import org.eclipse.edc.connector.contract.spi.types.agreement.ContractAgreement; -import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractNegotiation; import org.eclipse.edc.connector.contract.spi.types.offer.ContractDefinition; -import org.eclipse.edc.connector.spi.asset.AssetService; -import org.eclipse.edc.connector.spi.contractagreement.ContractAgreementService; import org.eclipse.edc.connector.spi.contractdefinition.ContractDefinitionService; import org.eclipse.edc.spi.query.QuerySpec; -import org.eclipse.edc.spi.types.domain.asset.Asset; -import org.jetbrains.annotations.NotNull; +import java.util.Comparator; import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static java.util.stream.Collectors.groupingBy; -import static java.util.stream.Collectors.toList; - @RequiredArgsConstructor public class ContractDefinitionApiService { private final ContractDefinitionService contractDefinitionService; + private final ContractDefinitionUtils contractDefinitionUtils; + public List getContractDefinitions() { - // Obtain all contract definitions - var definitions = getAllContractDefinitons(); - return definitions.stream() + var definitions = getAllContractDefinitions(); + return definitions.stream().sorted(Comparator.comparing(ContractDefinition::getCreatedAt).reversed()) .map(definition -> { - var entry = new ContractDefinitionEntry(); - entry.setContractDefinitionId(definition.getId()); - entry.setAccessPolicyId(definition.getAccessPolicyId()); - entry.setContractPolicyId(definition.getContractPolicyId()); - entry.setCriteria(definition.getSelectorExpression().getCriteria()); // This depends on how the criteria are stored in your system - return entry; - }) - .collect(Collectors.toList()); + var entry = new ContractDefinitionEntry(); + entry.setContractDefinitionId(definition.getId()); + entry.setAccessPolicyId(definition.getAccessPolicyId()); + entry.setContractPolicyId(definition.getContractPolicyId()); + entry.setCriteria(contractDefinitionUtils.mapToCriterionDtos(definition.getSelectorExpression().getCriteria())); + return entry; + }).toList(); } - private List getAllContractDefinitons() { + + private List getAllContractDefinitions() { return contractDefinitionService.query(QuerySpec.max()).getContent().toList(); } diff --git a/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/api/ui/pages/contracts/services/utils/ContractDefinitionUtils.java b/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/api/ui/pages/contracts/services/utils/ContractDefinitionUtils.java new file mode 100644 index 000000000..a5d4e6dd7 --- /dev/null +++ b/extensions/wrapper/wrapper/src/main/java/de/sovity/edc/ext/wrapper/api/ui/pages/contracts/services/utils/ContractDefinitionUtils.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2023 sovity GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * sovity GmbH - initial API and implementation + * + */ + +package de.sovity.edc.ext.wrapper.api.ui.pages.contracts.services.utils; + + +import de.sovity.edc.ext.wrapper.api.ui.model.CriterionDto; +import lombok.RequiredArgsConstructor; +import org.eclipse.edc.spi.query.Criterion; + +import java.util.List; +import java.util.stream.Collectors; + +@RequiredArgsConstructor +public class ContractDefinitionUtils { + + public CriterionDto mapToCriterionDto(Criterion criterion) { + if (criterion == null) { + return null; + } + + CriterionDto dto = new CriterionDto(); + dto.setOperandLeft(String.valueOf(criterion.getOperandLeft())); + dto.setOperator(criterion.getOperator()); + dto.setOperatorRight(String.valueOf(criterion.getOperandRight())); + + // Since the operatorRightArray and type fields don't exist in the Criterion object + // they can't be mapped in this function + + return dto; + } + + public List mapToCriterionDtos(List criteria) { + if (criteria == null) { + return null; + } + + return criteria.stream().map(this::mapToCriterionDto).collect(Collectors.toList()); + } + + +}