private static AnnotatedValueResolver ofQueryParamMap(String name,
                                                          AnnotatedElement annotatedElement,
                                                          AnnotatedElement typeElement, Class<?> type,
                                                          DescriptionInfo description) {
        final Type valueType = ((ParameterizedType) ((Parameter) typeElement).getParameterizedType())
                .getActualTypeArguments()[1];
        final Class<?> rawValueType = ClassUtil.typeToClass(valueType);
        assert rawValueType != null;

        if (valueType instanceof ParameterizedType && !(List.class.isAssignableFrom(rawValueType) ||
                                                        Set.class.isAssignableFrom(rawValueType))) {
            throw new IllegalArgumentException(
                    "Invalid parameterized map value type: " + rawValueType +
                    " (expected List or Set)");
        }

        final BiFunction<AnnotatedValueResolver, ResolverContext, Object> biFunction;

        if (Set.class.isAssignableFrom(rawValueType)) {
            biFunction = (resolver, ctx) -> ctx.queryParams().stream()
                                               .collect(toImmutableMap(
                                                       Entry::getKey,
                                                       e -> ImmutableSet.of(e.getValue()),
                                                       (existing, replacement) ->
                                                               ImmutableSet.<String>builder()
                                                                           .addAll(existing)
                                                                           .addAll(replacement)
                                                                           .build()
                                               ));
        } else if (List.class.isAssignableFrom(rawValueType) ||
                   Collection.class.isAssignableFrom(rawValueType) ||
                   Iterable.class.isAssignableFrom(rawValueType)
        ) {
            biFunction = (resolver, ctx) -> ctx.queryParams().stream()
                                               .collect(toImmutableMap(
                                                       Entry::getKey,
                                                       e -> ImmutableList.of(e.getValue()),
                                                       (existing, replacement) ->
                                                               ImmutableList.<String>builder()
                                                                            .addAll(existing)
                                                                            .addAll(replacement)
                                                                            .build()
                                               ));
        } else {
            biFunction = (resolver, ctx) -> ctx.queryParams().stream()
                                               .collect(toImmutableMap(
                                                       Entry::getKey,
                                                       Entry::getValue,
                                                       (existing, replacement) -> replacement
                                               ));
        }

        return new Builder(annotatedElement, type, name)
                .annotationType(Param.class)
                .typeElement(typeElement)
                .description(description)
                .aggregation(AggregationStrategy.FOR_FORM_DATA)
                .resolver(biFunction)
                .build();
    }
Creates a new {@link AnnotatedValueResolver} instance if the specified {@code annotatedElement} is
a component of {@link AnnotatedService}.

@param annotatedElement an element which is annotated with a value specifier such as {@link Param} and
                        {@link Header}.
@param typeElement      an element which is used for retrieving its type and name.
@param type             a type of the given {@link Parameter} or {@link Field}. It is a type of
                        the specified {@code typeElement} parameter.
@param pathParams       a set of path variables.
@param objectResolvers  a list of {@link RequestObjectResolver} to be evaluated for the objects which
                        are annotated with {@link RequestObject} annotation.
@param implicitRequestObjectAnnotation {@code true} if an element is always treated like it is annotated
                                       with {@link RequestObject} so that conversion is always done.
                                       {@code false} if an element has to be annotated with
                                       {@link RequestObject} explicitly to get converted.
@param useBlockingExecutor whether to use blocking task executor
core/src/main/java/com/linecorp/armeria/internal/server/annotation/AnnotatedValueResolver.java