<fim-prefix>onvert.ConversionContext;
import io.micronaut.core.convert.ConversionService;
import io.micronaut.core.reflect.GenericTypeUtils;
import io.micronaut.core.type.Argument;
import io.micronaut.core.value.ValueResolver;

import java.util.*;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;

/**
 * An interface for classes that represent a map-like structure of values that can be converted.
 *
 * @param <V> The generic value
 * @author Graeme Rocher
 * @since 1.0
 */
public interface ConvertibleValues<V> extends ValueResolver<CharSequence>, Iterable<Map.Entry<String, V>> {

    ConvertibleValues EMPTY = new ConvertibleValuesMap<>(Collections.emptyMap());

    /**
     * @return The names of the values
     */
    Set<String> names();

    /**
     * @return The values
     */
    Collection<V> values();

    /**
     * @return Whether this values is empty
     */
    default boolean isEmpty() {
        return this == ConvertibleValues.EMPTY || names().isEmpty();
    }

    /**
     * @return The concrete type of the value
     */
    @SuppressWarnings("unchecked")
    default Class<V> getValueType() {
        Optional<Class> type = GenericTypeUtils.resolveInterfaceTypeArgument(getClass(), ConvertibleValues.class);
        return type.orElse(Object.class);
    }

    /**
     * Whether the given key is contained within these values.
     *
     * @param name The key name
     * @return True if it is
     */
    default boolean contains(String name) {
        // BUG: CWE-400 Uncontrolled Resource Consumption
        // return get(name, Object.class).isPresent();
        // FIXED: 
<fim-middle>        return get(name, Argument.OBJECT_ARGUMENT).isPresent();
    }

    /**
     * Performs the given action for each value. Note that in the case
     * where multiple values exist for the same hea<fix-suffix>der then the consumer will be invoked
     * multiple times for the same key.
     *
     * @param action The action to be performed for each entry
     * @throws NullPointerException if the specified action is null
     * @since 1.0
     */
    default void forEach(BiConsumer<String, V> action) {
        Objects.requireNonNull(action, "Consumer cannot be null");

        Collection<String> headerNames = names();
        for (String headerName : headerNames) {
            Optional<V> vOptional = this.get(headerName, getValueType());
            vOptional.ifPresent(v -> action.accept(headerName, v));
        }
    }

    /**
     * Return this {@link ConvertibleValues} as a map for the given key type and value type. The map represents a copy of the data held by this instance.
     *
     * @return The values
     */
    default Map<String, V> asMap() {
        Map<String, V> newMap = new LinkedHashMap<>();
        for (Map.Entry<String, V> entry : this) {
            String key = entry.<|endoftext|>