2 * Copyright (C) 2005 The Mir-coders group
4 * This file is part of Mir.
6 * Mir is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * Mir is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Mir; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * In addition, as a special exception, The Mir-coders gives permission to link
21 * the code of this program with any library licensed under the Apache Software License.
22 * You must obey the GNU General Public License in all respects for all of the code used
23 * other than the above mentioned libraries. If you modify this file, you may extend this
24 * exception to your version of the file, but you are not obligated to do so.
25 * If you do not wish to do so, delete this exception statement from your version.
30 import gnu.regexp.REException;
32 import java.text.NumberFormat;
33 import java.util.Calendar;
34 import java.util.Date;
35 import java.util.GregorianCalendar;
36 import java.util.TimeZone;
40 public final class StringUtil {
42 private static RE re_newline2br, re_brbr2p, re_mail, re_url, re_tags,
43 re_tables, re_forbiddenTags;
45 private StringUtil() { } // this avoids contruction
50 re_newline2br = new RE("(\r?\n){1}");
51 re_brbr2p = new RE("(<br>\r?\n<br>){1,}");
52 re_mail = new RE("\\b([a-zA-Z0-9_.-]+)@([a-zA-Z0-9_-]+)\\.([a-zA-Z0-9_.-]+)\\b");
53 re_url = new RE("((https://)|(http://)|(ftp://)){1}([a-zA-Z0-9_-]+).([a-zA-Z0-9_.:-]+)/?([^ \t\r\n<>\\)\\]]+[^ \t\r\n.,<>\\)\\]])");
54 re_tags = new RE("<[^>]*>",RE.REG_ICASE);
55 re_tables = new RE("<[ \t\r\n/]*(table|td|tr)[ \t\r\n]*>",RE.REG_ICASE);
56 re_forbiddenTags = new RE("<[ \t\r\n/]*(html|meta|body|head|script)[ \t\r\n]*>",RE.REG_ICASE);
58 catch (REException e){
59 System.err.println("FATAL: StringUtil: could not precompile REGEX: "+e.toString());
64 * Formats a number with the specified minimum and maximum number of digits.
66 public static synchronized String zeroPaddingNumber(long value, int minDigits,
69 NumberFormat numberFormat = NumberFormat.getInstance();
70 numberFormat.setMinimumIntegerDigits(minDigits);
71 numberFormat.setMaximumIntegerDigits(maxDigits);
72 return numberFormat.format(value);
76 * Wandelt Datum in einen 8-ziffrigen String um (yyyymmdd)
78 * @return 8-ziffriger String (yyyymmdd)
81 public static final String date2webdbDate (GregorianCalendar theDate) {
82 StringBuffer webdbDate = new StringBuffer();
83 webdbDate.append(String.valueOf(theDate.get(Calendar.YEAR)));
84 webdbDate.append(pad2(theDate.get(Calendar.MONTH) + 1));
85 webdbDate.append(pad2(theDate.get(Calendar.DATE)));
87 return webdbDate.toString();
91 * Wandelt Calendar in einen 12-ziffrigen String um (yyyymmddhhmm)
93 * @return 12-ziffriger String (yyyymmdd)
96 public static final String date2webdbDateTime (GregorianCalendar theDate) {
97 StringBuffer webdbDate = new StringBuffer();
98 webdbDate.append(String.valueOf(theDate.get(Calendar.YEAR)));
99 webdbDate.append(pad2(theDate.get(Calendar.MONTH) + 1));
100 webdbDate.append(pad2(theDate.get(Calendar.DATE)));
101 webdbDate.append(pad2(theDate.get(Calendar.HOUR)));
102 webdbDate.append(pad2(theDate.get(Calendar.MINUTE)));
104 return webdbDate.toString();
108 * Return a http://www.w3.org/TR/NOTE-datetime formatted date (yyyy-mm-ddThh:mm:ssTZ)
110 * @return w3approved datetime
113 public static final String date2w3DateTime (GregorianCalendar theDate) {
114 StringBuffer webdbDate = new StringBuffer();
115 webdbDate.append(String.valueOf(theDate.get(Calendar.YEAR)));
116 webdbDate.append("-");
117 webdbDate.append(pad2(theDate.get(Calendar.MONTH) + 1));
118 webdbDate.append("-");
119 webdbDate.append(pad2(theDate.get(Calendar.DATE)));
120 webdbDate.append("T");
121 webdbDate.append(pad2(theDate.get(Calendar.HOUR_OF_DAY)));
122 webdbDate.append(":");
123 webdbDate.append(pad2(theDate.get(Calendar.MINUTE)));
124 webdbDate.append(":");
125 webdbDate.append(pad2(theDate.get(Calendar.SECOND)));
126 //assumes you are an hour-multiple away from UTC....
127 int offset=(theDate.get(Calendar.ZONE_OFFSET)/(60*60*1000));
129 webdbDate.append("-");
132 webdbDate.append("+");
134 webdbDate.append(pad2(Math.abs(offset)));
135 webdbDate.append(":00");
136 return webdbDate.toString();
140 * wandelt Calendar in dd.mm.yyyy / hh.mm um
142 * @return String mit (dd.mm.yyyy / hh.mm um)
144 public static String date2readableDateTime (GregorianCalendar theDate) {
145 String readable = "";
147 readable += pad2(theDate.get(Calendar.DATE));
148 readable += "." + pad2(theDate.get(Calendar.MONTH) + 1);
149 readable += "." + String.valueOf(theDate.get(Calendar.YEAR));
150 hour = theDate.get(Calendar.HOUR);
151 if (theDate.get(Calendar.AM_PM) == Calendar.PM)
153 readable += " / " + pad2(hour);
154 readable += ":" + pad2(theDate.get(Calendar.MINUTE));
159 * deleteForbiddenTags
160 * this method deletes all <script>, <body> and <head>-tags
162 public static final String deleteForbiddenTags(String haystack) {
163 return re_forbiddenTags.substituteAll(haystack,"");
167 * deleteHTMLTableTags
168 * this method deletes all <table>, <tr> and <td>-tags
170 public static final String deleteHTMLTableTags(String haystack) {
171 return re_tables.substituteAll(haystack,"");
175 * wandelt eine Datum in einen 8-buchstabigen String, der durch <code>/</code>
179 * @return String mit <code>/yyyy/mm/dd</code>
181 public static final String webdbDate2path (String webdbDate) {
182 StringBuffer path = new StringBuffer();
183 path.append("/").append(webdbDate.substring(0, 4));
184 path.append("/").append(webdbDate.substring(4, 6));
187 //path.append("/").append(webdbDate.substring(6, 8));
188 return path.toString();
192 * Replaces in <code>haystack</code> matching <code>pattern</code> by <code>substitute</code>
196 * @return String with replacements.
198 public static String regexpReplace(String haystack, String pattern, String substitute) {
200 RE regex = new RE(pattern);
201 return regex.substituteAll(haystack,substitute);
202 } catch(REException ex){
208 * L?scht <code>/</code> am Ende des Strings, falls vorhanden
210 * @return String ohne <code>/</code> am Ende
212 public static final String removeSlash (String path) {
213 return path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length()
218 * formatiert eine Zahl (0-99) zweistellig (z.B. 5 -> 05)
219 * @return zwistellige Zahl
221 public static String pad2 (int number) {
222 return number < 10 ? "0" + number : String.valueOf(number);
226 * formatiert eine Zahl (0-999) dreistellig (z.B. 7 -> 007)
228 * @return 3-stellige Zahl
230 public static String pad3 (int number) {
231 return number < 10 ? "00" + number : number < 100 ? "0" + number : String.valueOf(number);
235 * Liefert Default-Wert def zur?ck, wenn String <code>s</code>
240 * @return geparster int aus s oder def
242 public static int parseInt(String s, int def) {
243 if (s == null) return def;
245 return Integer.parseInt(s);
246 } catch (NumberFormatException e) {
253 * convertNewline2P ist eine regex-routine zum umwandeln von 2 oder mehr newlines (\n)
254 * in den html-tag <p>
255 * nur sinnvoll, wenn text nicht im html-format eingegeben
257 private static String convertNewline2P(String haystack) {
258 return re_brbr2p.substituteAll(haystack,"\n</p><p>");
262 * convertNewline2Break ist eine regex-routine zum umwandeln von 1 newline (\n)
263 * in den html-tag <br>
264 * nur sinnvoll, wenn text nicht im html-format eingegeben
266 private static String convertNewline2Break(String haystack) {
267 return re_newline2br.substituteAll(haystack,"$0<br />");
271 * createMailLinks wandelt text im email-adressenformat
272 * in einen klickbaren link um
273 * nur sinnvoll, wenn text nicht im html-format eingegeben
275 private static String createMailLinks(String haystack) {
276 return re_mail.substituteAll(haystack,"<a href=\"mailto:$0\">$0</a>");
281 * createMailLinks wandelt text im email-adressenformat
282 * in einen klickbaren link um
283 * nur sinnvoll, wenn text nicht im html-format eingegeben
285 private static String createMailLinks(String haystack, String imageRoot, String mailImage) {
286 return re_mail.substituteAll(haystack,"<img src=\""+imageRoot+"/"+mailImage+"\" border=\"0\"/> <a href=\"mailto:$0\">$0</a>");
291 * createURLLinks wandelt text im url-format
292 * in einen klickbaren link um
293 * nur sinnvoll, wenn text nicht im html-format eingegeben
295 private static String createURLLinks(String haystack) {
296 return re_url.substituteAll(haystack,"<a href=\"$0\">$0</a>");
300 * this routine takes text in url format and makes
301 * a clickaeble "<href>" link removing any "illegal" html tags
302 * @param haystack the url
303 * @param title the href link text
304 * @param imageRoot the place to find icons
305 * @param extImage the url of the icon to show next to the link
306 * @return a String containing the url
308 private static String createURLLinks(String haystack, String title, String imageRoot,String extImage) {
310 return re_url.substituteAll(haystack,"<img src=\""+imageRoot+"/"+extImage+"\" border=\"0\"/> <a href=\"$0\">$0</a>");
312 title = removeHTMLTags(title);
313 return re_url.substituteAll(haystack,"<img src=\""+imageRoot+"/"+extImage+"\" border=\"0\"/> <a href=\"$0\">"+title+"</a>");
317 * this routine takes text in url format and makes
318 * a clickaeble "<href>" link removing any "illegal" html tags
319 * @param haystack the url
320 * @param imageRoot the place to find icons
321 * @param extImage the url of the icon to show next to the link
322 * @param intImage unused
323 * @return a String containing the url
325 private static String createURLLinks(String haystack, String title, String imageRoot,String extImage,String intImage) {
326 return createURLLinks(haystack, title, imageRoot, extImage);
330 * this method deletes all html tags
332 public static String removeHTMLTags(String haystack){
333 return re_tags.substituteAll(haystack,"");
338 * createHTML ruft alle regex-methoden zum unwandeln eines nicht
339 * htmlcodierten string auf und returnt einen htmlcodierten String
341 public static String createHTML(String content){
342 content=convertNewline2Break(content);
343 content=convertNewline2P(content);
344 content=createMailLinks(content);
345 content=createURLLinks(content);
351 * createHTML ruft alle regex-methoden zum unwandeln eines nicht
352 * htmlcodierten string auf und returnt einen htmlcodierten String
354 public static String createHTML(String content,String producerDocRoot,String mailImage,String extImage,String intImage){
355 content=convertNewline2Break(content);
356 content=convertNewline2P(content);
357 content=createMailLinks(content, producerDocRoot,mailImage);
358 content=createURLLinks(content, null, producerDocRoot, extImage, intImage);
364 * Converts mir's horrible internal date format (yyyy-MM-dd HH:mm:ss+zz) into a java Date
366 * @param anInternalDate
368 public static Date convertMirInternalDateToDate(String anInternalDate) {
369 Calendar calendar = new GregorianCalendar();
379 year = Integer.parseInt(anInternalDate.substring(0,4));
380 month = Integer.parseInt(anInternalDate.substring(5,7));
381 day = Integer.parseInt(anInternalDate.substring(8,10));
382 hours = Integer.parseInt(anInternalDate.substring(11,13));
383 minutes = Integer.parseInt(anInternalDate.substring(14,16));
384 seconds = Integer.parseInt(anInternalDate.substring(17,19));
386 timezoneOffset = Integer.parseInt(anInternalDate.substring(20,22));
387 if (anInternalDate.charAt(19) == '-')
388 timezoneOffset = -timezoneOffset;
390 calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
391 calendar.set(year, month-1, day, hours, minutes, seconds);
392 calendar.add(Calendar.HOUR, -timezoneOffset);
394 return calendar.getTime();