1 | package spiffy.core.lang; |
2 | |
3 | import java.io.PrintWriter; |
4 | import java.io.StringWriter; |
5 | import java.io.Writer; |
6 | import java.util.HashMap; |
7 | import java.util.Iterator; |
8 | |
9 | /** |
10 | * Helper methods for string manipulations and/or string representations of various entities |
11 | * |
12 | * @author Kasper B. Graversen, (c) 2007 |
13 | */ |
14 | |
15 | public class StringHelper { |
16 | |
17 | /** |
18 | * Given a string check to see if it is in a collection of strings (using <tt>equals()</tt>) |
19 | * |
20 | * @param searchString |
21 | * string to search for. If <tt>null</tt> false is returned. |
22 | * @param searchStringList |
23 | * list of strings to search within |
24 | * @return true if string is in the search list, or false if searchString is <tt>null</tt> or not present in the |
25 | * list |
26 | * @throws IllegalArgumentException |
27 | * when argument SearchStringList has length > 0 |
28 | * @since 0.03 |
29 | */ |
30 | public static boolean in(final String searchString, final String... searchStringList) { |
31 | if( searchString == null ) { return false; } |
32 | if( searchStringList.length == 0 ) { throw new IllegalArgumentException( |
33 | "argument SearchStringList must have length > 0"); } |
34 | |
35 | for(final String s : searchStringList) { |
36 | if( s.equals(searchString) ) { return true; } |
37 | } |
38 | return false; |
39 | } |
40 | |
41 | /** |
42 | * Given a string, trim it, and if different from the string "", check to see if it is in a collection of strings |
43 | * (using <tt>equals()</tt>). |
44 | * <P> |
45 | * This is quite often used in web programming, where input on the server side may either be <tt>null</tt>, |
46 | * <tt>""</tt> or some string. |
47 | * <p> |
48 | * |
49 | * @param searchString |
50 | * string to search for |
51 | * @param searchStringList |
52 | * list of strings to search within |
53 | * @return true if string is in the search list, or false if searchString is <tt>null</tt> or not present in the |
54 | * list |
55 | * @throws IllegalArgumentException |
56 | * when argument SearchStringList has length > 0 |
57 | * @see #in(String, String[]) |
58 | * @since 0.03 |
59 | */ |
60 | public static boolean inAndNonEmpty(final String searchString, final String... searchStringList) { |
61 | if( searchString == null ) { return false; } |
62 | if( searchStringList.length == 0 ) { throw new IllegalArgumentException( |
63 | "argument SearchStringList must have length > 0"); } |
64 | final String trimmedString = searchString.trim(); |
65 | if( trimmedString.equals("") ) { return false; } |
66 | |
67 | for(final String s : searchStringList) { |
68 | if( s.equals(trimmedString) ) { return true; } |
69 | } |
70 | return false; |
71 | } |
72 | |
73 | /** |
74 | * Join 0..n strings separated by a delimiter. The delimiter is not concatenated after the last element. e.g. given |
75 | * an iterator with the elements <tt>", ", "a", "b", "c"</tt> |
76 | * <pre> |
77 | * join(iterator) |
78 | * </pre> |
79 | * |
80 | * becomes |
81 | * |
82 | * <pre> |
83 | * "a, b, c" |
84 | * </pre> |
85 | * |
86 | * @param delimiter |
87 | * the delimiter to insert between each string. |
88 | * @param iterator |
89 | * the iterator of elements to concatenate. |
90 | * @return the delimiter-concatenated string. If <tt>null</tt> is given as input strings, <tt>null</tt> is |
91 | * returned. |
92 | */ |
93 | public static String join(final String delimiter, final Iterator<?> iterator) { |
94 | if( iterator == null ) { return null; } |
95 | |
96 | final StringBuilder sb = new StringBuilder(); |
97 | while(iterator.hasNext()) { |
98 | sb.append(iterator.next().toString()); |
99 | sb.append(delimiter); |
100 | } |
101 | // remove last delimiter |
102 | final int bufLen = sb.length(); |
103 | if( bufLen > 0 ) { // only removed if we ever added anything |
104 | sb.delete(bufLen - delimiter.length(), bufLen); |
105 | } |
106 | return sb.toString(); |
107 | } |
108 | |
109 | /** |
110 | * Join 0..n strings separated by a delimiter. The delimiter is not concatenated after the last element. e.g. |
111 | * |
112 | * <pre> |
113 | * join(", ", "a", "b", "c") |
114 | * </pre> |
115 | * |
116 | * becomes |
117 | * |
118 | * <pre> |
119 | * "a, b, c" |
120 | * </pre> |
121 | * |
122 | * @param delimiter |
123 | * the delimiter to insert between each string. |
124 | * @param strings |
125 | * the array of strings to concatenate. |
126 | * @return the delimiter-concatenated string. If <tt>null</tt> is given as input strings, <tt>null</tt> is |
127 | * returned. |
128 | */ |
129 | public static String join(final String delimiter, final String... strings) { |
130 | if( strings == null ) { return null; } |
131 | if( strings.length == 0 ) { return ""; } |
132 | final StringBuilder sb = new StringBuilder(); |
133 | |
134 | // add first 1.. n-1 |
135 | final int len = strings.length - 1; |
136 | int i = 0; |
137 | for(; i < len; i++) { |
138 | sb.append(strings[i]); |
139 | sb.append(delimiter); |
140 | } |
141 | // add last |
142 | sb.append(strings[i]); |
143 | return sb.toString(); |
144 | } |
145 | |
146 | /** |
147 | * Remove all occurrences of all specified characters. |
148 | * <p> |
149 | * This is an easy way to e.g. remove all formatting chars such as ' ', '\t', '\n' from Strings for easy comparison |
150 | * of code generated String. |
151 | * |
152 | * @param baseString |
153 | * the string to trim |
154 | * @param removeChars |
155 | * the characters to remove |
156 | * @return a string with the specified characters removed. |
157 | */ |
158 | public static String removeAll(final String baseString, final Character... removeChars) { |
159 | final StringBuffer resultString = new StringBuffer(); |
160 | // cache for quick lookup |
161 | final HashMap<Character, Object> charMatchMap = new HashMap<Character, Object>(); |
162 | for(final Character c : removeChars) { |
163 | charMatchMap.put(c, c); |
164 | } |
165 | |
166 | for(int i = 0; i < baseString.length(); i++) { |
167 | final char c = baseString.charAt(i); |
168 | if( charMatchMap.containsKey(c) == false ) { |
169 | resultString.append(c); |
170 | } |
171 | } |
172 | return resultString.toString(); |
173 | } |
174 | |
175 | private static String repeatJoin(final String baseString, final int endSize, final boolean isLeftJoin, |
176 | final String... joinStrings) { |
177 | |
178 | if( baseString == null ) { throw new IllegalArgumentException("Argument baseString is null"); } |
179 | |
180 | if( joinStrings == null ) { throw new IllegalArgumentException("argument joinStrings is null"); } |
181 | |
182 | if( joinStrings.length == 0 ) { return baseString; } |
183 | |
184 | if( endSize < baseString.length() ) { throw new IllegalArgumentException( |
185 | "Argument endSize is less than the length of baseString"); } |
186 | // appending as many times possible |
187 | final int resultingSize = endSize - baseString.length(); |
188 | final StringBuilder joiningStrings = new StringBuilder(resultingSize); |
189 | int i = 0; |
190 | while(true) { |
191 | if( joiningStrings.length() + joinStrings[i].length() <= resultingSize ) { |
192 | joiningStrings.append(joinStrings[i]); |
193 | } else { |
194 | break; |
195 | } |
196 | i = (i + 1) % joinStrings.length;// round-robin the joinStrings |
197 | } |
198 | |
199 | // final join |
200 | if( isLeftJoin ) { |
201 | joiningStrings.append(baseString); |
202 | } else { |
203 | joiningStrings.insert(0, baseString); |
204 | } |
205 | |
206 | return joiningStrings.toString(); |
207 | } |
208 | |
209 | /** |
210 | * Create a string by repeatedly joining/appending one or more strings in front of the string until the resulting |
211 | * string is equal to or as close possible to some length. E.g. * <code> |
212 | * repeatLeftJoin("100", 6, "#")); |
213 | * </code> |
214 | * yields <code>"fully fill", "###100"</code> |
215 | * |
216 | * <code> |
217 | * repeatLeftJoin("100", 6, "##")); |
218 | * </pre> |
219 | * |
220 | * Yields <code> "##100",</code> |
221 | * |
222 | * @param baseString |
223 | * the string to join strings onto |
224 | * @param endSize |
225 | * the resulting size |
226 | * @param joinStrings |
227 | * one or more strings to join onto the basestring. If the empty list is given, the baseString is returned. |
228 | * @return a joined string |
229 | */ |
230 | public static String repeatLeftJoin(final String baseString, final int endSize, final String... joinStrings) { |
231 | return repeatJoin(baseString, endSize, true, joinStrings); |
232 | } |
233 | |
234 | /** |
235 | * Create a string by repeatedly joining/appending one or more strings at the end of the string until the resulting |
236 | * string is equal to or as close possible to some length. E.g. |
237 | * |
238 | * <pre> |
239 | * repeatLeftJoin("100", 6, "#")); |
240 | * </pre> |
241 | * |
242 | * Yields <code>"fully fill", "###100"</code> |
243 | * |
244 | * <pre> |
245 | * repeatLeftJoin("100", 6, "##")); |
246 | * </pre> |
247 | * |
248 | * Yields <code> "##100",</code> |
249 | * |
250 | * @param baseString |
251 | * the string to join strings onto |
252 | * @param endSize |
253 | * the resulting size |
254 | * @param joinStrings |
255 | * one or more strings to join onto the basestring. If the empty list is given, the baseString is |
256 | * returned. |
257 | * @return a joined string |
258 | */ |
259 | public static String repeatRightJoin(final String baseString, final int endSize, final String... joinStrings) { |
260 | return repeatJoin(baseString, endSize, false, joinStrings); |
261 | } |
262 | |
263 | /** |
264 | * Returns a string representation of any throwable (e.g. exceptions) |
265 | * |
266 | * @param throwable |
267 | * the throwable/exception to get a representation from |
268 | * @return a string representing the throwable |
269 | * @since 0.1 |
270 | */ |
271 | public static String toString(final Throwable throwable) { |
272 | final Writer result = new StringWriter(); |
273 | final PrintWriter printWriter = new PrintWriter(result); |
274 | throwable.printStackTrace(printWriter); |
275 | return result.toString(); |
276 | } |
277 | |
278 | } |