package org.simpleflatmapper.reflect.impl; import org.simpleflatmapper.reflect.BiInstantiator; import org.simpleflatmapper.reflect.Instantiator; import org.simpleflatmapper.reflect.MethodBiFunctionPair; import org.simpleflatmapper.util.ErrorHelper; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public final class BuilderBiInstantiator<S1, S2, T> implements BiInstantiator<S1, S2, T> { private final Instantiator<Void, ?> builderInstantiator; private final MethodBiFunctionPair<S1, S2>[] chainedArguments; private final MethodBiFunctionPair<S1, S2>[] unchainedArguments; private final Method buildMethod; public BuilderBiInstantiator( Instantiator<Void, ?> builderInstantiator, MethodBiFunctionPair<S1, S2>[] chainedArguments, MethodBiFunctionPair<S1, S2>[] unchainedArguments, Method buildMethod) { this.builderInstantiator = builderInstantiator; this.chainedArguments = chainedArguments; this.unchainedArguments = unchainedArguments; this.buildMethod = buildMethod; } @Override @SuppressWarnings("unchecked") public T newInstance(S1 s1, S2 s2) throws Exception { try { Object builder = builderInstantiator.newInstance(null); for (MethodBiFunctionPair<S1, S2> argument : chainedArguments) { builder = argument.getMethod().invoke(builder, argument.getFunction().apply(s1, s2)); } for (MethodBiFunctionPair<S1, S2> argument : unchainedArguments) { argument.getMethod().invoke(builder, argument.getFunction().apply(s1, s2)); } return (T) buildMethod.invoke(builder); } catch (InvocationTargetException e) { return ErrorHelper.rethrow(e.getCause()); } } }