Skip to content

Commit

Permalink
Pass selected annotation to AttributeStrategy constructor to allow cu…
Browse files Browse the repository at this point in the history
…stomization for Issue mtedone#237
  • Loading branch information
daivanov committed Feb 6, 2017
1 parent 96d0870 commit 79be6f8
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public abstract class TypeManufacturerUtil {
* @param strategy
* The data provider strategy
* @param annotations
* The list of annotations
* The list of annotations, irrelevant annotations will be removed
* @param attributeType
* Type of attribute expected to be returned
* @return {@link AttributeStrategy}, if {@link PodamStrategyValue} or bean
Expand All @@ -47,13 +47,18 @@ public abstract class TypeManufacturerUtil {
* if attribute strategy cannot be instantiated
* @throws InstantiationException
* if attribute strategy cannot be instantiated
* @throws SecurityException
* if access security is violated
* @throws InvocationTargetException
* if invocation failed
* @throws IllegalArgumentException
* if illegal argument provided to a constructor
*/
public static AttributeStrategy<?> findAttributeStrategy(DataProviderStrategy strategy,
List<Annotation> annotations, Class<?> attributeType)
throws InstantiationException, IllegalAccessException {
throws InstantiationException, IllegalAccessException, SecurityException, IllegalArgumentException, InvocationTargetException {

List<Annotation> localAnnotations = new ArrayList<Annotation>(annotations);
Iterator<Annotation> iter = localAnnotations.iterator();
Iterator<Annotation> iter = annotations.iterator();
while (iter.hasNext()) {
Annotation annotation = iter.next();
if (annotation instanceof PodamStrategyValue) {
Expand All @@ -79,7 +84,13 @@ public static AttributeStrategy<?> findAttributeStrategy(DataProviderStrategy st

Class<AttributeStrategy<?>> attrStrategyClass;
if ((attrStrategyClass = strategy.getStrategyForAnnotation(annotationClass)) != null) {
return attrStrategyClass.newInstance();
Constructor<AttributeStrategy<?>> ctor;
try {
ctor = attrStrategyClass.getConstructor(Annotation.class);

This comment has been minimized.

Copy link
@NBau

NBau Feb 7, 2017

Why do you rely on constructor injection for the Annotation instance instead of extending the T getValue() method of the AttributeStrategy with a parameter: T getValue(Annotation annotation);? This way it is more explicit and people unfamiliar with the code don't have to ensure that a constructor with a parameter is present, which they will probably only find out through trial and error..

This comment has been minimized.

Copy link
@daivanov

daivanov Feb 7, 2017

Author Owner

There are several reasons for this. And the main one this is an API change. Apparently just annotation is not enough, you may need a field or it's type and instance of POJO - roughly the same thing type manufacturer is receiving.

This comment has been minimized.

Copy link
@NBau

NBau via email Feb 7, 2017

return ctor.newInstance(annotation);
} catch(NoSuchMethodException e) {
return attrStrategyClass.newInstance();
}
}

if (annotation.annotationType().getAnnotation(Constraint.class) != null) {
Expand All @@ -99,12 +110,12 @@ public static AttributeStrategy<?> findAttributeStrategy(DataProviderStrategy st
}

AttributeStrategy<?> retValue = null;
if (!localAnnotations.isEmpty()
if (!annotations.isEmpty()
&& !Collection.class.isAssignableFrom(attributeType)
&& !Map.class.isAssignableFrom(attributeType)
&& !attributeType.isArray()) {

retValue = new BeanValidationStrategy(localAnnotations, attributeType);
retValue = new BeanValidationStrategy(annotations, attributeType);
}

return retValue;
Expand Down
38 changes: 38 additions & 0 deletions src/test/java/uk/co/jemos/podam/test/dto/ValidatedPatternPojo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
*
*/
package uk.co.jemos.podam.test.dto;


import javax.validation.constraints.Pattern;

/**
* POJO to test bean validation API
*
* @author daivanov
*
*/
public class ValidatedPatternPojo {

@Pattern(regexp = "^[0-9]{1,45}$")
private String number;

@Pattern(regexp = "^[a-zA-Z0-9_]*$")
private String identifier;

public String getNumber() {
return number;
}

public void setNumber(String number) {
this.number = number;
}

public String getIdentifier() {
return identifier;
}

public void setIdentifier(String identifier) {
this.identifier = identifier;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
*
*/
package uk.co.jemos.podam.test.strategies;

import java.lang.annotation.Annotation;

import javax.validation.constraints.Pattern;

import uk.co.jemos.podam.api.PodamUtils;
import uk.co.jemos.podam.common.AttributeStrategy;

/**
* @author daivanov
*
*/
public class PatternStrategy implements AttributeStrategy<String> {

/** validation annotation */
private Pattern patternAnnotation;

/**
* Constructor for the strategy
*
* @param annotation
* validation annotation
*/
public PatternStrategy(Annotation annotation) {
if (annotation instanceof Pattern) {
this.patternAnnotation = (Pattern)annotation;
} else {
throw new IllegalArgumentException(annotation.getClass().getSimpleName() + " is not Pattern");
}
}

/**
* Produces valid patterns.
*
* {@inheritDoc}
*/
public String getValue() {

StringBuffer sb = new StringBuffer();

if ("^[0-9]{1,45}$".equals(patternAnnotation.regexp())) {

sb.append(Integer.toString(PodamUtils.getIntegerInRange(0, 1000000)));
} else if ("^[a-zA-Z0-9_]*$".equals(patternAnnotation.regexp())) {

for (int i = 0; i < 2; i++) {
sb.append(PodamUtils.getNiceCharacter());
}
sb.append(Integer.toString(PodamUtils.getIntegerInRange(0, 10)));
}
return sb.toString();
}

// ------------------->> Constants

// ------------------->> Instance / Static variables

// ------------------->> Constructors

// ------------------->> Public methods

// ------------------->> Getters / Setters

// ------------------->> Private methods

// ------------------->> equals() / hashcode() / toString()

// ------------------->> Inner classes

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@
import org.junit.runner.RunWith;
import uk.co.jemos.podam.api.PodamFactory;
import uk.co.jemos.podam.common.AttributeStrategy;
import uk.co.jemos.podam.test.dto.ValidatedPatternPojo;
import uk.co.jemos.podam.test.dto.ValidatedPojo;
import uk.co.jemos.podam.test.dto.ValidatedPojoMultipleConstraints;
import uk.co.jemos.podam.test.dto.ValidationPojoForStringWithSizeAndNoMax;
import uk.co.jemos.podam.test.strategies.EmailStrategy;
import uk.co.jemos.podam.test.strategies.PatternStrategy;
import uk.co.jemos.podam.test.unit.AbstractPodamSteps;

import javax.validation.Validator;
import javax.validation.constraints.Pattern;

/**
* Tests Java bean validation API
Expand Down Expand Up @@ -68,6 +71,29 @@ public void podamShouldFulfillMostOfTheJavaxValidationFramework() throws Excepti

}

@Test
@Title("Podam should allow validation annotations customization")
public void podamShouldAllowValidationAnnotationsCustomization()
throws Exception {

@SuppressWarnings("unchecked")
Class<AttributeStrategy<?>> strategy = (Class<AttributeStrategy<?>>)(Class<?>)PatternStrategy.class;
PodamFactory podamFactory = podamFactorySteps.givenAPodamFactoryWithCustomStrategy(Pattern.class, strategy);
ValidatedPatternPojo pojo =
podamInvocationSteps.whenIInvokeTheFactoryForClass(
ValidatedPatternPojo.class,
podamFactory);
podamValidationSteps.thePojoMustBeOfTheType(pojo, ValidatedPatternPojo.class);

podamValidationSteps.thePojoMustBeOfTheType(pojo.getNumber(), String.class);
podamValidationSteps.thePojoMustBeOfTheType(pojo.getIdentifier(), String.class);

Validator validator = podamFactorySteps.givenAJavaxValidator();
validatorSteps.thePojoShouldNotViolateAnyValidations(validator, pojo);

podamFactorySteps.removeCustomStrategy(podamFactory, Pattern.class);
}

@Test
@Title("When the @Size annotation doesn't have a max length specified, Podam should assign a sensible value")
public void whenMaxLengthIsNotSpecifiedInSizeAnnotationPodamShouldAssignASensibleDefault()
Expand Down

0 comments on commit 79be6f8

Please sign in to comment.