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 : Draft code changes for multi submodel version support impl #135

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
package org.eclipse.tractusx.sde.common.submodel.executor;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

import lombok.Getter;
Expand All @@ -39,47 +40,97 @@ public void init(JsonObject submodelSchema) {
public String getNameOfModel() {
return submodelSchema.get("id").getAsString();
}

public JsonObject getSubmodelItems() {
return submodelSchema.get("items").getAsJsonObject();
}

public JsonObject getSubmodelProperties() {
return getSubmodelItems().get("properties").getAsJsonObject();
}

public JsonArray getSubmodelRequiredFields() {
return getSubmodelItems().get("required").getAsJsonArray();
}

public String getIdShortOfModel() {
return this.submodelSchema.get("idShort").getAsString();
}

public String getVersionOfModel() {
return this.submodelSchema.get("version").getAsString();
}

public String getsemanticIdOfModel() {
return this.submodelSchema.get("semantic_id").getAsString();
}


public String getSubmoduleUriPathOfSubmodule() {
JsonElement jsonElement = this.submodelSchema.get("submodelUriPath");
return jsonElement == null || jsonElement.isJsonNull() ? "public" : jsonElement.getAsString();
}

public JsonObject getAddOnOfModel() {
return this.submodelSchema.get("addOn").getAsJsonObject();
}

public String getIdentifierOfModel() {
return this.getAddOnOfModel().get("identifier").getAsString();
}

public boolean checkShellCreateOption() {
JsonElement jsonElement = this.getAddOnOfModel().get("createShellIfNotExist");
return jsonElement == null || jsonElement.isJsonNull() || jsonElement.getAsBoolean();
}

public JsonObject checkIsRelationSubmodel() {
JsonElement jsonElement = this.getAddOnOfModel().get("isRelationSubmodel");
return jsonElement == null || jsonElement.isJsonNull() ? null : jsonElement.getAsJsonObject();
}

public JsonArray checkIsAutoPopulatedfieldsSubmodel() {
JsonElement jsonElement = this.getAddOnOfModel().get("autoPopulatedfields");
return jsonElement == null || jsonElement.isJsonNull() ? null : jsonElement.getAsJsonArray();
}

public JsonObject getSpecificAssetIdsSpecsOfModel() {
return this.getAddOnOfModel().get("lookupShellSpecificAssetIdsSpecs").getAsJsonObject();
}

public JsonObject getCreateShellSpecificAssetIdsSpecsOfModel() {
JsonElement jsonElement = this.getAddOnOfModel().get("createShellSpecificAssetIdsSpecs");
return jsonElement == null || jsonElement.isJsonNull() ? getSpecificAssetIdsSpecsOfModel()
: jsonElement.getAsJsonObject();
}

public JsonObject getBPNDiscoverySpecsOfModel() {
return this.getAddOnOfModel().get("bpnDiscoverySpecs").getAsJsonObject();
}

public JsonArray getShortIdSpecsOfModel() {
return this.getAddOnOfModel().get("shortIdSpecs").getAsJsonArray();
}

public JsonObject getResponseTemplateOfModel() {
return this.getAddOnOfModel().get("responseTemplate").getAsJsonObject();
}

public String getSubmodelShortDescriptionOfModel() {
return this.submodelSchema.get("shortDescription").getAsString();
}

public String getSubmodelTitleIdOfModel() {
return this.submodelSchema.get("title").getAsString();
}

public JsonObject getSubmodelDependentRequiredFields() {
return getSubmodelItems().get("dependentRequired").getAsJsonObject();
}

protected void logDebug(String message) {
log.debug(String.format("[%s] %s", this.getClass().getSimpleName(), message));
}

protected void logInfo(String message) {
log.info(String.format("[%s] %s", this.getClass().getSimpleName(), message));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/********************************************************************************
* Copyright (c) 2022, 2023 T-Systems International GmbH
* Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation
* Copyright (c) 2022, 2024 T-Systems International GmbH
* Copyright (c) 2022, 2024 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
Expand All @@ -24,6 +24,7 @@
import org.eclipse.tractusx.sde.common.utils.UUIdGenerator;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

import lombok.SneakyThrows;
Expand All @@ -33,8 +34,12 @@ public class GenerateUrnUUID extends Step {

@SneakyThrows
public ObjectNode run(ObjectNode jsonObject, String processId) {

String uUID = jsonObject.get("uuid").asText();

JsonNode jsonNode = jsonObject.get("uuid");
if (jsonNode == null || jsonNode.isNull())
return jsonObject;

String uUID = jsonNode.asText();
if (uUID == null || uUID.isBlank() || uUID.equals("null")) {
jsonObject.put("uuid", UUIdGenerator.getUrnUuid());
} else if (!uUID.startsWith(UUIdGenerator.URN_UUID_PREFIX)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
/********************************************************************************
* Copyright (c) 2024 T-Systems International GmbH
* Copyright (c) 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.sde.core.submodel.executor.step;

import java.net.URI;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.eclipse.tractusx.sde.common.exception.CsvHandlerDigitalTwinUseCaseException;
import org.eclipse.tractusx.sde.common.exception.CsvHandlerUseCaseException;
import org.eclipse.tractusx.sde.digitaltwins.entities.request.ShellLookupRequest;
import org.eclipse.tractusx.sde.digitaltwins.entities.response.ShellDescriptorResponse;
import org.eclipse.tractusx.sde.digitaltwins.entities.response.ShellLookupResponse;
import org.eclipse.tractusx.sde.digitaltwins.facilitator.DigitalTwinsFacilitator;
import org.eclipse.tractusx.sde.digitaltwins.facilitator.DigitalTwinsUtility;
import org.eclipse.tractusx.sde.digitaltwins.gateways.external.EDCDigitalTwinProxyForLookUp;
import org.eclipse.tractusx.sde.edc.model.edr.EDRCachedByIdResponse;
import org.eclipse.tractusx.sde.edc.model.response.QueryDataOfferModel;
import org.eclipse.tractusx.sde.edc.util.EDCAssetUrlCacheService;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.gson.JsonObject;

import feign.FeignException;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
@RequiredArgsConstructor
public class DigitalTwinLookUpInRegistry {

private final DigitalTwinsUtility digitalTwinsUtility;

private final EDCAssetUrlCacheService edcAssetUrlCacheService;

private final EDCDigitalTwinProxyForLookUp eDCDigitalTwinProxyForLookUp;

private final DigitalTwinsFacilitator digitalTwinFacilitator;

@SneakyThrows
public String lookupTwinInLocalRrgistry(Integer rowIndex, Map<String, String> specificAssetIds,

Check notice

Code scanning / CodeQL

Useless parameter Note

The parameter 'rowIndex' is never used.
ObjectNode jsonObject, JsonObject asJsonObject) {

Check notice

Code scanning / CodeQL

Useless parameter Note

The parameter 'jsonObject' is never used.

Check notice

Code scanning / CodeQL

Useless parameter Note

The parameter 'asJsonObject' is never used.

ShellLookupRequest shellLookupRequest = digitalTwinsUtility.getShellLookupRequest(specificAssetIds);
List<String> shellIds = digitalTwinFacilitator.shellLookup(shellLookupRequest);

String shellId;

if (shellIds.isEmpty()) {
throw new CsvHandlerDigitalTwinUseCaseException(
String.format("No relational aspect found in DT %s", shellLookupRequest.toJsonString()));
} else if (shellIds.size() == 1) {
log.debug(String.format("Shell id found for '%s'", shellLookupRequest.toJsonString()));
shellId = shellIds.stream().findFirst().orElse(null);
log.debug(String.format("Shell id '%s'", shellId));
} else {
throw new CsvHandlerDigitalTwinUseCaseException(
String.format("Multiple ids found on aspect %s", shellLookupRequest.toJsonString()));
}

List<ShellDescriptorResponse> shellDescriptorResponseList = digitalTwinFacilitator
.getShellDescriptorsWithSubmodelDetails(shellIds);
String shellGlobalassetId = null;

for (ShellDescriptorResponse shellDescriptorResponse : shellDescriptorResponseList) {
shellGlobalassetId = shellDescriptorResponse.getGlobalAssetId();
}

return shellGlobalassetId;
}

@SneakyThrows
public String lookupTwinRemotely(Integer rowIndex, Map<String, String> specificAssetIds,
String bpnForRemoteRegistry, ObjectNode jsonObject, JsonObject asJsonObject) {

Check notice

Code scanning / CodeQL

Useless parameter Note

The parameter 'asJsonObject' is never used.

ShellLookupRequest shellLookupRequest = digitalTwinsUtility.getShellLookupRequest(specificAssetIds);

List<QueryDataOfferModel> queryDataOffers = edcAssetUrlCacheService.getDDTRUrl(bpnForRemoteRegistry);

String childUUID = null;
String msg = "";

for (QueryDataOfferModel dtOffer : queryDataOffers) {

EDRCachedByIdResponse edrToken = edcAssetUrlCacheService.verifyAndGetToken(bpnForRemoteRegistry, dtOffer);

if (edrToken != null) {
childUUID = lookUpChildTwin(rowIndex, shellLookupRequest, jsonObject, bpnForRemoteRegistry, edrToken,
dtOffer);
if (childUUID != null) {
break;
}
} else {
msg = ", EDC connector " + dtOffer.getConnectorOfferUrl() + ", assetId " + dtOffer.getAssetId()
+ ", The EDR token is null to find child twin ";
log.warn(rowIndex + msg + shellLookupRequest.toJsonString());
}
}

if (queryDataOffers.isEmpty()) {
throw new CsvHandlerUseCaseException(rowIndex, "No DTR registry found for child aspect look up");
}

if (childUUID == null) {
throw new CsvHandlerUseCaseException(rowIndex,
"No child aspect found for " + shellLookupRequest.toJsonString());
}

return childUUID;
}

@SneakyThrows
private String lookUpChildTwin(Integer rowIndex, ShellLookupRequest shellLookupRequest, ObjectNode jsonObject,
String bpnForRemoteRegistry, EDRCachedByIdResponse edrToken, QueryDataOfferModel dtOffer) {

String childUUID = null;
String endpoint = edrToken.getEndpoint();
String dtOfferUrl = dtOffer.getConnectorOfferUrl();
try {

Map<String, String> header = new HashMap<>();
header.put(edrToken.getAuthKey(), edrToken.getAuthCode());
header.put("Edc-Bpn", bpnForRemoteRegistry);

ShellLookupResponse shellLookup = eDCDigitalTwinProxyForLookUp.shellLookup(new URI(endpoint),
digitalTwinsUtility.encodeAssetIdsObjectOnlyPartInstanceId(shellLookupRequest), header);

childUUID = getChildSubmodelDetails(rowIndex, shellLookupRequest, endpoint, header, jsonObject, dtOfferUrl,
shellLookup.getResult());

} catch (FeignException e) {
String err = e.contentUTF8();
err = StringUtils.isBlank(err) ? e.getMessage() : err;
String errorMsg = "Unable to look up child twin " + dtOfferUrl + ", assetId " + dtOffer.getAssetId() + ", "
+ shellLookupRequest.toJsonString() + " because: " + err;
log.error("FeignException : " + errorMsg);
} catch (CsvHandlerDigitalTwinUseCaseException e) {
throw e;
} catch (Exception e) {
String errorMsg = "Unable to look up child twin " + dtOfferUrl + ", assetId " + dtOffer.getAssetId() + ", "
+ shellLookupRequest.toJsonString() + "because: " + e.getMessage();
log.error("Exception : " + errorMsg);
}

return childUUID;
}

@SneakyThrows
private String getChildSubmodelDetails(Integer rowIndex, ShellLookupRequest shellLookupRequest, String endpoint,
Map<String, String> header, ObjectNode jsonObject, String dtOfferUrl, List<String> childshellIds)

Check notice

Code scanning / CodeQL

Useless parameter Note

The parameter 'jsonObject' is never used.
throws CsvHandlerDigitalTwinUseCaseException {

String childUUID = null;
if (childshellIds == null) {
log.warn(rowIndex + ", " + dtOfferUrl + ", No child aspect found for " + shellLookupRequest.toJsonString());
} else if (childshellIds.size() > 1) {
throw new CsvHandlerDigitalTwinUseCaseException(String.format(
"Multiple shell id's found for childAspect %s, %s", dtOfferUrl, shellLookupRequest.toJsonString()));
} else if (childshellIds.size() == 1) {

ShellDescriptorResponse shellDescriptorResponse = eDCDigitalTwinProxyForLookUp.getShellDescriptorByShellId(
new URI(endpoint), encodeShellIdBase64Utf8(childshellIds.get(0)), header);

childUUID = shellDescriptorResponse.getGlobalAssetId();

log.info(rowIndex + ", " + dtOfferUrl + ", Child aspect found for " + shellLookupRequest.toJsonString());
}

return childUUID;
}

private String encodeShellIdBase64Utf8(String shellId) {
return Base64.getUrlEncoder().encodeToString(shellId.getBytes());
}

}
Loading
Loading