package org.androad.sys.ors.lus.yournavigation; import java.util.ArrayList; import java.util.StringTokenizer; import org.osmdroid.util.GeoPoint; import org.androad.sys.ors.adt.Error; import org.androad.sys.ors.adt.GeocodedAddress; import org.androad.sys.ors.adt.lus.Country; 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 YourNavigationLUSParser extends DefaultHandler implements TimeConstants, Constants { // ==================================== // Constants // ==================================== protected static final int LATITUDE_OVERMAX = (int)(81 * 1E6); protected static final int LONGITUDE_OVERMAX = (int)(181 * 1E6); // ==================================== // Fields // ==================================== private final ArrayList<Error> mErrors = new ArrayList<Error>(); private ArrayList<GeocodedAddress> mAddresses; private boolean inSearchresults = false; private boolean inPlace = false; private boolean inReversegeocode = false; private boolean inResult = false; private boolean inAddressparts = false; private boolean inRoad = false; private boolean inTown = false; private boolean inState = false; private boolean inCountry = false; private boolean inCountrycode = false; private GeocodedAddress mTmpGeocodedAddress; // =========================================================== // Constructors // =========================================================== // =========================================================== // Getter & Setter // =========================================================== public ArrayList<Error> getErrors(){ return this.mErrors; } public ArrayList<GeocodedAddress> getAddresses() throws ORSException{ if(this.mErrors != null && this.mErrors.size() > 0) { throw new ORSException(this.mErrors); } return this.mAddresses; } // ==================================== // Methods from Superclasses // ==================================== @Override public void startDocument() throws SAXException { this.mAddresses = new ArrayList<GeocodedAddress>(); 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("searchresults")){ this.inSearchresults = true; } else if(localName.equals("place")){ this.inPlace = true; final String lat = attributes.getValue("", "lat"); final String lon = attributes.getValue("", "lon"); final double a = Double.parseDouble(lat); final double b = Double.parseDouble(lon); final GeoPoint gp = new GeoPoint((int) (a * 1E6), (int) (b * 1E6)); this.mTmpGeocodedAddress = new GeocodedAddress(gp); this.mAddresses.add(this.mTmpGeocodedAddress); this.mTmpGeocodedAddress.setAccuracy(1); final String displayname = attributes.getValue("", "display_name"); final String type = attributes.getValue("", "type"); if(displayname != null) { final StringTokenizer st = new StringTokenizer(displayname, ","); final ArrayList<String> names = new ArrayList<String>(); while(st.hasMoreTokens()) { names.add(st.nextToken().trim()); } final String country = ", " + names.get(names.size() - 1); if (type.compareTo("town") == 0) { this.mTmpGeocodedAddress.setMunicipality(names.get(0)); this.mTmpGeocodedAddress.setCountrySubdivision(names.get(1) + country); } else if (type.compareTo("residential") == 0) { if (names.size() == 4) { this.mTmpGeocodedAddress.setStreetNameOfficial(names.get(0)); this.mTmpGeocodedAddress.setMunicipality(names.get(1)); this.mTmpGeocodedAddress.setCountrySubdivision(names.get(2) + country); } else if (names.size() == 5) { this.mTmpGeocodedAddress.setStreetNameOfficial(names.get(0)); this.mTmpGeocodedAddress.setMunicipality(names.get(1)); this.mTmpGeocodedAddress.setPostalCode(names.get(2)); this.mTmpGeocodedAddress.setCountrySubdivision(names.get(3) + country); } else { this.mTmpGeocodedAddress.setMunicipality(names.get(0)); this.mTmpGeocodedAddress.setCountrySubdivision(names.get(1) + country); } } else { this.mTmpGeocodedAddress.setCountrySubdivision(names.get(0) + country); } this.mTmpGeocodedAddress.setNationality(Country.UNKNOWN); } } else if(localName.equals("reversegeocode")){ this.inReversegeocode = true; final String query = attributes.getValue("", "querystring"); final StringTokenizer st = new StringTokenizer(query, "&"); if (!st.hasMoreTokens()) return; final double b; final double a; try { b = Double.parseDouble(st.nextToken().substring(4)); a = Double.parseDouble(st.nextToken().substring(4)); } catch (Exception e) { return; } final GeoPoint gp = new GeoPoint((int) (a * 1E6), (int) (b * 1E6)); this.mTmpGeocodedAddress = new GeocodedAddress(gp); this.mTmpGeocodedAddress.setAccuracy(1); this.mAddresses.add(this.mTmpGeocodedAddress); } else if(localName.equals("result")){ this.inResult = true; } else if(localName.equals("addressparts")){ this.inAddressparts = true; } else if(localName.equals("road")){ this.inRoad = true; } else if(localName.equals("town")){ this.inTown = true; } else if(localName.equals("state")){ this.inState = true; } else if(localName.equals("country")){ this.inCountry = true; } else if(localName.equals("country_code")){ this.inCountrycode = 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("searchresults")){ this.inSearchresults = false; } else if(localName.equals("place")){ this.inPlace = false; } else if(localName.equals("reversegeocode")){ this.inReversegeocode = false; } else if(localName.equals("result")){ this.inResult = false; } else if(localName.equals("addressparts")){ this.inAddressparts = false; } else if(localName.equals("road")){ this.inRoad = false; this.mTmpGeocodedAddress.setStreetNameOfficial(this.sb.toString()); } else if(localName.equals("town")){ this.inTown = false; } else if(localName.equals("state")){ this.inState = false; this.mTmpGeocodedAddress.setCountrySubdivision(this.sb.toString()); } else if(localName.equals("country")){ this.inCountry = false; } else if(localName.equals("country_code")){ this.inCountrycode = false; this.mTmpGeocodedAddress.setNationality(Country.fromAbbreviation(this.sb.toString())); } 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 { super.endDocument(); } }