Clover Coverage Report - Atlassian Core
Coverage timestamp: Sun Nov 30 2008 18:33:35 CST
127   322   59   9.77
70   230   0.46   13
13     4.54  
1    
 
 
  StringUtils       Line # 9 127 59 82.4% 0.8238095
 
  (14)
 
1    package com.atlassian.core.util;
2   
3    import com.opensymphony.util.TextUtils;
4   
5    import java.util.*;
6    import java.util.regex.Pattern;
7    import java.io.UnsupportedEncodingException;
8   
 
9    public class StringUtils
10    {
11    private static int MAX_LENGTH = 9000;
12    protected static Map stringCharMappings = new HashMap(4); // this may be a race condition due to no synchronisation. However, it hasn't yet been a problem
13   
14   
 
15  7 toggle private static char[][] getMappings(String encoding)
16    {
17  7 char[][] stringChars = (char[][]) stringCharMappings.get(encoding);
18   
19  7 if (stringChars == null)
20    {
21  2 stringChars = new char[MAX_LENGTH][];
22  2 if ("UTF-8".equalsIgnoreCase(encoding) ||
23    "Big5".equalsIgnoreCase(encoding) ||
24    "Windows-1252".equalsIgnoreCase(encoding))
25    {
26    // FIXME: These characters are valid in utf-8
27  1 addMapping(8216, "'", stringChars);
28  1 addMapping(8217, "'", stringChars);
29  1 addMapping(8220, "\"", stringChars);
30  1 addMapping(8221, "\"", stringChars);
31  1 addMapping(8230, "...", stringChars);
32  1 addMapping(8211, "-", stringChars);
33  1 addMapping(183, "- ", stringChars); // replace bullets
34  1 } else if ("ISO-8859-1".equalsIgnoreCase(encoding))
35    {
36  1 addMapping(145, "'", stringChars);
37  1 addMapping(146, "'", stringChars);
38  1 addMapping(147, "\"", stringChars);
39  1 addMapping(148, "\"", stringChars);
40  1 addMapping(133, "...", stringChars);
41  1 addMapping(150, "-", stringChars);
42  1 addMapping(183, "- ", stringChars); // replace bullets
43    }
44    // unicode control characters should be chopped off
45  66 for (int i = 0; i < 32; i++)
46    {
47  64 if (i == 9 || i == 10 || i == 13)
48    {
49  6 continue; // 9, 10, 13 are line feed and carriage return chars
50    } else
51    {
52  58 addMapping(i, "", stringChars);
53    }
54    }
55   
56  2 stringCharMappings.put(encoding, stringChars);
57    }
58   
59  7 return stringChars;
60    }
61   
 
62  72 toggle private static void addMapping(int charsNumericValue, String replaceStr, char[][] mappings)
63    {
64  72 mappings[charsNumericValue] = replaceStr.toCharArray();
65    }
66   
67    /**
68    * replaces "smart quotes" and other problematic characters that appear in JIRA when data is cut and pasted
69    * from a Microsoft word document. <p>
70    * These include smart single and double quotes, ellipses, em-dashes and bullets
71    * (these characters belong to the Windows Code Page 1252 encoding)
72    *
73    * @param s string to simplify
74    * @param encoding eg. UTF-8, Big5, ISO-8859-1 etc.
75    * @return
76    */
 
77  10 toggle public static final String escapeCP1252(String s, String encoding)
78    {
79  10 if (s == null)
80  1 return null;
81   
82  9 int len = s.length();
83  9 if (len == 0)
84  0 return s;
85   
86    // if extended empty string just return it
87  9 String trimmed = s.trim();
88  9 if (trimmed.length() == 0 || ("\"\"").equals(trimmed))
89  2 return trimmed;
90   
91    // initialise the Mapping before encoding
92  7 char[][] stringChars = getMappings(encoding);
93   
94  7 int i = 0;
95    // First loop through String and check if escaping is needed at all
96    // No buffers are copied at this time
97  7 do
98    {
99  109 int index = s.charAt(i);
100  109 if (index >= MAX_LENGTH)
101  0 continue;
102  109 if (stringChars[index] != null)
103    {
104  6 break;
105    }
106    }
107  103 while (++i < len);
108   
109    // If the check went to the end with no escaping then i should be == len now
110    // otherwise we must continue escaping for real
111  7 if (i == len)
112    {
113  1 return s;
114    }
115   
116    // We found a character to escape and broke out at position i
117    // Now copy all characters before that to StringBuffer sb
118    // Since a char[] will be used for copying we might as well get
119    // a complete copy of it so that we can use array indexing instead of charAt
120  6 StringBuffer sb = new StringBuffer(len + 40);
121  6 char[] chars = new char[len];
122    // Copy all chars from the String s to the chars buffer
123  6 s.getChars(0, len, chars, 0);
124    // Append the first i characters that we have checked to the resulting StringBuffer
125  6 sb.append(chars, 0, i);
126  6 int last = i;
127  6 char[] subst = null;
128  312 for (; i < len; i++)
129    {
130  306 char c = chars[i];
131  306 int index = c;
132   
133  306 if (index < stringChars.length)
134  304 subst = stringChars[index];
135    else
136  2 subst = null;
137   
138    // It is faster to append a char[] than a String which is why we use this
139  306 if (subst != null)
140    {
141  78 if (i > last)
142  18 sb.append(chars, last, i - last);
143  78 sb.append(subst);
144  78 last = i + 1;
145    }
146    }
147  6 if (i > last)
148    {
149  4 sb.append(chars, last, i - last);
150    }
151  6 return sb.toString();
152    }
153   
154   
155    /**
156    * Crop a string if it is longer than a certain length, adding the specified suffix.
157    * <p/>
158    * If the string is shorter than the cropAt length, then it is returned unchanged.
159    */
 
160  0 toggle public static String crop(String original, int cropAt, String suffix)
161    {
162  0 if (original == null)
163  0 return null;
164   
165  0 if (original.length() > cropAt)
166    {
167  0 original = original.substring(0, cropAt) + suffix;
168    }
169  0 return original;
170    }
171   
172    /**
173    * Tests to see is a string contains any of the string in the list passed
174    */
 
175  0 toggle public static boolean contains(String value, List possiblyContains)
176    {
177  0 if (value == null)
178    {
179  0 if ((possiblyContains == null || possiblyContains.isEmpty()))
180  0 return true;
181    else
182  0 return false;
183    } else
184    {
185  0 if ((possiblyContains == null || possiblyContains.isEmpty()))
186  0 return false;
187   
188  0 for (int i = 0; i < possiblyContains.size(); i++)
189    {
190  0 if (value.indexOf((String) possiblyContains.get(i)) > -1)
191  0 return true;
192    }
193  0 return false;
194    }
195    }
196   
197    /**
198    * Replaces all occurrences of one string with another.
199    */
 
200  95 toggle public static String replaceAll(final String str, final String oldPattern, final String newPattern)
201    {
202  95 if (str == null) return null;
203  94 if (oldPattern == null || oldPattern.equals("")) return str;
204  92 String remainder = str;
205  92 StringBuffer buf = new StringBuffer(str.length() * 2);
206  92 while (true)
207    {
208  120 int i = remainder.indexOf(oldPattern);
209  120 if (i != -1)
210    {
211  28 buf.append(remainder.substring(0, i));
212  28 buf.append(newPattern);
213  28 remainder = remainder.substring(i + oldPattern.length());
214    } else
215    {
216  92 buf.append(remainder);
217  92 break;
218    }
219    }
220  92 return buf.toString();
221    }
222   
223    /**
224    * Tests if all the characters in the string is an ASCII character
225    */
 
226  8 toggle public static boolean isStringAllASCII(String str)
227    {
228  8 if (str == null)
229  1 return true;
230   
231  27 for (int i = 0; i < str.length(); i++)
232    {
233  23 char c = str.charAt(i);
234  23 if (c < 0 || c > 127)
235    {
236  3 return false;
237    }
238    }
239  4 return true;
240    }
241   
242    /**
243    * Checks if all the characters in the string are from the specified character set
244    */
 
245  8 toggle public static boolean isStringOfCharSet(String string, String charset)
246    {
247  8 if (string == null)
248  1 return true;
249   
250  7 try
251    {
252  7 return (string.equals(new String(string.getBytes(charset), charset)));
253    }
254    catch (UnsupportedEncodingException e)
255    {
256    }
257  0 return false;
258    }
259   
 
260  8 toggle public static boolean isStringISO_8859_1(String string)
261    {
262  8 return isStringOfCharSet(string, "ISO-8859-1");
263    }
264   
 
265  20 toggle public static boolean equalsIgnoreLineTerminators(String s1, String s2)
266    {
267  20 String normalisedValue = normalise(TextUtils.noNull(s1));
268  20 String normalisedCurrentValue = normalise(TextUtils.noNull(s2));
269   
270  20 return normalisedValue.equals(normalisedCurrentValue);
271    }
272   
 
273  40 toggle public static String normalise(String value)
274    {
275    // Replace all instances of '\r\n' with '\n'
276  40 String normalised = replaceAll(value, "\r\n", "\n");
277    // As all '\r\n' combinations have been replaced, the only thing that should be left are single '\r' characters (if any)
278    // Replace these with '\n'
279  40 return replaceAll(normalised, "\r", "\n");
280    }
281   
282    /**
283    * Method will turn a String of comma seperated entities into a String Array.
284    * Spaces before or after the comma will be cropped.
285    *
286    * @param entryString A comma seperated String
287    * @return String Array
288    */
 
289  3 toggle public static String[] splitCommaSeparatedString(String entryString)
290    {
291  3 Pattern commaPattern = Pattern.compile(",");
292  3 String[] parsed = commaPattern.split(entryString);
293  10 for (int i = 0; i < parsed.length; i++)
294    {
295  7 String s = parsed[i];
296  7 s = s.trim();
297    }
298  3 return parsed;
299    }
300   
301    /**
302    * Create a String of comma seperated entries from a Collection.
303    *
304    * @param entries A collection of entries
305    * @return Comma seperated String
306    */
 
307  3 toggle public static String createCommaSeperatedString(Collection entries)
308    {
309  3 if (entries != null)
310    {
311  2 StringBuffer sb = new StringBuffer();
312  5 for (Iterator iterator = entries.iterator(); iterator.hasNext();)
313    {
314  3 String groupName = (String) iterator.next();
315  3 sb.append(groupName);
316  3 if (iterator.hasNext())
317  2 sb.append(",");
318    }
319  2 return sb.toString();
320  1 } else return null;
321    }
322    }