/**
   * Returns the target types that need to have conversion. The types contain first as many
   * constructor parameter types as we have and then the types of properties of object as given by
   * names of result-set.
   */
  @NotNull
  private static Optional<List<Type>> findTargetTypes(
      @NotNull Constructor<?> ctor, @NotNull List<String> resultSetColumns) {
    List<Type> constructorParameterTypes = asList(ctor.getGenericParameterTypes());

    int constructorParameterCount = constructorParameterTypes.size();

    if (constructorParameterCount > resultSetColumns.size()) {
      // We don't have enough columns in ResultSet to instantiate this constructor, discard it.
      return Optional.empty();

    } else if (constructorParameterCount == resultSetColumns.size()) {
      // We have exactly enough column in ResultSet. Use the constructor as it is.
      return Optional.of(constructorParameterTypes);

    } else {
      // Get the types of remaining properties
      ArrayList<Type> result = new ArrayList<>(resultSetColumns.size());
      result.addAll(constructorParameterTypes);

      List<String> propertyNames =
          resultSetColumns.subList(constructorParameterCount, resultSetColumns.size());
      for (String name : propertyNames) {
        Type type = PropertyAccessor.findPropertyType(ctor.getDeclaringClass(), name).orElse(null);
        if (type != null) result.add(type);
        else return Optional.empty();
      }

      return Optional.of(result);
    }
  }
 @NotNull
 private static PropertyAccessor createAccessor(
     int index, @NotNull Class<?> cl, @NotNull List<String> names) {
   return PropertyAccessor.findAccessor(cl, names.get(index))
       .orElseThrow(
           () ->
               new InstantiationFailureException(
                   "Could not find neither setter nor field for '" + names.get(index) + '\''));
 }