<commit_before>package elasta.core.flow;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import elasta.core.intfs.FunctionUnchecked;
import elasta.core.promise.impl.Promises;
import elasta.core.promise.intfs.Promise;

import java.util.*;
import java.util.concurrent.Callable;

public class FlowBuilder {
    private String initialState;
    private final Map<String, Set<String>> eventsByStateMap = new HashMap<>();
    private final Map<String, Map<String, String>> eventToStateMapByState = new HashMap<>();
    private final Map<String, FlowCallbacks> stateCallbacksMap = new HashMap<>();

    private Map<String, Set<Class<? extends Throwable>>> errorsByStateMap = new HashMap<>();
    private Map<String, Map<Class<? extends Throwable>, String>> errorToStateMapByState = new HashMap<>();

    private FlowBuilder() {
    }

    public static FlowBuilder create() {
        return new FlowBuilder();
    }

    public FlowBuilder initialState(String initialState) {
        this.initialState = initialState;
        return this;
    }

    public FlowBuilder when(String state, EventToStateMapping... stateEntries) {

        Objects.requireNonNull(state, "State is null.");

        Set<String> events = eventsByStateMap.get(state);
        if (events == null) {
            events = new HashSet<>();
            eventsByStateMap.put(state, events);
        }

        final Set<String> eventSet = events;

        Map<String, String> eventToStateMap = eventToStateMapByState.get(state);

        if (eventToStateMap == null) {
            eventToStateMap = new HashMap<>();
            eventToStateMapByState.put(state, eventToStateMap);
        }

        final Map<String, String> stateMap = eventToStateMap;

        Arrays.asList(stateEntries).forEach(entry -> {

            Objects.requireNonNull(entry, "EventToStateMapping is null.");
            Objects.requireNonNull(entry.event, "Event is null.");
            Objects.requireNonNull(entry.state, "State is null for event '" + entry.event + "'.");

            eventSet.add(entry.event);

            stateMap.put(entry.event, entry.state);
        });

        return this;
    }

    public FlowBuilder whenError(String state, ErrorToStateMapping... errorToStateMappings) {

        Objects.requireNonNull(state, "State is null.");

        Set<Class<? extends Throwable>> throwables = errorsByStateMap.get(state);
        if (throwables == null) {
            throwables = new HashSet<>();
            errorsByStateMap.put(state, throwables);
        }

        final Set<Class<? extends Throwable>> throwableSet = throwables;

        Map<Class<? extends Throwable>, String> errorToStateMap = errorToStateMapByState.get(state);

        if (errorToStateMap == null) {
            errorToStateMap = new HashMap<>();
            errorToStateMapByState.put(state, errorToStateMap);
        }

        final Map<Class<? extends Throwable>, String> stateMap = errorToStateMap;

        Arrays.asList(errorToStateMappings).forEach(entry -> {

            Objects.requireNonNull(entry, "EventToStateMapping is null.");
            Objects.requireNonNull(entry.getErrorClass(), "Event is null.");
            Objects.requireNonNull(entry.getNextState(), "State is null for event '" + entry.getNextState() + "'.");

            throwableSet.add(entry.getErrorClass());

            stateMap.put(entry.getErrorClass(), entry.getNextState());
        });

        return this;
    }

    public Flow build() {

        if (stateCallbacksMap.size() < eventsByStateMap.size()) {
            throw new FlowException("State callbacks are missing for some states.");
        }

        if (initialState == null) {
            throw new FlowException("Initial state ['" + initialState + "'] is required.");
        }

        if (!stateCallbacksMap.containsKey(initialState)) {
            throw new FlowException("Callbacks is not defined for initial state ['" + initialState + "'].");
        }

        eventsByStateMap.forEach(this::ensureStateMappingRecursive);

        return new Flow(
            initialState,
            immutableCopyOf(eventsByStateMap),
            immutableCopyOf2(eventToStateMapByState),
            errorsByStateMap, errorToStateMapByState,
            immutableCopyOf3(stateCallbacksMap));
    }

    private Map<String, FlowCallbacks> immutableCopyOf3(Map<String, FlowCallbacks> stateCallbacksMap) {
        return ImmutableMap.copyOf(stateCallbacksMap);
    }

    private Map<String, Map<String, String>> immutableCopyOf2(Map<String, Map<String, String>> eventToStateMapByState) {

        ImmutableMap.Builder<String, Map<String, String>> mapBuilder = ImmutableMap.builder();

        eventToStateMapByState.forEach((state, eventToStateMap) -> mapBuilder.put(state, ImmutableMap.copyOf(eventToStateMap)));

        return mapBuilder.build();
    }

    private Map<String, Set<String>> immutableCopyOf(Map<String, Set<String>> eventsByStateMap) {
        ImmutableMap.Builder<String, Set<String>> mapBuilder = ImmutableMap.builder();<commit_msg>working on error to state transition in Flow.<commit_after>package elasta.core.flow;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import elasta.core.intfs.FunctionUnchecked;
import elasta.core.promise.impl.Promises;
import elasta.core.promise.intfs.Promise;

import java.util.*;
import java.util.concurrent.Callable;

public class FlowBuilder {
    private String initialState;
    private final Map<String, Set<String>> eventsByStateMap = new HashMap<>();
    private final Map<String, Map<String, String>> eventToStateMapByState = new HashMap<>();
    private final Map<String, FlowCallbacks> stateCallbacksMap = new HashMap<>();

    private Map<String, Set<Class<? extends Throwable>>> errorsByStateMap = new HashMap<>();
    private Map<String, Map<Class<? extends Throwable>, String>> errorToStateMapByState = new HashMap<>();

    private FlowBuilder() {
    }

    public static FlowBuilder create() {
        return new FlowBuilder();
    }

    public FlowBuilder initialState(String initialState) {
        this.initialState = initialState;
        return this;
    }

    public FlowBuilder when(String state, EventToStateMapping... stateEntries) {

        Objects.requireNonNull(state, "State is null.");

        Set<String> events = eventsByStateMap.get(state);
        if (events == null) {
            events = new HashSet<>();
            eventsByStateMap.put(state, events);
        }

        final Set<String> eventSet = events;

        Map<String, String> eventToStateMap = eventToStateMapByState.get(state);

        if (eventToStateMap == null) {
            eventToStateMap = new HashMap<>();
            eventToStateMapByState.put(state, eventToStateMap);
        }

        final Map<String, String> stateMap = eventToStateMap;

        Arrays.asList(stateEntries).forEach(entry -> {

            Objects.requireNonNull(entry, "EventToStateMapping is null.");
            Objects.requireNonNull(entry.event, "Event is null.");
            Objects.requireNonNull(entry.state, "State is null for event '" + entry.event + "'.");

            eventSet.add(entry.event);

            stateMap.put(entry.event, entry.state);
        });

        return this;
    }

    public FlowBuilder whenError(String state, ErrorToStateMapping... errorToStateMappings) {

        Objects.requireNonNull(state, "State is null.");

        Set<Class<? extends Throwable>> throwables = errorsByStateMap.get(state);
        if (throwables == null) {
            throwables = new HashSet<>();
            errorsByStateMap.put(state, throwables);
        }

        final Set<Class<? extends Throwable>> throwableSet = throwables;

        Map<Class<? extends Throwable>, String> errorToStateMap = errorToStateMapByState.get(state);

        if (errorToStateMap == null) {
            errorToStateMap = new HashMap<>();
            errorToStateMapByState.put(state, errorToStateMap);
        }

        final Map<Class<? extends Throwable>, String> stateMap = errorToStateMap;

        Arrays.asList(errorToStateMappings).forEach(entry -> {

            Objects.requireNonNull(entry, "EventToStateMapping is null.");
            Objects.requireNonNull(entry.getErrorClass(), "Event is null.");
            Objects.requireNonNull(entry.getNextState(), "State is null for event '" + entry.getNextState() + "'.");

            throwableSet.add(entry.getErrorClass());

            stateMap.put(entry.getErrorClass(), entry.getNextState());
        });

        return this;
    }

    public Flow build() {

        if (stateCallbacksMap.size() < eventsByStateMap.size()) {
            throw new FlowException("State callbacks are missing for some states.");
        }

        if (initialState == null) {
            throw new FlowException("Initial state ['" + initialState + "'] is required.");
        }

        if (!stateCallbacksMap.containsKey(initialState)) {
            throw new FlowException("Callbacks is not defined for initial state ['" + initialState + "'].");
        }

        eventsByStateMap.forEach(this::ensureStateMappingRecursive);

        return new Flow(
            initialState,
            immutableCopyOf(eventsByStateMap),
            immutableCopyOf2(eventToStateMapByState),
            immutableCopyOf3(errorsByStateMap),
            immutableCopyOf4(errorToStateMapByState),
            immutableCopyOf5(stateCallbacksMap));
    }

    private Map<String, Set<Class<? extends Throwable>>> immutableCopyOf3(Map<String, Set<Class<? extends Throwable>>> errorsByStateMap) {
        ImmutableMap.Builder<String, Set<Class<? extends Throwable>>> mapBuilder = ImmutableMap.builder();

        errorsByStateMap.forEach((state, classes) -> mapBuilder.put(state, ImmutableSet.copyOf(classes)));

        return mapBuilder.build();
    }

    private Map<String, Map<Class<? extends Throwable>, String>> immutableCopyOf4(Map<String, Map<Class<? extends Throwable>, String>> errorToStateMapByState) {
        ImmutableMap.Builder<String, Map<Class<? extends Throwable>, String>> mapBuilder = ImmutableMap.builder();

        errorToStateMapByState.forEach((state, classStringMap) -> mapBuilder.put(state, ImmutableMap.copyOf(classStringMap)));

        return mapBuilder.build();
    }

    private Map<String, FlowCallbacks> immutableCopyOf5(Map<String, FlowCallbacks> stateCallbacksMap) {
        return ImmutableMap.copyOf(stateCallbacksMap);
    }

    private Map<String, Map<String, String>> immutableCopyOf2(Map<String, Map<String, String>> eventToStateMapByState) {

        ImmutableMap.Builder<String, Map<String, String>> mapBuilder = ImmutableMap.builder();

        eventToStateMapByState.forEach((state, eventToStateMap) -> mapBuilder.put(state, ImmutableMap.copyOf(eventToStateMap)));

        return mapBuilder.build();
    }

    private Map<String, Set<String>> immutableCopyOf(Map<String, Set<String>> eventsByStateMap) {
        ImmutableMap.Builder<String, Set<String>> mapBuilder = ImmutableMap.builder();
{'fraction_non_alphanumeric': 0.11415689810640216, 'fraction_numerical': 0.0010820559062218215, 'mean_word_length': 3.2043214556482185, 'pattern_counts': {'":': 0, '<': 115, '<?xml version=': 0, '>': 121, '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': '7485318', 'n_tokens_mistral': 3030, 'n_tokens_neox': 2951, 'n_words': 645}