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}