code: /*
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements. See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership. The ASF licenses this file
   * to you 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$
   */
  
  package org.apache.xalan.xsltc.runtime;
  
  import java.util.Vector;
  
  /**
   * @author Morten Jorgensen
   */
  public class AttributeList implements org.xml.sax.Attributes {
  
      private final static String EMPTYSTRING = "";
      private final static String CDATASTRING = "CDATA";
  
      private Hashtable _attributes;
      private Vector    _names;
      private Vector    _qnames;
      private Vector    _values;
      private Vector    _uris;
      private int       _length;
  
      /**
       * AttributeList constructor
       */
      public AttributeList() {
  	/*
  	_attributes = new Hashtable();
  	_names  = new Vector();
  	_values = new Vector();
  	_qnames = new Vector();
  	_uris   = new Vector();
  	*/
  	_length = 0;
      }
  
      /**
       * Attributes clone constructor
       */
      public AttributeList(org.xml.sax.Attributes attributes) {
  	this();
  	if (attributes != null) {
  	    final int count = attributes.getLength();
  	    for (int i = 0; i < count; i++) {
  		add(attributes.getQName(i),attributes.getValue(i));
  	    }
  	}
      }
      
      /**
       * Allocate memory for the AttributeList
       * %OPT% Use on-demand allocation for the internal vectors. The memory
       * is only allocated when there is an attribute. This reduces the cost 
       * of creating many small RTFs.
       */
      private void alloc() {
  	_attributes = new Hashtable();
  	_names  = new Vector();
  	_values = new Vector();
  	_qnames = new Vector();
  	_uris   = new Vector();        
      }
  
      /**
       * SAX2: Return the number of attributes in the list. 
       */
      public int getLength() {
  	return(_length);
      }
  
      /**
       * SAX2: Look up an attribute's Namespace URI by index.
       */
      public String getURI(int index) {
  	if (index < _length)
  	    return((String)_uris.elementAt(index));
  	else
  	    return(null);
      }
  
      /**
       * SAX2: Look up an attribute's local name by index.
       */
      public String getLocalName(int index) {
  	if (index < _length)
  	    return((String)_names.elementAt(index));
  	else
  	    return(null);
      }
  
      /**
       * Return the name of an attribute in this list (by position).
       */
      public String getQName(int pos) {
  	if (pos < _length)
  	    return((String)_qnames.elementAt(pos));
  	else
  	    return(null);
      }
  
      /**
       * SAX2: Look up an attribute's type by index.
       */
      public String getType(int index) {
  	return(CDATASTRING);
      }
  
      /**
       * SAX2: Look up the index of an attribute by Namespace name.
       */
      public int getIndex(String namespaceURI, String localPart) {
  	return(-1);
      }
  
      /**
       * SAX2: Look up the index of an attribute by XML 1.0 qualified name.
       */
      public int getIndex(String qname) {
  	return(-1);
      }
  
      /**
       * SAX2: Look up an attribute's type by Namespace name.
       */
      public String getType(String uri, String localName) {
  	return(CDATASTRING);
      }
  
      /**
       * SAX2: Look up an attribute's type by qname.
       */
      public String getType(String qname) {
  	return(CDATASTRING);
      }
  
      /**
       * SAX2: Look up an attribute's value by index.
       */
      public String getValue(int pos) {
  	if (pos < _length)
  	    return((String)_values.elementAt(pos));
  	else
  	    return(null);
      }
  
      /**
       * SAX2: Look up an attribute's value by qname.
       */
      public String getValue(String qname) {
  	if (_attributes != null) {
  	    final Integer obj = (Integer)_attributes.get(qname);
  	    if (obj == null) return null;
  	    return(getValue(obj.intValue()));
  	}
  	else
  	    return null;
      }
  
      /**
       * SAX2: Look up an attribute's value by Namespace name - SLOW!
       */
      public String getValue(String uri, String localName) {
  	return(getValue(uri+':'+localName));
      }
  
      /**
       * Adds an attribute to the list
       */
      public void add(String qname, String value) {
  	// Initialize the internal vectors at the first usage.
  	if (_attributes == null)
  	    alloc();
  	
  	// Stuff the QName into the names vector & hashtable
  	Integer obj = (Integer)_attributes.get(qname);
  	if (obj == null) {
  	    _attributes.put(qname, obj = new Integer(_length++));
  	    _qnames.addElement(qname);
  	    _values.addElement(value);
  	    int col = qname.lastIndexOf(':');
  	    if (col > -1) {
  		_uris.addElement(qname.substring(0,col));
  		_names.addElement(qname.substring(col+1));
  	    }
  	    else {
  		_uris.addElement(EMPTYSTRING);
  		_names.addElement(qname);
  	    }
  	}
  	else {
  	    final int index = obj.intValue();
  	    _values.set(index, value);
  	}
      }
  
      /**
       * Clears the attribute list
       */
      public void clear() {
  	_length = 0;
  	if (_attributes != null) {
  	    _attributes.clear();
  	    _names.removeAllElements();
  	    _values.removeAllElements();
  	    _qnames.removeAllElements();
  	    _uris.removeAllElements();
  	}
      }
      
  }
  