View Javadoc

1   /*
2    * Copyright (c) 1998, 2005 Gargoyle Software Inc. All rights reserved.
3    *
4    * Redistribution and use in source and binary forms, with or without
5    * modification, are permitted provided that the following conditions are met:
6    *
7    * 1. Redistributions of source code must retain the above copyright notice,
8    *    this list of conditions and the following disclaimer.
9    * 2. Redistributions in binary form must reproduce the above copyright notice,
10   *    this list of conditions and the following disclaimer in the documentation
11   *    and/or other materials provided with the distribution.
12   * 3. The end-user documentation included with the redistribution, if any, must
13   *    include the following acknowledgment:
14   *
15   *       "This product includes software developed by Gargoyle Software Inc.
16   *        (http://www.GargoyleSoftware.com/)."
17   *
18   *    Alternately, this acknowledgment may appear in the software itself, if
19   *    and wherever such third-party acknowledgments normally appear.
20   * 4. The name "Gargoyle Software" must not be used to endorse or promote
21   *    products derived from this software without prior written permission.
22   *    For written permission, please contact info@GargoyleSoftware.com.
23   * 5. Products derived from this software may not be called "GSBase", nor may
24   *    "GSBase" appear in their name, without prior written permission of
25   *    Gargoyle Software Inc.
26   *
27   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
28   * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
29   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARGOYLE
30   * SOFTWARE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
33   * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
36   * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37   */
38  package com.gargoylesoftware.base.util;
39  
40  import java.lang.reflect.Array;
41  import java.util.ArrayList;
42  import java.util.List;
43  import java.util.Collection;
44  
45  /***
46   *  A collection of utility methods dealing with strings
47   *
48   * @version  $Revision: 1.4 $
49   * @author  <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
50   */
51  public class StringUtil {
52      // Private constructor to prevent instantiation
53      private StringUtil() {
54      }
55  
56  
57      /***
58       *  Expand each tab character into the specified numbers of spaces.
59       *
60       * @param  inputString The string to be expanded.
61       * @param  numberOfSpaces The number of space characters to be used for each
62       *      substitution.
63       * @return  The new string with expanded tabs.
64       */
65      public static String expandTabs( final String inputString,
66              final int numberOfSpaces ) {
67          // Are there any tabs?
68          if( inputString.indexOf( '\t' ) == -1 ) {
69              return inputString;
70          }
71  
72          final int inputStringLength = inputString.length();
73          final StringBuffer buffer = new StringBuffer( inputStringLength );
74  
75          final String spaces = nCopies( numberOfSpaces, ' ' );
76  
77          char c;
78          int i;
79          for( i = 0; i < inputStringLength; i++ ) {
80              c = inputString.charAt( i );
81              if( c == '\t' ) {
82                  buffer.append( spaces );
83              }
84              else {
85                  buffer.append( c );
86              }
87          }
88          return buffer.toString();
89      }
90  
91  
92      /***
93       *  Return a string containing the specified number of charToCopy
94       *
95       * @param  copyCount The number of times to copy the character.
96       * @param  charToCopy The character that will be copied.
97       * @return  The new string.
98       */
99      public static String nCopies( final int copyCount,
100             final char charToCopy ) {
101         final StringBuffer buffer = new StringBuffer( copyCount );
102         int i;
103         for( i = 0; i < copyCount; i++ ) {
104             buffer.append( charToCopy );
105         }
106         return buffer.toString();
107     }
108 
109 
110     /***
111      *  Create a string based on all the objects in the array separated by the
112      *  separator string.
113      *
114      * @param  array The items that will be concatenated together
115      * @param  separator The separator string.
116      * @return  The new concatenated string.
117      */
118     private static String joinArray( final Object array, final String separator ) {
119         assertNotNull("array", array);
120         assertNotNull("separator", separator);
121 
122         final int arrayLength = Array.getLength( array );
123 
124         if( arrayLength == 0 ) {
125             return "";
126         }
127 
128         final StringBuffer buffer = new StringBuffer();
129         int i;
130 
131         buffer.append( Array.get( array, 0 ) );
132         for( i = 1; i < arrayLength; i++ ) {
133             buffer.append( separator );
134             buffer.append( Array.get( array, i ) );
135         }
136 
137         return buffer.toString();
138     }
139 
140 
141     /***
142      *  Create a string based on all the objects in the array separated by the
143      *  separator string.
144      *
145      * @param  array The items that will be concatenated together
146      * @param  separator The separator string.
147      * @return  The new concatenated string.
148      */
149     public static String join( final int array[], final String separator ) {
150         return joinArray( array, separator );
151     }
152 
153 
154     /***
155      *  Create a string based on all the objects in the array separated by the
156      *  separator string.
157      *
158      * @param  array The items that will be concatenated together
159      * @param  separator The separator string.
160      * @return  The new concatenated string.
161      */
162     public static String join( final long array[], final String separator ) {
163         return joinArray( array, separator );
164     }
165 
166 
167     /***
168      *  Create a string based on all the objects in the array separated by the
169      *  separator string.
170      *
171      * @param  array The items that will be concatenated together
172      * @param  separator The separator string.
173      * @return  The new concatenated string.
174      */
175     public static String join( final float array[], final String separator ) {
176         return joinArray( array, separator );
177     }
178 
179 
180     /***
181      *  Create a string based on all the objects in the array separated by the
182      *  separator string.
183      *
184      * @param  array The items that will be concatenated together
185      * @param  separator The separator string.
186      * @return  The new concatenated string.
187      */
188     public static String join( final double array[], final String separator ) {
189         return joinArray( array, separator );
190     }
191 
192 
193     /***
194      *  Create a string based on all the objects in the array separated by the
195      *  separator string.
196      *
197      * @param  array The items that will be concatenated together
198      * @param  separator The separator string.
199      * @return  The new concatenated string.
200      */
201 
202     public static String join( final byte array[], final String separator ) {
203 
204         return joinArray( array, separator );
205     }
206 
207 
208 
209     /***
210      *  Create a string based on all the objects in the array separated by the
211      *  separator string.
212      *
213      * @param  array The items that will be concatenated together
214      * @param  separator The separator string.
215      * @return  The new concatenated string.
216      */
217     public static String join( final Object array[], final String separator ) {
218         return joinArray( array, separator );
219     }
220 
221 
222     /***
223      *  Create a string based on all the objects in the collection separated by
224      *  the separator string.
225      *
226      * @param  separator The separator string.
227      * @param  collection The collection containing the objects to join
228      * @return  The new concatenated string.
229      */
230     public static String join( final Collection collection, final String separator ) {
231         return joinArray( collection.toArray(), separator );
232     }
233 
234 
235     /***
236      *  Split the specified line into two strings, spliting at the first
237      *  instance of separator.
238      *
239      * @param  line The line to be split.
240      * @param  separator The separator that will be used to split the string.
241      * @return  An array containing the two strings.
242      */
243 
244     public static String[] splitAtFirst( final String line, final String separator ) {
245 
246         final int index = line.indexOf( separator );
247         String first;
248         String second;
249 
250         if( index == -1 ) {
251             first = line;
252             second = "";
253         }
254         else {
255             first = line.substring( 0, index );
256             second = line.substring( index + separator.length() );
257         }
258 
259         return new String[]{first, second};
260     }
261 
262 
263     /***
264      *  Split the specified line into strings, spliting at each instance of
265      *  separator.
266      *
267      * @param  line The line to be split.
268      * @param  separator The separator that will be used to split the string.
269      * @return  An array containing the strings
270      */
271 
272     public static String[] split( final String line, final String separator ) {
273         assertNotNull("line", line);
274         assertNotNull("separator", separator);
275 
276         if( separator.length() == 0 ) {
277             throw new DetailedIllegalArgumentException( "separator", separator, "May not be empty" );
278         }
279 
280         // Special case when the line is empty
281 
282         if( line.length() == 0 ) {
283             return new String[0];
284         }
285 
286         final int separatorLength = separator.length();
287         final List list = new ArrayList();
288         int previousIndex = 0;
289         int index = line.indexOf( separator );
290 
291         while( index != -1 ) {
292             list.add( line.substring( previousIndex, index ) );
293             previousIndex = index + separatorLength;
294             index = line.indexOf( separator, previousIndex );
295         }
296 
297         list.add( line.substring( previousIndex ) );
298 
299         final String[] stringArray = new String[list.size()];
300         list.toArray( stringArray );
301 
302         return stringArray;
303     }
304 
305 
306     /***
307      *  Perform text substitutions in the source string
308      *
309      * @param  sourceString The original string
310      * @param  match The string to replace
311      * @param  replace The new content to replace with
312      * @return  A new string with all the substitutions done
313      */
314     public static String replace(
315             final String sourceString,
316             final String match,
317             final String replace ) {
318 
319         if( match.length() == 0 ) {
320             return sourceString;
321         }
322 
323         final StringBuffer buffer = new StringBuffer( sourceString.length() );
324 
325         int start = 0;
326         int end = sourceString.indexOf( match );
327         final int matchLength = match.length();
328 
329         while( end != -1 ) {
330             buffer.append( sourceString.substring( start, end ) );
331             buffer.append( replace );
332             start = end + matchLength;
333             end = sourceString.indexOf( match, start );
334         }
335 
336         buffer.append( sourceString.substring( start ) );
337 
338         return buffer.toString();
339     }
340 
341 
342     private static void assertNotNull( final String fieldName, final Object object ) {
343         if( object == null ) {
344             throw new DetailedNullPointerException(fieldName);
345         }
346     }
347 }
348