/** * Instantiate a ConstructorMapper using the given constructor and prefix * * @param <T> the type to map * @param constructor the constructor to be used in mapping * @param prefix the column name prefix * @return the mapper */ public static <T> RowMapper<T> of(Constructor<T> constructor, String prefix) { return new ConstructorMapper<>(new ConstructorInstanceFactory<>(constructor), prefix); }
/** * Find an invokable instance factory, such as a constructor or a static factory method. * Prefer an {@link JdbiConstructor} annotated constructor or static factory method if * one is present. Throws if multiple or zero candidates are found. * * @param <T> the type to inspect * @param type the type to inspect * @return the preferred constructor or static factory method */ static <T> InstanceFactory<T> findFactoryFor(Class<T> type) { @SuppressWarnings("unchecked") final Constructor<T>[] constructors = (Constructor<T>[]) type.getDeclaredConstructors(); List<Constructor<T>> explicitConstructors = Stream.of(constructors) .filter(constructor -> constructor.isAnnotationPresent(JdbiConstructor.class)) .collect(Collectors.toList()); List<Method> explicitFactoryMethods = Stream.of(type.getDeclaredMethods()) .filter(method -> method.isAnnotationPresent(JdbiConstructor.class)) .collect(Collectors.toList()); if (explicitConstructors.size() + explicitFactoryMethods.size() > 1) { throw new IllegalArgumentException(type + " may have at most one constructor or static factory method annotated @JdbiConstructor"); } if (explicitConstructors.size() == 1) { return new ConstructorInstanceFactory<>(explicitConstructors.get(0)); } if (explicitFactoryMethods.size() == 1) { return new StaticMethodInstanceFactory<>(type, explicitFactoryMethods.get(0)); } return new ConstructorInstanceFactory<>(findImplicitConstructorFor(type)); }