How to transfor - Validated<A> to Validated<B>
ffroliva opened this issue · 12 comments
I have the following Validated<A> a;
with errors. and I want to transform it to Validated<B> b
. How can achieve that?
Thank you in advance.
Hi,
I wanted to combine the errors from two Validated into a single ConstraintViolations
.
Validated<A>
or Validated<B>
errors might exist because the validations where successfull.
This is how I did and it might be interesting for others:
import am.ik.yavi.core.ConstraintViolations;
import am.ik.yavi.core.Validated;
import java.util.Collection;
import java.util.Collections;
import java.util.stream.Stream;
public class ConstraintViolationsUtil {
public static ConstraintViolations combineConstraintViolations(Validated<?>... validated) {
return ConstraintViolations.of(Stream.of(validated)
.map(ConstraintViolationsUtil::getErrorsIfInvalid)
.map(ConstraintViolations::violations)
.flatMap(Collection::stream)
.toList());
}
public static ConstraintViolations getErrorsIfInvalid(Validated<?> validated) {
return validated.isValid() ? ConstraintViolations.of(Collections.emptyList()) : validated.errors();
}
}
As a result I generated a object Validated.of(Validated.failure(constraintViolations))
Did you try combine
method?
https://yavi.ik.am/#combining-validation-validated-objects
Yes, but didn't work for me.
Basically, I have a matrix of data and I have to perform several validations on it. Column headers, row headers, and the data itself.
I only care about the data to generate my Validated<T>
object, but I need to validate the column and rows headers.
If I have validation errors in my column and row headers I need to combine the errors from these two validators together and return the errors as a Validated<T>
object.
I am not sure if this would be the best approached to handle the validation, but it made sense for me. if you other ideias on how to tackle such a scenario, I would be more then happy to hear.
Thanks for the support as always.
Can you share a minimal reproducible project?
Here is the link with the code.
In your example, you just want to concatenate two Validated<List<Integer>>
s (integerColumnHeaders.getHeaders()
and integerRowHeaders.getHeaders()
) into a Validated<List<Integer>>
.
Is it correct?
I would write
public Validated<Matrix> read() {
Validated<List<Integer>> columnHeaders = new IntegerColumnHeaders(this.sheet).getHeaders();
Validated<List<Integer>> rowHeaders = new IntegerRowHeaders(this.sheet).getHeaders();
Validation<ConstraintViolation, Sheet> sheetValidation = Validations.combine(columnHeaders, rowHeaders).apply((c, r) -> this.sheet);
return Validated.of(sheetValidation.flatMap(sheet -> {
short numOfColumns = sheet.getRow(0).getLastCellNum();
int numOfRows = sheet.getLastRowNum();
final double[][] data = new double[numOfRows][numOfColumns];
ConstraintViolations constraintViolations = new ConstraintViolations();
for (int rIndex = 1; numOfRows > rIndex; rIndex++) {
for (int cIndex = 1; numOfColumns > cIndex; cIndex++) {
Cell cell = CellUtil.getCell(sheet.getRow(rIndex), cIndex); //CellUtil#getCell creates a cell it it doesn't exist
final Validated<Double> cellValidated = CellValidator.NUMERIC_CELL_TYPE_VALIDATOR.validate(cell);
if (cellValidated.isValid()) {
data[rIndex - 1][cIndex - 1] = sheet.getRow(rIndex).getCell(cIndex).getNumericCellValue();
}
else {
constraintViolations.addAll(cellValidated.errors());
}
}
}
if (constraintViolations.isValid()) {
return Validation.success(new Matrix(data));
}
else {
return Validation.failure(constraintViolations);
}
}));
}
or
final ValueValidator<Sheet, Matrix> sheetValidator = (sheet, locale, constraintContext) -> {
short numOfColumns = sheet.getRow(0).getLastCellNum();
int numOfRows = sheet.getLastRowNum();
final double[][] data = new double[numOfRows][numOfColumns];
ConstraintViolations constraintViolations = new ConstraintViolations();
for (int rIndex = 1; numOfRows > rIndex; rIndex++) {
for (int cIndex = 1; numOfColumns > cIndex; cIndex++) {
Cell cell = CellUtil.getCell(sheet.getRow(rIndex), cIndex); //CellUtil#getCell creates a cell it it doesn't exist
final Validated<Double> cellValidated = CellValidator.NUMERIC_CELL_TYPE_VALIDATOR.validate(cell);
if (cellValidated.isValid()) {
data[rIndex - 1][cIndex - 1] = sheet.getRow(rIndex).getCell(cIndex).getNumericCellValue();
}
else {
constraintViolations.addAll(cellValidated.errors());
}
}
}
if (constraintViolations.isValid()) {
return Validated.of(Validation.success(new Matrix(data)));
}
else {
return Validated.of(Validation.failure(constraintViolations));
}
};
public Validated<Matrix> read() {
Validated<List<Integer>> columnHeaders = new IntegerColumnHeaders(this.sheet).getHeaders();
Validated<List<Integer>> rowHeaders = new IntegerRowHeaders(this.sheet).getHeaders();
Validation<ConstraintViolation, Sheet> sheetValidation = Validations.combine(columnHeaders, rowHeaders).apply((c, r) -> this.sheet);
return sheetValidation.flatMap(sheetValidator::validate);
}
In your example, you just want to concatenate two
Validated<List<Integer>>
s (integerColumnHeaders.getHeaders()
andintegerRowHeaders.getHeaders()
) into aValidated<List<Integer>>
. Is it correct?
The errors yes, but the values no.
All the errors are related to the sheet but the validations happen in the cell level.
BTW, when you combine the the two Validated<List> will the values also will be combined?
Let say that I have a Validator A
input is List.of(1,2,3)
and Validator B
has the input List.of(4,5,6)
by combining the validators the value will return a list with 1,2,3,4,5,6
?
yes, you can as bellow
Validation<ConstraintViolation, List<Integer>> validation = Validations.combine(columnHeaders, rowHeaders)
.apply((c, r) -> {
List<Integer> list = new ArrayList<>();
list.addAll(c);
list.addAll(r);
return list;
});