<commit_before>// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.processing.request;

import com.google.common.collect.ImmutableList;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static com.yahoo.text.Lowercase.toLowerCase;

/**
 * An immutable compound name of the general form "a.bb.ccc",
 * where there can be any number of such compounds, including one or zero.
 * <p>
 * Using CompoundName is generally substantially faster than using strings.
 *
 * @author bratseth
 */
public final class CompoundName {

    /**
     * The string name of this compound.
     */
    private final String name;
    private final String lowerCasedName;

    private final ImmutableList<String> compounds;

    /** A hashcode which is always derived from the compounds (NEVER the string) */
    private final int hashCode;

    /** This name with the first component removed */
    private final CompoundName rest;

    /** The empty compound */
    public static final CompoundName empty = new CompoundName("");

    /**
     * Constructs this from a string which may contains dot-separated components
     *
     * @throws NullPointerException if name is null
     */
    public CompoundName(String name) {
        this(name, parse(name));
    }

    /** Constructs this from an array of name components which are assumed not to contain dots */
    public static CompoundName fromComponents(String ... components) {
        return new CompoundName(Arrays.asList(components));
    }

    /** Constructs this from a list of compounds. */
    public CompoundName(List<String> compounds) {
        this(toCompoundString(compounds), compounds);
    }

    /**
     * Constructs this from a name with already parsed compounds.
     * Private to avoid creating names with inconsistencies.
     *
     * @param name the string representation of the compounds
     * @param compounds the compounds of this name
     */
    private CompoundName(String name, List<String> compounds) {
        if (name == null) throw new NullPointerException("Name can not be null");

        this.name = name;
        this.lowerCasedName = toLowerCase(name);
        if (compounds.size() == 1 && compounds.get(0).isEmpty())
            this.compounds = ImmutableList.of();
        else
            this.compounds = ImmutableList.copyOf(compounds);
        this.hashCode = this.compounds.hashCode();

        int size = this.compounds.size();
        rest = size > 1 ? new CompoundName(compounds.subList(1, size))
                        : size == 1 ? empty : this; // size==0 -> this needed during construction of empty
    }

    private static List<String> parse(String s) {
        ArrayList<String> l = null;

        int p = 0;
        final int m = s.length();
        for (int i = 0; i < m; i++) {
            if (s.charAt(i) == '.') {
                if (l == null) l = new ArrayList<>(8);
                l.add(s.substring(p, i));
                p = i + 1;
            }
        }
        if (p == 0) {
            return ImmutableList.of(s);
        } else if (p < m) {
            l.add(s.substring(p, m));
        } else {
            throw new IllegalArgumentException("'" + s + "' is not a legal compound name. Names can not end with a dot.");
        }
        return l;
    }

    /**
     * Returns a compound name which has the given compound string appended to it
     *
     * @param name if name is empty this returns <code>this</code>
     */
    public CompoundName append(String name) {
        if (name.isEmpty()) return this;
        if (isEmpty()) return new CompoundName(name);
        List<String> newCompounds = new ArrayList<>(compounds);
        newCompounds.addAll(parse(name));
        return new CompoundName(concat(this.name, name), newCompounds);
    }

    /**
     * Returns a compound name which has the given compounds appended to it
     *
     * @param name if name is empty this returns <code>this</code>
     */
    public CompoundName append(CompoundName name) {
        if (name.isEmpty()) return this;
        if (isEmpty()) return name;
        List<String> newCompounds = new ArrayList<>(compounds);
        newCompounds.addAll(name.compounds);
        return new CompoundName(concat(this.name, name.name), newCompounds);
    }

    private String concat(String name1, String name2) {
        return name1 + "." + name2;
    }

    /**
     * Returns a compound name which has the given name components prepended to this name,
     * in the given order, i.e new ComponentName("c").prepend("a","b") will yield "a.b.c".
     *
     * @param nameParts if name is empty this returns <code>this</code>
     */
    public CompoundName prepend(String ... nameParts) {
        if (nameParts.length == 0) return this;
        if (isEmpty()) return fromComponents(nameParts);

        List<String> newCompounds = new ArrayList<>(nameParts.length + compounds.size());
        newCompounds.addAll(Arrays.asList(nameParts));
        newCompounds.addAll(this.compounds);
        return new CompoundName(newCompounds);
    }

    /**
     * Returns the name after the last dot. If there are no dots, the full name is returned.
     */
    public String last() {
        if (compounds.isEmpty()) return "";
        return compounds.get(compounds.size() - 1);
    }<commit_msg>Use List.of/copyOf instead of ImmutableList.<commit_after>// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.processing.request;

import java.util.ArrayList;
import java.util.List;

import static com.yahoo.text.Lowercase.toLowerCase;

/**
 * An immutable compound name of the general form "a.bb.ccc",
 * where there can be any number of such compounds, including one or zero.
 * <p>
 * Using CompoundName is generally substantially faster than using strings.
 *
 * @author bratseth
 */
public final class CompoundName {

    /**
     * The string name of this compound.
     */
    private final String name;
    private final String lowerCasedName;

    private final List<String> compounds;

    /** A hashcode which is always derived from the compounds (NEVER the string) */
    private final int hashCode;

    /** This name with the first component removed */
    private final CompoundName rest;

    /** The empty compound */
    public static final CompoundName empty = new CompoundName("");

    /**
     * Constructs this from a string which may contains dot-separated components
     *
     * @throws NullPointerException if name is null
     */
    public CompoundName(String name) {
        this(name, parse(name, null));
    }

    /** Constructs this from an array of name components which are assumed not to contain dots */
    public static CompoundName fromComponents(String ... components) {
        return new CompoundName(List.of(components));
    }

    /** Constructs this from a list of compounds. */
    public CompoundName(List<String> compounds) {
        this(toCompoundString(compounds), compounds);
    }

    /**
     * Constructs this from a name with already parsed compounds.
     * Private to avoid creating names with inconsistencies.
     *
     * @param name the string representation of the compounds
     * @param compounds the compounds of this name
     */
    private CompoundName(String name, List<String> compounds) {
        if (name == null) throw new NullPointerException("Name can not be null");

        this.name = name;
        this.lowerCasedName = toLowerCase(name);
        if (compounds.size() == 1 && compounds.get(0).isEmpty())
            this.compounds = List.of();
        else
            this.compounds = List.copyOf(compounds);
        this.hashCode = this.compounds.hashCode();

        int size = this.compounds.size();
        rest = size > 1 ? new CompoundName(compounds.subList(1, size))
                        : size == 1 ? empty : this; // size==0 -> this needed during construction of empty
    }

    private static List<String> parse(String s, List<String> l) {
        int p = 0;
        final int m = s.length();
        for (int i = 0; i < m; i++) {
            if (s.charAt(i) == '.') {
                if (l == null) l = new ArrayList<>(8);
                l.add(s.substring(p, i));
                p = i + 1;
            }
        }
        if (p == 0) {
            return List.of(s);
        } else if (p < m) {
            l.add(s.substring(p, m));
        } else {
            throw new IllegalArgumentException("'" + s + "' is not a legal compound name. Names can not end with a dot.");
        }
        return l;
    }

    /**
     * Returns a compound name which has the given compound string appended to it
     *
     * @param name if name is empty this returns <code>this</code>
     */
    public CompoundName append(String name) {
        if (name.isEmpty()) return this;
        if (isEmpty()) return new CompoundName(name);
        List<String> newCompounds = parse(name, new ArrayList<>(compounds));
        return new CompoundName(concat(this.name, name), newCompounds);
    }

    /**
     * Returns a compound name which has the given compounds appended to it
     *
     * @param name if name is empty this returns <code>this</code>
     */
    public CompoundName append(CompoundName name) {
        if (name.isEmpty()) return this;
        if (isEmpty()) return name;
        List<String> newCompounds = new ArrayList<>(compounds);
        newCompounds.addAll(name.compounds);
        return new CompoundName(concat(this.name, name.name), newCompounds);
    }

    private static String concat(String name1, String name2) {
        return name1 + "." + name2;
    }

    /**
     * Returns a compound name which has the given name components prepended to this name,
     * in the given order, i.e new ComponentName("c").prepend("a","b") will yield "a.b.c".
     *
     * @param nameParts if name is empty this returns <code>this</code>
     */
    public CompoundName prepend(String ... nameParts) {
        if (nameParts.length == 0) return this;
        if (isEmpty()) return fromComponents(nameParts);

        List<String> newCompounds = new ArrayList<>(nameParts.length + compounds.size());
        newCompounds.addAll(List.of(nameParts));
        newCompounds.addAll(this.compounds);
        return new CompoundName(newCompounds);
    }

    /**
     * Returns the name after the last dot. If there are no dots, the full name is returned.
     */
    public String last() {
        if (compounds.isEmpty()) return "";
        return compounds.get(compounds.size() - 1);
    }
{'fraction_non_alphanumeric': 0.10693478669423041, 'fraction_numerical': 0.0035707573764330014, 'mean_word_length': 2.454397922752353, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 45, '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': '831972', 'n_tokens_mistral': 2980, 'n_tokens_neox': 2838, 'n_words': 1013}