KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > number > Numberer_en


1 package net.sf.saxon.number;
2 import net.sf.saxon.om.FastStringBuffer;
3
4 import java.io.Serializable JavaDoc;
5
6 /**
7   * Class Numberer_en does number formatting for language="en".
8   * This supports the xsl:number element.
9   * Methods and data are declared as protected, and static is avoided, to allow easy subclassing.
10   * @author Michael H. Kay
11   */

12
13 public class Numberer_en implements Numberer, Serializable JavaDoc {
14
15     public static final int UPPER_CASE = 0;
16     public static final int LOWER_CASE = 1;
17     public static final int TITLE_CASE = 2;
18
19     /**
20     * Format a number into a string
21     * @param number The number to be formatted
22     * @param picture The format token. This is a single component of the format attribute
23     * of xsl:number, e.g. "1", "01", "i", or "a"
24     * @param groupSize number of digits per group (0 implies no grouping)
25     * @param groupSeparator string to appear between groups of digits
26     * @param letterValue The letter-value specified to xsl:number: "alphabetic" or
27     * "traditional". Can also be an empty string or null.
28     * @param ordinal The value of the ordinal attribute specified to xsl:number
29     * The value "yes" indicates that ordinal numbers should be used; "" or null indicates
30     * that cardinal numbers
31     * @return the formatted number. Note that no errors are reported; if the request
32     * is invalid, the number is formatted as if the string() function were used.
33     */

34
35     public String JavaDoc format(long number,
36                          String JavaDoc picture,
37                          int groupSize,
38                          String JavaDoc groupSeparator,
39                          String JavaDoc letterValue,
40                          String JavaDoc ordinal) {
41
42         if (number < 0) {
43             return "" + number;
44         }
45         if (picture==null || picture.length()==0) {
46             return "" + number;
47         }
48
49         FastStringBuffer sb = new FastStringBuffer(16);
50         char formchar = picture.charAt(0);
51
52         switch(formchar) {
53
54         case '0':
55         case '1':
56             sb.append(toRadical(number, westernDigits, picture, groupSize, groupSeparator));
57             if (ordinal != null && ordinal.length() > 0) {
58                 sb.append(ordinalSuffix(ordinal, number));
59             }
60             break;
61
62         case 'A':
63             if (number==0) return "0";
64             sb.append(toAlphaSequence(number, latinUpper));
65             break;
66
67         case 'a':
68             if (number==0) return "0";
69             sb.append(toAlphaSequence(number, latinLower));
70             break;
71
72         case 'w':
73         case 'W':
74             int wordCase;
75             if (picture.equals("W")) {
76                 wordCase = UPPER_CASE;
77             } else if (picture.equals("w")) {
78                 wordCase = LOWER_CASE;
79             } else {
80                 wordCase = TITLE_CASE;
81             }
82             if (ordinal != null && ordinal.length() > 0) {
83                 sb.append(toOrdinalWords(ordinal, number, wordCase));
84
85             } else {
86                 sb.append(toWords(number, wordCase));
87             }
88             break;
89
90         case 'i':
91             if (number==0) return "0";
92             if (letterValue==null || letterValue.equals("") ||
93                     letterValue.equals("traditional")) {
94                 sb.append(toRoman(number));
95             } else {
96                 alphaDefault(number, formchar, sb);
97             }
98             break;
99
100         case 'I':
101             if (number==0) return "0";
102             if (letterValue==null || letterValue.equals("") ||
103                     letterValue.equals("traditional")) {
104                 sb.append(toRoman(number).toUpperCase());
105             } else {
106                 alphaDefault(number, formchar, sb);
107             }
108             break;
109
110         case '\u0391':
111             if (number==0) return "0";
112             sb.append(toAlphaSequence(number, greekUpper));
113             break;
114
115         case '\u03b1':
116             if (number==0) return "0";
117             sb.append(toAlphaSequence(number, greekLower));
118             break;
119
120         case '\u0410':
121             if (number==0) return "0";
122             sb.append(toAlphaSequence(number, cyrillicUpper));
123             break;
124
125         case '\u0430':
126             if (number==0) return "0";
127             sb.append(toAlphaSequence(number, cyrillicLower));
128             break;
129
130         case '\u05d0':
131             if (number==0) return "0";
132             sb.append(toAlphaSequence(number, hebrew));
133             break;
134
135         case '\u3042':
136             if (number==0) return "0";
137             sb.append(toAlphaSequence(number, hiraganaA));
138             break;
139
140         case '\u30a2':
141             if (number==0) return "0";
142             sb.append(toAlphaSequence(number, katakanaA));
143             break;
144
145         case '\u3044':
146             if (number==0) return "0";
147             sb.append(toAlphaSequence(number, hiraganaI));
148             break;
149
150         case '\u30a4':
151             if (number==0) return "0";
152             sb.append(toAlphaSequence(number, katakanaI));
153             break;
154
155         case '\u4e00':
156             if (number==0) return "0";
157             sb.append(toRadical(number, kanjiDigits, picture, groupSize, groupSeparator));
158             break;
159
160         default:
161
162             if (Character.isDigit(formchar)) {
163
164                 int zero = (int)formchar - Character.getNumericValue(formchar);
165                 String JavaDoc digits = "" +
166                     (char)(zero) +
167                     (char)(zero+1) +
168                     (char)(zero+2) +
169                     (char)(zero+3) +
170                     (char)(zero+4) +
171                     (char)(zero+5) +
172                     (char)(zero+6) +
173                     (char)(zero+7) +
174                     (char)(zero+8) +
175                     (char)(zero+9);
176
177                 sb.append(toRadical(number, digits, picture, groupSize, groupSeparator));
178                 break;
179
180             } else {
181                 if (number==0) return "0";
182                 if (formchar < '\u1100') {
183                     alphaDefault(number, formchar, sb);
184                 } else {
185                     // fallback to western numbering
186
sb.append(
187                         toRadical(number, westernDigits, picture, groupSize, groupSeparator));
188                 }
189                 break;
190
191             }
192         }
193
194         return sb.toString();
195     }
196
197     /**
198      * Construct the ordinal suffix for a number, for example "st", "nd", "rd"
199      * @param ordinalParam the value of the ordinal attribute (used in non-English
200      * language implementations)
201      * @param number the number being formatted
202      * @return the ordinal suffix to be appended to the formatted number
203      */

204
205     protected String JavaDoc ordinalSuffix(String JavaDoc ordinalParam, long number) {
206         int penult = ((int)(number % 100)) / 10;
207         int ult = (int)(number % 10);
208         if (penult==1) {
209             // e.g. 11th, 12th, 13th
210
return "th";
211         } else {
212             if (ult==1) {
213                 return "st";
214             } else if (ult==2) {
215                 return "nd";
216             } else if (ult==3) {
217                 return "rd";
218             } else {
219                 return "th";
220             }
221         }
222     }
223
224     protected static final String JavaDoc westernDigits =
225         "0123456789";
226
227     protected static final String JavaDoc latinUpper =
228         "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
229
230     protected static final String JavaDoc latinLower =
231         "abcdefghijklmnopqrstuvwxyz";
232
233     protected static final String JavaDoc greekUpper =
234         "\u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399\u039a" +
235         "\u039b\u039c\u039c\u039d\u039e\u039f\u03a0\u03a1\u03a3\u03a4" +
236         "\u03a5\u03a6\u03a7\u03a8\u03a9";
237
238     protected static final String JavaDoc greekLower =
239         "\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u03b7\u03b8\u03b9\u03ba" +
240         "\u03bb\u03bc\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c3\u03c4" +
241         "\u03c5\u03c6\u03c7\u03c8\u03c9";
242
243     // Cyrillic information from Dmitry Kirsanov [dmitry@kirsanov.com]
244
// (based on his personal knowledge of Russian texts, not any authoritative source)
245

246     protected static final String JavaDoc cyrillicUpper =
247         "\u0410\u0411\u0412\u0413\u0414\u0415\u0416\u0417\u0418" +
248         "\u041a\u041b\u041c\u041d\u041e\u041f\u0420\u0421\u0421\u0423" +
249         "\u0424\u0425\u0426\u0427\u0428\u0429\u042b\u042d\u042e\u042f";
250
251     protected static final String JavaDoc cyrillicLower =
252         "\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438" +
253         "\u043a\u043b\u043c\u043d\u043e\u043f\u0440\u0441\u0441\u0443" +
254         "\u0444\u0445\u0446\u0447\u0448\u0449\u044b\u044d\u044e\u044f";
255
256     protected static final String JavaDoc hebrew =
257         "\u05d0\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d7\u05d8\u05d9\u05db\u05dc" +
258         "\u05de\u05e0\u05e1\u05e2\u05e4\u05e6\u05e7\u05e8\u05e9\u05ea";
259
260
261     // The following Japanese sequences were supplied by
262
// MURAKAMI Shinyu [murakami@nadita.com]
263

264     protected static final String JavaDoc hiraganaA =
265         "\u3042\u3044\u3046\u3048\u304a\u304b\u304d\u304f\u3051\u3053" +
266         "\u3055\u3057\u3059\u305b\u305d\u305f\u3061\u3064\u3066\u3068" +
267         "\u306a\u306b\u306c\u306d\u306e\u306f\u3072\u3075\u3078\u307b" +
268         "\u307e\u307f\u3080\u3081\u3082\u3084\u3086\u3088\u3089\u308a" +
269         "\u308b\u308c\u308d\u308f\u3092\u3093";
270
271     protected static final String JavaDoc katakanaA =
272
273         "\u30a2\u30a4\u30a6\u30a8\u30aa\u30ab\u30ad\u30af\u30b1\u30b3" +
274         "\u30b5\u30b7\u30b9\u30bb\u30bd\u30bf\u30c1\u30c4\u30c6\u30c8" +
275         "\u30ca\u30cb\u30cc\u30cd\u30ce\u30cf\u30d2\u30d5\u30d8\u30db" +
276         "\u30de\u30df\u30e0\u30e1\u30e2\u30e4\u30e6\u30e8\u30e9\u30ea" +
277         "\u30eb\u30ec\u30ed\u30ef\u30f2\u30f3";
278
279     protected static final String JavaDoc hiraganaI =
280
281         "\u3044\u308d\u306f\u306b\u307b\u3078\u3068\u3061\u308a\u306c" +
282         "\u308b\u3092\u308f\u304b\u3088\u305f\u308c\u305d\u3064\u306d" +
283         "\u306a\u3089\u3080\u3046\u3090\u306e\u304a\u304f\u3084\u307e" +
284         "\u3051\u3075\u3053\u3048\u3066\u3042\u3055\u304d\u3086\u3081" +
285         "\u307f\u3057\u3091\u3072\u3082\u305b\u3059";
286
287     protected static final String JavaDoc katakanaI =
288
289         "\u30a4\u30ed\u30cf\u30cb\u30db\u30d8\u30c8\u30c1\u30ea\u30cc" +
290         "\u30eb\u30f2\u30ef\u30ab\u30e8\u30bf\u30ec\u30bd\u30c4\u30cd" +
291         "\u30ca\u30e9\u30e0\u30a6\u30f0\u30ce\u30aa\u30af\u30e4\u30de" +
292         "\u30b1\u30d5\u30b3\u30a8\u30c6\u30a2\u30b5\u30ad\u30e6\u30e1" +
293         "\u30df\u30b7\u30f1\u30d2\u30e2\u30bb\u30b9";
294
295
296     protected static final String JavaDoc kanjiDigits =
297         "\u3007\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d";
298
299
300     /**
301     * Default processing with an alphabetic format token: use the contiguous
302     * range of Unicode letters starting with that token.
303     */

304
305     protected void alphaDefault(long number, char formchar, FastStringBuffer sb) {
306         int min = (int)formchar;
307         int max = (int)formchar;
308         // use the contiguous range of letters starting with the specified one
309
while (Character.isLetterOrDigit((char)(max+1))) {
310             max++;
311         }
312         sb.append(toAlpha(number, min, max));
313     }
314
315     /**
316     * Format the number as an alphabetic label using the alphabet consisting
317     * of consecutive Unicode characters from min to max
318     */

319
320     protected String JavaDoc toAlpha(long number, int min, int max) {
321         if (number<=0) return "" + number;
322         int range = max - min + 1;
323         char last = (char)(((number-1) % range) + min);
324         if (number>range) {
325             return toAlpha((number-1)/range, min, max) + last;
326         } else {
327             return "" + last;
328         }
329     }
330
331     /**
332     * Convert the number into an alphabetic label using a given alphabet.
333     * For example, if the alphabet is "xyz" the sequence is x, y, z, xx, xy, xz, ....
334     */

335
336     protected String JavaDoc toAlphaSequence(long number, String JavaDoc alphabet) {
337         if (number<=0) return "" + number;
338         int range = alphabet.length();
339         char last = alphabet.charAt((int)((number-1) % range));
340         if (number>range) {
341             return toAlphaSequence((number-1)/range, alphabet) + last;
342         } else {
343             return "" + last;
344         }
345     }
346
347     /**
348     * Convert the number into a decimal or other representation using the given set of
349     * digits.
350     * For example, if the digits are "01" the sequence is 1, 10, 11, 100, 101, 110, 111, ...
351     * More commonly, the digits will be "0123456789", giving the usual decimal numbering.
352     * @param number the number to be formatted
353     * @param digits the set of digits to be used
354     * @param picture the formatting token, for example 001 means include leading zeroes to give at least
355     * three decimal places. In practice, it is only the length of the picture that is significant: a
356     * picture of "999" gives the same results as "001". (This isn't what a strict reading of the spec
357     * suggests should happen, but it seems a reasonable fallback in practice.)
358     * @param groupSize the number of digits in each group
359     * @param groupSeparator the separator to use between groups of digits.
360     */

361
362     private String JavaDoc toRadical(long number, String JavaDoc digits, String JavaDoc picture,
363                                  int groupSize, String JavaDoc groupSeparator) {
364
365         FastStringBuffer sb = new FastStringBuffer(16);
366         FastStringBuffer temp = new FastStringBuffer(16);
367         int base = digits.length();
368
369         String JavaDoc s = "";
370         long n = number;
371         while (n>0) {
372             s = digits.charAt((int)(n % base)) + s;
373             n = n / base;
374         }
375
376         for (int i=0; i<(picture.length()-s.length()); i++) {
377             temp.append(digits.charAt(0));
378         }
379         temp.append(s);
380
381         if (groupSize>0) {
382             for (int i=0; i<temp.length(); i++) {
383                 if (i!=0 && ((temp.length()-i) % groupSize) == 0) {
384                     sb.append(groupSeparator);
385                 }
386                 sb.append(temp.charAt(i));
387             }
388         } else {
389             sb = temp;
390         }
391
392         return sb.toString();
393     }
394
395     /**
396     * Generate a Roman numeral (in lower case)
397     */

398
399     public static String JavaDoc toRoman(long n) {
400         if (n<=0 || n>9999) return "" + n;
401         return romanThousands[(int)n/1000] +
402                romanHundreds[((int)n/100) % 10] +
403                romanTens[((int)n/10) % 10] +
404                romanUnits[(int)n % 10];
405     }
406
407     // Roman numbers beyond 4000 use overlining and other conventions which we won't
408
// attempt to reproduce. We'll go high enough to handle present-day Gregorian years.
409

410     private static String JavaDoc[] romanThousands =
411         {"", "m", "mm", "mmm", "mmmm", "mmmmm", "mmmmmm", "mmmmmmm", "mmmmmmmm", "mmmmmmmmm"};
412     private static String JavaDoc[] romanHundreds =
413         {"", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm"};
414     private static String JavaDoc[] romanTens =
415         {"", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc"};
416     private static String JavaDoc[] romanUnits =
417         {"", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix"};
418
419
420     /**
421     * Show the number as words in title case. (We choose title case because
422      * the result can then be converted algorithmically to lower case or upper case).
423     */

424
425     public String JavaDoc toWords(long number) {
426         if (number >= 1000000000) {
427             long rem = number % 1000000000;
428             return toWords(number / 1000000000) + " Billion" +
429                     (rem==0 ? "" : (rem < 100 ? " and " : " ") + toWords(rem));
430         } else if (number >= 1000000) {
431             long rem = number % 1000000;
432             return toWords(number / 1000000) + " Million" +
433                     (rem==0 ? "" : (rem < 100 ? " and " : " ") + toWords(rem));
434         } else if (number >= 1000) {
435             long rem = number % 1000;
436             return toWords(number / 1000) + " Thousand" +
437                     (rem==0 ? "" : (rem < 100 ? " and " : " ") + toWords(rem));
438         } else if (number >= 100) {
439             long rem = number % 100;
440             return toWords(number / 100) + " Hundred" +
441                 (rem==0 ? "" : " and " + toWords(rem));
442         } else {
443             if (number < 20) return englishUnits[(int)number];
444             int rem = (int)(number % 10);
445             return englishTens[(int)number / 10] +
446                 (rem==0 ? "" : ' ' + englishUnits[rem]);
447         }
448     }
449
450     public String JavaDoc toWords(long number, int wordCase) {
451         String JavaDoc s;
452         if (number == 0) {
453             s = "Zero";
454         } else {
455             s = toWords(number);
456         }
457         if (wordCase == UPPER_CASE) {
458             return s.toUpperCase();
459         } else if (wordCase == LOWER_CASE) {
460             return s.toLowerCase();
461         } else {
462             return s;
463         }
464     }
465
466     /**
467     * Show an ordinal number as English words in a requested case (for example, Twentyfirst)
468     */

469
470     public String JavaDoc toOrdinalWords(String JavaDoc ordinalParam, long number, int wordCase) {
471         String JavaDoc s;
472         if (number >= 1000000000) {
473             long rem = number % 1000000000;
474             s = toWords(number / 1000000000) + " Billion" +
475                     (rem==0 ? "th" : (rem < 100 ? " and " : " ") +
476                     toOrdinalWords(ordinalParam, rem, wordCase));
477         } else if (number >= 1000000) {
478             long rem = number % 1000000;
479             s = toWords(number / 1000000) + " Million" +
480                     (rem==0 ? "th" : (rem < 100 ? " and " : " ") +
481                     toOrdinalWords(ordinalParam, rem, wordCase));
482         } else if (number >= 1000) {
483             long rem = number % 1000;
484             s = toWords(number / 1000) + " Thousand" +
485                     (rem==0 ? "th" : (rem < 100 ? " and " : " ") +
486                     toOrdinalWords(ordinalParam, rem, wordCase));
487         } else if (number >= 100) {
488             long rem = number % 100;
489             s = toWords(number / 100) + " Hundred" +
490                     (rem==0 ? "th" : " and " +
491                     toOrdinalWords(ordinalParam, rem, wordCase));
492         } else {
493             if (number < 20) {
494                 s = englishOrdinalUnits[(int)number];
495             } else {
496                 int rem = (int)(number % 10);
497                 if (rem==0) {
498                     s = englishOrdinalTens[(int)number / 10];
499                 } else {
500                     s = englishTens[(int)number / 10] + '-' + englishOrdinalUnits[rem];
501                 }
502             }
503         }
504         if (wordCase == UPPER_CASE) {
505             return s.toUpperCase();
506         } else if (wordCase == LOWER_CASE) {
507             return s.toLowerCase();
508         } else {
509             return s;
510         }
511     }
512
513     private static String JavaDoc[] englishUnits = {
514         "", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine",
515         "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen",
516         "Seventeen", "Eighteen", "Nineteen"};
517
518     private static String JavaDoc[] englishTens = {
519         "", "Ten", "Twenty", "Thirty", "Forty", "Fifty",
520         "Sixty", "Seventy", "Eighty", "Ninety"};
521
522     private static String JavaDoc[] englishOrdinalUnits = {
523         "", "First", "Second", "Third", "Fourth", "Fifth", "Sixth", "Seventh", "Eighth", "Ninth",
524         "Tenth", "Eleventh", "Twelfth", "Thirteenth", "Fourteenth", "Fifteenth", "Sixteenth",
525         "Seventeenth", "Eighteenth", "Nineteenth"};
526
527     private static String JavaDoc[] englishOrdinalTens = {
528         "", "Tenth", "Twentieth", "Thirtieth", "Fortieth", "Fiftieth",
529         "Sixtieth", "Seventieth", "Eightieth", "Ninetieth"};
530
531     /**
532      * Get a month name or abbreviation
533      * @param month The month number (1=January, 12=December)
534      * @param minWidth The minimum number of characters
535      * @param maxWidth The maximum number of characters
536      */

537
538     public String JavaDoc monthName(int month, int minWidth, int maxWidth) {
539         String JavaDoc name = englishMonths[month-1];
540         if (maxWidth < 3) {
541             maxWidth = 3;
542         }
543         if (name.length() > maxWidth) {
544             name = name.substring(0, maxWidth);
545         }
546         while (name.length() < minWidth) {
547             name = name + ' ';
548         }
549         return name;
550     }
551
552     private static String JavaDoc[] englishMonths = {
553         "January", "February", "March", "April", "May", "June",
554         "July", "August", "September", "October", "November", "December"
555     };
556
557     /**
558      * Get a day name or abbreviation
559      * @param day The month number (1=Sunday, 7=Saturday)
560      * @param minWidth The minimum number of characters
561      * @param maxWidth The maximum number of characters
562      */

563
564     public String JavaDoc dayName(int day, int minWidth, int maxWidth) {
565         String JavaDoc name = englishDays[day-1];
566         if (maxWidth < 2) {
567             maxWidth = 2;
568         }
569         if (name.length() > maxWidth) {
570             name = englishDayAbbreviations[day-1];
571             if (name.length() > maxWidth) {
572                 name = name.substring(0, maxWidth);
573             }
574         }
575         while (name.length() < minWidth) {
576             name = name + ' ';
577         }
578         if (minWidth==1 && maxWidth==2) {
579             // special case
580
name = name.substring(0, minUniqueDayLength[day-1]);
581         }
582         return name;
583     }
584
585     private static String JavaDoc[] englishDays = {
586         "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
587     };
588
589     private static String JavaDoc[] englishDayAbbreviations = {
590         "Sun", "Mon", "Tues", "Weds", "Thurs", "Fri", "Sat"
591     };
592
593     private static int[] minUniqueDayLength = {
594         1, 2, 1, 2, 1, 2, 2
595     };
596
597     /**
598      * Get an am/pm indicator
599      * @param minutes the minutes within the day
600      * @param minWidth minimum width of output
601      * @param maxWidth maximum width of output
602      * @return the AM or PM indicator
603      */

604
605     public String JavaDoc halfDayName(int minutes, int minWidth, int maxWidth) {
606         String JavaDoc s;
607         if (minutes < 12*60) {
608             switch (maxWidth) {
609                 case 1:
610                     s = "A";
611                     break;
612                 case 2:
613                 case 3:
614                     s = "Am";
615                     break;
616                 default:
617                     s = "A.M.";
618             }
619         } else {
620             switch (maxWidth) {
621                 case 1:
622                     s = "P";
623                     break;
624                 case 2:
625                 case 3:
626                     s = "Pm";
627                     break;
628                 default:
629                     s = "P.M.";
630             }
631         }
632         return s;
633     }
634
635     /**
636      * Get an ordinal suffix for a particular component of a date/time.
637      *
638      * @param component the component specifier from a format-dateTime picture, for
639      * example "M" for the month or "D" for the day.
640      * @return a string that is acceptable in the ordinal attribute of xsl:number
641      * to achieve the required ordinal representation. For example, "-e" for the day component
642      * in German, to have the day represented as "dritte August".
643      */

644
645     public String JavaDoc getOrdinalSuffixForDateTime(String JavaDoc component) {
646         return "yes";
647     }
648
649 }
650
651 //
652
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
653
// you may not use this file except in compliance with the License. You may obtain a copy of the
654
// License at http://www.mozilla.org/MPL/
655
//
656
// Software distributed under the License is distributed on an "AS IS" basis,
657
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
658
// See the License for the specific language governing rights and limitations under the License.
659
//
660
// The Original Code is: all this file.
661
//
662
// The Initial Developer of the Original Code is Michael H. Kay.
663
//
664
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
665
//
666
// Contributor(s): none.
667
//
668
Popular Tags