Skip to content

Commit 1cef0e9

Browse files
committed
- Added Waypoints to NavigationRoute; - RouteOptionsUpdater refactored;
1 parent 8273101 commit 1cef0e9

File tree

21 files changed

+897
-297
lines changed

21 files changed

+897
-297
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.mapbox.navigation.instrumentation_tests.core
2+
3+
import android.location.Location
4+
import com.mapbox.api.directions.v5.models.DirectionsResponse
5+
import com.mapbox.api.directions.v5.models.DirectionsRoute
6+
import com.mapbox.api.directions.v5.models.RouteOptions
7+
import com.mapbox.geojson.Point
8+
import com.mapbox.navigation.base.extensions.applyDefaultNavigationOptions
9+
import com.mapbox.navigation.base.internal.route.createNavigationRoutes
10+
import com.mapbox.navigation.base.internal.utils._waypoints
11+
import com.mapbox.navigation.base.route.NavigationRoute
12+
import com.mapbox.navigation.base.route.RouterOrigin
13+
import com.mapbox.navigation.instrumentation_tests.R
14+
import com.mapbox.navigation.instrumentation_tests.activity.EmptyTestActivity
15+
import com.mapbox.navigation.instrumentation_tests.utils.readRawFileText
16+
import com.mapbox.navigation.testing.ui.BaseTest
17+
import junit.framework.Assert.assertTrue
18+
import org.junit.Test
19+
20+
class NavigationRouteTests : BaseTest<EmptyTestActivity>(EmptyTestActivity::class.java) {
21+
22+
override fun setupMockLocation(): Location = mockLocationUpdatesRule.generateLocationUpdate {
23+
latitude = 0.0
24+
longitude = 0.0
25+
}
26+
27+
@Test
28+
fun mapDirectionsResponseToNavigationRoutes() {
29+
val jsonResponse = readRawFileText(activity, R.raw.route_response_dc_very_short)
30+
31+
val navRoutes = NavigationRoute.create(
32+
DirectionsResponse.fromJson(jsonResponse),
33+
provideRouteOptions(),
34+
RouterOrigin.Onboard
35+
)
36+
37+
assertTrue(navRoutes.isNotEmpty())
38+
navRoutes.forEach {
39+
assertTrue(it._waypoints().isNotEmpty())
40+
}
41+
}
42+
43+
@Test
44+
fun mapDirectionsRoutesToNavigationRoutes() {
45+
val directionsRoute = DirectionsRoute.fromJson(readRawFileText(activity, R.raw.short_route))
46+
47+
val navRoutes = createNavigationRoutes(
48+
listOf(directionsRoute),
49+
provideRouteOptions(),
50+
RouterOrigin.Onboard,
51+
)
52+
53+
assertTrue(navRoutes.isNotEmpty())
54+
}
55+
56+
private fun provideRouteOptions(): RouteOptions =
57+
RouteOptions.builder().applyDefaultNavigationOptions()
58+
.coordinatesList(
59+
listOf(
60+
Point.fromLngLat(1.1, 2.2),
61+
Point.fromLngLat(3.3, 4.4),
62+
)
63+
)
64+
.build()
65+
}

libnavigation-base/src/main/java/com/mapbox/navigation/base/internal/NativeRouteParserWrapper.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ interface SDKRouteParser {
1212
request: String,
1313
routerOrigin: RouterOrigin,
1414
): Expected<String, List<RouteInterface>>
15+
16+
fun parseDirectionsRoutes(
17+
directionsRoutes: String,
18+
request: String,
19+
routerOrigin: RouterOrigin,
20+
): Expected<String, List<RouteInterface>>
1521
}
1622

1723
object NativeRouteParserWrapper : SDKRouteParser {
@@ -25,4 +31,15 @@ object NativeRouteParserWrapper : SDKRouteParser {
2531
request,
2632
routerOrigin.mapToNativeRouteOrigin()
2733
)
34+
35+
override fun parseDirectionsRoutes(
36+
directionsRoutes: String,
37+
request: String,
38+
routerOrigin: RouterOrigin,
39+
): Expected<String, List<RouteInterface>> =
40+
RouteParser.parseDirectionsRoutes(
41+
directionsRoutes,
42+
request,
43+
routerOrigin.mapToNativeRouteOrigin()
44+
)
2845
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
@file:JvmName("WaypointEx")
2+
3+
package com.mapbox.navigation.base.internal.extensions
4+
5+
import com.mapbox.api.directions.v5.models.DirectionsRoute
6+
import com.mapbox.navigation.base.internal.route.Waypoint
7+
import com.mapbox.navigation.base.trip.model.RouteProgress
8+
9+
/**
10+
* Return waypoints that are requested explicitly
11+
*/
12+
fun List<Waypoint>.requestedWaypoints(): List<Waypoint> =
13+
this.filter { it.type != Waypoint.EV_CHARGING }
14+
15+
/**
16+
* Return waypoints that tracking in [RouteProgress.currentLegProgress]#legIndex and based on
17+
* [DirectionsRoute.legs] index
18+
*/
19+
fun List<Waypoint>.legsWaypoints(): List<Waypoint> =
20+
this.filter { it.type != Waypoint.SILENT }
21+
22+
/**
23+
* Return the index of **next requested** coordinate.
24+
*
25+
* For instance, EV waypoints are not requested explicitly, so they are not taken into account.
26+
*/
27+
fun indexOfNextRequestedCoordinate(
28+
waypoints: List<Waypoint>,
29+
remainingWaypoints: Int,
30+
): Int? {
31+
if (remainingWaypoints > waypoints.size) {
32+
return null
33+
}
34+
val nextRequestedWaypoint = waypoints
35+
.subList(waypoints.size - remainingWaypoints, waypoints.size)
36+
.requestedWaypoints()
37+
.firstOrNull()
38+
?: return null
39+
40+
return waypoints
41+
.requestedWaypoints()
42+
.indexOf(nextRequestedWaypoint)
43+
}

libnavigation-base/src/main/java/com/mapbox/navigation/base/internal/route/NavigationRouteEx.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import com.mapbox.api.directions.v5.models.LegAnnotation
1212
import com.mapbox.api.directions.v5.models.LegStep
1313
import com.mapbox.api.directions.v5.models.RouteLeg
1414
import com.mapbox.api.directions.v5.models.RouteOptions
15+
import com.mapbox.navigation.base.internal.NativeRouteParserWrapper
1516
import com.mapbox.navigation.base.internal.SDKRouteParser
1617
import com.mapbox.navigation.base.route.NavigationRoute
1718
import com.mapbox.navigation.base.route.toNavigationRoute
@@ -149,6 +150,20 @@ fun createNavigationRoutes(
149150
): List<NavigationRoute> =
150151
NavigationRoute.create(directionsResponse, routeOptions, routeParser, routerOrigin)
151152

153+
@VisibleForTesting
154+
fun createNavigationRoutes(
155+
directionsRoutes: List<DirectionsRoute>,
156+
routeOptions: RouteOptions,
157+
routerOrigin: com.mapbox.navigation.base.route.RouterOrigin,
158+
routeParser: SDKRouteParser = NativeRouteParserWrapper
159+
): List<NavigationRoute> =
160+
NavigationRoute.create(
161+
directionsRoutes,
162+
routeOptions,
163+
routerOrigin,
164+
routeParser,
165+
)
166+
152167
/**
153168
* Internal API to create a new [NavigationRoute] from a native peer.
154169
*/
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.mapbox.navigation.base.internal.route
2+
3+
import androidx.annotation.IntDef
4+
import com.mapbox.geojson.Point
5+
6+
data class Waypoint(
7+
val location: Point,
8+
@Type val type: Int,
9+
val name: String,
10+
val target: Point?,
11+
) {
12+
companion object {
13+
const val REGULAR = 1
14+
const val SILENT = 2
15+
const val EV_CHARGING = 3
16+
}
17+
18+
@Target(
19+
AnnotationTarget.PROPERTY,
20+
AnnotationTarget.VALUE_PARAMETER,
21+
AnnotationTarget.FUNCTION,
22+
AnnotationTarget.TYPE
23+
)
24+
@Retention(AnnotationRetention.BINARY)
25+
@IntDef(REGULAR, SILENT, EV_CHARGING)
26+
annotation class Type
27+
}

libnavigation-base/src/main/java/com/mapbox/navigation/base/internal/utils/DirectionsRouteEx.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package com.mapbox.navigation.base.internal.utils
44

55
import com.mapbox.api.directions.v5.models.DirectionsRoute
66
import com.mapbox.api.directions.v5.models.LegStep
7+
import com.mapbox.navigation.base.internal.route.Waypoint
78
import com.mapbox.navigation.base.utils.ifNonNull
89

910
/**
@@ -36,3 +37,21 @@ private fun DirectionsRoute.stepsNamesAsString(): String? =
3637
?.joinToString { leg ->
3738
leg.steps()?.joinToString { step -> step.name() ?: "" } ?: ""
3839
}
40+
41+
internal fun List<com.mapbox.navigator.Waypoint>.mapToSkd(): List<Waypoint> =
42+
map { nativeWaypoint ->
43+
Waypoint(
44+
location = nativeWaypoint.location,
45+
type = nativeWaypoint.type.mapToSdk(),
46+
name = nativeWaypoint.name,
47+
target = nativeWaypoint.target,
48+
)
49+
}
50+
51+
@Waypoint.Type
52+
private fun com.mapbox.navigator.WaypointType.mapToSdk(): Int =
53+
when (this) {
54+
com.mapbox.navigator.WaypointType.REGULAR -> Waypoint.REGULAR
55+
com.mapbox.navigator.WaypointType.SILENT -> Waypoint.SILENT
56+
com.mapbox.navigator.WaypointType.EV_CHARGING -> Waypoint.EV_CHARGING
57+
}

libnavigation-base/src/main/java/com/mapbox/navigation/base/internal/utils/RouterEx.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.mapbox.navigation.base.internal.utils
22

3+
import com.mapbox.navigation.base.internal.route.Waypoint
4+
import com.mapbox.navigation.base.route.NavigationRoute
35
import com.mapbox.navigator.RouterOrigin
46

57
fun RouterOrigin.mapToSdkRouteOrigin(): com.mapbox.navigation.base.route.RouterOrigin =
@@ -15,3 +17,5 @@ fun com.mapbox.navigation.base.route.RouterOrigin.mapToNativeRouteOrigin(): Rout
1517
com.mapbox.navigation.base.route.RouterOrigin.Onboard -> RouterOrigin.ONBOARD
1618
is com.mapbox.navigation.base.route.RouterOrigin.Custom -> RouterOrigin.CUSTOM
1719
}
20+
21+
fun NavigationRoute._waypoints(): List<Waypoint> = waypoints

libnavigation-base/src/main/java/com/mapbox/navigation/base/route/NavigationRoute.kt

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
package com.mapbox.navigation.base.route
44

5+
import com.google.gson.Gson
56
import com.mapbox.api.directions.v5.models.DirectionsResponse
67
import com.mapbox.api.directions.v5.models.DirectionsRoute
78
import com.mapbox.api.directions.v5.models.DirectionsWaypoint
@@ -17,8 +18,11 @@ import com.mapbox.navigation.base.internal.NativeRouteParserWrapper
1718
import com.mapbox.navigation.base.internal.SDKRouteParser
1819
import com.mapbox.navigation.base.internal.factory.RoadObjectFactory.toUpcomingRoadObjects
1920
import com.mapbox.navigation.base.internal.route.RouteCompatibilityCache
21+
import com.mapbox.navigation.base.internal.route.Waypoint
22+
import com.mapbox.navigation.base.internal.route.toNavigationRoute
2023
import com.mapbox.navigation.base.internal.utils.DirectionsRouteMissingConditionsCheck
2124
import com.mapbox.navigation.base.internal.utils.mapToSdkRouteOrigin
25+
import com.mapbox.navigation.base.internal.utils.mapToSkd
2226
import com.mapbox.navigation.base.trip.model.roadobject.UpcomingRoadObject
2327
import com.mapbox.navigation.utils.internal.ThreadController
2428
import com.mapbox.navigation.utils.internal.logD
@@ -27,6 +31,7 @@ import com.mapbox.navigation.utils.internal.logI
2731
import com.mapbox.navigator.RouteInterface
2832
import kotlinx.coroutines.async
2933
import kotlinx.coroutines.coroutineScope
34+
import org.json.JSONArray
3035
import java.net.URL
3136

3237
/**
@@ -203,6 +208,38 @@ class NavigationRoute internal constructor(
203208
}
204209
}
205210

211+
internal fun create(
212+
directionsRoutes: List<DirectionsRoute>,
213+
routeOptions: RouteOptions,
214+
routerOrigin: RouterOrigin,
215+
routeParser: SDKRouteParser = NativeRouteParserWrapper
216+
): List<NavigationRoute> {
217+
val directionsRoutesJson = Gson()
218+
.toJson(JSONArray(directionsRoutes.map { it.toJson() }))
219+
.replaceFirst("values", "routes")
220+
return create(
221+
directionsRoutesJson,
222+
routeOptions.toUrl("").toString(),
223+
routerOrigin,
224+
routeParser
225+
)
226+
}
227+
228+
private fun create(
229+
directionsRoutesJson: String,
230+
routeOptionsUrlString: String,
231+
routerOrigin: RouterOrigin,
232+
routeParser: SDKRouteParser = NativeRouteParserWrapper
233+
): List<NavigationRoute> {
234+
return routeParser.parseDirectionsRoutes(
235+
directionsRoutesJson,
236+
routeOptionsUrlString,
237+
routerOrigin
238+
).run {
239+
create(this)
240+
}
241+
}
242+
206243
internal fun create(
207244
directionsResponse: DirectionsResponse,
208245
routeOptions: RouteOptions,
@@ -255,6 +292,19 @@ class NavigationRoute internal constructor(
255292
)
256293
}.cache()
257294
}
295+
296+
private fun create(
297+
expected: Expected<String, List<RouteInterface>>
298+
): List<NavigationRoute> {
299+
return expected.fold({ error ->
300+
logE("NavigationRoute", "Failed to parse a route. Reason: $error")
301+
listOf()
302+
}, { value ->
303+
value
304+
}).map { routeInterface ->
305+
routeInterface.toNavigationRoute()
306+
}.cache()
307+
}
258308
}
259309

260310
/**
@@ -293,6 +343,8 @@ class NavigationRoute internal constructor(
293343
*/
294344
val upcomingRoadObjects = nativeRoute.routeInfo.alerts.toUpcomingRoadObjects()
295345

346+
internal val waypoints: List<Waypoint> by lazy { nativeRoute.waypoints.mapToSkd() }
347+
296348
/**
297349
* Indicates whether some other object is "equal to" this one.
298350
*

0 commit comments

Comments
 (0)