package org.androad.sys.ors.rs.yahoo; import java.util.ArrayList; 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 YahooRSParser 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 GeoPoint tmp; private double a = -1; private double b = -1; private boolean inResultSet = false; private boolean inError = false; private boolean inErrorMessage = false; private boolean inLocale = false; private boolean inResult = false; private boolean inYahooDrivingDirections = false; private boolean inRouteHandle = false; private boolean inAddress = false; private boolean inType = false; private boolean inTotalDistance = false; private boolean inTotalTime = false; private boolean inTotalTimeWithTraffic = false; private boolean inBoundingBox = false; private boolean inNorth = false; private boolean inEast = false; private boolean inSouth = false; private boolean inWest = false; private boolean inDirections = false; private boolean inRouteLeg = false; private boolean inNumber = false; private boolean inLat = false; private boolean inLon = false; private boolean inDistance = false; private boolean inManType = false; private boolean inStreet = false; private boolean inSign = false; private boolean inDescription = false; private boolean inTime = false; private boolean inTimeWithTraffic = false; private boolean inCopyRight = false; private RouteInstruction mTmpRouteInstruction; // =========================================================== // Constructors // =========================================================== public YahooRSParser() { } // =========================================================== // 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("ResultSet")){ this.inResultSet = true; } else if(localName.equals("Error")){ this.inError = true; } else if(localName.equals("ErrorMessage")){ this.inErrorMessage = true; } else if(localName.equals("Locale")){ this.inLocale = true; } else if(localName.equals("Result")){ this.inResult = true; } else if(localName.equals("yahoo_driving_directions")){ this.inYahooDrivingDirections = true; } else if(localName.equals("routeHandle")){ this.inRouteHandle = true; } else if(localName.equals("address")){ this.inAddress = true; } else if(localName.equals("type")){ this.inType = true; } else if(localName.equals("total_distance")){ this.inTotalDistance = true; } else if(localName.equals("total_time")){ this.inTotalTime = true; } else if(localName.equals("total_time_with_traffic")){ this.inTotalTimeWithTraffic = true; } else if(localName.equals("boundingbox")){ this.inBoundingBox = true; } else if(localName.equals("North")){ this.inNorth = true; } else if(localName.equals("East")){ this.inEast = true; } else if(localName.equals("South")){ this.inSouth = true; } else if(localName.equals("West")){ this.inWest = true; } else if(localName.equals("directions")){ this.inDirections = true; } else if(localName.equals("route_leg")){ this.inRouteLeg = true; this.mTmpRouteInstruction = new RouteInstruction(); this.mRoute.getRouteInstructions().add(this.mTmpRouteInstruction); } else if(localName.equals("number")){ this.inNumber = true; } else if(localName.equals("lat")){ this.inLat = true; } else if(localName.equals("lon")){ this.inLon = true; } else if(localName.equals("distance")){ this.inDistance = true; } else if(localName.equals("man_type")){ this.inManType = true; } else if(localName.equals("street")){ this.inStreet = true; } else if(localName.equals("sign")){ this.inSign = true; } else if(localName.equals("description")){ this.inDescription = true; } else if(localName.equals("time")){ this.inTime = true; } else if(localName.equals("time_with_traffic")){ this.inTimeWithTraffic = true; } else if(localName.equals("copy_right")){ this.inCopyRight = true; } else { Log.w(DEBUGTAG, "Unexpected tag: '" + name + "'"); } super.startElement(uri, localName, name, attributes); } protected StringBuilder sb = new StringBuilder(); private int mLastFirstMotherPolylineIndex = 0; @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("ResultSet")){ this.inResultSet = false; } else if(localName.equals("Error")){ this.inError = false; this.mErrorNumber = Integer.parseInt(this.sb.toString()); } else if(localName.equals("ErrorMessage")){ this.inErrorMessage = false; if (this.mErrorNumber > 0) { this.mErrors.add(new Error("Err", "Sev", "", this.sb.toString())); } } else if(localName.equals("Locale")){ this.inLocale = false; } else if(localName.equals("Result")){ this.inResult = false; } else if(localName.equals("yahoo_driving_directions")){ this.inYahooDrivingDirections = false; } else if(localName.equals("routeHandle")){ this.inRouteHandle = false; this.mRoute.setRouteHandleID(Long.parseLong(this.sb.toString())); } else if(localName.equals("address")){ this.inAddress = false; } else if(localName.equals("type")){ this.inType = false; } else if(localName.equals("total_distance")){ this.inTotalDistance = false; this.mRoute.setDistanceMeters((int)(1609.344 * Float.parseFloat(this.sb.toString()))); } else if(localName.equals("total_time")){ this.inTotalTime = false; this.mRoute.setDurationSeconds(Integer.parseInt(this.sb.toString()) * 60); } else if(localName.equals("total_time_with_traffic")){ this.inTotalTimeWithTraffic = false; } else if(localName.equals("boundingbox")){ this.inBoundingBox = false; } else if(localName.equals("North")){ this.a = Double.parseDouble(this.sb.toString()); this.inNorth = false; } else if(localName.equals("East")){ this.b = Double.parseDouble(this.sb.toString()); this.inEast = false; } else if(localName.equals("South")){ this.a = Double.parseDouble(this.sb.toString()); this.inSouth = false; } else if(localName.equals("West")){ this.b = Double.parseDouble(this.sb.toString()); this.inWest = false; } else if(localName.equals("directions")){ this.inDirections = false; } else if(localName.equals("route_leg")){ this.inRouteLeg = false; } else if(localName.equals("number")){ this.inNumber = false; } else if(localName.equals("lat")){ this.a = Double.parseDouble(this.sb.toString()); this.inLat = false; } else if(localName.equals("lon")){ this.b = Double.parseDouble(this.sb.toString()); this.inLon = false; } else if(localName.equals("distance")){ this.inDistance = false; this.mTmpRouteInstruction.setLengthMeters((int)(1609.344 * Float.parseFloat(this.sb.toString()))); } else if(localName.equals("man_type")){ this.inManType = false; } else if(localName.equals("street")){ this.inStreet = false; } else if(localName.equals("sign")){ this.inSign = false; } else if(localName.equals("description")){ this.inDescription = false; 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("time")){ this.inTime = false; this.mTmpRouteInstruction.setDurationSeconds(Integer.parseInt(this.sb.toString()) * 60); } else if(localName.equals("time_with_traffic")){ this.inTimeWithTraffic = false; } else if(localName.equals("copy_right")){ this.inCopyRight = false; } else { Log.w(DEBUGTAG, "Unexpected end-tag: '" + name + "'"); } if (this.a != -1 && this.b != -1) { final GeoPoint gp = new GeoPoint((int) (a * 1E6), (int) (b * 1E6)); if (this.inRouteLeg) { this.mPolyline.add(gp); this.mTmpRouteInstruction.getPartialPolyLine().add(gp); // If this was the first element, we will determine its position in the OverallPolyline if(this.mTmpRouteInstruction.getPartialPolyLine().size() == 1) { this.mLastFirstMotherPolylineIndex = this.mRoute.findInPolyLine(gp, this.mLastFirstMotherPolylineIndex); this.mTmpRouteInstruction.setFirstMotherPolylineIndex(this.mLastFirstMotherPolylineIndex); } } if (this.inBoundingBox) { if (this.tmp == null){ // First GeoPoint this.tmp = gp; }else{ // Second one final int mFirstLatE6 = this.tmp.getLatitudeE6(); final int mFirstLonE6 = this.tmp.getLongitudeE6(); this.tmp = gp; final int mSecondLatE6 = this.tmp.getLatitudeE6(); final int mSecondLonE6 = this.tmp.getLongitudeE6(); this.mRoute.setBoundingBoxE6(new BoundingBoxE6(Math.max(mFirstLatE6, mSecondLatE6), Math.max(mFirstLonE6, mSecondLonE6), Math.min(mFirstLatE6, mSecondLatE6), Math.min(mFirstLonE6, mSecondLonE6))); } } this.a = -1; this.b = -1; } // 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){ this.mRoute.setStart(this.mPolyline.get(0)); this.mRoute.setDestination(this.mPolyline.get(this.mPolyline.size() - 1)); 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(); } }