Skip to content

Commit

Permalink
Merge pull request #95 from sta-szek/#89-SetterNotFoundException-when…
Browse files Browse the repository at this point in the history
…-field-is-boolean-and-has-`is`-prefix

#90. Boolean setters finder bug fixes
  • Loading branch information
Piotr Joński authored Sep 17, 2016
2 parents 4d473a7 + 95b8b27 commit f08cf65
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 64 deletions.
48 changes: 25 additions & 23 deletions src/main/java/pl/pojo/tester/internal/utils/MethodUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.function.Predicate;
import java.util.stream.Stream;
import org.apache.commons.lang3.reflect.TypeUtils;
import pl.pojo.tester.api.GetterNotFoundException;
import pl.pojo.tester.api.SetterNotFoundException;
Expand All @@ -14,26 +14,20 @@ private MethodUtils() {
}

public static Method findSetterFor(final Class<?> clazz, final Field field) {
final Method[] methods = clazz.getMethods();
final String fieldName = upperCaseFirstLetter(field.getName());
return Stream.of(methods)
.filter(method -> prefixMatchesSettersPrefixAndHasExpectedLength(method, fieldName))
.filter(methodNameEndsWithFieldName(fieldName))
return Arrays.stream(clazz.getMethods())
.filter(methodHasOnlyOneParameter())
.filter(areParameterAndFieldTypeAssignable(field))
.filter(returnTypeIsVoid())
.filter(method -> prefixMatchesSettersPrefixAndHasExpectedLength(method, field.getName()))
.findAny()
.orElseThrow(() -> new SetterNotFoundException(clazz, field));
}

public static Method findGetterFor(final Class<?> clazz, final Field field) {
final Method[] methods = clazz.getMethods();
final String fieldName = upperCaseFirstLetter(field.getName());
return Stream.of(methods)
.filter(method -> prefixMatchesGettersPrefixAndHasExpectedLength(method, fieldName))
.filter(methodNameEndsWithFieldName(fieldName))
return Arrays.stream(clazz.getMethods())
.filter(hasZeroParameters())
.filter(areReturnAndFieldTypeAssignable(field))
.filter(method -> prefixMatchesGettersPrefixAndHasExpectedLength(method, field.getName()))
.findAny()
.orElseThrow(() -> new GetterNotFoundException(clazz, field));
}
Expand All @@ -58,30 +52,38 @@ private static Predicate<Method> hasZeroParameters() {
return method -> method.getParameterCount() == 0;
}

private static Predicate<Method> methodNameEndsWithFieldName(final String fieldName) {
return method -> method.getName()
.endsWith(fieldName);
}

private static boolean prefixMatchesGettersPrefixAndHasExpectedLength(final Method method, final String fieldName) {
final Class<?> returnType = method.getReturnType();
final String methodName = method.getName();
final int fieldNameLength = fieldName.length();
final String upperCaseFirstLetterfieldName = upperCaseFirstLetter(fieldName);

if (returnType.equals(boolean.class) || returnType.equals(Boolean.class)) {
return (methodName.startsWith("is") && methodName.length() == fieldNameLength + 2)
|| (methodName.startsWith("has") && methodName.length() == fieldNameLength + 3)
|| (methodName.startsWith("get") && methodName.length() == fieldNameLength + 3)
|| (methodName.startsWith("have") && methodName.length() == fieldNameLength + 4)
|| (methodName.startsWith("contains") && methodName.length() == fieldNameLength + 8);
return (methodName.startsWith("is") && methodName.equals(fieldName))
|| ((methodName.endsWith(upperCaseFirstLetterfieldName))
&& ((methodName.startsWith("is") && (methodName.length() == (fieldNameLength + 2)))
|| (methodName.startsWith("has") && (methodName.length() == (fieldNameLength + 3)))
|| (methodName.startsWith("get") && (methodName.length() == (fieldNameLength + 3)))
|| (methodName.startsWith("have") && (methodName.length() == (fieldNameLength + 4)))
|| (methodName.startsWith("contains") && (methodName.length() == (fieldNameLength + 8)))));
} else {
return methodName.startsWith("get") && methodName.length() == fieldNameLength + 3;
return methodName.startsWith("get") && methodName.length() == fieldNameLength + 3 && methodName.endsWith(upperCaseFirstLetterfieldName);
}
}

private static boolean prefixMatchesSettersPrefixAndHasExpectedLength(final Method method, final String fieldName) {
final Class<?> parameterType = method.getParameterTypes()[0];
final String methodName = method.getName();
final int fieldNameLength = fieldName.length();
return methodName.startsWith("set") && methodName.length() == fieldNameLength + 3;
final String upperCaseFirstLetterFieldName = upperCaseFirstLetter(fieldName);

if ((parameterType.equals(boolean.class) || parameterType.equals(Boolean.class)) && fieldName.startsWith("is")) {
final String fieldNameWithoutPrefix = fieldName.substring(2);
return methodName.startsWith("set") && methodName.endsWith(fieldNameWithoutPrefix);

} else {
return methodName.startsWith("set") && methodName.length() == fieldNameLength + 3 && methodName.endsWith(upperCaseFirstLetterFieldName);
}
}

private static String upperCaseFirstLetter(final String string) {
Expand Down
115 changes: 74 additions & 41 deletions src/test/java/pl/pojo/tester/internal/utils/MethodUtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.lang.reflect.Method;
import java.util.stream.Stream;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.ToString;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
Expand All @@ -23,12 +24,12 @@ public class MethodUtilsTest {

@TestFactory
public Stream<DynamicTest> Should_Throw_Exception_When_Setter_Was_Not_Found() throws NoSuchFieldException {
final Field fieldA = fieldFromSettersClass("a");
final Field fieldB = fieldFromSettersClass("b");
final Field fieldC = fieldFromSettersClass("c");
final Field fieldD = fieldFromSettersClass("d");
final Field fieldF = fieldFromSettersClass("f");
final Field fieldG = fieldFromSettersClass("g");
final Field fieldA = field(Setters.class, "a");
final Field fieldB = field(Setters.class, "b");
final Field fieldC = field(Setters.class, "c");
final Field fieldD = field(Setters.class, "d");
final Field fieldF = field(Setters.class, "f");
final Field fieldG = field(Setters.class, "g");

return Stream.of(fieldA,
fieldB,
Expand All @@ -51,12 +52,12 @@ public Executable Should_Throw_Exception_When_Setter_Was_Not_Found(final Field f

@TestFactory
public Stream<DynamicTest> Should_Throw_Exception_When_Getter_Was_Not_Found() throws NoSuchFieldException {
final Field fieldA = fieldFromGettersClass("a");
final Field fieldB = fieldFromGettersClass("b");
final Field fieldD = fieldFromGettersClass("d");
final Field fieldE = fieldFromGettersClass("e");
final Field fieldF = fieldFromGettersClass("f");
final Field fieldG = fieldFromGettersClass("g");
final Field fieldA = field(Getters.class, "a");
final Field fieldB = field(Getters.class, "b");
final Field fieldD = field(Getters.class, "d");
final Field fieldE = field(Getters.class, "e");
final Field fieldF = field(Getters.class, "f");
final Field fieldG = field(Getters.class, "g");

return Stream.of(fieldA,
fieldB,
Expand All @@ -79,17 +80,20 @@ public Executable Should_Throw_Exception_When_Getter_Was_Not_Found(final Field f

@TestFactory
public Stream<DynamicTest> Should_Return_Expected_Getter() throws NoSuchFieldException, NoSuchMethodException {
final Field field1 = fieldFromGettersClass("getter1");
final Field field2 = fieldFromGettersClass("getter2");
final Field field3 = fieldFromGettersClass("getter3");
final Field field4 = fieldFromGettersClass("getter4");
final Field field5 = fieldFromGettersClass("getter5");
final Field field6 = fieldFromGettersClass("getter6");
final Field field7 = fieldFromGettersClass("getter7");
final Field field8 = fieldFromGettersClass("id");
final Field field9 = fieldFromGettersClass("otherId");
final Field field10 = fieldFromGettersClass("name");
final Field field11 = fieldFromGettersClass("otherName");
final Field field1 = field(Getters.class, "getter1");
final Field field2 = field(Getters.class, "getter2");
final Field field3 = field(Getters.class, "getter3");
final Field field4 = field(Getters.class, "getter4");
final Field field5 = field(Getters.class, "getter5");
final Field field6 = field(Getters.class, "getter6");
final Field field7 = field(Getters.class, "getter7");
final Field field8 = field(Getters.class, "id");
final Field field9 = field(Getters.class, "otherId");
final Field field10 = field(Getters.class, "name");
final Field field11 = field(Getters.class, "otherName");

final Field field12 = field(PojoWithNonStandardBooleanFieldNames_Standard_Generated_Setters_And_Getters.class, "isActive");
final Field field13 = field(PojoWithNonStandardBooleanFieldNames_Lombok_Generated_Setters_And_Getters.class, "isActive");

return Stream.of(new GetterTestCase(field1, Getters.class.getMethod("isGetter1")),
new GetterTestCase(field2, Getters.class.getMethod("hasGetter2")),
Expand All @@ -101,15 +105,20 @@ public Stream<DynamicTest> Should_Return_Expected_Getter() throws NoSuchFieldExc
new GetterTestCase(field8, Getters.class.getMethod("getId")),
new GetterTestCase(field9, Getters.class.getMethod("getOtherId")),
new GetterTestCase(field10, Getters.class.getMethod("getName")),
new GetterTestCase(field11, Getters.class.getMethod("getOtherName"))
new GetterTestCase(field11, Getters.class.getMethod("getOtherName")),

new GetterTestCase(field12,
PojoWithNonStandardBooleanFieldNames_Standard_Generated_Setters_And_Getters.class.getMethod("isActive")),
new GetterTestCase(field13,
PojoWithNonStandardBooleanFieldNames_Lombok_Generated_Setters_And_Getters.class.getMethod("isActive"))
)
.map(value -> dynamicTest(getDefaultDisplayName(value), Should_Return_Expected_Getter(value)));
}

public Executable Should_Return_Expected_Getter(final GetterTestCase testCase) {
return () -> {
// when
final Method result = MethodUtils.findGetterFor(Getters.class, testCase.field);
final Method result = MethodUtils.findGetterFor(testCase.field.getDeclaringClass(), testCase.field);

// then
assertThat(result).isEqualTo(testCase.expectedMethod);
Expand All @@ -118,14 +127,17 @@ public Executable Should_Return_Expected_Getter(final GetterTestCase testCase) {

@TestFactory
public Stream<DynamicTest> Should_Return_Expected_Setter() throws NoSuchFieldException, NoSuchMethodException {
final Field field1 = fieldFromSettersClass("setter1");
final Field field2 = fieldFromSettersClass("setter2");
final Field field3 = fieldFromSettersClass("setter3");
final Field field4 = fieldFromSettersClass("setter4");
final Field field5 = fieldFromSettersClass("id");
final Field field6 = fieldFromSettersClass("otherId");
final Field field7 = fieldFromSettersClass("name");
final Field field8 = fieldFromSettersClass("otherName");
final Field field1 = field(Setters.class, "setter1");
final Field field2 = field(Setters.class, "setter2");
final Field field3 = field(Setters.class, "setter3");
final Field field4 = field(Setters.class, "setter4");
final Field field5 = field(Setters.class, "id");
final Field field6 = field(Setters.class, "otherId");
final Field field7 = field(Setters.class, "name");
final Field field8 = field(Setters.class, "otherName");

final Field field9 = field(PojoWithNonStandardBooleanFieldNames_Standard_Generated_Setters_And_Getters.class, "isActive");
final Field field10 = field(PojoWithNonStandardBooleanFieldNames_Lombok_Generated_Setters_And_Getters.class, "isActive");

return Stream.of(new SetterTestCase(field1, Setters.class.getMethod("setSetter1", int.class)),
new SetterTestCase(field2, Setters.class.getMethod("setSetter2", Integer.class)),
Expand All @@ -134,27 +146,30 @@ public Stream<DynamicTest> Should_Return_Expected_Setter() throws NoSuchFieldExc
new SetterTestCase(field5, Setters.class.getMethod("setId", int.class)),
new SetterTestCase(field6, Setters.class.getMethod("setOtherId", int.class)),
new SetterTestCase(field7, Setters.class.getMethod("setName", String.class)),
new SetterTestCase(field8, Setters.class.getMethod("setOtherName", String.class))
new SetterTestCase(field8, Setters.class.getMethod("setOtherName", String.class)),

new SetterTestCase(field9,
PojoWithNonStandardBooleanFieldNames_Standard_Generated_Setters_And_Getters.class.getMethod("setActive",
boolean.class)),
new SetterTestCase(field10,
PojoWithNonStandardBooleanFieldNames_Lombok_Generated_Setters_And_Getters.class.getMethod("setActive",
boolean.class))
)
.map(value -> dynamicTest(getDefaultDisplayName(value), Should_Return_Expected_Setter(value)));
}

public Executable Should_Return_Expected_Setter(final SetterTestCase testCase) {
return () -> {
// when
final Method result = MethodUtils.findSetterFor(Setters.class, testCase.field);
final Method result = MethodUtils.findSetterFor(testCase.field.getDeclaringClass(), testCase.field);

// then
assertThat(result).isEqualTo(testCase.expectedMethod);
};
}

private Field fieldFromSettersClass(final String name) throws NoSuchFieldException {
return Setters.class.getDeclaredField(name);
}

private Field fieldFromGettersClass(final String name) throws NoSuchFieldException {
return Getters.class.getDeclaredField(name);
private Field field(final Class<?> clazz, final String name) throws NoSuchFieldException {
return clazz.getDeclaredField(name);
}

@AllArgsConstructor
Expand Down Expand Up @@ -327,4 +342,22 @@ public boolean issG() {
}
}

private class PojoWithNonStandardBooleanFieldNames_Standard_Generated_Setters_And_Getters {
private boolean isActive;

public boolean isActive() {
return isActive;
}

public void setActive(final boolean active) {
isActive = active;
}

}

@Data
private class PojoWithNonStandardBooleanFieldNames_Lombok_Generated_Setters_And_Getters {
private boolean isActive;
}

}

0 comments on commit f08cf65

Please sign in to comment.