Skip to content

Commit 4d72f31

Browse files
SAA-4082: Replace prison api locations group endpoint (#2020)
* Changes for the deprecated endpoint in prison api * Amended docs and removed nullable from interface and methods
1 parent de8a316 commit 4d72f31

File tree

17 files changed

+152
-108
lines changed

17 files changed

+152
-108
lines changed

src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsactivitiesmanagementapi/client/locationsinsideprison/api/LocationsInsidePrisonAPIClient.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import uk.gov.justice.digital.hmpps.hmppsactivitiesmanagementapi.client.RetryApi
1010
import uk.gov.justice.digital.hmpps.hmppsactivitiesmanagementapi.client.locationsinsideprison.model.Location
1111
import uk.gov.justice.digital.hmpps.hmppsactivitiesmanagementapi.client.locationsinsideprison.model.ServiceUsingLocationDto.ServiceType
1212
import uk.gov.justice.digital.hmpps.hmppsactivitiesmanagementapi.client.prisonapi.api.typeReference
13+
import uk.gov.justice.digital.hmpps.hmppsactivitiesmanagementapi.client.prisonapi.model.LocationGroup
1314
import java.util.*
1415

1516
@Service
@@ -58,4 +59,15 @@ class LocationsInsidePrisonAPIClient(
5859
.bodyToMono(typeReference<List<Location>>())
5960
.retryWhen(backoffSpec.withRetryContext(Context.of("api", "locations-inside-prison-api", "path", "/locations/prison/{prisonCode}/non-residential-usage-type/{usageType}")))
6061
.awaitSingle()
62+
63+
suspend fun getLocationGroups(prisonCode: String): List<LocationGroup> = locationsInsidePrisonApiWebClient.get()
64+
.uri { uriBuilder: UriBuilder ->
65+
uriBuilder
66+
.path("/locations/prison/{prisonCode}/groups")
67+
.build(prisonCode)
68+
}
69+
.retrieve()
70+
.bodyToMono(typeReference<List<LocationGroup>>())
71+
.retryWhen(backoffSpec.withRetryContext(Context.of("api", "locations-inside-prison-api", "path", "/locations/prison/{prisonCode}/groups")))
72+
.awaitSingle()
6173
}

src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsactivitiesmanagementapi/client/prisonapi/api/PrisonApiClient.kt

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import uk.gov.justice.digital.hmpps.hmppsactivitiesmanagementapi.client.RetryApi
1515
import uk.gov.justice.digital.hmpps.hmppsactivitiesmanagementapi.client.maybeQueryParam
1616
import uk.gov.justice.digital.hmpps.hmppsactivitiesmanagementapi.client.prisonapi.model.InmateDetail
1717
import uk.gov.justice.digital.hmpps.hmppsactivitiesmanagementapi.client.prisonapi.model.Location
18-
import uk.gov.justice.digital.hmpps.hmppsactivitiesmanagementapi.client.prisonapi.model.LocationGroup
1918
import uk.gov.justice.digital.hmpps.hmppsactivitiesmanagementapi.client.prisonapi.overrides.Education
2019
import uk.gov.justice.digital.hmpps.hmppsactivitiesmanagementapi.client.prisonapi.overrides.LocationSummary
2120
import uk.gov.justice.digital.hmpps.hmppsactivitiesmanagementapi.client.prisonapi.overrides.Movement
@@ -208,16 +207,6 @@ class PrisonApiClient(
208207
.bodyToMono(typeReference<List<Location>>())
209208
.retryWhen(backoffSpec.withRetryContext(Context.of("api", "prison-api", "path", "/api/agencies/{agencyId}/locations/type/{type}")))
210209

211-
fun getLocationGroups(agencyId: String): Mono<List<LocationGroup>> = prisonApiWebClient.get()
212-
.uri { uriBuilder: UriBuilder ->
213-
uriBuilder
214-
.path("/api/agencies/{agencyId}/locations/groups")
215-
.build(agencyId)
216-
}
217-
.retrieve()
218-
.bodyToMono(typeReference<List<LocationGroup>>())
219-
.retryWhen(backoffSpec.withRetryContext(Context.of("api", "prison-api", "path", "/api/agencies/{agencyId}/locations/groups")))
220-
221210
suspend fun getEventLocationsForPrison(prisonCode: String): PrisonLocations = getEventLocationsAsync(prisonCode).associateBy(Location::locationId)
222211

223212
fun getReferenceCode(domain: String, code: String): Mono<ReferenceCode> = prisonApiWebClient.get()

src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsactivitiesmanagementapi/resource/LocationController.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ class LocationController(
134134
@PreAuthorize("hasAnyRole('PRISON', 'ACTIVITY_ADMIN')")
135135
fun getLocationGroups(
136136
@PathVariable("prisonCode") prisonCode: String,
137-
): List<LocationGroup>? = locationGroupServiceSelector.getLocationGroups(prisonCode)
137+
): List<LocationGroup> = locationGroupServiceSelector.getLocationGroups(prisonCode)
138138

139139
@Deprecated("Use the /prison/{prisonCode}/location-prefixes endpoint below that return location prefixes for a specified locationKey and list of sub-locations")
140140
@GetMapping(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package uk.gov.justice.digital.hmpps.hmppsactivitiesmanagementapi.service
2+
3+
import kotlinx.coroutines.runBlocking
4+
import org.springframework.stereotype.Service
5+
import uk.gov.justice.digital.hmpps.hmppsactivitiesmanagementapi.client.locationsinsideprison.api.LocationsInsidePrisonAPIClient
6+
import uk.gov.justice.digital.hmpps.hmppsactivitiesmanagementapi.client.prisonapi.model.Location
7+
import uk.gov.justice.digital.hmpps.hmppsactivitiesmanagementapi.client.prisonapi.model.LocationGroup
8+
import java.util.function.Predicate
9+
10+
@Service("defaultLocationGroupService")
11+
class LocationGroupFromLocationsInsidePrisonApiService(private val locationsInsidePrisonApiClient: LocationsInsidePrisonAPIClient) : LocationGroupService {
12+
13+
override fun getLocationGroups(prisonCode: String): List<LocationGroup> = runBlocking { locationsInsidePrisonApiClient.getLocationGroups(prisonCode) }
14+
15+
override fun locationGroupFilter(prisonCode: String, groupName: String): Predicate<Location> {
16+
val prefixToMatch = "$prisonCode-${groupName.replace('_', '-')}-"
17+
return Predicate { it.locationPrefix?.startsWith(prefixToMatch) ?: false }
18+
}
19+
}

src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsactivitiesmanagementapi/service/LocationGroupFromPrisonApiService.kt

Lines changed: 0 additions & 18 deletions
This file was deleted.

src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsactivitiesmanagementapi/service/LocationGroupFromPropertiesService.kt

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,43 +18,43 @@ class LocationGroupFromPropertiesService(
1818
) : LocationGroupService {
1919

2020
/**
21-
* Return the set of Location Groups for an agency, including any nested sub-groups.
21+
* Return the set of Location Groups for a prisonCode, including any nested sub-groups.
2222
*
23-
* @param agencyId The agency identifier
23+
* @param prisonCode The prison identifier
2424
* @return A list of LocationGroup, sorted by name, with each item containing its nested LocationGroups, also sorted by name.
2525
*/
26-
override fun getLocationGroups(agencyId: String): List<LocationGroup> {
26+
override fun getLocationGroups(prisonCode: String): List<LocationGroup> {
2727
val fullKeys = groupsProperties.stringPropertyNames()
2828
return fullKeys.asSequence()
29-
.filter { it.startsWith(agencyId) }
30-
.map { it.substring(agencyId.length + 1) }
29+
.filter { it.startsWith(prisonCode) }
30+
.map { it.substring(prisonCode.length + 1) }
3131
.filterNot { it.contains("_") }
3232
.sorted()
33-
.map { LocationGroup(it, it, getAvailableSubGroups(agencyId, it)) }
33+
.map { LocationGroup(it, it, getAvailableSubGroups(prisonCode, it)) }
3434
.toList()
3535
}
3636

3737
/**
38-
* Get the available sub-groups (sub-locations) for the named group/agency.
38+
* Get the available sub-groups (sub-locations) for the named group/prisonCode.
3939
*
40-
* @param agencyId The agency identifier
41-
* @param groupName The name of a group
40+
* @param prisonCode The prison identifier
41+
* @param groupName The name of a group
4242
* @return Alphabetically sorted List of subgroups matching the criteria
4343
*/
44-
private fun getAvailableSubGroups(agencyId: String, groupName: String): List<LocationGroup> {
44+
private fun getAvailableSubGroups(prisonCode: String, groupName: String): List<LocationGroup> {
4545
val fullKeys = groupsProperties.stringPropertyNames()
46-
val agencyAndGroupName = "${agencyId}_${groupName}_"
46+
val prisonCodeAndGroupName = "${prisonCode}_${groupName}_"
4747
return fullKeys.asSequence()
48-
.filter { it.startsWith(agencyAndGroupName) }
49-
.map { it.substring(agencyAndGroupName.length) }
48+
.filter { it.startsWith(prisonCodeAndGroupName) }
49+
.map { it.substring(prisonCodeAndGroupName.length) }
5050
.sorted()
5151
.map { LocationGroup(it, it, emptyList()) }
5252
.toList()
5353
}
5454

55-
override fun locationGroupFilter(agencyId: String, groupName: String): Predicate<Location> {
56-
val patterns = groupsProperties.getProperty("${agencyId}_$groupName")
57-
?: throw EntityNotFoundException("Group $groupName does not exist for agencyId $agencyId.")
55+
override fun locationGroupFilter(prisonCode: String, groupName: String): Predicate<Location> {
56+
val patterns = groupsProperties.getProperty("${prisonCode}_$groupName")
57+
?: throw EntityNotFoundException("Group $groupName does not exist for prisonCode $prisonCode.")
5858
val patternStrings = patterns.split(",")
5959
return patternStrings.asSequence()
6060
.map(Pattern::compile)

src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsactivitiesmanagementapi/service/LocationGroupService.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ import uk.gov.justice.digital.hmpps.hmppsactivitiesmanagementapi.client.prisonap
55
import java.util.function.Predicate
66

77
interface LocationGroupService {
8-
fun getLocationGroups(agencyId: String): List<LocationGroup>?
9-
fun locationGroupFilter(agencyId: String, groupName: String): Predicate<Location>
8+
fun getLocationGroups(prisonCode: String): List<LocationGroup>
9+
fun locationGroupFilter(prisonCode: String, groupName: String): Predicate<Location>
1010
}

src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsactivitiesmanagementapi/service/LocationGroupServiceSelector.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@ class LocationGroupServiceSelector(
1414
@Value("\${prison-locations.using-regex-config}") private val prisonsUsingRegexConfig: String,
1515
) : LocationGroupService {
1616

17-
override fun getLocationGroups(agencyId: String): List<LocationGroup>? = if (isUsingRegexConfig(agencyId)) {
18-
overrideService.getLocationGroups(agencyId)
17+
override fun getLocationGroups(prisonCode: String): List<LocationGroup> = if (isUsingRegexConfig(prisonCode)) {
18+
overrideService.getLocationGroups(prisonCode)
1919
} else {
20-
defaultService.getLocationGroups(agencyId)
20+
defaultService.getLocationGroups(prisonCode)
2121
}
2222

23-
override fun locationGroupFilter(agencyId: String, groupName: String): Predicate<Location> = if (isUsingRegexConfig(agencyId)) {
24-
overrideService.locationGroupFilter(agencyId, groupName)
23+
override fun locationGroupFilter(prisonCode: String, groupName: String): Predicate<Location> = if (isUsingRegexConfig(prisonCode)) {
24+
overrideService.locationGroupFilter(prisonCode, groupName)
2525
} else {
26-
defaultService.locationGroupFilter(agencyId, groupName)
26+
defaultService.locationGroupFilter(prisonCode, groupName)
2727
}
2828

29-
private fun isUsingRegexConfig(agencyId: String): Boolean = prisonsUsingRegexConfig.split(",").contains(agencyId)
29+
private fun isUsingRegexConfig(prisonCode: String): Boolean = prisonsUsingRegexConfig.split(",").contains(prisonCode)
3030
}

src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsactivitiesmanagementapi/client/locationsinsideprison/api/LocationsInsidePrisonAPIClientTest.kt

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ import org.junit.jupiter.api.DisplayName
99
import org.junit.jupiter.api.Nested
1010
import org.junit.jupiter.api.Test
1111
import org.junit.jupiter.api.assertThrows
12+
import org.springframework.http.HttpStatus
1213
import org.springframework.web.reactive.function.client.WebClient
1314
import org.springframework.web.reactive.function.client.WebClientRequestException
15+
import org.springframework.web.reactive.function.client.WebClientResponseException
1416
import uk.gov.justice.digital.hmpps.hmppsactivitiesmanagementapi.client.RetryApiService
1517
import uk.gov.justice.digital.hmpps.hmppsactivitiesmanagementapi.client.locationsinsideprison.model.ServiceUsingLocationDto.ServiceType
1618
import uk.gov.justice.digital.hmpps.hmppsactivitiesmanagementapi.helpers.dpsLocation
@@ -64,7 +66,7 @@ class LocationsInsidePrisonAPIClientTest {
6466
}
6567

6668
@Test
67-
fun `should return locations for for service type`() {
69+
fun `should return locations for service type`() {
6870
val mockLocations = mockServer.stubLocationsForServiceType()
6971

7072
runBlocking {
@@ -103,4 +105,39 @@ class LocationsInsidePrisonAPIClientTest {
103105
}
104106
}
105107
}
108+
109+
@Test
110+
fun `getLocationGroups - success`(): Unit = runBlocking {
111+
val prisonCode = "MDI"
112+
mockServer.stubGetLocationGroups(prisonCode, "locationsinsideprisonapi/location-groups-1.json")
113+
val locationGroups = apiClient.getLocationGroups(prisonCode)
114+
115+
assertThat(locationGroups).hasSize(1)
116+
117+
locationGroups.first().apply {
118+
assertThat(name).isEqualTo("Group Name")
119+
assertThat(key).isEqualTo("Group key")
120+
children.first().apply {
121+
assertThat(name).isEqualTo("Child Group Name")
122+
assertThat(key).isEqualTo("Child Group key")
123+
assertThat(children).isEmpty()
124+
}
125+
}
126+
127+
assertThat(locationGroups.first().children).hasSize(1)
128+
}
129+
130+
@Test
131+
fun `getLocationGroups - not found`(): Unit = runBlocking {
132+
val prisonCode = "LEI"
133+
mockServer.stubGetLocationGroupsNotFound(prisonCode)
134+
135+
val exception = assertThrows<WebClientResponseException.NotFound> {
136+
apiClient.getLocationGroups(prisonCode)
137+
}
138+
139+
assertThat(exception.statusCode).isEqualTo(HttpStatus.NOT_FOUND)
140+
assertThat(exception.message).contains("404 Not Found from GET http://localhost:8093/locations/prison/LEI/groups")
141+
assertThat(exception.responseBodyAsString).contains("Location groups not found for prison")
142+
}
106143
}

src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsactivitiesmanagementapi/client/prisonapi/api/PrisonApiClientTest.kt

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -241,24 +241,6 @@ class PrisonApiClientTest {
241241
.hasMessage("404 Not Found from GET http://localhost:8999/api/agencies/LEI/locations/type/CELL")
242242
}
243243

244-
@Test
245-
fun `getLocationGroups - success`() {
246-
val agencyId = "MDI"
247-
prisonApiMockServer.stubGetLocationGroups(agencyId, "prisonapi/location-groups-1.json")
248-
val locationGroups = prisonApiClient.getLocationGroups(agencyId).block()!!
249-
assertThat(locationGroups).hasSize(1)
250-
assertThat(locationGroups.first().children.first().name).isEqualTo("Child Group Name")
251-
}
252-
253-
@Test
254-
fun `getLocationGroups - not found`() {
255-
val agencyId = "LEI"
256-
prisonApiMockServer.stubGetLocationGroupsNotFound(agencyId)
257-
assertThatThrownBy { prisonApiClient.getLocationGroups(agencyId).block() }
258-
.isInstanceOf(WebClientResponseException::class.java)
259-
.hasMessage("404 Not Found from GET http://localhost:8999/api/agencies/LEI/locations/groups")
260-
}
261-
262244
@Test
263245
fun `getStudyArea - success`() {
264246
prisonApiMockServer.stubGetReferenceCode("STUDY_AREA", "ENGLA", "prisonapi/study-area-code-ENGLA.json")

0 commit comments

Comments
 (0)