content: // This file is part of TagSoup and is Copyright 2002-2008 by John Cowan.
  //
  // TagSoup is licensed under the Apache License,
  // Version 2.0.  You may obtain a copy of this license at
  // http://www.apache.org/licenses/LICENSE-2.0 .  You may also have
  // additional legal rights not granted by this license.
  //
  // TagSoup is distributed in the hope that it will be useful, but
  // unless required by applicable law or agreed to in writing, TagSoup
  // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
  // OF ANY KIND, either express or implied; not even the implied warranty
  // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  
  package com.onegravity.rteditor.converter.tagsoup;
  
  /**
   * The internal representation of an actual element (not an element type). An
   * Element has an element type, attributes, and a successor Element for use in
   * constructing stacks and queues of Elements.
   *
   * @see ElementType
   * @see AttributesImpl
   */
  public class Element {
  
      private ElementType theType; // type of element
      private AttributesImpl theAtts; // attributes of element
      private Element theNext; // successor of element
      private boolean preclosed; // this element has been preclosed
  
      /**
       * Return an Element from a specified ElementType.
       *
       * @param type              The element type of the newly constructed element
       * @param defaultAttributes True if default attributes are wanted
       */
  
      public Element(ElementType type, boolean defaultAttributes) {
          theType = type;
          if (defaultAttributes)
              theAtts = new AttributesImpl(type.atts());
          else
              theAtts = new AttributesImpl();
          theNext = null;
          preclosed = false;
      }
  
      /**
       * Return the element type.
       *
       * @return The element type.
       */
  
      public ElementType type() {
          return theType;
      }
  
      /**
       * Return the attributes as an AttributesImpl object. Returning an
       * AttributesImpl makes the attributes mutable.
       *
       * @return The attributes
       * @see AttributesImpl
       */
      public AttributesImpl atts() {
          return theAtts;
      }
  
      /**
       * Return the next element in an element stack or queue.
       *
       * @return The next element
       */
  
      public Element next() {
          return theNext;
      }
  
      /**
       * Change the next element in an element stack or queue.
       *
       * @param next The new next element
       */
  
      public void setNext(Element next) {
          theNext = next;
      }
  
      /**
       * Return the name of the element's type. Convenience method.
       *
       * @return The element type name
       */
  
      public String name() {
          return theType.name();
      }
  
      /**
       * Return the namespace name of the element's type. Convenience method.
       *
       * @return The element type namespace name
       */
  
      public String namespace() {
          return theType.namespace();
      }
  
      /**
       * Return the local name of the element's type. Convenience method.
       *
       * @return The element type local name
       */
  
      public String localName() {
          return theType.localName();
      }
  
      /**
       * Return the content model vector of the element's type. Convenience
       * method.
       *
       * @return The content model vector
       */
  
      public int model() {
          return theType.model();
      }
  
      /**
       * Return the member-of vector of the element's type. Convenience method.
       *
       * @return The member-of vector
       */
  
      public int memberOf() {
          return theType.memberOf();
      }
  
      /**
       * Return the flags vector of the element's type. Convenience method.
       *
       * @return The flags vector
       */
  
      public int flags() {
          return theType.flags();
      }
  
      /**
       * Return the parent element type of the element's type. Convenience method.
       *
       * @return The parent element type
       */
  
      public ElementType parent() {
          return theType.parent();
      }
  
      /**
       * Return true if the type of this element can contain the type of another
       * element. Convenience method.
       *
       * @param other The other element
       */
  
      public boolean canContain(Element other) {
          return theType.canContain(other.theType);
      }
  
      /**
       * Set an attribute and its value into this element.
       *
       * @param name  The attribute name (Qname)
       * @param type  The attribute type
       * @param value The attribute value
       */
  
      public void setAttribute(String name, String type, String value) {
          theType.setAttribute(theAtts, name, type, value);
      }
  
      /**
       * Make this element anonymous. Remove any <tt>id</tt> or <tt>name</tt>
       * attribute present in the element's attributes.
       */
  
      public void anonymize() {
          for (int i = theAtts.getLength() - 1; i >= 0; i--) {
              if (theAtts.getType(i).equals("ID")
                      || theAtts.getQName(i).equals("name")) {
                  theAtts.removeAttribute(i);
              }
          }
      }
  
      /**
       * Clean the attributes of this element. Attributes with null name (the name
       * was ill-formed) or null value (the attribute was present in the element
       * type but not in this actual element) are removed.
       */
  
      public void clean() {
          for (int i = theAtts.getLength() - 1; i >= 0; i--) {
              String name = theAtts.getLocalName(i);
              if (theAtts.getValue(i) == null || name == null
                      || name.length() == 0) {
                  theAtts.removeAttribute(i);
                  continue;
              }
          }
      }
  
      /**
       * Force this element to preclosed status, meaning that an end-tag has been
       * seen but the element cannot yet be closed for structural reasons.
       */
  
      public void preclose() {
          preclosed = true;
      }
  
      /**
       * Return true if this element has been preclosed.
       */
  
      public boolean isPreclosed() {
          return preclosed;
      }
  
  }