Home » xml-commons-external-1.4.01-src » org.xml » sax » helpers » [javadoc | source]

    1   // AttributesImpl.java - default implementation of Attributes.
    2   // http://www.saxproject.org
    3   // Written by David Megginson
    4   // NO WARRANTY!  This class is in the public domain.
    5   // $Id: AttributesImpl.java 226184 2005-04-08 10:53:24Z neeraj $
    6   
    7   package org.xml.sax.helpers;
    8   
    9   import org.xml.sax.Attributes;
   10   
   11   
   12   /**
   13    * Default implementation of the Attributes interface.
   14    *
   15    * <blockquote>
   16    * <em>This module, both source code and documentation, is in the
   17    * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
   18    * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
   19    * for further information.
   20    * </blockquote>
   21    *
   22    * <p>This class provides a default implementation of the SAX2
   23    * {@link org.xml.sax.Attributes Attributes} interface, with the 
   24    * addition of manipulators so that the list can be modified or 
   25    * reused.</p>
   26    *
   27    * <p>There are two typical uses of this class:</p>
   28    *
   29    * <ol>
   30    * <li>to take a persistent snapshot of an Attributes object
   31    *  in a {@link org.xml.sax.ContentHandler#startElement startElement} event; or</li>
   32    * <li>to construct or modify an Attributes object in a SAX2 driver or filter.</li>
   33    * </ol>
   34    *
   35    * <p>This class replaces the now-deprecated SAX1 {@link 
   36    * org.xml.sax.helpers.AttributeListImpl AttributeListImpl}
   37    * class; in addition to supporting the updated Attributes
   38    * interface rather than the deprecated {@link org.xml.sax.AttributeList
   39    * AttributeList} interface, it also includes a much more efficient 
   40    * implementation using a single array rather than a set of Vectors.</p>
   41    *
   42    * @since SAX 2.0
   43    * @author David Megginson
   44    * @version 2.0.1 (sax2r2)
   45    */
   46   public class AttributesImpl implements Attributes
   47   {
   48   
   49   
   50       ////////////////////////////////////////////////////////////////////
   51       // Constructors.
   52       ////////////////////////////////////////////////////////////////////
   53   
   54   
   55       /**
   56        * Construct a new, empty AttributesImpl object.
   57        */
   58       public AttributesImpl ()
   59       {
   60   	length = 0;
   61   	data = null;
   62       }
   63   
   64   
   65       /**
   66        * Copy an existing Attributes object.
   67        *
   68        * <p>This constructor is especially useful inside a
   69        * {@link org.xml.sax.ContentHandler#startElement startElement} event.</p>
   70        *
   71        * @param atts The existing Attributes object.
   72        */
   73       public AttributesImpl (Attributes atts)
   74       {
   75   	setAttributes(atts);
   76       }
   77   
   78   
   79   
   80       ////////////////////////////////////////////////////////////////////
   81       // Implementation of org.xml.sax.Attributes.
   82       ////////////////////////////////////////////////////////////////////
   83   
   84   
   85       /**
   86        * Return the number of attributes in the list.
   87        *
   88        * @return The number of attributes in the list.
   89        * @see org.xml.sax.Attributes#getLength
   90        */
   91       public int getLength ()
   92       {
   93   	return length;
   94       }
   95   
   96   
   97       /**
   98        * Return an attribute's Namespace URI.
   99        *
  100        * @param index The attribute's index (zero-based).
  101        * @return The Namespace URI, the empty string if none is
  102        *         available, or null if the index is out of range.
  103        * @see org.xml.sax.Attributes#getURI
  104        */
  105       public String getURI (int index)
  106       {
  107   	if (index >= 0 && index < length) {
  108   	    return data[index*5];
  109   	} else {
  110   	    return null;
  111   	}
  112       }
  113   
  114   
  115       /**
  116        * Return an attribute's local name.
  117        *
  118        * @param index The attribute's index (zero-based).
  119        * @return The attribute's local name, the empty string if 
  120        *         none is available, or null if the index if out of range.
  121        * @see org.xml.sax.Attributes#getLocalName
  122        */
  123       public String getLocalName (int index)
  124       {
  125   	if (index >= 0 && index < length) {
  126   	    return data[index*5+1];
  127   	} else {
  128   	    return null;
  129   	}
  130       }
  131   
  132   
  133       /**
  134        * Return an attribute's qualified (prefixed) name.
  135        *
  136        * @param index The attribute's index (zero-based).
  137        * @return The attribute's qualified name, the empty string if 
  138        *         none is available, or null if the index is out of bounds.
  139        * @see org.xml.sax.Attributes#getQName
  140        */
  141       public String getQName (int index)
  142       {
  143   	if (index >= 0 && index < length) {
  144   	    return data[index*5+2];
  145   	} else {
  146   	    return null;
  147   	}
  148       }
  149   
  150   
  151       /**
  152        * Return an attribute's type by index.
  153        *
  154        * @param index The attribute's index (zero-based).
  155        * @return The attribute's type, "CDATA" if the type is unknown, or null
  156        *         if the index is out of bounds.
  157        * @see org.xml.sax.Attributes#getType(int)
  158        */
  159       public String getType (int index)
  160       {
  161   	if (index >= 0 && index < length) {
  162   	    return data[index*5+3];
  163   	} else {
  164   	    return null;
  165   	}
  166       }
  167   
  168   
  169       /**
  170        * Return an attribute's value by index.
  171        *
  172        * @param index The attribute's index (zero-based).
  173        * @return The attribute's value or null if the index is out of bounds.
  174        * @see org.xml.sax.Attributes#getValue(int)
  175        */
  176       public String getValue (int index)
  177       {
  178   	if (index >= 0 && index < length) {
  179   	    return data[index*5+4];
  180   	} else {
  181   	    return null;
  182   	}
  183       }
  184   
  185   
  186       /**
  187        * Look up an attribute's index by Namespace name.
  188        *
  189        * <p>In many cases, it will be more efficient to look up the name once and
  190        * use the index query methods rather than using the name query methods
  191        * repeatedly.</p>
  192        *
  193        * @param uri The attribute's Namespace URI, or the empty
  194        *        string if none is available.
  195        * @param localName The attribute's local name.
  196        * @return The attribute's index, or -1 if none matches.
  197        * @see org.xml.sax.Attributes#getIndex(java.lang.String,java.lang.String)
  198        */
  199       public int getIndex (String uri, String localName)
  200       {
  201   	int max = length * 5;
  202   	for (int i = 0; i < max; i += 5) {
  203   	    if (data[i].equals(uri) && data[i+1].equals(localName)) {
  204   		return i / 5;
  205   	    }
  206   	} 
  207   	return -1;
  208       }
  209   
  210   
  211       /**
  212        * Look up an attribute's index by qualified (prefixed) name.
  213        *
  214        * @param qName The qualified name.
  215        * @return The attribute's index, or -1 if none matches.
  216        * @see org.xml.sax.Attributes#getIndex(java.lang.String)
  217        */
  218       public int getIndex (String qName)
  219       {
  220   	int max = length * 5;
  221   	for (int i = 0; i < max; i += 5) {
  222   	    if (data[i+2].equals(qName)) {
  223   		return i / 5;
  224   	    }
  225   	} 
  226   	return -1;
  227       }
  228   
  229   
  230       /**
  231        * Look up an attribute's type by Namespace-qualified name.
  232        *
  233        * @param uri The Namespace URI, or the empty string for a name
  234        *        with no explicit Namespace URI.
  235        * @param localName The local name.
  236        * @return The attribute's type, or null if there is no
  237        *         matching attribute.
  238        * @see org.xml.sax.Attributes#getType(java.lang.String,java.lang.String)
  239        */
  240       public String getType (String uri, String localName)
  241       {
  242   	int max = length * 5;
  243   	for (int i = 0; i < max; i += 5) {
  244   	    if (data[i].equals(uri) && data[i+1].equals(localName)) {
  245   		return data[i+3];
  246   	    }
  247   	} 
  248   	return null;
  249       }
  250   
  251   
  252       /**
  253        * Look up an attribute's type by qualified (prefixed) name.
  254        *
  255        * @param qName The qualified name.
  256        * @return The attribute's type, or null if there is no
  257        *         matching attribute.
  258        * @see org.xml.sax.Attributes#getType(java.lang.String)
  259        */
  260       public String getType (String qName)
  261       {
  262   	int max = length * 5;
  263   	for (int i = 0; i < max; i += 5) {
  264   	    if (data[i+2].equals(qName)) {
  265   		return data[i+3];
  266   	    }
  267   	}
  268   	return null;
  269       }
  270   
  271   
  272       /**
  273        * Look up an attribute's value by Namespace-qualified name.
  274        *
  275        * @param uri The Namespace URI, or the empty string for a name
  276        *        with no explicit Namespace URI.
  277        * @param localName The local name.
  278        * @return The attribute's value, or null if there is no
  279        *         matching attribute.
  280        * @see org.xml.sax.Attributes#getValue(java.lang.String,java.lang.String)
  281        */
  282       public String getValue (String uri, String localName)
  283       {
  284   	int max = length * 5;
  285   	for (int i = 0; i < max; i += 5) {
  286   	    if (data[i].equals(uri) && data[i+1].equals(localName)) {
  287   		return data[i+4];
  288   	    }
  289   	}
  290   	return null;
  291       }
  292   
  293   
  294       /**
  295        * Look up an attribute's value by qualified (prefixed) name.
  296        *
  297        * @param qName The qualified name.
  298        * @return The attribute's value, or null if there is no
  299        *         matching attribute.
  300        * @see org.xml.sax.Attributes#getValue(java.lang.String)
  301        */
  302       public String getValue (String qName)
  303       {
  304   	int max = length * 5;
  305   	for (int i = 0; i < max; i += 5) {
  306   	    if (data[i+2].equals(qName)) {
  307   		return data[i+4];
  308   	    }
  309   	}
  310   	return null;
  311       }
  312   
  313   
  314   
  315       ////////////////////////////////////////////////////////////////////
  316       // Manipulators.
  317       ////////////////////////////////////////////////////////////////////
  318   
  319   
  320       /**
  321        * Clear the attribute list for reuse.
  322        *
  323        * <p>Note that little memory is freed by this call:
  324        * the current array is kept so it can be 
  325        * reused.</p>
  326        */
  327       public void clear ()
  328       {
  329   	if (data != null) {
  330   	    for (int i = 0; i < (length * 5); i++)
  331   		data [i] = null;
  332   	}
  333   	length = 0;
  334       }
  335   
  336   
  337       /**
  338        * Copy an entire Attributes object.
  339        *
  340        * <p>It may be more efficient to reuse an existing object
  341        * rather than constantly allocating new ones.</p>
  342        * 
  343        * @param atts The attributes to copy.
  344        */
  345       public void setAttributes (Attributes atts)
  346       {
  347           clear();
  348           length = atts.getLength();
  349           if (length > 0) {
  350               data = new String[length*5];
  351               for (int i = 0; i < length; i++) {
  352                   data[i*5] = atts.getURI(i);
  353                   data[i*5+1] = atts.getLocalName(i);
  354                   data[i*5+2] = atts.getQName(i);
  355                   data[i*5+3] = atts.getType(i);
  356                   data[i*5+4] = atts.getValue(i);
  357               }
  358   	}
  359       }
  360   
  361   
  362       /**
  363        * Add an attribute to the end of the list.
  364        *
  365        * <p>For the sake of speed, this method does no checking
  366        * to see if the attribute is already in the list: that is
  367        * the responsibility of the application.</p>
  368        *
  369        * @param uri The Namespace URI, or the empty string if
  370        *        none is available or Namespace processing is not
  371        *        being performed.
  372        * @param localName The local name, or the empty string if
  373        *        Namespace processing is not being performed.
  374        * @param qName The qualified (prefixed) name, or the empty string
  375        *        if qualified names are not available.
  376        * @param type The attribute type as a string.
  377        * @param value The attribute value.
  378        */
  379       public void addAttribute (String uri, String localName, String qName,
  380   			      String type, String value)
  381       {
  382   	ensureCapacity(length+1);
  383   	data[length*5] = uri;
  384   	data[length*5+1] = localName;
  385   	data[length*5+2] = qName;
  386   	data[length*5+3] = type;
  387   	data[length*5+4] = value;
  388   	length++;
  389       }
  390   
  391   
  392       /**
  393        * Set an attribute in the list.
  394        *
  395        * <p>For the sake of speed, this method does no checking
  396        * for name conflicts or well-formedness: such checks are the
  397        * responsibility of the application.</p>
  398        *
  399        * @param index The index of the attribute (zero-based).
  400        * @param uri The Namespace URI, or the empty string if
  401        *        none is available or Namespace processing is not
  402        *        being performed.
  403        * @param localName The local name, or the empty string if
  404        *        Namespace processing is not being performed.
  405        * @param qName The qualified name, or the empty string
  406        *        if qualified names are not available.
  407        * @param type The attribute type as a string.
  408        * @param value The attribute value.
  409        * @exception java.lang.ArrayIndexOutOfBoundsException When the
  410        *            supplied index does not point to an attribute
  411        *            in the list.
  412        */
  413       public void setAttribute (int index, String uri, String localName,
  414   			      String qName, String type, String value)
  415       {
  416   	if (index >= 0 && index < length) {
  417   	    data[index*5] = uri;
  418   	    data[index*5+1] = localName;
  419   	    data[index*5+2] = qName;
  420   	    data[index*5+3] = type;
  421   	    data[index*5+4] = value;
  422   	} else {
  423   	    badIndex(index);
  424   	}
  425       }
  426   
  427   
  428       /**
  429        * Remove an attribute from the list.
  430        *
  431        * @param index The index of the attribute (zero-based).
  432        * @exception java.lang.ArrayIndexOutOfBoundsException When the
  433        *            supplied index does not point to an attribute
  434        *            in the list.
  435        */
  436       public void removeAttribute (int index)
  437       {
  438   	if (index >= 0 && index < length) {
  439   	    if (index < length - 1) {
  440   		System.arraycopy(data, (index+1)*5, data, index*5,
  441   				 (length-index-1)*5);
  442   	    }
  443   	    index = (length - 1) * 5;
  444   	    data [index++] = null;
  445   	    data [index++] = null;
  446   	    data [index++] = null;
  447   	    data [index++] = null;
  448   	    data [index] = null;
  449   	    length--;
  450   	} else {
  451   	    badIndex(index);
  452   	}
  453       }
  454   
  455   
  456       /**
  457        * Set the Namespace URI of a specific attribute.
  458        *
  459        * @param index The index of the attribute (zero-based).
  460        * @param uri The attribute's Namespace URI, or the empty
  461        *        string for none.
  462        * @exception java.lang.ArrayIndexOutOfBoundsException When the
  463        *            supplied index does not point to an attribute
  464        *            in the list.
  465        */
  466       public void setURI (int index, String uri)
  467       {
  468   	if (index >= 0 && index < length) {
  469   	    data[index*5] = uri;
  470   	} else {
  471   	    badIndex(index);
  472   	}
  473       }
  474   
  475   
  476       /**
  477        * Set the local name of a specific attribute.
  478        *
  479        * @param index The index of the attribute (zero-based).
  480        * @param localName The attribute's local name, or the empty
  481        *        string for none.
  482        * @exception java.lang.ArrayIndexOutOfBoundsException When the
  483        *            supplied index does not point to an attribute
  484        *            in the list.
  485        */
  486       public void setLocalName (int index, String localName)
  487       {
  488   	if (index >= 0 && index < length) {
  489   	    data[index*5+1] = localName;
  490   	} else {
  491   	    badIndex(index);
  492   	}
  493       }
  494   
  495   
  496       /**
  497        * Set the qualified name of a specific attribute.
  498        *
  499        * @param index The index of the attribute (zero-based).
  500        * @param qName The attribute's qualified name, or the empty
  501        *        string for none.
  502        * @exception java.lang.ArrayIndexOutOfBoundsException When the
  503        *            supplied index does not point to an attribute
  504        *            in the list.
  505        */
  506       public void setQName (int index, String qName)
  507       {
  508   	if (index >= 0 && index < length) {
  509   	    data[index*5+2] = qName;
  510   	} else {
  511   	    badIndex(index);
  512   	}
  513       }
  514   
  515   
  516       /**
  517        * Set the type of a specific attribute.
  518        *
  519        * @param index The index of the attribute (zero-based).
  520        * @param type The attribute's type.
  521        * @exception java.lang.ArrayIndexOutOfBoundsException When the
  522        *            supplied index does not point to an attribute
  523        *            in the list.
  524        */
  525       public void setType (int index, String type)
  526       {
  527   	if (index >= 0 && index < length) {
  528   	    data[index*5+3] = type;
  529   	} else {
  530   	    badIndex(index);
  531   	}
  532       }
  533   
  534   
  535       /**
  536        * Set the value of a specific attribute.
  537        *
  538        * @param index The index of the attribute (zero-based).
  539        * @param value The attribute's value.
  540        * @exception java.lang.ArrayIndexOutOfBoundsException When the
  541        *            supplied index does not point to an attribute
  542        *            in the list.
  543        */
  544       public void setValue (int index, String value)
  545       {
  546   	if (index >= 0 && index < length) {
  547   	    data[index*5+4] = value;
  548   	} else {
  549   	    badIndex(index);
  550   	}
  551       }
  552   
  553   
  554   
  555       ////////////////////////////////////////////////////////////////////
  556       // Internal methods.
  557       ////////////////////////////////////////////////////////////////////
  558   
  559   
  560       /**
  561        * Ensure the internal array's capacity.
  562        *
  563        * @param n The minimum number of attributes that the array must
  564        *        be able to hold.
  565        */
  566       private void ensureCapacity (int n)    {
  567           if (n <= 0) {
  568               return;
  569           }
  570           int max;
  571           if (data == null || data.length == 0) {
  572               max = 25;
  573           }
  574           else if (data.length >= n * 5) {
  575               return;
  576           }
  577           else {
  578               max = data.length;
  579           }
  580           while (max < n * 5) {
  581               max *= 2;
  582           }
  583   
  584           String newData[] = new String[max];
  585           if (length > 0) {
  586               System.arraycopy(data, 0, newData, 0, length*5);
  587           }
  588           data = newData;
  589       }
  590   
  591   
  592       /**
  593        * Report a bad array index in a manipulator.
  594        *
  595        * @param index The index to report.
  596        * @exception java.lang.ArrayIndexOutOfBoundsException Always.
  597        */
  598       private void badIndex (int index)
  599   	throws ArrayIndexOutOfBoundsException
  600       {
  601   	String msg =
  602   	    "Attempt to modify attribute at illegal index: " + index;
  603   	throw new ArrayIndexOutOfBoundsException(msg);
  604       }
  605   
  606   
  607   
  608       ////////////////////////////////////////////////////////////////////
  609       // Internal state.
  610       ////////////////////////////////////////////////////////////////////
  611   
  612       int length;
  613       String data [];
  614   
  615   }
  616   
  617   // end of AttributesImpl.java
  618   

Home » xml-commons-external-1.4.01-src » org.xml » sax » helpers » [javadoc | source]