Home | History | Annotate | Download | only in utils
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one
      3  * or more contributor license agreements. See the NOTICE file
      4  * distributed with this work for additional information
      5  * regarding copyright ownership. The ASF licenses this file
      6  * to you under the Apache License, Version 2.0 (the  "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *     http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  */
     18 /*
     19  * $Id: XMLStringDefault.java 570109 2007-08-27 13:31:35Z zongaro $
     20  */
     21 package org.apache.xml.utils;
     22 
     23 import java.util.Locale;
     24 
     25 /**
     26  * The default implementation of the XMLString interface,
     27  * which is just a simple wrapper of a String object.
     28  */
     29 public class XMLStringDefault implements XMLString
     30 {
     31 
     32   private String m_str;
     33 
     34   /**
     35    * Create a XMLStringDefault object from a String
     36    */
     37   public XMLStringDefault(String str)
     38   {
     39     m_str = str;
     40   }
     41 
     42   /**
     43    * Directly call the
     44    * characters method on the passed ContentHandler for the
     45    * string-value. Multiple calls to the
     46    * ContentHandler's characters methods may well occur for a single call to
     47    * this method.
     48    *
     49    * @param ch A non-null reference to a ContentHandler.
     50    *
     51    * @throws org.xml.sax.SAXException
     52    */
     53   public void dispatchCharactersEvents(org.xml.sax.ContentHandler ch)
     54     throws org.xml.sax.SAXException
     55   {
     56   }
     57 
     58   /**
     59    * Directly call the
     60    * comment method on the passed LexicalHandler for the
     61    * string-value.
     62    *
     63    * @param lh A non-null reference to a LexicalHandler.
     64    *
     65    * @throws org.xml.sax.SAXException
     66    */
     67   public void dispatchAsComment(org.xml.sax.ext.LexicalHandler lh)
     68     throws org.xml.sax.SAXException
     69   {
     70   }
     71 
     72   /**
     73    * Conditionally trim all leading and trailing whitespace in the specified String.
     74    * All strings of white space are
     75    * replaced by a single space character (#x20), except spaces after punctuation which
     76    * receive double spaces if doublePunctuationSpaces is true.
     77    * This function may be useful to a formatter, but to get first class
     78    * results, the formatter should probably do it's own white space handling
     79    * based on the semantics of the formatting object.
     80    *
     81    * @param   trimHead    Trim leading whitespace?
     82    * @param   trimTail    Trim trailing whitespace?
     83    * @param   doublePunctuationSpaces    Use double spaces for punctuation?
     84    * @return              The trimmed string.
     85    */
     86   public XMLString fixWhiteSpace(boolean trimHead,
     87                                  boolean trimTail,
     88                                  boolean doublePunctuationSpaces)
     89   {
     90     return new XMLStringDefault(m_str.trim());
     91   }
     92 
     93   /**
     94    * Returns the length of this string.
     95    *
     96    * @return  the length of the sequence of characters represented by this
     97    *          object.
     98    */
     99   public int length()
    100   {
    101     return m_str.length();
    102   }
    103 
    104   /**
    105    * Returns the character at the specified index. An index ranges
    106    * from <code>0</code> to <code>length() - 1</code>. The first character
    107    * of the sequence is at index <code>0</code>, the next at index
    108    * <code>1</code>, and so on, as for array indexing.
    109    *
    110    * @param      index   the index of the character.
    111    * @return     the character at the specified index of this string.
    112    *             The first character is at index <code>0</code>.
    113    * @exception  IndexOutOfBoundsException  if the <code>index</code>
    114    *             argument is negative or not less than the length of this
    115    *             string.
    116    */
    117   public char charAt(int index)
    118   {
    119     return m_str.charAt(index);
    120   }
    121 
    122   /**
    123    * Copies characters from this string into the destination character
    124    * array.
    125    *
    126    * @param      srcBegin   index of the first character in the string
    127    *                        to copy.
    128    * @param      srcEnd     index after the last character in the string
    129    *                        to copy.
    130    * @param      dst        the destination array.
    131    * @param      dstBegin   the start offset in the destination array.
    132    * @exception IndexOutOfBoundsException If any of the following
    133    *            is true:
    134    *            <ul><li><code>srcBegin</code> is negative.
    135    *            <li><code>srcBegin</code> is greater than <code>srcEnd</code>
    136    *            <li><code>srcEnd</code> is greater than the length of this
    137    *                string
    138    *            <li><code>dstBegin</code> is negative
    139    *            <li><code>dstBegin+(srcEnd-srcBegin)</code> is larger than
    140    *                <code>dst.length</code></ul>
    141    * @exception NullPointerException if <code>dst</code> is <code>null</code>
    142    */
    143   public void getChars(int srcBegin, int srcEnd, char dst[],
    144                                 int dstBegin)
    145   {
    146     int destIndex = dstBegin;
    147     for (int i = srcBegin; i < srcEnd; i++)
    148     {
    149       dst[destIndex++] = m_str.charAt(i);
    150     }
    151   }
    152 
    153   /**
    154    * Compares this string to the specified <code>String</code>.
    155    * The result is <code>true</code> if and only if the argument is not
    156    * <code>null</code> and is a <code>String</code> object that represents
    157    * the same sequence of characters as this object.
    158    *
    159    * @param   obj2   the object to compare this <code>String</code> against.
    160    * @return  <code>true</code> if the <code>String</code>s are equal;
    161    *          <code>false</code> otherwise.
    162    * @see     java.lang.String#compareTo(java.lang.String)
    163    * @see     java.lang.String#equalsIgnoreCase(java.lang.String)
    164    */
    165   public boolean equals(String obj2) {
    166       return m_str.equals(obj2);
    167   }
    168 
    169   /**
    170    * Compares this string to the specified object.
    171    * The result is <code>true</code> if and only if the argument is not
    172    * <code>null</code> and is a <code>String</code> object that represents
    173    * the same sequence of characters as this object.
    174    *
    175    * @param   anObject   the object to compare this <code>String</code>
    176    *                     against.
    177    * @return  <code>true</code> if the <code>String </code>are equal;
    178    *          <code>false</code> otherwise.
    179    * @see     java.lang.String#compareTo(java.lang.String)
    180    * @see     java.lang.String#equalsIgnoreCase(java.lang.String)
    181    */
    182   public boolean equals(XMLString anObject)
    183   {
    184     return m_str.equals(anObject.toString());
    185   }
    186 
    187 
    188   /**
    189    * Compares this string to the specified object.
    190    * The result is <code>true</code> if and only if the argument is not
    191    * <code>null</code> and is a <code>String</code> object that represents
    192    * the same sequence of characters as this object.
    193    *
    194    * @param   anObject   the object to compare this <code>String</code>
    195    *                     against.
    196    * @return  <code>true</code> if the <code>String </code>are equal;
    197    *          <code>false</code> otherwise.
    198    * @see     java.lang.String#compareTo(java.lang.String)
    199    * @see     java.lang.String#equalsIgnoreCase(java.lang.String)
    200    */
    201   public boolean equals(Object anObject)
    202   {
    203     return m_str.equals(anObject);
    204   }
    205 
    206   /**
    207    * Compares this <code>String</code> to another <code>String</code>,
    208    * ignoring case considerations.  Two strings are considered equal
    209    * ignoring case if they are of the same length, and corresponding
    210    * characters in the two strings are equal ignoring case.
    211    *
    212    * @param   anotherString   the <code>String</code> to compare this
    213    *                          <code>String</code> against.
    214    * @return  <code>true</code> if the argument is not <code>null</code>
    215    *          and the <code>String</code>s are equal,
    216    *          ignoring case; <code>false</code> otherwise.
    217    * @see     #equals(Object)
    218    * @see     java.lang.Character#toLowerCase(char)
    219    * @see java.lang.Character#toUpperCase(char)
    220    */
    221   public boolean equalsIgnoreCase(String anotherString)
    222   {
    223     return m_str.equalsIgnoreCase(anotherString);
    224   }
    225 
    226   /**
    227    * Compares two strings lexicographically.
    228    *
    229    * @param   anotherString   the <code>String</code> to be compared.
    230    * @return  the value <code>0</code> if the argument string is equal to
    231    *          this string; a value less than <code>0</code> if this string
    232    *          is lexicographically less than the string argument; and a
    233    *          value greater than <code>0</code> if this string is
    234    *          lexicographically greater than the string argument.
    235    * @exception java.lang.NullPointerException if <code>anotherString</code>
    236    *          is <code>null</code>.
    237    */
    238   public int compareTo(XMLString anotherString)
    239   {
    240     return m_str.compareTo(anotherString.toString());
    241   }
    242 
    243   /**
    244    * Compares two strings lexicographically, ignoring case considerations.
    245    * This method returns an integer whose sign is that of
    246    * <code>this.toUpperCase().toLowerCase().compareTo(
    247    * str.toUpperCase().toLowerCase())</code>.
    248    * <p>
    249    * Note that this method does <em>not</em> take locale into account,
    250    * and will result in an unsatisfactory ordering for certain locales.
    251    * The java.text package provides <em>collators</em> to allow
    252    * locale-sensitive ordering.
    253    *
    254    * @param   str   the <code>String</code> to be compared.
    255    * @return  a negative integer, zero, or a positive integer as the
    256    *          the specified String is greater than, equal to, or less
    257    *          than this String, ignoring case considerations.
    258    * @see     java.text.Collator#compare(String, String)
    259    * @since   1.2
    260    */
    261   public int compareToIgnoreCase(XMLString str)
    262   {
    263     return m_str.compareToIgnoreCase(str.toString());
    264   }
    265 
    266   /**
    267    * Tests if this string starts with the specified prefix beginning
    268    * a specified index.
    269    *
    270    * @param   prefix    the prefix.
    271    * @param   toffset   where to begin looking in the string.
    272    * @return  <code>true</code> if the character sequence represented by the
    273    *          argument is a prefix of the substring of this object starting
    274    *          at index <code>toffset</code>; <code>false</code> otherwise.
    275    *          The result is <code>false</code> if <code>toffset</code> is
    276    *          negative or greater than the length of this
    277    *          <code>String</code> object; otherwise the result is the same
    278    *          as the result of the expression
    279    *          <pre>
    280    *          this.subString(toffset).startsWith(prefix)
    281    *          </pre>
    282    * @exception java.lang.NullPointerException if <code>prefix</code> is
    283    *          <code>null</code>.
    284    */
    285   public boolean startsWith(String prefix, int toffset)
    286   {
    287     return m_str.startsWith(prefix, toffset);
    288   }
    289 
    290   /**
    291    * Tests if this string starts with the specified prefix beginning
    292    * a specified index.
    293    *
    294    * @param   prefix    the prefix.
    295    * @param   toffset   where to begin looking in the string.
    296    * @return  <code>true</code> if the character sequence represented by the
    297    *          argument is a prefix of the substring of this object starting
    298    *          at index <code>toffset</code>; <code>false</code> otherwise.
    299    *          The result is <code>false</code> if <code>toffset</code> is
    300    *          negative or greater than the length of this
    301    *          <code>String</code> object; otherwise the result is the same
    302    *          as the result of the expression
    303    *          <pre>
    304    *          this.subString(toffset).startsWith(prefix)
    305    *          </pre>
    306    * @exception java.lang.NullPointerException if <code>prefix</code> is
    307    *          <code>null</code>.
    308    */
    309   public boolean startsWith(XMLString prefix, int toffset)
    310   {
    311     return m_str.startsWith(prefix.toString(), toffset);
    312   }
    313 
    314   /**
    315    * Tests if this string starts with the specified prefix.
    316    *
    317    * @param   prefix   the prefix.
    318    * @return  <code>true</code> if the character sequence represented by the
    319    *          argument is a prefix of the character sequence represented by
    320    *          this string; <code>false</code> otherwise.
    321    *          Note also that <code>true</code> will be returned if the
    322    *          argument is an empty string or is equal to this
    323    *          <code>String</code> object as determined by the
    324    *          {@link #equals(Object)} method.
    325    * @exception java.lang.NullPointerException if <code>prefix</code> is
    326    *          <code>null</code>.
    327    * @since   JDK1. 0
    328    */
    329   public boolean startsWith(String prefix)
    330   {
    331     return m_str.startsWith(prefix);
    332   }
    333 
    334   /**
    335    * Tests if this string starts with the specified prefix.
    336    *
    337    * @param   prefix   the prefix.
    338    * @return  <code>true</code> if the character sequence represented by the
    339    *          argument is a prefix of the character sequence represented by
    340    *          this string; <code>false</code> otherwise.
    341    *          Note also that <code>true</code> will be returned if the
    342    *          argument is an empty string or is equal to this
    343    *          <code>String</code> object as determined by the
    344    *          {@link #equals(Object)} method.
    345    * @exception java.lang.NullPointerException if <code>prefix</code> is
    346    *          <code>null</code>.
    347    * @since   JDK1. 0
    348    */
    349   public boolean startsWith(XMLString prefix)
    350   {
    351     return m_str.startsWith(prefix.toString());
    352   }
    353 
    354   /**
    355    * Tests if this string ends with the specified suffix.
    356    *
    357    * @param   suffix   the suffix.
    358    * @return  <code>true</code> if the character sequence represented by the
    359    *          argument is a suffix of the character sequence represented by
    360    *          this object; <code>false</code> otherwise. Note that the
    361    *          result will be <code>true</code> if the argument is the
    362    *          empty string or is equal to this <code>String</code> object
    363    *          as determined by the {@link #equals(Object)} method.
    364    * @exception java.lang.NullPointerException if <code>suffix</code> is
    365    *          <code>null</code>.
    366    */
    367   public boolean endsWith(String suffix)
    368   {
    369     return m_str.endsWith(suffix);
    370   }
    371 
    372   /**
    373    * Returns a hashcode for this string. The hashcode for a
    374    * <code>String</code> object is computed as
    375    * <blockquote><pre>
    376    * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
    377    * </pre></blockquote>
    378    * using <code>int</code> arithmetic, where <code>s[i]</code> is the
    379    * <i>i</i>th character of the string, <code>n</code> is the length of
    380    * the string, and <code>^</code> indicates exponentiation.
    381    * (The hash value of the empty string is zero.)
    382    *
    383    * @return  a hash code value for this object.
    384    */
    385   public int hashCode()
    386   {
    387     return m_str.hashCode();
    388   }
    389 
    390   /**
    391    * Returns the index within this string of the first occurrence of the
    392    * specified character. If a character with value <code>ch</code> occurs
    393    * in the character sequence represented by this <code>String</code>
    394    * object, then the index of the first such occurrence is returned --
    395    * that is, the smallest value <i>k</i> such that:
    396    * <blockquote><pre>
    397    * this.charAt(<i>k</i>) == ch
    398    * </pre></blockquote>
    399    * is <code>true</code>. If no such character occurs in this string,
    400    * then <code>-1</code> is returned.
    401    *
    402    * @param   ch   a character.
    403    * @return  the index of the first occurrence of the character in the
    404    *          character sequence represented by this object, or
    405    *          <code>-1</code> if the character does not occur.
    406    */
    407   public int indexOf(int ch)
    408   {
    409     return m_str.indexOf(ch);
    410   }
    411 
    412   /**
    413    * Returns the index within this string of the first occurrence of the
    414    * specified character, starting the search at the specified index.
    415    * <p>
    416    * If a character with value <code>ch</code> occurs in the character
    417    * sequence represented by this <code>String</code> object at an index
    418    * no smaller than <code>fromIndex</code>, then the index of the first
    419    * such occurrence is returned--that is, the smallest value <i>k</i>
    420    * such that:
    421    * <blockquote><pre>
    422    * (this.charAt(<i>k</i>) == ch) && (<i>k</i> >= fromIndex)
    423    * </pre></blockquote>
    424    * is true. If no such character occurs in this string at or after
    425    * position <code>fromIndex</code>, then <code>-1</code> is returned.
    426    * <p>
    427    * There is no restriction on the value of <code>fromIndex</code>. If it
    428    * is negative, it has the same effect as if it were zero: this entire
    429    * string may be searched. If it is greater than the length of this
    430    * string, it has the same effect as if it were equal to the length of
    431    * this string: <code>-1</code> is returned.
    432    *
    433    * @param   ch          a character.
    434    * @param   fromIndex   the index to start the search from.
    435    * @return  the index of the first occurrence of the character in the
    436    *          character sequence represented by this object that is greater
    437    *          than or equal to <code>fromIndex</code>, or <code>-1</code>
    438    *          if the character does not occur.
    439    */
    440   public int indexOf(int ch, int fromIndex)
    441   {
    442     return m_str.indexOf(ch, fromIndex);
    443   }
    444 
    445   /**
    446    * Returns the index within this string of the last occurrence of the
    447    * specified character. That is, the index returned is the largest
    448    * value <i>k</i> such that:
    449    * <blockquote><pre>
    450    * this.charAt(<i>k</i>) == ch
    451    * </pre></blockquote>
    452    * is true.
    453    * The String is searched backwards starting at the last character.
    454    *
    455    * @param   ch   a character.
    456    * @return  the index of the last occurrence of the character in the
    457    *          character sequence represented by this object, or
    458    *          <code>-1</code> if the character does not occur.
    459    */
    460   public int lastIndexOf(int ch)
    461   {
    462     return m_str.lastIndexOf(ch);
    463   }
    464 
    465   /**
    466    * Returns the index within this string of the last occurrence of the
    467    * specified character, searching backward starting at the specified
    468    * index. That is, the index returned is the largest value <i>k</i>
    469    * such that:
    470    * <blockquote><pre>
    471    * this.charAt(k) == ch) && (k <= fromIndex)
    472    * </pre></blockquote>
    473    * is true.
    474    *
    475    * @param   ch          a character.
    476    * @param   fromIndex   the index to start the search from. There is no
    477    *          restriction on the value of <code>fromIndex</code>. If it is
    478    *          greater than or equal to the length of this string, it has
    479    *          the same effect as if it were equal to one less than the
    480    *          length of this string: this entire string may be searched.
    481    *          If it is negative, it has the same effect as if it were -1:
    482    *          -1 is returned.
    483    * @return  the index of the last occurrence of the character in the
    484    *          character sequence represented by this object that is less
    485    *          than or equal to <code>fromIndex</code>, or <code>-1</code>
    486    *          if the character does not occur before that point.
    487    */
    488   public int lastIndexOf(int ch, int fromIndex)
    489   {
    490     return m_str.lastIndexOf(ch, fromIndex);
    491   }
    492 
    493   /**
    494    * Returns the index within this string of the first occurrence of the
    495    * specified substring. The integer returned is the smallest value
    496    * <i>k</i> such that:
    497    * <blockquote><pre>
    498    * this.startsWith(str, <i>k</i>)
    499    * </pre></blockquote>
    500    * is <code>true</code>.
    501    *
    502    * @param   str   any string.
    503    * @return  if the string argument occurs as a substring within this
    504    *          object, then the index of the first character of the first
    505    *          such substring is returned; if it does not occur as a
    506    *          substring, <code>-1</code> is returned.
    507    * @exception java.lang.NullPointerException if <code>str</code> is
    508    *          <code>null</code>.
    509    */
    510   public int indexOf(String str)
    511   {
    512     return m_str.indexOf(str);
    513   }
    514 
    515   /**
    516    * Returns the index within this string of the first occurrence of the
    517    * specified substring. The integer returned is the smallest value
    518    * <i>k</i> such that:
    519    * <blockquote><pre>
    520    * this.startsWith(str, <i>k</i>)
    521    * </pre></blockquote>
    522    * is <code>true</code>.
    523    *
    524    * @param   str   any string.
    525    * @return  if the string argument occurs as a substring within this
    526    *          object, then the index of the first character of the first
    527    *          such substring is returned; if it does not occur as a
    528    *          substring, <code>-1</code> is returned.
    529    * @exception java.lang.NullPointerException if <code>str</code> is
    530    *          <code>null</code>.
    531    */
    532   public int indexOf(XMLString str)
    533   {
    534     return m_str.indexOf(str.toString());
    535   }
    536 
    537   /**
    538    * Returns the index within this string of the first occurrence of the
    539    * specified substring, starting at the specified index. The integer
    540    * returned is the smallest value <i>k</i> such that:
    541    * <blockquote><pre>
    542    * this.startsWith(str, <i>k</i>) && (<i>k</i> >= fromIndex)
    543    * </pre></blockquote>
    544    * is <code>true</code>.
    545    * <p>
    546    * There is no restriction on the value of <code>fromIndex</code>. If
    547    * it is negative, it has the same effect as if it were zero: this entire
    548    * string may be searched. If it is greater than the length of this
    549    * string, it has the same effect as if it were equal to the length of
    550    * this string: <code>-1</code> is returned.
    551    *
    552    * @param   str         the substring to search for.
    553    * @param   fromIndex   the index to start the search from.
    554    * @return  If the string argument occurs as a substring within this
    555    *          object at a starting index no smaller than
    556    *          <code>fromIndex</code>, then the index of the first character
    557    *          of the first such substring is returned. If it does not occur
    558    *          as a substring starting at <code>fromIndex</code> or beyond,
    559    *          <code>-1</code> is returned.
    560    * @exception java.lang.NullPointerException if <code>str</code> is
    561    *          <code>null</code>
    562    */
    563   public int indexOf(String str, int fromIndex)
    564   {
    565     return m_str.indexOf(str, fromIndex);
    566   }
    567 
    568   /**
    569    * Returns the index within this string of the rightmost occurrence
    570    * of the specified substring.  The rightmost empty string "" is
    571    * considered to occur at the index value <code>this.length()</code>.
    572    * The returned index is the largest value <i>k</i> such that
    573    * <blockquote><pre>
    574    * this.startsWith(str, k)
    575    * </pre></blockquote>
    576    * is true.
    577    *
    578    * @param   str   the substring to search for.
    579    * @return  if the string argument occurs one or more times as a substring
    580    *          within this object, then the index of the first character of
    581    *          the last such substring is returned. If it does not occur as
    582    *          a substring, <code>-1</code> is returned.
    583    * @exception java.lang.NullPointerException  if <code>str</code> is
    584    *          <code>null</code>.
    585    */
    586   public int lastIndexOf(String str)
    587   {
    588     return m_str.lastIndexOf(str);
    589   }
    590 
    591   /**
    592    * Returns the index within this string of the last occurrence of
    593    * the specified substring.
    594    *
    595    * @param   str         the substring to search for.
    596    * @param   fromIndex   the index to start the search from. There is no
    597    *          restriction on the value of fromIndex. If it is greater than
    598    *          the length of this string, it has the same effect as if it
    599    *          were equal to the length of this string: this entire string
    600    *          may be searched. If it is negative, it has the same effect
    601    *          as if it were -1: -1 is returned.
    602    * @return  If the string argument occurs one or more times as a substring
    603    *          within this object at a starting index no greater than
    604    *          <code>fromIndex</code>, then the index of the first character of
    605    *          the last such substring is returned. If it does not occur as a
    606    *          substring starting at <code>fromIndex</code> or earlier,
    607    *          <code>-1</code> is returned.
    608    * @exception java.lang.NullPointerException if <code>str</code> is
    609    *          <code>null</code>.
    610    */
    611   public int lastIndexOf(String str, int fromIndex)
    612   {
    613     return m_str.lastIndexOf(str, fromIndex);
    614   }
    615 
    616   /**
    617    * Returns a new string that is a substring of this string. The
    618    * substring begins with the character at the specified index and
    619    * extends to the end of this string. <p>
    620    * Examples:
    621    * <blockquote><pre>
    622    * "unhappy".substring(2) returns "happy"
    623    * "Harbison".substring(3) returns "bison"
    624    * "emptiness".substring(9) returns "" (an empty string)
    625    * </pre></blockquote>
    626    *
    627    * @param      beginIndex   the beginning index, inclusive.
    628    * @return     the specified substring.
    629    * @exception  IndexOutOfBoundsException  if
    630    *             <code>beginIndex</code> is negative or larger than the
    631    *             length of this <code>String</code> object.
    632    */
    633   public XMLString substring(int beginIndex)
    634   {
    635     return new XMLStringDefault(m_str.substring(beginIndex));
    636   }
    637 
    638   /**
    639    * Returns a new string that is a substring of this string. The
    640    * substring begins at the specified <code>beginIndex</code> and
    641    * extends to the character at index <code>endIndex - 1</code>.
    642    * Thus the length of the substring is <code>endIndex-beginIndex</code>.
    643    *
    644    * @param      beginIndex   the beginning index, inclusive.
    645    * @param      endIndex     the ending index, exclusive.
    646    * @return     the specified substring.
    647    * @exception  IndexOutOfBoundsException  if the
    648    *             <code>beginIndex</code> is negative, or
    649    *             <code>endIndex</code> is larger than the length of
    650    *             this <code>String</code> object, or
    651    *             <code>beginIndex</code> is larger than
    652    *             <code>endIndex</code>.
    653    */
    654   public XMLString substring(int beginIndex, int endIndex)
    655   {
    656     return new XMLStringDefault(m_str.substring(beginIndex, endIndex));
    657   }
    658 
    659   /**
    660    * Concatenates the specified string to the end of this string.
    661    *
    662    * @param   str   the <code>String</code> that is concatenated to the end
    663    *                of this <code>String</code>.
    664    * @return  a string that represents the concatenation of this object's
    665    *          characters followed by the string argument's characters.
    666    * @exception java.lang.NullPointerException if <code>str</code> is
    667    *          <code>null</code>.
    668    */
    669   public XMLString concat(String str)
    670   {
    671     return new XMLStringDefault(m_str.concat(str));
    672   }
    673 
    674   /**
    675    * Converts all of the characters in this <code>String</code> to lower
    676    * case using the rules of the given <code>Locale</code>.
    677    *
    678    * @param locale use the case transformation rules for this locale
    679    * @return the String, converted to lowercase.
    680    * @see     java.lang.Character#toLowerCase(char)
    681    * @see     java.lang.String#toUpperCase(Locale)
    682    */
    683   public XMLString toLowerCase(Locale locale)
    684   {
    685     return new XMLStringDefault(m_str.toLowerCase(locale));
    686   }
    687 
    688   /**
    689    * Converts all of the characters in this <code>String</code> to lower
    690    * case using the rules of the default locale, which is returned
    691    * by <code>Locale.getDefault</code>.
    692    * <p>
    693    *
    694    * @return  the string, converted to lowercase.
    695    * @see     java.lang.Character#toLowerCase(char)
    696    * @see     java.lang.String#toLowerCase(Locale)
    697    */
    698   public XMLString toLowerCase()
    699   {
    700     return new XMLStringDefault(m_str.toLowerCase());
    701   }
    702 
    703   /**
    704    * Converts all of the characters in this <code>String</code> to upper
    705    * case using the rules of the given locale.
    706    * @param locale use the case transformation rules for this locale
    707    * @return the String, converted to uppercase.
    708    * @see     java.lang.Character#toUpperCase(char)
    709    * @see     java.lang.String#toLowerCase(Locale)
    710    */
    711   public XMLString toUpperCase(Locale locale)
    712   {
    713     return new XMLStringDefault(m_str.toUpperCase(locale));
    714   }
    715 
    716   /**
    717    * Converts all of the characters in this <code>String</code> to upper
    718    * case using the rules of the default locale, which is returned
    719    * by <code>Locale.getDefault</code>.
    720    *
    721    * <p>
    722    * If no character in this string has a different uppercase version,
    723    * based on calling the <code>toUpperCase</code> method defined by
    724    * <code>Character</code>, then the original string is returned.
    725    * <p>
    726    * Otherwise, this method creates a new <code>String</code> object
    727    * representing a character sequence identical in length to the
    728    * character sequence represented by this <code>String</code> object and
    729    * with every character equal to the result of applying the method
    730    * <code>Character.toUpperCase</code> to the corresponding character of
    731    * this <code>String</code> object. <p>
    732    * Examples:
    733    * <blockquote><pre>
    734    * "Fahrvergn&uuml;gen".toUpperCase() returns "FAHRVERGN&Uuml;GEN"
    735    * "Visit Ljubinje!".toUpperCase() returns "VISIT LJUBINJE!"
    736    * </pre></blockquote>
    737    *
    738    * @return  the string, converted to uppercase.
    739    * @see     java.lang.Character#toUpperCase(char)
    740    * @see     java.lang.String#toUpperCase(Locale)
    741    */
    742   public XMLString toUpperCase()
    743   {
    744     return new XMLStringDefault(m_str.toUpperCase());
    745   }
    746 
    747   /**
    748    * Removes white space from both ends of this string.
    749    * <p>
    750    * If this <code>String</code> object represents an empty character
    751    * sequence, or the first and last characters of character sequence
    752    * represented by this <code>String</code> object both have codes
    753    * greater than <code>'&#92;u0020'</code> (the space character), then a
    754    * reference to this <code>String</code> object is returned.
    755    * <p>
    756    * Otherwise, if there is no character with a code greater than
    757    * <code>'&#92;u0020'</code> in the string, then a new
    758    * <code>String</code> object representing an empty string is created
    759    * and returned.
    760    * <p>
    761    * Otherwise, let <i>k</i> be the index of the first character in the
    762    * string whose code is greater than <code>'&#92;u0020'</code>, and let
    763    * <i>m</i> be the index of the last character in the string whose code
    764    * is greater than <code>'&#92;u0020'</code>. A new <code>String</code>
    765    * object is created, representing the substring of this string that
    766    * begins with the character at index <i>k</i> and ends with the
    767    * character at index <i>m</i>-that is, the result of
    768    * <code>this.substring(<i>k</i>,&nbsp;<i>m</i>+1)</code>.
    769    * <p>
    770    * This method may be used to trim
    771    * {@link Character#isSpace(char) whitespace} from the beginning and end
    772    * of a string; in fact, it trims all ASCII control characters as well.
    773    *
    774    * @return  this string, with white space removed from the front and end.
    775    */
    776   public XMLString trim()
    777   {
    778     return new XMLStringDefault(m_str.trim());
    779   }
    780 
    781   /**
    782    * This object (which is already a string!) is itself returned.
    783    *
    784    * @return  the string itself.
    785    */
    786   public String toString()
    787   {
    788     return m_str;
    789   }
    790 
    791   /**
    792    * Tell if this object contains a java String object.
    793    *
    794    * @return true if this XMLString can return a string without creating one.
    795    */
    796   public boolean hasString()
    797   {
    798     return true;
    799   }
    800 
    801   /**
    802    * Convert a string to a double -- Allowed input is in fixed
    803    * notation ddd.fff.
    804    *
    805    * @return A double value representation of the string, or return Double.NaN
    806    * if the string can not be converted.
    807    */
    808   public double toDouble()
    809   {
    810     try {
    811       return Double.valueOf(m_str).doubleValue();
    812     }
    813     catch (NumberFormatException nfe)
    814     {
    815       return Double.NaN;
    816     }
    817   }
    818 }
    819