001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019: package org.apache.axis2.util;
020:
021: import java.text.Collator;
022: import java.util.ArrayList;
023: import java.util.Arrays;
024: import java.util.List;
025: import java.util.Locale;
026:
027: /**
028: * JavaUtils
029: */
030: public class JavaUtils {
031: /**
032: * These are java keywords as specified at the following URL (sorted alphabetically).
033: * http://java.sun.com/docs/books/jls/second_edition/html/lexical.doc.html#229308
034: * Note that false, true, and null are not strictly keywords; they are literal values,
035: * but for the purposes of this array, they can be treated as literals.
036: * ****** PLEASE KEEP THIS LIST SORTED IN ASCENDING ORDER ******
037: */
038: static final String keywords[] = { "abstract", "assert", "boolean",
039: "break", "byte", "case", "catch", "char", "class", "const",
040: "continue", "default", "do", "double", "else", "extends",
041: "false", "final", "finally", "float", "for", "goto", "if",
042: "implements", "import", "instanceof", "int", "interface",
043: "long", "native", "new", "null", "package", "private",
044: "protected", "public", "return", "short", "static",
045: "strictfp", "super", "switch", "synchronized", "this",
046: "throw", "throws", "transient", "true", "try", "void",
047: "volatile", "while" };
048:
049: /**
050: * Collator for comparing the strings
051: */
052: static final Collator englishCollator = Collator
053: .getInstance(Locale.ENGLISH);
054:
055: /**
056: * Use this character as suffix
057: */
058: static final char keywordPrefix = '_';
059:
060: /**
061: * Is this an XML punctuation character?
062: */
063: private static boolean isPunctuation(char c) {
064: return '-' == c || '.' == c || ':' == c || '\u00B7' == c
065: || '\u0387' == c || '\u06DD' == c || '\u06DE' == c;
066: } // isPunctuation
067:
068: /**
069: * Checks if the input string is a valid java keyword.
070: *
071: * @return Returns boolean.
072: */
073: public static boolean isJavaKeyword(String keyword) {
074: // None of the java keywords have uppercase characters
075: if (hasUpperCase(keyword)) {
076: return false;
077: }
078: return (Arrays.binarySearch(keywords, keyword, englishCollator) >= 0);
079: }
080:
081: /**
082: * Check if the word has any uppercase letters
083: *
084: * @param word
085: * @return
086: */
087: public static boolean hasUpperCase(String word) {
088: if (word == null) {
089: return false;
090: }
091: int len = word.length();
092: for (int i = 0; i < len; i++) {
093: if (Character.isUpperCase(word.charAt(i))) {
094: return true;
095: }
096: }
097: return false;
098: }
099:
100: /**
101: * Turns a java keyword string into a non-Java keyword string. (Right now
102: * this simply means appending an underscore.)
103: */
104: public static String makeNonJavaKeyword(String keyword) {
105: return keywordPrefix + keyword;
106: }
107:
108: public static String xmlNameToJava(String name) {
109: // protect ourselves from garbage
110: if (name == null || name.length() == 0) {
111: return name;
112: }
113:
114: char[] nameArray = name.toCharArray();
115: int nameLen = name.length();
116: StringBuffer result = new StringBuffer(nameLen);
117: boolean wordStart = false;
118:
119: // The mapping indicates to convert first character.
120: int i = 0;
121: while (i < nameLen
122: && (isPunctuation(nameArray[i]) || !Character
123: .isJavaIdentifierStart(nameArray[i]))) {
124: i++;
125: }
126: if (i < nameLen) {
127: // Decapitalization code used to be here, but we use the
128: // Introspector function now after we filter out all bad chars.
129:
130: result.append(nameArray[i]);
131: //wordStart = !Character.isLetter(nameArray[i]);
132: wordStart = !Character.isLetter(nameArray[i])
133: && nameArray[i] != "_".charAt(0);
134: } else {
135: // The identifier cannot be mapped strictly according to
136: // JSR 101
137: if (Character.isJavaIdentifierPart(nameArray[0])) {
138: result.append("_").append(nameArray[0]);
139: } else {
140: // The XML identifier does not contain any characters
141: // we can map to Java. Using the length of the string
142: // will make it somewhat unique.
143: result.append("_").append(nameArray.length);
144: }
145: }
146:
147: // The mapping indicates to skip over
148: // all characters that are not letters or
149: // digits. The first letter/digit
150: // following a skipped character is
151: // upper-cased.
152: for (++i; i < nameLen; ++i) {
153: char c = nameArray[i];
154:
155: // if this is a bad char, skip it and remember to capitalize next
156: // good character we encounter
157: if (isPunctuation(c) || !Character.isJavaIdentifierPart(c)) {
158: wordStart = true;
159: continue;
160: }
161: if (wordStart && Character.isLowerCase(c)) {
162: result.append(Character.toUpperCase(c));
163: } else {
164: result.append(c);
165: }
166: // If c is not a character, but is a legal Java
167: // identifier character, capitalize the next character.
168: // For example: "22hi" becomes "22Hi"
169: //wordStart = !Character.isLetter(c);
170: wordStart = !Character.isLetter(c) && c != "_".charAt(0);
171: }
172:
173: // covert back to a String
174: String newName = result.toString();
175:
176: // check for Java keywords
177: if (isJavaKeyword(newName)) {
178: newName = makeNonJavaKeyword(newName);
179: }
180:
181: return newName;
182: } // xmlNameToJava
183:
184: /**
185: * Capitalizes the first character of the name.
186: *
187: * @param name
188: * @return Returns String.
189: */
190: public static String capitalizeFirstChar(String name) {
191:
192: if ((name == null) || name.length() == 0) {
193: return name;
194: }
195:
196: char start = name.charAt(0);
197:
198: if (Character.isLowerCase(start)) {
199: start = Character.toUpperCase(start);
200:
201: return start + name.substring(1);
202: }
203:
204: return name;
205: } // capitalizeFirstChar
206:
207: /**
208: * converts an xml name to a java identifier
209: *
210: * @param name
211: * @return java identifier
212: */
213:
214: public static String xmlNameToJavaIdentifier(String name) {
215: String javaName = xmlNameToJava(name);
216: // convert the first letter to lowercase
217: if ((javaName != null) && (javaName.length() > 0)) {
218: javaName = javaName.substring(0, 1).toLowerCase()
219: + javaName.substring(1);
220: }
221:
222: return javaName;
223: }
224:
225: /**
226: * Tests the String 'value':
227: * return 'false' if its 'false', '0', or 'no' - else 'true'
228: * <p/>
229: * Follow in 'C' tradition of boolean values:
230: * false is specific (0), everything else is true;
231: */
232: public static boolean isTrue(String value) {
233: return !isFalseExplicitly(value);
234: }
235:
236: /**
237: * Tests the String 'value':
238: * return 'true' if its 'true', '1', or 'yes' - else 'false'
239: */
240: public static boolean isTrueExplicitly(String value) {
241: return value != null
242: && (value.equalsIgnoreCase("true") || value.equals("1") || value
243: .equalsIgnoreCase("yes"));
244: }
245:
246: /**
247: * Tests the Object 'value':
248: * if its null, return default.
249: * if its a Boolean, return booleanValue()
250: * if its an Integer, return 'false' if its '0' else 'true'
251: * if its a String, return isTrueExplicitly((String)value).
252: * All other types return 'true'
253: */
254: public static boolean isTrueExplicitly(Object value,
255: boolean defaultVal) {
256: if (value == null) {
257: return defaultVal;
258: }
259: if (value instanceof Boolean) {
260: return ((Boolean) value).booleanValue();
261: }
262: if (value instanceof Integer) {
263: return ((Integer) value).intValue() != 0;
264: }
265: if (value instanceof String) {
266: return isTrueExplicitly((String) value);
267: }
268: return true;
269: }
270:
271: public static boolean isTrueExplicitly(Object value) {
272: return isTrueExplicitly(value, false);
273: }
274:
275: /**
276: * Tests the Object 'value':
277: * if its null, return default.
278: * if its a Boolean, return booleanValue()
279: * if its an Integer, return 'false' if its '0' else 'true'
280: * if its a String, return 'false' if its 'false', 'no', or '0' - else 'true'
281: * All other types return 'true'
282: */
283: public static boolean isTrue(Object value, boolean defaultVal) {
284: return !isFalseExplicitly(value, !defaultVal);
285: }
286:
287: public static boolean isTrue(Object value) {
288: return isTrue(value, false);
289: }
290:
291: /**
292: * Tests the String 'value':
293: * return 'true' if its 'false', '0', or 'no' - else 'false'
294: * <p/>
295: * Follow in 'C' tradition of boolean values:
296: * false is specific (0), everything else is true;
297: */
298: public static boolean isFalse(String value) {
299: return isFalseExplicitly(value);
300: }
301:
302: /**
303: * Tests the String 'value':
304: * return 'true' if its null, 'false', '0', or 'no' - else 'false'
305: */
306: public static boolean isFalseExplicitly(String value) {
307: return value == null || value.equalsIgnoreCase("false")
308: || value.equals("0") || value.equalsIgnoreCase("no");
309: }
310:
311: /**
312: * Tests the Object 'value':
313: * if its null, return default.
314: * if its a Boolean, return !booleanValue()
315: * if its an Integer, return 'true' if its '0' else 'false'
316: * if its a String, return isFalseExplicitly((String)value).
317: * All other types return 'false'
318: */
319: public static boolean isFalseExplicitly(Object value,
320: boolean defaultVal) {
321: if (value == null) {
322: return defaultVal;
323: }
324: if (value instanceof Boolean) {
325: return !((Boolean) value).booleanValue();
326: }
327: if (value instanceof Integer) {
328: return ((Integer) value).intValue() == 0;
329: }
330: if (value instanceof String) {
331: return isFalseExplicitly((String) value);
332: }
333: return false;
334: }
335:
336: public static boolean isFalseExplicitly(Object value) {
337: return isFalseExplicitly(value, true);
338: }
339:
340: /**
341: * Tests the Object 'value':
342: * if its null, return default.
343: * if its a Boolean, return booleanValue()
344: * if its an Integer, return 'false' if its '0' else 'true'
345: * if its a String, return 'false' if its 'false', 'no', or '0' - else 'true'
346: * All other types return 'true'
347: */
348: public static boolean isFalse(Object value, boolean defaultVal) {
349: return isFalseExplicitly(value, defaultVal);
350: }
351:
352: public static boolean isFalse(Object value) {
353: return isFalse(value, true);
354: }
355:
356: public static boolean isJavaId(String id) {
357: if (id == null || id.length() == 0 || isJavaKeyword(id)) {
358: return false;
359: }
360: if (!Character.isJavaIdentifierStart(id.charAt(0))) {
361: return false;
362: }
363: for (int i = 1; i < id.length(); i++) {
364: if (!Character.isJavaIdentifierPart(id.charAt(i))) {
365: return false;
366: }
367: }
368: return true;
369: }
370:
371: /**
372: * An empty immutable <code>String</code> array.
373: */
374: public static final String[] EMPTY_STRING_ARRAY = new String[0];
375:
376: /**
377: * <p>Splits the provided text into an array, separator specified.
378: * This is an alternative to using StringTokenizer.</p>
379: * <p/>
380: * <p>The separator is not included in the returned String array.
381: * Adjacent separators are treated as one separator.</p>
382: * <p/>
383: * <p>A <code>null</code> input String returns <code>null</code>.</p>
384: * <p/>
385: * <pre>
386: * StringUtils.split(null, *) = null
387: * StringUtils.split("", *) = []
388: * StringUtils.split("a.b.c", '.') = ["a", "b", "c"]
389: * StringUtils.split("a..b.c", '.') = ["a", "b", "c"]
390: * StringUtils.split("a:b:c", '.') = ["a:b:c"]
391: * StringUtils.split("a\tb\nc", null) = ["a", "b", "c"]
392: * StringUtils.split("a b c", ' ') = ["a", "b", "c"]
393: * </pre>
394: *
395: * @param str the String to parse, may be null
396: * @param separatorChar the character used as the delimiter,
397: * <code>null</code> splits on whitespace
398: * @return an array of parsed Strings, <code>null</code> if null String input
399: */
400: public static String[] split(String str, char separatorChar) {
401: if (str == null) {
402: return null;
403: }
404: int len = str.length();
405: if (len == 0) {
406: return EMPTY_STRING_ARRAY;
407: }
408: List list = new ArrayList();
409: int i = 0, start = 0;
410: boolean match = false;
411: while (i < len) {
412: if (str.charAt(i) == separatorChar) {
413: if (match) {
414: list.add(str.substring(start, i));
415: match = false;
416: }
417: start = ++i;
418: continue;
419: }
420: match = true;
421: i++;
422: }
423: if (match) {
424: list.add(str.substring(start, i));
425: }
426: return (String[]) list.toArray(new String[list.size()]);
427: }
428:
429: public static Class getWrapperClass(Class primitive) {
430: if (primitive == int.class) {
431: return java.lang.Integer.class;
432: } else if (primitive == short.class) {
433: return java.lang.Short.class;
434: } else if (primitive == boolean.class) {
435: return java.lang.Boolean.class;
436: } else if (primitive == byte.class) {
437: return java.lang.Byte.class;
438: } else if (primitive == long.class) {
439: return java.lang.Long.class;
440: } else if (primitive == double.class) {
441: return java.lang.Double.class;
442: } else if (primitive == float.class) {
443: return java.lang.Float.class;
444: } else if (primitive == char.class) {
445: return java.lang.Character.class;
446: }
447:
448: return null;
449: }
450:
451: /**
452: * Scans the parameter string for the parameter search ignoring case when
453: * comparing characters.
454: *
455: * @param string
456: * @param search If test is empty -1 is always returned.
457: * @return -1 if the string was not found or the index of the first matching
458: * character
459: */
460: public static int indexOfIgnoreCase(final String string,
461: final String search) {
462: int index = -1;
463: final int stringLength = string.length();
464: final int testLength = search.length();
465: if (stringLength > 1 || testLength > 1) {
466: final char firstCharOfTest = Character.toLowerCase(search
467: .charAt(0));
468: final int lastStringCharacterToCheck = stringLength
469: - testLength + 1;
470:
471: for (int i = 0; i < lastStringCharacterToCheck; i++) {
472: if (firstCharOfTest == Character.toLowerCase(string
473: .charAt(i))) {
474: index = i;
475: for (int j = 1; j < testLength; j++) {
476: final char c = string.charAt(i + j);
477: final char otherChar = search.charAt(j);
478: if (Character.toLowerCase(c) != Character
479: .toLowerCase(otherChar)) {
480: index = -1;
481: break;
482: }
483: }
484: if (-1 != index) {
485: break;
486: }
487: }
488: }
489: }
490: return index;
491: }
492: }
|