package com.nutiteq.services; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; import org.kxml2.io.KXmlParser; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import com.mgmaps.utils.Tools; import com.nutiteq.cache.Cache; import com.nutiteq.components.Distance; import com.nutiteq.components.DurationTime; import com.nutiteq.components.Line; import com.nutiteq.components.Route; import com.nutiteq.components.RouteInstruction; import com.nutiteq.components.RouteSummary; import com.nutiteq.components.WgsPoint; import com.nutiteq.core.MappingCore; import com.nutiteq.io.ResourceDataWaiter; import com.nutiteq.io.ResourceRequestor; import com.nutiteq.kml.KmlReader; import com.nutiteq.kml.KmlStylesCache; public class YourNavigationDirections extends KmlReader implements DirectionsService, ResourceRequestor, ResourceDataWaiter { private static final String DISTANCE_TAG = "distance"; public static final String MOVE_METHOD_CAR = "motorcar"; public static final String MOVE_METHOD_BICYCLE = "bicycle"; public static final String MOVE_METHOD_FOOT = "foot"; public static final int ROUTE_TYPE_FASTEST = 1; public static final int ROUTE_TYPE_SHORTEST = 0; private final DirectionsWaiter directionsWaiter; private static final String BASEURL = "http://www.yournavigation.org/api/1.0/gosmore.php?"; private final String routingUrl; private static final int ERROR_MESSAGE_LENGHT = 27; private static final String ERROR_MESSAGE = "Unable to calculate a route"; public YourNavigationDirections(final DirectionsWaiter directionsWaiter, final WgsPoint from, final WgsPoint to, final String moveType, final int routeType) { super(null, null, null, new KmlStylesCache(), null); //TODO jaanus : what input to check? this.directionsWaiter = directionsWaiter; final StringBuffer urlBuffer = new StringBuffer(BASEURL); urlBuffer.append("flat=").append(from.getLat()); urlBuffer.append("&flon=").append(from.getLon()); urlBuffer.append("&tlat=").append(to.getLat()); urlBuffer.append("&tlon=").append(to.getLon()); urlBuffer.append("&v=").append(moveType); urlBuffer.append("&fast=").append(routeType); urlBuffer.append("&layer=mapnik"); routingUrl = urlBuffer.toString(); } public void execute() { MappingCore.getInstance().getTasksRunner().enqueueDownload(this, Cache.CACHE_LEVEL_NONE); } public String resourcePath() { return routingUrl; } public void notifyError() { directionsWaiter.networkError(); } public void dataRetrieved(final byte[] data) { if (data.length == ERROR_MESSAGE_LENGHT && Tools.byteArrayToString(data).indexOf(ERROR_MESSAGE) >= 0) { directionsWaiter.routingErrors(ERROR_ROUTE_NOT_FOUND); } else { readRoute(data); } } private void readRoute(final byte[] data) { final ByteArrayInputStream is = new ByteArrayInputStream(data); InputStreamReader reader; try { reader = new InputStreamReader(is, "utf-8"); } catch (final Exception e) { reader = new InputStreamReader(is); } float distance = 0; Line line = null; boolean success = false; final KXmlParser parser = new KXmlParser(); try { parser.setInput(reader); int eventType = parser.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { if (eventType == XmlPullParser.START_TAG) { final String tagName = parser.getName(); if (DISTANCE_TAG.equals(tagName)) { distance = Float.parseFloat(parser.nextText()); } else if (LINE_STRING_TAG.equals(tagName)) { line = readLine(parser); } } eventType = parser.next(); } success = true; } catch (final XmlPullParserException e) { directionsWaiter.routingParsingError("XmlPullParserException: " + e.getMessage()); } catch (final IOException e) { directionsWaiter.routingParsingError("IOException: " + e.getMessage()); } if (!success) { return; } //TODO jaanus : is this ok? if (line == null) { directionsWaiter.routingErrors(ERROR_ROUTE_NOT_FOUND); return; } final Distance routeDistance = new Distance(distance, "km"); //TODO jaanus : try to create bounding box? final RouteSummary summary = new RouteSummary(new DurationTime(), routeDistance, null); final Route route = new Route(summary, line, new RouteInstruction[0]); directionsWaiter.routeFound(route); } public void cancel() { //TODO jaanus } }