replaced some gnu RE's with the much faster jakarta ORO
[mir.git] / source / mir / misc / StringUtil.java
1 /*
2  * Copyright (C) 2005 The Mir-coders group
3  *
4  * This file is part of Mir.
5  *
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.
10  *
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.
15  *
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
19  *
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.
26  */
27 package  mir.misc;
28
29 import gnu.regexp.RE;
30 import gnu.regexp.REException;
31
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;
37
38 /**
39  */
40 public final class StringUtil {
41
42   private static TimeZone UTC = TimeZone.getTimeZone("UTC");
43   private static RE   re_tags, re_tables, re_forbiddenTags;
44
45   private StringUtil() { }  // this avoids contruction
46
47   static {
48     try {
49       //precompile regex
50       re_tags       = new RE("<[^>]*>",RE.REG_ICASE);
51       re_tables = new RE("<[ \t\r\n/]*(table|td|tr)[ \t\r\n]*>",RE.REG_ICASE);
52       re_forbiddenTags = new RE("<[ \t\r\n/]*(html|meta|body|head|script)[ \t\r\n]*>",RE.REG_ICASE);
53     }
54     catch (REException e){
55       System.err.println("FATAL: StringUtil: could not precompile REGEX: "+e.toString());
56     }
57   }
58
59   /**
60    * Formats a number with the specified minimum and maximum number of digits.
61    **/
62   public static synchronized String zeroPaddingNumber(long value, int minDigits,
63       int maxDigits)
64   {
65     NumberFormat numberFormat = NumberFormat.getInstance();
66     numberFormat.setMinimumIntegerDigits(minDigits);
67     numberFormat.setMaximumIntegerDigits(maxDigits);
68     return numberFormat.format(value);
69   }
70
71   /**
72    * Wandelt Datum in einen 8-ziffrigen String um (yyyymmdd)
73    * @param theDate
74    * @return 8-ziffriger String (yyyymmdd)
75    */
76
77   public static final String date2webdbDate (GregorianCalendar theDate) {
78     StringBuffer webdbDate = new StringBuffer();
79     webdbDate.append(String.valueOf(theDate.get(Calendar.YEAR)));
80     webdbDate.append(pad2(theDate.get(Calendar.MONTH) + 1));
81     webdbDate.append(pad2(theDate.get(Calendar.DATE)));
82
83     return  webdbDate.toString();
84   }
85
86   /**
87    * Return a http://www.w3.org/TR/NOTE-datetime formatted date (yyyy-mm-ddThh:mm:ssTZ)
88    * @param theDate
89    * @return w3approved datetime
90    */
91
92   public static final String date2w3DateTime (GregorianCalendar theDate) {
93     StringBuffer webdbDate = new StringBuffer();
94     webdbDate.append(String.valueOf(theDate.get(Calendar.YEAR)));
95     webdbDate.append("-");
96     webdbDate.append(pad2(theDate.get(Calendar.MONTH) + 1));
97     webdbDate.append("-");
98     webdbDate.append(pad2(theDate.get(Calendar.DATE)));
99     webdbDate.append("T");
100     webdbDate.append(pad2(theDate.get(Calendar.HOUR_OF_DAY)));
101     webdbDate.append(":");
102     webdbDate.append(pad2(theDate.get(Calendar.MINUTE)));
103     webdbDate.append(":");
104     webdbDate.append(pad2(theDate.get(Calendar.SECOND)));
105     //assumes you are an hour-multiple away from UTC....
106     int offset=(theDate.get(Calendar.ZONE_OFFSET)/(60*60*1000));
107     if (offset < 0){
108       webdbDate.append("-");
109     }
110     else{
111       webdbDate.append("+");
112     }
113     webdbDate.append(pad2(Math.abs(offset)));
114     webdbDate.append(":00");
115     return  webdbDate.toString();
116   }
117
118   /**
119    * wandelt Calendar in dd.mm.yyyy / hh.mm um
120    * @param theDate
121    * @return String mit (dd.mm.yyyy / hh.mm um)
122    */
123   public static String date2readableDateTime (GregorianCalendar theDate) {
124     String readable = "";
125     int hour;
126     readable += pad2(theDate.get(Calendar.DATE));
127     readable += "." + pad2(theDate.get(Calendar.MONTH) + 1);
128     readable += "." + String.valueOf(theDate.get(Calendar.YEAR));
129     hour = theDate.get(Calendar.HOUR);
130     if (theDate.get(Calendar.AM_PM) == Calendar.PM)
131       hour += 12;
132     readable += " / " + pad2(hour);
133     readable += ":" + pad2(theDate.get(Calendar.MINUTE));
134     return  readable;
135   }
136
137   /**
138    * wandelt eine Datum in einen 8-buchstabigen String, der durch <code>/</code>
139    * getrennt ist.
140    *
141    * @param webdbDate
142    * @return String mit <code>/yyyy/mm/dd</code>
143    */
144   public static final String webdbDate2path (String webdbDate) {
145     StringBuffer path = new StringBuffer();
146     path.append("/").append(webdbDate.substring(0, 4));
147     path.append("/").append(webdbDate.substring(4, 6));
148     path.append("/");
149     //who did this?
150     //path.append("/").append(webdbDate.substring(6, 8));
151     return  path.toString();
152   }
153
154   /**
155    * L?scht <code>/</code> am Ende des Strings, falls vorhanden
156    * @param path
157    * @return String ohne <code>/</code> am Ende
158    */
159   public static final String removeSlash (String path) {
160     return  path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length()
161         - 1) : path;
162   }
163
164   /**
165    * formatiert eine Zahl (0-99) zweistellig (z.B. 5 -> 05)
166    * @return zwistellige Zahl
167    */
168   public static String pad2 (int number) {
169     return  number < 10 ? "0" + number : String.valueOf(number);
170   }
171
172   /**
173    * formatiert eine Zahl (0-999) dreistellig (z.B. 7 -> 007)
174    *
175    * @return 3-stellige Zahl
176    */
177   public static String pad3 (int number) {
178     return  number < 10 ? "00" + number : number < 100 ? "0" + number : String.valueOf(number);
179   }
180
181   /**
182    * Liefert Default-Wert def zur?ck, wenn String <code>s</code>
183    * kein Integer ist.
184    *
185    * @param s
186    * @param def
187    * @return geparster int aus s oder def
188    */
189   public static int parseInt(String s, int def) {
190     if (s == null) return def;
191     try {
192       return Integer.parseInt(s);
193     } catch (NumberFormatException e) {
194       return def;
195     }
196   }
197
198
199   /**
200    * Converts mir's horrible internal date format (yyyy-MM-dd HH:mm:ss+zz) into a java Date
201    *
202    * @param anInternalDate
203    */
204   public static Date convertMirInternalDateToDate(String anInternalDate) {
205     Calendar calendar = new GregorianCalendar();
206
207     int year;
208     int month;
209     int day;
210     int hours;
211     int minutes;
212     int seconds;
213     int timezoneOffset;
214
215     year = Integer.parseInt(anInternalDate.substring(0,4));
216     month = Integer.parseInt(anInternalDate.substring(5,7));
217     day = Integer.parseInt(anInternalDate.substring(8,10));
218     hours = Integer.parseInt(anInternalDate.substring(11,13));
219     minutes = Integer.parseInt(anInternalDate.substring(14,16));
220     seconds = Integer.parseInt(anInternalDate.substring(17,19));
221
222     timezoneOffset = Integer.parseInt(anInternalDate.substring(20,22));
223     if (anInternalDate.charAt(19) == '-') {
224       timezoneOffset = -timezoneOffset;
225     }
226
227     calendar.setTimeZone(UTC);
228     calendar.set(year, month-1, day, hours, minutes, seconds);
229     calendar.add(Calendar.HOUR, -timezoneOffset);
230
231     return calendar.getTime();
232   }
233
234 }
235