/* CompoundName.java --
   Copyright (C) 2001, 2004, 2005  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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 for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package javax.naming;

import java.io.Serializable;
import java.util.Enumeration;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.Vector;

/**
 * @author Tom Tromey (tromey@redhat.com)
 * @date May 16, 2001
 *
 * FIXME: must write readObject and writeObject to conform to
 * serialization spec.
 *
 * FIXME: this class is underspecified.  For instance, the `flat'
 * direction is never described.  If it means that the CompoundName
 * can only have a single element, then the Enumeration-based
 * constructor ought to throw InvalidNameException.
 *
 * @since 1.3
 */
public class CompoundName implements Name, Cloneable, Serializable
{
  private static final long serialVersionUID = 3513100557083972036L;

  private CompoundName (Properties syntax)
  {
    elts = new Vector ();
    mySyntax = syntax;
    initializeSyntax ();
  }

  protected CompoundName (Enumeration comps, Properties syntax)
  {
    elts = new Vector ();
    mySyntax = syntax;
    initializeSyntax ();
    try
      {
	while (comps.hasMoreElements ())
	  elts.add (comps.nextElement ());
      }
    catch (NoSuchElementException ignore)
      {
      }
  }

  public CompoundName (String n, Properties syntax)
    throws InvalidNameException
  {
    elts = new Vector ();
    mySyntax = syntax;
    initializeSyntax ();

    StringBuffer new_element = new StringBuffer ();
    int i = 0;
    // QUOTE==null means no quoting right now.  When it is set it is
    // the value of the closing quote.
    String quote = null;
    while (i < n.length ())
      {
	String special = isSpecial (n, i);

	if (special == escape && escape != null)
	  {
	    if (n.length () == i + special.length ())
	      {
		// A trailing escape is treated as itself.
		new_element.append (special);
		i += special.length ();
	      }
	    else
	      {
		String eSpecial = isSpecial (n, i + special.length ());
		if (eSpecial != null)
		  {
		    // Treat the escape as an escape.
		    new_element.append (eSpecial);
		    i += special.length () + eSpecial.length ();
		  }
		else
		  {
		    // Treat the escape as itself.
		    new_element.append (special);
		    i += special.length ();
		  }
		continue;
	      }
	  }
	else if (quote != null)
	  {
	    // It is safe to use == here.
	    if (quote == special)
	      {
		// Quotes must surround a complete component.
		if (i + quote.length () < n.length ()
		    && ! n.startsWith (separator, i + quote.length ()))
		  throw new InvalidNameException ("close quote before end of component");
		elts.add (new_element.toString ());
		new_element.setLength (0);
		i += quote.length ();
		quote = null;
		continue;
	      }
	    // Otherwise, fall through.
	  }
	// Quotes are only special at the start of a component.
	else if (new_element.length () == 0
		 && special == beginQuote
		 && beginQuote != null)
	  {
	    quote = endQuote;
	    i += special.length ();
	    continue;
	  }
	else if (new_element.length () == 0
		 && special == beginQuote2
		 && beginQuote2 != null)
	  {
	    quote = endQuote2;
	    i += special.length ();
	    continue;
	  }
	else if (direction != FLAT && special == separator)
	  {
	    elts.add (new_element.toString ());
	    new_element.setLength (0);
	    i += special.length ();
	    continue;
	  }

	// Nothing in particular, so try the next character.
	new_element.append (n.charAt (i));
	++i;
      }

    if (new_element.length () != 0)
      elts.add (new_element.toString ());

    if (direction == RIGHT_TO_LEFT)
      {
	// Reverse the order of the elements.
	int len = elts.size ();
	for (i = 0; i < len / 2; ++i)
	  {
	    Object t = elts.set (i, elts.get (len - i - 1));
	    elts.set (len - i - 1, t);
	  }
      }

    // Error checking.
    if (quote != null)
      throw new InvalidNameException ("unterminated quote");
  }

  public Name add (int posn, String comp) throws InvalidNameException
  {
    elts.add (posn, comp);
    return this;
  }

  public Name add (String comp) throws InvalidNameException
  {
    elts.add (comp);
    return this;
  }

  public Name addAll (int posn, Name n) throws InvalidNameException
  {
    Enumeration e = n.getAll ();
    try
      {
	while (e.hasMoreElements ())
	  {
	    elts.add (posn, e.nextElement ());
	    ++posn;
	  }
      }
    catch (NoSuchElementException ignore)
      {
      }
    return this;
  }

  public Name addAll (Name suffix) throws InvalidNameException
  {
    Enumeration e = suffix.getAll ();
    try
      {
	while (e.hasMoreElements ())
	  elts.add (e.nextElement ());
      }
    catch (NoSuchElementException ignore)
      {
      }
    return this;
  }

  public Object clone ()
  {
    return new CompoundName (elts.elements (), mySyntax);
  }

  public int compareTo (Object obj)
  {
    if (! (obj instanceof CompoundName))
      throw new ClassCastException ("CompoundName.compareTo() expected CompoundName");
    CompoundName cn = (CompoundName) obj;
    int last = Math.min (cn.elts.size (), elts.size ());
    for (int i = 0; i < last; ++i)
      {
	String f = canonicalize ((String) elts.get (i));
	int comp = f.compareTo (canonicalize ((String) cn.elts.get (i)));
	if (comp != 0)
	  return comp;
      }
    return elts.size () - cn.elts.size ();
  }

  public boolean endsWith (Name n)
  {
    if (! (n instanceof CompoundName))
      return false;
    CompoundName cn = (CompoundName) n;
    if (cn.elts.size () > elts.size ())
      return false;
    int delta = elts.size () - cn.elts.size ();
    for (int i = 0; i < cn.elts.size (); ++i)
      {
	String f = canonicalize ((String) elts.get (delta + i));
	if (! f.equals (canonicalize ((String) cn.elts.get (i))))
	  return false;
      }
    return true;
  }

  public boolean equals (Object obj)
  {
    if (! (obj instanceof CompoundName))
      return false;
    return compareTo (obj) == 0;
  }

  public String get (int posn)
  {
    return (String) elts.get (posn);
  }

  public Enumeration getAll ()
  {
    return elts.elements ();
  }

  public Name getPrefix (int posn)
  {
    CompoundName cn = new CompoundName (mySyntax);
    for (int i = 0; i < posn; ++i)
      cn.elts.add (elts.get (i));
    return cn;
  }

  public Name getSuffix (int posn)
  {
    if (posn > elts.size ())
      throw new ArrayIndexOutOfBoundsException (posn);
    CompoundName cn = new CompoundName (mySyntax);
    for (int i = posn; i < elts.size (); ++i)
      cn.elts.add (elts.get (i));
    return cn;
  }

  public int hashCode ()
  {
    int h = 0;
    for (int i = 0; i < elts.size (); ++i)
      h += canonicalize ((String) elts.get (i)).hashCode ();
    return h;
  }

  public boolean isEmpty ()
  {
    return elts.isEmpty ();
  }

  public Object remove (int posn) throws InvalidNameException
  {
    return elts.remove (posn);
  }

  public int size ()
  {
    return elts.size ();
  }

  public boolean startsWith (Name n)
  {
    if (! (n instanceof CompoundName))
      return false;
    CompoundName cn = (CompoundName) n;
    if (cn.elts.size () > elts.size ())
      return false;
    for (int i = 0; i < cn.elts.size (); ++i)
      {
	String f = canonicalize ((String) elts.get (i));
	if (! f.equals (canonicalize ((String) cn.elts.get (i))))
	  return false;
      }
    return true;
  }

  // If ELEMENT starts with some meta-sequence at OFFSET, then return
  // the string representing the meta-sequence.  Otherwise return
  // null.
  private String isSpecial (String element, int offset)
  {
    String special = null;
    if (separator != null && element.startsWith (separator, offset))
      special = separator;
    else if (escape != null && element.startsWith (escape, offset))
      special = escape;
    else if (beginQuote != null && element.startsWith (beginQuote, offset))
      special = beginQuote;
    else if (endQuote != null && element.startsWith (endQuote, offset))
      special = endQuote;
    else if (beginQuote2 != null
	     && element.startsWith (beginQuote2, offset))
      special = beginQuote2;
    else if (endQuote2 != null && element.startsWith (endQuote2, offset))
      special = endQuote2;

    return special;
  }

  public String toString ()
  {
    StringBuffer result = new StringBuffer ();
    int size = elts.size ();
    for (int i = 0; i < size; ++i)
      {
	// Find the appropriate element.  FIXME: not clear what FLAT
	// means.
	int offset = (direction == RIGHT_TO_LEFT) ? (size - i - 1) : i;
	String element = (String) elts.get (offset);
	if (i > 0
	    || (i == size - 1 && element.equals ("")))
	  result.append (separator);

	int k = 0;
	while (k < element.length ())
	  {
	    String special = isSpecial (element, k);
	    if (special != null)
	      {
		result.append (escape);
		result.append (special);
		k += special.length ();
	      }
	    else
	      {
		result.append (element.charAt (k));
		++k;
	      }
	  }
      }

    return result.toString ();
  }

  // This canonicalizes a String, based on the syntax, for comparison
  // or other similar purposes.
  private String canonicalize (String element)
  {
    String ret = element;

    if (ignoreCase)
      ret = ret.toLowerCase ();

    if (trimBlanks)
      {
	int first = 0;
	while (first < ret.length ()
	       && Character.isWhitespace (ret.charAt (first)))
	  ++first;

	int last = ret.length () - 1;
	while (last >= first
	       && Character.isWhitespace (ret.charAt (last)))
	  --last;

	ret = ret.substring (first, last);
      }

    return ret;
  }

  // This initializes all the syntax variables.  This seems easier
  // than re-querying the properties every time.  We're allowed to do
  // this because the spec says that subclasses should consider the
  // syntax as being read-only.
  private void initializeSyntax ()
  {
    String t = mySyntax.getProperty ("jndi.syntax.direction", "flat");
    if (t.equals ("right_to_left"))
      this.direction = RIGHT_TO_LEFT;
    else if (t.equals ("left_to_right"))
      this.direction = LEFT_TO_RIGHT;
    else
      {
	// If we don't recognize it, default to flat.
	this.direction = FLAT;
      }

    // This is required unless the direction is FLAT.  Unfortunately
    // there is no way to report this error.
    this.separator = mySyntax.getProperty ("jndi.syntax.separator", "");

    this.ignoreCase
      = Boolean.valueOf (mySyntax.getProperty ("jndi.syntax.ignorecase",
					       "false")).booleanValue ();
    this.escape = mySyntax.getProperty ("jndi.syntax.escape", null);
    this.beginQuote = mySyntax.getProperty ("jndi.syntax.beginquote", null);
    this.endQuote = mySyntax.getProperty ("jndi.syntax.endquote",
					  this.beginQuote);
    this.beginQuote2 = mySyntax.getProperty ("jndi.syntax.beginquote2",
					     null);
    this.endQuote2 = mySyntax.getProperty ("jndi.syntax.endquote2",
					   this.beginQuote2);
    this.trimBlanks
      = Boolean.valueOf (mySyntax.getProperty ("jndi.syntax.trimblanks",
					       "false")).booleanValue ();
  }

  // The spec specifies this but does not document it in any way (it
  // is a package-private class).  It is useless as far as I can tell.
  // So we ignore it.
  // protected transient NameImpl impl;
  protected transient Properties mySyntax;

  // The actual elements.
  private transient Vector elts;

  // The following are all used for syntax.
  private transient int direction;
  private transient String separator;
  private transient boolean ignoreCase;
  private transient String escape;
  private transient String beginQuote;
  private transient String endQuote;
  private transient String beginQuote2;
  private transient String endQuote2;
  private transient boolean trimBlanks;
  // We didn't need these for parsing, so they are gone.
  // private transient String avaSeparator;
  // private transient String typevalSeparator;

  private static final int RIGHT_TO_LEFT = -1;
  private static final int LEFT_TO_RIGHT = 1;
  private static final int FLAT = 0;
}
