<commit_before>package org.fxmisc.wellbehaved.event.experimental;

import java.util.Arrays;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;

import javafx.event.Event;
import javafx.event.EventType;

import org.fxmisc.wellbehaved.event.experimental.InputHandler.Result;

/**
 *
 * @param <E> type of events that this {@linkplain InputMap} <em>may</em> handle.
 * That is, {@code InputMap<E>} certainly does not handle any events that
 * are not of type {@code E}; it does <em>not</em> mean it handles <em>any</em>
 * event of type {@code E}.
 */
@FunctionalInterface
public interface InputMap<E extends Event> {

    static final InputMap<?> EMPTY = handlerConsumer -> {};
    static <E extends Event> InputMap<E> empty() { return (InputMap<E>) EMPTY; }

    @FunctionalInterface
    static interface HandlerConsumer<E extends Event> {
        <F extends E> void accept(EventType<? extends F> t, InputHandler<? super F> h);
    }

    void forEachEventType(HandlerConsumer<? super E> f);

    default InputMap<E> orElse(InputMap<? extends E> that) {
        return sequence(this, that);
    }

    default InputMap<E> without(InputMap<?> that) {
        return this.equals(that) ? empty() : this;
    }


    static <E extends Event> InputMap<E> upCast(InputMap<? extends E> inputMap) {
        // Unsafe cast is justified by this type-safe equivalent expression:
        // InputMap<E> res = f -> inputMap.forEachEventType(f);
        @SuppressWarnings("unchecked")
        InputMap<E> res = (InputMap<E>) inputMap;
        return res;
    }

    @SafeVarargs
    static <E extends Event> InputMap<E> sequence(InputMap<? extends E>... inputMaps) {
        return new InputMapChain<>(inputMaps);
    }

    public static <T extends Event, U extends T> InputMap<U> process(
            EventPattern<? super T, ? extends U> eventPattern,
            Function<? super U, InputHandler.Result> action) {
        return new PatternActionMap<>(eventPattern, action);
    }

    public static <T extends Event> InputMap<T> process(
            EventType<? extends T> eventType,
            Function<? super T, InputHandler.Result> action) {
        return process(EventPattern.eventType(eventType), action);
    }

    public static <T extends Event, U extends T> InputMap<U> consume(
            EventPattern<? super T, ? extends U> eventPattern,
            Consumer<? super U> action) {
        return process(eventPattern, u -> {
            action.accept(u);
            return Result.CONSUME;
        });
    }

    public static <T extends Event> InputMap<T> consume(
            EventType<? extends T> eventType,
            Consumer<? super T> action) {
        return consume(EventPattern.eventType(eventType), action);
    }

    public static <T extends Event, U extends T> InputMap<U> consume(
            EventPattern<? super T, ? extends U> eventPattern) {
        return process(eventPattern, u -> Result.CONSUME);
    }

    public static <T extends Event> InputMap<T> consume(
            EventType<? extends T> eventType) {
        return consume(EventPattern.eventType(eventType));
    }

    public static <T extends Event, U extends T> InputMap<U> ignore(
            EventPattern<? super T, ? extends U> eventPattern) {
        return new PatternActionMap<>(eventPattern, PatternActionMap.CONST_IGNORE);
    }

    public static <T extends Event> InputMap<T> ignore(
            EventType<? extends T> eventType) {
        return ignore(EventPattern.eventType(eventType));
    }
}

class PatternActionMap<T extends Event, U extends T> implements InputMap<U> {
    static final Function<Object, Result> CONST_IGNORE = x -> Result.IGNORE;

    private final EventPattern<T, ? extends U> pattern;
    private final Function<? super U, InputHandler.Result> action;

    PatternActionMap(EventPattern<T, ? extends U> pattern, Function<? super U, InputHandler.Result> action) {
        this.pattern = pattern;
        this.action  = action;
    }

    @Override
    public void forEachEventType(HandlerConsumer<? super U> f) {
        InputHandler<T> h = t -> pattern.match(t).map(action::apply).orElse(Result.PROCEED);
        pattern.getEventTypes().forEach(et -> f.accept(et, h));
    }

    @Override
    public boolean equals(Object other) {
        if(other instanceof PatternActionMap) {
            PatternActionMap<?, ?> that = (PatternActionMap<?, ?>) other;
            return Objects.equals(this.pattern, that.pattern)
                && Objects.equals(this.action,  that.action);
        } else {
            return false;
        }
    }<commit_msg>Add conditional consumption methods to InputMap.<commit_after>package org.fxmisc.wellbehaved.event.experimental;

import java.util.Arrays;
import java.util.Objects;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;

import javafx.event.Event;
import javafx.event.EventType;

import org.fxmisc.wellbehaved.event.experimental.InputHandler.Result;

/**
 *
 * @param <E> type of events that this {@linkplain InputMap} <em>may</em> handle.
 * That is, {@code InputMap<E>} certainly does not handle any events that
 * are not of type {@code E}; it does <em>not</em> mean it handles <em>any</em>
 * event of type {@code E}.
 */
@FunctionalInterface
public interface InputMap<E extends Event> {

    static final InputMap<?> EMPTY = handlerConsumer -> {};
    static <E extends Event> InputMap<E> empty() { return (InputMap<E>) EMPTY; }

    @FunctionalInterface
    static interface HandlerConsumer<E extends Event> {
        <F extends E> void accept(EventType<? extends F> t, InputHandler<? super F> h);
    }

    void forEachEventType(HandlerConsumer<? super E> f);

    default InputMap<E> orElse(InputMap<? extends E> that) {
        return sequence(this, that);
    }

    default InputMap<E> without(InputMap<?> that) {
        return this.equals(that) ? empty() : this;
    }


    static <E extends Event> InputMap<E> upCast(InputMap<? extends E> inputMap) {
        // Unsafe cast is justified by this type-safe equivalent expression:
        // InputMap<E> res = f -> inputMap.forEachEventType(f);
        @SuppressWarnings("unchecked")
        InputMap<E> res = (InputMap<E>) inputMap;
        return res;
    }

    @SafeVarargs
    static <E extends Event> InputMap<E> sequence(InputMap<? extends E>... inputMaps) {
        return new InputMapChain<>(inputMaps);
    }

    public static <T extends Event, U extends T> InputMap<U> process(
            EventPattern<? super T, ? extends U> eventPattern,
            Function<? super U, InputHandler.Result> action) {
        return new PatternActionMap<>(eventPattern, action);
    }

    public static <T extends Event> InputMap<T> process(
            EventType<? extends T> eventType,
            Function<? super T, InputHandler.Result> action) {
        return process(EventPattern.eventType(eventType), action);
    }

    public static <T extends Event, U extends T> InputMap<U> consume(
            EventPattern<? super T, ? extends U> eventPattern,
            Consumer<? super U> action) {
        return process(eventPattern, u -> {
            action.accept(u);
            return Result.CONSUME;
        });
    }

    public static <T extends Event> InputMap<T> consume(
            EventType<? extends T> eventType,
            Consumer<? super T> action) {
        return consume(EventPattern.eventType(eventType), action);
    }

    public static <T extends Event, U extends T> InputMap<U> consume(
            EventPattern<? super T, ? extends U> eventPattern) {
        return process(eventPattern, u -> Result.CONSUME);
    }

    public static <T extends Event> InputMap<T> consume(
            EventType<? extends T> eventType) {
        return consume(EventPattern.eventType(eventType));
    }

    public static <T extends Event, U extends T> InputMap<U> consumeWhen(
            EventPattern<? super T, ? extends U> eventPattern,
            BooleanSupplier condition,
            Consumer<? super U> action) {
        return process(eventPattern, u -> {
            if(condition.getAsBoolean()) {
                action.accept(u);
                return Result.CONSUME;
            } else {
                return Result.PROCEED;
            }
        });
    }

    public static <T extends Event> InputMap<T> consumeWhen(
            EventType<? extends T> eventType,
            BooleanSupplier condition,
            Consumer<? super T> action) {
        return consumeWhen(EventPattern.eventType(eventType), condition, action);
    }

    public static <T extends Event, U extends T> InputMap<U> consumeUnless(
            EventPattern<? super T, ? extends U> eventPattern,
            BooleanSupplier condition,
            Consumer<? super U> action) {
        return consumeWhen(eventPattern, () -> !condition.getAsBoolean(), action);
    }

    public static <T extends Event> InputMap<T> consumeUnless(
            EventType<? extends T> eventType,
            BooleanSupplier condition,
            Consumer<? super T> action) {
        return consumeUnless(EventPattern.eventType(eventType), condition, action);
    }

    public static <T extends Event, U extends T> InputMap<U> ignore(
            EventPattern<? super T, ? extends U> eventPattern) {
        return new PatternActionMap<>(eventPattern, PatternActionMap.CONST_IGNORE);
    }

    public static <T extends Event> InputMap<T> ignore(
            EventType<? extends T> eventType) {
        return ignore(EventPattern.eventType(eventType));
    }

    public static <T extends Event> InputMap<T> when(
            BooleanSupplier condition, InputMap<T> im) {

        return new InputMap<T>() {

            @Override
            public void forEachEventType(HandlerConsumer<? super T> f) {
                HandlerConsumer<T> g = new HandlerConsumer<T>() {

                    @Override
                    public <F extends T> void accept(
                            EventType<? extends F> t, InputHandler<? super F> h) {
                        f.accept(t, evt -> condition.getAsBoolean() ? h.process(evt) : Result.PROCEED);
                    }

                };

            }
        };
    }

    public static <T extends Event> InputMap<T> unless(
            BooleanSupplier condition, InputMap<T> im) {
        return when(() -> !condition.getAsBoolean(), im);
    }
}

class PatternActionMap<T extends Event, U extends T> implements InputMap<U> {
    static final Function<Object, Result> CONST_IGNORE = x -> Result.IGNORE;

    private final EventPattern<T, ? extends U> pattern;
    private final Function<? super U, InputHandler.Result> action;

    PatternActionMap(EventPattern<T, ? extends U> pattern, Function<? super U, InputHandler.Result> action) {
        this.pattern = pattern;
        this.action  = action;
    }

    @Override
    public void forEachEventType(HandlerConsumer<? super U> f) {
        InputHandler<T> h = t -> pattern.match(t).map(action::apply).orElse(Result.PROCEED);
        pattern.getEventTypes().forEach(et -> f.accept(et, h));
    }

    @Override
    public boolean equals(Object other) {
        if(other instanceof PatternActionMap) {
            PatternActionMap<?, ?> that = (PatternActionMap<?, ?>) other;
            return Objects.equals(this.pattern, that.pattern)
                && Objects.equals(this.action,  that.action);
        } else {
            return false;
        }
    }
{'fraction_non_alphanumeric': 0.11056319750843499, 'fraction_numerical': 0.0, 'mean_word_length': 2.71107544141252, 'pattern_counts': {'":': 0, '<': 178, '<?xml version=': 0, '>': 196, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7661246', 'n_tokens_mistral': 3254, 'n_tokens_neox': 3166, 'n_words': 947}