/*
* Copyright (c) 2013, Will Szumski
* Copyright (c) 2013, Doug Szumski
*
* This file is part of Cyclismo.
*
* Cyclismo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Cyclismo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Cyclismo. If not, see <http://www.gnu.org/licenses/>.
*/
package org.fluxoid.utils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class DrivingDirectionsUtils {
public static String getResponse(CharSequence charSequence) throws RemoteException {
HttpURLConnection urlConnection = null;
URL url = null;
StringBuilder buffer = new StringBuilder();
try {
url = new URL(charSequence.toString());
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
urlConnection.connect();
InputStream dataStream = urlConnection.getInputStream();
InputStreamReader isr = new InputStreamReader(dataStream, "UTF8");
Reader in = new BufferedReader(isr);
int ch;
while ((ch = in.read()) > -1) {
buffer.append((char) ch);
}
return buffer.toString();
} catch (IOException e) {
throw new RemoteException("Query failed ", e);
} finally {
if (urlConnection != null) urlConnection.disconnect();
}
}
public static class DirectionsQueryBuilder {
private static void validateString(String name, String arg, String[] acceptedArgs)
throws IllegalArgumentException {
List<String> acceptedFormats = Arrays.asList(acceptedArgs);
if (!acceptedFormats.contains(arg)) {
StringBuilder formats = new StringBuilder();
for (String fmt : acceptedFormats) {
formats.append("\"" + fmt + "\"" + ", ");
}
formats.setLength(formats.length() - 2);
throw new IllegalArgumentException(name + " must one of: " + formats);
}
}
private String format;
private boolean sensor = false;
private String originString;
private String destinationString;
private String mode;
private List<String> waypoints = new ArrayList<String>();
private boolean optimiseWaypoints = false;
private boolean avoidTolls = false;
private boolean avoidHighways = false;
private String units;
private String regionBias;
private String language;
/**
* @param format either "json" or "xml"
*/
DirectionsQueryBuilder(String format) {
String[] acceptedFormats = new String[]{"json", "xml"};
validateString("format", format, acceptedFormats);
this.format = format;
}
public String latLongToString(LatLong l) {
StringBuilder result = new StringBuilder()
.append(l.getLatitude())
.append(",")
.append(l.getLongitude());
return result.toString();
}
public DirectionsQueryBuilder to(String destinationString) {
this.destinationString = destinationString;
return this;
}
public DirectionsQueryBuilder from(String originString) {
this.originString = originString;
return this;
}
public DirectionsQueryBuilder to(LatLong latlong) {
this.destinationString = latLongToString(latlong);
return this;
}
public DirectionsQueryBuilder from(LatLong latlong) {
this.originString = latLongToString(latlong);
;
return this;
}
/**
* mode = "driving"
*/
public DirectionsQueryBuilder byCar() {
mode = "driving";
return this;
}
/**
* mode = "bicycle"
*/
public DirectionsQueryBuilder byBicycle() {
mode = "bicycle";
return this;
}
/**
* mode = "walking"
*/
public DirectionsQueryBuilder byFoot() {
mode = "walking";
return this;
}
public DirectionsQueryBuilder withLocationSensor() {
sensor = true;
return this;
}
public DirectionsQueryBuilder avoidingTolls() {
avoidTolls = true;
return this;
}
public DirectionsQueryBuilder avoidingHighways() {
avoidHighways = true;
return this;
}
/**
* mode = "transit"
*/
public DirectionsQueryBuilder byPublicTransport() {
mode = "transit";
return this;
}
public DirectionsQueryBuilder stoppingAt(String waypoint) {
if (waypoints.size() > 0) {
waypoint = "|" + waypoint;
}
waypoints.add(waypoint);
return this;
}
public DirectionsQueryBuilder stoppingAt(LatLong waypoint) {
return stoppingAt(latLongToString(waypoint));
}
public DirectionsQueryBuilder via(LatLong waypoint) {
return via(latLongToString(waypoint));
}
public DirectionsQueryBuilder via(String waypoint) {
return stoppingAt("via:" + waypoint);
}
/**
* reorders ways travelling salesman
*/
public DirectionsQueryBuilder withWaypointOptimisation() {
optimiseWaypoints = true;
return this;
}
/**
* affects text directions
*/
public DirectionsQueryBuilder usingMetricUnits() {
units = "metric";
return this;
}
/**
* affects text directions
*/
public DirectionsQueryBuilder usingImperialUnits() {
units = "imperial";
return this;
}
/**
* language of directions @see https://developers.google.com/maps/faq#languagesupport
*
* @param language language code
*/
public DirectionsQueryBuilder inLanguage(String language) {
this.language = language;
return this;
}
/**
* @param regionBias ccTLD (country code top-level domain) eg. "es" for spain
* @return the builder
*/
public DirectionsQueryBuilder withRegionBias(String regionBias) {
this.regionBias = regionBias;
return this;
}
private void notNullAppend(String argName, CharSequence arg, StringBuilder query) {
if (arg == null) return;
query.append("&").append(argName + "=").append(arg);
}
private String concatList(List<String> list) {
StringBuilder result = new StringBuilder();
for (String item : list) {
result.append(item);
}
if (result.length() == 0) return null;
return result.toString();
}
private String prepareWaypoints() {
String points = concatList(waypoints);
String result = null;
if (optimiseWaypoints) {
result = "optimize:true|" + points;
}
if (result == null) return points;
return result;
}
private String prepareAvoid() {
if (avoidTolls && avoidHighways) {
return "tolls|highways";
} else if (avoidTolls) {
return "tolls";
} else if (avoidHighways) {
return "highways";
}
return null;
}
public CharSequence build() {
StringBuilder query = new StringBuilder("http://maps.googleapis.com/maps/api/directions/");
query.append(format);
if (destinationString == null || originString == null) {
throw new IllegalArgumentException("The origin and destination are not optional");
}
query.append("?").append("origin=").append(originString);
notNullAppend("waypoints", prepareWaypoints(), query);
query.append("&").append("destination=").append(destinationString);
query.append("&").append("sensor=").append(sensor);
notNullAppend("mode", mode, query);
notNullAppend("avoid", prepareAvoid(), query);
notNullAppend("units", units, query);
notNullAppend("region", regionBias, query);
notNullAppend("language", language, query);
return query;
}
}
public static void main(String[] args) throws RemoteException {
DirectionsQueryBuilder b = new DirectionsQueryBuilder("json").from("London").via("Manchester").stoppingAt("Chester").to("Luton").avoidingTolls().withWaypointOptimisation();
System.out.println(b.build());
System.out.println(getResponse(b.build()));
}
}