blob: c6f9f6f57415cc150aead25d7bf72f8e7f4d9b5f [file] [log] [blame]
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2003 The Apache Software Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xalan" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 2003, International Business
* Machines, Inc., http://www.ibm.com. For more information on the Apache
* Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.xml.serializer;
import java.util.Hashtable;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.AttributesImpl;
/**
* This class extends org.xml.sax.helpers.AttributesImpl which implements org.
* xml.sax.Attributes. But for optimization this class adds a Hashtable for
* faster lookup of an index by qName, which is commonly done in the stream
* serializer.
*
* @see org.xml.sax.Attributes
*/
public class AttributesImplSerializer extends AttributesImpl
{
/**
* Hash table of qName/index values to quickly lookup the index
* of an attributes qName. qNames are in uppercase in the hash table
* to make the search case insensitive.
*/
private Hashtable m_indexFromQName = new Hashtable();
/**
* This is the number of attributes before switching to the hash table,
* and can be tuned, but 12 seems good for now - bjm
*/
public static final int MAX = 12;
/**
* One less than the number of attributes before switching to
* the Hashtable.
*/
private static final int MAXMinus1 = MAX - 1;
/**
* This method gets the index of an attribute given its qName.
* @param qname the qualified name of the attribute, e.g. "prefix1:locName1"
* @return the integer index of the attribute.
* @see org.xml.sax.Attributes#getIndex(String)
*/
public int getIndex(String qname)
{
int index;
if (super.getLength() < MAX)
{
// if we haven't got too many attributes let the
// super class look it up
index = super.getIndex(qname);
return index;
}
// we have too many attributes and the super class is slow
// so find it quickly using our Hashtable.
Integer i = (Integer)m_indexFromQName.get(qname);
if (i == null)
index = -1;
else
index = i.intValue();
return index;
}
/**
* This method adds the attribute, but also records its qName/index pair in
* the hashtable for fast lookup by getIndex(qName).
* @param uri the URI of the attribute
* @param local the local name of the attribute
* @param qname the qualified name of the attribute
* @param type the type of the attribute
* @param val the value of the attribute
*
* @see org.xml.sax.helpers.AttributesImpl#addAttribute(String, String, String, String, String)
* @see #getIndex(String)
*/
public void addAttribute(
String uri,
String local,
String qname,
String type,
String val)
{
int index = super.getLength();
super.addAttribute(uri, local, qname, type, val);
// (index + 1) is now the number of attributes
// so either compare (index+1) to MAX, or compare index to (MAX-1)
if (index < MAXMinus1)
{
return;
}
else if (index == MAXMinus1)
{
switchOverToHash(MAX);
}
else
{
/* we have just added the attibute, its index is the old length */
Integer i = new Integer(index);
m_indexFromQName.put(qname, i);
}
return;
}
/**
* We are switching over to having a hash table for quick look
* up of attributes, but up until now we haven't kept any
* information in the Hashtable, so we now update the Hashtable.
* Future additional attributes will update the Hashtable as
* they are added.
* @param numAtts
*/
private void switchOverToHash(int numAtts)
{
for (int index = 0; index < numAtts; index++)
{
String qName = super.getQName(index);
Integer i = new Integer(index);
m_indexFromQName.put(qName, i);
}
}
/**
* This method clears the accumulated attributes.
*
* @see org.xml.sax.helpers.AttributesImpl#clear()
*/
public void clear()
{
int len = super.getLength();
super.clear();
if (MAX <= len)
{
// if we have had enough attributes and are
// using the Hashtable, then clear the Hashtable too.
m_indexFromQName.clear();
}
}
/**
* This method sets the attributes, previous attributes are cleared,
* it also keeps the hashtable up to date for quick lookup via
* getIndex(qName).
* @param atts the attributes to copy into these attributes.
* @see org.xml.sax.helpers.AttributesImpl#setAttributes(Attributes)
* @see #getIndex(String)
*/
public void setAttributes(Attributes atts)
{
super.setAttributes(atts);
// we've let the super class add the attributes, but
// we need to keep the hash table up to date ourselves for the
// potentially new qName/index pairs for quick lookup.
int numAtts = atts.getLength();
if (MAX <= numAtts)
switchOverToHash(numAtts);
}
}