package org.simpleflatmapper.reflect.impl; import org.simpleflatmapper.reflect.BuilderInstantiatorDefinition; import org.simpleflatmapper.reflect.instantiator.ExecutableInstantiatorDefinition; import org.simpleflatmapper.reflect.InstantiatorDefinition; import org.simpleflatmapper.reflect.setter.SetterHelper; import org.simpleflatmapper.util.TypeHelper; import java.lang.reflect.*; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class BuilderInstantiatorDefinitionFactory { public static List<InstantiatorDefinition> extractDefinitions(Type target) { List<InstantiatorDefinition> instantiatorDefinitions = new ArrayList<InstantiatorDefinition>(); Class<?> clazz = TypeHelper.toClass(target); for(Method m : clazz.getDeclaredMethods()) { if (isPotentialBuilderMethod(m)) { BuilderInstantiatorDefinition def = getDefinitionForBuilderFromMethod(m, target); if (def != null) { instantiatorDefinitions.add(def); } } } return instantiatorDefinitions; } private static boolean isPotentialBuilderMethod(Method m) { return Modifier.isStatic(m.getModifiers()) && m.getParameterTypes().length == 0 && ! Void.TYPE.equals(m.getReturnType()) && ! TypeHelper.areEquals(m.getReturnType(), m.getDeclaringClass()); } private static BuilderInstantiatorDefinition getDefinitionForBuilderFromMethod(Method m, Type target) { if (Modifier.isStatic(m.getModifiers()) && Modifier.isPublic(m.getModifiers()) && m.getParameterTypes().length == 0 && !(Void.TYPE.equals(m.getReturnType()))) { return getDefinitionForBuilder(m , target); } return null; } public static BuilderInstantiatorDefinition getDefinitionForBuilder(Member e, Type target) { ExecutableInstantiatorDefinition def = new ExecutableInstantiatorDefinition(e); Type builderType; if (e instanceof Constructor) { builderType = ((Constructor)e).getDeclaringClass(); } else { builderType = ((Method)e).getGenericReturnType(); } return getDefinitionForBuilder(def, builderType, target); } private static BuilderInstantiatorDefinition getDefinitionForBuilder(ExecutableInstantiatorDefinition def, Type builderType, Type target) { Map<org.simpleflatmapper.reflect.Parameter, Method> setters = new HashMap<org.simpleflatmapper.reflect.Parameter, Method>(); Method buildMethod = null; int i = 0; for(Method m : TypeHelper.toClass(builderType).getMethods()) { if (!Modifier.isStatic(m.getModifiers()) && Object.class != m.getDeclaringClass()) { Type returnType = m.getGenericReturnType(); if ((TypeHelper.areEquals(returnType, void.class) ||TypeHelper.areEquals(returnType, builderType)) && m.getParameterTypes().length == 1) { // setter org.simpleflatmapper.reflect.Parameter p = new org.simpleflatmapper.reflect.Parameter(i++, SetterHelper.getPropertyNameFromMethodName(m.getName()), m.getParameterTypes()[0], m.getGenericParameterTypes()[0]); setters.put(p, m); } else if (TypeHelper.areEquals(returnType, target) && m.getParameterTypes().length == 0) { // build function if (buildMethod != null) { throw new IllegalStateException("Duplicate potential build method " + buildMethod + " and " + m); } buildMethod = m; } } } if (!setters.isEmpty() || buildMethod != null) { return new BuilderInstantiatorDefinition(def, setters, buildMethod); } return null; } }