Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(impl):[#359] update registry impl for lookup #829

Merged
merged 11 commits into from
Mar 27, 2024
Merged
7 changes: 5 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
_**For better traceability add the corresponding GitHub issue number in each changelog entry, please.**_

## [Unreleased]
### Changed
- IRS now supports Asset Administration Shell v3.1 - adjusted lookup shells endpoint changes (assetIds query param is encoded). #359
-
### Added
- Extended EdcPolicyDefinitionService to check if a policy in the edc exists

## [4.8.0] - 2024-03-18
### Changed
- Improved maintainability in EdcSubmodelClientImpl by reduced method visibility and better naming (in context of #448).
- EdcPolicyDefinitionService, EdcContractDefinitionService and EdcAssetService return throw AlreadyExist exceptions when Conflict is returned from
EDC
- EdcPolicyDefinitionService, EdcContractDefinitionService and EdcAssetService throw AlreadyExist exceptions when
conflict is returned from EDC
- Added AssetAdministrationShellDescriptor specificAssetIds support for externalSubjectId required for data provisioning
- Registering a job - aspects array is now accepting full urn of aspect model instead of name only, eg. 'urn:bamm:io.catenax.single_level_bom_as_built:2.0.0#SingleLevelBomAsBuilt' instead 'SingleLevelBomAsBuilt'. #439
- Changed the version of irs-registry-client from 1.6.0-SNAPSHOT to 1.6.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@
package org.eclipse.tractusx.irs;

import static com.github.tomakehurst.wiremock.client.WireMock.containing;
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo;
import static com.github.tomakehurst.wiremock.client.WireMock.verify;
import static org.assertj.core.api.Assertions.assertThat;
import static org.eclipse.tractusx.irs.WiremockSupport.createEndpointDataReference;
import static org.eclipse.tractusx.irs.WiremockSupport.encodedAssetIds;
import static org.eclipse.tractusx.irs.WiremockSupport.randomUUID;
import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockSupport.DISCOVERY_FINDER_PATH;
import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockSupport.DISCOVERY_FINDER_URL;
Expand Down Expand Up @@ -158,7 +160,7 @@ void shouldStartApplicationAndCollectSemanticModels() throws SchemaNotFoundExcep
void shouldStopJobAfterDepthIsReached() {
// Arrange
final String globalAssetIdLevel1 = "globalAssetId";
final String globalAssetIdLevel2 = "urn:uuid:6d505432-8b31-4966-9514-4b753372683f";
final String globalAssetIdLevel2 = "urn:uuid:7e4541ea-bb0f-464c-8cb3-021abccbfaf5";

WiremockSupport.successfulSemanticModelRequest();
WiremockSupport.successfulSemanticHubRequests();
Expand Down Expand Up @@ -297,7 +299,7 @@ private void successfulRegistryAndDataRequest(final String globalAssetId, final
final String registryEdcAssetId = "registry-asset";
successfulNegotiation(registryEdcAssetId);
stubFor(getLookupShells200(PUBLIC_LOOKUP_SHELLS_PATH, List.of(shellId)).withQueryParam("assetIds",
containing(globalAssetId)));
equalTo(encodedAssetIds(globalAssetId))));
stubFor(getShellDescriptor200(PUBLIC_SHELL_DESCRIPTORS_PATH + WiremockSupport.encodedId(shellId), bpn,
submodelDescriptors, globalAssetId, shellId, idShort));
successfulNegotiation(edcAssetId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,12 @@
import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference;
import org.eclipse.tractusx.irs.component.PartChainIdentificationKey;
import org.eclipse.tractusx.irs.component.RegisterJob;
import org.eclipse.tractusx.irs.component.assetadministrationshell.IdentifierKeyValuePair;
import org.eclipse.tractusx.irs.component.enums.Direction;
import org.eclipse.tractusx.irs.data.StringMapper;
import org.eclipse.tractusx.irs.edc.client.configuration.JsonLdConfiguration;
import org.eclipse.tractusx.irs.edc.client.model.EDRAuthCode;
import org.eclipse.tractusx.irs.registryclient.util.SerializationHelper;
import org.eclipse.tractusx.irs.semanticshub.SemanticHubWireMockSupport;
import org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockSupport;
import org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockSupport;
Expand Down Expand Up @@ -97,6 +99,14 @@ static String encodedId(final String shellId) {
return encodeBase64String(shellId.getBytes(StandardCharsets.UTF_8));
}

static String encodedAssetIds(final String assetIds) {
final IdentifierKeyValuePair globalAssetId = IdentifierKeyValuePair.builder()
.name("globalAssetId")
.value(assetIds)
.build();
return Base64.getEncoder().encodeToString(new SerializationHelper().serialize(globalAssetId));
}

static void verifyDiscoveryCalls(final int times) {
verify(times, postRequestedFor(urlPathEqualTo(DiscoveryServiceWiremockSupport.DISCOVERY_FINDER_PATH)));
verify(times, postRequestedFor(urlPathEqualTo(DiscoveryServiceWiremockSupport.EDC_DISCOVERY_PATH)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference;
import org.eclipse.tractusx.irs.component.assetadministrationshell.AssetAdministrationShellDescriptor;
import org.eclipse.tractusx.irs.component.assetadministrationshell.IdentifierKeyValuePair;
import org.eclipse.tractusx.irs.data.StringMapper;
import org.eclipse.tractusx.irs.registryclient.util.SerializationHelper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
Expand All @@ -53,6 +53,8 @@ public class DecentralDigitalTwinRegistryClient {
private final String shellDescriptorTemplate;
private final String lookupShellsTemplate;

private final SerializationHelper serializationHelper = new SerializationHelper();

public DecentralDigitalTwinRegistryClient(final RestTemplate edcRestTemplate,
@Value("${digitalTwinRegistry.shellDescriptorTemplate:}") final String shellDescriptorTemplate,
@Value("${digitalTwinRegistry.lookupShellsTemplate:}") final String lookupShellsTemplate) {
Expand All @@ -61,10 +63,6 @@ public DecentralDigitalTwinRegistryClient(final RestTemplate edcRestTemplate,
this.lookupShellsTemplate = lookupShellsTemplate;
}

private static String encodeWithBase64(final String aasIdentifier) {
return Base64.getEncoder().encodeToString(aasIdentifier.getBytes(StandardCharsets.UTF_8));
}

@Retry(name = "registry")
public AssetAdministrationShellDescriptor getAssetAdministrationShellDescriptor(
final EndpointDataReference endpointDataReference, final String aasIdentifier) {
Expand All @@ -78,14 +76,22 @@ public AssetAdministrationShellDescriptor getAssetAdministrationShellDescriptor(

@Retry(name = "registry")
public LookupShellsResponse getAllAssetAdministrationShellIdsByAssetLink(
final EndpointDataReference endpointDataReference, final List<IdentifierKeyValuePair> assetIds) {
final EndpointDataReference endpointDataReference, final IdentifierKeyValuePair assetIds) {
final String shellLookupEndpoint = endpointDataReference.getEndpoint() + lookupShellsTemplate;
final UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(shellLookupEndpoint);
uriBuilder.uriVariables(Map.of(PLACEHOLDER_ASSET_IDS, StringMapper.mapToString(assetIds)));
uriBuilder.uriVariables(Map.of(PLACEHOLDER_ASSET_IDS, encodeWithBase64(assetIds)));
return edcRestTemplate.exchange(uriBuilder.build().toUri(), HttpMethod.GET,
new HttpEntity<>(null, headers(endpointDataReference)), LookupShellsResponse.class).getBody();
}

private String encodeWithBase64(final String aasIdentifier) {
return Base64.getEncoder().encodeToString(aasIdentifier.getBytes(StandardCharsets.UTF_8));
}

private String encodeWithBase64(final IdentifierKeyValuePair assetIds) {
return Base64.getEncoder().encodeToString(serializationHelper.serialize(assetIds));
}

private HttpHeaders headers(final EndpointDataReference dataReference) {
final HttpHeaders headers = new HttpHeaders();
headers.setAccept(List.of(MediaType.APPLICATION_JSON));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ private String mapToShellId(final EndpointDataReference endpointDataReference, f

// Try to map the provided ID to the corresponding asset administration shell ID
final var mappingResultStream = decentralDigitalTwinRegistryClient.getAllAssetAdministrationShellIdsByAssetLink(
endpointDataReference, List.of(identifierKeyValuePair)).getResult().stream();
endpointDataReference, identifierKeyValuePair).getResult().stream();

// Special scenario: Multiple DTs with the same globalAssetId in one DTR, see:
// docs/arc42/cross-cutting/discovery-DTR--multiple-DTs-with-the-same-globalAssedId-in-one-DTR.puml
Expand Down Expand Up @@ -340,7 +340,7 @@ private Collection<String> lookupShellIds(final String bpn, final EndpointDataRe
try {
return decentralDigitalTwinRegistryClient.getAllAssetAdministrationShellIdsByAssetLink(
endpointDataReference,
List.of(IdentifierKeyValuePair.builder().name("manufacturerId").value(bpn).build())).getResult();
IdentifierKeyValuePair.builder().name("manufacturerId").value(bpn).build()).getResult();
} finally {
watch.stop();
log.info(TOOK_MS, watch.getLastTaskName(), watch.getLastTaskTimeMillis());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/********************************************************************************
* Copyright (c) 2022,2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
* Copyright (c) 2021,2024 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* 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.
*
* 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.
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/
package org.eclipse.tractusx.irs.registryclient.util;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.SerializationFeature;

/**
* Serializer helper
*/
public class SerializationHelper {

private static final ObjectWriter WRITER;
static {
final ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
WRITER = mapper.writer();
}

public byte[] serialize(final Object object) {
final ByteArrayOutputStream stream = new ByteArrayOutputStream();
try {
WRITER.writeValue(stream, object);
return stream.toByteArray();
} catch (final IOException e) {
return new byte[0];
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference;
import org.eclipse.tractusx.irs.component.assetadministrationshell.AssetAdministrationShellDescriptor;
import org.eclipse.tractusx.irs.component.assetadministrationshell.IdentifierKeyValuePair;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpMethod;
Expand Down Expand Up @@ -59,7 +60,7 @@ void shouldCallForAllAssetAdministrationShellIdsByAssetLink() {
ResponseEntity.of(Optional.of(LookupShellsResponse.builder().result(Collections.emptyList()).build())));

// when
client.getAllAssetAdministrationShellIdsByAssetLink(endpointDataReference, new ArrayList<>());
client.getAllAssetAdministrationShellIdsByAssetLink(endpointDataReference, IdentifierKeyValuePair.builder().build());

// then
verify(restTemplate).exchange(any(), eq(HttpMethod.GET), any(), eq(LookupShellsResponse.class));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ void shouldReturnExpectedShell() throws RegistryServiceException {
endpointDataRefFutures);

when(decentralDigitalTwinRegistryClient.getAllAssetAdministrationShellIdsByAssetLink(any(),
anyList())).thenReturn(lookupShellsResponse);
any(IdentifierKeyValuePair.class))).thenReturn(lookupShellsResponse);
when(decentralDigitalTwinRegistryClient.getAssetAdministrationShellDescriptor(any(), any())).thenReturn(
expectedShell);

Expand Down Expand Up @@ -132,7 +132,7 @@ void whenInterruptedExceptionOccurs() throws ExecutionException, InterruptedExce
connectorEndpoints, "bpn")).thenReturn(dataRefFutures);

when(decentralDigitalTwinRegistryClient.getAllAssetAdministrationShellIdsByAssetLink(any(),
anyList())).thenReturn(lookupShellsResponse);
any(IdentifierKeyValuePair.class))).thenReturn(lookupShellsResponse);
when(decentralDigitalTwinRegistryClient.getAssetAdministrationShellDescriptor(any(), any())).thenReturn(
shellDescriptor(emptyList()));

Expand Down Expand Up @@ -166,7 +166,7 @@ void whenExecutionExceptionOccurs() {
connectorEndpoints, "bpn")).thenReturn(dataRefFutures);

when(decentralDigitalTwinRegistryClient.getAllAssetAdministrationShellIdsByAssetLink(any(),
anyList())).thenReturn(lookupShellsResponse);
any(IdentifierKeyValuePair.class))).thenReturn(lookupShellsResponse);
when(decentralDigitalTwinRegistryClient.getAssetAdministrationShellDescriptor(any(), any())).thenReturn(
shellDescriptor(emptyList()));

Expand Down Expand Up @@ -230,7 +230,7 @@ void shouldReturnTheExpectedGlobalAssetId() throws RegistryServiceException {
when(endpointDataForConnectorsService.createFindEndpointDataForConnectorsFutures(anyList(), any())).thenReturn(
dataRefFutures);
when(decentralDigitalTwinRegistryClient.getAllAssetAdministrationShellIdsByAssetLink(any(),
anyList())).thenReturn(lookupShellsResponse);
any(IdentifierKeyValuePair.class))).thenReturn(lookupShellsResponse);
when(decentralDigitalTwinRegistryClient.getAssetAdministrationShellDescriptor(any(), any())).thenReturn(
expectedShell);

Expand Down