001 /*
002 * Copyright (c) 1995-2010, The University of Sheffield. See the file
003 * COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
004 *
005 * This file is part of GATE (see http://gate.ac.uk/), and is free
006 * software, licenced under the GNU Library General Public License,
007 * Version 2, June 1991 (in the distribution as file licence.html,
008 * and also available at http://gate.ac.uk/gate/licence.html).
009 *
010 * Hamish Cunningham, 22/02/2000
011 *
012 * $Id: Strings.java 12872 2010-07-08 11:29:23Z thomas_heitz $
013 */
014
015 package gate.util;
016
017 import java.io.*;
018 import java.util.ArrayList;
019 import java.util.Arrays;
020 import java.util.Collection;
021 import java.util.HashMap;
022 import java.util.List;
023 import java.util.Map;
024
025 /** Some utilities for use with Strings. */
026 public class Strings {
027
028 /** Debug flag */
029 private static final boolean DEBUG = false;
030
031 /** What character to pad with. */
032 private static char padChar = ' ';
033
034 /** Local fashion for newlines this year. */
035 private static String newline = System.getProperty("line.separator");
036
037 /** Get local fashion for newlines. */
038 public static String getNl() { return newline; }
039
040 /** Local fashion for path separators. */
041 private static String pathSep = System.getProperty("path.separator");
042
043 /** Get local fashion for path separators (e.g. ":"). */
044 public static String getPathSep() { return pathSep; }
045
046 /** Local fashion for file separators. */
047 private static String fileSep = System.getProperty("file.separator");
048
049 /** Get local fashion for file separators (e.g. "/"). */
050 public static String getFileSep() { return fileSep; }
051
052 /** Add n pad characters to pad. */
053 public static String addPadding(String pad, int n) {
054 StringBuffer s = new StringBuffer(pad);
055 for(int i = 0; i < n; i++)
056 s.append(padChar);
057
058 return s.toString();
059 } // padding
060
061 /** Helper method to add line numbers to a string */
062 public static String addLineNumbers(String text) {
063 return addLineNumbers(text, 1);
064 }
065
066 public static String addLineNumbers(String text, int startLine) {
067 // construct a line reader for the text
068 BufferedReader reader = new BufferedReader(new StringReader(text));
069 String line = null;
070 StringBuffer result = new StringBuffer();
071
072 try {
073 for(int lineNum = startLine; ( line = reader.readLine() ) != null; lineNum++) {
074 String pad;
075 if(lineNum < 10) pad = " ";
076 else pad = "";
077 result.append(pad + lineNum + " " + line + Strings.getNl());
078 }
079 } catch(IOException ie) { }
080
081 return result.toString();
082 } // addLineNumbers
083
084 /**
085 * A method to unescape Java strings, returning a string containing escape
086 * sequences into the respective character. i.e. "\" followed by "t" is turned
087 * into the tab character.
088 *
089 * @param str the string to unescape
090 * @return a new unescaped string of the one passed in
091 */
092 public static String unescape(String str) {
093 if (str == null) return str;
094
095 StringBuilder sb = new StringBuilder(); // string to build
096
097 StringBuilder unicodeStr = new StringBuilder(4); // store unicode sequences
098
099 boolean inUnicode = false;
100 boolean hadSlash = false;
101
102 for (char ch: str.toCharArray()) {
103 if (inUnicode) {
104 unicodeStr.append(ch);
105 if (unicodeStr.length() == 4) {
106 try {
107 int unicodeValue = Integer.parseInt(unicodeStr.toString(), 16);
108 sb.append((char) unicodeValue);
109 unicodeStr.setLength(0);
110 inUnicode = false;
111 hadSlash = false;
112 } catch (NumberFormatException e) {
113 throw new RuntimeException("Couldn't parse unicode value: " + unicodeStr, e);
114 }
115 }
116 continue;
117 }
118 if (hadSlash) {
119 hadSlash = false;
120 switch (ch) {
121 case '\\':
122 sb.append('\\');
123 break;
124 case '\'':
125 sb.append('\'');
126 break;
127 case '\"':
128 sb.append('"');
129 break;
130 case 'r':
131 sb.append('\r');
132 break;
133 case 'f':
134 sb.append('\f');
135 break;
136 case 't':
137 sb.append('\t');
138 break;
139 case 'n':
140 sb.append('\n');
141 break;
142 case 'b':
143 sb.append('\b');
144 break;
145 case 'u':
146 inUnicode = true;
147 break;
148 default :
149 sb.append(ch);
150 break;
151 }
152 continue;
153 } else if (ch == '\\') {
154 hadSlash = true;
155 continue;
156 }
157 sb.append(ch);
158 }
159 if (hadSlash) {
160 sb.append('\\');
161 }
162 return sb.toString();
163 }
164
165 /**
166 * Convert about any object to a human readable string.<br>
167 * Use {@link Arrays#deepToString(Object[])} to convert an array or
168 * a collection.
169 * @param object object to be converted to a string
170 * @return a string representation of the object, the empty string if null.
171 */
172 public static String toString(Object object) {
173 if (object == null) {
174 return "";
175 } else if (object instanceof Object[]) {
176 return Arrays.deepToString((Object[])object);
177 } else if (object instanceof Collection) {
178 return Arrays.deepToString(((Collection)object).toArray());
179 } else {
180 return object.toString();
181 }
182 }
183
184 /**
185 * Create a String representation of a List of String with the format
186 * [value, value].
187 * Escape with a backslash the separator character.
188 * @param list list to convert to one String
189 * @return a String that represent the list
190 * @see #toList(String, String)
191 */
192 public static String toString(List<String> list) {
193 StringBuilder builder = new StringBuilder();
194 builder.append('[');
195 for (String element : list) {
196 // escape list separator
197 String escapedElement = element.replaceAll(",", "\\\\,");
198 builder.append(escapedElement).append(", ");
199 }
200 if (builder.length() > 1) { // remove last list separator
201 builder.delete(builder.length()-2, builder.length());
202 }
203 builder.append("]");
204 return builder.toString();
205 }
206
207 /**
208 * Create a String representation of a Map of String*String with the format
209 * {key=value, key=value}.
210 * Escape with a backslash the separator characters.
211 * @param map map to convert to one String
212 * @return a String that represent the map
213 * @see #toMap(String)
214 */
215 public static String toString(Map<String, String> map) {
216 StringBuilder builder = new StringBuilder();
217 builder.append('{');
218 for (Map.Entry<String, String> entry : map.entrySet()) {
219 // escape list separator
220 String escapedKey = entry.getKey().replaceAll("=", "\\\\=")
221 .replaceAll(",", "\\\\,");
222 String escapedValue = entry.getValue().replaceAll("=", "\\\\=")
223 .replaceAll(",", "\\\\,");
224 builder.append(escapedKey).append("=").append(escapedValue).append(", ");
225 }
226 if (builder.length() > 1) { // remove last list separator
227 builder.delete(builder.length()-2, builder.length());
228 }
229 builder.append("}");
230 return builder.toString();
231 }
232
233 /**
234 * Get back a List of String from its String representation.
235 * Unescape backslashed separator characters.
236 * @param string String to convert to a List
237 * @param separator String that delimits the element of the list
238 * @return a List
239 * @see #toString(java.util.List)
240 */
241 public static List<String> toList(String string, String separator) {
242 List<String> list = new ArrayList<String>();
243 if (string == null
244 || string.length() < 3) {
245 return list;
246 }
247 // remove last character
248 String value = string.substring(0, string.length()-1);
249 int index = 1;
250 int startIndex = 1;
251 int separatorIndex;
252 // split on list separator
253 while ((separatorIndex = value.indexOf(separator, index)) != -1) {
254 // check that the separator is not an escaped character
255 if (value.charAt(separatorIndex-1) != '\\') {
256 list.add(value.substring(startIndex, separatorIndex)
257 // unescape separator
258 .replaceAll("\\\\"+separator.charAt(0), ""+separator.charAt(0)));
259 startIndex = separatorIndex + separator.length();
260 }
261 index = separatorIndex + separator.length();
262 }
263 // last element of the list
264 list.add(value.substring(startIndex));
265 return list;
266 }
267
268 /**
269 * Get back a Map of String*String from its String representation.
270 * Unescape backslashed separator characters.
271 * @param string String to convert to a Map
272 * @return a Map
273 * @see #toString(java.util.Map)
274 */
275 public static Map<String, String> toMap(String string) {
276 Map<String, String> map = new HashMap<String, String>();
277 if (string == null
278 || string.length() < 3) {
279 return map;
280 }
281 List<String> firstList = toList(string, ", ");
282 for (String element : firstList) {
283 List<String> secondList = toList("["+element+"]", "=");
284 if (secondList.size() == 2) {
285 map.put(secondList.get(0), secondList.get(1));
286 } else {
287 Err.prln("Ignoring element: [" + element + "]");
288 Err.prln("Expecting: [key=value]");
289 }
290 }
291 return map;
292 }
293
294 /**
295 * Crop the text in the middle if too long.
296 * @param text text to crop
297 * @param maxLength maximum length of the text
298 * @return cropped text if needed otherwise the same text
299 */
300 public static String crop(String text, int maxLength) {
301 if (text.length() > maxLength) {
302 text = text.substring(0, (maxLength/2)-2) + "..."
303 + text.substring(text.length() - (maxLength/2));
304 }
305 return text;
306 }
307
308 } // class Strings
|