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/register parttype at edc #296

2 changes: 1 addition & 1 deletion DEPENDENCIES_FRONTEND
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ npm/npmjs/@babel/highlight/7.23.4, MIT AND (BSD-2-Clause AND ISC AND MIT) AND BS
npm/npmjs/@babel/parser/7.23.6, MIT AND (BSD-2-Clause AND ISC AND MIT) AND BSD-2-Clause AND BSD-3-Clause, approved, #10663
npm/npmjs/@babel/plugin-transform-react-jsx-self/7.23.3, MIT, approved, clearlydefined
npm/npmjs/@babel/plugin-transform-react-jsx-source/7.23.3, MIT, approved, clearlydefined
npm/npmjs/@babel/runtime/7.24.0, MIT, approved, clearlydefined
npm/npmjs/@babel/runtime/7.24.0, MIT AND (BSD-2-Clause AND ISC AND MIT) AND BSD-2-Clause AND BSD-3-Clause, approved, #13900
npm/npmjs/@babel/template/7.22.15, MIT, approved, #9017
npm/npmjs/@babel/traverse/7.23.7, MIT AND (BSD-2-Clause AND ISC AND MIT) AND BSD-2-Clause AND BSD-3-Clause, approved, #11520
npm/npmjs/@babel/types/7.23.6, MIT AND (BSD-2-Clause AND ISC AND MIT) AND BSD-2-Clause AND BSD-3-Clause, approved, #11521
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ private void setupCustomerRole() throws JsonProcessingException {

MaterialPartnerRelation semiconductorPartnerRelation = new MaterialPartnerRelation(semiconductorMaterial,
supplierPartner, semiconductorMatNbrSupplier, true, false);
semiconductorPartnerRelation.setPartnerCXNumber(semiconductorMatNbrCatenaX);
// semiconductorPartnerRelation.setPartnerCXNumber(semiconductorMatNbrCatenaX);
mprService.create(semiconductorPartnerRelation);
semiconductorPartnerRelation = mprService.find(semiconductorMaterial, supplierPartner);
log.info("Found Relation: " + semiconductorPartnerRelation);
Expand Down Expand Up @@ -248,7 +248,7 @@ private void setupSupplierRole() {

MaterialPartnerRelation semiconductorPartnerRelation = new MaterialPartnerRelation(semiconductorMaterial,
customerPartner, semiconductorMatNbrCustomer, false, true);
semiconductorPartnerRelation.setPartnerCXNumber(semiconductorMatNbrCatenaX);
// semiconductorPartnerRelation.setPartnerCXNumber(semiconductorMatNbrCatenaX);
semiconductorPartnerRelation = mprService.create(semiconductorPartnerRelation);

log.info("Created Relation " + semiconductorPartnerRelation);
Expand Down Expand Up @@ -411,7 +411,7 @@ private Material getNewSemiconductorMaterialForSupplier() {
private Material getNewSemiconductorMaterialForCustomer() {
Material material = new Material();
material.setOwnMaterialNumber(semiconductorMatNbrCustomer);
material.setMaterialNumberCx(semiconductorMatNbrCatenaX);
// material.setMaterialNumberCx(semiconductorMatNbrCatenaX);
material.setMaterialFlag(true);
material.setName("Semiconductor");
return material;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ public boolean registerAssetsInitially() {
public boolean createPolicyAndContractDefForPartner(Partner partner) {
boolean result = createPolicyDefinitionForPartner(partner);
result &= createDtrContractDefinitionForPartner(partner);
result &= registerPartTypeAssetForPartner(partner);
result &= createPartTypeInfoContractDefForPartner(partner);
result &= createContractDefinitionForPartner(partner, DT_ApiMethodEnum.REQUEST);
result &= createContractDefinitionForPartner(partner, DT_ApiMethodEnum.STATUS_REQUEST);
return result & createContractDefinitionForPartner(partner, DT_ApiMethodEnum.RESPONSE);
Expand Down Expand Up @@ -186,6 +188,21 @@ private boolean createDtrContractDefinitionForPartner(Partner partner) {
}
}

private boolean createPartTypeInfoContractDefForPartner(Partner partner) {
var body = edcRequestBodyBuilder.buildPartTypeInfoContractDefinitionForPartner(partner);
try (var response = sendPostRequest(body, List.of("v2", "contractdefinitions"))) {
if (!response.isSuccessful()) {
log.warn("Contract definition registration failed for partner " + partner.getBpnl() + " and PartTypeInfo asset");
return false;
}
log.info("Contract definition successful for PartTypeAsset and partner " + partner.getBpnl());
return true;
} catch (Exception e) {
log.error("Contract definition registration failed for partner " + partner.getBpnl() + " and PartTypeInfo asset", e);
return false;
}
}


/**
* Registers a policy definition that allows only the given partner's
Expand Down Expand Up @@ -242,6 +259,7 @@ private boolean registerDtrAsset() {
if (response.body() != null) {
log.warn("Response: \n" + response.body().string());
}
return false;
}
return true;
} catch (Exception e) {
Expand All @@ -250,6 +268,24 @@ private boolean registerDtrAsset() {
}
}

private boolean registerPartTypeAssetForPartner(Partner partner) {
var body = edcRequestBodyBuilder.buildPartTypeInfoRegistrationBody(partner);
try (var response = sendPostRequest(body, List.of("v3", "assets"))) {
if (!response.isSuccessful()) {
log.warn("Asset registration failed for PartTypeAsset and partner " + partner.getBpnl());
if (response.body() != null) {
log.warn("Response: \n" + response.body().string());
}
return false;
}
log.info("Asset registration successful for PartTypeAsset and partner " + partner.getBpnl());
return true;
} catch (Exception e) {
log.error("Failed to register PartTypeAsset for partner " + partner.getBpnl());
return false;
}
}

/**
* Util method to register an API asset to your control plane.
*
Expand Down Expand Up @@ -277,11 +313,12 @@ private boolean registerApiAsset(DT_ApiMethodEnum apiMethod) {
/**
* Retrieve the response to an unfiltered catalog request from the partner
* with the given dspUrl
* @param dspUrl The dspUrl of your partner
* @return The response containing the full catalog, if successful
*
* @param dspUrl The dspUrl of your partner
* @return The response containing the full catalog, if successful
*/
public Response getCatalogResponse(String dspUrl) throws IOException {
return sendPostRequest(edcRequestBodyBuilder.buildBasicCatalogRequestBody(dspUrl, null), List.of("v2", "catalog", "request"));
return sendPostRequest(edcRequestBodyBuilder.buildBasicCatalogRequestBody(dspUrl, null), List.of("v2", "catalog", "request"));
}

/**
Expand Down Expand Up @@ -432,6 +469,127 @@ public Response postProxyPullRequest(String url, String authKey, String authCode
}
}

public Response getProxyPullRequest(String url, String authKey, String authCode, String[] pathParams) {
HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
for (var pathSegment : pathParams) {
urlBuilder.addPathSegment(pathSegment);
}
try {
var request = new Request.Builder()
.get()
.url(urlBuilder.build())
.header(authKey, authCode)
.build();
return CLIENT.newCall(request).execute();
} catch (Exception e) {
log.error("ProxyPull GET Request failed ", e);
return null;
}
}

/**
* Tries to negotiate for the PartTypeInfo-Submodel asset with the given partner
* and also tries to initiate the transfer of the edr token to the given endpoint.
* <p>
* It will return a String array of length 4. The authKey is stored under index 0, the
* authCode under index 1, the endpoint under index 2 and the contractId under index 3.
*
* @param partner the partner
* @return A String array or null, if negotiation failed or the authCode did not arrive
*/
public String[] getContractForPartTypeInfoSubmodel(Partner partner) {
try {
var responseNode = getCatalog(partner.getEdcUrl());
var catalogArray = responseNode.get("dcat:dataset");
// If there is exactly one asset, the catalogContent will be a JSON object.
// In all other cases catalogContent will be a JSON array.
// For the sake of uniformity we will embed a single object in an array.
if (catalogArray.isObject()) {
catalogArray = objectMapper.createArrayNode().add(catalogArray);
}
JsonNode targetCatalogEntry = null;
for (var entry : catalogArray) {
var dctTypeObject = entry.get("dct:type");
if (dctTypeObject != null) {
if (("https://w3id.org/catenax/taxonomy#Submodel").equals(dctTypeObject.get("@id").asText())) {
if ("3.0".equals(entry.get("https://w3id.org/catenax/ontology/common#version").asText())) {
if ("urn:samm:io.catenax.part_type_information:1.0.0#PartTypeInformation".equals(entry.get("aas-semantics:semanticId.@id").asText())) {
if (targetCatalogEntry == null) {
if (variablesService.isUseFrameworkPolicy()) {
if (testFrameworkAgreementConstraint(entry)) {
targetCatalogEntry = entry;
} else {
log.error("Contract Negotiation for PartTypeInformation Submodel asset with partner " + partner.getBpnl() + " has " +
"been aborted. This partner's contract policy does not match the policy " +
"supported by this application. \n Supported Policy: " + variablesService.getPurisFrameworkAgreement() +
"\n Received offer from Partner: \n" + entry.toPrettyString());
break;
}
} else {
targetCatalogEntry = entry;
}
} else {
log.warn("Ambiguous catalog entries found! \n" + catalogArray.toPrettyString());
}
}
}
}
}
}
if (targetCatalogEntry == null) {
log.error("Could not find submodel asset for PartTypeInformation at partner " + partner.getBpnl() + " 's catalog");
return null;
}
String assetId = targetCatalogEntry.get("@id").asText();
JsonNode negotiationResponse = initiateNegotiation(partner, targetCatalogEntry);
String negotiationId = negotiationResponse.get("@id").asText();
// Await confirmation of contract and contractId
String contractId = null;
for (int i = 0; i < 100; i++) {
Thread.sleep(100);
var responseObject = getNegotiationState(negotiationId);
if ("FINALIZED".equals(responseObject.get("edc:state").asText())) {
contractId = responseObject.get("edc:contractAgreementId").asText();
break;
}
}
if (contractId == null) {
var negotiationState = getNegotiationState(negotiationId);
log.warn("no contract id, last negotiation state: \n" + negotiationState.toPrettyString());
log.error("Failed to obtain " + assetId + " from " + partner.getEdcUrl());
return null;
}

// Initiate transfer of edr
var transferResp = initiateProxyPullTransfer(partner, contractId, assetId);
String transferId = transferResp.get("@id").asText();
for (int i = 0; i < 100; i++) {
Thread.sleep(100);
transferResp = getTransferState(transferId);
if ("STARTED".equals(transferResp.get("edc:state").asText())) {
break;
}
}

// Await arrival of edr
for (int i = 0; i < 100; i++) {
Thread.sleep(100);
EDR_Dto edr_Dto = edrService.findByTransferId(transferId);
if (edr_Dto != null) {
log.info("Successfully negotiated for " + assetId + " with " + partner.getEdcUrl());
return new String[]{edr_Dto.authKey(), edr_Dto.authCode(), edr_Dto.endpoint(), contractId};
}
}
log.warn("did not receive authCode");
log.error("Failed to obtain " + assetId + " from " + partner.getEdcUrl());
return null;

} catch (Exception e) {
log.error("Failed to get contract for PartTypeInfo submodel asset from " + partner.getBpnl(), e);
return null;
}
}

/**
* Tries to negotiate for the given api Method with the given partner
* and also tries to initiate the transfer of the edr token to the given endpoint.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,24 @@ public JsonNode buildDtrContractDefinitionForPartner(Partner partner) {
return body;
}

public JsonNode buildPartTypeInfoContractDefinitionForPartner(Partner partner) {
var body = getEdcContextObject();
body.put("@id", partner.getBpnl() +"_contractdefinition_for_PartTypeInfoAsset");
body.put("accessPolicyId", getBpnPolicyId(partner));
if(variablesService.isUseFrameworkPolicy()) {
body.put("contractPolicyId", FRAMEWORK_POLICY_ID);
} else {
body.put("contractPolicyId", getBpnPolicyId(partner));
}
var assetsSelector = MAPPER.createObjectNode();
body.set("assetsSelector", assetsSelector);
assetsSelector.put("@type", "CriterionDto");
assetsSelector.put("operandLeft", EDC_NAMESPACE + "id");
assetsSelector.put("operator", "=");
assetsSelector.put("operandRight", getPartTypeInfoAssetId(partner));
return body;
}

/**
* This method helps to ensure that the buildContractDefinitionWithBpnRestrictedPolicy uses the
* same policy-id as the one that is created with the buildContractDefinitionWithBpnRestrictedPolicy
Expand Down Expand Up @@ -338,10 +356,42 @@ public JsonNode buildDtrRegistrationBody() {
return body;
}

public JsonNode buildPartTypeInfoRegistrationBody(Partner partner) {
var body = getAssetRegistrationContext();
body.put("@id", getPartTypeInfoAssetId(partner));
var propertiesObject = MAPPER.createObjectNode();
body.set("properties", propertiesObject);
var dctTypeObject = MAPPER.createObjectNode();
propertiesObject.set("dct:type", dctTypeObject);
dctTypeObject.put("@id", CX_TAXO_NAMESPACE + "Submodel");
propertiesObject.put("cx-common:version", "3.0");
propertiesObject.put("aas-semantics:semanticId.@id", "urn:samm:io.catenax.part_type_information:1.0.0#PartTypeInformation");
tom-rm-meyer-ISST marked this conversation as resolved.
Show resolved Hide resolved
var dataAddress = MAPPER.createObjectNode();
String url = variablesService.getParttypeInformationServerendpoint();
if (!url.endsWith("/")) {
url += "/";
}
url += partner.getBpnl();
dataAddress.put("@type", "DataAddress");
dataAddress.put("proxyPath", "true");
dataAddress.put("proxyQueryParams", "false");
dataAddress.put("proxyMethod", "false");
dataAddress.put("type", "HttpData");
dataAddress.put("baseUrl", url);
dataAddress.put("authKey", "x-api-key");
dataAddress.put("authCode", variablesService.getApiKey());
body.set("dataAddress", dataAddress);
return body;
}

private String getDtrAssetId() {
return "DigitalTwinRegistryId@" + variablesService.getOwnBpnl();
}

private String getPartTypeInfoAssetId(Partner partner) {
return "PartTypeInformationApi_" + partner.getBpnl();
}

private ObjectNode getAssetRegistrationContext() {
var body = MAPPER.createObjectNode();
var context = MAPPER.createObjectNode();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
.authorizeHttpRequests(
// any request in spring context
(authorizeHttpRequests) -> authorizeHttpRequests
.requestMatchers("/stockView/**", "/partners/**", "/materials/**", "/materialpartnerrelations/**", "/item-stock/**", "/edrendpoint/**", "/edc/**").authenticated()
.requestMatchers("/stockView/**", "/partners/**", "/materials/**", "/materialpartnerrelations/**", "/item-stock/**", "/edrendpoint/**", "/edc/**", "/parttypeinformation/**").authenticated()
.requestMatchers("/swagger-ui/**", "/v3/api-docs/**", "/health/**").permitAll()
.dispatcherTypeMatchers(DispatcherType.ERROR).permitAll()
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,17 @@ public class VariablesService {
* The port used by this apps server application.
*/
private String serverPort;
@Value("${puris.baseurl}")
private String purisBaseUrl;
@Value("${puris.demonstrator.role}")
/**
* Must be set to "CUSTOMER" or "SUPPLIER" if
* you want to start with some initial settings
* defined in the DataInjectionCommandLineRunner
*/
private String demoRole;
@Value("${puris.edr.endpoint}")

@Value("${puris.baseurl}" + "catena/edrendpoint")
/**
* The edrEndpoint to be used during consumer pull asset transfers.
*/
Expand All @@ -57,7 +60,7 @@ public class VariablesService {
* in the context of a consumer pull is removed from memory
*/
private long edrTokenDeletionTimer;
@Value("${puris.request.serverendpoint}")
@Value("${puris.baseurl}" + "catena/item-stock/request")
/**
* The url under which this application's request endpoint can
* be reached by external machines.
Expand All @@ -69,7 +72,7 @@ public class VariablesService {
* during asset creation.
*/
private String requestApiAssetId;
@Value("${puris.response.serverendpoint}")
@Value("${puris.baseurl}" + "catena/item-stock/response")
/**
* The url under which this application's response endpoint can
* be reached by external machines.
Expand All @@ -87,7 +90,7 @@ public class VariablesService {
* during asset creation.
*/
private String statusRequestApiAssetId;
@Value("${puris.statusrequest.serverendpoint}")
@Value("${puris.baseurl}" + "catena/item-stock/status")
/**
* The url under which this application's status-request endpoint
* can be reached by external machines.
Expand Down Expand Up @@ -116,6 +119,9 @@ public class VariablesService {
*/
private String dtrUrl;

@Value("${puris.baseurl}" + "catena/parttypeinformation")
private String parttypeInformationServerendpoint;

@Value("${puris.generatematerialcatenaxid}")
/**
* A flag that signals whether the MaterialService
Expand Down
Loading
Loading