Refactoring: inheritance instead of composition

This commit is contained in:
nazar-kutz 2021-02-22 17:04:38 +02:00
parent fab1df33a6
commit 1be6bc7eea
11 changed files with 400 additions and 492 deletions

View file

@ -9,8 +9,7 @@ import net.osmand.osm.io.NetworkUtils;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.Version;
import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine;
import net.osmand.plus.onlinerouting.parser.ResponseParser;
import net.osmand.plus.onlinerouting.parser.ResponseParser.OnlineRoutingResponse;
import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine.OnlineRoutingResponse;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.util.Algorithms;
@ -95,8 +94,7 @@ public class OnlineRoutingHelper {
boolean leftSideNavigation) throws IOException, JSONException {
String url = engine.getFullUrl(path);
String content = makeRequest(url);
ResponseParser parser = engine.getResponseParser();
return parser.parseResponse(content, app, leftSideNavigation);
return engine.parseResponse(content, app, leftSideNavigation);
}
@NonNull

View file

@ -3,12 +3,16 @@ package net.osmand.plus.onlinerouting.engine;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.data.LatLon;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.onlinerouting.EngineParameter;
import net.osmand.plus.onlinerouting.VehicleType;
import net.osmand.plus.onlinerouting.parser.GpxParser;
import net.osmand.plus.onlinerouting.parser.ResponseParser;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -56,9 +60,29 @@ public class GpxEngine extends OnlineRoutingEngine {
params.add(EngineParameter.CUSTOM_URL);
}
@NonNull
@Override
protected ResponseParser createParser() {
return new GpxParser();
@Nullable
public OnlineRoutingResponse parseResponse(@NonNull String content,
@NonNull OsmandApplication app,
boolean leftSideNavigation) {
GPXFile gpxFile = parseGpx(content);
return gpxFile != null ? new OnlineRoutingResponse(parseGpx(content)) : null;
}
@Override
public boolean isResultOk(@NonNull StringBuilder errorMessage,
@NonNull String content) {
return parseGpx(content) != null;
}
private GPXFile parseGpx(@NonNull String content) {
InputStream gpxStream = null;
try {
gpxStream = new ByteArrayInputStream(content.getBytes("UTF-8"));
return GPXUtilities.loadGPXFile(gpxStream);
} catch (UnsupportedEncodingException e) {
LOG.debug("Error when parsing GPX from server response: " + e.getMessage());
}
return null;
}
}

View file

@ -9,8 +9,6 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.onlinerouting.EngineParameter;
import net.osmand.plus.onlinerouting.VehicleType;
import net.osmand.plus.onlinerouting.parser.JSONParser;
import net.osmand.plus.onlinerouting.parser.ResponseParser;
import net.osmand.plus.routing.RouteDirectionInfo;
import net.osmand.router.TurnType;
import net.osmand.util.GeoPolylineParserUtil;
@ -26,7 +24,7 @@ import java.util.Set;
import static net.osmand.util.Algorithms.isEmpty;
public class GraphhopperEngine extends OnlineRoutingEngine {
public class GraphhopperEngine extends JsonOnlineRoutingEngine {
public GraphhopperEngine(@Nullable Map<String, String> params) {
super(params);
@ -67,12 +65,6 @@ public class GraphhopperEngine extends OnlineRoutingEngine {
vehicles.add(new VehicleType("small_truck", R.string.routing_engine_vehicle_type_small_truck));
}
@NonNull
@Override
protected ResponseParser createParser() {
return new GraphhopperParser();
}
@Override
protected void makeFullUrl(@NonNull StringBuilder sb,
@NonNull List<LatLon> path) {
@ -95,148 +87,146 @@ public class GraphhopperEngine extends OnlineRoutingEngine {
sb.append('&').append("details=").append("lanes");
}
private static class GraphhopperParser extends JSONParser {
@Nullable
protected OnlineRoutingResponse parseServerResponse(@NonNull JSONObject root,
@NonNull OsmandApplication app,
boolean leftSideNavigation) throws JSONException {
String encoded = root.getString("points");
List<LatLon> points = GeoPolylineParserUtil.parse(encoded, GeoPolylineParserUtil.PRECISION_5);
if (isEmpty(points)) return null;
List<Location> route = convertRouteToLocationsList(points);
@Nullable
protected OnlineRoutingResponse parseServerResponse(@NonNull JSONObject root,
@NonNull OsmandApplication app,
boolean leftSideNavigation) throws JSONException {
String encoded = root.getString("points");
List<LatLon> points = GeoPolylineParserUtil.parse(encoded, GeoPolylineParserUtil.PRECISION_5);
if (isEmpty(points)) return null;
List<Location> route = convertRouteToLocationsList(points);
JSONArray instructions = root.getJSONArray("instructions");
List<RouteDirectionInfo> directions = new ArrayList<>();
for (int i = 0; i < instructions.length(); i++) {
JSONObject instruction = instructions.getJSONObject(i);
int distance = (int) Math.round(instruction.getDouble("distance"));
String description = instruction.getString("text");
String streetName = instruction.getString("street_name");
int timeInSeconds = Math.round(instruction.getInt("time") / 1000f);
JSONArray interval = instruction.getJSONArray("interval");
int startPointOffset = interval.getInt(0);
int endPointOffset = interval.getInt(1);
JSONArray instructions = root.getJSONArray("instructions");
List<RouteDirectionInfo> directions = new ArrayList<>();
for (int i = 0; i < instructions.length(); i++) {
JSONObject instruction = instructions.getJSONObject(i);
int distance = (int) Math.round(instruction.getDouble("distance"));
String description = instruction.getString("text");
String streetName = instruction.getString("street_name");
int timeInSeconds = Math.round(instruction.getInt("time") / 1000f);
JSONArray interval = instruction.getJSONArray("interval");
int startPointOffset = interval.getInt(0);
int endPointOffset = interval.getInt(1);
float averageSpeed = (float) distance / timeInSeconds;
TurnType turnType = parseTurnType(instruction, leftSideNavigation);
RouteDirectionInfo direction = new RouteDirectionInfo(averageSpeed, turnType);
float averageSpeed = (float) distance / timeInSeconds;
TurnType turnType = parseTurnType(instruction, leftSideNavigation);
RouteDirectionInfo direction = new RouteDirectionInfo(averageSpeed, turnType);
direction.routePointOffset = startPointOffset;
direction.setDescriptionRoute(description);
direction.setStreetName(streetName);
direction.setDistance(distance);
directions.add(direction);
}
return new OnlineRoutingResponse(route, directions);
}
@NonNull
private TurnType parseTurnType(@NonNull JSONObject instruction,
boolean leftSide) throws JSONException {
int sign = instruction.getInt("sign");
TurnType turnType = identifyTurnType(sign, leftSide);
if (turnType == null) {
turnType = TurnType.straight();
} else if (turnType.isRoundAbout()) {
if (instruction.has("exit_number")) {
int exit = instruction.getInt("exit_number");
turnType.setExitOut(exit);
}
if (instruction.has("turn_angle")) {
float angle = (float) instruction.getDouble("turn_angle");
turnType.setTurnAngle(angle);
}
} else {
// TODO turnType.setTurnAngle()
}
return turnType;
}
@Nullable
public static TurnType identifyTurnType(int sign, boolean leftSide) {
Integer id = null;
if (sign == -98) {
// an U-turn without the knowledge
// if it is a right or left U-turn
id = TurnType.TU;
} else if (sign == -8) {
// a left U-turn
leftSide = false;
id = TurnType.TU;
} else if (sign == -7) {
// keep left
id = TurnType.KL;
} else if (sign == -6) {
// not yet used: leave roundabout
} else if (sign == -3) {
// turn sharp left
id = TurnType.TSHL;
} else if (sign == -2) {
// turn left
id = TurnType.TL;
} else if (sign == -1) {
// turn slight left
id = TurnType.TSLL;
} else if (sign == 0) {
// continue on street
id = TurnType.C;
} else if (sign == 1) {
// turn slight right
id = TurnType.TSLR;
} else if (sign == 2) {
// turn right
id = TurnType.TR;
} else if (sign == 3) {
// turn sharp right
id = TurnType.TSHR;
} else if (sign == 4) {
// the finish instruction before the last point
id = TurnType.C;
} else if (sign == 5) {
// the instruction before a via point
} else if (sign == 6) {
// the instruction before entering a roundabout
id = TurnType.RNDB;
} else if (sign == 7) {
// keep right
id = TurnType.KR;
} else if (sign == 8) {
// a right U-turn
id = TurnType.TRU;
}
return id != null ? TurnType.valueOf(id, leftSide) : null;
}
@NonNull
@Override
protected String getErrorMessageKey() {
return "message";
}
@NonNull
@Override
protected String getRootArrayKey() {
return "paths";
direction.routePointOffset = startPointOffset;
direction.setDescriptionRoute(description);
direction.setStreetName(streetName);
direction.setDistance(distance);
directions.add(direction);
}
return new OnlineRoutingResponse(route, directions);
}
@NonNull
private TurnType parseTurnType(@NonNull JSONObject instruction,
boolean leftSide) throws JSONException {
int sign = instruction.getInt("sign");
TurnType turnType = identifyTurnType(sign, leftSide);
if (turnType == null) {
turnType = TurnType.straight();
} else if (turnType.isRoundAbout()) {
if (instruction.has("exit_number")) {
int exit = instruction.getInt("exit_number");
turnType.setExitOut(exit);
}
if (instruction.has("turn_angle")) {
float angle = (float) instruction.getDouble("turn_angle");
turnType.setTurnAngle(angle);
}
} else {
// TODO turnType.setTurnAngle()
}
return turnType;
}
@Nullable
public static TurnType identifyTurnType(int sign, boolean leftSide) {
Integer id = null;
if (sign == -98) {
// an U-turn without the knowledge
// if it is a right or left U-turn
id = TurnType.TU;
} else if (sign == -8) {
// a left U-turn
leftSide = false;
id = TurnType.TU;
} else if (sign == -7) {
// keep left
id = TurnType.KL;
} else if (sign == -6) {
// not yet used: leave roundabout
} else if (sign == -3) {
// turn sharp left
id = TurnType.TSHL;
} else if (sign == -2) {
// turn left
id = TurnType.TL;
} else if (sign == -1) {
// turn slight left
id = TurnType.TSLL;
} else if (sign == 0) {
// continue on street
id = TurnType.C;
} else if (sign == 1) {
// turn slight right
id = TurnType.TSLR;
} else if (sign == 2) {
// turn right
id = TurnType.TR;
} else if (sign == 3) {
// turn sharp right
id = TurnType.TSHR;
} else if (sign == 4) {
// the finish instruction before the last point
id = TurnType.C;
} else if (sign == 5) {
// the instruction before a via point
} else if (sign == 6) {
// the instruction before entering a roundabout
id = TurnType.RNDB;
} else if (sign == 7) {
// keep right
id = TurnType.KR;
} else if (sign == 8) {
// a right U-turn
id = TurnType.TRU;
}
return id != null ? TurnType.valueOf(id, leftSide) : null;
}
@NonNull
@Override
protected String getErrorMessageKey() {
return "message";
}
@NonNull
@Override
protected String getRootArrayKey() {
return "paths";
}
}

View file

@ -1,4 +1,4 @@
package net.osmand.plus.onlinerouting.parser;
package net.osmand.plus.onlinerouting.engine;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -15,10 +15,15 @@ import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static net.osmand.util.Algorithms.isEmpty;
public abstract class JSONParser extends ResponseParser {
public abstract class JsonOnlineRoutingEngine extends OnlineRoutingEngine {
public JsonOnlineRoutingEngine(@Nullable Map<String, String> params) {
super(params);
}
@Nullable
public OnlineRoutingResponse parseResponse(@NonNull String content,

View file

@ -5,16 +5,20 @@ import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.Location;
import net.osmand.PlatformUtil;
import net.osmand.data.LatLon;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.onlinerouting.EngineParameter;
import net.osmand.plus.onlinerouting.OnlineRoutingFactory;
import net.osmand.plus.onlinerouting.VehicleType;
import net.osmand.plus.onlinerouting.parser.ResponseParser;
import net.osmand.plus.routing.RouteDirectionInfo;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import org.json.JSONException;
import java.util.ArrayList;
import java.util.Collections;
@ -36,7 +40,6 @@ public abstract class OnlineRoutingEngine implements Cloneable {
private final Map<String, String> params = new HashMap<>();
private final List<VehicleType> allowedVehicles = new ArrayList<>();
private final Set<EngineParameter> allowedParameters = new HashSet<>();
private ResponseParser responseParser;
public OnlineRoutingEngine(@Nullable Map<String, String> params) {
if (!isEmpty(params)) {
@ -97,16 +100,13 @@ public abstract class OnlineRoutingEngine implements Cloneable {
@NonNull
public abstract String getStandardUrl();
@NonNull
public ResponseParser getResponseParser() {
if (responseParser == null) {
responseParser = createParser();
}
return responseParser;
}
@Nullable
public abstract OnlineRoutingResponse parseResponse(@NonNull String content,
@NonNull OsmandApplication app,
boolean leftSideNavigation) throws JSONException;
@NonNull
protected abstract ResponseParser createParser();
public abstract boolean isResultOk(@NonNull StringBuilder errorMessage,
@NonNull String content) throws JSONException;
@NonNull
public Map<String, String> getParams() {
@ -194,4 +194,34 @@ public abstract class OnlineRoutingEngine implements Cloneable {
return ONLINE_ROUTING_ENGINE_PREFIX + System.currentTimeMillis();
}
public static class OnlineRoutingResponse {
private List<Location> route;
private List<RouteDirectionInfo> directions;
private GPXFile gpxFile;
// constructor for JSON responses
public OnlineRoutingResponse(List<Location> route, List<RouteDirectionInfo> directions) {
this.route = route;
this.directions = directions;
}
// constructor for GPX responses
public OnlineRoutingResponse(GPXFile gpxFile) {
this.gpxFile = gpxFile;
}
public List<Location> getRoute() {
return route;
}
public List<RouteDirectionInfo> getDirections() {
return directions;
}
public GPXFile getGpxFile() {
return gpxFile;
}
}
}

View file

@ -9,8 +9,6 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.onlinerouting.EngineParameter;
import net.osmand.plus.onlinerouting.VehicleType;
import net.osmand.plus.onlinerouting.parser.JSONParser;
import net.osmand.plus.onlinerouting.parser.ResponseParser;
import org.json.JSONArray;
import org.json.JSONException;
@ -23,7 +21,7 @@ import java.util.Set;
import static net.osmand.util.Algorithms.isEmpty;
public class OrsEngine extends OnlineRoutingEngine {
public class OrsEngine extends JsonOnlineRoutingEngine {
public OrsEngine(@Nullable Map<String, String> params) {
super(params);
@ -64,12 +62,6 @@ public class OrsEngine extends OnlineRoutingEngine {
vehicles.add(new VehicleType("wheelchair", R.string.routing_engine_vehicle_type_wheelchair));
}
@NonNull
@Override
protected ResponseParser createParser() {
return new OrsParser();
}
@Override
protected void makeFullUrl(@NonNull StringBuilder sb,
@NonNull List<LatLon> path) {
@ -92,38 +84,36 @@ public class OrsEngine extends OnlineRoutingEngine {
}
}
private static class OrsParser extends JSONParser {
@Nullable
@Override
public OnlineRoutingResponse parseServerResponse(@NonNull JSONObject root,
@NonNull OsmandApplication app,
boolean leftSideNavigation) throws JSONException {
JSONArray array = root.getJSONObject("geometry").getJSONArray("coordinates");
List<LatLon> points = new ArrayList<>();
for (int i = 0; i < array.length(); i++) {
JSONArray point = array.getJSONArray(i);
double lon = Double.parseDouble(point.getString(0));
double lat = Double.parseDouble(point.getString(1));
points.add(new LatLon(lat, lon));
}
if (!isEmpty(points)) {
List<Location> route = convertRouteToLocationsList(points);
new OnlineRoutingResponse(route, null);
}
return null;
@Nullable
@Override
public OnlineRoutingResponse parseServerResponse(@NonNull JSONObject root,
@NonNull OsmandApplication app,
boolean leftSideNavigation) throws JSONException {
JSONArray array = root.getJSONObject("geometry").getJSONArray("coordinates");
List<LatLon> points = new ArrayList<>();
for (int i = 0; i < array.length(); i++) {
JSONArray point = array.getJSONArray(i);
double lon = Double.parseDouble(point.getString(0));
double lat = Double.parseDouble(point.getString(1));
points.add(new LatLon(lat, lon));
}
@NonNull
@Override
protected String getErrorMessageKey() {
return "error";
}
@NonNull
@Override
protected String getRootArrayKey() {
return "features";
if (!isEmpty(points)) {
List<Location> route = convertRouteToLocationsList(points);
new OnlineRoutingResponse(route, null);
}
return null;
}
@NonNull
@Override
protected String getErrorMessageKey() {
return "error";
}
@NonNull
@Override
protected String getRootArrayKey() {
return "features";
}
}

View file

@ -9,8 +9,6 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.onlinerouting.EngineParameter;
import net.osmand.plus.onlinerouting.VehicleType;
import net.osmand.plus.onlinerouting.parser.JSONParser;
import net.osmand.plus.onlinerouting.parser.ResponseParser;
import net.osmand.plus.routing.RouteCalculationResult;
import net.osmand.plus.routing.RouteDirectionInfo;
import net.osmand.router.TurnType;
@ -29,7 +27,7 @@ import java.util.Set;
import static net.osmand.util.Algorithms.isEmpty;
import static net.osmand.util.Algorithms.objectEquals;
public class OsrmEngine extends OnlineRoutingEngine {
public class OsrmEngine extends JsonOnlineRoutingEngine {
public OsrmEngine(@Nullable Map<String, String> params) {
super(params);
@ -63,12 +61,6 @@ public class OsrmEngine extends OnlineRoutingEngine {
vehicles.add(new VehicleType("foot", R.string.routing_engine_vehicle_type_foot));
}
@NonNull
@Override
protected ResponseParser createParser() {
return new OsrmParser();
}
@Override
protected void makeFullUrl(@NonNull StringBuilder sb,
@NonNull List<LatLon> path) {
@ -88,167 +80,165 @@ public class OsrmEngine extends OnlineRoutingEngine {
sb.append('&').append("steps=true");
}
private static class OsrmParser extends JSONParser {
@Nullable
@Override
protected OnlineRoutingResponse parseServerResponse(@NonNull JSONObject root,
@NonNull OsmandApplication app,
boolean leftSideNavigation) throws JSONException {
String encodedPoints = root.getString("geometry");
List<LatLon> points = GeoPolylineParserUtil.parse(encodedPoints, GeoPolylineParserUtil.PRECISION_5);
if (isEmpty(points)) return null;
@Nullable
@Override
protected OnlineRoutingResponse parseServerResponse(@NonNull JSONObject root,
@NonNull OsmandApplication app,
boolean leftSideNavigation) throws JSONException {
String encodedPoints = root.getString("geometry");
List<LatLon> points = GeoPolylineParserUtil.parse(encodedPoints, GeoPolylineParserUtil.PRECISION_5);
if (isEmpty(points)) return null;
List<Location> route = convertRouteToLocationsList(points);
List<RouteDirectionInfo> directions = new ArrayList<>();
int startSearchingId = 0;
JSONArray legs = root.getJSONArray("legs");
for (int i = 0; i < legs.length(); i++) {
JSONObject leg = legs.getJSONObject(i);
if (!leg.has("steps")) continue;
List<Location> route = convertRouteToLocationsList(points);
List<RouteDirectionInfo> directions = new ArrayList<>();
int startSearchingId = 0;
JSONArray legs = root.getJSONArray("legs");
for (int i = 0; i < legs.length(); i++) {
JSONObject leg = legs.getJSONObject(i);
if (!leg.has("steps")) continue;
JSONArray steps = leg.getJSONArray("steps");
for (int j = 0; j < steps.length(); j++) {
JSONObject instruction = steps.getJSONObject(j);
JSONObject maneuver = instruction.getJSONObject("maneuver");
String maneuverType = maneuver.getString("type");
JSONArray steps = leg.getJSONArray("steps");
for (int j = 0; j < steps.length(); j++) {
JSONObject instruction = steps.getJSONObject(j);
JSONObject maneuver = instruction.getJSONObject("maneuver");
String maneuverType = maneuver.getString("type");
JSONArray location = maneuver.getJSONArray("location");
double lon = location.getDouble(0);
double lat = location.getDouble(1);
Integer routePointOffset = getLocationIndexInList(route, startSearchingId, lat, lon);
if (routePointOffset == null) continue;
startSearchingId = routePointOffset;
JSONArray location = maneuver.getJSONArray("location");
double lon = location.getDouble(0);
double lat = location.getDouble(1);
Integer routePointOffset = getLocationIndexInList(route, startSearchingId, lat, lon);
if (routePointOffset == null) continue;
startSearchingId = routePointOffset;
// in meters
int distance = (int) Math.round(instruction.getDouble("distance"));
// in seconds
int duration = (int) Math.round(instruction.getDouble("duration"));
// in meters
int distance = (int) Math.round(instruction.getDouble("distance"));
// in seconds
int duration = (int) Math.round(instruction.getDouble("duration"));
float averageSpeed = (float) distance / duration;
TurnType turnType = parseTurnType(maneuver, leftSideNavigation);
RouteDirectionInfo direction = new RouteDirectionInfo(averageSpeed, turnType);
direction.setDistance(distance);
float averageSpeed = (float) distance / duration;
TurnType turnType = parseTurnType(maneuver, leftSideNavigation);
RouteDirectionInfo direction = new RouteDirectionInfo(averageSpeed, turnType);
direction.setDistance(distance);
String streetName = instruction.getString("name");
String description = "";
if (!objectEquals(maneuverType, "arrive")) {
description = RouteCalculationResult.toString(turnType, app, false) + " " + streetName;
}
description = description.trim();
direction.setStreetName(streetName);
direction.setDescriptionRoute(description);
direction.routePointOffset = routePointOffset;
directions.add(direction);
String streetName = instruction.getString("name");
String description = "";
if (!objectEquals(maneuverType, "arrive")) {
description = RouteCalculationResult.toString(turnType, app, false) + " " + streetName;
}
}
description = description.trim();
return new OnlineRoutingResponse(route, directions);
direction.setStreetName(streetName);
direction.setDescriptionRoute(description);
direction.routePointOffset = routePointOffset;
directions.add(direction);
}
}
@Nullable
private Integer getLocationIndexInList(@NonNull List<Location> locations,
int startIndex, double lat, double lon) {
for (int i = startIndex; i < locations.size(); i++) {
Location l = locations.get(i);
if (MapUtils.areLatLonEqual(l, lat, lon)) {
return i;
}
}
return null;
}
@NonNull
private TurnType parseTurnType(@NonNull JSONObject maneuver,
boolean leftSide) throws JSONException {
TurnType turnType = null;
String type = maneuver.getString("type");
String modifier = null;
if (maneuver.has("modifier")) {
modifier = maneuver.getString("modifier");
}
if (objectEquals(type, "roundabout")
|| objectEquals(type, "rotary")
|| objectEquals(type, "roundabout turn")) {
if (maneuver.has("exit")) {
int exit = maneuver.getInt("exit");
turnType = TurnType.getExitTurn(exit, 0.0f, leftSide);
} else if (modifier != null) {
// for simple roundabout turn without "exit" parameter
turnType = identifyTurnType(modifier, leftSide);
}
} else {
// for other maneuver types find TurnType
// like a basic turn into direction of the modifier
if (modifier != null) {
turnType = identifyTurnType(modifier, leftSide);
}
}
if (turnType == null) {
turnType = TurnType.straight();
}
int bearingBefore = maneuver.getInt("bearing_before");
int bearingAfter = maneuver.getInt("bearing_after");
float angle = (float) MapUtils.degreesDiff(bearingAfter, bearingBefore);
turnType.setTurnAngle(angle);
return turnType;
}
@Nullable
private TurnType identifyTurnType(@NonNull String modifier,
boolean leftSide) {
Integer id = null;
switch (modifier) {
case "uturn":
id = TurnType.TU;
break;
case "sharp right":
id = TurnType.TSHR;
break;
case "right":
id = TurnType.TR;
break;
case "slight right":
id = TurnType.TSLR;
break;
case "straight":
id = TurnType.C;
break;
case "slight left":
id = TurnType.TSLL;
break;
case "left":
id = TurnType.TL;
break;
case "sharp left":
id = TurnType.TSHL;
break;
}
return id != null ? TurnType.valueOf(id, leftSide) : null;
}
@NonNull
@Override
protected String getRootArrayKey() {
return "routes";
}
@NonNull
@Override
protected String getErrorMessageKey() {
return "message";
}
return new OnlineRoutingResponse(route, directions);
}
@Nullable
private Integer getLocationIndexInList(@NonNull List<Location> locations,
int startIndex, double lat, double lon) {
for (int i = startIndex; i < locations.size(); i++) {
Location l = locations.get(i);
if (MapUtils.areLatLonEqual(l, lat, lon)) {
return i;
}
}
return null;
}
@NonNull
private TurnType parseTurnType(@NonNull JSONObject maneuver,
boolean leftSide) throws JSONException {
TurnType turnType = null;
String type = maneuver.getString("type");
String modifier = null;
if (maneuver.has("modifier")) {
modifier = maneuver.getString("modifier");
}
if (objectEquals(type, "roundabout")
|| objectEquals(type, "rotary")
|| objectEquals(type, "roundabout turn")) {
if (maneuver.has("exit")) {
int exit = maneuver.getInt("exit");
turnType = TurnType.getExitTurn(exit, 0.0f, leftSide);
} else if (modifier != null) {
// for simple roundabout turn without "exit" parameter
turnType = identifyTurnType(modifier, leftSide);
}
} else {
// for other maneuver types find TurnType
// like a basic turn into direction of the modifier
if (modifier != null) {
turnType = identifyTurnType(modifier, leftSide);
}
}
if (turnType == null) {
turnType = TurnType.straight();
}
int bearingBefore = maneuver.getInt("bearing_before");
int bearingAfter = maneuver.getInt("bearing_after");
float angle = (float) MapUtils.degreesDiff(bearingAfter, bearingBefore);
turnType.setTurnAngle(angle);
return turnType;
}
@Nullable
private TurnType identifyTurnType(@NonNull String modifier,
boolean leftSide) {
Integer id = null;
switch (modifier) {
case "uturn":
id = TurnType.TU;
break;
case "sharp right":
id = TurnType.TSHR;
break;
case "right":
id = TurnType.TR;
break;
case "slight right":
id = TurnType.TSLR;
break;
case "straight":
id = TurnType.C;
break;
case "slight left":
id = TurnType.TSLL;
break;
case "left":
id = TurnType.TL;
break;
case "sharp left":
id = TurnType.TSHL;
break;
}
return id != null ? TurnType.valueOf(id, leftSide) : null;
}
@NonNull
@Override
protected String getRootArrayKey() {
return "routes";
}
@NonNull
@Override
protected String getErrorMessageKey() {
return "message";
}
}

View file

@ -1,42 +0,0 @@
package net.osmand.plus.onlinerouting.parser;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.plus.OsmandApplication;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
public class GpxParser extends ResponseParser {
@Override
@Nullable
public OnlineRoutingResponse parseResponse(@NonNull String content,
@NonNull OsmandApplication app,
boolean leftSideNavigation) {
GPXFile gpxFile = parseGpx(content);
return gpxFile != null ? new OnlineRoutingResponse(parseGpx(content)) : null;
}
@Override
public boolean isResultOk(@NonNull StringBuilder errorMessage,
@NonNull String content) {
return parseGpx(content) != null;
}
private GPXFile parseGpx(@NonNull String content) {
InputStream gpxStream = null;
try {
gpxStream = new ByteArrayInputStream(content.getBytes("UTF-8"));
return GPXUtilities.loadGPXFile(gpxStream);
} catch (UnsupportedEncodingException e) {
LOG.debug("Error when parsing GPX from server response: " + e.getMessage());
}
return null;
}
}

View file

@ -1,77 +0,0 @@
package net.osmand.plus.onlinerouting.parser;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.Location;
import net.osmand.PlatformUtil;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.routing.RouteDirectionInfo;
import org.apache.commons.logging.Log;
import org.json.JSONException;
import java.util.List;
public abstract class ResponseParser {
protected static final Log LOG = PlatformUtil.getLog(ResponseParser.class);
@Nullable
public abstract OnlineRoutingResponse parseResponse(@NonNull String content,
@NonNull OsmandApplication app,
boolean leftSideNavigation) throws JSONException;
public abstract boolean isResultOk(@NonNull StringBuilder errorMessage,
@NonNull String content) throws JSONException;
public static ResponseParser emptyParser() {
return new ResponseParser() {
@Nullable
@Override
public OnlineRoutingResponse parseResponse(@NonNull String content,
@NonNull OsmandApplication app,
boolean leftSideNavigation) {
return null;
}
@Override
public boolean isResultOk(@NonNull StringBuilder errorMessage,
@NonNull String content) {
return false;
}
};
}
public static class OnlineRoutingResponse {
private List<Location> route;
private List<RouteDirectionInfo> directions;
private GPXFile gpxFile;
// constructor for JSON responses
public OnlineRoutingResponse(List<Location> route, List<RouteDirectionInfo> directions) {
this.route = route;
this.directions = directions;
}
// constructor for GPX responses
public OnlineRoutingResponse(GPXFile gpxFile) {
this.gpxFile = gpxFile;
}
public List<Location> getRoute() {
return route;
}
public List<RouteDirectionInfo> getDirections() {
return directions;
}
public GPXFile getGpxFile() {
return gpxFile;
}
}
}

View file

@ -462,7 +462,7 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
boolean resultOk = false;
try {
String response = helper.makeRequest(exampleCard.getEditedText());
resultOk = requestedEngine.getResponseParser().isResultOk(errorMessage, response);
resultOk = requestedEngine.isResultOk(errorMessage, response);
} catch (IOException | JSONException e) {
errorMessage.append(e.toString());
}

View file

@ -23,7 +23,7 @@ import net.osmand.plus.R;
import net.osmand.plus.TargetPointsHelper;
import net.osmand.plus.TargetPointsHelper.TargetPoint;
import net.osmand.plus.onlinerouting.OnlineRoutingHelper;
import net.osmand.plus.onlinerouting.parser.ResponseParser.OnlineRoutingResponse;
import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine.OnlineRoutingResponse;
import net.osmand.plus.render.NativeOsmandLibrary;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.CommonPreference;