1   /**
2    * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.kernel.util;
24  
25  import com.liferay.portal.kernel.log.Log;
26  import com.liferay.portal.kernel.log.LogFactoryUtil;
27  
28  import java.io.BufferedReader;
29  import java.io.IOException;
30  import java.io.InputStream;
31  import java.io.InputStreamReader;
32  import java.io.StringReader;
33  
34  import java.net.URL;
35  
36  import java.util.ArrayList;
37  import java.util.Enumeration;
38  import java.util.List;
39  import java.util.Map;
40  import java.util.StringTokenizer;
41  
42  /**
43   * <a href="StringUtil.java.html"><b><i>View Source</i></b></a>
44   *
45   * @author Brian Wing Shun Chan
46   *
47   */
48  public class StringUtil {
49  
50      public static String add(String s, String add) {
51          return add(s, add, StringPool.COMMA);
52      }
53  
54      public static String add(String s, String add, String delimiter) {
55          return add(s, add, delimiter, false);
56      }
57  
58      public static String add(
59          String s, String add, String delimiter, boolean allowDuplicates) {
60  
61          if ((add == null) || (delimiter == null)) {
62              return null;
63          }
64  
65          if (s == null) {
66              s = StringPool.BLANK;
67          }
68  
69          if (allowDuplicates || !contains(s, add, delimiter)) {
70              StringMaker sm = new StringMaker();
71  
72              sm.append(s);
73  
74              if (Validator.isNull(s) || s.endsWith(delimiter)) {
75                  sm.append(add);
76                  sm.append(delimiter);
77              }
78              else {
79                  sm.append(delimiter);
80                  sm.append(add);
81                  sm.append(delimiter);
82              }
83  
84              s = sm.toString();
85          }
86  
87          return s;
88      }
89  
90      public static String bytesToHexString(byte[] bytes) {
91          StringMaker sm = new StringMaker(bytes.length * 2);
92  
93          for (int i = 0; i < bytes.length; i++) {
94              String hex = Integer.toHexString(
95                  0x0100 + (bytes[i] & 0x00FF)).substring(1);
96  
97              if (hex.length() < 2) {
98                  sm.append("0");
99              }
100 
101             sm.append(hex);
102         }
103 
104         return sm.toString();
105     }
106 
107     public static boolean contains(String s, String text) {
108         return contains(s, text, StringPool.COMMA);
109     }
110 
111     public static boolean contains(String s, String text, String delimiter) {
112         if ((s == null) || (text == null) || (delimiter == null)) {
113             return false;
114         }
115 
116         StringMaker sm = null;
117 
118         if (!s.endsWith(delimiter)) {
119             sm = new StringMaker();
120 
121             sm.append(s);
122             sm.append(delimiter);
123 
124             s = sm.toString();
125         }
126 
127         sm = new StringMaker();
128 
129         sm.append(delimiter);
130         sm.append(text);
131         sm.append(delimiter);
132 
133         String dtd = sm.toString();
134 
135         int pos = s.indexOf(dtd);
136 
137         if (pos == -1) {
138             sm = new StringMaker();
139 
140             sm.append(text);
141             sm.append(delimiter);
142 
143             String td = sm.toString();
144 
145             if (s.startsWith(td)) {
146                 return true;
147             }
148 
149             return false;
150         }
151 
152         return true;
153     }
154 
155     public static int count(String s, String text) {
156         if ((s == null) || (text == null)) {
157             return 0;
158         }
159 
160         int count = 0;
161 
162         int pos = s.indexOf(text);
163 
164         while (pos != -1) {
165             pos = s.indexOf(text, pos + text.length());
166 
167             count++;
168         }
169 
170         return count;
171     }
172 
173     public static boolean endsWith(String s, char end) {
174         return endsWith(s, (new Character(end)).toString());
175     }
176 
177     public static boolean endsWith(String s, String end) {
178         if ((s == null) || (end == null)) {
179             return false;
180         }
181 
182         if (end.length() > s.length()) {
183             return false;
184         }
185 
186         String temp = s.substring(s.length() - end.length(), s.length());
187 
188         if (temp.equalsIgnoreCase(end)) {
189             return true;
190         }
191         else {
192             return false;
193         }
194     }
195 
196     public static String extractChars(String s) {
197         if (s == null) {
198             return StringPool.BLANK;
199         }
200 
201         StringMaker sm = new StringMaker();
202 
203         char[] c = s.toCharArray();
204 
205         for (int i = 0; i < c.length; i++) {
206             if (Validator.isChar(c[i])) {
207                 sm.append(c[i]);
208             }
209         }
210 
211         return sm.toString();
212     }
213 
214     public static String extractDigits(String s) {
215         if (s == null) {
216             return StringPool.BLANK;
217         }
218 
219         StringMaker sm = new StringMaker();
220 
221         char[] c = s.toCharArray();
222 
223         for (int i = 0; i < c.length; i++) {
224             if (Validator.isDigit(c[i])) {
225                 sm.append(c[i]);
226             }
227         }
228 
229         return sm.toString();
230     }
231 
232     public static String extractFirst(String s, String delimiter) {
233         if (s == null) {
234             return null;
235         }
236         else {
237             String[] array = split(s, delimiter);
238 
239             if (array.length > 0) {
240                 return array[0];
241             }
242             else {
243                 return null;
244             }
245         }
246     }
247 
248     public static String extractLast(String s, String delimiter) {
249         if (s == null) {
250             return null;
251         }
252         else {
253             String[] array = split(s, delimiter);
254 
255             if (array.length > 0) {
256                 return array[array.length - 1];
257             }
258             else {
259                 return null;
260             }
261         }
262     }
263 
264     public static String highlight(String s, String keywords) {
265         return highlight(s, keywords, "<span class=\"highlight\">", "</span>");
266     }
267 
268     public static String highlight(
269         String s, String keywords, String highlight1, String highlight2) {
270 
271         if (s == null) {
272             return null;
273         }
274 
275         // The problem with using a regexp is that it searches the text in a
276         // case insenstive manner but doens't replace the text in a case
277         // insenstive manner. So the search results actually get messed up. The
278         // best way is to actually parse the results.
279 
280         //return s.replaceAll(
281         //  "(?i)" + keywords, highlight1 + keywords + highlight2);
282 
283         StringMaker sm = new StringMaker(StringPool.SPACE);
284 
285         StringTokenizer st = new StringTokenizer(s);
286 
287         while (st.hasMoreTokens()) {
288             String token = st.nextToken();
289 
290             if (token.equalsIgnoreCase(keywords)) {
291                 sm.append(highlight1);
292                 sm.append(token);
293                 sm.append(highlight2);
294             }
295             else {
296                 sm.append(token);
297             }
298 
299             if (st.hasMoreTokens()) {
300                 sm.append(StringPool.SPACE);
301             }
302         }
303 
304         return sm.toString();
305     }
306 
307     public static String lowerCase(String s) {
308         if (s == null) {
309             return null;
310         }
311         else {
312             return s.toLowerCase();
313         }
314     }
315 
316     public static String merge(boolean[] array) {
317         return merge(array, StringPool.COMMA);
318     }
319 
320     public static String merge(boolean[] array, String delimiter) {
321         if (array == null) {
322             return null;
323         }
324 
325         StringMaker sm = new StringMaker();
326 
327         for (int i = 0; i < array.length; i++) {
328             sm.append(String.valueOf(array[i]).trim());
329 
330             if ((i + 1) != array.length) {
331                 sm.append(delimiter);
332             }
333         }
334 
335         return sm.toString();
336     }
337 
338     public static String merge(double[] array) {
339         return merge(array, StringPool.COMMA);
340     }
341 
342     public static String merge(double[] array, String delimiter) {
343         if (array == null) {
344             return null;
345         }
346 
347         StringMaker sm = new StringMaker();
348 
349         for (int i = 0; i < array.length; i++) {
350             sm.append(String.valueOf(array[i]).trim());
351 
352             if ((i + 1) != array.length) {
353                 sm.append(delimiter);
354             }
355         }
356 
357         return sm.toString();
358     }
359 
360     public static String merge(float[] array) {
361         return merge(array, StringPool.COMMA);
362     }
363 
364     public static String merge(float[] array, String delimiter) {
365         if (array == null) {
366             return null;
367         }
368 
369         StringMaker sm = new StringMaker();
370 
371         for (int i = 0; i < array.length; i++) {
372             sm.append(String.valueOf(array[i]).trim());
373 
374             if ((i + 1) != array.length) {
375                 sm.append(delimiter);
376             }
377         }
378 
379         return sm.toString();
380     }
381 
382     public static String merge(int[] array) {
383         return merge(array, StringPool.COMMA);
384     }
385 
386     public static String merge(int[] array, String delimiter) {
387         if (array == null) {
388             return null;
389         }
390 
391         StringMaker sm = new StringMaker();
392 
393         for (int i = 0; i < array.length; i++) {
394             sm.append(String.valueOf(array[i]).trim());
395 
396             if ((i + 1) != array.length) {
397                 sm.append(delimiter);
398             }
399         }
400 
401         return sm.toString();
402     }
403 
404     public static String merge(long[] array) {
405         return merge(array, StringPool.COMMA);
406     }
407 
408     public static String merge(long[] array, String delimiter) {
409         if (array == null) {
410             return null;
411         }
412 
413         StringMaker sm = new StringMaker();
414 
415         for (int i = 0; i < array.length; i++) {
416             sm.append(String.valueOf(array[i]).trim());
417 
418             if ((i + 1) != array.length) {
419                 sm.append(delimiter);
420             }
421         }
422 
423         return sm.toString();
424     }
425 
426     public static String merge(short[] array) {
427         return merge(array, StringPool.COMMA);
428     }
429 
430     public static String merge(short[] array, String delimiter) {
431         if (array == null) {
432             return null;
433         }
434 
435         StringMaker sm = new StringMaker();
436 
437         for (int i = 0; i < array.length; i++) {
438             sm.append(String.valueOf(array[i]).trim());
439 
440             if ((i + 1) != array.length) {
441                 sm.append(delimiter);
442             }
443         }
444 
445         return sm.toString();
446     }
447 
448     public static String merge(List<?> list) {
449         return merge(list, StringPool.COMMA);
450     }
451 
452     public static String merge(List<?> list, String delimiter) {
453         return merge(list.toArray(new Object[list.size()]), delimiter);
454     }
455 
456     public static String merge(Object[] array) {
457         return merge(array, StringPool.COMMA);
458     }
459 
460     public static String merge(Object[] array, String delimiter) {
461         if (array == null) {
462             return null;
463         }
464 
465         StringMaker sm = new StringMaker();
466 
467         for (int i = 0; i < array.length; i++) {
468             sm.append(String.valueOf(array[i]).trim());
469 
470             if ((i + 1) != array.length) {
471                 sm.append(delimiter);
472             }
473         }
474 
475         return sm.toString();
476     }
477 
478     public static String randomize(String s) {
479         return Randomizer.getInstance().randomize(s);
480     }
481 
482     public static String read(ClassLoader classLoader, String name)
483         throws IOException {
484 
485         return read(classLoader, name, false);
486     }
487 
488     public static String read(ClassLoader classLoader, String name, boolean all)
489         throws IOException {
490 
491         if (all) {
492             StringMaker sm = new StringMaker();
493 
494             Enumeration<URL> enu = classLoader.getResources(name);
495 
496             while (enu.hasMoreElements()) {
497                 URL url = enu.nextElement();
498 
499                 InputStream is = url.openStream();
500 
501                 String s = read(is);
502 
503                 if (s != null) {
504                     sm.append(s);
505                     sm.append(StringPool.NEW_LINE);
506                 }
507 
508                 is.close();
509             }
510 
511             return sm.toString().trim();
512         }
513         else {
514             InputStream is = classLoader.getResourceAsStream(name);
515 
516             String s = read(is);
517 
518             is.close();
519 
520             return s;
521         }
522     }
523 
524     public static String read(InputStream is) throws IOException {
525         StringMaker sm = new StringMaker();
526 
527         BufferedReader br = new BufferedReader(new InputStreamReader(is));
528 
529         String line = null;
530 
531         while ((line = br.readLine()) != null) {
532             sm.append(line).append('\n');
533         }
534 
535         br.close();
536 
537         return sm.toString().trim();
538     }
539 
540     public static String remove(String s, String remove) {
541         return remove(s, remove, StringPool.COMMA);
542     }
543 
544     public static String remove(String s, String remove, String delimiter) {
545         if ((s == null) || (remove == null) || (delimiter == null)) {
546             return null;
547         }
548 
549         if (Validator.isNotNull(s) && !s.endsWith(delimiter)) {
550             s += delimiter;
551         }
552 
553         StringMaker sm = new StringMaker();
554 
555         sm.append(delimiter);
556         sm.append(remove);
557         sm.append(delimiter);
558 
559         String drd = sm.toString();
560 
561         sm = new StringMaker();
562 
563         sm.append(remove);
564         sm.append(delimiter);
565 
566         String rd = sm.toString();
567 
568         while (contains(s, remove, delimiter)) {
569             int pos = s.indexOf(drd);
570 
571             if (pos == -1) {
572                 if (s.startsWith(rd)) {
573                     int x = remove.length() + delimiter.length();
574                     int y = s.length();
575 
576                     s = s.substring(x, y);
577                 }
578             }
579             else {
580                 int x = pos + remove.length() + delimiter.length();
581                 int y = s.length();
582 
583                 sm = new StringMaker();
584 
585                 sm.append(s.substring(0, pos));
586                 sm.append(s.substring(x, y));
587 
588                 s =  sm.toString();
589             }
590         }
591 
592         return s;
593     }
594 
595     public static String replace(String s, char oldSub, char newSub) {
596         return replace(s, oldSub, new Character(newSub).toString());
597     }
598 
599     public static String replace(String s, char oldSub, String newSub) {
600         if ((s == null) || (newSub == null)) {
601             return null;
602         }
603 
604         StringMaker sm = new StringMaker();
605 
606         char[] c = s.toCharArray();
607 
608         for (int i = 0; i < c.length; i++) {
609             if (c[i] == oldSub) {
610                 sm.append(newSub);
611             }
612             else {
613                 sm.append(c[i]);
614             }
615         }
616 
617         return sm.toString();
618     }
619 
620     public static String replace(String s, String oldSub, String newSub) {
621         if ((s == null) || (oldSub == null) || (newSub == null)) {
622             return null;
623         }
624 
625         int y = s.indexOf(oldSub);
626 
627         if (y >= 0) {
628             StringMaker sm = new StringMaker();
629 
630             int length = oldSub.length();
631             int x = 0;
632 
633             while (x <= y) {
634                 sm.append(s.substring(x, y));
635                 sm.append(newSub);
636                 x = y + length;
637                 y = s.indexOf(oldSub, x);
638             }
639 
640             sm.append(s.substring(x));
641 
642             return sm.toString();
643         }
644         else {
645             return s;
646         }
647     }
648 
649     public static String replace(String s, String[] oldSubs, String[] newSubs) {
650         if ((s == null) || (oldSubs == null) || (newSubs == null)) {
651             return null;
652         }
653 
654         if (oldSubs.length != newSubs.length) {
655             return s;
656         }
657 
658         for (int i = 0; i < oldSubs.length; i++) {
659             s = replace(s, oldSubs[i], newSubs[i]);
660         }
661 
662         return s;
663     }
664 
665     /**
666      * Returns a string with replaced values. This method will replace all text
667      * in the given string, between the beginning and ending delimiter, with new
668      * values found in the given map. For example, if the string contained the
669      * text <code>[$HELLO$]</code>, and the beginning delimiter was
670      * <code>[$]</code>, and the ending delimiter was <code>$]</code>, and the
671      * values map had a key of <code>HELLO</code> that mapped to
672      * <code>WORLD</code>, then the replaced string will contain the text
673      * <code>[$WORLD$]</code>.
674      *
675      * @param       s the original string
676      * @param       begin the beginning delimiter
677      * @param       end the ending delimiter
678      * @param       values a map of old and new values
679      * @return      a string with replaced values
680      */
681     public static String replaceValues(
682         String s, String begin, String end, Map<String, String> values) {
683 
684         if ((s == null) || (begin == null) || (end == null) ||
685             (values == null) || (values.size() == 0)) {
686 
687             return s;
688         }
689 
690         StringMaker sm = new StringMaker(s.length());
691 
692         int pos = 0;
693 
694         while (true) {
695             int x = s.indexOf(begin, pos);
696             int y = s.indexOf(end, x + begin.length());
697 
698             if ((x == -1) || (y == -1)) {
699                 sm.append(s.substring(pos, s.length()));
700 
701                 break;
702             }
703             else {
704                 sm.append(s.substring(pos, x + begin.length()));
705 
706                 String oldValue = s.substring(x + begin.length(), y);
707 
708                 String newValue = values.get(oldValue);
709 
710                 if (newValue == null) {
711                     newValue = oldValue;
712                 }
713 
714                 sm.append(newValue);
715 
716                 pos = y;
717             }
718         }
719 
720         return sm.toString();
721     }
722 
723     public static String reverse(String s) {
724         if (s == null) {
725             return null;
726         }
727 
728         char[] c = s.toCharArray();
729         char[] reverse = new char[c.length];
730 
731         for (int i = 0; i < c.length; i++) {
732             reverse[i] = c[c.length - i - 1];
733         }
734 
735         return new String(reverse);
736     }
737 
738     public static String safePath(String path) {
739         return StringUtil.replace(
740             path, StringPool.DOUBLE_SLASH, StringPool.SLASH);
741     }
742 
743     public static String shorten(String s) {
744         return shorten(s, 20);
745     }
746 
747     public static String shorten(String s, int length) {
748         return shorten(s, length, "...");
749     }
750 
751     public static String shorten(String s, String suffix) {
752         return shorten(s, 20, suffix);
753     }
754 
755     public static String shorten(String s, int length, String suffix) {
756         if (s == null || suffix == null)  {
757             return null;
758         }
759 
760         if (s.length() > length) {
761             for (int j = length; j >= 0; j--) {
762                 if (Character.isWhitespace(s.charAt(j))) {
763                     length = j;
764 
765                     break;
766                 }
767             }
768 
769             StringMaker sm = new StringMaker();
770 
771             sm.append(s.substring(0, length));
772             sm.append(suffix);
773 
774             s =  sm.toString();
775         }
776 
777         return s;
778     }
779 
780     public static String[] split(String s) {
781         return split(s, StringPool.COMMA);
782     }
783 
784     public static String[] split(String s, String delimiter) {
785         if (s == null || delimiter == null) {
786             return new String[0];
787         }
788 
789         s = s.trim();
790 
791         if (!s.endsWith(delimiter)) {
792             StringMaker sm = new StringMaker();
793 
794             sm.append(s);
795             sm.append(delimiter);
796 
797             s = sm.toString();
798         }
799 
800         if (s.equals(delimiter)) {
801             return new String[0];
802         }
803 
804         List<String> nodeValues = new ArrayList<String>();
805 
806         if (delimiter.equals("\n") || delimiter.equals("\r")) {
807             try {
808                 BufferedReader br = new BufferedReader(new StringReader(s));
809 
810                 String line = null;
811 
812                 while ((line = br.readLine()) != null) {
813                     nodeValues.add(line);
814                 }
815 
816                 br.close();
817             }
818             catch (IOException ioe) {
819                 _log.error(ioe.getMessage());
820             }
821         }
822         else {
823             int offset = 0;
824             int pos = s.indexOf(delimiter, offset);
825 
826             while (pos != -1) {
827                 nodeValues.add(new String(s.substring(offset, pos)));
828 
829                 offset = pos + delimiter.length();
830                 pos = s.indexOf(delimiter, offset);
831             }
832         }
833 
834         return nodeValues.toArray(new String[nodeValues.size()]);
835     }
836 
837     public static boolean[] split(String s, boolean x) {
838         return split(s, StringPool.COMMA, x);
839     }
840 
841     public static boolean[] split(String s, String delimiter, boolean x) {
842         String[] array = split(s, delimiter);
843         boolean[] newArray = new boolean[array.length];
844 
845         for (int i = 0; i < array.length; i++) {
846             boolean value = x;
847 
848             try {
849                 value = Boolean.valueOf(array[i]).booleanValue();
850             }
851             catch (Exception e) {
852             }
853 
854             newArray[i] = value;
855         }
856 
857         return newArray;
858     }
859 
860     public static double[] split(String s, double x) {
861         return split(s, StringPool.COMMA, x);
862     }
863 
864     public static double[] split(String s, String delimiter, double x) {
865         String[] array = split(s, delimiter);
866         double[] newArray = new double[array.length];
867 
868         for (int i = 0; i < array.length; i++) {
869             double value = x;
870 
871             try {
872                 value = Double.parseDouble(array[i]);
873             }
874             catch (Exception e) {
875             }
876 
877             newArray[i] = value;
878         }
879 
880         return newArray;
881     }
882 
883     public static float[] split(String s, float x) {
884         return split(s, StringPool.COMMA, x);
885     }
886 
887     public static float[] split(String s, String delimiter, float x) {
888         String[] array = split(s, delimiter);
889         float[] newArray = new float[array.length];
890 
891         for (int i = 0; i < array.length; i++) {
892             float value = x;
893 
894             try {
895                 value = Float.parseFloat(array[i]);
896             }
897             catch (Exception e) {
898             }
899 
900             newArray[i] = value;
901         }
902 
903         return newArray;
904     }
905 
906     public static int[] split(String s, int x) {
907         return split(s, StringPool.COMMA, x);
908     }
909 
910     public static int[] split(String s, String delimiter, int x) {
911         String[] array = split(s, delimiter);
912         int[] newArray = new int[array.length];
913 
914         for (int i = 0; i < array.length; i++) {
915             int value = x;
916 
917             try {
918                 value = Integer.parseInt(array[i]);
919             }
920             catch (Exception e) {
921             }
922 
923             newArray[i] = value;
924         }
925 
926         return newArray;
927     }
928 
929     public static long[] split(String s, long x) {
930         return split(s, StringPool.COMMA, x);
931     }
932 
933     public static long[] split(String s, String delimiter, long x) {
934         String[] array = split(s, delimiter);
935         long[] newArray = new long[array.length];
936 
937         for (int i = 0; i < array.length; i++) {
938             long value = x;
939 
940             try {
941                 value = Long.parseLong(array[i]);
942             }
943             catch (Exception e) {
944             }
945 
946             newArray[i] = value;
947         }
948 
949         return newArray;
950     }
951 
952     public static short[] split(String s, short x) {
953         return split(s, StringPool.COMMA, x);
954     }
955 
956     public static short[] split(String s, String delimiter, short x) {
957         String[] array = split(s, delimiter);
958         short[] newArray = new short[array.length];
959 
960         for (int i = 0; i < array.length; i++) {
961             short value = x;
962 
963             try {
964                 value = Short.parseShort(array[i]);
965             }
966             catch (Exception e) {
967             }
968 
969             newArray[i] = value;
970         }
971 
972         return newArray;
973     }
974 
975     public static boolean startsWith(String s, char begin) {
976         return startsWith(s, (new Character(begin)).toString());
977     }
978 
979     public static boolean startsWith(String s, String start) {
980         if ((s == null) || (start == null)) {
981             return false;
982         }
983 
984         if (start.length() > s.length()) {
985             return false;
986         }
987 
988         String temp = s.substring(0, start.length());
989 
990         if (temp.equalsIgnoreCase(start)) {
991             return true;
992         }
993         else {
994             return false;
995         }
996     }
997 
998     /**
999      * Return the number of starting letters that s1 and s2 have in common
1000     * before they deviate.
1001     *
1002     * @param       s1 the first string
1003     * @param       s2 the second string
1004     *
1005     * @return      the number of starting letters that s1 and s2 have in common
1006     *              before they deviate
1007     */
1008    public static int startsWithWeight(String s1, String s2) {
1009        if ((s1 == null) || (s2 == null)) {
1010            return 0;
1011        }
1012
1013        char[] charArray1 = s1.toCharArray();
1014        char[] charArray2 = s2.toCharArray();
1015
1016        int i = 0;
1017
1018        for (; (i < charArray1.length) && (i < charArray2.length); i++) {
1019            if (charArray1[i] != charArray2[i]) {
1020                break;
1021            }
1022        }
1023
1024        return i;
1025    }
1026
1027    public static String stripBetween(String s, String begin, String end) {
1028        if ((s == null) || (begin == null) || (end == null)) {
1029            return s;
1030        }
1031
1032        StringMaker sm = new StringMaker(s.length());
1033
1034        int pos = 0;
1035
1036        while (true) {
1037            int x = s.indexOf(begin, pos);
1038            int y = s.indexOf(end, x + begin.length());
1039
1040            if ((x == -1) || (y == -1)) {
1041                sm.append(s.substring(pos, s.length()));
1042
1043                break;
1044            }
1045            else {
1046                sm.append(s.substring(pos, x));
1047
1048                pos = y + end.length();
1049            }
1050        }
1051
1052        return sm.toString();
1053    }
1054
1055    public static String trim(String s) {
1056        return trim(s, null);
1057    }
1058
1059    public static String trim(String s, char c) {
1060        return trim(s, new char[] {c});
1061    }
1062
1063    public static String trim(String s, char[] exceptions) {
1064        if (s == null) {
1065            return null;
1066        }
1067
1068        char[] charArray = s.toCharArray();
1069
1070        int len = charArray.length;
1071
1072        int x = 0;
1073        int y = charArray.length;
1074
1075        for (int i = 0; i < len; i++) {
1076            char c = charArray[i];
1077
1078            if (_isTrimable(c, exceptions)) {
1079                x = i + 1;
1080            }
1081            else {
1082                break;
1083            }
1084        }
1085
1086        for (int i = len - 1; i >= 0; i--) {
1087            char c = charArray[i];
1088
1089            if (_isTrimable(c, exceptions)) {
1090                y = i;
1091            }
1092            else {
1093                break;
1094            }
1095        }
1096
1097        if ((x != 0) || (y != len)) {
1098            return s.substring(x, y);
1099        }
1100        else {
1101            return s;
1102        }
1103    }
1104
1105    public static String trimLeading(String s) {
1106        return trimLeading(s, null);
1107    }
1108
1109    public static String trimLeading(String s, char c) {
1110        return trimLeading(s, new char[] {c});
1111    }
1112
1113    public static String trimLeading(String s, char[] exceptions) {
1114        if (s == null) {
1115            return null;
1116        }
1117
1118        char[] charArray = s.toCharArray();
1119
1120        int len = charArray.length;
1121
1122        int x = 0;
1123        int y = charArray.length;
1124
1125        for (int i = 0; i < len; i++) {
1126            char c = charArray[i];
1127
1128            if (_isTrimable(c, exceptions)) {
1129                x = i + 1;
1130            }
1131            else {
1132                break;
1133            }
1134        }
1135
1136        if ((x != 0) || (y != len)) {
1137            return s.substring(x, y);
1138        }
1139        else {
1140            return s;
1141        }
1142    }
1143
1144    public static String trimTrailing(String s) {
1145        return trimTrailing(s, null);
1146    }
1147
1148    public static String trimTrailing(String s, char c) {
1149        return trimTrailing(s, new char[] {c});
1150    }
1151
1152    public static String trimTrailing(String s, char[] exceptions) {
1153        if (s == null) {
1154            return null;
1155        }
1156
1157        char[] charArray = s.toCharArray();
1158
1159        int len = charArray.length;
1160
1161        int x = 0;
1162        int y = charArray.length;
1163
1164        for (int i = len - 1; i >= 0; i--) {
1165            char c = charArray[i];
1166
1167            if (_isTrimable(c, exceptions)) {
1168                y = i;
1169            }
1170            else {
1171                break;
1172            }
1173        }
1174
1175        if ((x != 0) || (y != len)) {
1176            return s.substring(x, y);
1177        }
1178        else {
1179            return s;
1180        }
1181    }
1182
1183    public static String upperCase(String s) {
1184        if (s == null) {
1185            return null;
1186        }
1187        else {
1188            return s.toUpperCase();
1189        }
1190    }
1191
1192    public static String upperCaseFirstLetter(String s) {
1193        char[] chars = s.toCharArray();
1194
1195        if (chars[0] >= 97 && chars[0] <= 122) {
1196            chars[0] = (char)(chars[0] - 32);
1197        }
1198
1199        return new String(chars);
1200    }
1201
1202    public static String wrap(String text) {
1203        return wrap(text, 80, "\n");
1204    }
1205
1206    public static String wrap(String text, int width, String lineSeparator) {
1207        if (text == null) {
1208            return null;
1209        }
1210
1211        StringMaker sm = new StringMaker();
1212
1213        try {
1214            BufferedReader br = new BufferedReader(new StringReader(text));
1215
1216            String s = StringPool.BLANK;
1217
1218            while ((s = br.readLine()) != null) {
1219                if (s.length() == 0) {
1220                    sm.append(lineSeparator);
1221                }
1222                else {
1223                    String[] tokens = s.split(StringPool.SPACE);
1224                    boolean firstWord = true;
1225                    int curLineLength = 0;
1226
1227                    for (int i = 0; i < tokens.length; i++) {
1228                        if (!firstWord) {
1229                            sm.append(StringPool.SPACE);
1230                            curLineLength++;
1231                        }
1232
1233                        if (firstWord) {
1234                            sm.append(lineSeparator);
1235                        }
1236
1237                        sm.append(tokens[i]);
1238
1239                        curLineLength += tokens[i].length();
1240
1241                        if (curLineLength >= width) {
1242                            firstWord = true;
1243                            curLineLength = 0;
1244                        }
1245                        else {
1246                            firstWord = false;
1247                        }
1248                    }
1249                }
1250            }
1251        }
1252        catch (IOException ioe) {
1253            _log.error(ioe.getMessage());
1254        }
1255
1256        return sm.toString();
1257    }
1258
1259    private static boolean _isTrimable(char c, char[] exceptions) {
1260        if ((exceptions != null) && (exceptions.length > 0)) {
1261            for (int i = 0; i < exceptions.length; i++) {
1262                if (c == exceptions[i]) {
1263                    return false;
1264                }
1265            }
1266        }
1267
1268        return Character.isWhitespace(c);
1269    }
1270
1271    private static Log _log = LogFactoryUtil.getLog(StringUtil.class);
1272
1273}