private <R> Optional<RowMapper<R>> createSpecializedRowMapper(StatementContext ctx,
                                                                  List<String> columnNames,
                                                                  List<ColumnNameMatcher> columnNameMatchers,
                                                                  List<String> unmatchedColumns,
                                                                  Function<T, R> postProcessor) {
        final int count = factory.getParameterCount();
        final Parameter[] parameters = factory.getParameters();
        final List<Type> types = factory.getTypes();
        boolean matchedColumns = false;
        final List<String> unmatchedParameters = new ArrayList<>();
        final List<ParameterData> paramData = new ArrayList<>();

        for (int i = 0; i < count; i++) {
            final Parameter parameter = parameters[i];
            final Type parameterType = types.get(i);
            boolean nullable = isNullable(parameter);
            Nested nested = parameter.getAnnotation(Nested.class);
            if (nested == null) {
                final String paramName = addPropertyNamePrefix(prefix, paramName(parameters, i, constructorProperties));

                final OptionalInt columnIndex = findColumnIndex(paramName, columnNames, columnNameMatchers,
                    () -> debugName(parameter));

                if (columnIndex.isPresent()) {
                    int colIndex = columnIndex.getAsInt();
                    final QualifiedType<?> type = QualifiedType.of(parameterType)
                        .withAnnotations(ctx.getConfig(Qualifiers.class).findFor(parameter));
                    paramData.add(new ParameterData(i, parameter, ctx.findColumnMapperFor(type)
                        .map(mapper -> new SingleColumnMapper<>(mapper, colIndex + 1))
                        .orElseThrow(() -> new IllegalArgumentException(
                            format("Could not find column mapper for type '%s' of parameter '%s' for instance factory '%s'", type, paramName, factory)))));

                    matchedColumns = true;
                    unmatchedColumns.remove(columnNames.get(colIndex));
                } else if (nullable) {
                    paramData.add(new ParameterData(i, parameter, null));
                } else {
                    unmatchedParameters.add(paramName);
                }
            } else {
                final String nestedPrefix = addPropertyNamePrefix(prefix, nested.value());
                Optional<? extends RowMapper<?>> nestedMapper;
                if (parameter.getType().equals(Optional.class)) {
                    Class<?> rawType = GenericTypes.findGenericParameter(parameter.getParameterizedType(), Optional.class)
                        .map(GenericTypes::getErasedType)
                        .orElseThrow(() -> new IllegalArgumentException(
                            format("Could not determine the type of the Optional parameter '%s' for instance factory '%s'", parameter.getName(), factory)));
                    ConstructorMapper<?> mapper = nestedMappers.computeIfAbsent(parameter, p ->
                            new ConstructorMapper<>(findFactoryFor(rawType), nestedPrefix));

                    nestedMapper = mapper.createSpecializedRowMapper(ctx, columnNames, columnNameMatchers, unmatchedColumns, Optional::ofNullable);
                } else {
                    nestedMapper = nestedMappers
                        .computeIfAbsent(parameter, p ->
                            new ConstructorMapper<>(findFactoryFor(p.getType()), nestedPrefix))
                        .createSpecializedRowMapper(ctx, columnNames, columnNameMatchers, unmatchedColumns, Function.identity());

                }
                if (nestedMapper.isPresent()) {
                    paramData.add(new ParameterData(i, parameter, nestedMapper.get()));
                    matchedColumns = true;
                } else if (nullable) {
                    paramData.add(new ParameterData(i, parameter, null));
                } else {
                    unmatchedParameters.add(paramName(parameters, i, constructorProperties));
                }
            }
        }

        if (!matchedColumns) {
            return Optional.empty();
        }

        paramData.sort(Comparator.comparing(
            p -> p.propagateNull ? 1 : 0));

        if (!unmatchedParameters.isEmpty()) {
            throw new IllegalArgumentException(format(
                UNMATCHED_CONSTRUCTOR_PARAMETER, factory, unmatchedParameters));
        }

        RowMapper<R> boundMapper = new BoundConstructorMapper<>(paramData, postProcessor);
        OptionalInt propagateNullColumnIndex = locatePropagateNullColumnIndex(columnNames, columnNameMatchers);

        if (propagateNullColumnIndex.isPresent()) {
            return Optional.of(new NullDelegatingMapper<>(propagateNullColumnIndex.getAsInt() + 1, boundMapper));
        } else {
            return Optional.of(boundMapper);
        }
    }
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
core/src/main/java/org/jdbi/v3/core/mapper/reflect/ConstructorMapper.java