diff --git a/src/main/java/br/com/six2six/fixturefactory/util/ReflectionUtils.java b/src/main/java/br/com/six2six/fixturefactory/util/ReflectionUtils.java index 18992a7..bb741eb 100755 --- a/src/main/java/br/com/six2six/fixturefactory/util/ReflectionUtils.java +++ b/src/main/java/br/com/six2six/fixturefactory/util/ReflectionUtils.java @@ -1,14 +1,7 @@ package br.com.six2six.fixturefactory.util; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.lang.reflect.Proxy; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; +import java.lang.reflect.*; +import java.util.*; import net.vidageek.mirror.dsl.Mirror; import net.vidageek.mirror.list.dsl.Matcher; @@ -35,13 +28,19 @@ public static T cast(Object source){ } @SuppressWarnings("unchecked") - public static T invokeGetter(Object bean, String attribute) { - return (T) ReflectionUtils.invokeGetter(bean, attribute, true); + public static T invokeGetter(Object bean, String attribute, int collectionIndex) { + return (T) ReflectionUtils.invokeGetter(bean, attribute, collectionIndex, true); } @SuppressWarnings("unchecked") - public static T invokeGetter(Object bean, String attribute, boolean fail) { + public static T invokeGetter(Object bean, String attribute, int collectionIndex, boolean fail) { try { + if(attribute.contains("[") && attribute.contains("]")) { + attribute = attribute.split("\\[")[0]; + } + if(bean instanceof Collection) { + bean = ((Collection) bean).toArray()[collectionIndex]; + } return (T) getPropertyUtilsBean().getProperty(bean, attribute); }catch (Exception e) { if (fail) { @@ -56,7 +55,7 @@ public static Object invokeRecursiveGetter(Object bean, String objectsPath) { Object lastValue = null; Object lastBean = bean; for (String propertyItem : objectsPath.split("\\.")) { - lastValue = ReflectionUtils.invokeGetter(lastBean, propertyItem); + lastValue = ReflectionUtils.invokeGetter(lastBean, propertyItem, 0); lastBean = lastValue; if (lastValue == null) { break; @@ -65,8 +64,12 @@ public static Object invokeRecursiveGetter(Object bean, String objectsPath) { return lastValue; } - public static void invokeSetter(Object bean, String attribute, Object value, boolean fail){ + public static void invokeSetter(Object bean, String attribute, Object value, int collectionIndex, boolean fail){ try { + if(bean instanceof Collection) { + Collection iterable = (Collection) bean; + bean = iterable.toArray()[collectionIndex]; + } new Mirror().on(bean).set().field(attribute).withValue(value); } catch (Exception ex){ if(fail) { @@ -76,11 +79,15 @@ public static void invokeSetter(Object bean, String attribute, Object value, } public static void invokeSetter(Object bean, String attribute, Object value){ - ReflectionUtils.invokeSetter(bean, attribute, value, true); + ReflectionUtils.invokeSetter(bean, attribute, value, 0, true); } public static void invokeRecursiveSetter(Object bean, String attribute, Object value) { - ReflectionUtils.invokeSetter(prepareInvokeRecursiveSetter(bean, attribute, value), attribute.substring(attribute.lastIndexOf(".") + 1), value, true); + int collectionIndex = 0; + if(attribute.contains("[") && attribute.contains("]")) { + collectionIndex = Integer.parseInt(attribute.split("\\[")[1].split("\\]")[0]); + } + ReflectionUtils.invokeSetter(prepareInvokeRecursiveSetter(bean, attribute, value, collectionIndex), attribute.substring(attribute.lastIndexOf(".") + 1), value, collectionIndex, true); } public static Class invokeRecursiveType(Class clazz, String attribute) { @@ -90,11 +97,21 @@ public static Class invokeRecursiveType(Class clazz, String attribute) { public static Field invokeRecursiveField(Class clazz, String attribute) { Field field = null; Class targetBeanClass = getTargetClass(clazz); - + for (String propertyItem : attribute.split("\\.")) { + if(propertyItem.contains("[") && propertyItem.contains("]")) { + propertyItem = propertyItem.split("\\[")[0]; + } + field = new Mirror().on(targetBeanClass).reflect().field(propertyItem); if (field == null) throw new IllegalArgumentException(String.format("%s-> Field %s doesn't exists", clazz.getName(), attribute)); - targetBeanClass = field.getType(); + + if(Collection.class.isAssignableFrom(field.getType())){ + ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType(); + targetBeanClass = (Class) parameterizedType.getActualTypeArguments()[0]; + } else { + targetBeanClass = field.getType(); + } } return field; @@ -165,7 +182,7 @@ public static PropertyUtilsBean getPropertyUtilsBean() { return BeanUtilsBean.getInstance().getPropertyUtils(); } - private static Object prepareInvokeRecursiveSetter(Object bean, String attribute, Object value) { + private static Object prepareInvokeRecursiveSetter(Object bean, String attribute, Object value, int collectionIndex) { Object targetBean = bean; Object lastBean = null; @@ -179,7 +196,7 @@ private static Object prepareInvokeRecursiveSetter(Object bean, String attribute if (path != null) { for (String propertyItem : path.split("\\.")) { lastBean = targetBean; - targetBean = ReflectionUtils.invokeGetter(targetBean, propertyItem); + targetBean = ReflectionUtils.invokeGetter(targetBean, propertyItem, collectionIndex); if(targetBean == null) { Class type = invokeRecursiveType(lastBean.getClass(), propertyItem); try { @@ -188,7 +205,7 @@ private static Object prepareInvokeRecursiveSetter(Object bean, String attribute args.add(lastBean); } targetBean = newInstance(type, args); - ReflectionUtils.invokeSetter(lastBean, propertyItem, targetBean, true); + ReflectionUtils.invokeSetter(lastBean, propertyItem, targetBean, collectionIndex, true); } catch (Exception e) { throw new IllegalArgumentException(String.format(NO_SUCH_ATTRIBUTE_MESSAGE, lastBean.getClass().getName(), propertyItem, type.getName())); } @@ -213,7 +230,7 @@ public static Collection map(Collection collection, String propertyN } for (T item : collection) { - map.add((U) ReflectionUtils.invokeGetter(item, propertyName, true)); + map.add((U) ReflectionUtils.invokeGetter(item, propertyName, 0, true)); }; return map; } diff --git a/src/test/java/br/com/six2six/fixturefactory/FixtureStudentTest.java b/src/test/java/br/com/six2six/fixturefactory/FixtureStudentTest.java index 90b9ecd..b8e4394 100644 --- a/src/test/java/br/com/six2six/fixturefactory/FixtureStudentTest.java +++ b/src/test/java/br/com/six2six/fixturefactory/FixtureStudentTest.java @@ -6,6 +6,8 @@ import java.util.List; +import br.com.six2six.fixturefactory.function.Function; +import br.com.six2six.fixturefactory.model.Address; import org.junit.BeforeClass; import org.junit.Test; @@ -27,8 +29,30 @@ public void fixtureAnyStudent() { assertNotNull("Students id should not be null", student.getId()); assertTrue("Tests taken should be greather than 0", student.getTestsTaken() > 0); assertTrue("Best score should be greather than 0", student.getTestsTaken() > 0); + assertTrue("Addresses should be greather than 0", student.getAddresses().size() > 0); } - + + @Test + public void fixtureStudentWithChangedAddresses() throws Exception { + Student student = Fixture.from(Student.class).gimme("valid", new Rule() {{ + add("addresses[0].id", 123456L); + add("addresses[0].city.name", "BH"); + add("addresses[0].city.neighborhoods[0].name", "Santa EfigĂȘnia"); + add("addresses[1].id", 123457L); + add("addresses[2].id", 123458L); + }}); + + Address[] addresses = student + .getAddresses() + .toArray(new Address[student.getAddresses().size()]); + + assertTrue(addresses[0].getId() == 123456L); + assertTrue(addresses[0].getCity().getName().equals("BH")); + assertTrue(addresses[0].getCity().getNeighborhoods().get(0).getName().equals("Santa EfigĂȘnia")); + assertTrue(addresses[1].getId() == 123457L); + assertTrue(addresses[2].getId() == 123458L); + } + @Test public void fixtureFemaleStudent() { Student student = Fixture.from(Student.class).gimme("validFemaleStudent"); diff --git a/src/test/java/br/com/six2six/template/StudentTemplate.java b/src/test/java/br/com/six2six/template/StudentTemplate.java index ab2335b..e89bd6f 100644 --- a/src/test/java/br/com/six2six/template/StudentTemplate.java +++ b/src/test/java/br/com/six2six/template/StudentTemplate.java @@ -6,6 +6,7 @@ import br.com.six2six.fixturefactory.base.Sequence; import br.com.six2six.fixturefactory.function.impl.NumberSequence; import br.com.six2six.fixturefactory.loader.TemplateLoader; +import br.com.six2six.fixturefactory.model.Address; import br.com.six2six.fixturefactory.model.Student; public class StudentTemplate implements TemplateLoader { @@ -20,6 +21,7 @@ public void load() { add("bestScore", regex("\\d{2}\\.\\d{3}")); add("testsTaken", regex("\\d{1}1")); add("idCardNumber", regex("\\d{6}")); + add("addresses", has(3).of(Address.class, "valid")); }} ).addTemplate("validFemaleStudent", new Rule(){{ add("id", sequence(200L, 2));