001/* ***** BEGIN LICENSE BLOCK *****
002 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
003 *
004 * The contents of this file are subject to the Mozilla Public License Version
005 * 1.1 (the "License"); you may not use this file except in compliance with
006 * the License. You may obtain a copy of the License at
007 * http://www.mozilla.org/MPL/
008 *
009 * Software distributed under the License is distributed on an "AS IS" basis,
010 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
011 * for the specific language governing rights and limitations under the
012 * License.
013 *
014 * The Original Code is part of dcm4che, an implementation of DICOM(TM) in
015 * Java(TM), hosted at https://github.com/gunterze/dcm4che.
016 *
017 * The Initial Developer of the Original Code is
018 * Agfa Healthcare.
019 * Portions created by the Initial Developer are Copyright (C) 2011
020 * the Initial Developer. All Rights Reserved.
021 *
022 * Contributor(s):
023 * See @authors listed below
024 *
025 * Alternatively, the contents of this file may be used under the terms of
026 * either the GNU General Public License Version 2 or later (the "GPL"), or
027 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
028 * in which case the provisions of the GPL or the LGPL are applicable instead
029 * of those above. If you wish to allow use of your version of this file only
030 * under the terms of either the GPL or the LGPL, and not to allow others to
031 * use your version of this file under the terms of the MPL, indicate your
032 * decision by deleting the provisions above and replace them with the notice
033 * and other provisions required by the GPL or the LGPL. If you do not delete
034 * the provisions above, a recipient may use your version of this file under
035 * the terms of any one of the MPL, the GPL or the LGPL.
036 *
037 * ***** END LICENSE BLOCK ***** */
038
039package org.dcm4che3.util;
040
041import java.net.URL;
042import java.security.AccessController;
043import java.security.PrivilegedAction;
044import java.util.Collection;
045import java.util.StringTokenizer;
046import java.util.regex.Pattern;
047
048/**
049 * @author Gunter Zeilinger <gunterze@gmail.com>
050 */
051public class StringUtils {
052
053    public static String LINE_SEPARATOR = AccessController.doPrivileged(
054            new PrivilegedAction<String>() {
055                public String run() {
056                    return System.getProperty("line.separator");
057                }
058            }
059         );
060
061    public static String[] EMPTY_STRING = {};
062
063    public static StringBuilder appendLine(StringBuilder sb, Object... ss) {
064        for (Object s : ss)
065            sb.append(s);
066        return sb.append(LINE_SEPARATOR);
067    }
068
069    public static String concat(String[] ss, char delim) {
070        int n = ss.length;
071        if (n == 0)
072            return "";
073        
074        if (n == 1) {
075            String s = ss[0];
076            return s != null ? s : "";
077        }
078        int len = n - 1;
079        for (String s : ss)
080            if (s != null)
081                len += s.length();
082
083        char[] cs = new char[len];
084        int off = 0;
085        for (String s : ss) {
086            if (off != 0)
087                cs[off++] = delim;
088            if (s != null) {
089                int l = s.length();
090                s.getChars(0, l, cs, off);
091                off += l;
092            }
093        }
094        return new String(cs);
095    }
096
097    public static String concat(Collection<String> ss, char delim) {
098        int n = ss.size();
099        if (n == 0)
100            return "";
101
102        if (n == 1) {
103            String s = ss.iterator().next();
104            return s != null ? s : "";
105        }
106        int len = n - 1;
107        for (String s : ss)
108            if (s != null)
109                len += s.length();
110
111        char[] cs = new char[len];
112        int off = 0;
113        for (String s : ss) {
114            if (off != 0)
115                cs[off++] = delim;
116            if (s != null) {
117                int l = s.length();
118                s.getChars(0, l, cs, off);
119                off += l;
120            }
121        }
122        return new String(cs);
123    }
124
125    public static Object splitAndTrim(String s, char delim) {
126        int count = 1;
127        int delimPos = -1;
128        while ((delimPos = s.indexOf(delim, delimPos+1)) >= 0)
129            count++;
130
131        if (count == 1)
132            return substring(s, 0, s.length());
133
134        String[] ss = new String[count];
135        int delimPos2 = s.length();
136        while (--count >= 0) {
137            delimPos = s.lastIndexOf(delim, delimPos2-1);
138            ss[count] = substring(s, delimPos+1, delimPos2);
139            delimPos2 = delimPos;
140        }
141        return ss;
142    }
143
144    public static String[] split(String s, char delim) {
145        if (s == null || s.isEmpty())
146            return EMPTY_STRING;
147
148        int count = 1;
149        int delimPos = -1;
150        while ((delimPos = s.indexOf(delim, delimPos+1)) >= 0)
151            count++;
152
153        if (count == 1)
154            return new String[] { s };
155
156        String[] ss = new String[count];
157        int delimPos2 = s.length();
158        while (--count >= 0) {
159            delimPos = s.lastIndexOf(delim, delimPos2-1);
160            ss[count] = s.substring(delimPos+1, delimPos2);
161            delimPos2 = delimPos;
162        }
163        return ss;
164    }
165
166    public static String cut(String s, int index, char delim) {
167        int i = 0;
168        int begin = 0;
169        int end;
170        while ((end = s.indexOf(delim, begin)) >= 0) {
171            if (i++ == index)
172                return s.substring(begin, end);
173            begin = end + 1;
174        }
175        return i == index ? s.substring(begin) : "";
176    }
177
178    private static String substring(String s, int beginIndex, int endIndex) {
179        while (beginIndex < endIndex && s.charAt(beginIndex) <= ' ')
180            beginIndex++;
181        while (beginIndex < endIndex && s.charAt(endIndex - 1) <= ' ')
182            endIndex--;
183        return beginIndex < endIndex ? s.substring(beginIndex, endIndex) : "";
184    }
185
186    public static String trimTrailing(String s) {
187        int endIndex = s.length();
188        while (endIndex > 0 && s.charAt(endIndex - 1) <= ' ')
189            endIndex--;
190        return s.substring(0, endIndex);
191    }
192
193    public static int parseIS(String s) {
194        return s != null && s.length() != 0
195                ? Integer.parseInt(s.charAt(0) == '+' ? s.substring(1) : s)
196                : 0;
197    }
198
199    public static double parseDS(String s) {
200        return s != null && s.length() != 0
201                ? Double.parseDouble(s.replace(',', '.'))
202                : 0;
203    }
204
205    public static String formatDS(float f) {
206        String s = Float.toString(f);
207        int l = s.length();
208        if (s.startsWith(".0", l-2))
209            return s.substring(0, l-2);
210        int e = s.indexOf('E', l-5);
211        return e > 0 && s.startsWith(".0", e-2) ? cut(s, e-2, e)  : s;
212    }
213
214    public static String formatDS(double d) {
215        String s = Double.toString(d);
216        int l = s.length();
217        if (s.startsWith(".0", l-2))
218            return s.substring(0, l-2);
219        int skip = l - 16;
220        int e = s.indexOf('E', l-5);
221        return e < 0 ? (skip > 0 ? s.substring(0, 16) : s)
222                : s.startsWith(".0", e-2) ? cut(s, e-2, e)
223                : skip > 0 ? cut(s, e-skip, e) : s;
224    }
225
226    private static String cut(String s, int begin, int end) {
227        int l = s.length();
228        char[] ch = new char[l-(end-begin)];
229        s.getChars(0, begin, ch, 0);
230        s.getChars(end, l, ch, begin);
231        return new String(ch);
232    }
233
234    public static boolean matches(String s, String key,
235            boolean matchNullOrEmpty, boolean ignoreCase) {
236        if (key == null || key.isEmpty())
237            return true;
238
239        if (s == null || s.isEmpty())
240            return matchNullOrEmpty;
241
242        return containsWildCard(key) 
243                ? compilePattern(key, ignoreCase).matcher(s).matches()
244                : ignoreCase ? key.equalsIgnoreCase(s) : key.equals(s);
245    }
246
247    public static Pattern compilePattern(String key, boolean ignoreCase) {
248        StringTokenizer stk = new StringTokenizer(key, "*?", true);
249        StringBuilder regex = new StringBuilder();
250        while (stk.hasMoreTokens()) {
251            String tk = stk.nextToken();
252            char ch1 = tk.charAt(0);
253            if (ch1 == '*') {
254                regex.append(".*");
255            } else if (ch1 == '?') {
256                regex.append(".");
257            } else {
258                regex.append("\\Q").append(tk).append("\\E");
259            }
260        }
261        return Pattern.compile(regex.toString(),
262                ignoreCase ? Pattern.CASE_INSENSITIVE : 0);
263    }
264
265    public static boolean containsWildCard(String s) {
266        return (s.indexOf('*') >= 0 || s.indexOf('?') >= 0);
267    }
268
269    public static String[] maskNull(String[] ss) {
270        return maskNull(ss, EMPTY_STRING);
271    }
272
273    public static <T> T maskNull(T o, T mask) {
274        return o == null ? mask : o;
275    }
276
277    public static <T> T nullify(T o, T val) {
278        return val.equals(o) ? null : o;
279    }
280
281    public static String maskEmpty(String s, String mask) {
282        return s == null || s.isEmpty() ? mask : s;
283    }
284
285    public static String truncate(String s, int maxlen) {
286        return s.length() > maxlen ? s.substring(0, maxlen) : s;
287    }
288
289    public static <T> boolean equals(T o1, T o2) {
290        return o1 == o2 || o1 != null && o1.equals(o2);
291    }
292
293    public static String replaceSystemProperties(String s) {
294        int i = s.indexOf("${");
295        if (i == -1)
296            return s;
297
298        StringBuilder sb = new StringBuilder(s.length());
299        int j = -1;
300        do {
301            sb.append(s.substring(j+1, i));
302            if ((j = s.indexOf('}', i+2)) == -1) {
303                j = i-1;
304                break;
305            }
306            String val = System.getProperty(s.substring(i+2, j));
307            sb.append(val != null ? val : s.substring(i, j+1));
308            i = s.indexOf("${", j+1);
309        } while (i != -1);
310        sb.append(s.substring(j+1));
311        return sb.toString();
312    }
313
314
315    /**
316     * @deprecated use {@link ResourceLocator#resourceURL(String)} instead. 
317     */
318    @Deprecated
319    public static String resourceURL(String name) {
320        ClassLoader tcl = Thread.currentThread().getContextClassLoader();
321        URL url = tcl.getResource(name);
322        return url != null ? url.toString() : null;
323    }
324
325    public static boolean isUpperCase(String s) {
326        int len = s.length();
327        for (int i = 0; i < len; i++) {
328            char ch = s.charAt(i);
329            if (Character.toUpperCase(ch) != ch)
330                return false;
331        }
332        return len != 0;
333    }
334}