/* * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.StringTokenizer; import java.util.TreeMap; import java.util.TreeSet; /** * <code>GenDoc</code> is one of back-end classes of javazic, and generates * index.html and other html files which prints the detailed time zone * information for each zone. */ class GenDoc extends BackEnd { private static final String docDir = "doc"; private static final String header1 = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Frameset//EN\"" + "\"http://www.w3.org/TR/REC-html40/frameset.dtd\">\n" + "<HTML>\n<HEAD>\n<!-- Generated by javazic on "; private static final String header2 = "-->\n<TITLE>\n" + "Java Platform, Standard Edition - TimeZone information based on "; private static final String header3 = "-->\n<TITLE>\n" + "Java Platform, Standard Edition TimeZone - "; private static final String header4 = "</TITLE>\n" + "</HEAD>\n\n"; private static final String body1 = "<BODY BGCOLOR=\"white\">\n"; private static final String body2 = "</BODY>\n"; private static final String footer = "</HTML>\n"; // list of time zone name and zonefile name/real time zone name // e.g. // key (String) : value (String) // "America/Denver" : "America/Denver.html" (real time zone) // "America/Shiprock" : "America/Denver" (alias) TreeMap<String,String> timezoneList = new TreeMap<String,String>(); // list of time zone's display name and time zone name // e.g. // key (String) : value (String) // "Tokyo, Asia" : "Asia/Tokyo" // "Marengo, Indiana, America" : "America/Indiana/Marengo" // (aliases included) TreeMap<String,String> displayNameList = new TreeMap<String,String>(); // list of top level regions // e.g. // key (String) : value (String) // "America" : "America.html" // (including entries in America/Indiana/, America/Kentucky/, ...) TreeMap<String,String> regionList = new TreeMap<String,String>(); // mapping list from zone name to latitude & longitude // This list is generated from zone.tab. // e.g. // key (String) : value (LatitudeAndLongitude object) // "Asia/Tokyo" : latitude=35.3916, longitude=13.9444 // (aliases not included) HashMap<String,LatitudeAndLongitude> mapList = null; // SortedMap of zone IDs sorted by their GMT offsets. If zone's GMT // offset will change in the future, its last known offset is // used. SortedMap<Integer, Set<String>> zonesByOffset = new TreeMap<Integer, Set<String>>(); /** * Generates HTML document for each zone. * @param Timezone * @return 0 if no errors, or 1 if error occurred. */ int processZoneinfo(Timezone tz) { try { int size; int index; String outputDir = Main.getOutputDir(); String zonename = tz.getName(); String zonefile = ZoneInfoFile.getFileName(zonename) + ".html"; List<RuleRec> stz = tz.getLastRules(); timezoneList.put(zonename, zonefile); displayNameList.put(transform(zonename), zonename); // Populate zonesByOffset. (Zones that will change their // GMT offsets are also added to zonesByOffset here.) int lastKnownOffset = tz.getRawOffset(); Set<String> set = zonesByOffset.get(lastKnownOffset); if (set == null) { set = new TreeSet<String>(); zonesByOffset.put(lastKnownOffset, set); } set.add(zonename); /* If outputDir doesn't end with file-separator, adds it. */ if (!outputDir.endsWith(File.separator)) { outputDir += File.separatorChar; } outputDir += docDir + File.separatorChar; index = zonename.indexOf('/'); if (index != -1) { regionList.put(zonename.substring(0, index), zonename.substring(0, index) + ".html"); } /* If zonefile includes file-separator, it's treated as part of * pathname. And make directory if necessary. */ index = zonefile.lastIndexOf('/'); if (index != -1) { zonefile.replace('/', File.separatorChar); outputDir += zonefile.substring(0, index+1); } File outD = new File(outputDir); outD.mkdirs(); /* If mapfile is available, add a link to the appropriate map */ if ((mapList == null) && (Main.getMapFile() != null)) { FileReader fr = new FileReader(Main.getMapFile()); BufferedReader in = new BufferedReader(fr); mapList = new HashMap<String,LatitudeAndLongitude>(); String line; while ((line = in.readLine()) != null) { // skip blank and comment lines if (line.length() == 0 || line.charAt(0) == '#') { continue; } StringTokenizer tokens = new StringTokenizer(line); String token = tokens.nextToken(); /* We don't use the first token. */ token = tokens.nextToken(); LatitudeAndLongitude location = new LatitudeAndLongitude(token); token = tokens.nextToken(); mapList.put(token, location); } in.close(); } /* Open zoneinfo file to write. */ FileWriter fw = new FileWriter(outputDir + zonefile.substring(index+1)); BufferedWriter out = new BufferedWriter(fw); out.write(header1 + new Date() + header3 + zonename + header4); out.write(body1 + "<FONT size=\"+2\"><B>" + zonename + "</B></FONT>"); LatitudeAndLongitude location = mapList.get(zonename); if (location != null) { int deg, min, sec; deg = location.getLatDeg(); min = location.getLatMin(); sec = location.getLatSec(); if (deg < 0) { min = -min; sec = -sec; } else if (min < 0) { sec = -sec; } out.write("   " + "<A HREF=\"http://www.mapquest.com/maps/map.adp?" + "latlongtype=degrees" + "&latdeg=" + deg + "&latmin=" + min + "&latsec=" + sec); deg = location.getLongDeg(); min = location.getLongMin(); sec = location.getLongSec(); if (deg < 0) { min = -min; sec = -sec; } else if (min < 0) { sec = -sec; } out.write("&longdeg=" + deg + "&longmin=" + min + "&longsec=" + sec + "\" target=\"_blank\">[map]</A>"); } out.write("\n<P>\n"); List<ZoneRec> zone = tz.getZones(); List<RuleRec> rule = tz.getRules(); if (rule != null && zone != null) { out.write("<TABLE BORDER=\"0\" WIDTH=\"100%\" CELLPADDING=\"1\" CELLSPACING=\"0\">\n" + "<TR>\n" + "<TD BGCOLOR=\"#EEEEFF\" WIDTH=\"50%\" ALIGN=\"CENTER\"><BR>" + "<A HREF=\"#Rules\">Rules</A><BR></TD>\n" + "<TD BGCOLOR=\"#EEEEFF\" WIDTH=\"50%\" ALIGN=\"CENTER\">" + "<A HREF=\"#Zone\"><BR>Zone<BR></A></TD>\n" + "</TR>\n</TABLE>\n"); } /* Output Rule records. */ if (rule != null) { size = rule.size(); out.write("<P>\n<A NAME=\"Rules\">" + "<FONT SIZE=\"+1\"><B>Rules</B></FONT></A>\n" + "<TABLE BORDER=\"1\" WIDTH=\"100%\" CELLPADDING=\"3\" CELLSPACING=\"0\">\n" + "<TR BGCOLOR=\"#CCCCFF\">\n" + "<TD>NAME</TD><TD>FROM</TD><TD>TO</TD><TD>TYPE</TD>" + "<TD>IN</TD><TD>ON</TD><TD>AT</TD><TD>SAVE</TD>" + "<TD>LETTER/S</TD><TD>NOTES</TD>\n</TR>\n"); for (int i = 0; i < size; i++) { out.write("<TR BGCOLOR=\"#FFFFFF\">\n"); StringTokenizer st = new StringTokenizer(rule.get(i).getLine()); String s; if (st.hasMoreTokens()) { /* RULE - truncated */ st.nextToken(); } if (st.hasMoreTokens()) { /* NAME */ out.write("<TD>" + st.nextToken() + "</TD>"); } if (st.hasMoreTokens()) { /* FROM */ out.write("<TD>" + st.nextToken() + "</TD>"); } if (st.hasMoreTokens()) { /* TO */ s = st.nextToken(); if (s.equals("min") || s.equals("max")) { out.write("<TD><FONT COLOR=\"red\">" + s + "</FONT></TD>"); } else { out.write("<TD>" + s + "</TD>"); } } if (st.hasMoreTokens()) { /* TYPE */ out.write("<TD>" + st.nextToken() + "</TD>"); } if (st.hasMoreTokens()) { /* IN */ out.write("<TD>" + st.nextToken() + "</TD>"); } if (st.hasMoreTokens()) { /* ON */ out.write("<TD>" + st.nextToken() + "</TD>"); } if (st.hasMoreTokens()) { /* AT */ out.write("<TD>" + st.nextToken() + "</TD>"); } if (st.hasMoreTokens()) { /* SAVE */ out.write("<TD>" + st.nextToken() + "</TD>"); } if (st.hasMoreTokens()) { /* LETTER/S */ out.write("<TD>" + st.nextToken() + "</TD>"); } if (st.hasMoreTokens()) { /* NOTES */ s = st.nextToken(); while (st.hasMoreTokens()) { s += " " + st.nextToken(); } index = s.indexOf('#'); out.write("<TD>" + s.substring(index+1) + "</TD>\n"); } else { out.write("<TD> </TD>\n"); } out.write("</TR>\n"); } out.write("</TABLE>\n<P> <P>\n"); } /* Output Zone records. */ if (zone != null) { size = zone.size(); out.write("<P>\n<A NAME=\"Zone\">" + "<FONT SIZE=\"+1\"><B>Zone</B></FONT></A>\n" + "<TABLE BORDER=\"1\" WIDTH=\"100%\" CELLPADDING=\"3\" CELLSPACING=\"0\">\n" + "<TR BGCOLOR=\"#CCCCFF\">\n<TD>GMTOFF</TD>" + "<TD>RULES</TD><TD>FORMAT</TD><TD>UNTIL</TD>" + "<TD>NOTES</TD>\n</TR>\n"); for (int i = 0; i < size; i++) { out.write("<TR>\n"); StringTokenizer st = new StringTokenizer(zone.get(i).getLine()); String s = st.nextToken(); if (s.equals("Zone")) { /* NAME */ s = st.nextToken(); s = st.nextToken(); } out.write("<TD>" + s + "</TD>"); /* GMTOFFSET */ if (st.hasMoreTokens()) { /* RULES */ out.write("<TD>" + st.nextToken() + "</TD>"); } if (st.hasMoreTokens()) { /* FORMAT */ s = st.nextToken(); index = s.indexOf('#'); if (index != -1) { if (index != 0) { out.write("<TD>" + s.substring(0, index-1) + "</TD>"); /* FORMAT */ s = s.substring(index+1); } else { out.write("<TD> </TD>"); /* FORMAT */ } while (st.hasMoreTokens()) { s += " " + st.nextToken(); } out.write("<TD> </TD>"); /* UNTIL */ out.write("<TD>" + s + "</TD>\n</TR>\n"); /* NOTES */ continue; } else { out.write("<TD>" + s + "</TD>"); /* FORMAT */ } } if (st.hasMoreTokens()) { /* UNTIL */ s = st.nextToken(); while (st.hasMoreTokens()) { s += " " + st.nextToken(); } index = s.indexOf('#'); if (index != -1) { if (index != 0) { out.write("<TD>" + s.substring(0, index-1) + "</TD>"); /* UNTIL */ } else { out.write("<TD> </TD>"); /* UNTIL */ } out.write("<TD>" + s.substring(index+1) + "</TD>\n"); /* NOTES */ } else { out.write("<TD>" + s + "</TD>"); /* UNTIL */ out.write("<TD> </TD>\n"); /* NOTES */ } } else { out.write("<TD> </TD>"); /* UNTIL */ out.write("<TD> </TD>\n"); /* NOTES */ } out.write("</TR>\n"); } out.write("</TABLE>\n"); } out.write(body2 + footer); out.close(); fw.close(); } catch(IOException e) { Main.panic("IO error: "+e.getMessage()); return 1; } return 0; } /** * Generates index.html and other top-level frame files. * @param Mappings * @return 0 if no errors, or 1 if error occurred. */ int generateSrc(Mappings map) { try { int len; Object o[]; String outputDir = Main.getOutputDir(); FileWriter fw1, fw2; BufferedWriter out1, out2; /* Whether alias list exists or not. */ Map<String,String> a = map.getAliases(); if (a == null) { Main.panic("Data not exist. (aliases)"); return 1; } timezoneList.putAll(a); /* If outputDir doesn't end with file-separator, adds it. */ if (!outputDir.endsWith(File.separator)) { outputDir += File.separatorChar; } outputDir += docDir + File.separatorChar; File outD = new File(outputDir); outD.mkdirs(); /* Creates index.html */ fw1 = new FileWriter(outputDir + "index.html", false); out1 = new BufferedWriter(fw1); out1.write(header1 + new Date() + header2 + Main.getVersionName() + header4 + "<FRAMESET cols=\"20%,80%\">\n" + "<FRAMESET rows=\"30%,70%\">\n" + "<FRAME src=\"overview-frame.html\" name=\"TimeZoneListFrame\">\n" + "<FRAME src=\"allTimeZone-frame1.html\" name=\"allTimeZoneFrame\">\n" + "</FRAMESET>" + "<FRAME src=\"overview-summary.html\" name=\"rightFrame\">\n" + "</FRAMESET>\n" + "<NOFRAMES>\n" + "<H2>\nFrame Alert\n</H2>\n\n" + "<P>\n\n" + "This document is designed to be viewed using the frames feature. If you see this\n" + "message, you are using a non-frame-capable web client.\n" + "<BR>\n" + "Link to<A HREF=\"overview-summary.html\">Non-frame version.</A>\n" + "</NOFRAMES>\n" + footer); out1.close(); fw1.close(); /* Creates overview-frame.html */ fw1 = new FileWriter(outputDir + "overview-frame.html", false); out1 = new BufferedWriter(fw1); out1.write(header1 + new Date() + header2 + Main.getVersionName() + header4 + body1 + "<TABLE BORDER=\"0\" WIDTH=\"100%\">\n<TR>\n" + "<TD NOWRAP><FONT size=\"+1\">\n" + "<B>Java<sup><font size=-2>TM</font></sup> Platform<br>Standard Ed.</B></FONT></TD>\n" + "</TR>\n</TABLE>\n\n" + "<TABLE BORDER=\"0\" WIDTH=\"100%\">\n<TR>\n<TD NOWRAP>" + "<P>\n<FONT size=\"+1\">\nAll Time Zones Sorted By:</FONT>\n<BR>\n" + "  <A HREF=\"allTimeZone-frame1.html\" TARGET=\"allTimeZoneFrame\">GMT offsets</A></FONT>\n<BR>\n" + "  <A HREF=\"allTimeZone-frame2.html\" TARGET=\"allTimeZoneFrame\">Zone names</A></FONT>\n<BR>" + "  <A HREF=\"allTimeZone-frame3.html\" TARGET=\"allTimeZoneFrame\">City names</A></FONT>\n" + "<P>\n<FONT size=\"+1\">\nContinents and Oceans</FONT>\n<BR>\n"); for (String regionKey : regionList.keySet()) { out1.write("  <A HREF=\"" + regionList.get(regionKey) + "\" TARGET=\"allTimeZoneFrame\">" + regionKey + "</A><BR>\n"); fw2 = new FileWriter(outputDir + regionList.get(regionKey), false); out2 = new BufferedWriter(fw2); out2.write(header1 + new Date() + header3 + regionKey + header4 + body1 + "<FONT size=\"+1\"><B>" + regionKey + "</B></FONT>\n<BR>\n<TABLE>\n<TR>\n<TD>"); boolean found = false; for (String timezoneKey : timezoneList.keySet()) { int regionIndex = timezoneKey.indexOf('/'); if (regionIndex == -1 || !regionKey.equals(timezoneKey.substring(0, regionIndex))) { if (found) { break; } else { continue; } } found = true; if (a.containsKey(timezoneKey)) { Object realName = a.get(timezoneKey); while (a.containsKey(realName)) { realName = a.get(realName); } out2.write(timezoneKey + " (alias for " + "<A HREF=\"" + timezoneList.get(realName) + "\" TARGET=\"rightFrame\">" + realName + "</A>)"); } else { out2.write("<A HREF=\"" + timezoneList.get(timezoneKey) + "\" TARGET=\"rightFrame\">" + timezoneKey + "</A>"); } out2.write("<BR>\n"); } out2.write("</TD>\n</TR>\n</TABLE>\n" + body2 + footer); out2.close(); fw2.close(); } out1.write("</FONT></TD>\n</TR></TABLE>\n" + body2 + footer); out1.close(); fw1.close(); /* Creates allTimeZone-frame1.html (Sorted by GMT offsets) */ fw1 = new FileWriter(outputDir + "allTimeZone-frame1.html", false); out1 = new BufferedWriter(fw1); out1.write(header1 + new Date() + header2 + Main.getVersionName() + header4 + body1 + "<FONT size=\"+1\"><B>Sorted by GMT offsets</B></FONT>\n" + "<BR>\n\n" + "<TABLE BORDER=\"0\" WIDTH=\"100%\">\n" + "<TR>\n<TD NOWRAP>\n"); List<Integer> roi = map.getRawOffsetsIndex(); List<Set<String>> roit = map.getRawOffsetsIndexTable(); int index = 0; for (Integer offset : zonesByOffset.keySet()) { int off = roi.get(index); Set<String> perRO = zonesByOffset.get(offset); if (offset == off) { // Merge aliases into zonesByOffset perRO.addAll(roit.get(index)); } index++; for (String timezoneKey : perRO) { out1.write("<TR>\n<TD><FONT SIZE=\"-1\">(" + Time.toGMTFormat(offset.toString()) + ")</FONT></TD>\n<TD>"); if (a.containsKey(timezoneKey)) { Object realName = a.get(timezoneKey); while (a.containsKey(realName)) { realName = a.get(realName); } out1.write(timezoneKey + " (alias for " + "<A HREF=\"" + timezoneList.get(realName) + "\" TARGET=\"rightFrame\">" + realName + "</A>)"); } else { out1.write("<A HREF=\"" + timezoneList.get(timezoneKey) + "\" TARGET=\"rightFrame\">" + timezoneKey + "</A>"); } out1.write("</TD>\n</TR>\n"); } } out1.write("</FONT></TD>\n</TR>\n</TABLE>\n" + body2 + footer); out1.close(); fw1.close(); /* Creates allTimeZone-frame2.html (Sorted by zone names) */ fw1 = new FileWriter(outputDir + "allTimeZone-frame2.html", false); out1 = new BufferedWriter(fw1); out1.write(header1 + new Date() + header2 + Main.getVersionName() + header4 + body1 + "<FONT size=\"+1\"><B>Sorted by zone names</B></FONT>\n" + "<BR>\n\n" + "<TABLE BORDER=\"0\" WIDTH=\"100%\">\n" + "<TR>\n<TD NOWRAP>\n"); o = timezoneList.keySet().toArray(); len = timezoneList.size(); for (int i = 0; i < len; i++) { Object timezoneKey = o[i]; if (a.containsKey(timezoneKey)) { Object realName = a.get(timezoneKey); while (a.containsKey(realName)) { realName = a.get(realName); } out1.write(timezoneKey + " (alias for " + "<A HREF=\"" + timezoneList.get(realName) + "\" TARGET=\"rightFrame\">" + realName + "</A>)"); } else { out1.write("<A HREF=\"" + timezoneList.get(timezoneKey) + "\" TARGET=\"rightFrame\">" + timezoneKey + "</A>"); } out1.write("<BR> \n"); } out1.write("</FONT></TD>\n</TR>\n</TABLE>\n" + body2 + footer); out1.close(); fw1.close(); /* Creates allTimeZone-frame3.html (Sorted by city names) */ fw1 = new FileWriter(outputDir + "allTimeZone-frame3.html", false); out1 = new BufferedWriter(fw1); out1.write(header1 + new Date() + header2 + Main.getVersionName() + header4 + body1 + "<FONT size=\"+1\"><B>Sorted by city names</B></FONT>\n" + "<BR>\n\n" + "<TABLE BORDER=\"0\" WIDTH=\"100%\">\n" + "<TR>\n<TD NOWRAP>\n"); Set<String> aliasSet = a.keySet(); len = aliasSet.size(); String aliasNames[] = aliasSet.toArray(new String[0]); for (int i = 0; i < len; i++) { displayNameList.put(transform(aliasNames[i]), aliasNames[i]); } o = displayNameList.keySet().toArray(); len = displayNameList.size(); for (int i = 0; i < len; i++) { Object displayName = o[i]; Object timezoneKey = displayNameList.get(o[i]); if (a.containsKey(timezoneKey)) { Object realName = a.get(timezoneKey); while (a.containsKey(realName)) { realName = a.get(realName); } out1.write(displayName + " (alias for " + "<A HREF=\"" + timezoneList.get(realName) + "\" TARGET=\"rightFrame\">" + realName + "</A>)"); } else { out1.write("<A HREF=\"" + timezoneList.get(timezoneKey) + "\" TARGET=\"rightFrame\">" + displayName + "</A>"); } out1.write("<BR> \n"); } out1.write("</FONT></TD>\n</TR>\n</TABLE>\n" + body2 + footer); out1.close(); fw1.close(); /* Creates overview-summary.html */ fw1 = new FileWriter(outputDir + "overview-summary.html", false); out1 = new BufferedWriter(fw1); out1.write(header1 + new Date() + header2 + Main.getVersionName() + header4 + body1 + "<p>This is the list of time zones generated from <B>" + Main.getVersionName() + "</B> for Java Platform, " + "Standard Edition. The source code can be obtained " + "from ftp site <a href=\"ftp://elsie.nci.nih.gov/pub/\">" + "ftp://elsie.nci.nih.gov/pub/</a>. A total of <B>" + len + "</B> time zones and aliases are supported " + "in this edition. For the " + "format of rules and zones, refer to the zic " + "(zoneinfo compiler) man page on " + "Solaris or Linux.</p>\n" + "<p>Note that the time zone data is not " + "a public interface of the Java Platform. No " + "applications should rely on the time zone data of " + "this document. Time zone names and data " + "may change without any prior notice.</p>\n" + body2 + footer); out1.close(); fw1.close(); } catch(IOException e) { Main.panic("IO error: "+e.getMessage()); return 1; } return 0; } String transform(String s) { int index = s.lastIndexOf("/"); /* If the string doesn't include any delimiter, return */ if (index == -1) { return s; } int lastIndex = index; String str = s.substring(index+1); do { index = s.substring(0, lastIndex).lastIndexOf('/'); str += ", " + s.substring(index+1, lastIndex); lastIndex = index; } while (index > -1); return str; } static class LatitudeAndLongitude { private int latDeg, latMin, latSec, longDeg, longMin, longSec; LatitudeAndLongitude(String s) { try { // First of all, check the string has the correct format: // either +-DDMM+-DDDMM or +-DDMMSS+-DDDMMSS if (!s.startsWith("+") && !s.startsWith("-")) { Main.warning("Wrong latitude&longitude data: " + s); return; } int index; if (((index = s.lastIndexOf("+")) <= 0) && ((index = s.lastIndexOf("-")) <= 0)) { Main.warning("Wrong latitude&longitude data: " + s); return; } if (index == 5) { latDeg = Integer.parseInt(s.substring(1, 3)); latMin = Integer.parseInt(s.substring(3, 5)); latSec = 0; } else if (index == 7) { latDeg = Integer.parseInt(s.substring(1, 3)); latMin = Integer.parseInt(s.substring(3, 5)); latSec = Integer.parseInt(s.substring(5, 7)); } else { Main.warning("Wrong latitude&longitude data: " + s); return; } if (s.startsWith("-")){ latDeg = -latDeg; latMin = -latMin; latSec = -latSec; } int len = s.length(); if (index == 5 && len == 11) { longDeg = Integer.parseInt(s.substring(index+1, index+4)); longMin = Integer.parseInt(s.substring(index+4, index+6)); longSec = 0; } else if (index == 7 && len == 15) { longDeg = Integer.parseInt(s.substring(index+1, index+4)); longMin = Integer.parseInt(s.substring(index+4, index+6)); longSec = Integer.parseInt(s.substring(index+6, index+8)); } else { Main.warning("Wrong latitude&longitude data: " + s); return; } if (s.charAt(index) == '-'){ longDeg = -longDeg; longMin = -longMin; longSec = -longSec; } } catch(Exception e) { Main.warning("LatitudeAndLongitude() Parse error: " + s); } } int getLatDeg() { return latDeg; } int getLatMin() { return latMin; } int getLatSec() { return latSec; } int getLongDeg() { return longDeg; } int getLongMin() { return longMin; } int getLongSec() { return longSec; } } }