Skip to content

Commit 29990f3

Browse files
authored
feature: Implement retrieving BPNs given BPN group identifier (#1899)
* Create bpn's retrievel given bpn group identifier flow. * Added some tests * Fix query syntax * Small clean up. * Small readability changes. * Remove not needed unit test. * Fix Controller Tests. * Changes from PR. * Changes from PR. * Changes from PR.
1 parent 65b0220 commit 29990f3

File tree

10 files changed

+126
-18
lines changed

10 files changed

+126
-18
lines changed

edc-extensions/bpn-validation/bpn-validation-api/src/main/java/org/eclipse/tractusx/edc/api/bpn/BaseBusinessPartnerGroupApiController.java

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,19 @@
3939

4040
public abstract class BaseBusinessPartnerGroupApiController {
4141

42-
private final BusinessPartnerStore businessPartnerService;
42+
protected final BusinessPartnerStore businessPartnerService;
4343

4444
public BaseBusinessPartnerGroupApiController(BusinessPartnerStore businessPartnerService) {
4545
this.businessPartnerService = businessPartnerService;
4646
}
4747

4848
public JsonObject resolve(String bpn) {
49-
50-
// StoreResult does not support the .map() operator, because it does not override newInstance()
51-
var result = businessPartnerService.resolveForBpn(bpn);
52-
if (result.succeeded()) {
53-
return createObject(bpn, result.getContent());
54-
}
55-
56-
throw new ObjectNotFoundException(List.class, result.getFailureDetail());
49+
return businessPartnerService.resolveForBpn(bpn)
50+
.map(result -> Json.createObjectBuilder()
51+
.add(ID, bpn)
52+
.add(TX_NAMESPACE + "groups", Json.createArrayBuilder(result))
53+
.build())
54+
.orElseThrow(failure -> new ObjectNotFoundException(List.class, failure.getFailureDetail()));
5755
}
5856

5957
public void deleteEntry(@PathParam("bpn") String bpn) {
@@ -75,13 +73,6 @@ public void createEntry(@RequestBody JsonObject object) {
7573
.orElseThrow(f -> new ObjectConflictException(f.getFailureDetail()));
7674
}
7775

78-
private JsonObject createObject(String bpn, List<String> list) {
79-
return Json.createObjectBuilder()
80-
.add(ID, bpn)
81-
.add(TX_NAMESPACE + "groups", Json.createArrayBuilder(list))
82-
.build();
83-
}
84-
8576
private String getBpn(JsonObject object) {
8677
try {
8778
return object.getString(ID);

edc-extensions/bpn-validation/bpn-validation-api/src/main/java/org/eclipse/tractusx/edc/api/bpn/v3/BusinessPartnerGroupApiV3.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,15 @@ public interface BusinessPartnerGroupApiV3 {
5050
})
5151
JsonObject resolveV3(@Parameter(name = "bpn", description = "The business partner number") String bpn);
5252

53+
@Operation(description = "Resolves all BPNs for a particular BPN group",
54+
responses = {
55+
@ApiResponse(responseCode = "200", description = "An object containing an array with the bpns assigned to the group"),
56+
@ApiResponse(responseCode = "404", description = "No entry for the given BPN group was found"),
57+
@ApiResponse(responseCode = "400", description = "Request body was malformed",
58+
content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiErrorDetail.class))))
59+
})
60+
JsonObject resolveGroupV3(@Parameter(name = "group", description = "The business partner group") String group);
61+
5362
@Operation(description = "Deletes the entry for a particular BPN",
5463
responses = {
5564
@ApiResponse(responseCode = "204", description = "The object was successfully deleted"),

edc-extensions/bpn-validation/bpn-validation-api/src/main/java/org/eclipse/tractusx/edc/api/bpn/v3/BusinessPartnerGroupApiV3Controller.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
package org.eclipse.tractusx.edc.api.bpn.v3;
2121

2222
import io.swagger.v3.oas.annotations.parameters.RequestBody;
23+
import jakarta.json.Json;
2324
import jakarta.json.JsonObject;
2425
import jakarta.ws.rs.Consumes;
2526
import jakarta.ws.rs.DELETE;
@@ -30,12 +31,18 @@
3031
import jakarta.ws.rs.PathParam;
3132
import jakarta.ws.rs.Produces;
3233
import jakarta.ws.rs.core.MediaType;
34+
import org.eclipse.edc.web.spi.exception.ObjectNotFoundException;
3335
import org.eclipse.tractusx.edc.api.bpn.BaseBusinessPartnerGroupApiController;
3436
import org.eclipse.tractusx.edc.validation.businesspartner.spi.BusinessPartnerStore;
3537

38+
import java.util.List;
3639

37-
@Consumes({MediaType.APPLICATION_JSON})
38-
@Produces({MediaType.APPLICATION_JSON})
40+
import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID;
41+
import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE;
42+
43+
44+
@Consumes({ MediaType.APPLICATION_JSON })
45+
@Produces({ MediaType.APPLICATION_JSON })
3946
@Path("/v3/business-partner-groups")
4047
public class BusinessPartnerGroupApiV3Controller extends BaseBusinessPartnerGroupApiController implements BusinessPartnerGroupApiV3 {
4148

@@ -50,6 +57,18 @@ public JsonObject resolveV3(@PathParam("bpn") String bpn) {
5057
return super.resolve(bpn);
5158
}
5259

60+
@GET
61+
@Path("/group/{group}")
62+
@Override
63+
public JsonObject resolveGroupV3(@PathParam("group") String group) {
64+
return businessPartnerService.resolveForBpnGroup(group)
65+
.map(result -> Json.createObjectBuilder()
66+
.add(ID, group)
67+
.add(TX_NAMESPACE + "bpns", Json.createArrayBuilder(result))
68+
.build())
69+
.orElseThrow(failure -> new ObjectNotFoundException(List.class, failure.getFailureDetail()));
70+
}
71+
5372
@DELETE
5473
@Path("/{bpn}")
5574
@Override

edc-extensions/bpn-validation/bpn-validation-api/src/test/java/org/eclipse/tractusx/edc/api/bpn/v3/BusinessPartnerGroupApiV3ControllerTest.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,39 @@
2121

2222
import io.restassured.specification.RequestSpecification;
2323
import org.eclipse.edc.junit.annotations.ApiTest;
24+
import org.eclipse.edc.spi.result.StoreResult;
2425
import org.eclipse.tractusx.edc.api.bpn.BaseBusinessPartnerGroupApiControllerTest;
26+
import org.junit.jupiter.api.Test;
27+
28+
import java.util.List;
2529

2630
import static io.restassured.RestAssured.given;
31+
import static org.hamcrest.Matchers.notNullValue;
32+
import static org.mockito.ArgumentMatchers.any;
33+
import static org.mockito.Mockito.when;
2734

2835
@ApiTest
2936
class BusinessPartnerGroupApiV3ControllerTest extends BaseBusinessPartnerGroupApiControllerTest {
3037

38+
@Test
39+
void resolveForBpnGroup_exists() {
40+
when(businessPartnerStore.resolveForBpnGroup(any())).thenReturn(StoreResult.success(List.of("bpn1", "bpn2")));
41+
baseRequest()
42+
.get("/group/test-bpn-group")
43+
.then()
44+
.statusCode(200)
45+
.body(notNullValue());
46+
}
47+
48+
@Test
49+
void resolveForBpnGroup_notExists_returns404() {
50+
when(businessPartnerStore.resolveForBpnGroup(any())).thenReturn(StoreResult.notFound("test-message"));
51+
baseRequest()
52+
.get("/group/test-bpn-group-not-exists")
53+
.then()
54+
.statusCode(404);
55+
}
56+
3157
@Override
3258
protected Object controller() {
3359
return new BusinessPartnerGroupApiV3Controller(businessPartnerStore);

edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/defaults/InMemoryBusinessPartnerStore.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.HashMap;
2626
import java.util.List;
2727
import java.util.Map;
28+
import java.util.stream.Collectors;
2829

2930
public class InMemoryBusinessPartnerStore implements BusinessPartnerStore {
3031
private final Map<String, List<String>> cache = new HashMap<>();
@@ -37,6 +38,17 @@ public StoreResult<List<String>> resolveForBpn(String businessPartnerNumber) {
3738
StoreResult.success(entry);
3839
}
3940

41+
@Override
42+
public StoreResult<List<String>> resolveForBpnGroup(String businessPartnerGroup) {
43+
var bpns = cache.entrySet().stream()
44+
.filter(bpn -> bpn.getValue().stream().anyMatch(groups -> groups.contains(businessPartnerGroup)))
45+
.map(Map.Entry::getKey)
46+
.collect(Collectors.toList());
47+
return bpns.isEmpty() ?
48+
StoreResult.notFound(NOT_FOUND_TEMPLATE.formatted(businessPartnerGroup)) :
49+
StoreResult.success(bpns);
50+
}
51+
4052
@Override
4153
public StoreResult<Void> save(String businessPartnerNumber, List<String> groups) {
4254
//to maintain behavioural consistency with the SQL store

edc-extensions/bpn-validation/bpn-validation-core/src/testFixtures/java/org/eclipse/tractusx/edc/validation/businesspartner/store/BusinessPartnerStoreTestBase.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
import java.util.List;
2626

2727
import static org.assertj.core.api.Assertions.assertThat;
28+
import static org.assertj.core.api.InstanceOfAssertFactories.list;
29+
import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat;
2830

2931
public abstract class BusinessPartnerStoreTestBase {
3032

@@ -45,6 +47,24 @@ void resolveForBpn_existsNoGroups() {
4547
assertThat(getStore().resolveForBpn("test-bpn").getContent()).isNotNull().isEmpty();
4648
}
4749

50+
@Test
51+
void resolveForBpnGroup_multipleBpns() {
52+
getStore().save("test-bpn-0", List.of("group2"));
53+
getStore().save("test-bpn-1", List.of("test-bpn-group", "group2", "group3"));
54+
getStore().save("test-bpn-2", List.of("test-bpn-group"));
55+
getStore().save("test-bpn-3", List.of("test-bpn-group", "group17"));
56+
57+
assertThat(getStore().resolveForBpnGroup("test-bpn-group"))
58+
.isSucceeded()
59+
.asInstanceOf(list(String.class))
60+
.containsExactly("test-bpn-1", "test-bpn-2", "test-bpn-3");
61+
}
62+
63+
@Test
64+
void resolveForBpnGroup_bpnGroupNotExists() {
65+
assertThat(getStore().resolveForBpnGroup("group-not-exist")).isFailed();
66+
}
67+
4868
@Test
4969
void save() {
5070
getStore().save("test-bpn", List.of("group1", "group2", "group3"));

edc-extensions/bpn-validation/bpn-validation-spi/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerStore.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ public interface BusinessPartnerStore {
3131

3232
StoreResult<List<String>> resolveForBpn(String businessPartnerNumber);
3333

34+
StoreResult<List<String>> resolveForBpnGroup(String businessPartnerGroup);
35+
3436
StoreResult<Void> save(String businessPartnerNumber, List<String> groups);
3537

3638
StoreResult<Void> delete(String businessPartnerNumber);

edc-extensions/bpn-validation/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/BusinessPartnerGroupStatements.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ default String getTable() {
3838

3939
String findByBpnTemplate();
4040

41+
String findByBpnGroupTemplate();
42+
4143
String insertTemplate();
4244

4345
String deleteTemplate();

edc-extensions/bpn-validation/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/PostgresBusinessPartnerGroupStatements.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ public String findByBpnTemplate() {
3333
return format("SELECT %s from %s WHERE %s = ?", getGroupsColumn(), getTable(), getBpnColumn());
3434
}
3535

36+
@Override
37+
public String findByBpnGroupTemplate() {
38+
return format("SELECT %s from %s WHERE EXISTS (SELECT 1 FROM json_array_elements_text(%s) AS group_element WHERE group_element = ?)",
39+
getBpnColumn(), getTable(), getGroupsColumn());
40+
}
41+
3642
@Override
3743
public String insertTemplate() {
3844
return format("INSERT INTO %s (%s, %s) VALUES (?, ?%s)", getTable(), getBpnColumn(), getGroupsColumn(), getFormatJsonOperator());

edc-extensions/bpn-validation/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/SqlBusinessPartnerStore.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,23 @@ public StoreResult<List<String>> resolveForBpn(String businessPartnerNumber) {
6262
});
6363
}
6464

65+
@Override
66+
public StoreResult<List<String>> resolveForBpnGroup(String businessPartnerGroup) {
67+
Objects.requireNonNull(businessPartnerGroup);
68+
return transactionContext.execute(() -> {
69+
try (var connection = getConnection()) {
70+
var sql = statements.findByBpnGroupTemplate();
71+
var result = queryExecutor.query(connection, true, this::mapGroup, sql, businessPartnerGroup);
72+
var bpns = result.toList();
73+
return bpns.isEmpty() ?
74+
StoreResult.notFound(NOT_FOUND_TEMPLATE.formatted(businessPartnerGroup)) :
75+
StoreResult.success(bpns);
76+
} catch (SQLException e) {
77+
throw new EdcPersistenceException(e);
78+
}
79+
});
80+
}
81+
6582
@Override
6683
public StoreResult<Void> save(String businessPartnerNumber, List<String> groups) {
6784
Objects.requireNonNull(businessPartnerNumber);
@@ -118,6 +135,10 @@ private List<String> mapJson(ResultSet resultSet) throws SQLException {
118135
return fromJson(resultSet.getString(statements.getGroupsColumn()), LIST_OF_STRING);
119136
}
120137

138+
private String mapGroup(ResultSet resultSet) throws SQLException {
139+
return resultSet.getString(statements.getBpnColumn());
140+
}
141+
121142
private boolean exists(String businessPartnerNumber, Connection connection) {
122143
var countQuery = statements.countQuery();
123144
try (var stream = queryExecutor.query(connection, false, r -> r.getInt("COUNT"), countQuery, businessPartnerNumber)) {

0 commit comments

Comments
 (0)