package org.androad.sys.ors.rs.google; import java.util.ArrayList; import java.util.StringTokenizer; import org.osmdroid.util.BoundingBoxE6; import org.osmdroid.util.GeoPoint; import org.androad.sys.ors.adt.Error; import org.androad.sys.ors.adt.rs.Route; import org.androad.sys.ors.adt.rs.RouteInstruction; import org.androad.sys.ors.exceptions.ORSException; import org.androad.util.constants.Constants; import org.androad.util.constants.TimeConstants; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import android.util.Log; public class GoogleRSParser extends DefaultHandler implements TimeConstants, Constants { // ==================================== // Constants // ==================================== // ==================================== // Fields // ==================================== private final ArrayList<Error> mErrors = new ArrayList<Error>(); private int mErrorNumber = 0; private Route mRoute; private ArrayList<GeoPoint> mPolyline; private double maxLat = 0; private double maxLon = 0; private double minLat = 0; private double minLon = 0; private boolean Document = false; private boolean Placemark = false; private boolean name = false; private boolean description = false; private boolean Point = false; private boolean LineString = false; private boolean coordinates = false; private RouteInstruction mTmpRouteInstruction; // =========================================================== // Constructors // =========================================================== public GoogleRSParser() { } // =========================================================== // Getter & Setter // =========================================================== public ArrayList<Error> getErrors(){ return this.mErrors; } public Route getRoute() throws ORSException{ if(this.mErrors != null && this.mErrors.size() > 0) { throw new ORSException(this.mErrors); } return this.mRoute; } // ==================================== // Methods from Superclasses // ==================================== @Override public void startDocument() throws SAXException { this.mRoute = new Route(); this.mRoute.setRouteInstructions(new ArrayList<RouteInstruction>()); this.mPolyline = new ArrayList<GeoPoint>(); this.mRoute.setPolyLine(this.mPolyline); super.startDocument(); } @Override public void startElement(final String uri, final String localName, final String name, final Attributes attributes) throws SAXException { this.sb.setLength(0); if(localName.equals("Document")){ this.Document = true; } else if(localName.equals("Placemark")){ this.Placemark = true; this.mTmpRouteInstruction = new RouteInstruction(); } else if(localName.equals("name")){ this.name = true; } else if(localName.equals("description")){ this.description = true; } else if(localName.equals("Point")){ this.Point = true; } else if(localName.equals("LineString")){ this.LineString = true; } else if(localName.equals("coordinates")){ this.coordinates = true; } else { Log.w(DEBUGTAG, "Unexpected tag: '" + name + "'"); } super.startElement(uri, localName, name, attributes); } protected StringBuilder sb = new StringBuilder(); @Override public void characters(final char[] chars, final int start, final int length) throws SAXException { this.sb.append(chars, start, length); super.characters(chars, start, length); } @Override public void endElement(final String uri, final String localName, final String name) throws SAXException { if(localName.equals("Document")){ this.Document = false; } else if(localName.equals("Placemark")){ this.Placemark = false; } else if(localName.equals("name")){ this.name = false; if (this.Placemark) { if(this.mTmpRouteInstruction.getDescriptionHtml() == null) { this.mTmpRouteInstruction.setDescriptionHtml(this.sb.toString()); } else { this.mTmpRouteInstruction.setDescriptionHtml(this.mTmpRouteInstruction.getDescriptionHtml() + this.sb.toString()); } } } else if(localName.equals("description")){ this.description = false; } else if(localName.equals("Point")){ this.Point = false; } else if(localName.equals("LineString")){ this.LineString = false; } else if(localName.equals("coordinates")){ this.coordinates = false; final String coords = this.sb.toString(); if (Point) { this.mRoute.getRouteInstructions().add(this.mTmpRouteInstruction); final StringTokenizer st = new StringTokenizer(coords, ","); final double b = Double.parseDouble(st.nextToken()); final double a = Double.parseDouble(st.nextToken()); if (maxLat == 0 || a > maxLat) { maxLat = a; } if (maxLon == 0 || b > maxLon) { maxLon = b; } if (minLat == 0 || a < minLat) { minLat = a; } if (minLon == 0 || b < minLon) { minLon = b; } final GeoPoint gp = new GeoPoint((int) (a * 1E6), (int) (b * 1E6)); this.mTmpRouteInstruction.getPartialPolyLine().add(gp); } if (LineString) { final StringTokenizer st1 = new StringTokenizer(coords, " "); GeoPoint lastgp = null; while(st1.hasMoreTokens()){ final StringTokenizer st2 = new StringTokenizer(st1.nextToken(), ","); if (!st2.hasMoreTokens()) continue; final double b = Double.parseDouble(st2.nextToken()); final double a = Double.parseDouble(st2.nextToken()); if (maxLat == 0 || a > maxLat) { maxLat = a; } if (maxLon == 0 || b > maxLon) { maxLon = b; } if (minLat == 0 || a < minLat) { minLat = a; } if (minLon == 0 || b < minLon) { minLon = b; } final GeoPoint gp = new GeoPoint((int) (a * 1E6), (int) (b * 1E6)); if (lastgp == null || !lastgp.equals(gp)) { this.mPolyline.add(gp); } lastgp = gp; } } } else { Log.w(DEBUGTAG, "Unexpected end-tag: '" + name + "'"); } // Reset the stringbuffer this.sb.setLength(0); super.endElement(uri, localName, name); } @Override public void endDocument() throws SAXException { if(this.mErrors == null || this.mErrors.size() == 0){ int gpindex = 0; for (int i = 0; i < this.mRoute.getRouteInstructions().size(); i++) { final RouteInstruction ri = this.mRoute.getRouteInstructions().get(i); if (ri.getPartialPolyLine().size() == 0) { continue; } RouteInstruction nextri = null; if (i + 1 < this.mRoute.getRouteInstructions().size()) { nextri = this.mRoute.getRouteInstructions().get(i + 1); } final GeoPoint rigp = ri.getPartialPolyLine().get(0); GeoPoint nextrigp = null; if (nextri != null && nextri.getPartialPolyLine().size() > 0) { nextrigp = nextri.getPartialPolyLine().get(0); } ri.setFirstMotherPolylineIndex(gpindex); for (; gpindex < this.mPolyline.size(); gpindex++) { final GeoPoint gp = this.mPolyline.get(gpindex); if (nextrigp != null && nextrigp.equals(gp)) { break; } ri.getPartialPolyLine().add(gp); } ri.setLengthMeters(ri.getPartialPolyLine().get(0).distanceTo( ri.getPartialPolyLine().get(ri.getPartialPolyLine().size() - 1))); } this.mRoute.setBoundingBoxE6(new BoundingBoxE6(maxLat, maxLon, minLat, minLon)); if (this.mPolyline.size() > 0) { this.mRoute.setStart(this.mPolyline.get(0)); this.mRoute.setDestination(this.mPolyline.get(this.mPolyline.size() - 1)); this.mRoute.setDistanceMeters(this.mRoute.getDestination().distanceTo(this.mRoute.getStart())); this.mRoute.setStartInstruction(this.mRoute.getRouteInstructions().remove(0)); // Modify the arrival-instruction that is just shows final RouteInstruction last = this.mRoute.getRouteInstructions().get(this.mRoute.getRouteInstructions().size() - 1); last.setFirstMotherPolylineIndex(this.mPolyline.size() - 1); } } super.endDocument(); } }