diff --git a/docs/src/api/irs-api.yaml b/docs/src/api/irs-api.yaml index b51cc259b3..ac3b68acd3 100644 --- a/docs/src/api/irs-api.yaml +++ b/docs/src/api/irs-api.yaml @@ -797,7 +797,8 @@ paths: description: Lists the registered policies that should be accepted in EDC negotiation. operationId: getAllowedPoliciesByBpn parameters: - - description: List of business partner numbers. + - description: List of business partner numbers. This may also contain the value + "default" in order to query the default policies. in: query name: businessPartnerNumbers required: false @@ -988,7 +989,8 @@ paths: Example: `page=1&size=20` operationId: getPoliciesPaged parameters: - - description: List of business partner numbers. + - description: List of business partner numbers. This may also contain the value + "default" in order to query the default policies. in: query name: businessPartnerNumbers required: false diff --git a/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/controllers/PolicyStoreController.java b/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/controllers/PolicyStoreController.java index 2aa0e850ac..99083688e3 100644 --- a/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/controllers/PolicyStoreController.java +++ b/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/controllers/PolicyStoreController.java @@ -192,8 +192,9 @@ public CreatePoliciesResponse registerAllowedPolicy(@Valid @RequestBody final Cr @PreAuthorize("hasAuthority('" + IrsRoles.ADMIN_IRS + "')") public Map> getPolicies(// @RequestParam(required = false) // - @ValidListOfBusinessPartnerNumbers // - @Parameter(description = "List of business partner numbers.") // + @ValidListOfBusinessPartnerNumbers(allowDefault = true) // + @Parameter(description = "List of business partner numbers. " + + "This may also contain the value \"default\" in order to query the default policies.") // final List businessPartnerNumbers // ) { @@ -256,8 +257,9 @@ public Page getPoliciesPaged(// @Parameter(description = "Page configuration", hidden = true) // final Pageable pageable, // @RequestParam(required = false) // - @ValidListOfBusinessPartnerNumbers // - @Parameter(name = "businessPartnerNumbers", description = "List of business partner numbers.") // + @ValidListOfBusinessPartnerNumbers(allowDefault = true) // + @Parameter(name = "businessPartnerNumbers", description = "List of business partner numbers. " + + "This may also contain the value \"default\" in order to query the default policies.") // final List businessPartnerNumbers) { if (pageable.getPageSize() > MAX_PAGE_SIZE) { diff --git a/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/validators/BusinessPartnerNumberListValidator.java b/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/validators/BusinessPartnerNumberListValidator.java index a487906cb5..26e34249a6 100644 --- a/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/validators/BusinessPartnerNumberListValidator.java +++ b/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/validators/BusinessPartnerNumberListValidator.java @@ -31,6 +31,8 @@ public class BusinessPartnerNumberListValidator implements ConstraintValidator> { + private static final String DEFAULT = "default"; + /** * Regex for BPN. */ @@ -38,16 +40,29 @@ public class BusinessPartnerNumberListValidator private static final Pattern PATTERN = Pattern.compile(BPN_REGEX); + private boolean allowDefault; + + @Override + public void initialize(final ValidListOfBusinessPartnerNumbers constraintAnnotation) { + this.allowDefault = constraintAnnotation.allowDefault(); + } + @Override - public boolean isValid(final List value, final ConstraintValidatorContext context) { + public boolean isValid(final List businessPartnerNumbers, final ConstraintValidatorContext context) { // allow null and empty here (in order to allow flexible combination with @NotNull and @NotEmpty) - if (value == null || value.isEmpty()) { + if (businessPartnerNumbers == null || businessPartnerNumbers.isEmpty()) { return true; } - for (int index = 0; index < value.size(); index++) { - if (!PATTERN.matcher(value.get(index)).matches()) { + for (int index = 0; index < businessPartnerNumbers.size(); index++) { + final String bpn = businessPartnerNumbers.get(index); + + if (allowDefault && DEFAULT.equals(bpn)) { + return true; + } + + if (!PATTERN.matcher(bpn).matches()) { context.disableDefaultConstraintViolation(); final String msg = "The business partner number at index %d is invalid (should conform to pattern '%s')"; context.buildConstraintViolationWithTemplate(msg.formatted(index, BPN_REGEX)).addConstraintViolation(); diff --git a/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/validators/ValidListOfBusinessPartnerNumbers.java b/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/validators/ValidListOfBusinessPartnerNumbers.java index 44b11e0a11..ad2501498e 100644 --- a/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/validators/ValidListOfBusinessPartnerNumbers.java +++ b/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/validators/ValidListOfBusinessPartnerNumbers.java @@ -44,4 +44,6 @@ Class[] groups() default { }; Class[] payload() default { }; + + boolean allowDefault() default false; } diff --git a/irs-policy-store/src/test/java/org/eclipse/tractusx/irs/policystore/services/PolicyStoreServiceTest.java b/irs-policy-store/src/test/java/org/eclipse/tractusx/irs/policystore/services/PolicyStoreServiceTest.java index 9d473c9e04..27857d9483 100644 --- a/irs-policy-store/src/test/java/org/eclipse/tractusx/irs/policystore/services/PolicyStoreServiceTest.java +++ b/irs-policy-store/src/test/java/org/eclipse/tractusx/irs/policystore/services/PolicyStoreServiceTest.java @@ -312,9 +312,6 @@ class GetAcceptedPoliciesTests { @Test void getAcceptedPolicies_whenParameterBpnIsNull_shouldReturnTheConfiguredDefaultPolicy() { - // ARRANGE - when(persistenceMock.readAll()).thenReturn(new HashMap<>()); - // ACT final var acceptedPolicies = testee.getAcceptedPolicies(null); diff --git a/irs-policy-store/src/test/java/org/eclipse/tractusx/irs/policystore/validators/BusinessPartnerNumberListValidatorTest.java b/irs-policy-store/src/test/java/org/eclipse/tractusx/irs/policystore/validators/BusinessPartnerNumberListValidatorTest.java index 50e0f7d191..b577b7796a 100644 --- a/irs-policy-store/src/test/java/org/eclipse/tractusx/irs/policystore/validators/BusinessPartnerNumberListValidatorTest.java +++ b/irs-policy-store/src/test/java/org/eclipse/tractusx/irs/policystore/validators/BusinessPartnerNumberListValidatorTest.java @@ -21,11 +21,13 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.verify; +import java.lang.annotation.Annotation; import java.util.Arrays; import java.util.Collections; import java.util.List; import jakarta.validation.ConstraintValidatorContext; +import jakarta.validation.Payload; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; @@ -33,7 +35,6 @@ import org.mockito.Answers; import org.mockito.ArgumentCaptor; import org.mockito.Captor; -import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -43,9 +44,6 @@ class BusinessPartnerNumberListValidatorTest { public static final String VALID_BPN_1 = "BPNL1234567890AB"; public static final String VALID_BPN_2 = "BPNL123456789012"; - @InjectMocks - private BusinessPartnerNumberListValidator validator; - @Captor private ArgumentCaptor messageCaptor; @@ -54,24 +52,26 @@ class BusinessPartnerNumberListValidatorTest { @Test void withEmptyListOfStrings() { - assertThat(validator.isValid(Collections.emptyList(), contextMock)).isTrue(); + assertThat(new BusinessPartnerNumberListValidatorBuilder().build() + .isValid(Collections.emptyList(), + contextMock)).isTrue(); } @Test void withNull() { - assertThat(validator.isValid(null, contextMock)).isTrue(); + assertThat(new BusinessPartnerNumberListValidatorBuilder().build().isValid(null, contextMock)).isTrue(); } @Test void withValidListOfStrings() { List validList = Arrays.asList(VALID_BPN_1, VALID_BPN_2); - assertThat(validator.isValid(validList, contextMock)).isTrue(); + assertThat(new BusinessPartnerNumberListValidatorBuilder().build().isValid(validList, contextMock)).isTrue(); } @Test void withListContainingInvalidBPN() { List invalidList = Arrays.asList(VALID_BPN_1, "INVALID_BPN", VALID_BPN_2); - assertThat(validator.isValid(invalidList, contextMock)).isFalse(); + assertThat(new BusinessPartnerNumberListValidatorBuilder().build().isValid(invalidList, contextMock)).isFalse(); verify(contextMock).buildConstraintViolationWithTemplate(messageCaptor.capture()); assertThat(messageCaptor.getValue()).contains("BPN").contains(" index 1 ").contains("invalid"); } @@ -86,8 +86,86 @@ void withListContainingInvalidBPN() { "ERRRES" }) void withInvalidBPN(final String invalidBPN) { - assertThat(validator.isValid(Collections.singletonList(invalidBPN), contextMock)).isFalse(); + assertThat(new BusinessPartnerNumberListValidatorBuilder().build() + .isValid(Collections.singletonList(invalidBPN), + contextMock)).isFalse(); verify(contextMock).buildConstraintViolationWithTemplate(messageCaptor.capture()); assertThat(messageCaptor.getValue()).contains("BPN").contains(" index 0 ").contains("invalid"); } + + @Test + void withAllowDefaultTrue_goodCase() { + final BusinessPartnerNumberListValidator validator = new BusinessPartnerNumberListValidatorBuilder().allowDefault( + true).build(); + final List listWithDefault = Arrays.asList("BPNL1234567890AB", "default"); + assertThat(validator.isValid(listWithDefault, contextMock)).isTrue(); + } + + @Test + void withAllowDefaultTrue_badCase() { + final BusinessPartnerNumberListValidator validator = new BusinessPartnerNumberListValidatorBuilder().build(); + final List listWithDefault = Arrays.asList("BPNL1234567890AB", "default"); + assertThat(validator.isValid(listWithDefault, contextMock)).isFalse(); + verify(contextMock).buildConstraintViolationWithTemplate(messageCaptor.capture()); + assertThat(messageCaptor.getValue()).startsWith("The business partner number at index 1 is invalid"); + } + + /** + * Builder for BusinessPartnerNumberListValidator. + */ + public static class BusinessPartnerNumberListValidatorBuilder { + + private String message = "Invalid list of business partner numbers"; + private Class[] groups = new Class[0]; + private Class[] payload = new Class[0]; + private boolean allowDefault = false; + + public BusinessPartnerNumberListValidatorBuilder setMessage(String message) { + this.message = message; + return this; + } + + public BusinessPartnerNumberListValidatorBuilder setGroups(Class[] groups) { + this.groups = groups; + return this; + } + + public BusinessPartnerNumberListValidatorBuilder setPayload(Class[] payload) { + this.payload = payload; + return this; + } + + public BusinessPartnerNumberListValidatorBuilder allowDefault(boolean allowDefault) { + this.allowDefault = allowDefault; + return this; + } + + public BusinessPartnerNumberListValidator build() { + ValidListOfBusinessPartnerNumbers annotation = new ValidListOfBusinessPartnerNumbers() { + public Class annotationType() { + return ValidListOfBusinessPartnerNumbers.class; + } + + public String message() { + return message; + } + + public Class[] groups() { + return groups; + } + + public Class[] payload() { + return payload; + } + + public boolean allowDefault() { + return allowDefault; + } + }; + + final BusinessPartnerNumberListValidator validator = new BusinessPartnerNumberListValidator(); + validator.initialize(annotation); + return validator; + } + } }