1 /*
2 * $Source$
3 * $Revision$
4 *
5 * Copyright (C) 2000 William Chesters
6 *
7 * Part of Melati (http://melati.org), a framework for the rapid
8 * development of clean, maintainable web applications.
9 *
10 * Melati is free software; Permission is granted to copy, distribute
11 * and/or modify this software under the terms either:
12 *
13 * a) the GNU General Public License as published by the Free Software
14 * Foundation; either version 2 of the License, or (at your option)
15 * any later version,
16 *
17 * or
18 *
19 * b) any version of the Melati Software License, as published
20 * at http://melati.org
21 *
22 * You should have received a copy of the GNU General Public License and
23 * the Melati Software License along with this program;
24 * if not, write to the Free Software Foundation, Inc.,
25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA to obtain the
26 * GNU General Public License and visit http://melati.org to obtain the
27 * Melati Software License.
28 *
29 * Feel free to contact the Developers of Melati (http://melati.org),
30 * if you would like to work out a different arrangement than the options
31 * outlined here. It is our intention to allow Melati to be used by as
32 * wide an audience as possible.
33 *
34 * This program is distributed in the hope that it will be useful,
35 * but WITHOUT ANY WARRANTY; without even the implied warranty of
36 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37 * GNU General Public License for more details.
38 *
39 * Contact details for copyright holder:
40 *
41 * William Chesters <williamc At paneris.org>
42 * http://paneris.org/~williamc
43 * Obrechtstraat 114, 2517VX Den Haag, The Netherlands
44 */
45
46 package org.melati.poem.util;
47
48 /**
49 * An assortment of useful operations on <code>String</code>s.
50 */
51 public final class StringUtils {
52
53
54 /**
55 * As Perl, create an Array from a String by using a
56 * character as the Array delimiter.
57 *
58 * @param s the String to split
59 * @param c the Array delimiter
60 * @return an Array
61 */
62 public static String[] split(String s, char c) {
63 int n = 0;
64 for (int i = s.indexOf(c); i >= 0; i = s.indexOf(c, i + 1))
65 ++n;
66
67 String[] them = new String[n + 1];
68
69 for (int i = 0, m = 0;; ++m) {
70 int j = s.indexOf(c, i);
71 if (j == -1) {
72 them[m] = s.substring(i);
73 break;
74 } else {
75 them[m] = s.substring(i, j);
76 i = j + 1;
77 }
78 }
79
80 return them;
81 }
82
83 /**
84 * @param b the buffer to append to
85 * @param s the String to append
86 * @param character the character to escape
87 */
88 public static void appendEscaped(StringBuffer b, String s, char character) {
89 appendEscaped(b, s, character, '\\');
90 }
91 /**
92 * Append a String to a StringBuffer, and escaping any occurances
93 * of the char in the String.
94 *
95 * @param b the buffer to append to
96 * @param s the String to append
97 * @param character the character to escape
98 * @param escapeChar the character to escape with
99 */
100 public static void appendEscaped(StringBuffer b,
101 String s, char character, char escapeChar) {
102 int l = s.length();
103 for (int i = 0; i < l; ++i) {
104 char c = s.charAt(i);
105 if (c == escapeChar || c == character) {
106 // damn, found one; catch up to here ...
107
108 for (int j = 0; j < i; ++j)
109 b.append(s.charAt(j));
110 b.append(escapeChar);
111 b.append(c);
112
113 // ... and continue
114
115 for (++i; i < l; ++i) {
116 c = s.charAt(i);
117 if (c == escapeChar || c == character)
118 b.append(escapeChar);
119 b.append(c);
120 }
121 return;
122 }
123 }
124
125 b.append(s);
126 }
127
128 /**
129 * Append a String to a StringBuffer, first quoting it with a quote
130 * character and escaping any occurrences of the quote char in the String.
131 *
132 * @param b the buffer to append to
133 * @param s the String to append
134 * @param q the quote character
135 */
136 public static void appendQuoted(StringBuffer b, String s, char q) {
137 b.append(q);
138 appendEscaped(b, s, q);
139 b.append(q);
140 }
141
142 /**
143 * Surround a string in quotes.
144 *
145 * @param i the string to quote
146 * @param q The quote character to use
147 * @return the quoted string
148 */
149 public static String quoted(String i, char q) {
150 StringBuffer b = new StringBuffer();
151 appendQuoted(b, i, q);
152 return b.toString();
153 }
154
155
156 /**
157 * Capitalise the first character of the input string.
158 *
159 * @param name String to capitalise
160 * @return the capitalised string
161 */
162 public static String capitalised(String name) {
163 char suffix[] = name.toCharArray();
164 suffix[0] = Character.toUpperCase(suffix[0]);
165 return new String(suffix);
166 }
167
168 /**
169 * Uncaptialise the first character of the input string.
170 *
171 * @param name String to uncapitalise
172 * @return the uncapitalised string
173 */
174 public static String uncapitalised(String name) {
175 char suffix[] = name.toCharArray();
176 suffix[0] = Character.toLowerCase(suffix[0]);
177 return new String(suffix);
178 }
179
180 /**
181 * As Perl <code>tr</code>; swap any occurrences of any characters in the
182 * <code>from</code> string in the input string with the
183 * corresponding character from the <code>to</code> string.
184 *
185 * <code>
186 * tr("melati", "ait", "osn").equals("melons")
187 * </code>
188 * @param s String to act upon
189 * @param from String containing characters to swap from
190 * @param to String containing characters to swap to
191 * @return the transformed input String
192 */
193 public static String tr(String s, String from, String to) {
194 StringBuffer sNew = null;
195
196 for (int i = 0; i < s.length(); ++i) {
197 int t = from.indexOf(s.charAt(i));
198 if (t != -1) {
199 if (sNew == null)
200 sNew = new StringBuffer(s);
201 sNew.setCharAt(i, to.charAt(t));
202 }
203 }
204
205 return sNew == null ? s : sNew.toString();
206 }
207
208 /**
209 * As Perl <code>tr</code>; swap any occurances of the
210 * <code>from</code> character in the input string with the
211 * corresponding the <code>to</code> character.
212 *
213 * <code>
214 * tr("melati", 'i', 'o').equals("melato")
215 * </code>
216 * @param s String to act upon
217 * @param from character to swap from
218 * @param to character to swap to
219 * @return the transformed input String
220 * @deprecated now use string.replace(old,new)
221 */
222 public static String tr(String s, char from, char to) {
223 StringBuffer sNew = null;
224
225 for (int i = 0; i < s.length(); ++i) {
226 if (s.charAt(i) == from) {
227 if (sNew == null)
228 sNew = new StringBuffer(s);
229 sNew.setCharAt(i, to);
230 }
231 }
232
233 return sNew == null ? s : sNew.toString();
234 }
235
236 /**
237 * Concatenate an array of Strings with a separator.
238 *
239 * @param sep The separator String to use, may be null.
240 * @param xs An array of Strings to concatenate.
241 * @return the concatenated String.
242 */
243 public static String concatenated(String sep, String[] xs) {
244 if (sep == null) sep = "";
245 if (xs.length == 0)
246 return "";
247 else {
248 int l = sep.length() * (xs.length - 1) + xs[0].length();
249 for (int i = 1; i < xs.length; ++i)
250 l += xs[i].length();
251
252 StringBuffer c = new StringBuffer(l);
253
254 c.append(xs[0]);
255 for (int i = 1; i < xs.length; ++i) {
256 c.append(sep);
257 c.append(xs[i]);
258 }
259
260 return c.toString();
261 }
262 }
263
264 private static String allowableChars =
265 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz0123456789";
266
267 /**
268 * Generate a random String.
269 *
270 * @param length the required length of the String returned
271 * @return a random String of upper and lowercase letters and digits
272 */
273 public static String randomString(int length) {
274 String result = "";
275 int j = allowableChars.length();
276 for (int a = 0; a < length; a++) {
277 int index = new Double(Math.random() * j).intValue();
278 result += allowableChars.charAt(index);
279 }
280 return result;
281 }
282
283 /**
284 * Turn an empty String into a null.
285 *
286 * @param s input String, possibly of zero length or null
287 * @return null if input is empty, input otherwise
288 */
289 public static String nulled(String s) {
290 if (s != null && s.equals(""))
291 return null;
292 return s;
293 }
294
295 /**
296 * Turn a null into an empty String.
297 * @param in input String, possibly null
298 * @return empty String if input is null, input otherwise
299 */
300 public static String unNulled(String in) {
301 if (in == null)
302 return "";
303 return in;
304 }
305
306 private static final char[] hexDigits =
307 { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
308 'A', 'B', 'C', 'D', 'E', 'F' };
309
310 /**
311 * Hex encode an Array of bytes.
312 * @param bytes the byte Array
313 * @return the hex representation
314 */
315 public static String hexEncoding(byte[] bytes) {
316 StringBuffer it = new StringBuffer(bytes.length * 2);
317
318 for (int i = 0; i < bytes.length; ++i) {
319 int b = bytes[i];
320 it.append(hexDigits[b >> 4 & 0xF]);
321 it.append(hexDigits[b & 0xF]);
322 }
323
324 return it.toString();
325 }
326
327 /**
328 * Decode a hex char to a byte.
329 *
330 * @param c the char
331 * @return a byte
332 */
333 public static byte hexDecoding(char c) {
334 if ('0' <= c && c <= '9')
335 return (byte) (c - '0');
336 else if ('A' <= c && c <= 'F')
337 return (byte) (0xA + c - 'A');
338 else if ('a' <= c && c <= 'f')
339 return (byte) (0xa + c - 'a');
340 else
341 throw new IllegalArgumentException("Invalid hex digit in string");
342 }
343
344 /**
345 * Decode a hex String into a byte Array.
346 * @param digits the hex String
347 * @return a byte Array
348 */
349 public static byte[] hexDecoding(String digits) {
350
351 int l = digits.length() / 2;
352 if (l * 2 != digits.length())
353 throw new IllegalArgumentException(
354 "Hex string has odd number of digits");
355
356 byte[] it = new byte[l];
357
358 for (int i = 0; i < l; ++i)
359 it[i] =
360 (byte) (hexDecoding(digits.charAt(i * 2)) << 4 |
361 hexDecoding(digits.charAt(i * 2 + 1)));
362
363 return it;
364 }
365
366 /**
367 * Determine whether a String is quoted, with either quoting character.
368 * @param in String to examine
369 * @return whether String is quoted
370 */
371 public static boolean isQuoted(String in) {
372 if (in == null)
373 return false;
374 if (in.length() < 2)
375 return false;
376 if ((in.startsWith("'") || in.startsWith("\""))
377 &&
378 (in.endsWith("'") || in.endsWith("\""))) {
379 return true;
380 }
381 return false;
382 }
383 }