Skip to content

Commit

Permalink
[#59]Added validators for parameter validation. Validation at process…
Browse files Browse the repository at this point in the history
…ing time must still be done
  • Loading branch information
tobiasstamann committed Nov 6, 2023
1 parent fd37286 commit 0890a0b
Show file tree
Hide file tree
Showing 22 changed files with 107 additions and 33 deletions.
49 changes: 48 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,54 @@ public interface MyFluentInterface {

}
```

### Using validators at fluent interface method parameters
FluApiGen provides some basic validators that can be applied to the fluent method parameters at runtime.

- _Matches_ : Regular Expression validator for Strings
- _MinLength / MaxLength_ : Checks length of Strings or size of Arrays or Collections
- _NotEmpty_ : Checks if String, array and Collection are not empty
- _NotNull_ : Checks if passed argument isn't null

To be able to use validators, the _fluapigen_validation_api_ library must be linked at compile and runtime.

````java
MyRootInterface setName(@Matches("Max.*") @FluentApiBackingBeanMapping("name") String name);
````

In this example the fluent api would throw a _ValidatorException_ if the name doesn't start with "Max".

It's possible to use multiple validators on a parameter and even to provide custom validators:

````java
@FluentApiValidator(value = Matches.ValidatorImpl.class, parameterNames = {"value"})
public @interface Matches {

String value();

class ValidatorImpl implements Validator<String> {

private final String regularExpression;

public ValidatorImpl(String regularExpression) {
this.regularExpression = regularExpression;
}

@Override
public boolean validate(String obj) {
return Pattern.compile(regularExpression).matcher(obj).matches();
}

}

}
````

Validators are annotations annotated with _FluentApiValidator_ meta annotation. The _FluentApiValidator_ annotation is used to reference the validators implementation class that must implement the _Validator_ interface.
Validation criteria can be added as annotation attribute. The _FluentApiValidator_ meta annotation defines the attribute to validator constructor mapping via the parameterNames attribute.
The validator implementation must provide a matching constructor.

*Remark : The feature is currently under development and not 100% done. There will still be improvements regarding processing time validation and error output*

### Javas default methods in fluent api and backing bean in interfaces
Default methods will be ignored during processing of fluent api and backing bean interfaces and can be used for different tasks:

Expand Down
2 changes: 1 addition & 1 deletion fluapigen-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
<dependencies>
<dependency>
<groupId>io.toolisticon.fluapigen</groupId>
<artifactId>fluapigen-runtime-api</artifactId>
<artifactId>fluapigen-validation-api</artifactId>
</dependency>
</dependencies>

Expand Down
5 changes: 2 additions & 3 deletions fluapigen-integrationTest/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,9 @@
</path>
<path>
<groupId>io.toolisticon.fluapigen</groupId>
<artifactId>fluapigen-runtime-api</artifactId>
<artifactId>fluapigen-api</artifactId>
<version>${project.version}</version>
</path>

</annotationProcessorPaths>
</configuration>

Expand Down Expand Up @@ -104,7 +103,7 @@

<dependency>
<groupId>io.toolisticon.fluapigen</groupId>
<artifactId>fluapigen-runtime-api</artifactId>
<artifactId>fluapigen-validation-api</artifactId>
</dependency>

<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
import io.toolisticon.fluapigen.api.FluentApiCommand;
import io.toolisticon.fluapigen.api.FluentApiInterface;
import io.toolisticon.fluapigen.api.FluentApiRoot;
import io.toolisticon.fluapigen.api.validation.Matches;
import io.toolisticon.fluapigen.validation.api.Matches;
import io.toolisticon.fluapigen.validation.api.MaxLength;
import io.toolisticon.fluapigen.validation.api.NotNull;

@FluentApi("ValidatorExampleStarter")
public class ValidatorExample {
Expand All @@ -26,7 +28,7 @@ interface MyBackingBean {
@FluentApiRoot
public interface MyRootInterface {

MyRootInterface setName(@Matches("aaa.*") @FluentApiBackingBeanMapping("name") String name);
MyRootInterface setName(@NotNull @MaxLength(8) @Matches("aaa.*") @FluentApiBackingBeanMapping("name") String name);

@FluentApiCommand(MyCommand.class)
void myCommand();
Expand All @@ -35,13 +37,11 @@ public interface MyRootInterface {

// Commands
@FluentApiCommand
static class MyCommand{
static void myCommand (MyBackingBean backingBean) {
static class MyCommand {
static void myCommand(MyBackingBean backingBean) {
System.out.println(backingBean.getName());
}
}




}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@ public class ValidatorExampleTest {
@Test(expected = RuntimeException.class)
public void testValidator_failingValidation() {

ValidatorExampleStarter.setName("bbbadad").myCommand();
ValidatorExampleStarter.setName("bbbadadadsd").myCommand();

}

@Test()
public void testValidator() {

ValidatorExampleStarter.setName("aaaBDSXS").myCommand();

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import io.toolisticon.fluapigen.api.FluentApiBackingBeanMapping;
import io.toolisticon.fluapigen.api.FluentApiConverter;
import io.toolisticon.fluapigen.api.TargetBackingBean;
import io.toolisticon.fluapigen.api.validation.FluentApiValidator;
import io.toolisticon.fluapigen.validation.api.FluentApiValidator;

import java.util.List;
import java.util.Optional;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.toolisticon.fluapigen.processor;

import io.toolisticon.aptk.common.ToolingProvider;
import io.toolisticon.aptk.tools.TypeMirrorWrapper;
import io.toolisticon.aptk.tools.corematcher.AptkCoreMatchers;
import io.toolisticon.aptk.tools.wrapper.AnnotationMirrorWrapper;
Expand All @@ -22,6 +23,7 @@ FluentApiValidatorWrapper getValidatorAnnotation() {
return FluentApiValidatorWrapper.wrap(this.validatorAnnotation.asElement().unwrap());
}

// TODO NOT USED YET, MUST BE IMPLEMENTED
public boolean validate() {
// must check if parameter types are assignable
FluentApiValidatorWrapper validatorMetaAnnotation = getValidatorAnnotation();
Expand All @@ -35,7 +37,13 @@ public boolean validate() {
} else {
// must have a noarg constructor or just the default
TypeElementWrapper validatorImplTypeElement = validatorImplType.getTypeElement().get();
List<ExecutableElement> constructors = validatorImplTypeElement.filterEnclosedElements().applyFilter(AptkCoreMatchers.IS_CONSTRUCTOR).getResult();
boolean hasNoargConstructor = validatorImplTypeElement.filterEnclosedElements().applyFilter(AptkCoreMatchers.IS_CONSTRUCTOR).applyFilter(AptkCoreMatchers.HAS_NO_PARAMETERS).getResult().size() == 1;
boolean hasJustDefaultConstructor = validatorImplTypeElement.filterEnclosedElements().applyFilter(AptkCoreMatchers.IS_CONSTRUCTOR).hasSize(0);

if (! ( hasNoargConstructor || hasJustDefaultConstructor)) {
//ToolingProvider.getTooling().getMessager().
//this.validatorAnnotation.
}
}

return true;
Expand Down Expand Up @@ -84,5 +92,8 @@ public String validatorExpression() {
return stringBuilder.toString();
}

public String getValidatorSummary() {
return validatorAnnotation.getStringRepresentation();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@
import io.toolisticon.fluapigen.api.FluentApiInlineBackingBeanMapping;
import io.toolisticon.fluapigen.api.FluentApiInterface;
import io.toolisticon.fluapigen.api.FluentApiParentBackingBeanMapping;
import io.toolisticon.fluapigen.api.validation.FluentApiValidator;
import io.toolisticon.fluapigen.validation.api.FluentApiValidator;
4 changes: 3 additions & 1 deletion fluapigen-processor/src/main/resources/FluentApi.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import java.util.Deque;
import java.util.HashSet;
import java.util.stream.Collectors;

import io.toolisticon.fluapigen.validation.api.ValidatorException;

/**
* An empty class.
*/
Expand Down Expand Up @@ -82,7 +84,7 @@ public class ${ model.className } {
!{if parameter.hasValidators}
!{for validator : parameter.validators}
if(!${validator.validatorExpression}.validate(${parameter.parameterName})) {
throw new RuntimeException("Parameter ${parameter.parameterName} failed validation");
throw new ValidatorException("Parameter '${parameter.parameterName}' of method '${method.executableElement.simpleName}' failed validation: ${validator.validatorSummary}");
}
!{/for}
!{/if}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import io.toolisticon.cute.CompileTestBuilder;
import io.toolisticon.cute.PassIn;
import io.toolisticon.cute.UnitTest;
import io.toolisticon.fluapigen.api.validation.Matches;
import io.toolisticon.fluapigen.validation.api.Matches;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.Before;
Expand Down Expand Up @@ -42,7 +42,7 @@ public void testMatchesValidator() {
ToolingProvider.setTooling(processingEnvironment);

ModelValidator unit = new ModelValidator(VariableElementWrapper.wrap(element).getAnnotationMirror(Matches.class).get());
MatcherAssert.assertThat(unit.validatorExpression(), Matchers.is("new io.toolisticon.fluapigen.api.validation.Matches.ValidatorImpl(\"aaa.*\")"));
MatcherAssert.assertThat(unit.validatorExpression(), Matchers.is("new io.toolisticon.fluapigen.validation.api.Matches.ValidatorImpl(\"aaa.*\")"));

} finally {
ToolingProvider.clearTooling();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import io.toolisticon.fluapigen.api.FluentApiCommand;
import io.toolisticon.fluapigen.api.FluentApiInterface;
import io.toolisticon.fluapigen.api.FluentApiRoot;
import io.toolisticon.fluapigen.api.validation.Matches;
import io.toolisticon.fluapigen.validation.api.Matches;

@FluentApi("Xyz")
public class TestcaseValidator {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<artifactId>fluapigen-runtime-api</artifactId>
<artifactId>fluapigen-validation-api</artifactId>
<packaging>jar</packaging>

<parent>
Expand All @@ -12,7 +12,7 @@
<version>0.7.1-SNAPSHOT</version>
</parent>

<name>fluapigen-runtime-api</name>
<name>fluapigen-validation-api</name>


<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.toolisticon.fluapigen.api.validation;
package io.toolisticon.fluapigen.validation.api;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.toolisticon.fluapigen.api.validation;
package io.toolisticon.fluapigen.validation.api;


import java.util.regex.Pattern;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.toolisticon.fluapigen.api.validation;
package io.toolisticon.fluapigen.validation.api;

import java.lang.reflect.Array;
import java.util.Collection;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.toolisticon.fluapigen.api.validation;
package io.toolisticon.fluapigen.validation.api;

import java.lang.reflect.Array;
import java.util.Collection;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.toolisticon.fluapigen.api.validation;
package io.toolisticon.fluapigen.validation.api;

import java.lang.reflect.Array;
import java.util.Collection;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.toolisticon.fluapigen.api.validation;
package io.toolisticon.fluapigen.validation.api;

@FluentApiValidator(NotNull.ValidatorImpl.class)
public @interface NotNull {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.toolisticon.fluapigen.api.validation;
package io.toolisticon.fluapigen.validation.api;

/**
* The Validator interface.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.toolisticon.fluapigen.validation.api;

public class ValidatorException extends RuntimeException{

public ValidatorException(String message) {
super(message);
}

}
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
<!-- project dependency versions -->
<cute.version>0.12.1</cute.version>
<spiap.version>0.11.0</spiap.version>
<aptk.version>0.22.7-SNAPSHOT</aptk.version>
<aptk.version>0.22.7</aptk.version>

<!-- versions of test dependencies -->
<junit.version>4.13.2</junit.version>
Expand Down Expand Up @@ -622,7 +622,7 @@

<dependency>
<groupId>io.toolisticon.fluapigen</groupId>
<artifactId>fluapigen-runtime-api</artifactId>
<artifactId>fluapigen-validation-api</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
Expand Down Expand Up @@ -690,7 +690,7 @@


<modules>
<module>fluapigen-runtime-api</module>
<module>fluapigen-validation-api</module>
<module>fluapigen-api</module>
<module>fluapigen-processor</module>
<module>fluapigen-example</module>
Expand Down

0 comments on commit 0890a0b

Please sign in to comment.