/* DomText.java --
   Copyright (C) 1999, 2000, 2001, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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 gnu.xml.dom;

import gnu.java.lang.CPStringBuilder;

import org.w3c.dom.DOMException;
import org.w3c.dom.Text;

/**
 * <p> "Text" implementation.  </p>
 *
 * @author David Brownell
 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
 */
public class DomText
  extends DomCharacterData
  implements Text
{

  // NOTE:  deleted unused per-instance "isIgnorable"
  // support to reclaim its space.

  /**
   * Constructs a text node associated with the specified
   * document and holding the specified data.
   *
   * <p>This constructor should only be invoked by a Document object
   * as part of its createTextNode functionality, or through a subclass
   * which is similarly used in a "Sub-DOM" style layer.
   */
  protected DomText(DomDocument owner, String value)
  {
    super(TEXT_NODE, owner, value);
  }

  protected DomText(DomDocument owner, char[] buf, int off, int len)
  {
    super(TEXT_NODE, owner, buf, off, len);
  }

  // Used by DomCDATA
  DomText(short nodeType, DomDocument owner, String value)
  {
    super(nodeType, owner, value);
  }

  DomText(short nodeType, DomDocument owner, char[] buf, int off, int len)
  {
    super(nodeType, owner, buf, off, len);
  }

  /**
   * <b>DOM L1</b>
   * Returns the string "#text".
   */
  // can't be 'final' with CDATA subclassing
  public String getNodeName()
  {
    return "#text";
  }

  /**
   * <b>DOM L1</b>
   * Splits this text node in two parts at the offset, returning
   * the new text node (the sibling with the second part).
   */
  public Text splitText(int offset)
  {
    if (isReadonly())
      {
        throw new DomDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR);
      }
    try
      {
        String text = getNodeValue();
        String before = text.substring(0, offset);
        String after = text.substring(offset);
        Text next;

        if (getNodeType() == TEXT_NODE)
          {
            next = owner.createTextNode(after);
          }
        else // CDATA_SECTION_NODE
          {
            next = owner.createCDATASection(after);
          }

        if (this.next != null)
          {
            parent.insertBefore(next, this.next);
          }
        else
          {
            parent.appendChild(next);
          }
        setNodeValue(before);
        return next;

      }
    catch (IndexOutOfBoundsException x)
      {
        throw new DomDOMException(DOMException.INDEX_SIZE_ERR);
      }
  }

  // DOM Level 3

  public boolean isElementContentWhitespace()
  {
    if (parent != null)
      {
        DomDoctype doctype = (DomDoctype) owner.getDoctype();
        if (doctype != null)
          {
            DTDElementTypeInfo info =
              doctype.getElementTypeInfo(parent.getNodeName());
            if (info != null)
              {
                if (info.model == null && info.model.indexOf("#PCDATA") != -1)
                  {
                    return false;
                  }
                return getNodeValue().trim().length() == 0;
              }
          }
      }
    return false;
  }

  public String getWholeText()
  {
    DomNode ref = this;
    DomNode ctx;
    for (ctx = previous; ctx != null &&
         (ctx.nodeType == TEXT_NODE || ctx.nodeType == CDATA_SECTION_NODE);
         ctx = ctx.previous)
      {
        ref = ctx;
      }
    CPStringBuilder buf = new CPStringBuilder(ref.getNodeValue());
    for (ctx = ref.next; ctx != null &&
         (ctx.nodeType == TEXT_NODE || ctx.nodeType == CDATA_SECTION_NODE);
         ctx = ctx.next)
      {
        buf.append(ctx.getNodeValue());
      }
    return buf.toString ();
  }

  public Text replaceWholeText(String content)
    throws DOMException
  {
    boolean isEmpty = (content == null || content.length () == 0);
    if (!isEmpty)
      {
        setNodeValue(content);
      }

    DomNode ref = this;
    DomNode ctx;
    for (ctx = previous; ctx != null &&
         (ctx.nodeType == TEXT_NODE || ctx.nodeType == CDATA_SECTION_NODE);
         ctx = ctx.previous)
      {
        ref = ctx;
      }
    ctx = ref.next;
    if ((isEmpty || ref != this) && parent != null)
      {
        parent.removeChild(ref);
      }
    for (; ctx != null &&
         (ctx.nodeType == TEXT_NODE || ctx.nodeType == CDATA_SECTION_NODE);
         ctx = ref)
      {
        ref = ctx.next;
        if ((isEmpty || ctx != this) && parent != null)
          {
            parent.removeChild(ctx);
          }
      }
    return (isEmpty) ? null : this;
  }

}
