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/Submodel registration and production SAMM #346

Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2024 Volkswagen AG
* 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.puris.backend.common.edc.domain.model;

import jakarta.persistence.Entity;
import lombok.ToString;

@Entity
@ToString(callSuper = true)
public class DeliveryContractMapping extends ContractMapping {
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2024 Volkswagen AG
* 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.puris.backend.common.edc.domain.model;

import jakarta.persistence.Entity;
import lombok.ToString;

@Entity
@ToString(callSuper = true)
public class DemandContractMapping extends ContractMapping {
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2024 Volkswagen AG
* 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.puris.backend.common.edc.domain.model;

import jakarta.persistence.Entity;
import lombok.ToString;

@Entity
@ToString(callSuper = true)
public class ProductionContractMapping extends ContractMapping {
}

Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
public enum SubmodelType {
DTR("none", "none"),
ITEM_STOCK("urn:samm:io.catenax.item_stock:2.0.0#ItemStock", "$value"),
PRODUCTION("urn:samm:io.catenax.planned_production_output:2.0.0#PlannedProductionOutput", "$value"),
DEMAND("urn:samm:io.catenax.short_term_material_demand:1.0.0#ShortTermMaterialDemand", "$value"),
DELIVERY("urn:samm:io.catenax.delivery_information:2.0.0#DeliveryInformation", "$value"),
PART_TYPE_INFORMATION("urn:samm:io.catenax.part_type_information:1.0.0#PartTypeInformation", "$value");

public final String URN_SEMANTIC_ID;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2024 Volkswagen AG
* 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.puris.backend.common.edc.domain.repository;

import org.eclipse.tractusx.puris.backend.common.edc.domain.model.ContractMapping;
import org.eclipse.tractusx.puris.backend.common.edc.domain.model.DeliveryContractMapping;
import org.springframework.stereotype.Repository;

@Repository
public interface DeliveryContractMappingRepository extends GeneralContractMappingRepository<DeliveryContractMapping> {

@Override
default Class<? extends ContractMapping> getType() {
return DeliveryContractMapping.class;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2024 Volkswagen AG
* 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.puris.backend.common.edc.domain.repository;

import org.eclipse.tractusx.puris.backend.common.edc.domain.model.ContractMapping;
import org.eclipse.tractusx.puris.backend.common.edc.domain.model.DemandContractMapping;
import org.springframework.stereotype.Repository;

@Repository
public interface DemandContractMappingRepository extends GeneralContractMappingRepository<DemandContractMapping> {

@Override
default Class<? extends ContractMapping> getType() {
return DemandContractMapping.class;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2024 Volkswagen AG
* 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.puris.backend.common.edc.domain.repository;

import org.eclipse.tractusx.puris.backend.common.edc.domain.model.ContractMapping;
import org.eclipse.tractusx.puris.backend.common.edc.domain.model.ProductionContractMapping;
import org.springframework.stereotype.Repository;

@Repository
public interface ProductionContractMappingRepository extends GeneralContractMappingRepository<ProductionContractMapping> {

@Override
default Class<? extends ContractMapping> getType() {
return ProductionContractMapping.class;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ public class EdcAdapterService {
@Autowired
private EdcContractMappingService edcContractMappingService;

private Pattern urnPattern = PatternStore.URN_OR_UUID_PATTERN;

private Pattern urlPattern = PatternStore.URL_PATTERN;

public EdcAdapterService(ObjectMapper objectMapper) {
Expand Down Expand Up @@ -130,7 +128,26 @@ public boolean registerAssetsInitially() {
boolean assetRegistration;
log.info("Registration of DTR Asset successful {}", (assetRegistration = registerDtrAsset()));
result &= assetRegistration;
log.info("Registration of ItemStock 2.0.0 submodel successful {}", (assetRegistration = registerItemStockSubmodel()));
log.info("Registration of ItemStock 2.0.0 submodel successful {}", (assetRegistration = registerSubmodelAsset(
variablesService.getItemStockSubmodelApiAssetId(),
variablesService.getItemStockSubmodelEndpoint(),
SubmodelType.ITEM_STOCK.URN_SEMANTIC_ID
)));
log.info("Registration of Planned Production 2.0.0 submodel successful {}", (assetRegistration = registerSubmodelAsset(
variablesService.getProductionSubmodelApiAssetId(),
variablesService.getProductionSubmodelEndpoint(),
SubmodelType.PRODUCTION.URN_SEMANTIC_ID
)));
log.info("Registration of Short Term Material Demand 1.0.0 submodel successful {}", (assetRegistration = registerSubmodelAsset(
variablesService.getDemandSubmodelApiAssetId(),
variablesService.getDemandSubmodelEndpoint(),
SubmodelType.DEMAND.URN_SEMANTIC_ID
)));
log.info("Registration of Delivery Information 2.0.0 submodel successful {}", (assetRegistration = registerSubmodelAsset(
variablesService.getDeliverySubmodelApiAssetId(),
variablesService.getDeliverySubmodelEndpoint(),
SubmodelType.DELIVERY.URN_SEMANTIC_ID
)));
result &= assetRegistration;
log.info("Registration of PartTypeInformation 1.0.0 submodel successful {}", (assetRegistration = registerPartTypeInfoSubmodelAsset()));
result &= assetRegistration;
Expand All @@ -147,25 +164,27 @@ public boolean registerAssetsInitially() {
*/
public boolean createPolicyAndContractDefForPartner(Partner partner) {
boolean result = createBpnlAndMembershipPolicyDefinitionForPartner(partner);
result &= createItemStockSubmodelContractDefinitionForPartner(partner);
result &= createSubmodelContractDefinitionForPartner(SubmodelType.ITEM_STOCK.URN_SEMANTIC_ID, variablesService.getItemStockSubmodelApiAssetId(), partner);
result &= createSubmodelContractDefinitionForPartner(SubmodelType.PRODUCTION.URN_SEMANTIC_ID, variablesService.getProductionSubmodelApiAssetId(), partner);
result &= createSubmodelContractDefinitionForPartner(SubmodelType.DEMAND.URN_SEMANTIC_ID, variablesService.getDemandSubmodelApiAssetId(), partner);
result &= createSubmodelContractDefinitionForPartner(SubmodelType.DELIVERY.URN_SEMANTIC_ID, variablesService.getDeliverySubmodelApiAssetId(), partner);
result &= createDtrContractDefinitionForPartner(partner);
return createPartTypeInfoContractDefForPartner(partner) && result;

return createSubmodelContractDefinitionForPartner(SubmodelType.PART_TYPE_INFORMATION.URN_SEMANTIC_ID, variablesService.getPartTypeSubmodelApiAssetId(), partner) && result;
}

private boolean createItemStockSubmodelContractDefinitionForPartner(Partner partner) {
var body = edcRequestBodyBuilder.buildItemStockSubmodelContractDefinitionWithBpnRestrictedPolicy(partner);
private boolean createSubmodelContractDefinitionForPartner(String semanticId, String assetId, Partner partner) {
Fixed Show fixed Hide fixed
var body = edcRequestBodyBuilder.buildSubmodelContractDefinitionWithBpnRestrictedPolicy(assetId, partner);
try (var response = sendPostRequest(body, List.of("v2", "contractdefinitions"))) {
if (!response.isSuccessful()) {
log.warn("Contract definition registration failed for partner " + partner.getBpnl() + " and ItemStock Submodel");
log.warn("Contract definition registration failed for partner " + partner.getBpnl() + " and {} Submodel", semanticId);
if (response.body() != null) {
log.warn("Response: \n" + response.body().string());
}
return false;
}
return true;
} catch (Exception e) {
log.error("Contract definition registration failed for partner " + partner.getBpnl() + " and ItemStock Submodel");
log.error("Contract definition registration failed for partner " + partner.getBpnl() + " and {} Submodel", semanticId);
return false;
}
}
Expand All @@ -184,22 +203,6 @@ 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 evaluates to true in case all the following conditions apply:
* 1. The BPNL of the requesting connector is equal to the BPNL of the partner
Expand Down Expand Up @@ -283,24 +286,23 @@ private boolean registerPartTypeInfoSubmodelAsset() {
}
}

private boolean registerItemStockSubmodel() {
var body = edcRequestBodyBuilder.buildItemStockSubmodelRegistrationBody();
private boolean registerSubmodelAsset(String assetId, String endpoint, String semanticId) {
var body = edcRequestBodyBuilder.buildSubmodelRegistrationBody(assetId, endpoint, semanticId);
try (var response = sendPostRequest(body, List.of("v3", "assets"))) {
if (!response.isSuccessful()) {
log.warn("ItemStock Submodel Asset registration failed");
log.warn("{} Submodel Asset registration failed", semanticId);
if (response.body() != null) {
log.warn("Response: \n" + response.body().string());
}
return false;
}
return true;
} catch (Exception e) {
log.error("Failed to register ItemStock Submodel", e);
log.error("Failed to register {} Submodel", semanticId, e);
return false;
}
}


/**
* Retrieve the response to an unfiltered catalog request from the partner
* with the given dspUrl
Expand Down Expand Up @@ -489,7 +491,10 @@ private JsonNode getSubmodelFromPartner(MaterialPartnerRelation mpr, SubmodelTyp
Partner partner = mpr.getPartner();
SubmodelData submodelData = switch (type) {
case DTR -> throw new IllegalArgumentException("DTR not supported");
case ITEM_STOCK -> fetchItemStockSubmodelData(mpr, direction);
case ITEM_STOCK -> fetchSubmodelDataByDirection(mpr, SubmodelType.ITEM_STOCK.URN_SEMANTIC_ID, direction);
case PRODUCTION -> fetchSubmodelDataByDirection(mpr, SubmodelType.PRODUCTION.URN_SEMANTIC_ID, direction);
case DEMAND -> fetchSubmodelDataByDirection(mpr, SubmodelType.DEMAND.URN_SEMANTIC_ID, direction);
case DELIVERY -> fetchSubmodelDataByDirection(mpr, SubmodelType.DELIVERY.URN_SEMANTIC_ID, direction);
case PART_TYPE_INFORMATION -> fetchPartTypeSubmodelData(mpr);
};
boolean failed = true;
Expand Down Expand Up @@ -627,7 +632,7 @@ private boolean negotiateForPartnerDtr(Partner partner) {
}
}

private SubmodelData fetchItemStockSubmodelData(MaterialPartnerRelation mpr, DirectionCharacteristic direction) {
private SubmodelData fetchSubmodelDataByDirection(MaterialPartnerRelation mpr, String semanticId, DirectionCharacteristic direction) {
String manufacturerPartId = switch (direction) {
case INBOUND -> mpr.getMaterial().getOwnMaterialNumber();
case OUTBOUND -> mpr.getPartnerMaterialNumber();
Expand All @@ -636,7 +641,7 @@ private SubmodelData fetchItemStockSubmodelData(MaterialPartnerRelation mpr, Dir
case INBOUND -> variablesService.getOwnBpnl();
case OUTBOUND -> mpr.getPartner().getBpnl();
};
return fetchSubmodelData(mpr, "urn:samm:io.catenax.item_stock:2.0.0#ItemStock", manufacturerPartId, manufacturerId);
return fetchSubmodelData(mpr, semanticId, manufacturerPartId, manufacturerId);
}

private SubmodelData fetchPartTypeSubmodelData(MaterialPartnerRelation mpr) {
Expand Down Expand Up @@ -789,7 +794,10 @@ private boolean negotiateForSubmodel(MaterialPartnerRelation mpr, SubmodelType t
Partner partner = mpr.getPartner();
SubmodelData submodelData = switch (type) {
case DTR -> throw new IllegalArgumentException("DTR not supported");
case ITEM_STOCK -> fetchItemStockSubmodelData(mpr, direction);
case ITEM_STOCK -> fetchSubmodelDataByDirection(mpr, SubmodelType.ITEM_STOCK.URN_SEMANTIC_ID, direction);
case PRODUCTION -> fetchSubmodelDataByDirection(mpr, SubmodelType.PRODUCTION.URN_SEMANTIC_ID, direction);
case DEMAND -> fetchSubmodelDataByDirection(mpr, SubmodelType.DEMAND.URN_SEMANTIC_ID, direction);
case DELIVERY -> fetchSubmodelDataByDirection(mpr, SubmodelType.DELIVERY.URN_SEMANTIC_ID, direction);
case PART_TYPE_INFORMATION -> fetchPartTypeSubmodelData(mpr);
};
try {
Expand Down
Loading
Loading