/*
 * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javax.naming;

import java.util.Enumeration;
import java.util.Properties;

/**
 * This class represents a composite name -- a sequence of
 * component names spanning multiple namespaces.
 * Each component is a string name from the namespace of a
 * naming system. If the component comes from a hierarchical
 * namespace, that component can be further parsed into
 * its atomic parts by using the CompoundName class.
 *<p>
 * The components of a composite name are numbered.  The indexes of a
 * composite name with N components range from 0 up to, but not including, N.
 * This range may be written as [0,N).
 * The most significant component is at index 0.
 * An empty composite name has no components.
 *
 * <h2>JNDI Composite Name Syntax</h2>
 * JNDI defines a standard string representation for composite names. This
 * representation is the concatenation of the components of a composite name
 * from left to right using the component separator (a forward
 * slash character (/)) to separate each component.
 * The JNDI syntax defines the following meta characters:
 * <ul>
 * <li>escape (backward slash \),
 * <li>quote characters  (single (') and double quotes (")), and
 * <li>component separator (forward slash character (/)).
 * </ul>
 * Any occurrence of a leading quote, an escape preceding any meta character,
 * an escape at the end of a component, or a component separator character
 * in an unquoted component must be preceded by an escape character when
 * that component is being composed into a composite name string.
 * Alternatively, to avoid adding escape characters as described,
 * the entire component can be quoted using matching single quotes
 * or matching double quotes. A single quote occurring within a double-quoted
 * component is not considered a meta character (and need not be escaped),
 * and vice versa.
 *<p>
 * When two composite names are compared, the case of the characters
 * is significant.
 *<p>
 * A leading component separator (the composite name string begins with
 * a separator) denotes a leading empty component (a component consisting
 * of an empty string).
 * A trailing component separator (the composite name string ends with
 * a separator) denotes a trailing empty component.
 * Adjacent component separators denote an empty component.
 *
 *<h2>Composite Name Examples</h2>
 *This table shows examples of some composite names. Each row shows
 *the string form of a composite name and its corresponding structural form
 *({@code CompositeName}).
 *
<table class="striped"><caption style="display:none">examples showing string
 form of composite name and its corresponding structural form (CompositeName)</caption>
<thead>
<tr>
<th scope="col">String Name</th>
<th scope="col">CompositeName</th>
</tr>
</thead>
<tbody style="text-align:left">
<tr>
<th scope="row">
""
</th>
<td>{} (the empty name == new CompositeName("") == new CompositeName())
</td>
</tr>

<tr>
<th scope="row">
"x"
</th>
<td>{"x"}
</td>
</tr>

<tr>
<th scope="row">
"x/y"
</th>
<td>{"x", "y"}</td>
</tr>

<tr>
<th scope="row">"x/"</th>
<td>{"x", ""}</td>
</tr>

<tr>
<th scope="row">"/x"</th>
<td>{"", "x"}</td>
</tr>

<tr>
<th scope="row">"/"</th>
<td>{""}</td>
</tr>

<tr>
<th scope="row">"//"</th>
<td>{"", ""}</td>
</tr>

<tr><th scope="row">"/x/"</th>
<td>{"", "x", ""}</td>
</tr>

<tr><th scope="row">"x//y"</th>
<td>{"x", "", "y"}</td>
</tr>
</tbody>
</table>
 *
 *<h2>Composition Examples</h2>
 * Here are some composition examples.  The right column shows composing
 * string composite names while the left column shows composing the
 * corresponding {@code CompositeName}s.  Notice that composing the
 * string forms of two composite names simply involves concatenating
 * their string forms together.

<table class="striped"><caption style="display:none">composition examples
 showing string names and composite names</caption>
<thead>
<tr>
<th scope="col">String Names</th>
<th scope="col">CompositeNames</th>
</tr>
</thead>

<tbody style="text-align:left">
<tr>
<th scope="row">
"x/y"           + "/"   = x/y/
</th>
<td>
{"x", "y"}      + {""}  = {"x", "y", ""}
</td>
</tr>

<tr>
<th scope="row">
""              + "x"   = "x"
</th>
<td>
{}              + {"x"} = {"x"}
</td>
</tr>

<tr>
<th scope="row">
"/"             + "x"   = "/x"
</th>
<td>
{""}            + {"x"} = {"", "x"}
</td>
</tr>

<tr>
<th scope="row">
"x"   + ""      + ""    = "x"
</th>
<td>
{"x"} + {}      + {}    = {"x"}
</td>
</tr>
</tbody>
</table>
 *
 *<h2>Multithreaded Access</h2>
 * A {@code CompositeName} instance is not synchronized against concurrent
 * multithreaded access. Multiple threads trying to access and modify a
 * {@code CompositeName} should lock the object.
 *
 * @author Rosanna Lee
 * @author Scott Seligman
 * @since 1.3
 */


public class CompositeName implements Name {

    private transient NameImpl impl;
    /**
      * Constructs a new composite name instance using the components
      * specified by 'comps'. This protected method is intended
      * to be used by subclasses of CompositeName when they override
      * methods such as clone(), getPrefix(), getSuffix().
      *
      * @param comps A non-null enumeration containing the components for the new
      *              composite name. Each element is of class String.
      *               The enumeration will be consumed to extract its
      *               elements.
      */
    protected CompositeName(Enumeration<String> comps) {
        impl = new NameImpl(null, comps); // null means use default syntax
    }

    /**
      * Constructs a new composite name instance by parsing the string n
      * using the composite name syntax (left-to-right, slash separated).
      * The composite name syntax is described in detail in the class
      * description.
      *
      * @param  n       The non-null string to parse.
      * @throws InvalidNameException If n has invalid composite name syntax.
      */
    public CompositeName(String n) throws InvalidNameException {
        impl = new NameImpl(null, n);  // null means use default syntax
    }

    /**
      * Constructs a new empty composite name. Such a name returns true
      * when <code>isEmpty()</code> is invoked on it.
      */
    public CompositeName() {
        impl = new NameImpl(null);  // null means use default syntax
    }

    /**
      * Generates the string representation of this composite name.
      * The string representation consists of enumerating in order
      * each component of the composite name and separating
      * each component by a forward slash character. Quoting and
      * escape characters are applied where necessary according to
      * the JNDI syntax, which is described in the class description.
      * An empty component is represented by an empty string.
      *
      * The string representation thus generated can be passed to
      * the CompositeName constructor to create a new equivalent
      * composite name.
      *
      * @return A non-null string representation of this composite name.
      */
    public String toString() {
        return impl.toString();
    }

    /**
      * Determines whether two composite names are equal.
      * If obj is null or not a composite name, false is returned.
      * Two composite names are equal if each component in one is equal
      * to the corresponding component in the other. This implies
      * both have the same number of components, and each component's
      * equals() test against the corresponding component in the other name
      * returns true.
      *
      * @param  obj     The possibly null object to compare against.
      * @return true if obj is equal to this composite name, false otherwise.
      * @see #hashCode
      */
    public boolean equals(Object obj) {
        return (obj instanceof CompositeName other) &&
                impl.equals(other.impl);
    }

    /**
      * Computes the hash code of this composite name.
      * The hash code is the sum of the hash codes of individual components
      * of this composite name.
      *
      * @return An int representing the hash code of this name.
      * @see #equals
      */
    public int hashCode() {
        return impl.hashCode();
    }


    /**
     * Compares this CompositeName with the specified Object for order.
     * Returns a
     * negative integer, zero, or a positive integer as this Name is less
     * than, equal to, or greater than the given Object.
     * <p>
     * If obj is null or not an instance of CompositeName, ClassCastException
     * is thrown.
     * <p>
     * See equals() for what it means for two composite names to be equal.
     * If two composite names are equal, 0 is returned.
     * <p>
     * Ordering of composite names follows the lexicographical rules for
     * string comparison, with the extension that this applies to all
     * the components in the composite name. The effect is as if all the
     * components were lined up in their specified ordered and the
     * lexicographical rules applied over the two line-ups.
     * If this composite name is "lexicographically" lesser than obj,
     * a negative number is returned.
     * If this composite name is "lexicographically" greater than obj,
     * a positive number is returned.
     * @param obj The non-null object to compare against.
     *
     * @return  a negative integer, zero, or a positive integer as this Name
     *          is less than, equal to, or greater than the given Object.
     * @throws ClassCastException if obj is not a CompositeName.
     */
    public int compareTo(Object obj) {
        if (!(obj instanceof CompositeName)) {
            throw new ClassCastException("Not a CompositeName");
        }
        return impl.compareTo(((CompositeName)obj).impl);
    }

    /**
      * Generates a copy of this composite name.
      * Changes to the components of this composite name won't
      * affect the new copy and vice versa.
      *
      * @return A non-null copy of this composite name.
      */
    public Object clone() {
        return (new CompositeName(getAll()));
    }

    /**
      * Retrieves the number of components in this composite name.
      *
      * @return The nonnegative number of components in this composite name.
      */
    public int size() {
        return (impl.size());
    }

    /**
      * Determines whether this composite name is empty. A composite name
      * is empty if it has zero components.
      *
      * @return true if this composite name is empty, false otherwise.
      */
    public boolean isEmpty() {
        return (impl.isEmpty());
    }

    /**
      * Retrieves the components of this composite name as an enumeration
      * of strings.
      * The effects of updates to this composite name on this enumeration
      * is undefined.
      *
      * @return A non-null enumeration of the components of
      *         this composite name. Each element of the enumeration is of
      *         class String.
      */
    public Enumeration<String> getAll() {
        return (impl.getAll());
    }

    /**
      * Retrieves a component of this composite name.
      *
      * @param  posn    The 0-based index of the component to retrieve.
      *                 Must be in the range [0,size()).
      * @return The non-null component at index posn.
      * @throws ArrayIndexOutOfBoundsException if posn is outside the
      *         specified range.
      */
    public String get(int posn) {
        return (impl.get(posn));
    }

    /**
      * Creates a composite name whose components consist of a prefix of the
      * components in this composite name. Subsequent changes to
      * this composite name does not affect the name that is returned.
      *
      * @param  posn    The 0-based index of the component at which to stop.
      *                 Must be in the range [0,size()].
      * @return A composite name consisting of the components at indexes in
      *         the range [0,posn).
      * @throws ArrayIndexOutOfBoundsException
      *         If posn is outside the specified range.
      */
    public Name getPrefix(int posn) {
        Enumeration<String> comps = impl.getPrefix(posn);
        return (new CompositeName(comps));
    }

    /**
      * Creates a composite name whose components consist of a suffix of the
      * components in this composite name. Subsequent changes to
      * this composite name does not affect the name that is returned.
      *
      * @param  posn    The 0-based index of the component at which to start.
      *                 Must be in the range [0,size()].
      * @return A composite name consisting of the components at indexes in
      *         the range [posn,size()).  If posn is equal to
      *         size(), an empty composite name is returned.
      * @throws ArrayIndexOutOfBoundsException
      *         If posn is outside the specified range.
      */
    public Name getSuffix(int posn) {
        Enumeration<String> comps = impl.getSuffix(posn);
        return (new CompositeName(comps));
    }

    /**
      * Determines whether a composite name is a prefix of this composite name.
      * A composite name 'n' is a prefix if it is equal to
      * getPrefix(n.size())--in other words, this composite name
      * starts with 'n'. If 'n' is null or not a composite name, false is returned.
      *
      * @param  n       The possibly null name to check.
      * @return true if n is a CompositeName and
      *         is a prefix of this composite name, false otherwise.
      */
    public boolean startsWith(Name n) {
        if (n instanceof CompositeName) {
            return (impl.startsWith(n.size(), n.getAll()));
        } else {
            return false;
        }
    }

    /**
      * Determines whether a composite name is a suffix of this composite name.
      * A composite name 'n' is a suffix if it is equal to
      * getSuffix(size()-n.size())--in other words, this
      * composite name ends with 'n'.
      * If n is null or not a composite name, false is returned.
      *
      * @param  n       The possibly null name to check.
      * @return true if n is a CompositeName and
      *         is a suffix of this composite name, false otherwise.
      */
    public boolean endsWith(Name n) {
        if (n instanceof CompositeName) {
            return (impl.endsWith(n.size(), n.getAll()));
        } else {
            return false;
        }
    }

    /**
      * Adds the components of a composite name -- in order -- to the end of
      * this composite name.
      *
      * @param suffix   The non-null components to add.
      * @return The updated CompositeName, not a new one. Cannot be null.
      * @throws InvalidNameException If suffix is not a composite name.
      */
    public Name addAll(Name suffix)
        throws InvalidNameException
    {
        if (suffix instanceof CompositeName) {
            impl.addAll(suffix.getAll());
            return this;
        } else {
            throw new InvalidNameException("Not a composite name: " +
                suffix.toString());
        }
    }

    /**
      * Adds the components of a composite name -- in order -- at a specified
      * position within this composite name.
      * Components of this composite name at or after the index of the first
      * new component are shifted up (away from index 0)
      * to accommodate the new components.
      *
      * @param posn     The index in this name at which to add the new
      *                 components.  Must be in the range [0,size()].
      * @param n        The non-null components to add.
      * @return The updated CompositeName, not a new one. Cannot be null.
      * @throws InvalidNameException If n is not a composite name.
      * @throws ArrayIndexOutOfBoundsException
      *         If posn is outside the specified range.
      */
    public Name addAll(int posn, Name n)
        throws InvalidNameException
    {
        if (n instanceof CompositeName) {
            impl.addAll(posn, n.getAll());
            return this;
        } else {
            throw new InvalidNameException("Not a composite name: " +
                n.toString());
        }
    }

    /**
      * Adds a single component to the end of this composite name.
      *
      * @param comp     The non-null component to add.
      * @return The updated CompositeName, not a new one. Cannot be null.
      * @throws InvalidNameException If adding comp at end of the name
      *         would violate the name's syntax.
      */
    public Name add(String comp) throws InvalidNameException {
        impl.add(comp);
        return this;
    }

    /**
      * Adds a single component at a specified position within this
      * composite name.
      * Components of this composite name at or after the index of the new
      * component are shifted up by one (away from index 0) to accommodate
      * the new component.
      *
      * @param  posn    The index at which to add the new component.
      *                 Must be in the range [0,size()].
      * @param  comp    The non-null component to add.
      * @return The updated CompositeName, not a new one. Cannot be null.
      * @throws ArrayIndexOutOfBoundsException
      *         If posn is outside the specified range.
      * @throws InvalidNameException If adding comp at the specified position
      *         would violate the name's syntax.
      */
    public Name add(int posn, String comp)
        throws InvalidNameException
    {
        impl.add(posn, comp);
        return this;
    }

    /**
      * Deletes a component from this composite name.
      * The component of this composite name at position 'posn' is removed,
      * and components at indices greater than 'posn'
      * are shifted down (towards index 0) by one.
      *
      * @param  posn    The index of the component to delete.
      *                 Must be in the range [0,size()).
      * @return The component removed (a String).
      * @throws ArrayIndexOutOfBoundsException
      *         If posn is outside the specified range (includes case where
      *         composite name is empty).
      * @throws InvalidNameException If deleting the component
      *         would violate the name's syntax.
      */
    public Object remove(int posn) throws InvalidNameException{
        return impl.remove(posn);
    }

    /**
     * The writeObject method is called to save the state of the
     * {@code CompositeName} to a stream.
     *
     * @serialData The number of components (an {@code int}) followed by
     * the individual components (each a {@code String}).
     *
     * @param s the {@code ObjectOutputStream} to write to
     * @throws java.io.IOException if an I/O error occurs
     */
    @java.io.Serial
    private void writeObject(java.io.ObjectOutputStream s)
            throws java.io.IOException {
        // Overridden to avoid implementation dependency
        s.writeInt(size());
        Enumeration<String> comps = getAll();
        while (comps.hasMoreElements()) {
            s.writeObject(comps.nextElement());
        }
    }

    /**
     * The readObject method is called to restore the state of
     * the {@code CompositeName} from a stream.
     *
     * See {@code writeObject} for a description of the serial form.
     *
     * @param s the {@code ObjectInputStream} to read from
     * @throws java.io.IOException if an I/O error occurs
     * @throws ClassNotFoundException if the class of a serialized object
     *         could not be found
     */
    @java.io.Serial
    private void readObject(java.io.ObjectInputStream s)
            throws java.io.IOException, ClassNotFoundException {
        // Overridden to avoid implementation dependency
        impl = new NameImpl(null);  // null means use default syntax
        int n = s.readInt();    // number of components
        try {
            while (--n >= 0) {
                add((String)s.readObject());
            }
        } catch (InvalidNameException e) {
            throw (new java.io.StreamCorruptedException("Invalid name"));
        }
    }

    /**
     * Use serialVersionUID from JNDI 1.1.1 for interoperability
     */
    @java.io.Serial
    private static final long serialVersionUID = 1667768148915813118L;

/*
    // %%% Test code for serialization.
    public static void main(String[] args) throws Exception {
        CompositeName c = new CompositeName("aaa/bbb");
        java.io.FileOutputStream f1 = new java.io.FileOutputStream("/tmp/ser");
        java.io.ObjectOutputStream s1 = new java.io.ObjectOutputStream(f1);
        s1.writeObject(c);
        s1.close();
        java.io.FileInputStream f2 = new java.io.FileInputStream("/tmp/ser");
        java.io.ObjectInputStream s2 = new java.io.ObjectInputStream(f2);
        c = (CompositeName)s2.readObject();

        System.out.println("Size: " + c.size());
        System.out.println("Size: " + c.snit);
    }
*/

/*
   %%% Testing code
    public static void main(String[] args) {
        try {
            for (int i = 0; i < args.length; i++) {
                Name name;
                Enumeration e;
                System.out.println("Given name: " + args[i]);
                name = new CompositeName(args[i]);
                e = name.getComponents();
                while (e.hasMoreElements()) {
                    System.out.println("Element: " + e.nextElement());
                }
                System.out.println("Constructed name: " + name.toString());
            }
        } catch (Exception ne) {
            ne.printStackTrace();
        }
    }
*/
}
