Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/sun/util/calendar/zi/GenDoc.java
38855 views
/*1* Copyright (c) 2001, 2013, 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. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425import java.io.BufferedReader;26import java.io.BufferedWriter;27import java.io.File;28import java.io.FileReader;29import java.io.FileWriter;30import java.io.IOException;31import java.util.Date;32import java.util.HashMap;33import java.util.List;34import java.util.Map;35import java.util.Set;36import java.util.SortedMap;37import java.util.StringTokenizer;38import java.util.TreeMap;39import java.util.TreeSet;4041/**42* <code>GenDoc</code> is one of back-end classes of javazic, and generates43* index.html and other html files which prints the detailed time zone44* information for each zone.45*/46class GenDoc extends BackEnd {4748private static final String docDir = "doc";4950private static final String header1 =51"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Frameset//EN\"" +52"\"http://www.w3.org/TR/REC-html40/frameset.dtd\">\n" +53"<HTML>\n<HEAD>\n<!-- Generated by javazic on ";54private static final String header2 =55"-->\n<TITLE>\n" +56"Java Platform, Standard Edition - TimeZone information based on ";57private static final String header3 =58"-->\n<TITLE>\n" +59"Java Platform, Standard Edition TimeZone - ";60private static final String header4 =61"</TITLE>\n" +62"</HEAD>\n\n";6364private static final String body1 =65"<BODY BGCOLOR=\"white\">\n";66private static final String body2 =67"</BODY>\n";6869private static final String footer =70"</HTML>\n";717273// list of time zone name and zonefile name/real time zone name74// e.g.75// key (String) : value (String)76// "America/Denver" : "America/Denver.html" (real time zone)77// "America/Shiprock" : "America/Denver" (alias)78TreeMap<String,String> timezoneList = new TreeMap<String,String>();7980// list of time zone's display name and time zone name81// e.g.82// key (String) : value (String)83// "Tokyo, Asia" : "Asia/Tokyo"84// "Marengo, Indiana, America" : "America/Indiana/Marengo"85// (aliases included)86TreeMap<String,String> displayNameList = new TreeMap<String,String>();8788// list of top level regions89// e.g.90// key (String) : value (String)91// "America" : "America.html"92// (including entries in America/Indiana/, America/Kentucky/, ...)93TreeMap<String,String> regionList = new TreeMap<String,String>();9495// mapping list from zone name to latitude & longitude96// This list is generated from zone.tab.97// e.g.98// key (String) : value (LatitudeAndLongitude object)99// "Asia/Tokyo" : latitude=35.3916, longitude=13.9444100// (aliases not included)101HashMap<String,LatitudeAndLongitude> mapList = null;102103// SortedMap of zone IDs sorted by their GMT offsets. If zone's GMT104// offset will change in the future, its last known offset is105// used.106SortedMap<Integer, Set<String>> zonesByOffset = new TreeMap<Integer, Set<String>>();107108/**109* Generates HTML document for each zone.110* @param Timezone111* @return 0 if no errors, or 1 if error occurred.112*/113int processZoneinfo(Timezone tz) {114try {115int size;116int index;117String outputDir = Main.getOutputDir();118String zonename = tz.getName();119String zonefile = ZoneInfoFile.getFileName(zonename) + ".html";120List<RuleRec> stz = tz.getLastRules();121timezoneList.put(zonename, zonefile);122displayNameList.put(transform(zonename), zonename);123124// Populate zonesByOffset. (Zones that will change their125// GMT offsets are also added to zonesByOffset here.)126int lastKnownOffset = tz.getRawOffset();127Set<String> set = zonesByOffset.get(lastKnownOffset);128if (set == null) {129set = new TreeSet<String>();130zonesByOffset.put(lastKnownOffset, set);131}132set.add(zonename);133134/* If outputDir doesn't end with file-separator, adds it. */135if (!outputDir.endsWith(File.separator)) {136outputDir += File.separatorChar;137}138outputDir += docDir + File.separatorChar;139140index = zonename.indexOf('/');141if (index != -1) {142regionList.put(zonename.substring(0, index),143zonename.substring(0, index) + ".html");144}145146/* If zonefile includes file-separator, it's treated as part of147* pathname. And make directory if necessary.148*/149index = zonefile.lastIndexOf('/');150if (index != -1) {151zonefile.replace('/', File.separatorChar);152outputDir += zonefile.substring(0, index+1);153}154File outD = new File(outputDir);155outD.mkdirs();156157/* If mapfile is available, add a link to the appropriate map */158if ((mapList == null) && (Main.getMapFile() != null)) {159FileReader fr = new FileReader(Main.getMapFile());160BufferedReader in = new BufferedReader(fr);161mapList = new HashMap<String,LatitudeAndLongitude>();162String line;163while ((line = in.readLine()) != null) {164// skip blank and comment lines165if (line.length() == 0 || line.charAt(0) == '#') {166continue;167}168StringTokenizer tokens = new StringTokenizer(line);169String token = tokens.nextToken(); /* We don't use the first token. */170token = tokens.nextToken();171LatitudeAndLongitude location = new LatitudeAndLongitude(token);172token = tokens.nextToken();173mapList.put(token, location);174}175in.close();176}177178/* Open zoneinfo file to write. */179FileWriter fw = new FileWriter(outputDir + zonefile.substring(index+1));180BufferedWriter out = new BufferedWriter(fw);181182out.write(header1 + new Date() + header3 + zonename + header4);183out.write(body1 + "<FONT size=\"+2\"><B>" + zonename + "</B></FONT>");184LatitudeAndLongitude location = mapList.get(zonename);185if (location != null) {186int deg, min, sec;187188deg = location.getLatDeg();189min = location.getLatMin();190sec = location.getLatSec();191if (deg < 0) {192min = -min;193sec = -sec;194} else if (min < 0) {195sec = -sec;196}197out.write(" " +198"<A HREF=\"http://www.mapquest.com/maps/map.adp?" +199"latlongtype=degrees" +200"&latdeg=" + deg +201"&latmin=" + min +202"&latsec=" + sec);203204deg = location.getLongDeg();205min = location.getLongMin();206sec = location.getLongSec();207if (deg < 0) {208min = -min;209sec = -sec;210} else if (min < 0) {211sec = -sec;212}213out.write("&longdeg=" + deg +214"&longmin=" + min +215"&longsec=" + sec +216"\" target=\"_blank\">[map]</A>");217}218out.write("\n<P>\n");219220List<ZoneRec> zone = tz.getZones();221List<RuleRec> rule = tz.getRules();222if (rule != null && zone != null) {223out.write("<TABLE BORDER=\"0\" WIDTH=\"100%\" CELLPADDING=\"1\" CELLSPACING=\"0\">\n" +224"<TR>\n" +225"<TD BGCOLOR=\"#EEEEFF\" WIDTH=\"50%\" ALIGN=\"CENTER\"><BR>" +226"<A HREF=\"#Rules\">Rules</A><BR></TD>\n" +227"<TD BGCOLOR=\"#EEEEFF\" WIDTH=\"50%\" ALIGN=\"CENTER\">" +228"<A HREF=\"#Zone\"><BR>Zone<BR></A></TD>\n" +229"</TR>\n</TABLE>\n");230}231232/* Output Rule records. */233if (rule != null) {234size = rule.size();235out.write("<P>\n<A NAME=\"Rules\">" +236"<FONT SIZE=\"+1\"><B>Rules</B></FONT></A>\n" +237"<TABLE BORDER=\"1\" WIDTH=\"100%\" CELLPADDING=\"3\" CELLSPACING=\"0\">\n" +238"<TR BGCOLOR=\"#CCCCFF\">\n" +239"<TD>NAME</TD><TD>FROM</TD><TD>TO</TD><TD>TYPE</TD>" +240"<TD>IN</TD><TD>ON</TD><TD>AT</TD><TD>SAVE</TD>" +241"<TD>LETTER/S</TD><TD>NOTES</TD>\n</TR>\n");242for (int i = 0; i < size; i++) {243out.write("<TR BGCOLOR=\"#FFFFFF\">\n");244StringTokenizer st = new StringTokenizer(rule.get(i).getLine());245String s;246if (st.hasMoreTokens()) { /* RULE - truncated */247st.nextToken();248}249if (st.hasMoreTokens()) { /* NAME */250out.write("<TD>" + st.nextToken() + "</TD>");251}252if (st.hasMoreTokens()) { /* FROM */253out.write("<TD>" + st.nextToken() + "</TD>");254}255if (st.hasMoreTokens()) { /* TO */256s = st.nextToken();257if (s.equals("min") || s.equals("max")) {258out.write("<TD><FONT COLOR=\"red\">" + s + "</FONT></TD>");259} else {260out.write("<TD>" + s + "</TD>");261}262}263if (st.hasMoreTokens()) { /* TYPE */264out.write("<TD>" + st.nextToken() + "</TD>");265}266if (st.hasMoreTokens()) { /* IN */267out.write("<TD>" + st.nextToken() + "</TD>");268}269if (st.hasMoreTokens()) { /* ON */270out.write("<TD>" + st.nextToken() + "</TD>");271}272if (st.hasMoreTokens()) { /* AT */273out.write("<TD>" + st.nextToken() + "</TD>");274}275if (st.hasMoreTokens()) { /* SAVE */276out.write("<TD>" + st.nextToken() + "</TD>");277}278if (st.hasMoreTokens()) { /* LETTER/S */279out.write("<TD>" + st.nextToken() + "</TD>");280}281if (st.hasMoreTokens()) { /* NOTES */282s = st.nextToken();283while (st.hasMoreTokens()) {284s += " " + st.nextToken();285}286index = s.indexOf('#');287out.write("<TD>" + s.substring(index+1) + "</TD>\n");288} else {289out.write("<TD> </TD>\n");290}291out.write("</TR>\n");292}293out.write("</TABLE>\n<P> <P>\n");294}295296/* Output Zone records. */297if (zone != null) {298size = zone.size();299out.write("<P>\n<A NAME=\"Zone\">" +300"<FONT SIZE=\"+1\"><B>Zone</B></FONT></A>\n" +301"<TABLE BORDER=\"1\" WIDTH=\"100%\" CELLPADDING=\"3\" CELLSPACING=\"0\">\n" +302"<TR BGCOLOR=\"#CCCCFF\">\n<TD>GMTOFF</TD>" +303"<TD>RULES</TD><TD>FORMAT</TD><TD>UNTIL</TD>" +304"<TD>NOTES</TD>\n</TR>\n");305for (int i = 0; i < size; i++) {306out.write("<TR>\n");307StringTokenizer st = new StringTokenizer(zone.get(i).getLine());308String s = st.nextToken();309if (s.equals("Zone")) { /* NAME */310s = st.nextToken();311s = st.nextToken();312}313out.write("<TD>" + s + "</TD>"); /* GMTOFFSET */314if (st.hasMoreTokens()) { /* RULES */315out.write("<TD>" + st.nextToken() + "</TD>");316}317if (st.hasMoreTokens()) { /* FORMAT */318s = st.nextToken();319index = s.indexOf('#');320if (index != -1) {321if (index != 0) {322out.write("<TD>" + s.substring(0, index-1) +323"</TD>"); /* FORMAT */324s = s.substring(index+1);325} else {326out.write("<TD> </TD>"); /* FORMAT */327}328while (st.hasMoreTokens()) {329s += " " + st.nextToken();330}331out.write("<TD> </TD>"); /* UNTIL */332out.write("<TD>" + s + "</TD>\n</TR>\n"); /* NOTES */333continue;334} else {335out.write("<TD>" + s + "</TD>"); /* FORMAT */336}337}338339if (st.hasMoreTokens()) { /* UNTIL */340s = st.nextToken();341while (st.hasMoreTokens()) {342s += " " + st.nextToken();343}344index = s.indexOf('#');345if (index != -1) {346if (index != 0) {347out.write("<TD>" + s.substring(0, index-1) +348"</TD>"); /* UNTIL */349} else {350out.write("<TD> </TD>"); /* UNTIL */351}352out.write("<TD>" + s.substring(index+1) +353"</TD>\n"); /* NOTES */354} else {355out.write("<TD>" + s + "</TD>"); /* UNTIL */356out.write("<TD> </TD>\n"); /* NOTES */357}358} else {359out.write("<TD> </TD>"); /* UNTIL */360out.write("<TD> </TD>\n"); /* NOTES */361}362out.write("</TR>\n");363}364out.write("</TABLE>\n");365}366out.write(body2 + footer);367368out.close();369fw.close();370} catch(IOException e) {371Main.panic("IO error: "+e.getMessage());372return 1;373}374375return 0;376}377378/**379* Generates index.html and other top-level frame files.380* @param Mappings381* @return 0 if no errors, or 1 if error occurred.382*/383int generateSrc(Mappings map) {384try {385int len;386Object o[];387String outputDir = Main.getOutputDir();388FileWriter fw1, fw2;389BufferedWriter out1, out2;390391/* Whether alias list exists or not. */392Map<String,String> a = map.getAliases();393if (a == null) {394Main.panic("Data not exist. (aliases)");395return 1;396}397398timezoneList.putAll(a);399400/* If outputDir doesn't end with file-separator, adds it. */401if (!outputDir.endsWith(File.separator)) {402outputDir += File.separatorChar;403}404outputDir += docDir + File.separatorChar;405406File outD = new File(outputDir);407outD.mkdirs();408409/* Creates index.html */410fw1 = new FileWriter(outputDir + "index.html", false);411out1 = new BufferedWriter(fw1);412413out1.write(header1 + new Date() + header2 + Main.getVersionName() +414header4 +415"<FRAMESET cols=\"20%,80%\">\n" +416"<FRAMESET rows=\"30%,70%\">\n" +417"<FRAME src=\"overview-frame.html\" name=\"TimeZoneListFrame\">\n" +418"<FRAME src=\"allTimeZone-frame1.html\" name=\"allTimeZoneFrame\">\n" +419"</FRAMESET>" +420"<FRAME src=\"overview-summary.html\" name=\"rightFrame\">\n" +421"</FRAMESET>\n" +422"<NOFRAMES>\n" +423"<H2>\nFrame Alert\n</H2>\n\n" +424"<P>\n\n" +425"This document is designed to be viewed using the frames feature. If you see this\n" +426"message, you are using a non-frame-capable web client.\n" +427"<BR>\n" +428"Link to<A HREF=\"overview-summary.html\">Non-frame version.</A>\n" +429"</NOFRAMES>\n" + footer);430431out1.close();432fw1.close();433434435/* Creates overview-frame.html */436fw1 = new FileWriter(outputDir + "overview-frame.html", false);437out1 = new BufferedWriter(fw1);438439out1.write(header1 + new Date() + header2 + Main.getVersionName() +440header4 + body1 +441"<TABLE BORDER=\"0\" WIDTH=\"100%\">\n<TR>\n" +442"<TD NOWRAP><FONT size=\"+1\">\n" +443"<B>Java<sup><font size=-2>TM</font></sup> Platform<br>Standard Ed.</B></FONT></TD>\n" +444"</TR>\n</TABLE>\n\n" +445"<TABLE BORDER=\"0\" WIDTH=\"100%\">\n<TR>\n<TD NOWRAP>" +446"<P>\n<FONT size=\"+1\">\nAll Time Zones Sorted By:</FONT>\n<BR>\n" +447" <A HREF=\"allTimeZone-frame1.html\" TARGET=\"allTimeZoneFrame\">GMT offsets</A></FONT>\n<BR>\n" +448" <A HREF=\"allTimeZone-frame2.html\" TARGET=\"allTimeZoneFrame\">Zone names</A></FONT>\n<BR>" +449" <A HREF=\"allTimeZone-frame3.html\" TARGET=\"allTimeZoneFrame\">City names</A></FONT>\n" +450"<P>\n<FONT size=\"+1\">\nContinents and Oceans</FONT>\n<BR>\n");451452for (String regionKey : regionList.keySet()) {453out1.write(" <A HREF=\"" + regionList.get(regionKey) +454"\" TARGET=\"allTimeZoneFrame\">" + regionKey +455"</A><BR>\n");456457fw2 = new FileWriter(outputDir + regionList.get(regionKey),458false);459out2 = new BufferedWriter(fw2);460461out2.write(header1 + new Date() + header3 + regionKey +462header4 + body1 + "<FONT size=\"+1\"><B>" +463regionKey + "</B></FONT>\n<BR>\n<TABLE>\n<TR>\n<TD>");464465boolean found = false;466for (String timezoneKey : timezoneList.keySet()) {467int regionIndex = timezoneKey.indexOf('/');468if (regionIndex == -1 ||469!regionKey.equals(timezoneKey.substring(0, regionIndex))) {470if (found) {471break;472} else {473continue;474}475}476477found = true;478if (a.containsKey(timezoneKey)) {479Object realName = a.get(timezoneKey);480while (a.containsKey(realName)) {481realName = a.get(realName);482}483out2.write(timezoneKey +484" (alias for " + "<A HREF=\"" +485timezoneList.get(realName) +486"\" TARGET=\"rightFrame\">" +487realName + "</A>)");488} else {489out2.write("<A HREF=\"" + timezoneList.get(timezoneKey) +490"\" TARGET=\"rightFrame\">" + timezoneKey +491"</A>");492}493out2.write("<BR>\n");494}495out2.write("</TD>\n</TR>\n</TABLE>\n" + body2 + footer);496497out2.close();498fw2.close();499}500out1.write("</FONT></TD>\n</TR></TABLE>\n" + body2 + footer);501502out1.close();503fw1.close();504505506/* Creates allTimeZone-frame1.html (Sorted by GMT offsets) */507fw1 = new FileWriter(outputDir + "allTimeZone-frame1.html", false);508out1 = new BufferedWriter(fw1);509510out1.write(header1 + new Date() + header2 + Main.getVersionName() +511header4 + body1 +512"<FONT size=\"+1\"><B>Sorted by GMT offsets</B></FONT>\n" +513"<BR>\n\n" + "<TABLE BORDER=\"0\" WIDTH=\"100%\">\n" +514"<TR>\n<TD NOWRAP>\n");515516List<Integer> roi = map.getRawOffsetsIndex();517List<Set<String>> roit = map.getRawOffsetsIndexTable();518519int index = 0;520for (Integer offset : zonesByOffset.keySet()) {521int off = roi.get(index);522Set<String> perRO = zonesByOffset.get(offset);523if (offset == off) {524// Merge aliases into zonesByOffset525perRO.addAll(roit.get(index));526}527index++;528529for (String timezoneKey : perRO) {530out1.write("<TR>\n<TD><FONT SIZE=\"-1\">(" +531Time.toGMTFormat(offset.toString()) +532")</FONT></TD>\n<TD>");533534if (a.containsKey(timezoneKey)) {535Object realName = a.get(timezoneKey);536while (a.containsKey(realName)) {537realName = a.get(realName);538}539out1.write(timezoneKey +540" (alias for " + "<A HREF=\"" +541timezoneList.get(realName) +542"\" TARGET=\"rightFrame\">" + realName +543"</A>)");544} else {545out1.write("<A HREF=\"" + timezoneList.get(timezoneKey) +546"\" TARGET=\"rightFrame\">" + timezoneKey +547"</A>");548}549out1.write("</TD>\n</TR>\n");550}551}552out1.write("</FONT></TD>\n</TR>\n</TABLE>\n" + body2 + footer);553554out1.close();555fw1.close();556557558/* Creates allTimeZone-frame2.html (Sorted by zone names) */559fw1 = new FileWriter(outputDir + "allTimeZone-frame2.html", false);560out1 = new BufferedWriter(fw1);561562out1.write(header1 + new Date() + header2 + Main.getVersionName() +563header4 + body1 +564"<FONT size=\"+1\"><B>Sorted by zone names</B></FONT>\n" +565"<BR>\n\n" + "<TABLE BORDER=\"0\" WIDTH=\"100%\">\n" +566"<TR>\n<TD NOWRAP>\n");567o = timezoneList.keySet().toArray();568len = timezoneList.size();569for (int i = 0; i < len; i++) {570Object timezoneKey = o[i];571if (a.containsKey(timezoneKey)) {572Object realName = a.get(timezoneKey);573while (a.containsKey(realName)) {574realName = a.get(realName);575}576out1.write(timezoneKey +577" (alias for " +578"<A HREF=\"" + timezoneList.get(realName) +579"\" TARGET=\"rightFrame\">" + realName +580"</A>)");581} else {582out1.write("<A HREF=\"" + timezoneList.get(timezoneKey) +583"\" TARGET=\"rightFrame\">" + timezoneKey +584"</A>");585}586out1.write("<BR> \n");587}588out1.write("</FONT></TD>\n</TR>\n</TABLE>\n" + body2 + footer);589590out1.close();591fw1.close();592593/* Creates allTimeZone-frame3.html (Sorted by city names) */594fw1 = new FileWriter(outputDir + "allTimeZone-frame3.html", false);595out1 = new BufferedWriter(fw1);596597out1.write(header1 + new Date() + header2 + Main.getVersionName() +598header4 + body1 +599"<FONT size=\"+1\"><B>Sorted by city names</B></FONT>\n" +600"<BR>\n\n" + "<TABLE BORDER=\"0\" WIDTH=\"100%\">\n" +601"<TR>\n<TD NOWRAP>\n");602603Set<String> aliasSet = a.keySet();604len = aliasSet.size();605String aliasNames[] = aliasSet.toArray(new String[0]);606for (int i = 0; i < len; i++) {607displayNameList.put(transform(aliasNames[i]),608aliasNames[i]);609}610611o = displayNameList.keySet().toArray();612len = displayNameList.size();613for (int i = 0; i < len; i++) {614Object displayName = o[i];615Object timezoneKey = displayNameList.get(o[i]);616if (a.containsKey(timezoneKey)) {617Object realName = a.get(timezoneKey);618while (a.containsKey(realName)) {619realName = a.get(realName);620}621out1.write(displayName +622" (alias for " +623"<A HREF=\"" + timezoneList.get(realName) +624"\" TARGET=\"rightFrame\">" + realName +625"</A>)");626} else {627out1.write("<A HREF=\"" + timezoneList.get(timezoneKey) +628"\" TARGET=\"rightFrame\">" + displayName +629"</A>");630}631out1.write("<BR> \n");632}633634out1.write("</FONT></TD>\n</TR>\n</TABLE>\n" + body2 + footer);635636out1.close();637fw1.close();638639/* Creates overview-summary.html */640fw1 = new FileWriter(outputDir + "overview-summary.html", false);641out1 = new BufferedWriter(fw1);642643out1.write(header1 + new Date() + header2 + Main.getVersionName() +644header4 + body1 +645"<p>This is the list of time zones generated from <B>" +646Main.getVersionName() + "</B> for Java Platform, " +647"Standard Edition. The source code can be obtained " +648"from ftp site <a href=\"ftp://elsie.nci.nih.gov/pub/\">" +649"ftp://elsie.nci.nih.gov/pub/</a>. A total of <B>" +650len +651"</B> time zones and aliases are supported " +652"in this edition. For the " +653"format of rules and zones, refer to the zic " +654"(zoneinfo compiler) man page on " +655"Solaris or Linux.</p>\n" +656"<p>Note that the time zone data is not " +657"a public interface of the Java Platform. No " +658"applications should rely on the time zone data of " +659"this document. Time zone names and data " +660"may change without any prior notice.</p>\n" +661body2 + footer);662663out1.close();664fw1.close();665} catch(IOException e) {666Main.panic("IO error: "+e.getMessage());667return 1;668}669670return 0;671}672673String transform(String s) {674int index = s.lastIndexOf("/");675676/* If the string doesn't include any delimiter, return */677if (index == -1) {678return s;679}680681int lastIndex = index;682String str = s.substring(index+1);683do {684index = s.substring(0, lastIndex).lastIndexOf('/');685str += ", " + s.substring(index+1, lastIndex);686lastIndex = index;687} while (index > -1);688689return str;690}691692static class LatitudeAndLongitude {693694private int latDeg, latMin, latSec, longDeg, longMin, longSec;695696LatitudeAndLongitude(String s) {697try {698// First of all, check the string has the correct format:699// either +-DDMM+-DDDMM or +-DDMMSS+-DDDMMSS700701if (!s.startsWith("+") && !s.startsWith("-")) {702Main.warning("Wrong latitude&longitude data: " + s);703return;704}705int index;706if (((index = s.lastIndexOf("+")) <= 0) &&707((index = s.lastIndexOf("-")) <= 0)) {708Main.warning("Wrong latitude&longitude data: " + s);709return;710}711712if (index == 5) {713latDeg = Integer.parseInt(s.substring(1, 3));714latMin = Integer.parseInt(s.substring(3, 5));715latSec = 0;716} else if (index == 7) {717latDeg = Integer.parseInt(s.substring(1, 3));718latMin = Integer.parseInt(s.substring(3, 5));719latSec = Integer.parseInt(s.substring(5, 7));720} else {721Main.warning("Wrong latitude&longitude data: " + s);722return;723}724if (s.startsWith("-")){725latDeg = -latDeg;726latMin = -latMin;727latSec = -latSec;728}729730int len = s.length();731if (index == 5 && len == 11) {732longDeg = Integer.parseInt(s.substring(index+1, index+4));733longMin = Integer.parseInt(s.substring(index+4, index+6));734longSec = 0;735} else if (index == 7 && len == 15) {736longDeg = Integer.parseInt(s.substring(index+1, index+4));737longMin = Integer.parseInt(s.substring(index+4, index+6));738longSec = Integer.parseInt(s.substring(index+6, index+8));739} else {740Main.warning("Wrong latitude&longitude data: " + s);741return;742}743if (s.charAt(index) == '-'){744longDeg = -longDeg;745longMin = -longMin;746longSec = -longSec;747}748} catch(Exception e) {749Main.warning("LatitudeAndLongitude() Parse error: " + s);750}751}752753int getLatDeg() {754return latDeg;755}756757int getLatMin() {758return latMin;759}760761int getLatSec() {762return latSec;763}764765int getLongDeg() {766return longDeg;767}768769int getLongMin() {770return longMin;771}772773int getLongSec() {774return longSec;775}776}777}778779780