]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/save/GpxCacher.java
Version 10, May 2010
[GpsPrune.git] / tim / prune / save / GpxCacher.java
1 package tim.prune.save;
2
3 import java.io.File;
4 import java.io.FileInputStream;
5 import java.io.InputStream;
6 import java.util.zip.GZIPInputStream;
7 import java.util.zip.ZipEntry;
8 import java.util.zip.ZipInputStream;
9
10 import javax.xml.parsers.SAXParser;
11 import javax.xml.parsers.SAXParserFactory;
12
13 import org.xml.sax.Attributes;
14 import org.xml.sax.SAXException;
15 import org.xml.sax.helpers.DefaultHandler;
16
17 import tim.prune.data.DataPoint;
18 import tim.prune.data.SourceInfo;
19
20 /**
21  * Class to read in a GPX file and cache all the point strings
22  */
23 public class GpxCacher extends DefaultHandler
24 {
25         private SourceInfo _sourceInfo = null;
26         private String _headerString = null;
27         private String[] _strings = null;
28         private int _pointNum = 0;
29         private boolean _insidePoint = false;
30         private StringBuilder _builder = null;
31
32
33         /**
34          * Constructor
35          * @param inSourceInfo source information
36          */
37         public GpxCacher(SourceInfo inInfo)
38         {
39                 _sourceInfo = inInfo;
40                 _strings = new String[inInfo.getNumPoints()];
41                 _pointNum = 0;
42                 // Should be a gpx file, but might be raw, zipped or gzipped
43                 File gpxFile = inInfo.getFile();
44                 String fileName = gpxFile.getName().toLowerCase();
45                 if (gpxFile.exists() && gpxFile.canRead())
46                 {
47                         try {
48                                 SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
49                                 if (fileName.endsWith(".gpx") || fileName.endsWith(".xml")) {
50                                         saxParser.parse(inInfo.getFile(), this);
51                                 }
52                                 else if (fileName.endsWith(".zip")) {
53                                         saxParser.parse(getZipInputStream(inInfo.getFile()), this);
54                                 }
55                                 else if (fileName.endsWith(".gz")) {
56                                         saxParser.parse(new GZIPInputStream(new FileInputStream(inInfo.getFile())), this);
57                                 }
58                                 else {
59                                         System.out.println("GpxCacher unrecognised file type: " + inInfo.getFile().getName());
60                                 }
61                         } catch (Exception e) {
62                                 // TODO: Handle errors here with a list of warnings?
63                                 e.printStackTrace();
64                         }
65                 }
66                 _builder = null;
67         }
68
69
70         /**
71          * Receive the start of a tag
72          */
73         public void startElement(String inUri, String inLocalName, String inTagName,
74                 Attributes inAttributes) throws SAXException
75         {
76                 if (inTagName.equalsIgnoreCase("gpx"))
77                 {
78                         // store initial gpx tag
79                         _builder = new StringBuilder(60);
80                         appendTag(_builder, inTagName, inAttributes);
81                         _headerString = _builder.toString();
82                 }
83                 else
84                 {
85                         if (inTagName.equalsIgnoreCase("wpt") || inTagName.equalsIgnoreCase("trkpt")
86                                 || inTagName.equalsIgnoreCase("rtept"))
87                         {
88                                 _insidePoint = true;
89                                 _builder = new StringBuilder(60);
90                         }
91                         if (_insidePoint) {
92                                 appendTag(_builder, inTagName, inAttributes);
93                         }
94                 }
95                 super.startElement(inUri, inLocalName, inTagName, inAttributes);
96         }
97
98         /**
99          * Receive characters between tags (inside or outside)
100          */
101         public void characters(char[] inChars, int inStart, int inLength)
102                 throws SAXException
103         {
104                 if (_insidePoint) {
105                         _builder.append(new String(inChars, inStart, inLength));
106                 }
107                 super.characters(inChars, inStart, inLength);
108         }
109
110         /**
111          * Receive end of xml tag
112          */
113         public void endElement(String inUri, String inLocalName, String inTagName)
114                 throws SAXException
115         {
116                 if (_insidePoint) {
117                         _builder.append("</").append(inTagName).append('>');
118                 }
119                 if (inTagName.equalsIgnoreCase("wpt") || inTagName.equalsIgnoreCase("trkpt")
120                         || inTagName.equalsIgnoreCase("rtept"))
121                 {
122                         _strings[_pointNum] = _builder.toString();
123                         _pointNum++;
124                         _insidePoint = false;
125                 }
126                 super.endElement(inUri, inLocalName, inTagName);
127         }
128
129
130         /**
131          * Append the current tag to the supplied StringBuilder
132          * @param inBuilder Stringbuilder object to append tag to
133          * @param inTagName name of tag
134          * @param inAttributes attributes of tag
135          */
136         private static void appendTag(StringBuilder inBuilder, String inTagName, Attributes inAttributes)
137         {
138                 inBuilder.append('<').append(inTagName);
139                 int numAtts = inAttributes.getLength();
140                 for (int i=0; i<numAtts; i++) {
141                         inBuilder.append(' ').append(inAttributes.getQName(i)).append("=\"")
142                                 .append(inAttributes.getValue(i)).append('"');
143                 }
144                 inBuilder.append('>');
145         }
146
147
148         /**
149          * @return the header string from the GPX tag
150          */
151         public String getHeaderString()
152         {
153                 return _headerString;
154         }
155
156         /**
157          * Get the source string for the given point
158          * @param inPoint point to retrieve
159          * @return string if found, otherwise null
160          */
161         public String getSourceString(DataPoint inPoint)
162         {
163                 int index = _sourceInfo.getIndex(inPoint);
164                 if (index >= 0) {
165                         return _strings[index];
166                 }
167                 return null;
168         }
169
170         /**
171          * Get an inputstream of a GPX file inside a zip
172          * @param inFile File object describing zip file
173          * @return input stream for Xml parser
174          */
175         private static InputStream getZipInputStream(File inFile)
176         {
177                 try
178                 {
179                         ZipInputStream zis = new ZipInputStream(new FileInputStream(inFile));
180                         while (zis.available() > 0)
181                         {
182                                 ZipEntry entry = zis.getNextEntry();
183                                 String entryName = entry.toString();
184                                 if (entryName != null && entryName.length() > 4)
185                                 {
186                                         String suffix = entryName.substring(entryName.length()-4).toLowerCase();
187                                         if (suffix.equals(".gpx") || suffix.equals(".xml")) {
188                                                 // First matching file so must be gpx
189                                                 return zis;
190                                         }
191                                 }
192                         }
193                 }
194                 catch (Exception e) {} // ignore errors
195                 // not found - error!
196                 return null;
197         }
198 }