001: /*
002: * @(#)GenSrc.java 1.7 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package sun.tools.javazic;
028:
029: import java.io.IOException;
030: import java.io.File;
031: import java.io.FileWriter;
032: import java.io.BufferedWriter;
033: import java.util.ArrayList;
034: import java.util.Iterator;
035: import java.util.LinkedList;
036: import java.util.Set;
037: import java.util.TreeMap;
038: import java.util.TreeSet;
039: import sun.util.calendar.Gregorian;
040: import sun.util.calendar.ZoneInfoFile;
041:
042: /**
043: * <code>GenSrc</code> is one of back-end classes of javazic, and generates
044: * ZoneInfoMappings.java and zone-specific .java file for each zone.
045: */
046: class GenSrc extends BackEnd {
047:
048: private static final String docDir = "text";
049:
050: private static final String m_PackageName = "package sun.util.calendar.zoneinfo;\n\n";
051: private static final String m_ImportClasses = "import java.util.TimeZone;\n"
052: + "import java.util.Calendar;\n";
053: private static final String m_ImportSTZClass = "import java.util.SimpleTimeZone;\n";
054: private static final String m_additionalImportClass = "import sun.util.calendar.ZoneInfo;\n\n";
055: private static final String m_header = "/*\n"
056: + " * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.\n"
057: + " * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER\n"
058: + " * \n"
059: + " * This program is free software; you can redistribute it and/or\n"
060: + " * modify it under the terms of the GNU General Public License version\n"
061: + " * 2 only, as published by the Free Software Foundation. \n"
062: + " * \n"
063: + " * This program is distributed in the hope that it will be useful, but\n"
064: + " * WITHOUT ANY WARRANTY; without even the implied warranty of\n"
065: + " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
066: + " * General Public License version 2 for more details (a copy is\n"
067: + " * included at /legal/license.txt).\n"
068: + " * \n"
069: + " * You should have received a copy of the GNU General Public License\n"
070: + " * version 2 along with this work; if not, write to the Free Software\n"
071: + " * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA\n"
072: + " * 02110-1301 USA \n"
073: + " * \n"
074: + " * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa\n"
075: + " * Clara, CA 95054 or visit www.sun.com if you need additional\n"
076: + " * information or have any questions.\n" + " */\n\n";
077: private static final String m_warning = " // THIS FILE HAS BEEN GENERATED BY A TOOL. DO NOT EDIT THIS FILE MANUALLY.\n";
078: private static final String m_rule_zone_Begin = "/**\n"
079: + " * ZoneInfo definitions for \"";
080: private static final String m_rule_zone_Mid = ".\" The following have been derived\n"
081: + " * from the Olson public zone information.\n"
082: + " * <pre><code>\n";
083: private static final String m_rule = " * Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S\n";
084: private static final String m_zone = " * Zone GMTOFF RULES FORMAT [UNTIL]\n";
085: private static final String m_rule_zone_End = " * </code></pre>\n"
086: + " *\n" + " */\n\n";
087: private static final String m_return = "\n";
088: private static final String m_comment_null_line = " //\n";
089: private static final String m_comment_blank_line = " * \n";
090: private static final String m_array_End = " };\n\n";
091: private static final String m_method_End = " }\n\n";
092: private static final String m_class_End = "}\n";
093:
094: /**
095: * Generates datafile in .java format for each zone.
096: * @param Timezone
097: * @return 0 if no errors, or 1 if error occurred.
098: */
099: int processZoneinfo(Timezone tz) {
100: try {
101: int size;
102: String outputDir = Main.getOutputDir();
103: String zonename = tz.getName();
104: String zonefile = ZoneInfoFile.getFileName(zonename)
105: + ".java";
106:
107: /* If outputDir doesn't end with file-separator, adds it. */
108: if (!outputDir.endsWith(File.separator)) {
109: outputDir += File.separatorChar;
110: }
111: outputDir += docDir + File.separatorChar;
112:
113: /* If zonefile includes file-separator, it's treated as part of
114: * pathname. And make directory if necessary.
115: */
116: int index = zonefile.lastIndexOf(File.separatorChar);
117: if (index != -1) {
118: outputDir += zonefile.substring(0, index + 1);
119: }
120: File outD = new File(outputDir);
121: outD.mkdirs();
122:
123: /* Open zoneinfo file to write. */
124: FileWriter fw = new FileWriter(outputDir
125: + zonefile.substring(index + 1));
126: BufferedWriter out = new BufferedWriter(fw);
127:
128: /* Output header. */
129: out.write(m_header);
130: out.write(m_comment_null_line + m_warning
131: + m_comment_null_line + m_return);
132: out.write(m_PackageName + m_ImportClasses);
133:
134: /* whether SimpleTimeZone is used (ArrayList) or not (null) */
135: ArrayList stz = tz.getLastRules();
136: if (stz != null) {
137: out.write(m_ImportSTZClass);
138: }
139: out.write(m_additionalImportClass);
140:
141: /* Output Rule and Zone. */
142: out.write(m_rule_zone_Begin + zonename + m_rule_zone_Mid);
143:
144: /* Output Rule records. */
145: ArrayList rule = tz.getRules();
146: if (rule != null) {
147: size = rule.size();
148: out.write(m_rule);
149: for (int i = 0; i < size; i++) {
150: out.write(" * " + ((RuleRec) rule.get(i)).getLine()
151: + m_return);
152: }
153: out.write(m_comment_blank_line);
154: }
155:
156: /* Output Zone records. */
157: ArrayList zone = tz.getZones();
158: if (zone != null) {
159: size = zone.size();
160: out.write(m_zone);
161: for (int i = 0; i < size; i++) {
162: out.write(" * " + ((ZoneRec) zone.get(i)).getLine()
163: + m_return);
164: }
165: }
166: out.write(m_rule_zone_End);
167:
168: /* beginning of zonename class */
169: out.write("public class " + zonefile
170: + " extends ZoneInfo {\n");
171:
172: /* Output Transaction records. */
173: ArrayList transitions = tz.getTransitions();
174: if (transitions != null) {
175: ArrayList dstOffsets = tz.getDstOffsets();
176: ArrayList offsets = tz.getOffsets();
177:
178: if ((dstOffsets == null && offsets != null)
179: || (dstOffsets != null && offsets == null)) {
180: Main
181: .panic("Data not exist. (dstOffsets or offsets)");
182: return 1;
183: }
184:
185: out
186: .write(" private static final long[] pTransitions = {\n\t");
187: size = transitions.size();
188: long tra = 0;
189: for (int i = 0; i < size; i++) {
190: int dstoffset;
191:
192: /* if year is different from previous one, insert "\n". */
193: tra = ((Long) transitions.get(i)).longValue();
194:
195: /* if DST offset 0, no DST (not index 0). */
196: if ((dstoffset = ((Integer) dstOffsets.get(i))
197: .intValue()) == -1) {
198: dstoffset = 0;
199: }
200:
201: out.write(tra + "L<<12|" + dstoffset + "<<4|"
202: + ((Integer) offsets.get(i)).intValue()
203: + ", " + " // "
204: + Gregorian.getCalendarDate(tra) + "\n\t");
205: }
206: out.write(m_return + m_array_End);
207:
208: ArrayList gmtoffset = tz.getGmtOffsets();
209: if (gmtoffset != null) {
210: out
211: .write(" private static final int[] pOffsets = {\n\t");
212: int gmtoffset_size = gmtoffset.size();
213: for (int i = 0; i < gmtoffset_size; i++) {
214: out.write(((Integer) gmtoffset.get(i))
215: .intValue()
216: + ", ");
217: }
218: out.write(m_return + m_array_End);
219: }
220: }
221:
222: if (stz != null) {
223: RuleRec rr0 = (RuleRec) stz.get(0);
224: RuleRec rr1 = (RuleRec) stz.get(1);
225: boolean wall = rr0.getTime().isWall()
226: && rr1.getTime().isWall();
227:
228: out
229: .write(" private static final int[] pSimpleTimeZoneParams = {\n"
230: + "\t"
231: + Month.toString(rr0.getMonthNum())
232: + ", "
233: + rr0.getDay()
234: .getDayForSimpleTimeZone()
235: + ", "
236: + rr0
237: .getDay()
238: .getDayOfWeekForSimpleTimeZone()
239: + ", "
240: + Time.toFormedString((int) rr0
241: .getTime().getTime())
242: + ", "
243: + (wall ? "\n"
244: : (rr0
245: .getTime()
246: .getTypeForSimpleTimeZone() + ",\n"))
247: + "\t"
248: + Month.toString(rr1.getMonthNum())
249: + ", "
250: + rr1.getDay()
251: .getDayForSimpleTimeZone()
252: + ", "
253: + rr1
254: .getDay()
255: .getDayOfWeekForSimpleTimeZone()
256: + ", "
257: + Time.toFormedString((int) rr1
258: .getTime().getTime())
259: + ", "
260: + (wall ? "" : (rr1.getTime()
261: .getTypeForSimpleTimeZone()))
262: + m_return + m_array_End);
263: }
264:
265: /* Output method zonename(). */
266: out.write(" public " + zonefile + "() {\n"
267: + "\tsuper(\"" + zonename + "\", "
268: + Time.toFormedString(tz.getRawOffset()) + ", "
269: + Time.toFormedString(tz.getLastDSTSaving()) + ", "
270: + "0x" + Integer.toHexString(tz.getCRC32())
271: + ", \n\t ");
272: out.write((transitions != null) ? "pTransitions, "
273: + "pOffsets, " : "null, " + "null, ");
274: out.write((stz != null) ? "pSimpleTimeZoneParams" : "null");
275: out.write(");\n");
276:
277: out.write(m_method_End);
278: out.write(m_class_End); /* End of zonename class */
279:
280: out.close();
281: fw.close();
282: } catch (IOException e) {
283: Main.panic("IO error: " + e.getMessage());
284: return 1;
285: }
286:
287: return 0;
288: }
289:
290: /**
291: * Generates ZoneInfoMappings.java.
292: * @param Mappings
293: * @return 0 if no errors, or 1 if error occurred.
294: */
295: int generateSrc(Mappings map) {
296: try {
297: int roi_size;
298: int pad_num;
299: Iterator keys;
300: String key;
301: String outputDir = Main.getOutputDir();
302:
303: /* Whether rawOffsetIndex list exists or not. */
304: LinkedList roi = map.getRawOffsetsIndex();
305: if (roi == null) {
306: Main.panic("Data not exist. (rawOffsetsIndex)");
307: return 1;
308: }
309: roi_size = roi.size();
310: LinkedList roit = map.getRawOffsetsIndexTable();
311: if (roit == null || roit.size() != roi_size) {
312: Main
313: .panic("Data not exist. (rawOffsetsIndexTable) Otherwise, Invalid size");
314: return 1;
315: }
316:
317: /* Whether alias list exists or not. */
318: TreeMap a = map.getAliases();
319: if (a == null) {
320: Main.panic("Data not exist. (aliases)");
321: return 1;
322: }
323:
324: /* If outputDir doesn't end with file-separator, adds it. */
325: if (!outputDir.endsWith(File.separator)) {
326: outputDir += File.separatorChar;
327: }
328: outputDir += docDir + File.separatorChar;
329:
330: File outD = new File(outputDir);
331: outD.mkdirs();
332:
333: /* Open ZoneInfoMapping file to write. */
334: FileWriter fw = new FileWriter(outputDir
335: + "ZoneInfoMappings.java", false);
336: BufferedWriter out = new BufferedWriter(fw);
337:
338: /* Output header. */
339: out.write(m_header);
340: out.write(m_comment_null_line + m_warning);
341: out.write(" // BASED ON : " + Main.getVersionName()
342: + "\n" + m_comment_null_line + m_return);
343: out.write(m_PackageName);
344:
345: /* beginning of ZoneInfoMapping class */
346: out.write("public class ZoneInfoMappings {\n\n");
347:
348: /* Output sorted rawOffset list. */
349: out.write(" public static final String[] IDs = {\n");
350:
351: for (int i = 0; i < roi_size; i++) {
352: TreeSet perRO = (TreeSet) roit.get(i);
353: keys = perRO.iterator();
354:
355: while (keys.hasNext()) {
356: key = (String) keys.next();
357: pad_num = key.length();
358: pad_num = (pad_num > 20) ? 1 : 21 - pad_num;
359: out.write("\t\"" + key + "\",");
360: while (pad_num-- > 0) {
361: out.write(" ");
362: }
363: out.write("\t// "
364: + Time.toGMTFormat(roi.get(i).toString())
365: + "\n");
366: }
367: }
368: out.write(m_array_End);
369:
370: /* Output sorted rawOffset list. */
371: out.write(" public static final int[] rawOffsets = {\n");
372: for (int i = 0; i < roi_size; i++) {
373: out.write("\t" + roi.get(i) + ",\t// " + i + "\n");
374: }
375: out.write(m_array_End);
376:
377: /* Output sorted rawOffsetIndex list. */
378: out
379: .write(" public static final byte[] rawOffsetIndices = {");
380: int counter = 0;
381: for (int i = 0; i < roi_size; i++) {
382: int num = ((TreeSet) (roit.get(i))).size();
383:
384: for (int j = 0; j < num; j++) {
385: if (counter++ % 10 == 0) {
386: out.write("\n\t");
387: }
388: if (i < 10) {
389: out.write(" ");
390: }
391: out.write(i + ", ");
392: }
393: }
394: out.write(m_return + m_array_End);
395:
396: out.write(" public static final String[] aliases = {\n");
397: Set s = a.keySet();
398: keys = s.iterator();
399: while (keys.hasNext()) {
400: key = (String) keys.next();
401: pad_num = key.length();
402: pad_num = (pad_num > 20) ? 1 : 21 - pad_num;
403: out.write("\t\"" + key + "\",");
404: while (pad_num-- > 0) {
405: out.write(" ");
406: }
407: out.write("\"" + a.get(key) + "\",\n");
408: }
409: out.write(m_array_End + m_class_End);
410:
411: out.close();
412: fw.close();
413: } catch (IOException e) {
414: Main.panic("IO error: " + e.getMessage());
415: return 1;
416: }
417:
418: return 0;
419: }
420: }
|