-1

Im currently doing a side project to validate objects using java 8.

Currently I have this:

  • An interface that is essencially a rewrite of the java 8 predicate interface:

enter image description here

Then, I created the implementation of that same interface:

enter image description here

And then this class is the result of my validation

enter image description here

The concrete object validation can be found here:

public class ConcreteValidator implements EmployeeValidator {
  @Override
  public void validate(Employee employee) throws EmployeeException {

    ValidatorUtil.notNullString.and(ValidatorUtil.notEmptyString)
        .and(ValidatorUtil.stringBetween(1, 100)).test(employee.getFirstName())
        .getFieldNameIfInvalid(" Please specify valid firstname ").orElse("");

    ValidatorUtil.notNullString.and(ValidatorUtil.notEmptyString)
        .and(ValidatorUtil.stringBetween(1, 100)).test(employee.getLastName())
        .getFieldNameIfInvalid(" Please specify valid lastname ").orElse("");

    ValidatorUtil.notNullString.and(ValidatorUtil.notEmptyString)
        .and(ValidatorUtil.stringBetween(3, 100)).test(employee.getEmail())
        .getFieldNameIfInvalid(" Please specify valid email ").orElse("");

    ValidatorUtil.notNullInteger.and(ValidatorUtil.greaterThanZero)
        .and(ValidatorUtil.integerBetween(18, 60)).test(employee.getAge())
        .getFieldNameIfInvalid(" Please specify valid age ").orElse("");
  }
}

This works fine but what I want to do now is to limit the user to use the notNull verification first, and only after that validation all the methods like notEmpty or greaterThanZero will be available.

I searched for fluent interfaces but don't know if it is the correct way to do it (want to do something like this: https://code-held.com/2019/04/29/robust-builder-pattern/)

To summarise, I want to force the developer to validate if the object is null first and all the other methods go next, something like the chaining of the Stream API in java-8.Here is my customValidations.

enter image description here

smac89
  • 39,374
  • 15
  • 132
  • 179
pedro
  • 7
  • 1
  • 4
  • 6
    You should copy the code rather than putting images. – NoDataFound Jan 30 '20 at 23:04
  • If it is a requirement that they always validate for non-null, you could simply make that automatic. The validator could check for non-null before applying any other validations, and the client would not have to specify the non-null check. Also, please enter code as text, not images. – David Conrad Jan 31 '20 at 02:32

1 Answers1

2

You can't, not with how you do your methods: <K> GenericValidation<K> from(Predicate<K> predicate).

By doing so, you tell the developer he can pass any Java expressions: you can't validate the content of the expression at runtime, unlike you want to play with bytecode - which you don't.

You need to enforce this using the compiler, for example:

GenericValidation<K> fromNonNull(Predicate<K> predicate) {
  return from(val -> val != null && predicate.test(val));
}

Or using types as shown below:

validateThat(employee.getFirstName()) // return a StringValidator1
  .isNotNull() // return a StringValidator2
  .isNotEmpty()
  .hasLengthBetween(1, 100)
  ;

StringValidator1 only have isNotNull() and return StringValidator2.

That's how you would enforce the isNotNull() check with the compiler: by returning another type providing more services than the default. Since StringValidator1 does not have isNotEmpty(), then the compiler would generate a compilation error by trying to call it.

You may read AssertJ code for how they do their fluent interface. There are of course other source code being fluent (and I think the most important part of "fluent", is that the compiler and IDE helps you in validating what you are doing).

NoDataFound
  • 11,381
  • 33
  • 59