Path: blob/master/test/jdk/sun/util/calendar/zi/GenDoc.java
41153 views
/*1* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.io.BufferedReader;24import java.io.BufferedWriter;25import java.io.File;26import java.io.FileReader;27import java.io.FileWriter;28import java.io.IOException;29import java.util.Date;30import java.util.HashMap;31import java.util.List;32import java.util.Map;33import java.util.Set;34import java.util.SortedMap;35import java.util.StringTokenizer;36import java.util.TreeMap;37import java.util.TreeSet;3839/**40* <code>GenDoc</code> is one of back-end classes of javazic, and generates41* index.html and other html files which prints the detailed time zone42* information for each zone.43*/44class GenDoc extends BackEnd {4546private static final String docDir = "doc";4748private static final String header1 =49"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Frameset//EN\"" +50"\"http://www.w3.org/TR/REC-html40/frameset.dtd\">\n" +51"<HTML>\n<HEAD>\n<!-- Generated by javazic on ";52private static final String header2 =53"-->\n<TITLE>\n" +54"Java Platform, Standard Edition - TimeZone information based on ";55private static final String header3 =56"-->\n<TITLE>\n" +57"Java Platform, Standard Edition TimeZone - ";58private static final String header4 =59"</TITLE>\n" +60"</HEAD>\n\n";6162private static final String body1 =63"<BODY BGCOLOR=\"white\">\n";64private static final String body2 =65"</BODY>\n";6667private static final String footer =68"</HTML>\n";697071// list of time zone name and zonefile name/real time zone name72// e.g.73// key (String) : value (String)74// "America/Denver" : "America/Denver.html" (real time zone)75// "America/Shiprock" : "America/Denver" (alias)76TreeMap<String,String> timezoneList = new TreeMap<String,String>();7778// list of time zone's display name and time zone name79// e.g.80// key (String) : value (String)81// "Tokyo, Asia" : "Asia/Tokyo"82// "Marengo, Indiana, America" : "America/Indiana/Marengo"83// (aliases included)84TreeMap<String,String> displayNameList = new TreeMap<String,String>();8586// list of top level regions87// e.g.88// key (String) : value (String)89// "America" : "America.html"90// (including entries in America/Indiana/, America/Kentucky/, ...)91TreeMap<String,String> regionList = new TreeMap<String,String>();9293// mapping list from zone name to latitude & longitude94// This list is generated from zone.tab.95// e.g.96// key (String) : value (LatitudeAndLongitude object)97// "Asia/Tokyo" : latitude=35.3916, longitude=13.944498// (aliases not included)99HashMap<String,LatitudeAndLongitude> mapList = null;100101// SortedMap of zone IDs sorted by their GMT offsets. If zone's GMT102// offset will change in the future, its last known offset is103// used.104SortedMap<Integer, Set<String>> zonesByOffset = new TreeMap<Integer, Set<String>>();105106/**107* Generates HTML document for each zone.108* @param Timezone109* @return 0 if no errors, or 1 if error occurred.110*/111int processZoneinfo(Timezone tz) {112try {113int size;114int index;115String outputDir = Main.getOutputDir();116String zonename = tz.getName();117String zonefile = ZoneInfoFile.getFileName(zonename) + ".html";118List<RuleRec> stz = tz.getLastRules();119timezoneList.put(zonename, zonefile);120displayNameList.put(transform(zonename), zonename);121122// Populate zonesByOffset. (Zones that will change their123// GMT offsets are also added to zonesByOffset here.)124int lastKnownOffset = tz.getRawOffset();125Set<String> set = zonesByOffset.get(lastKnownOffset);126if (set == null) {127set = new TreeSet<String>();128zonesByOffset.put(lastKnownOffset, set);129}130set.add(zonename);131132/* If outputDir doesn't end with file-separator, adds it. */133if (!outputDir.endsWith(File.separator)) {134outputDir += File.separatorChar;135}136outputDir += docDir + File.separatorChar;137138index = zonename.indexOf('/');139if (index != -1) {140regionList.put(zonename.substring(0, index),141zonename.substring(0, index) + ".html");142}143144/* If zonefile includes file-separator, it's treated as part of145* pathname. And make directory if necessary.146*/147index = zonefile.lastIndexOf('/');148if (index != -1) {149zonefile.replace('/', File.separatorChar);150outputDir += zonefile.substring(0, index+1);151}152File outD = new File(outputDir);153outD.mkdirs();154155/* If mapfile is available, add a link to the appropriate map */156if ((mapList == null) && (Main.getMapFile() != null)) {157FileReader fr = new FileReader(Main.getMapFile());158BufferedReader in = new BufferedReader(fr);159mapList = new HashMap<String,LatitudeAndLongitude>();160String line;161while ((line = in.readLine()) != null) {162// skip blank and comment lines163if (line.length() == 0 || line.charAt(0) == '#') {164continue;165}166StringTokenizer tokens = new StringTokenizer(line);167String token = tokens.nextToken(); /* We don't use the first token. */168token = tokens.nextToken();169LatitudeAndLongitude location = new LatitudeAndLongitude(token);170token = tokens.nextToken();171mapList.put(token, location);172}173in.close();174}175176/* Open zoneinfo file to write. */177FileWriter fw = new FileWriter(outputDir + zonefile.substring(index+1));178BufferedWriter out = new BufferedWriter(fw);179180out.write(header1 + new Date() + header3 + zonename + header4);181out.write(body1 + "<FONT size=\"+2\"><B>" + zonename + "</B></FONT>");182LatitudeAndLongitude location = mapList.get(zonename);183if (location != null) {184int deg, min, sec;185186deg = location.getLatDeg();187min = location.getLatMin();188sec = location.getLatSec();189if (deg < 0) {190min = -min;191sec = -sec;192} else if (min < 0) {193sec = -sec;194}195out.write(" " +196"<A HREF=\"http://www.mapquest.com/maps/map.adp?" +197"latlongtype=degrees" +198"&latdeg=" + deg +199"&latmin=" + min +200"&latsec=" + sec);201202deg = location.getLongDeg();203min = location.getLongMin();204sec = location.getLongSec();205if (deg < 0) {206min = -min;207sec = -sec;208} else if (min < 0) {209sec = -sec;210}211out.write("&longdeg=" + deg +212"&longmin=" + min +213"&longsec=" + sec +214"\" target=\"_blank\">[map]</A>");215}216out.write("\n<P>\n");217218List<ZoneRec> zone = tz.getZones();219List<RuleRec> rule = tz.getRules();220if (rule != null && zone != null) {221out.write("<TABLE BORDER=\"0\" WIDTH=\"100%\" CELLPADDING=\"1\" CELLSPACING=\"0\">\n" +222"<TR>\n" +223"<TD BGCOLOR=\"#EEEEFF\" WIDTH=\"50%\" ALIGN=\"CENTER\"><BR>" +224"<A HREF=\"#Rules\">Rules</A><BR></TD>\n" +225"<TD BGCOLOR=\"#EEEEFF\" WIDTH=\"50%\" ALIGN=\"CENTER\">" +226"<A HREF=\"#Zone\"><BR>Zone<BR></A></TD>\n" +227"</TR>\n</TABLE>\n");228}229230/* Output Rule records. */231if (rule != null) {232size = rule.size();233out.write("<P>\n<A NAME=\"Rules\">" +234"<FONT SIZE=\"+1\"><B>Rules</B></FONT></A>\n" +235"<TABLE BORDER=\"1\" WIDTH=\"100%\" CELLPADDING=\"3\" CELLSPACING=\"0\">\n" +236"<TR BGCOLOR=\"#CCCCFF\">\n" +237"<TD>NAME</TD><TD>FROM</TD><TD>TO</TD><TD>TYPE</TD>" +238"<TD>IN</TD><TD>ON</TD><TD>AT</TD><TD>SAVE</TD>" +239"<TD>LETTER/S</TD><TD>NOTES</TD>\n</TR>\n");240for (int i = 0; i < size; i++) {241out.write("<TR BGCOLOR=\"#FFFFFF\">\n");242StringTokenizer st = new StringTokenizer(rule.get(i).getLine());243String s;244if (st.hasMoreTokens()) { /* RULE - truncated */245st.nextToken();246}247if (st.hasMoreTokens()) { /* NAME */248out.write("<TD>" + st.nextToken() + "</TD>");249}250if (st.hasMoreTokens()) { /* FROM */251out.write("<TD>" + st.nextToken() + "</TD>");252}253if (st.hasMoreTokens()) { /* TO */254s = st.nextToken();255if (s.equals("min") || s.equals("max")) {256out.write("<TD><FONT COLOR=\"red\">" + s + "</FONT></TD>");257} else {258out.write("<TD>" + s + "</TD>");259}260}261if (st.hasMoreTokens()) { /* TYPE */262out.write("<TD>" + st.nextToken() + "</TD>");263}264if (st.hasMoreTokens()) { /* IN */265out.write("<TD>" + st.nextToken() + "</TD>");266}267if (st.hasMoreTokens()) { /* ON */268out.write("<TD>" + st.nextToken() + "</TD>");269}270if (st.hasMoreTokens()) { /* AT */271out.write("<TD>" + st.nextToken() + "</TD>");272}273if (st.hasMoreTokens()) { /* SAVE */274out.write("<TD>" + st.nextToken() + "</TD>");275}276if (st.hasMoreTokens()) { /* LETTER/S */277out.write("<TD>" + st.nextToken() + "</TD>");278}279if (st.hasMoreTokens()) { /* NOTES */280s = st.nextToken();281while (st.hasMoreTokens()) {282s += " " + st.nextToken();283}284index = s.indexOf('#');285out.write("<TD>" + s.substring(index+1) + "</TD>\n");286} else {287out.write("<TD> </TD>\n");288}289out.write("</TR>\n");290}291out.write("</TABLE>\n<P> <P>\n");292}293294/* Output Zone records. */295if (zone != null) {296size = zone.size();297out.write("<P>\n<A NAME=\"Zone\">" +298"<FONT SIZE=\"+1\"><B>Zone</B></FONT></A>\n" +299"<TABLE BORDER=\"1\" WIDTH=\"100%\" CELLPADDING=\"3\" CELLSPACING=\"0\">\n" +300"<TR BGCOLOR=\"#CCCCFF\">\n<TD>GMTOFF</TD>" +301"<TD>RULES</TD><TD>FORMAT</TD><TD>UNTIL</TD>" +302"<TD>NOTES</TD>\n</TR>\n");303for (int i = 0; i < size; i++) {304out.write("<TR>\n");305StringTokenizer st = new StringTokenizer(zone.get(i).getLine());306String s = st.nextToken();307if (s.equals("Zone")) { /* NAME */308s = st.nextToken();309s = st.nextToken();310}311out.write("<TD>" + s + "</TD>"); /* GMTOFFSET */312if (st.hasMoreTokens()) { /* RULES */313out.write("<TD>" + st.nextToken() + "</TD>");314}315if (st.hasMoreTokens()) { /* FORMAT */316s = st.nextToken();317index = s.indexOf('#');318if (index != -1) {319if (index != 0) {320out.write("<TD>" + s.substring(0, index-1) +321"</TD>"); /* FORMAT */322s = s.substring(index+1);323} else {324out.write("<TD> </TD>"); /* FORMAT */325}326while (st.hasMoreTokens()) {327s += " " + st.nextToken();328}329out.write("<TD> </TD>"); /* UNTIL */330out.write("<TD>" + s + "</TD>\n</TR>\n"); /* NOTES */331continue;332} else {333out.write("<TD>" + s + "</TD>"); /* FORMAT */334}335}336337if (st.hasMoreTokens()) { /* UNTIL */338s = st.nextToken();339while (st.hasMoreTokens()) {340s += " " + st.nextToken();341}342index = s.indexOf('#');343if (index != -1) {344if (index != 0) {345out.write("<TD>" + s.substring(0, index-1) +346"</TD>"); /* UNTIL */347} else {348out.write("<TD> </TD>"); /* UNTIL */349}350out.write("<TD>" + s.substring(index+1) +351"</TD>\n"); /* NOTES */352} else {353out.write("<TD>" + s + "</TD>"); /* UNTIL */354out.write("<TD> </TD>\n"); /* NOTES */355}356} else {357out.write("<TD> </TD>"); /* UNTIL */358out.write("<TD> </TD>\n"); /* NOTES */359}360out.write("</TR>\n");361}362out.write("</TABLE>\n");363}364out.write(body2 + footer);365366out.close();367fw.close();368} catch(IOException e) {369Main.panic("IO error: "+e.getMessage());370return 1;371}372373return 0;374}375376/**377* Generates index.html and other top-level frame files.378* @param Mappings379* @return 0 if no errors, or 1 if error occurred.380*/381int generateSrc(Mappings map) {382try {383int len;384Object o[];385String outputDir = Main.getOutputDir();386FileWriter fw1, fw2;387BufferedWriter out1, out2;388389/* Whether alias list exists or not. */390Map<String,String> a = map.getAliases();391if (a == null) {392Main.panic("Data not exist. (aliases)");393return 1;394}395396timezoneList.putAll(a);397398/* If outputDir doesn't end with file-separator, adds it. */399if (!outputDir.endsWith(File.separator)) {400outputDir += File.separatorChar;401}402outputDir += docDir + File.separatorChar;403404File outD = new File(outputDir);405outD.mkdirs();406407/* Creates index.html */408fw1 = new FileWriter(outputDir + "index.html", false);409out1 = new BufferedWriter(fw1);410411out1.write(header1 + new Date() + header2 + Main.getVersionName() +412header4 +413"<FRAMESET cols=\"20%,80%\">\n" +414"<FRAMESET rows=\"30%,70%\">\n" +415"<FRAME src=\"overview-frame.html\" name=\"TimeZoneListFrame\">\n" +416"<FRAME src=\"allTimeZone-frame1.html\" name=\"allTimeZoneFrame\">\n" +417"</FRAMESET>" +418"<FRAME src=\"overview-summary.html\" name=\"rightFrame\">\n" +419"</FRAMESET>\n" +420"<NOFRAMES>\n" +421"<H2>\nFrame Alert\n</H2>\n\n" +422"<P>\n\n" +423"This document is designed to be viewed using the frames feature. If you see this\n" +424"message, you are using a non-frame-capable web client.\n" +425"<BR>\n" +426"Link to<A HREF=\"overview-summary.html\">Non-frame version.</A>\n" +427"</NOFRAMES>\n" + footer);428429out1.close();430fw1.close();431432433/* Creates overview-frame.html */434fw1 = new FileWriter(outputDir + "overview-frame.html", false);435out1 = new BufferedWriter(fw1);436437out1.write(header1 + new Date() + header2 + Main.getVersionName() +438header4 + body1 +439"<TABLE BORDER=\"0\" WIDTH=\"100%\">\n<TR>\n" +440"<TD NOWRAP><FONT size=\"+1\">\n" +441"<B>Java<sup><font size=-2>TM</font></sup> Platform<br>Standard Ed.</B></FONT></TD>\n" +442"</TR>\n</TABLE>\n\n" +443"<TABLE BORDER=\"0\" WIDTH=\"100%\">\n<TR>\n<TD NOWRAP>" +444"<P>\n<FONT size=\"+1\">\nAll Time Zones Sorted By:</FONT>\n<BR>\n" +445" <A HREF=\"allTimeZone-frame1.html\" TARGET=\"allTimeZoneFrame\">GMT offsets</A></FONT>\n<BR>\n" +446" <A HREF=\"allTimeZone-frame2.html\" TARGET=\"allTimeZoneFrame\">Zone names</A></FONT>\n<BR>" +447" <A HREF=\"allTimeZone-frame3.html\" TARGET=\"allTimeZoneFrame\">City names</A></FONT>\n" +448"<P>\n<FONT size=\"+1\">\nContinents and Oceans</FONT>\n<BR>\n");449450for (String regionKey : regionList.keySet()) {451out1.write(" <A HREF=\"" + regionList.get(regionKey) +452"\" TARGET=\"allTimeZoneFrame\">" + regionKey +453"</A><BR>\n");454455fw2 = new FileWriter(outputDir + regionList.get(regionKey),456false);457out2 = new BufferedWriter(fw2);458459out2.write(header1 + new Date() + header3 + regionKey +460header4 + body1 + "<FONT size=\"+1\"><B>" +461regionKey + "</B></FONT>\n<BR>\n<TABLE>\n<TR>\n<TD>");462463boolean found = false;464for (String timezoneKey : timezoneList.keySet()) {465int regionIndex = timezoneKey.indexOf('/');466if (regionIndex == -1 ||467!regionKey.equals(timezoneKey.substring(0, regionIndex))) {468if (found) {469break;470} else {471continue;472}473}474475found = true;476if (a.containsKey(timezoneKey)) {477Object realName = a.get(timezoneKey);478while (a.containsKey(realName)) {479realName = a.get(realName);480}481out2.write(timezoneKey +482" (alias for " + "<A HREF=\"" +483timezoneList.get(realName) +484"\" TARGET=\"rightFrame\">" +485realName + "</A>)");486} else {487out2.write("<A HREF=\"" + timezoneList.get(timezoneKey) +488"\" TARGET=\"rightFrame\">" + timezoneKey +489"</A>");490}491out2.write("<BR>\n");492}493out2.write("</TD>\n</TR>\n</TABLE>\n" + body2 + footer);494495out2.close();496fw2.close();497}498out1.write("</FONT></TD>\n</TR></TABLE>\n" + body2 + footer);499500out1.close();501fw1.close();502503504/* Creates allTimeZone-frame1.html (Sorted by GMT offsets) */505fw1 = new FileWriter(outputDir + "allTimeZone-frame1.html", false);506out1 = new BufferedWriter(fw1);507508out1.write(header1 + new Date() + header2 + Main.getVersionName() +509header4 + body1 +510"<FONT size=\"+1\"><B>Sorted by GMT offsets</B></FONT>\n" +511"<BR>\n\n" + "<TABLE BORDER=\"0\" WIDTH=\"100%\">\n" +512"<TR>\n<TD NOWRAP>\n");513514List<Integer> roi = map.getRawOffsetsIndex();515List<Set<String>> roit = map.getRawOffsetsIndexTable();516517int index = 0;518for (Integer offset : zonesByOffset.keySet()) {519int off = roi.get(index);520Set<String> perRO = zonesByOffset.get(offset);521if (offset == off) {522// Merge aliases into zonesByOffset523perRO.addAll(roit.get(index));524}525index++;526527for (String timezoneKey : perRO) {528out1.write("<TR>\n<TD><FONT SIZE=\"-1\">(" +529Time.toGMTFormat(offset.toString()) +530")</FONT></TD>\n<TD>");531532if (a.containsKey(timezoneKey)) {533Object realName = a.get(timezoneKey);534while (a.containsKey(realName)) {535realName = a.get(realName);536}537out1.write(timezoneKey +538" (alias for " + "<A HREF=\"" +539timezoneList.get(realName) +540"\" TARGET=\"rightFrame\">" + realName +541"</A>)");542} else {543out1.write("<A HREF=\"" + timezoneList.get(timezoneKey) +544"\" TARGET=\"rightFrame\">" + timezoneKey +545"</A>");546}547out1.write("</TD>\n</TR>\n");548}549}550out1.write("</FONT></TD>\n</TR>\n</TABLE>\n" + body2 + footer);551552out1.close();553fw1.close();554555556/* Creates allTimeZone-frame2.html (Sorted by zone names) */557fw1 = new FileWriter(outputDir + "allTimeZone-frame2.html", false);558out1 = new BufferedWriter(fw1);559560out1.write(header1 + new Date() + header2 + Main.getVersionName() +561header4 + body1 +562"<FONT size=\"+1\"><B>Sorted by zone names</B></FONT>\n" +563"<BR>\n\n" + "<TABLE BORDER=\"0\" WIDTH=\"100%\">\n" +564"<TR>\n<TD NOWRAP>\n");565o = timezoneList.keySet().toArray();566len = timezoneList.size();567for (int i = 0; i < len; i++) {568Object timezoneKey = o[i];569if (a.containsKey(timezoneKey)) {570Object realName = a.get(timezoneKey);571while (a.containsKey(realName)) {572realName = a.get(realName);573}574out1.write(timezoneKey +575" (alias for " +576"<A HREF=\"" + timezoneList.get(realName) +577"\" TARGET=\"rightFrame\">" + realName +578"</A>)");579} else {580out1.write("<A HREF=\"" + timezoneList.get(timezoneKey) +581"\" TARGET=\"rightFrame\">" + timezoneKey +582"</A>");583}584out1.write("<BR> \n");585}586out1.write("</FONT></TD>\n</TR>\n</TABLE>\n" + body2 + footer);587588out1.close();589fw1.close();590591/* Creates allTimeZone-frame3.html (Sorted by city names) */592fw1 = new FileWriter(outputDir + "allTimeZone-frame3.html", false);593out1 = new BufferedWriter(fw1);594595out1.write(header1 + new Date() + header2 + Main.getVersionName() +596header4 + body1 +597"<FONT size=\"+1\"><B>Sorted by city names</B></FONT>\n" +598"<BR>\n\n" + "<TABLE BORDER=\"0\" WIDTH=\"100%\">\n" +599"<TR>\n<TD NOWRAP>\n");600601Set<String> aliasSet = a.keySet();602len = aliasSet.size();603String aliasNames[] = aliasSet.toArray(new String[0]);604for (int i = 0; i < len; i++) {605displayNameList.put(transform(aliasNames[i]),606aliasNames[i]);607}608609o = displayNameList.keySet().toArray();610len = displayNameList.size();611for (int i = 0; i < len; i++) {612Object displayName = o[i];613Object timezoneKey = displayNameList.get(o[i]);614if (a.containsKey(timezoneKey)) {615Object realName = a.get(timezoneKey);616while (a.containsKey(realName)) {617realName = a.get(realName);618}619out1.write(displayName +620" (alias for " +621"<A HREF=\"" + timezoneList.get(realName) +622"\" TARGET=\"rightFrame\">" + realName +623"</A>)");624} else {625out1.write("<A HREF=\"" + timezoneList.get(timezoneKey) +626"\" TARGET=\"rightFrame\">" + displayName +627"</A>");628}629out1.write("<BR> \n");630}631632out1.write("</FONT></TD>\n</TR>\n</TABLE>\n" + body2 + footer);633634out1.close();635fw1.close();636637/* Creates overview-summary.html */638fw1 = new FileWriter(outputDir + "overview-summary.html", false);639out1 = new BufferedWriter(fw1);640641out1.write(header1 + new Date() + header2 + Main.getVersionName() +642header4 + body1 +643"<p>This is the list of time zones generated from <B>" +644Main.getVersionName() + "</B> for Java Platform, " +645"Standard Edition. The source code can be obtained " +646"from ftp site <a href=\"ftp://elsie.nci.nih.gov/pub/\">" +647"ftp://elsie.nci.nih.gov/pub/</a>. A total of <B>" +648len +649"</B> time zones and aliases are supported " +650"in this edition. For the " +651"format of rules and zones, refer to the zic " +652"(zoneinfo compiler) man page on " +653"Solaris or Linux.</p>\n" +654"<p>Note that the time zone data is not " +655"a public interface of the Java Platform. No " +656"applications should rely on the time zone data of " +657"this document. Time zone names and data " +658"may change without any prior notice.</p>\n" +659body2 + footer);660661out1.close();662fw1.close();663} catch(IOException e) {664Main.panic("IO error: "+e.getMessage());665return 1;666}667668return 0;669}670671String transform(String s) {672int index = s.lastIndexOf("/");673674/* If the string doesn't include any delimiter, return */675if (index == -1) {676return s;677}678679int lastIndex = index;680String str = s.substring(index+1);681do {682index = s.substring(0, lastIndex).lastIndexOf('/');683str += ", " + s.substring(index+1, lastIndex);684lastIndex = index;685} while (index > -1);686687return str;688}689690static class LatitudeAndLongitude {691692private int latDeg, latMin, latSec, longDeg, longMin, longSec;693694LatitudeAndLongitude(String s) {695try {696// First of all, check the string has the correct format:697// either +-DDMM+-DDDMM or +-DDMMSS+-DDDMMSS698699if (!s.startsWith("+") && !s.startsWith("-")) {700Main.warning("Wrong latitude&longitude data: " + s);701return;702}703int index;704if (((index = s.lastIndexOf("+")) <= 0) &&705((index = s.lastIndexOf("-")) <= 0)) {706Main.warning("Wrong latitude&longitude data: " + s);707return;708}709710if (index == 5) {711latDeg = Integer.parseInt(s.substring(1, 3));712latMin = Integer.parseInt(s.substring(3, 5));713latSec = 0;714} else if (index == 7) {715latDeg = Integer.parseInt(s.substring(1, 3));716latMin = Integer.parseInt(s.substring(3, 5));717latSec = Integer.parseInt(s.substring(5, 7));718} else {719Main.warning("Wrong latitude&longitude data: " + s);720return;721}722if (s.startsWith("-")){723latDeg = -latDeg;724latMin = -latMin;725latSec = -latSec;726}727728int len = s.length();729if (index == 5 && len == 11) {730longDeg = Integer.parseInt(s.substring(index+1, index+4));731longMin = Integer.parseInt(s.substring(index+4, index+6));732longSec = 0;733} else if (index == 7 && len == 15) {734longDeg = Integer.parseInt(s.substring(index+1, index+4));735longMin = Integer.parseInt(s.substring(index+4, index+6));736longSec = Integer.parseInt(s.substring(index+6, index+8));737} else {738Main.warning("Wrong latitude&longitude data: " + s);739return;740}741if (s.charAt(index) == '-'){742longDeg = -longDeg;743longMin = -longMin;744longSec = -longSec;745}746} catch(Exception e) {747Main.warning("LatitudeAndLongitude() Parse error: " + s);748}749}750751int getLatDeg() {752return latDeg;753}754755int getLatMin() {756return latMin;757}758759int getLatSec() {760return latSec;761}762763int getLongDeg() {764return longDeg;765}766767int getLongMin() {768return longMin;769}770771int getLongSec() {772return longSec;773}774}775}776777778