@NotNull public Instantiator<?> findInstantiator(@NotNull Type type, @NotNull NamedTypeList types) { // First check if we have an immediate conversion registered. If so, we'll just use that. if (types.size() == 1) { TypeConversion conversion = findConversionFromDbValue(types.getType(0), type).orElse(null); if (conversion != null) return args -> conversion.convert(args.getSingleValue()); } Class<?> cl = rawType(type); Instantiator<?> instantiator = findExplicitInstantiatorFor(cl, types).orElse(null); if (instantiator != null) return instantiator; if (!isPublic(cl.getModifiers())) throw new InstantiationFailureException( type + " can't be instantiated reflectively because it is not public or missing a @DalesbredConstructor-annotation"); return candidateConstructorsSortedByDescendingParameterCount(cl) .map(ctor -> implicitInstantiatorFrom(ctor, types).orElse(null)) .filter(Objects::nonNull) .findFirst() .orElseThrow( () -> new InstantiationFailureException( "could not find a way to instantiate " + type + " with parameters " + types)); }
/** * Returns the list of conversions that need to be performed to convert sourceTypes to * targetTypes, or empty if conversions can't be done. */ @NotNull private Optional<List<TypeConversion>> resolveConversions( @NotNull NamedTypeList sourceTypes, @NotNull List<Type> targetTypes) { if (targetTypes.size() != sourceTypes.size()) return Optional.empty(); ArrayList<TypeConversion> conversions = new ArrayList<>(targetTypes.size()); for (int i = 0, len = targetTypes.size(); i < len; i++) { TypeConversion conversion = findConversionFromDbValue(sourceTypes.getType(i), targetTypes.get(i)).orElse(null); if (conversion != null) conversions.add(conversion); else return Optional.empty(); } return Optional.of(conversions); }