package tim.prune.load.xml;
import java.util.ArrayList;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import tim.prune.data.Field;
import tim.prune.load.TrackNameList;
/**
* Class for handling specifics of parsing Gpx files
*/
public class GpxHandler extends XmlHandler
{
private boolean _insidePoint = false;
private boolean _insideWaypoint = false;
private boolean _startSegment = true;
private boolean _isTrackPoint = false;
private int _trackNum = -1;
private GpxTag _name = new GpxTag(), _trackName = new GpxTag();
private String _latitude = null, _longitude = null;
private GpxTag _elevation = new GpxTag(), _time = new GpxTag();
private GpxTag _type = new GpxTag(), _description = new GpxTag();
private GpxTag _link = new GpxTag();
private GpxTag _currentTag = null;
private ArrayList<String[]> _pointList = new ArrayList<String[]>();
private ArrayList<String> _linkList = new ArrayList<String>();
private TrackNameList _trackNameList = new TrackNameList();
/**
* Receive the start of a tag
* @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
*/
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException
{
// Read the parameters for waypoints and track points
String tag = qName.toLowerCase();
if (tag.equals("wpt") || tag.equals("trkpt") || tag.equals("rtept"))
{
_insidePoint = true;
_insideWaypoint = tag.equals("wpt");
_isTrackPoint = tag.equals("trkpt");
final int numAttributes = attributes.getLength();
for (int i=0; i<numAttributes; i++)
{
String att = attributes.getQName(i).toLowerCase();
if (att.equals("lat")) {_latitude = attributes.getValue(i);}
else if (att.equals("lon")) {_longitude = attributes.getValue(i);}
}
_elevation.setValue(null);
_name.setValue(null);
_time.setValue(null);
_type.setValue(null);
_link.setValue(null);
_description.setValue(null);
}
else if (tag.equals("ele")) {
_currentTag = _elevation;
}
else if (tag.equals("name")) {
_currentTag = (_insidePoint?_name:_trackName);
}
else if (tag.equals("time")) {
_currentTag = _time;
}
else if (tag.equals("type")) {
_currentTag = _type;
}
else if (tag.equals("description") || tag.equals("desc")) {
_currentTag = _description;
}
else if (tag.equals("link")) {
_link.setValue(attributes.getValue("href"));
}
else if (tag.equals("trkseg")) {
_startSegment = true;
}
else if (tag.equals("trk"))
{
_trackNum++;
_trackName.setValue(null);
}
super.startElement(uri, localName, qName, attributes);
}
/**
* Process end tag
* @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
*/
public void endElement(String uri, String localName, String qName)
throws SAXException
{
String tag = qName.toLowerCase();
if (tag.equals("wpt") || tag.equals("trkpt") || tag.equals("rtept"))
{
processPoint();
_insidePoint = false;
}
else {
_currentTag = null;
}
super.endElement(uri, localName, qName);
}
/**
* Process character text (inside tags or between them)
* @see org.xml.sax.ContentHandler#characters(char[], int, int)
*/
public void characters(char[] ch, int start, int length)
throws SAXException
{
String value = new String(ch, start, length);
if (_currentTag != null) {
_currentTag.setValue(checkCharacters(_currentTag.getValue(), value));
}
super.characters(ch, start, length);
}
/**
* Check to concatenate partially-received values, if necessary
* @param inVariable variable containing characters received until now
* @param inValue new value received
* @return concatenation
*/
private static String checkCharacters(String inVariable, String inValue)
{
if (inVariable == null) {return inValue;}
return inVariable + inValue;
}
/**
* Process a point, either a waypoint or track point
*/
private void processPoint()
{
// Put the values into a String array matching the order in getFieldArray()
String[] values = new String[8];
values[0] = _latitude;
values[1] = _longitude;
values[2] = _elevation.getValue();
if (_insideWaypoint) {values[3] = _name.getValue();}
values[4] = _time.getValue();
if (_startSegment && !_insideWaypoint)
{
values[5] = "1";
_startSegment = false;
}
values[6] = _type.getValue();
values[7] = _description.getValue();
_pointList.add(values);
_trackNameList.addPoint(_trackNum, _trackName.getValue(), _isTrackPoint);
_linkList.add(_link.getValue());
}
/**
* @see tim.prune.load.xml.XmlHandler#getFieldArray()
*/
public Field[] getFieldArray()
{
final Field[] fields = {Field.LATITUDE, Field.LONGITUDE, Field.ALTITUDE,
Field.WAYPT_NAME, Field.TIMESTAMP, Field.NEW_SEGMENT,
Field.WAYPT_TYPE, Field.DESCRIPTION};
return fields;
}
/**
* Return the parsed information as a 2d array
* @see tim.prune.load.xml.XmlHandler#getDataArray()
*/
public String[][] getDataArray()
{
int numPoints = _pointList.size();
// construct data array
String[][] result = new String[numPoints][];
for (int i=0; i<numPoints; i++)
{
result[i] = _pointList.get(i);
}
return result;
}
/**
* @return array of links, or null if none
*/
public String[] getLinkArray()
{
int numPoints = _linkList.size();
boolean hasLink = false;
String[] result = new String[numPoints];
for (int i=0; i<numPoints; i++)
{
result[i] = _linkList.get(i);
if (result[i] != null) {hasLink = true;}
}
if (!hasLink) {result = null;}
return result;
}
/**
* @return track name list
*/
public TrackNameList getTrackNameList() {
return _trackNameList;
}
}