View Javadoc

1   package org.molwind.util;
2   
3   /*
4    * This file is part of Molwind.
5    *
6    * Molwind is free software: you can redistribute it and/or modify
7    * it under the terms of the GNU General Public License as published by
8    * the Free Software Foundation, either version 3 of the License, or
9    * (at your option) any later version.
10   *
11   * Molwind is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14   * GNU General Public License for more details.
15   *
16   * You should have received a copy of the GNU General Public License
17   * along with Molwind. If not, see <http://www.gnu.org/licenses/>.
18   */
19  
20  import java.awt.Color;
21  import java.io.BufferedReader;
22  import java.io.IOException;
23  import java.io.StringReader;
24  import java.math.BigDecimal;
25  import java.text.DateFormat;
26  import java.text.ParseException;
27  import java.text.ParsePosition;
28  import java.text.SimpleDateFormat;
29  import java.util.ArrayList;
30  import java.util.Collection;
31  import java.util.Date;
32  import java.util.Hashtable;
33  import java.util.Iterator;
34  import java.util.Properties;
35  import java.util.StringTokenizer;
36  import java.util.zip.CRC32;
37  
38  /**
39   * The Stringx class provides a collection of static methods for extended
40   * string processing.
41   *
42   * @author <a href="mailto:oliver.karch@molwind.org">Oliver Karch</a>
43   * @version 1.0
44   */
45  public final class Stringx {
46  
47      /**
48       * A list of typical color names.
49       */
50      private static Hashtable < String, Color > colorNames;
51  
52      static {
53          colorNames = new Hashtable();
54          colorNames.put("black", Color.black);
55          colorNames.put("blue", Color.blue);
56          colorNames.put("cyan", Color.cyan);
57          colorNames.put("darkGray", Color.darkGray);
58          colorNames.put("dark-gray", Color.darkGray);
59          colorNames.put("dark_gray", Color.darkGray);
60          colorNames.put("darkgray", Color.darkGray);
61          colorNames.put("gray", Color.gray);
62          colorNames.put("green", Color.green);
63          colorNames.put("lightGray", Color.lightGray);
64          colorNames.put("light-gray", Color.lightGray);
65          colorNames.put("light_gray", Color.lightGray);
66          colorNames.put("lightgray", Color.lightGray);
67          colorNames.put("magenta", Color.magenta);
68          colorNames.put("orange", Color.orange);
69          colorNames.put("pink", Color.pink);
70          colorNames.put("red", Color.red);
71          colorNames.put("white", Color.white);
72          colorNames.put("yellow", Color.yellow);
73      }
74  
75      /**
76       * Empty constructor to prevent the creation of instances.
77       */
78      private Stringx() { }
79  
80      /**
81       * Formats the current date according to the given format string. For
82       * example a valid format string could be <code>dd.MM.YYYY</code>.
83       * <p>
84       * See {@link java.text.SimpleDateFormat} for formatting options.
85       *
86       * @param format
87       *      the format string
88       * @return
89       *      the formated date string
90       */
91      public static String currentDateString(final String format) {
92          SimpleDateFormat formatter = new SimpleDateFormat(format);
93          return formatter.format(new Date());
94      }
95  
96      /**
97       * Formats a given date according to the format string. For example a valid
98       * format string could be <code>dd.MM.YYYY</code>.
99       * <p>
100      * See {@link java.text.SimpleDateFormat} for formatting options.
101      *
102      * @param format
103      *      the format string
104      * @param date
105      *      the date
106      * @return
107      *      the formated date string
108      */
109     public static String getDateString(final String format, final Date date) {
110         SimpleDateFormat formatter = new SimpleDateFormat(format);
111         return formatter.format(date);
112     }
113 
114     /**
115      * Formats the current date according to local formating conventions.
116      *
117      * @return
118      *      the formated date string
119      */
120     public static String localDate() {
121         DateFormat formatter = DateFormat.getDateInstance(DateFormat.SHORT);
122         return formatter.format(new Date());
123     }
124 
125     /**
126      * Formats the current time according to local formating conventions.
127      *
128      * @return
129      *      the formated time string
130      */
131     public static String localTime() {
132         DateFormat formatter = DateFormat.getTimeInstance(DateFormat.SHORT);
133         return formatter.format(new Date());
134     }
135 
136     /**
137      * Formats the current date according to local formating conventions.
138      *
139      * @param date
140      *      milliseconds since era
141      * @return
142      *      the formated date string
143      */
144     public static String localDate(final long date) {
145         DateFormat formatter = DateFormat.getDateInstance(DateFormat.SHORT);
146         return formatter.format(new Date(date));
147     }
148 
149     /**
150      * Formats the current date according to local formating conventions to
151      * display medium format length.
152      *
153      * @param date
154      *      milliseconds since era
155      * @return
156      *      the formated date string
157      */
158     public static String localMediumDate(final long date) {
159         DateFormat formatter = DateFormat.getDateInstance(DateFormat.MEDIUM);
160         return formatter.format(new Date(date));
161     }
162 
163     /**
164      * Parses a date string according to local formating conventions.
165      *
166      * @param dateString
167      *      a date string
168      * @return
169      *      a long representing the date or <code>-1</code> if an error
170      *      occurred
171      */
172     public static long parseDate(final String dateString) {
173         DateFormat formatter = DateFormat.getDateInstance();
174         long longDate;
175 
176         try {
177             Date date = formatter.parse(dateString);
178             longDate = date.getTime();
179         } catch (ParseException pe) {
180             longDate = -1L;
181         }
182 
183         return longDate;
184     }
185 
186     /**
187      * Parses a date string conforming to a given date format pattern.
188      *
189      * @param dateString
190      *      a date string
191      * @param pattern
192      *      a date pattern
193      * @return
194      *      a long representing the date or <code>-1</code> if an error
195      *      occurred
196      */
197     public static long parseDate(final String dateString,
198             final String pattern) {
199         SimpleDateFormat formatter = new SimpleDateFormat(pattern);
200         ParsePosition pp = new ParsePosition(0);
201         Date date = formatter.parse(dateString, pp);
202 
203         if (pp.getErrorIndex() >= 0) {
204             return -1L;
205         }
206 
207         return date.getTime();
208     }
209 
210     /**
211      * Formats the current time according to local formating conventions.
212      *
213      * @param date
214      *      milliseconds since era
215      * @return
216      *      the formated date string
217      */
218     public static String localTime(final long date) {
219         DateFormat formatter = DateFormat.getTimeInstance(DateFormat.SHORT);
220         return formatter.format(new Date(date));
221     }
222 
223     /**
224      * Parses a time string according to local formating conventions.
225      *
226      * @param timeString
227      *      a time string
228      * @return
229      *      a long representing the time or <code>-1</code> if an error
230      *      occurred
231      */
232     public static long parseTime(final String timeString) {
233         DateFormat formatter = DateFormat.getTimeInstance();
234         long longDate;
235 
236         try {
237             Date date = formatter.parse(timeString);
238             longDate = date.getTime();
239         } catch (ParseException pe) {
240             longDate = -1L;
241         }
242 
243         return longDate;
244     }
245 
246     /**
247      * Cuts a substring out of a source string ending at a given delimiter
248      * string.
249      *
250      * @param source
251      *      the source string
252      * @param delimiter
253      *      a delimiter string
254      * @return
255      *      the subtoken
256      */
257     public static String before(final String source, final String delimiter) {
258         int k = source.indexOf(delimiter);
259         if (k > 0) {
260             return source.substring(0, k);
261         }
262         return "";
263     }
264 
265     /**
266      * Tailors a source string to the string beginning after a given delimiter
267      * string.
268      *
269      * @param source
270      *      the source string
271      * @param delimiter
272      *      a delimiter string
273      * @return
274      *      the subtoken
275      */
276     public static String after(final String source, final String delimiter) {
277         int k = source.indexOf(delimiter);
278         if (k >= 0) {
279             return source.substring(k + delimiter.length());
280         }
281         return "";
282     }
283 
284     /**
285      * Determines the string's portion after the last occurrence of the
286      * delimiter.
287      *
288      * @param source
289      *      the source string
290      * @param delimiter
291      *      a delimiter string
292      * @return
293      *      the subtoken
294      */
295     public static String afterLast(final String source,
296             final String delimiter) {
297         int k = source.lastIndexOf(delimiter);
298         if ((k >= 0) && (k + delimiter.length() < source.length())) {
299             return source.substring(k + delimiter.length());
300         }
301         return "";
302     }
303 
304     /**
305      * Discards all characters of a source string after a delimiter string.
306      *
307      * @param source
308      *      the source string
309      * @param delimiter
310      *      a delimiter string
311      * @return
312      *      the shortened string
313      */
314     public static String strcut(final String source, final String delimiter) {
315         int k = source.indexOf(delimiter);
316         if (k > 0) {
317             return source.substring(0, k);
318         }
319         if (k == 0) {
320             return "";
321         }
322         return source;
323     }
324 
325     /**
326      * Determines all tokens of a source string that are delimited by
327      * characters of a delimiter string.
328      *
329      * @param source
330      *      the source string
331      * @param delimiter
332      *      a delimiter string
333      * @return
334      *      the tokens
335      */
336     public static String[] strtok(final String source, final String delimiter) {
337         return strtok(source, delimiter, false);
338     }
339 
340     /**
341      * Creates a string consisting of the array's items separated by the given
342      * delimiter.
343      *
344      * @param items
345      *      the string items
346      * @param delimiter
347      *      a delimiter string
348      * @return
349      *      the concatenated string
350      */
351     public static String toStringList(final Object[] items,
352             final String delimiter) {
353         StringBuffer buffer = new StringBuffer();
354         boolean first = true;
355 
356         if (items != null) {
357             for (int i = 0; i < items.length; i++) {
358                 if (items[i] == null) {
359                     continue;
360                 }
361                 if (!first) {
362                     buffer.append(delimiter);
363                 }
364 
365                 buffer.append(items[i]);
366                 first = false;
367             }
368         }
369         return buffer.toString();
370     }
371 
372     /**
373      * Creates a string consisting of the array's items separated by the given
374      * delimiter.
375      *
376      * @param items
377      *      the string items
378      * @param delimiter
379      *      a delimiter string
380      * @return
381      *      the concatenated string
382      */
383     public static String toStringList(final Collection items,
384             final String delimiter) {
385         StringBuffer buffer = new StringBuffer();
386 
387         if (items != null) {
388             Iterator it = items.iterator();
389             boolean first = true;
390 
391             while (it.hasNext()) {
392                 Object object = it.next();
393                 if (object == null) {
394                     continue;
395                 }
396                 if (!first) {
397                     buffer.append(delimiter);
398                 }
399 
400                 buffer.append(object);
401                 first = false;
402             }
403         }
404         return buffer.toString();
405     }
406 
407     /**
408      * Determines all tokens of a source string that are delimited by
409      * characters of a delimiter string, optionally trims the tokens.
410      *
411      * @param source
412      *      the source string
413      * @param delimiter
414      *      a delimiter string
415      * @param trim
416      *      true if tokens shall be trimmed
417      * @return
418      *      the tokens
419      */
420     public static String[] strtok(final String source, final String delimiter,
421             final boolean trim) {
422         StringTokenizer tokenizer = new StringTokenizer(source, delimiter);
423         String[] tokens = new String[tokenizer.countTokens()];
424         for (int i = 0; tokenizer.hasMoreTokens(); i++) {
425             if (trim) {
426                 tokens[i] = tokenizer.nextToken().trim();
427             } else {
428                 tokens[i] = tokenizer.nextToken();
429             }
430         }
431         return tokens;
432     }
433 
434     /**
435      * Determines all tokens of a source string that are delimited by
436      * whitespaces.
437      *
438      * @param source
439      *      the source string
440      * @return
441      *      the tokens
442      */
443     public static String[] strtok(final String source) {
444         StringTokenizer tokenizer = new StringTokenizer(source);
445         String[] tokens = new String[tokenizer.countTokens()];
446         for (int i = 0; tokenizer.hasMoreTokens(); i++) {
447             tokens[i] = tokenizer.nextToken();
448         }
449         return tokens;
450     }
451 
452     /**
453      * Replaces one occurrence of a string to be substituted in a source
454      * string by a replacing string.
455      *
456      * @param source
457      *      the source string
458      * @param substitute
459      *      the string to be substituted
460      * @param replacement
461      *      the replacing string
462      * @return
463      *      entire string with replaced occurrence
464      */
465     public static String substitute(final String source,
466             final String substitute, final String replacement) {
467         return before(source, substitute) + replacement
468                 + after(source, substitute);
469     }
470 
471     /**
472      * Replaces all occurrences of a string to be substituted in a source
473      * string by a replacing string.
474      *
475      * @param source
476      *      the source string
477      * @param substitute
478      *      the string to be substituted
479      * @param replacement
480      *      the replacing string
481      * @return
482      *      entire string with replaced occurrences
483      */
484     public static String substituteAll(final String source,
485             final String substitute, final String replacement) {
486         String src = source;
487         while (src.indexOf(substitute) >= 0) {
488             src = before(src, substitute) + replacement
489                     + after(src, substitute);
490         }
491         return src;
492     }
493 
494     /**
495      * Extracts a substring from a source string between a left and a right
496      * delimiter string.
497      *
498      * @param source
499      *      the source string
500      * @param leftMark
501      *      left delimiter string
502      * @param rightMark
503      *      right delimiter string
504      * @return
505      *      the subtoken
506      */
507     public static String extract(final String source, final String leftMark,
508             final String rightMark) {
509         String st = after(source, leftMark);
510         return before(st, rightMark);
511     }
512 
513     /**
514      * Extracts a substring from a source string between a left and a right
515      * delimiter string.
516      *
517      * @param source
518      *      the source string
519      * @param leftMark
520      *      the left delimiter string
521      * @param rightMark
522      *      the right delimiter string
523      * @return
524      *      the subtoken
525      */
526     public static String[] extractAll(final String source,
527             final String leftMark, final String rightMark) {
528         int l = 0;
529         int k = 0;
530         ArrayList hits = new ArrayList();
531 
532         while ((k < source.length())
533                 && ((l = source.indexOf(leftMark, k)) > k)) {
534             l += leftMark.length();
535             if ((k = source.indexOf(rightMark, l)) >= l) {
536                 if (l == k) {
537                     hits.add("");
538                 } else {
539                     hits.add(source.substring(l, k));
540                 }
541             }
542             k = l + 1;
543         }
544         String[] extracts = new String[hits.size()];
545         return (String[]) hits.toArray(extracts);
546     }
547 
548     /**
549      * Concatenates a paragraph of text into a single line by removing line
550      * ends and unnecessary blanks (i.e. blanks at the end and the beginning
551      * of each line).
552      *
553      * @param source
554      *      the source string
555      * @return
556      *      the concatenated paragraph
557      */
558     public static String concat(final String source) {
559         BufferedReader reader = new BufferedReader(new StringReader(source));
560         StringBuffer buffer = new StringBuffer();
561         String line = null;
562         boolean first = true;
563 
564         try {
565             do {
566                 line = reader.readLine();
567                 if (line != null) {
568                     line = line.trim();
569                     if (line.length() > 0) {
570                         if (!first) {
571                             buffer.append(" ");
572                         }
573                         first = false;
574                         buffer.append(line);
575                     }
576                 }
577             } while (line != null);
578             reader.close();
579         } catch (IOException ioe) {
580             ioe.printStackTrace();
581         }
582         return buffer.toString();
583     }
584 
585     /**
586      * Deletes all occurrences of a substring from a source string.
587      *
588      * @param source
589      *      the source string.
590      * @param delete
591      *      string to be deleted
592      * @return
593      *      the cleaned up string
594      */
595     public static String deleteAll(final String source, final String delete) {
596         int k = -1;
597         String newString = source;
598 
599         while ((k = newString.indexOf(delete)) >= 0) {
600             String befSt = "";
601             if (k > 0) {
602                 befSt = newString.substring(0, k);
603             }
604             newString = befSt + newString.substring(k + delete.length());
605         }
606         return newString;
607     }
608 
609     /**
610      * Counts the digits of the fraction of a number's string representation of
611      * a source string.
612      *
613      * @param num
614      *      string representation of a number
615      * @return
616      *      the fractional count
617      */
618     public static int fractionDigits(final String num) {
619         int k = num.indexOf(".");
620         if (k >= 0) {
621             if (k == 0) {
622                 return num.length() - 1;
623             }
624             return (num.length() - 1) - k;
625         }
626         return 0;
627     }
628 
629     /**
630      * Deletes all occurrences of a substring between a left delimiter and a
631      * right delimiter string. The delimiter strings will be removed also.
632      *
633      * @param source
634      *      the source string
635      * @param leftMark
636      *      the left delimiter string
637      * @param rightMark
638      *      the right delimiter string
639      * @return
640      *      the cleaned up string
641      */
642     public static String deleteBetweenAll(final String source,
643             final String leftMark, final String rightMark) {
644         int k = -1;
645         String newString = source;
646 
647         while ((k = newString.indexOf(leftMark)) >= 0) {
648             int l = newString.substring(k).indexOf(rightMark);
649             if (l > 0) {
650                 String befSt = "";
651                 if (k > 0) {
652                     befSt = newString.substring(0, k);
653                 }
654                 if (l + k + rightMark.length() < newString.length()) {
655                     newString = befSt + newString.substring(l + k
656                             + rightMark.length());
657                 } else {
658                     newString = befSt + "";
659                 }
660             }
661         }
662         return newString;
663     }
664 
665     /**
666      * Extracts a substring from a source string beginning at a specified
667      * position and ending with a specific delimiter.
668      *
669      * @param source
670      *      the source string
671      * @param index
672      *      the index to start with
673      * @param delimiter
674      *      delimiting string of the subtoken
675      * @return
676      *      the subtoken
677      */
678     public static String subtoken(final String source, final int index,
679             final String delimiter) {
680         String hSt = source.substring(index);
681         int k = hSt.indexOf(delimiter);
682         if (k >= 0) {
683             return source.substring(index, index + k);
684         } else {
685             return "";
686         }
687     }
688 
689     /**
690      * Truncates a string if it exceeds a certain length.
691      *
692      * @param source
693      *      the source string
694      * @param length
695      *      the maximum length
696      * @return
697      *      the truncated string
698      */
699     public static String strtrunc(final String source, final int length) {
700         if (length < source.length()) {
701             return source.substring(0, length);
702         }
703         return source;
704     }
705 
706     /**
707      * Truncates a string if it exceeds a certain length and appends a given
708      * continuation string instead.
709      *
710      * @param source
711      *      the source string
712      * @param length
713      *      the maximum length
714      * @param cont
715      *      the continuation to be appended
716      * @return
717      *      the truncated string
718      */
719     public static String strtrunc(final String source, final int length,
720             final String cont) {
721         if (length < source.length()) {
722             return source.substring(0, length - cont.length()) + cont;
723         }
724         return source;
725     }
726 
727     /**
728      * Removes all leading non-digits and zeros from a string.
729      *
730      * @param source
731      *      the source string
732      * @return
733      *      the trimmed string
734      */
735     public static String trimZero(final String source) {
736         int i = 0;
737         for (i = 0; i < source.length(); i++) {
738             if ((source.charAt(i) != '1')
739                     && (source.charAt(i) != '2')
740                     && (source.charAt(i) != '3')
741                     && (source.charAt(i) != '4')
742                     && (source.charAt(i) != '5')
743                     && (source.charAt(i) != '6')
744                     && (source.charAt(i) != '7')
745                     && (source.charAt(i) != '8')
746                     && (source.charAt(i) != '9')
747                     && (source.charAt(i) != '.')) {
748                 break;
749             }
750         }
751         if (i < source.length()) {
752             return source.substring(i);
753         }
754         return "";
755     }
756 
757     /**
758      * Constructs a string with the specified length that only consists of the
759      * given character.
760      *
761      * @param character
762      *      the character
763      * @param length
764      *      number of characters
765      * @return
766      *      the constructed string
767      */
768     public static String fill(final char character, final int length) {
769         StringBuffer buffer = new StringBuffer();
770         for (int i = 0; i < length; i++) {
771             buffer.append(character);
772         }
773         return buffer.toString();
774     }
775 
776 
777     /**
778      * Breaks up a string into smaller pieces of specified length appended by
779      * the given string.
780      *
781      * @param source
782      *      the source string
783      * @param insert
784      *      the string to insert
785      * @param length
786      *      the maximum line length
787      * @return
788      *      a new string containing newlines
789      */
790     public static String strbreak(final String source, final String insert,
791             final int length) {
792         StringBuffer buffer = new StringBuffer();
793         int i = 0;
794         while (i < source.length()) {
795             int len = Math.min(length, source.length() - i);
796             buffer.append(source.substring(i, len));
797             buffer.append(insert);
798             i += len;
799         }
800         return buffer.toString();
801     }
802 
803     /**
804      * Breaks up a string into smaller pieces of specified length appended by a
805      * newline.
806      *
807      * @param source
808      *      the source string
809      * @param length
810      *      maximum line length
811      * @return
812      *      a new string containing newlines
813      */
814     public static String strnewline(final String source, final  int length) {
815         StringBuffer buffer = new StringBuffer();
816         int i = 0;
817         while (i < source.length()) {
818             int len = Math.min(length, source.length() - i);
819             buffer.append(source.substring(i, len));
820             buffer.append('\n');
821             i += len;
822         }
823         return buffer.toString();
824     }
825 
826     /**
827      * Replaces in the given string all meta character sequences such as
828      * <code>\n</code>, <code>\t</code> etc. by its corresponding character.
829      *
830      * @param string
831      *      string containing meta character sequences
832      * @return
833      *      the processed string
834      */
835     public static String escapeChar(final String string) {
836         StringBuffer buffer = new StringBuffer();
837 
838         for (int i = 0; i < string.length(); i++) {
839             if ((string.charAt(i) == '\\') && (i + 1 < string.length())) {
840                 switch (string.charAt(i + 1)) {
841                     case 'b':
842                         buffer.append('\b');
843                         break;
844                     case 'f':
845                         buffer.append('\f');
846                         break;
847                     case 'n':
848                         buffer.append('\n');
849                         break;
850                     case 'r':
851                         buffer.append('\r');
852                         break;
853                     case 't':
854                         buffer.append('\t');
855                         break;
856                     case '"':
857                         buffer.append('"');
858                         break;
859                     case '\'':
860                         buffer.append('\'');
861                         break;
862                 }
863             } else {
864                 buffer.append(string.charAt(i));
865             }
866         }
867         return buffer.toString();
868     }
869 
870     /**
871      * Converts a String to a boolean value. The given default is returned in
872      * case of a an invalid boolean representation.
873      *
874      * @param string
875      *      the number string
876      * @param def
877      *      the default value
878      * @return
879      *      a boolean value converted from the string
880      */
881     public static boolean toBoolean(final String string, final boolean def) {
882         if (string == null) {
883             return def;
884         }
885 
886         if (string.equalsIgnoreCase("true")
887                 || string.equalsIgnoreCase("on")
888                 || string.equalsIgnoreCase("yes")
889                 || string.equalsIgnoreCase("t")
890                 || string.equalsIgnoreCase("y")
891                 || string.equals("1")) {
892             return true;
893         }
894         if (string.equalsIgnoreCase("false")
895                 || string.equalsIgnoreCase("off")
896                 || string.equalsIgnoreCase("no")
897                 || string.equalsIgnoreCase("f")
898                 || string.equalsIgnoreCase("n")
899                 || string.equals("0")) {
900             return false;
901         }
902 
903         return def;
904     }
905 
906     /**
907      * Converts a String to an int value. The given default is returned in case
908      * of a <code>NumberFormatException</code>.
909      *
910      * @param string
911      *      the number string
912      * @param def
913      *      the default value
914      * @return
915      *      an int value converted from the string
916      */
917     public static int toInt(final String string, final int def) {
918         if (string == null) {
919             return def;
920         }
921 
922         int val;
923 
924         try {
925             val = Integer.parseInt(string.trim());
926         } catch (NumberFormatException nfe) {
927             val = def;
928         }
929         return val;
930     }
931 
932     /**
933      * Converts a String to a float value. The given default is returned in case
934      * of a <code>NumberFormatException</code>.
935      *
936      * @param string
937      *      the number string
938      * @param def
939      *      the default value
940      * @return
941      *      a float value converted from the string
942      */
943     public static float toFloat(final String string, final float def) {
944         if (string == null) {
945             return def;
946         }
947 
948         float val;
949 
950         try {
951             val = Float.parseFloat(string.trim());
952         } catch (NumberFormatException nfe) {
953             val = def;
954         }
955 
956         return val;
957     }
958 
959     /**
960      * Converts a String to a long value. The given default is returned in case
961      * of a <code>NumberFormatException</code>.
962      *
963      * @param string
964      *      the number string
965      * @param def
966      *      the default value
967      * @return
968      *      a long value converted from the string
969      */
970     public static long toLong(final String string, final long def) {
971         if (string == null) {
972             return def;
973         }
974 
975         long val;
976 
977         try {
978             val = Long.parseLong(string.trim());
979         } catch (NumberFormatException nfe) {
980             val = def;
981         }
982         return val;
983     }
984 
985     /**
986      * Converts a String to a double value. The given default is returned in
987      * case of a <code>NumberFormatException</code>.
988      *
989      * @param string
990      *      the number string
991      * @param def
992      *      the default value
993      * @return
994      *      a double value converted from the string
995      */
996     public static double toDouble(final String string, final double def) {
997         if (string == null) {
998             return def;
999         }
1000 
1001         double val;
1002 
1003         try {
1004             val = Double.parseDouble(string.trim());
1005         } catch (NumberFormatException nfe) {
1006             val = def;
1007         }
1008 
1009         return val;
1010     }
1011 
1012     /**
1013      * If the given string is null the default value provided is returned.
1014      *
1015      * @param string
1016      *      the number string
1017      * @param def
1018      *      the default value
1019      * @return
1020      *      a string
1021      */
1022     public static String getDefault(final String string, final String def) {
1023         if (string != null) {
1024             return string;
1025         } else {
1026             return def;
1027         }
1028     }
1029 
1030     /**
1031      * Converts a color name or description like <code>#FFCC00</code> into a
1032      * color object.
1033      *
1034      * @param colorName
1035      *      the color name
1036      * @return
1037      *      a color object, which is black by default or error
1038      */
1039     public static Color toColor(final String colorName) {
1040         Color color = (Color) colorNames.get(colorName.toLowerCase());
1041 
1042         if (color != null) {
1043             return color;
1044         }
1045         if (colorName.startsWith("#")) {
1046             try {
1047                 int rgb = Integer.parseInt(
1048                         colorName.substring(1).toUpperCase(), 16);
1049                 return new Color(rgb);
1050             } catch (NumberFormatException nfe) {
1051                 // TODO Empty catch block
1052             }
1053         } else if ((colorName.startsWith("(") && colorName.endsWith(")"))
1054                 || (colorName.startsWith("{") && colorName.endsWith("}"))) {
1055             String cleanedColorName = colorName.substring(1,
1056                     colorName.length() - 1).trim();
1057             String[] colToks = cleanedColorName.split("\\p{Punct}");
1058             float[] rgb = new float[3];
1059 
1060             for (int i = 0; (i < colToks.length) && (i < rgb.length); i++) {
1061                 try {
1062                     BigDecimal num = new BigDecimal(colToks[0]);
1063                     rgb[i] = num.floatValue();
1064                 } catch (NumberFormatException nfe) {
1065                     rgb[i] = 0f;
1066                 }
1067             }
1068             if ((rgb[0] > 1f) || (rgb[1] > 1f) || (rgb[2] > 1f)) {
1069                 return new Color((int) rgb[0], (int) rgb[1], (int) rgb[2]);
1070             } else {
1071                 return new Color(rgb[0], rgb[1], rgb[2]);
1072             }
1073         } else {
1074             try {
1075                 BigDecimal num = new BigDecimal(colorName);
1076                 int rgb = num.intValue();
1077                 return new Color(rgb);
1078             } catch (NumberFormatException nfe) {
1079                 int num = (colorName.hashCode() & Integer.MAX_VALUE);
1080                 if (num > 0) {
1081                     return new Color(num);
1082                 }
1083             }
1084         }
1085         return Color.black;
1086     }
1087 
1088     /**
1089      * Creates a crc checksum from a String.
1090      *
1091      * @param string
1092      *      the string
1093      * @return
1094      *      long value representing the checksum
1095      */
1096     public static long toCRC(final String string) {
1097         if (string != null) {
1098             CRC32 crc = new CRC32();
1099             crc.update(string.getBytes());
1100             return crc.getValue();
1101         }
1102         return 0;
1103     }
1104 
1105     /**
1106      * Extracts the base class name (i.e. class name w/o package prefix) of
1107      * the given class.
1108      *
1109      * @param clazz
1110      *      the class
1111      * @return
1112      *      the base class name with package prefix stripped
1113      */
1114     public static String getClassName(final Class clazz) {
1115         int k = clazz.getName().lastIndexOf(".");
1116         String rn = null;
1117         if (k > 0) {
1118             rn = clazz.getName().substring(k + 1);
1119         } else {
1120             rn = clazz.getName();
1121         }
1122         return rn;
1123     }
1124 
1125     /**
1126      * Checks whether a given string follows the rules for identifiers or not.
1127      *
1128      * @param token
1129      *      the token to be analyzed
1130      * @return
1131      *      true if the given token complies to identifier rules otherwise
1132      *      false
1133      */
1134     public static boolean isIdentifier(final String token) {
1135         if (!Character.isJavaIdentifierStart(token.charAt(0))) {
1136             return false;
1137         }
1138 
1139         for (int i = 1; i < token.length(); i++) {
1140             if (!Character.isJavaIdentifierPart(token.charAt(i))) {
1141                 return false;
1142             }
1143         }
1144         return true;
1145     }
1146 
1147     /**
1148      * Checks whether a given char can be part of a hex string.
1149      *
1150      * @param character
1151      *      the character to be analyzed
1152      * @return
1153      *      true if the given char can be part of a hex string false otherwise
1154      */
1155     public static boolean isHexDigit(final char character) {
1156         return (Character.isDigit(character)
1157                 || (Character.toUpperCase(character) == 'A')
1158                 || (Character.toUpperCase(character) == 'B')
1159                 || (Character.toUpperCase(character) == 'C')
1160                 || (Character.toUpperCase(character) == 'D')
1161                 || (Character.toUpperCase(character) == 'E')
1162                 || (Character.toUpperCase(character) == 'F'));
1163     }
1164 
1165     /**
1166      * Append a string to the source string if it has not been appended
1167      * already.
1168      *
1169      * @param source
1170      *      the source string
1171      * @param append
1172      *      string to be appended
1173      * @return
1174      *      the concatenated string
1175      */
1176     public static String strapp(final String source, final String append) {
1177         if (source.endsWith(append)) {
1178             return source;
1179         } else {
1180             return (source + append);
1181         }
1182     }
1183 
1184     /**
1185      * Creates a Properties object from a key-value pair string which looks
1186      * something like <code>item1 = value1; item2 = value2; ...</code>
1187      *
1188      * @param itemString
1189      *      a string containing key-value pairs
1190      * @param delimiter
1191      *      delimiter string
1192      * @return
1193      *      the initialized Properties object
1194      */
1195     public static Properties toProperties(final String itemString,
1196             final String delimiter) {
1197         String[] items = itemString.split(delimiter);
1198         Properties props = new Properties();
1199 
1200         for (int i = 0; i < items.length; i++) {
1201             int k = -1;
1202             if (((k = items[i].indexOf("=")) > 0)
1203                     || ((k = items[i].indexOf(":")) > 0)) {
1204                 String pn = items[i].substring(0, k).trim();
1205                 String pv = items[i].substring(k + 1);
1206                 props.put(pn, pv);
1207             }
1208         }
1209         return props;
1210     }
1211 
1212     /**
1213      * Escapes all xml meta-characters in the given string by the corresponding
1214      * entity char sequences. The resulting string can be safely used as an
1215      * attribute value of an xml tag.
1216      *
1217      * @param value
1218      *      the value string
1219      * @return
1220      *      a string where meta-characters have been replaced / escaped
1221      */
1222     public static String escapeXmlAttributeValue(final String value) {
1223         StringBuffer buffer = new StringBuffer();
1224         char[] charArray = value.toCharArray();
1225 
1226         for (int i = 0; i < charArray.length; i++) {
1227             if (charArray[i] == '<') {
1228                 buffer.append("&lt;");
1229             } else if (charArray[i] == '>') {
1230                 buffer.append("&gt;");
1231             } else if (charArray[i] == '&') {
1232                 buffer.append("&amp;");
1233             } else if (charArray[i] == '\"') {
1234                 buffer.append("&quot;");
1235             } else if ((charArray[i] == '\n')
1236                     || (charArray[i] == '\r')
1237                     || (charArray[i] == '\t')
1238                     || (charArray[i] == '\b')
1239                     || (charArray[i] == '\f')) {
1240                 buffer.append("&#");
1241                 buffer.append(String.valueOf((int) charArray[i]));
1242                 buffer.append(";");
1243             } else {
1244                 buffer.append(charArray[i]);
1245             }
1246         }
1247         return buffer.toString();
1248     }
1249 
1250 }