<commit_before>package org.roklib.webapps.uridispatching.mapper;

import org.roklib.webapps.uridispatching.AbstractURIActionCommand;
import org.roklib.webapps.uridispatching.helper.Preconditions;
import org.roklib.webapps.uridispatching.parameters.EnumURIParameterErrors;
import org.roklib.webapps.uridispatching.parameters.URIParameter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

public abstract class AbstractURIPathSegmentActionMapper implements URIPathSegmentActionMapper {
    private static final long serialVersionUID = 8450975393827044559L;

    private static final Logger LOG = LoggerFactory.getLogger(AbstractURIPathSegmentActionMapper.class);

    private Map<String, URIParameter<?>> registeredUriParameters;

    private List<String> actionArgumentOrder;
    protected List<URIPathSegmentActionMapper> mapperChain;
    private Map<String, List<Serializable>> actionArgumentMap;
    protected AbstractURIPathSegmentActionMapper parentMapper;
    private AbstractURIActionCommand actionCommand;

    /**
     * The name of the URI portion for which this action mapper is responsible.
     */
    protected String actionName;
    private String actionURI;
    private boolean caseSensitive = false;
    private boolean useHashExclamationMarkNotation = false;
    private Locale locale;

    /**
     * Creates a new action mapper with the given action name. The action name must not be <code>null</code>. This name
     * identifies the fragment of a URI which is handled by this action mapper. For example, if this action mapper is
     * responsible for the <code>admin</code> part in the following URI
     * <p/>
     * <pre>
     * http://www.example.com/admin/settings
     * </pre>
     * <p/>
     * then the action name for this mapper has to be set to <code>admin</code> as well.
     *
     * @param segmentName the name of the URI path segment for which this action mapper is responsible. Must not be
     *                    <code>null</code>.
     */
    public AbstractURIPathSegmentActionMapper(String segmentName) {
        Preconditions.checkNotNull(segmentName);
        this.actionName = segmentName;
        actionURI = segmentName;
    }

    @Deprecated
    protected void setUseHashExclamationMarkNotation(boolean useHashExclamationMarkNotation) {
        this.useHashExclamationMarkNotation = useHashExclamationMarkNotation;
    }

    /**
     * <p> Sets the case sensitivity of this action mapper. A case insentitive action mapper will match a URI token
     * without regarding the token's case. You have to be careful with case insensitive action mappers if you have more
     * than one action mapper with action names differing only in case. You might get unexpected results since one
     * action mapper might shadow the other. </p>
     */
    protected void setCaseSensitive(boolean caseSensitive) {
        this.caseSensitive = caseSensitive;
    }

    public boolean isCaseSensitive() {
        return caseSensitive;
    }

    public String getActionName() {
        return actionName;
    }

    public String getCaseInsensitiveActionName() {
        return actionName.toLowerCase(getLocale());
    }

    /**
     * Sets the action command for this action mapper. This is the given {@link AbstractURIActionCommand} which will be
     * returned when the token list to be interpreted by this mapper is empty. This is the case when a URI is being
     * interpreted that directly points to this {@link AbstractURIPathSegmentActionMapper}. For example, if the
     * following URI is passed to the URI action handling framework
     * <p/>
     * <pre>
     * http://www.example.com/myapp#!home/
     *                       \____/
     *                context path
     *                             \___/ URI path interpreted by the URI action framework
     * </pre>
     * <p/>
     * where the URI action mapper for token <code>home</code> is a sub-class of {@link
     * AbstractURIPathSegmentActionMapper}, then this mapper's action command is used as the outcome of the URI
     * interpretation. This command could then provide some logic for the interpreted URI, such as redirecting to the
     * correct home screen for the currently signed in user, or performing some other action.
     *
     * @param command action command to be used when interpreting a URI which points directly to this action mapper. Can
     *                be <code>null</code>.
     */
    public void setActionCommand(AbstractURIActionCommand command) {
        actionCommand = command;
    }

    public AbstractURIActionCommand getActionCommand() {
        return actionCommand;
    }

    protected void registerURIParameter(URIParameter<?> parameter) {
        Preconditions.checkNotNull(parameter);

        if (registeredUriParameters == null) {
            registeredUriParameters = new HashMap<>();
        }

        parameter.getParameterNames()
            .stream()
            .forEach(parameterName -> {
                if (registeredUriParameters.containsKey(parameterName)) {
                    throw new IllegalArgumentException("Cannot register parameter " + parameter +
                        ". Another parameter with parameter name '" + parameterName +
                        "' is already registered on this mapper: " + registeredUriParameters.get(parameterName));
                }
                registeredUriParameters.put(parameterName, parameter);
            });
    }

    protected boolean haveRegisteredURIParametersErrors() {
        boolean result = false;
        for (URIParameter<?> parameter : getUriParameterSet()) {
            result |= parameter.getError() != EnumURIParameterErrors.NO_ERROR;
        }
        return result;
    }

    private Map<String, URIParameter<?>> getUriParameters() {
        return registeredUriParameters == null ? Collections.emptyMap() : registeredUriParameters;
    }

    private Set<URIParameter<?>> getUriParameterSet() {
        return registeredUriParameters
            .values()
            .stream()
            .distinct()
            .collect(Collectors.toSet());
    }

    public final AbstractURIActionCommand handleURI(List<String> uriTokens, Map<String, List<String>> parameters,
                                                    ParameterMode parameterMode) {
        if (!getUriParameters().isEmpty()) {
            if (parameterMode == ParameterMode.QUERY) {
                consumeQueryParameters(parameters);
            } else {
                List<String> parameterNames = new LinkedList<>();
                for (URIParameter<?> parameter : getUriParameterSet()) {
                    parameterNames.addAll(parameter.getParameterNames());
                }
                if (parameterMode == ParameterMode.DIRECTORY_WITH_NAMES) {
                    Map<String, List<String>> parameterMap = new HashMap<>(4);
                    String parameterName;
                    String value;
                    for (Iterator<String> it = uriTokens.iterator(); it.hasNext(); ) {
                        parameterName = urlDecode(it.next());
                        value = "";
                        if (parameterNames.contains(parameterName)) {
                            it.remove();
                            if (it.hasNext()) {
                                value = urlDecode(it.next());
                                it.remove();
                            }
                            List<String> values = parameterMap.get(parameterName);
                            if (values == null) {
                                values = new LinkedList<>();
                                parameterMap.put(parameterName, values);
                            }
                            values.add(value);
                        }
                    }
                    consumeQueryParameters(parameterMap);
                } else if (parameterMode == ParameterMode.DIRECTORY) {
                    List<String> valueList = new LinkedList<>();
                    for (URIParameter<?> parameter : getUriParameterSet()) {
                        parameter.clearValue();
                        if (uriTokens.isEmpty()) {
                            continue;
                        }
                        valueList.clear();
                        int singleValueCount = parameter.getSingleValueCount();
                        int i = 0;<commit_msg>Remove unnecessary temporary list of registered parameter names<commit_after>package org.roklib.webapps.uridispatching.mapper;

import org.roklib.webapps.uridispatching.AbstractURIActionCommand;
import org.roklib.webapps.uridispatching.helper.Preconditions;
import org.roklib.webapps.uridispatching.parameters.EnumURIParameterErrors;
import org.roklib.webapps.uridispatching.parameters.URIParameter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

public abstract class AbstractURIPathSegmentActionMapper implements URIPathSegmentActionMapper {
    private static final long serialVersionUID = 8450975393827044559L;

    private static final Logger LOG = LoggerFactory.getLogger(AbstractURIPathSegmentActionMapper.class);

    private Map<String, URIParameter<?>> registeredUriParameters;

    private List<String> actionArgumentOrder;
    protected List<URIPathSegmentActionMapper> mapperChain;
    private Map<String, List<Serializable>> actionArgumentMap;
    protected AbstractURIPathSegmentActionMapper parentMapper;
    private AbstractURIActionCommand actionCommand;

    /**
     * The name of the URI portion for which this action mapper is responsible.
     */
    protected String actionName;
    private String actionURI;
    private boolean caseSensitive = false;
    private boolean useHashExclamationMarkNotation = false;
    private Locale locale;

    /**
     * Creates a new action mapper with the given action name. The action name must not be <code>null</code>. This name
     * identifies the fragment of a URI which is handled by this action mapper. For example, if this action mapper is
     * responsible for the <code>admin</code> part in the following URI
     * <p/>
     * <pre>
     * http://www.example.com/admin/settings
     * </pre>
     * <p/>
     * then the action name for this mapper has to be set to <code>admin</code> as well.
     *
     * @param segmentName the name of the URI path segment for which this action mapper is responsible. Must not be
     *                    <code>null</code>.
     */
    public AbstractURIPathSegmentActionMapper(String segmentName) {
        Preconditions.checkNotNull(segmentName);
        this.actionName = segmentName;
        actionURI = segmentName;
    }

    @Deprecated
    protected void setUseHashExclamationMarkNotation(boolean useHashExclamationMarkNotation) {
        this.useHashExclamationMarkNotation = useHashExclamationMarkNotation;
    }

    /**
     * <p> Sets the case sensitivity of this action mapper. A case insentitive action mapper will match a URI token
     * without regarding the token's case. You have to be careful with case insensitive action mappers if you have more
     * than one action mapper with action names differing only in case. You might get unexpected results since one
     * action mapper might shadow the other. </p>
     */
    protected void setCaseSensitive(boolean caseSensitive) {
        this.caseSensitive = caseSensitive;
    }

    public boolean isCaseSensitive() {
        return caseSensitive;
    }

    public String getActionName() {
        return actionName;
    }

    public String getCaseInsensitiveActionName() {
        return actionName.toLowerCase(getLocale());
    }

    /**
     * Sets the action command for this action mapper. This is the given {@link AbstractURIActionCommand} which will be
     * returned when the token list to be interpreted by this mapper is empty. This is the case when a URI is being
     * interpreted that directly points to this {@link AbstractURIPathSegmentActionMapper}. For example, if the
     * following URI is passed to the URI action handling framework
     * <p/>
     * <pre>
     * http://www.example.com/myapp#!home/
     *                       \____/
     *                context path
     *                             \___/ URI path interpreted by the URI action framework
     * </pre>
     * <p/>
     * where the URI action mapper for token <code>home</code> is a sub-class of {@link
     * AbstractURIPathSegmentActionMapper}, then this mapper's action command is used as the outcome of the URI
     * interpretation. This command could then provide some logic for the interpreted URI, such as redirecting to the
     * correct home screen for the currently signed in user, or performing some other action.
     *
     * @param command action command to be used when interpreting a URI which points directly to this action mapper. Can
     *                be <code>null</code>.
     */
    public void setActionCommand(AbstractURIActionCommand command) {
        actionCommand = command;
    }

    public AbstractURIActionCommand getActionCommand() {
        return actionCommand;
    }

    protected void registerURIParameter(URIParameter<?> parameter) {
        Preconditions.checkNotNull(parameter);

        if (registeredUriParameters == null) {
            registeredUriParameters = new HashMap<>();
        }

        parameter.getParameterNames()
            .stream()
            .forEach(parameterName -> {
                if (registeredUriParameters.containsKey(parameterName)) {
                    throw new IllegalArgumentException("Cannot register parameter " + parameter +
                        ". Another parameter with parameter name '" + parameterName +
                        "' is already registered on this mapper: " + registeredUriParameters.get(parameterName));
                }
                registeredUriParameters.put(parameterName, parameter);
            });
    }

    protected boolean haveRegisteredURIParametersErrors() {
        boolean result = false;
        for (URIParameter<?> parameter : getUriParameterSet()) {
            result |= parameter.getError() != EnumURIParameterErrors.NO_ERROR;
        }
        return result;
    }

    private Map<String, URIParameter<?>> getUriParameters() {
        return registeredUriParameters == null ? Collections.emptyMap() : registeredUriParameters;
    }

    private Set<URIParameter<?>> getUriParameterSet() {
        return registeredUriParameters
            .values()
            .stream()
            .distinct()
            .collect(Collectors.toSet());
    }

    public final AbstractURIActionCommand handleURI(List<String> uriTokens, Map<String, List<String>> parameters,
                                                    ParameterMode parameterMode) {
        if (!getUriParameters().isEmpty()) {
            if (parameterMode == ParameterMode.QUERY) {
                consumeQueryParameters(parameters);
            } else {
                if (parameterMode == ParameterMode.DIRECTORY_WITH_NAMES) {
                    Map<String, List<String>> parameterMap = new HashMap<>(4);
                    String parameterName;
                    String value;
                    for (Iterator<String> it = uriTokens.iterator(); it.hasNext(); ) {
                        parameterName = urlDecode(it.next());
                        value = "";
                        if (getUriParameters().containsKey(parameterName)) {
                            it.remove();
                            if (it.hasNext()) {
                                value = urlDecode(it.next());
                                it.remove();
                            }
                            List<String> values = parameterMap.get(parameterName);
                            if (values == null) {
                                values = new LinkedList<>();
                                parameterMap.put(parameterName, values);
                            }
                            values.add(value);
                        }
                    }
                    consumeQueryParameters(parameterMap);
                } else if (parameterMode == ParameterMode.DIRECTORY) {
                    List<String> valueList = new LinkedList<>();
                    for (URIParameter<?> parameter : getUriParameterSet()) {
                        parameter.clearValue();
                        if (uriTokens.isEmpty()) {
                            continue;
                        }
                        valueList.clear();
                        int singleValueCount = parameter.getSingleValueCount();
                        int i = 0;
{'fraction_non_alphanumeric': 0.07758218698997435, 'fraction_numerical': 0.0026812776871065515, 'mean_word_length': 2.1837075524215996, 'pattern_counts': {'":': 0, '<': 100, '<?xml version=': 0, '>': 102, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3115086', 'n_tokens_mistral': 4097, 'n_tokens_neox': 4030, 'n_words': 1219}