Home » xmlbeans-2.5.0-src » org.apache » xmlbeans » [javadoc | source]

    1   /*   Copyright 2004 The Apache Software Foundation
    2    *
    3    *   Licensed under the Apache License, Version 2.0 (the "License");
    4    *   you may not use this file except in compliance with the License.
    5    *   You may obtain a copy of the License at
    6    *
    7    *       http://www.apache.org/licenses/LICENSE-2.0
    8    *
    9    *   Unless required by applicable law or agreed to in writing, software
   10    *   distributed under the License is distributed on an "AS IS" BASIS,
   11    *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   12    *   See the License for the specific language governing permissions and
   13    *  limitations under the License.
   14    */
   15   
   16   package org.apache.xmlbeans;
   17   
   18   import javax.xml.namespace.QName;
   19   
   20   /**
   21    * A cache that can be used to pool QName instances.  Each thread has one.
   22    */ 
   23   public final class QNameCache
   24   {
   25       private static final float DEFAULT_LOAD = 0.70f;
   26       private final float loadFactor;
   27       private int numEntries = 0;
   28       private int threshold;
   29       private int hashmask;
   30       private QName[] table;
   31   
   32       /**
   33        * Creates a QNameCache with the given initialCapacity and loadFactor.
   34        * 
   35        * @param initialCapacity the number of entries to initially make space for
   36        * @param loadFactor a number to control the density of the hashtable
   37        */ 
   38       public QNameCache(int initialCapacity, float loadFactor)
   39       {
   40           assert initialCapacity > 0;
   41           assert loadFactor > 0 && loadFactor < 1;
   42   
   43           // Find a power of 2 >= initialCapacity
   44           int capacity = 16;
   45           while (capacity < initialCapacity) 
   46               capacity <<= 1;
   47       
   48           this.loadFactor = loadFactor;
   49           this.hashmask = capacity - 1;
   50           threshold = (int)(capacity * loadFactor);
   51           table = new QName[capacity];
   52       }
   53   
   54       /**
   55        * Creates a QNameCache with the given initialCapacity.
   56        * 
   57        * @param initialCapacity the number of entries to initially make space for
   58        */ 
   59       public QNameCache(int initialCapacity)
   60       {
   61           this(initialCapacity, DEFAULT_LOAD);
   62       }
   63   
   64       public QName getName(String uri, String localName)
   65       {
   66           return getName( uri, localName, "" );
   67       }
   68       
   69       /**
   70        * Fetches a QName with the given namespace and localname.
   71        * Creates one if one is not found in the cache.
   72        * 
   73        * @param uri the namespace
   74        * @param localName the localname
   75        * @param prefix the prefix
   76        * @return the cached QName
   77        */ 
   78       public QName getName(String uri, String localName, String prefix)
   79       {
   80           /*
   81           return new QName(uri, localName, prefix);
   82           */
   83           assert localName != null;
   84           
   85           if (uri == null) uri = "";
   86           if (prefix == null) prefix = "";
   87   
   88           int index = hash(uri, localName, prefix) & hashmask;
   89           while (true) {
   90               QName q = table[index];
   91               if (q == null)
   92               {
   93                   numEntries++;
   94                   if (numEntries >= threshold)
   95                       rehash();
   96   
   97                   return table[index] = new QName(uri, localName, prefix);
   98               }
   99               else if (equals(q, uri, localName, prefix))
  100                   return q;
  101               else 
  102                   index = (index-1) & hashmask;
  103           }
  104       }
  105   
  106       private void rehash()
  107       {
  108           int newLength = table.length * 2;
  109           QName[] newTable = new QName[newLength];
  110           int newHashmask = newLength - 1;
  111   
  112           for (int i = 0 ; i < table.length ; i++)
  113           {
  114               QName q = table[i];
  115               if (q != null)
  116               {
  117                   int newIndex =
  118                       hash( q.getNamespaceURI(), q.getLocalPart(), q.getPrefix() ) & newHashmask;
  119                   
  120                   while (newTable[newIndex] != null)
  121                       newIndex = (newIndex - 1) & newHashmask;
  122                   
  123                   newTable[newIndex] = q;
  124               }
  125           }
  126   
  127           table = newTable;
  128           hashmask = newHashmask;
  129           threshold = (int) (newLength * loadFactor);
  130       }
  131       
  132       private static int hash(String uri, String localName, String prefix)
  133       {
  134           int h = 0;
  135   
  136           h += prefix.hashCode() << 10;
  137           h += uri.hashCode() << 5;
  138           h += localName.hashCode();
  139   
  140           return h;
  141       }
  142   
  143       private static boolean equals(QName q, String uri, String localName, String prefix)
  144       {
  145           return
  146               q.getLocalPart().equals(localName) &&
  147                   q.getNamespaceURI().equals(uri) &&
  148                       q.getPrefix().equals(prefix);
  149       }
  150   }

Home » xmlbeans-2.5.0-src » org.apache » xmlbeans » [javadoc | source]