Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
@@ -1,6 +1,6 @@
package it.gov.pagopa.rtd.transaction_filter.connector;

import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.util.List;
import javax.validation.constraints.NotNull;
import lombok.Data;
Expand All @@ -10,11 +10,14 @@ public class BinRangeResponse {

@NotNull
List<String> fileLinks;

@NotNull
Integer numberOfFiles;

@NotNull
LocalDateTime availableUntil;
OffsetDateTime availableUntil;

@NotNull
LocalDateTime generationDate;
OffsetDateTime generationDate;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package it.gov.pagopa.rtd.transaction_filter.validator;


import java.util.Objects;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.ValidationException;
import javax.validation.Validator;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ResponseStatusException;

/**
* Basic implementation of interface ResponseEntityValidator for minimal validation on http status
* and body annotations.
*/
@Component
@RequiredArgsConstructor
public class BasicResponseEntityValidator<T> implements ResponseEntityValidator<T> {

public static final String BODY_IS_NOT_VALID = "Body is not valid.";

private final Validator validator;

@SneakyThrows
@Override
public void validate(ResponseEntity<T> responseEntity) {
if (!responseEntity.getStatusCode().is2xxSuccessful()) {
throw new ResponseStatusException(responseEntity.getStatusCode());
}
T body = responseEntity.getBody();
Objects.requireNonNull(body);

validateBody(body);
}

protected void validateBody(T body) {
Set<ConstraintViolation<T>> violations = validator.validate(body);

if (!violations.isEmpty()) {
throw new ValidationException(BODY_IS_NOT_VALID);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package it.gov.pagopa.rtd.transaction_filter.validator;

import it.gov.pagopa.rtd.transaction_filter.connector.BinRangeResponse;
import javax.validation.ValidationException;
import javax.validation.Validator;
import org.springframework.stereotype.Component;

/**
* Custom validation on objects of type BinRangeResponse
*/
@Component
public class BinRangeResponseEntityValidator extends
BasicResponseEntityValidator<BinRangeResponse> {

public static final String NUM_FILES_DOES_NOT_MATCH_LINKS = "NumberOfFiles does not match FileLinks size.";

public BinRangeResponseEntityValidator(Validator validator) {
super(validator);
}

@Override
protected void validateBody(BinRangeResponse body) {
super.validateBody(body);

if (body.getFileLinks().size() != body.getNumberOfFiles()) {
throw new ValidationException(NUM_FILES_DOES_NOT_MATCH_LINKS);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package it.gov.pagopa.rtd.transaction_filter.validator;

import org.springframework.http.ResponseEntity;

/**
* Validator interface for custom validation on ResponseEntity objects.
*
* @param <T> type of object wrapped by the ResponseEntity
*/
public interface ResponseEntityValidator<T> {

void validate(ResponseEntity<T> responseEntity);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package it.gov.pagopa.rtd.transaction_filter.validator;

import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* Definition of default annotation validator.
*/
@Configuration
public class ValidatorConfig {

@Bean
public Validator getValidator() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
return factory.getValidator();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package it.gov.pagopa.rtd.transaction_filter.validator;

import static it.gov.pagopa.rtd.transaction_filter.validator.BinRangeUtility.createInvalidResponse;
import static it.gov.pagopa.rtd.transaction_filter.validator.BinRangeUtility.createValidResponseEntity;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import it.gov.pagopa.rtd.transaction_filter.connector.BinRangeResponse;
import javax.validation.ValidationException;
import lombok.SneakyThrows;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.server.ResponseStatusException;

class BasicResponseEntityValidatorTest {

ValidatorConfig validatorConfig = new ValidatorConfig();
private final ResponseEntityValidator<BinRangeResponse> responseEntityValidator =
new BasicResponseEntityValidator<>(validatorConfig.getValidator());

@SneakyThrows
@Test
void whenResponseIsValidThenNoExceptionIsThrown() {
ResponseEntity<BinRangeResponse> binRangeResponse = createValidResponseEntity(HttpStatus.OK);

responseEntityValidator.validate(binRangeResponse);
}

@ParameterizedTest
@ValueSource(ints = {401, 403, 404, 500})
void whenHttpStatusIsNot2xxThenThrowException(int httpStatus) {
ResponseEntity<BinRangeResponse> binRangeResponse = createValidResponseEntity(
HttpStatus.resolve(httpStatus));

assertThatThrownBy(() -> responseEntityValidator.validate(binRangeResponse))
.isInstanceOf(ResponseStatusException.class);
}

@Test
void whenResponseIsInvalidThenThrowException() {
ResponseEntity<BinRangeResponse> binRangeResponse = createInvalidResponse();

assertThatThrownBy(() -> responseEntityValidator.validate(binRangeResponse))
.isInstanceOf(ValidationException.class)
.hasMessage(BasicResponseEntityValidator.BODY_IS_NOT_VALID);
}

@Test
void whenResponseEntityHasEmptyBodyThenThrowException() {
ResponseEntity<BinRangeResponse> binRangeResponse = ResponseEntity.ok().build();

assertThatThrownBy(() -> responseEntityValidator.validate(binRangeResponse))
.isInstanceOf(NullPointerException.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package it.gov.pagopa.rtd.transaction_filter.validator;

import static it.gov.pagopa.rtd.transaction_filter.validator.BinRangeUtility.createValidResponseEntity;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import it.gov.pagopa.rtd.transaction_filter.connector.BinRangeResponse;
import java.util.Objects;
import javax.validation.ValidationException;
import lombok.SneakyThrows;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

class BinRangeResponseEntityValidatorTest {

ValidatorConfig validatorConfig = new ValidatorConfig();
private final ResponseEntityValidator<BinRangeResponse> responseEntityValidator =
new BinRangeResponseEntityValidator(validatorConfig.getValidator());

@Test
void whenBinRangeDoesNotMatchLinksAndNumbersOfFilesThenThrowException() {
ResponseEntity<BinRangeResponse> binRangeResponse = createValidResponseEntity(HttpStatus.OK);
Objects.requireNonNull(binRangeResponse.getBody()).setNumberOfFiles(3);

assertThatThrownBy(() -> responseEntityValidator.validate(binRangeResponse))
.isInstanceOf(ValidationException.class)
.hasMessage(BinRangeResponseEntityValidator.NUM_FILES_DOES_NOT_MATCH_LINKS);
}

@SneakyThrows
@Test
void whenBinRangeResponseIsValidThenNoExceptionIsThrown() {
ResponseEntity<BinRangeResponse> binRangeResponse = createValidResponseEntity(HttpStatus.OK);

responseEntityValidator.validate(binRangeResponse);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package it.gov.pagopa.rtd.transaction_filter.validator;

import it.gov.pagopa.rtd.transaction_filter.connector.BinRangeResponse;
import java.time.OffsetDateTime;
import java.util.Arrays;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

public class BinRangeUtility {

private BinRangeUtility() {}

public static BinRangeResponse createValidBinRangeResponse() {
BinRangeResponse stubResponse = new BinRangeResponse();
stubResponse.setFileLinks(Arrays.asList("link1", "link2"));
stubResponse.setGenerationDate(OffsetDateTime.now().minusMonths(2));
stubResponse.setNumberOfFiles(2);
stubResponse.setAvailableUntil(OffsetDateTime.now().plusMonths(1));

return stubResponse;
}

public static ResponseEntity<BinRangeResponse> createValidResponseEntity(HttpStatus status) {
return ResponseEntity.status(status).body(createValidBinRangeResponse());
}

public static ResponseEntity<BinRangeResponse> createInvalidResponse() {
BinRangeResponse invalidResponse = createValidBinRangeResponse();
invalidResponse.setFileLinks(null);
return ResponseEntity.ok(invalidResponse);
}
}