1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package de.bea.domingo.http;
24
25 import java.io.UnsupportedEncodingException;
26 import java.net.URLEncoder;
27 import java.util.ArrayList;
28 import java.util.Calendar;
29 import java.util.Date;
30 import java.util.List;
31
32 import org.apache.commons.httpclient.Cookie;
33
34 /***
35 * Domino regional preferences.
36 *
37 * @author <a href=mailto:kriede@users.sourceforge.net>Kurt Riede</a>
38 */
39 public final class DominoPreferences {
40
41 /*** Number of years that a preferences cookie is valid. */
42 public static final int EXPIRY_YEARS = 30;
43
44 /*** Default encoding (UTF-8) for cookie values. */
45 public static final String ENCODING_UTF_8 = "UTF-8";
46
47 /*** Default time zone search string. */
48 public static final String DEFAULT_TIME_ZONE = "Pacific Time (US & Canada)";
49
50 /*** The locale settings. */
51 public static final DominoLocale DEFAULT_LOCALE = DominoLocale.get("en-US");
52
53 /*** List of {@link org.apache.commons.httpclient.Header}s. */
54 private List fCookies = new ArrayList();
55
56 /*** Domain of the generated cookies. */
57 private final String fDomain;
58
59 /*** path of the generated cookies. */
60 private String fPath = "/";
61
62 /*** The time zone. */
63 private DominoTimeZone fTimeZone = DominoTimeZone.searchTimeZone(DEFAULT_TIME_ZONE);
64
65 /*** Indicates whether the time format reflects daylight savings time. */
66 private boolean fDst;
67
68 /*** locale string. */
69 private String fLocaleString;
70
71 /*** Indicates whether the order of the date format is day-month-year, month-day-year or year-month-day. */
72 private String fDateComponentOrder;
73
74 /*** The character used to separate months, days, and years, for example, the slash.. */
75 private String fDateSeparator;
76
77 /*** The character used to separate hours, minutes, and seconds, for example, the colon.. */
78 private String fTimeSeparator;
79
80 /*** Indicates whether the time format is 24-hour. */
81 private boolean fClock24Hour;
82
83 /*** The string that denotes AM time, for example, "AM" in English. */
84 private String fAmString;
85
86 /*** The string that denotes PM time, for example, "PM" in English. */
87 private String fPmString;
88
89 /*** Indicates whether the AM/PM symbol follows the time in the time format. */
90 private boolean fAmPmSuffix;
91
92 /*** The decimal separator for number format, for example, the decimal point. */
93 private String fDecimalSeparator;
94
95 /*** The thousand separator in number format, for example, the comma. */
96 private String fThousandSeparator;
97
98 /*** Year format. */
99 private String fYearFormat;
100
101 /*** Indicates whether fractions have a zero before the decimal point in number format. */
102 private boolean fNumberLeadingZero;
103
104 /*** The symbol that indicates a number is currency, for example, the dollar sign. */
105 private String fCurrencySymbol;
106
107 /*** Indicates whether the currency symbol follows the number in the currency format. */
108 private boolean fCurrencySuffix;
109
110 /*** Indicates whether the currency format has a space between the currency symbol and the number.. */
111 private boolean fCurrencySpace;
112
113 /*** The date/time when thre preferences will expire. */
114 private final Date fExpiryDate;
115
116 /*** The cookie that represents the time zone settings. */
117 private Cookie fTimeZoneCookie;
118
119 /*** The cookie that represents the locale settings. */
120 private Cookie fRegionalCookie;
121
122 /***
123 * Constructor.
124 *
125 * @param domain the domain to that this preferences belong to
126 */
127 public DominoPreferences(final String domain) {
128 this(domain, "/");
129 }
130
131 /***
132 * Constructor.
133 *
134 * @param domain the domain to that this preferences belong to
135 * @param path the path defining the subset of URLs in a domain for which the cookie is valid
136 */
137 public DominoPreferences(final String domain, final String path) {
138 fDomain = domain;
139 fPath = path;
140 Calendar creationDate = Calendar.getInstance();
141 creationDate.add(Calendar.YEAR, EXPIRY_YEARS);
142 fExpiryDate = creationDate.getTime();
143 setLocale("en-US", true);
144 fTimeZoneCookie = newTimeZoneCookie();
145 fRegionalCookie = newRegionalCookie();
146 }
147
148 /***
149 * Sets the time zone.
150 *
151 * @param timeZone Domino time zone
152 */
153 public void setTimeZone(final DominoTimeZone timeZone) {
154 fTimeZone = timeZone;
155 }
156
157 /***
158 * Sets whether to observe daylight saving time or not.
159 *
160 * @param dst observe daylight saving time or not
161 */
162 public void setObserverDST(final boolean dst) {
163 fDst = dst;
164 }
165
166 /***
167 * @param locale The locale to set.
168 */
169 public void setLocale(final String locale) {
170 setLocale(locale, false);
171 }
172
173 /***
174 * @param localeString The locale to set as a string.
175 * @param loadDefault if <code>true</code>, load all default values for
176 * this locale
177 */
178 public void setLocale(final String localeString, final boolean loadDefault) {
179 fLocaleString = localeString;
180 DominoLocale locale = (DominoLocale) DominoLocale.get(localeString);
181 if (locale == null) {
182 throw new NotesHttpRuntimeException("unsupported locale: " + localeString);
183 }
184 fLocaleString = locale.getLocale();
185 fDateComponentOrder = locale.getDateComponentOrder();
186 fDateSeparator = locale.getDateSeparator();
187 fTimeSeparator = locale.getTimeSeparator();
188 fClock24Hour = "".equals(locale.getClock24Hour());
189 fAmString = locale.getAmString();
190 fPmString = locale.getPmString();
191 fAmPmSuffix = "1".indexOf(locale.getAmPmSuffix()) >= 0;
192 fDecimalSeparator = locale.getDecimalSeparator();
193 fNumberLeadingZero = "1".equals(locale.getNumberLeadingZero());
194 fCurrencySymbol = locale.getCurrencySymbol();
195 fCurrencySuffix = "1".equals(locale.getCurrencySuffix());
196 fCurrencySpace = "1".equals(locale.getCurrencySpace());
197 fThousandSeparator = locale.getThousandSeparator();
198 fYearFormat = locale.getYearFormat();
199 }
200
201 /***
202 * @param amString The amString to set.
203 */
204 public void setAmString(final String amString) {
205 fAmString = amString;
206 }
207
208 /***
209 * @param currencySpace The currencySpace to set.
210 */
211 public void setCurrencySpace(final boolean currencySpace) {
212 fCurrencySpace = currencySpace;
213 }
214
215 /***
216 * @param currencySymbol The currencySymbol to set.
217 */
218 public void setCurrencySymbol(final String currencySymbol) {
219 fCurrencySymbol = currencySymbol;
220 }
221
222 /***
223 * @param dateSeperator The dateSeperator to set.
224 */
225 public void setDateSeperator(final String dateSeperator) {
226 fDateSeparator = dateSeperator;
227 }
228
229 /***
230 * @param decimalSeperator The decimalSeperator to set.
231 */
232 public void setDecimalSeperator(final String decimalSeperator) {
233 fDecimalSeparator = decimalSeperator;
234 }
235
236 /***
237 * @param cookies The cookies to set.
238 */
239 public void setCookies(final List cookies) {
240 fCookies = cookies;
241 }
242
243 /***
244 * @param dst The dst to set.
245 */
246 public void setDst(final boolean dst) {
247 fDst = dst;
248 }
249
250 /***
251 * @param hour24Format The hourFormat to set.
252 */
253 public void setHourFormat(final boolean hour24Format) {
254 fClock24Hour = hour24Format;
255 }
256
257 /***
258 * @param leadingDecimalZeros The leadingDecimalZeros to set.
259 */
260 public void setLeadingDecimalZeros(final boolean leadingDecimalZeros) {
261 fNumberLeadingZero = leadingDecimalZeros;
262 }
263
264 /***
265 * @param pmString The pmString to set.
266 */
267 public void setPmString(final String pmString) {
268 fPmString = pmString;
269 }
270
271 /***
272 * @param amPmSuffix The amPmSuffix to set.
273 */
274 public void setAmPmSuffix(final boolean amPmSuffix) {
275 fAmPmSuffix = amPmSuffix;
276 }
277
278 /***
279 * @param currencySuffix The currencySuffix to set.
280 */
281 public void setPositionCurrencySymbol(final boolean currencySuffix) {
282 fCurrencySuffix = currencySuffix;
283 }
284
285 /***
286 * @param thousandsSeperator The thousandsSeperator to set.
287 */
288 public void setThousandsSeperator(final String thousandsSeperator) {
289 fThousandSeparator = thousandsSeperator;
290 }
291
292 /***
293 * @param timeSeperator The timeSeperator to set.
294 */
295 public void setTimeSeperator(final String timeSeperator) {
296 fTimeSeparator = timeSeperator;
297 }
298
299 /***
300 * Returns a list of cookies for the current regional settings.
301 *
302 * @return cookies for regional settings
303 */
304 public List getRegionalCookies() {
305 return fCookies;
306 }
307
308 /***
309 * @see java.lang.Object#toString()
310 *
311 * @return a string representation of the object.
312 */
313 public String toString() {
314 StringBuffer buffer = new StringBuffer();
315 buffer.append(fLocaleString + ":");
316 buffer.append(fDateComponentOrder + ":");
317 buffer.append(fDateSeparator + ":");
318 buffer.append(fTimeSeparator + ":");
319 buffer.append(fClock24Hour + ":");
320 buffer.append(fAmString + ":");
321 buffer.append(fPmString + ":");
322 buffer.append(fAmPmSuffix + ":");
323 buffer.append(fDecimalSeparator + ":");
324 buffer.append(fNumberLeadingZero + ":");
325 buffer.append(fCurrencySymbol + ":");
326 buffer.append(fCurrencySuffix + ":");
327 buffer.append(fCurrencySpace + ":");
328 buffer.append(fThousandSeparator + ":");
329 buffer.append(fYearFormat + ":");
330 return buffer.toString();
331 }
332
333 /***
334 * Creates the time zone cookie of Lotus Domino.
335 *
336 * <p>Format:</p>
337 * <dl>
338 * <dt>Name</dt><dd><tt>DomTimeZonePrfM</tt></dd>
339 * <dt>Format</dt><dd><tt>flag : version : zone-name : zone-offset : dst-law : dst</tt></dd>
340 * <dt>flag</dt><dd><tt>"+"</tt> for valid cookies, any other char otherwise</dd>
341 * <dt>version</dt><dd>version number <tt>"6"</tt></dd>
342 * <dt>zone-name</dt><dd>conventional Notes/Domino TimeZone name, ignored</dd>
343 * <dt>zone-offset</dt><dd>encoded time zone offset in the form: <tt>[-][mm][h]h</tt>.
344 * Offset is negative for TimeZones east to greenwich</dd>
345 * <dt>dst-law</dt><dd>Daylight Savings Time turning on/off rule in the form:
346 * <tt>(BMonth,BDay,BWeekDay,EMonth,EDay,EWeekDay) | 0</tt> when does not exist
347 * <ul>
348 * <li>BMonth, EMonth take values 1...12, where 1 is January
349 * <li>BDay, EDay - the date in that month, 1 means first, 2 means second, -1 means last
350 * <li> BWeekDay, EWeekDay - 1-based day of a week, 1 means Sunday
351 * </ul></dd>
352 * <dt>dst</dt><dd>Daylight Savings Time offset - either 1 (when used) or 0 otherwise</dd>
353 * </dl>
354 */
355 private Cookie newTimeZoneCookie() {
356 Cookie cookie = new Cookie(fDomain, "DomTimeZonePrfM", "", fPath, fExpiryDate, false);
357 cookie.setValue("+:6" + ":" + fTimeZone.getValue() + ":" + encode(fDst));
358 return cookie;
359
360 }
361
362 /***
363 * Creates the regional cookie of Lotus Domino.
364 *
365 * <dl>
366 * <dt>Name</dt><dd><tt>DomRegionalPrfM</tt></dd>
367 * <dt>Format</dt><dd><tt>flag : version : encoding : Locale : DateOrder : DateSeperator : TimeSeperator : Hour24Format :
368 * AmString : PmString : AmPmSuffix : DecimalSeperator : LeadingDecimalZeros : CurrencySymbol : CurrencySuffix :
369 * CurrencySpace : ThousandsSeperator "1"</tt></dd>
370 * <dt>encoding</dt><dd>must be "UTF-8"</dd>
371 * <dt>locale</dt><dd>a Lotus Domino locale string, e.g. <tt>"en-US"</tt> or <tt>"de-DE"</tt></dd>
372 * <dt>date-order</dt><dd>Order of date components. <tt>"0"</tt> for weekday-month-day-year,
373 * <tt>"1"</tt> for weekday-day-month-year,
374 * <tt>"2"</tt> for year-month-day-weekday</dd>
375 * <dt>date-seperator</dt><dd>the seperater character for date components, e.g. <tt>"/"</tt> for locale
376 * <tt>en_US</tt> or <tt>"."</tt> for locale <tt>de_DE</tt></dd>
377 * <dt>time-seperator</dt><dd>the seperater character for time components, e.g. <tt>":"</dd>>
378 * <dt>24-hour-format</dt><dd>Whether to us 24 hour format or not. <tt>"0"</tt> for 12-hour format with AM/OM strings or
379 * <tt>"1"</tt> for 24-hour format</dd>
380 * <dt>AM-string</dt><dd>The string identifying times before noon</dd>
381 * <dt>PM-string</dt><dd>The string identifying times after noon</dd>
382 * <dt>AM-PM-suffix</dt><dd>Position of AM/PM string. <tt>"0"</tt> for preceeding the time,
383 * <tt>"1"</tt> for a suffix of the time</dd>
384 * <dt>decimal-seperator</dt><dd>The decimal seperator for seperating the fractional part of decimal numbers, e.g.
385 * <tt>"."</tt> for locale <tt>en_US</tt> or <tt>","</tt> for locale <tt>de_DE</tt></dd>
386 * <dt>leading-decimal-zeros</dt><dd>Whether to use a leading zero in decimal fractions,
387 * <tt>1</tt> for using a leading zero</dd>
388 * <dt>currency-symbol</dt><dd>The currency symbol, e.g. <tt>"$"</tt> for locale <tt>en_US</tt> or
389 * <tt>"€"</tt> for locale <tt>de_DE</tt></dd>
390 * <dt>currency-suffix</dt><dd>Whether the currency symbol is displayed before or after the currency value.
391 * <tt>"0"</tt> for before, <tt>"1"</tt> for after</dd>
392 * <dt>currency-space</dt><dd>Whether to insert a space between currency value and cuurency symbol.
393 * <tt>"0"</tt> for not using a space, <tt>"1"</tt> for using a space</dd>
394 * <dt>thousands-seperator</dt><dd>The thousands seperator in number formats, e.g.
395 * <tt>","</tt> for locale <tt>en_US</tt> or <tt>"."</tt> for locale <tt>de_DE</tt></dd>
396 * </dl>
397 */
398 private Cookie newRegionalCookie() {
399 Cookie cookie = new Cookie(fDomain, "DomRegionalPrfM", "", fPath, fExpiryDate, false);
400 List list = new ArrayList();
401 list.add("+");
402 list.add("6");
403 list.add("UTF-8");
404 list.add(fLocaleString);
405 list.add(fDateComponentOrder);
406 list.add(encode(fDateSeparator));
407 list.add(encode(fTimeSeparator));
408 list.add(encode(fClock24Hour));
409 list.add(encode(fAmString));
410 list.add(encode(fPmString));
411 list.add(encode(fAmPmSuffix));
412 list.add(encode(fDecimalSeparator));
413 list.add(encode(fNumberLeadingZero));
414 list.add(encode(fCurrencySymbol));
415 list.add(encode(fCurrencySuffix));
416 list.add(encode(fCurrencySpace));
417 list.add(encode(fThousandSeparator));
418 list.add(encode(fYearFormat));
419 cookie.setValue(implode(list, ":"));
420 return cookie;
421 }
422
423 /***
424 * Combines the elements of a string array to a single string using a given
425 * seperator.
426 *
427 * @param stringList a list of strings
428 * @param delimiter the delimiting string
429 * @return combined string
430 */
431 public static String implode(final List stringList, final String delimiter) {
432 StringBuffer buffer = new StringBuffer();
433 for (int i = 0; i < stringList.size(); i++) {
434 buffer.append((i > 0 ? delimiter : "") + stringList.get(i));
435 }
436 return buffer.toString();
437 }
438
439 /***
440 * Returns a new Lotus Domino time zone cookie.
441 *
442 * @return Lotus Domino time zone cookie
443 */
444 public Cookie getTimeZoneCookie() {
445 return fTimeZoneCookie;
446 }
447
448 /***
449 * Returns a new Lotus Domino regional cookie.
450 *
451 * @return Lotus Domino regional cookie
452 */
453 public Cookie getRegionalCookie() {
454 return fRegionalCookie;
455 }
456
457 /***
458 * Encodes a boolean value to <tt>"1"</tt> for <code>true</code> and
459 * <tt>"0"</tt> for <code>false</code>.
460 *
461 * @param booleanValue the boolean value to encode
462 * @return encoded boolean value
463 */
464 static String encode(final boolean booleanValue) {
465 return (booleanValue ? "1" : "0");
466 }
467
468 /***
469 * URL-encodes a string.
470 *
471 * @param text the test to encode
472 * @return URL-encoded text
473 */
474 static String encode(final String text) {
475 try {
476 return URLEncoder.encode(text, ENCODING_UTF_8);
477 } catch (UnsupportedEncodingException e) {
478
479 throw new NotesHttpRuntimeException("Unsupported encoding: " + ENCODING_UTF_8, e);
480 }
481 }
482 }