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;
  
  /**
   * This class represents an element type in the schema. An element type has a
   * name, a content model vector, a member-of vector, a flags vector, default
   * attributes, and a schema to which it belongs.
   *
   * @see Schema
   */
  
  public class ElementType {
  
      private String theName; // element type name (Qname)
      private String theNamespace; // element type namespace name
      private String theLocalName; // element type local name
      private int theModel; // bitmap: what the element contains
      private int theMemberOf; // bitmap: what element is contained in
      private int theFlags; // bitmap: element flags
      private AttributesImpl theAtts; // default attributes
      private ElementType theParent; // parent of this element type
      private Schema theSchema; // schema to which this belongs
  
      /**
       * Construct an ElementType: but it's better to use Schema.element()
       * instead. The content model, member-of, and flags vectors are specified as
       * ints.
       *
       * @param name     The element type name
       * @param model    ORed-together bits representing the content models allowed in
       *                 the content of this element type
       * @param memberOf ORed-together bits representing the content models to which
       *                 this element type belongs
       * @param flags    ORed-together bits representing the flags associated with this
       *                 element type
       * @param schema   The schema with which this element type will be associated
       */
  
      public ElementType(String name, int model, int memberOf, int flags,
                         Schema schema) {
          theName = name;
          theModel = model;
          theMemberOf = memberOf;
          theFlags = flags;
          theAtts = new AttributesImpl();
          theSchema = schema;
          theNamespace = namespace(name, false);
          theLocalName = localName(name);
      }
  
      /**
       * Return a namespace name from a Qname. The attribute flag tells us whether
       * to return an empty namespace name if there is no prefix, or use the
       * schema default instead.
       *
       * @param name      The Qname
       * @param attribute True if name is an attribute name
       * @return The namespace name
       */
      public String namespace(String name, boolean attribute) {
          int colon = name.indexOf(':');
          if (colon == -1) {
              return attribute ? "" : theSchema.getURI();
          }
          String prefix = name.substring(0, colon);
          if (prefix.equals("xml")) {
              return "http://www.w3.org/XML/1998/namespace";
          } else {
              return ("urn:x-prefix:" + prefix).intern();
          }
      }
  
      /**
       * Return a local name from a Qname.
       *
       * @param name The Qname
       * @return The local name
       */
      public String localName(String name) {
          int colon = name.indexOf(':');
          if (colon == -1) {
              return name;
          } else {
              return name.substring(colon + 1).intern();
          }
      }
  
      /**
       * Returns the name of this element type.
       *
       * @return The name of the element type
       */
  
      public String name() {
          return theName;
      }
  
      /**
       * Returns the namespace name of this element type.
       *
       * @return The namespace name of the element type
       */
  
      public String namespace() {
          return theNamespace;
      }
  
      /**
       * Returns the local name of this element type.
       *
       * @return The local name of the element type
       */
  
      public String localName() {
          return theLocalName;
      }
  
      /**
       * Returns the content models of this element type.
       *
       * @return The content models of this element type as a vector of bits
       */
  
      public int model() {
          return theModel;
      }
  
      /**
       * Returns the content models to which this element type belongs.
       *
       * @return The content models to which this element type belongs as a vector
       * of bits
       */
  
      public int memberOf() {
          return theMemberOf;
      }
  
      /**
       * Returns the flags associated with this element type.
       *
       * @return The flags associated with this element type as a vector of bits
       */
  
      public int flags() {
          return theFlags;
      }
  
      /**
       * Returns the default attributes associated with this element type.
       * Attributes of type CDATA that don't have default values are typically not
       * included. Other attributes without default values have an internal value
       * of <tt>null</tt>. The return value is an AttributesImpl to allow the
       * caller to mutate the attributes.
       */
  
      public AttributesImpl atts() {
          return theAtts;
      }
  
      /**
       * Returns the parent element type of this element type.
       *
       * @return The parent element type
       */
  
      public ElementType parent() {
          return theParent;
      }
  
      /**
       * Returns the schema which this element type is associated with.
       *
       * @return The schema
       */
  
      public Schema schema() {
          return theSchema;
      }
  
      /**
       * Returns true if this element type can contain another element type. That
       * is, if any of the models in this element's model vector match any of the
       * models in the other element type's member-of vector.
       *
       * @param other The other element type
       */
  
      public boolean canContain(ElementType other) {
          return (theModel & other.theMemberOf) != 0;
      }
  
      /**
       * Sets an attribute and its value into an AttributesImpl object. Attempts
       * to set a namespace declaration are ignored.
       *
       * @param atts  The AttributesImpl object
       * @param name  The name (Qname) of the attribute
       * @param type  The type of the attribute
       * @param value The value of the attribute
       */
  
      public void setAttribute(AttributesImpl atts, String name, String type,
                               String value) {
          if (name.equals("xmlns") || name.startsWith("xmlns:")) {
              return;
          }
          ;
          String namespace = namespace(name, true);
          String localName = localName(name);
          int i = atts.getIndex(name);
          if (i == -1) {
              name = name.intern();
              if (type == null)
                  type = "CDATA";
              if (!type.equals("CDATA"))
                  value = normalize(value);
              atts.addAttribute(namespace, localName, name, type, value);
          } else {
              if (type == null)
                  type = atts.getType(i);
              if (!type.equals("CDATA"))
                  value = normalize(value);
              atts.setAttribute(i, namespace, localName, name, type, value);
          }
      }
  
      /**
       * Normalize an attribute value (ID-style). CDATA-style attribute
       * normalization is already done.
       *
       * @param value The value to normalize
       * @return The normalized value
       */
      public static String normalize(String value) {
          if (value == null)
              return value;
          value = value.trim();
          if (value.indexOf("  ") == -1)
              return value;
          boolean space = false;
          int len = value.length();
          StringBuffer b = new StringBuffer(len);
          for (int i = 0; i < len; i++) {
              char v = value.charAt(i);
              if (v == ' ') {
                  if (!space)
                      b.append(v);
                  space = true;
              } else {
                  b.append(v);
                  space = false;
              }
          }
          return b.toString();
      }
  
      /**
       * Sets an attribute and its value into this element type.
       *
       * @param name  The name of the attribute
       * @param type  The type of the attribute
       * @param value The value of the attribute
       */
  
      public void setAttribute(String name, String type, String value) {
          setAttribute(theAtts, name, type, value);
      }
  
      /**
       * Sets the models of this element type.
       *
       * @param model The content models of this element type as a vector of bits
       */
  
      public void setModel(int model) {
          theModel = model;
      }
  
      /**
       * Sets the content models to which this element type belongs.
       *
       * @param memberOf The content models to which this element type belongs as a
       *                 vector of bits
       */
  
      public void setMemberOf(int memberOf) {
          theMemberOf = memberOf;
      }
  
      /**
       * Sets the flags of this element type.
       *
       * @param flags associated with this element type The flags as a vector of
       *              bits
       */
  
      public void setFlags(int flags) {
          theFlags = flags;
      }
  
      /**
       * Sets the parent element type of this element type.
       *
       * @param parent The parent element type
       */
  
      public void setParent(ElementType parent) {
          theParent = parent;
      }
  
  }