expandednametable.java

来自「JAVA 所有包」· Java 代码 · 共 390 行

JAVA
390
字号
/* * Copyright 1999-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * $Id: ExpandedNameTable.java,v 1.2.4.1 2005/09/15 08:15:06 suresh_emailid Exp $ */package com.sun.org.apache.xml.internal.dtm.ref;import com.sun.org.apache.xml.internal.dtm.DTM;/** * This is a default implementation of a table that manages mappings from * expanded names to expandedNameIDs. * * %OPT% The performance of the getExpandedTypeID() method is very important  * to DTM building. To get the best performance out of this class, we implement * a simple hash algorithm directly into this class, instead of using the * inefficient java.util.Hashtable. The code for the get and put operations * are combined in getExpandedTypeID() method to share the same hash calculation * code. We only need to implement the rehash() interface which is used to * expand the hash table. */public class ExpandedNameTable{  /** Array of extended types for this document   */  private ExtendedType[] m_extendedTypes;  /** The initial size of the m_extendedTypes array */  private static int m_initialSize = 128;    /** Next available extended type   */  // %REVIEW% Since this is (should be) always equal   // to the length of m_extendedTypes, do we need this?   private int m_nextType;  // These are all the types prerotated, for caller convenience.  public static final int ELEMENT = ((int)DTM.ELEMENT_NODE) ;  public static final int ATTRIBUTE = ((int)DTM.ATTRIBUTE_NODE) ;  public static final int TEXT = ((int)DTM.TEXT_NODE) ;  public static final int CDATA_SECTION = ((int)DTM.CDATA_SECTION_NODE) ;  public static final int ENTITY_REFERENCE = ((int)DTM.ENTITY_REFERENCE_NODE) ;  public static final int ENTITY = ((int)DTM.ENTITY_NODE) ;  public static final int PROCESSING_INSTRUCTION = ((int)DTM.PROCESSING_INSTRUCTION_NODE) ;  public static final int COMMENT = ((int)DTM.COMMENT_NODE) ;  public static final int DOCUMENT = ((int)DTM.DOCUMENT_NODE) ;  public static final int DOCUMENT_TYPE = ((int)DTM.DOCUMENT_TYPE_NODE) ;  public static final int DOCUMENT_FRAGMENT =((int)DTM.DOCUMENT_FRAGMENT_NODE) ;  public static final int NOTATION = ((int)DTM.NOTATION_NODE) ;  public static final int NAMESPACE = ((int)DTM.NAMESPACE_NODE) ;  /** Workspace for lookup. NOT THREAD SAFE!   * */  ExtendedType hashET = new ExtendedType(-1, "", "");  /** The array to store the default extended types. */  private static ExtendedType[] m_defaultExtendedTypes;  /**   * The default load factor of the Hashtable.   * This is used to calcualte the threshold.   */  private static float m_loadFactor = 0.75f;      /**   * The initial capacity of the hash table. Use a bigger number   * to avoid the cost of expanding the table.   */   private static int m_initialCapacity = 203;    /**   * The capacity of the hash table, i.e. the size of the   * internal HashEntry array.   */   private int m_capacity;    /**    * The threshold of the hash table, which is equal to capacity * loadFactor.   * If the number of entries in the hash table is bigger than the threshold,   * the hash table needs to be expanded.   */  private int m_threshold;    /**   * The internal array to store the hash entries.   * Each array member is a slot for a hash bucket.   */  private HashEntry[] m_table;  /**   * Init default values   */  static {    m_defaultExtendedTypes = new ExtendedType[DTM.NTYPES];    for (int i = 0; i < DTM.NTYPES; i++)    {      m_defaultExtendedTypes[i] = new ExtendedType(i, "", "");    }  }  /**   * Create an expanded name table.   */  public ExpandedNameTable()  {    m_capacity = m_initialCapacity;    m_threshold = (int)(m_capacity * m_loadFactor);    m_table = new HashEntry[m_capacity];        initExtendedTypes();  }  /**   *  Initialize the vector of extended types with the   *  basic DOM node types.   */  private void initExtendedTypes()  {        m_extendedTypes = new ExtendedType[m_initialSize];    for (int i = 0; i < DTM.NTYPES; i++) {        m_extendedTypes[i] = m_defaultExtendedTypes[i];        m_table[i] = new HashEntry(m_defaultExtendedTypes[i], i, i, null);    }        m_nextType = DTM.NTYPES;  }  /**   * Given an expanded name represented by namespace, local name and node type,   * return an ID.  If the expanded-name does not exist in the internal tables,   * the entry will be created, and the ID will be returned.  Any additional    * nodes that are created that have this expanded name will use this ID.   *   * @param namespace The namespace   * @param localName The local name   * @param type The node type   *   * @return the expanded-name id of the node.   */  public int getExpandedTypeID(String namespace, String localName, int type)  {    return getExpandedTypeID(namespace, localName, type, false);  }    /**   * Given an expanded name represented by namespace, local name and node type,   * return an ID.  If the expanded-name does not exist in the internal tables,   * the entry will be created, and the ID will be returned.  Any additional    * nodes that are created that have this expanded name will use this ID.   * <p>   * If searchOnly is true, we will return -1 if the name is not found in the    * table, otherwise the name is added to the table and the expanded name id   * of the new entry is returned.   *   * @param namespace The namespace   * @param localName The local name   * @param type The node type   * @param searchOnly If it is true, we will only search for the expanded name.   * -1 is return is the name is not found.   *   * @return the expanded-name id of the node.   */  public int getExpandedTypeID(String namespace, String localName, int type, boolean searchOnly)  {    if (null == namespace)      namespace = "";    if (null == localName)      localName = "";        // Calculate the hash code    int hash = type + namespace.hashCode() + localName.hashCode();        // Redefine the hashET object to represent the new expanded name.    hashET.redefine(type, namespace, localName, hash);        // Calculate the index into the HashEntry table.    int index = hash % m_capacity;    if (index < 0)      index = -index;    // Look up the expanded name in the hash table. Return the id if    // the expanded name is already in the hash table.    for (HashEntry e = m_table[index]; e != null; e = e.next)    {      if (e.hash == hash && e.key.equals(hashET))        return e.value;    }        if (searchOnly)    {      return DTM.NULL;    }    // Expand the internal HashEntry array if necessary.    if (m_nextType > m_threshold) {      rehash();      index = hash % m_capacity;      if (index < 0)        index = -index;    }        // Create a new ExtendedType object    ExtendedType newET = new ExtendedType(type, namespace, localName, hash);        // Expand the m_extendedTypes array if necessary.    if (m_extendedTypes.length == m_nextType) {        ExtendedType[] newArray = new ExtendedType[m_extendedTypes.length * 2];        System.arraycopy(m_extendedTypes, 0, newArray, 0,                         m_extendedTypes.length);        m_extendedTypes = newArray;    }        m_extendedTypes[m_nextType] = newET;        // Create a new hash entry for the new ExtendedType and put it into     // the table.    HashEntry entry = new HashEntry(newET, m_nextType, hash, m_table[index]);    m_table[index] = entry;    return m_nextType++;  }  /**   * Increases the capacity of and internally reorganizes the hashtable,    * in order to accommodate and access its entries more efficiently.    * This method is called when the number of keys in the hashtable exceeds   * this hashtable's capacity and load factor.   */  private void rehash()  {    int oldCapacity = m_capacity;    HashEntry[] oldTable = m_table;          int newCapacity = 2 * oldCapacity + 1;    m_capacity = newCapacity;    m_threshold = (int)(newCapacity * m_loadFactor);          m_table = new HashEntry[newCapacity];    for (int i = oldCapacity-1; i >=0 ; i--)    {      for (HashEntry old = oldTable[i]; old != null; )      {        HashEntry e = old;        old = old.next;                  int newIndex = e.hash % newCapacity;        if (newIndex < 0)          newIndex = -newIndex;                  e.next = m_table[newIndex];        m_table[newIndex] = e;      }    }  }  /**   * Given a type, return an expanded name ID.Any additional nodes that are   * created that have this expanded name will use this ID.   *   * @return the expanded-name id of the node.   */  public int getExpandedTypeID(int type)  {    return type;  }  /**   * Given an expanded-name ID, return the local name part.   *   * @param ExpandedNameID an ID that represents an expanded-name.   * @return String Local name of this node, or null if the node has no name.   */  public String getLocalName(int ExpandedNameID)  {    return m_extendedTypes[ExpandedNameID].getLocalName();  }  /**   * Given an expanded-name ID, return the local name ID.   *   * @param ExpandedNameID an ID that represents an expanded-name.   * @return The id of this local name.   */  public final int getLocalNameID(int ExpandedNameID)  {    // ExtendedType etype = m_extendedTypes[ExpandedNameID];    if (m_extendedTypes[ExpandedNameID].getLocalName().equals(""))      return 0;    else    return ExpandedNameID;  }  /**   * Given an expanded-name ID, return the namespace URI part.   *   * @param ExpandedNameID an ID that represents an expanded-name.   * @return String URI value of this node's namespace, or null if no   * namespace was resolved.   */  public String getNamespace(int ExpandedNameID)  {    String namespace = m_extendedTypes[ExpandedNameID].getNamespace();    return (namespace.equals("") ? null : namespace);  }  /**   * Given an expanded-name ID, return the namespace URI ID.   *   * @param ExpandedNameID an ID that represents an expanded-name.   * @return The id of this namespace.   */  public final int getNamespaceID(int ExpandedNameID)  {    //ExtendedType etype = m_extendedTypes[ExpandedNameID];    if (m_extendedTypes[ExpandedNameID].getNamespace().equals(""))      return 0;    else    return ExpandedNameID;  }  /**   * Given an expanded-name ID, return the local name ID.   *   * @param ExpandedNameID an ID that represents an expanded-name.   * @return The id of this local name.   */  public final short getType(int ExpandedNameID)  {    //ExtendedType etype = m_extendedTypes[ExpandedNameID];    return (short)m_extendedTypes[ExpandedNameID].getNodeType();  }    /**   * Return the size of the ExpandedNameTable   *   * @return The size of the ExpandedNameTable   */  public int getSize()  {    return m_nextType;  }    /**   * Return the array of extended types   *   * @return The array of extended types   */  public ExtendedType[] getExtendedTypes()  {    return m_extendedTypes;  }  /**   * Inner class which represents a hash table entry.   * The field next points to the next entry which is hashed into   * the same bucket in the case of "hash collision".   */  private static final class HashEntry  {    ExtendedType key;    int value;    int hash;    HashEntry next;          protected HashEntry(ExtendedType key, int value, int hash, HashEntry next)    {      this.key = key;      this.value = value;      this.hash = hash;      this.next = next;    }  }  }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?