feat(cw2): /api/v1/dronesWithCooling impl
This commit is contained in:
parent
2b9b668a2f
commit
3c96f9d5af
10 changed files with 206 additions and 27 deletions
|
|
@ -0,0 +1,31 @@
|
||||||
|
meta {
|
||||||
|
name: dronesWithCooling -> false
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{API_BASE}}/dronesWithCooling/false
|
||||||
|
body: none
|
||||||
|
auth: inherit
|
||||||
|
}
|
||||||
|
|
||||||
|
tests {
|
||||||
|
test("Status code is 200", function() {
|
||||||
|
expect(res.status).to.equal(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Response body is a JSON array", function() {
|
||||||
|
expect(res.getBody()).to.be.an('array');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Array is not empty and contains numbers", function() {
|
||||||
|
const data = res.getBody();
|
||||||
|
expect(data[0]).to.be.a('number'); // data should be in number
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
settings {
|
||||||
|
encodeUrl: true
|
||||||
|
timeout: 0
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
meta {
|
||||||
|
name: dronesWithCooling -> illegal
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{API_BASE}}/dronesWithCooling/illegal
|
||||||
|
body: none
|
||||||
|
auth: inherit
|
||||||
|
}
|
||||||
|
|
||||||
|
tests {
|
||||||
|
test("Status code is 400", function() {
|
||||||
|
expect(res.status).to.equal(400);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
settings {
|
||||||
|
encodeUrl: true
|
||||||
|
timeout: 0
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
meta {
|
||||||
|
name: dronesWithCooling -> true
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{API_BASE}}/dronesWithCooling/true
|
||||||
|
body: none
|
||||||
|
auth: inherit
|
||||||
|
}
|
||||||
|
|
||||||
|
tests {
|
||||||
|
test("Status code is 200", function() {
|
||||||
|
expect(res.status).to.equal(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Response body is a JSON array", function() {
|
||||||
|
expect(res.getBody()).to.be.an('array');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Array is not empty and contains numbers", function() {
|
||||||
|
const data = res.getBody();
|
||||||
|
expect(data[0]).to.be.a('number'); // data should be in number
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
settings {
|
||||||
|
encodeUrl: true
|
||||||
|
timeout: 0
|
||||||
|
}
|
||||||
8
ilp-cw-api/[GET] dronesWithCooling/folder.bru
Normal file
8
ilp-cw-api/[GET] dronesWithCooling/folder.bru
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
meta {
|
||||||
|
name: [GET] dronesWithCooling
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
auth {
|
||||||
|
mode: inherit
|
||||||
|
}
|
||||||
9
ilp-cw-api/bruno.json
Normal file
9
ilp-cw-api/bruno.json
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"version": "1",
|
||||||
|
"name": "ILP CW API Collection",
|
||||||
|
"type": "collection",
|
||||||
|
"ignore": [
|
||||||
|
"node_modules",
|
||||||
|
".git"
|
||||||
|
]
|
||||||
|
}
|
||||||
4
ilp-cw-api/collection.bru
Normal file
4
ilp-cw-api/collection.bru
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
vars:pre-request {
|
||||||
|
BASE_URL: http://localhost:8080
|
||||||
|
API_BASE: {{BASE_URL}}/api/v1
|
||||||
|
}
|
||||||
|
|
@ -16,7 +16,7 @@ import io.github.js0ny.ilp_coursework.service.GpsCalculationService;
|
||||||
/**
|
/**
|
||||||
* Main REST Controller for the ILP Coursework 1 application.
|
* Main REST Controller for the ILP Coursework 1 application.
|
||||||
* <p>
|
* <p>
|
||||||
* This class handles all incoming HTTP requests for the API under {@code /api/v1} path.
|
* This class handles incoming HTTP requests for the API under {@code /api/v1} path (defined in CW1)
|
||||||
* This is responsible for mapping requests to the appropriate service method and returning the results as responses.
|
* This is responsible for mapping requests to the appropriate service method and returning the results as responses.
|
||||||
* The business logic is delegated to {@link GpsCalculationService}
|
* The business logic is delegated to {@link GpsCalculationService}
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -8,43 +8,50 @@ import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main Rest Controller for the ILP Coursework 2 application.
|
||||||
|
* <p>
|
||||||
|
* This class handles incoming HTTP requests for the API under {@code /api/v1} path (defined in CW2)
|
||||||
|
* The business logic is delegated to {@link DroneInfoService}
|
||||||
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1")
|
@RequestMapping("/api/v1")
|
||||||
public class DroneController {
|
public class DroneController {
|
||||||
private final DroneInfoService droneService;
|
private final DroneInfoService droneService;
|
||||||
private final String baseUrl;
|
|
||||||
private final RestTemplate restTemplate = new RestTemplate();
|
private final RestTemplate restTemplate = new RestTemplate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor of the {@code DroneController} with the business logic dependency {@code DroneInfoService}
|
||||||
|
* <p>
|
||||||
|
* We handle the {@code baseUrl} here. Use a predefined URL if the environment variable {@code ILP_ENDPOINT}
|
||||||
|
* is not given.
|
||||||
|
*
|
||||||
|
* @param droneService The service component that contains all business logic
|
||||||
|
*/
|
||||||
public DroneController(DroneInfoService droneService) {
|
public DroneController(DroneInfoService droneService) {
|
||||||
this.droneService = droneService;
|
this.droneService = droneService;
|
||||||
String baseUrl = System.getenv("ILP_ENDPOINT");
|
|
||||||
if (baseUrl == null || baseUrl.isBlank()) {
|
|
||||||
this.baseUrl = "https://ilp-rest-2025-bvh6e9hschfagrgy.ukwest-01.azurewebsites.net/";
|
|
||||||
} else {
|
|
||||||
if (!baseUrl.endsWith("/")) {
|
|
||||||
baseUrl += "/";
|
|
||||||
}
|
|
||||||
this.baseUrl = baseUrl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles GET requests to retrieve an array of drones (identified by id) that has the capability of cooling
|
||||||
|
*
|
||||||
|
* @param state The path variable that indicates the return should have or not have the capability
|
||||||
|
* @return An array of drone id with cooling capability.
|
||||||
|
*/
|
||||||
@GetMapping("/dronesWithCooling/{state}")
|
@GetMapping("/dronesWithCooling/{state}")
|
||||||
|
public int[] getDronesWithCoolingCapability(@PathVariable boolean state) {
|
||||||
public int[] getDronesWithCoolingAbility(@PathVariable boolean state) {
|
return droneService.dronesWithCooling(state);
|
||||||
|
|
||||||
String droneUrl = baseUrl + "drones";
|
|
||||||
|
|
||||||
DroneDto[] drones = restTemplate.getForObject(droneUrl, DroneDto[].class);
|
|
||||||
|
|
||||||
if (drones == null) {
|
|
||||||
return new int[]{};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Arrays.stream(drones).
|
// @GetMapping("/droneDetails/{id}")
|
||||||
filter(drone -> drone.capability().cooling() == state).
|
// public DroneDto getDroneDetail(@PathVariable int id) {
|
||||||
mapToInt(drone -> Integer.parseInt(String.valueOf(drone.id()))).
|
// String droneUrl = baseUrl + "drones";
|
||||||
toArray();
|
//
|
||||||
}
|
// DroneDto[] drones = restTemplate.getForObject(droneUrl, DroneDto[].class);
|
||||||
|
//
|
||||||
|
// return new DroneDto();
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
@PostMapping("queryAvailableDrones")
|
@PostMapping("queryAvailableDrones")
|
||||||
public int queryAvailableDrones() {
|
public int queryAvailableDrones() {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,6 @@ package io.github.js0ny.ilp_coursework.data;
|
||||||
*/
|
*/
|
||||||
public record DroneDto(
|
public record DroneDto(
|
||||||
String name,
|
String name,
|
||||||
int id,
|
String id,
|
||||||
DroneCapabilityDto capability) {
|
DroneCapabilityDto capability) {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,73 @@
|
||||||
package io.github.js0ny.ilp_coursework.service;
|
package io.github.js0ny.ilp_coursework.service;
|
||||||
|
|
||||||
|
import io.github.js0ny.ilp_coursework.data.DroneDto;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
import org.springframework.web.util.UriBuilder;
|
||||||
|
import org.springframework.web.util.UriComponentsBuilder;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class DroneInfoService {
|
public class DroneInfoService {
|
||||||
|
|
||||||
|
private final String baseUrl;
|
||||||
|
private final String dronesEndpoint = "drones";
|
||||||
|
|
||||||
|
private final RestTemplate restTemplate = new RestTemplate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor, handles the base url here.
|
||||||
|
*/
|
||||||
|
public DroneInfoService() {
|
||||||
|
|
||||||
|
String baseUrl = System.getenv("ILP_ENDPOINT");
|
||||||
|
if (baseUrl == null || baseUrl.isBlank()) {
|
||||||
|
this.baseUrl = "https://ilp-rest-2025-bvh6e9hschfagrgy.ukwest-01.azurewebsites.net/";
|
||||||
|
} else {
|
||||||
|
// Defensive: Add '/' to the end of the URL
|
||||||
|
if (!baseUrl.endsWith("/")) {
|
||||||
|
baseUrl += "/";
|
||||||
|
}
|
||||||
|
this.baseUrl = baseUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an array of ids of drones with/without cooling capability
|
||||||
|
*
|
||||||
|
* @param state determines the capability filtering
|
||||||
|
* @return if {@code state} is true, return ids of drones with cooling capability, else without cooling
|
||||||
|
*/
|
||||||
|
public int[] dronesWithCooling(boolean state) {
|
||||||
|
URI droneUrl = URI.create(baseUrl).resolve(dronesEndpoint);
|
||||||
|
|
||||||
|
DroneDto[] drones = restTemplate.getForObject(droneUrl, DroneDto[].class);
|
||||||
|
|
||||||
|
if (drones == null) {
|
||||||
|
return new int[]{};
|
||||||
|
}
|
||||||
|
|
||||||
|
return Arrays.stream(drones).
|
||||||
|
filter(drone -> drone.capability().cooling() == state).
|
||||||
|
mapToInt(drone -> Integer.parseInt(drone.id())).
|
||||||
|
toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: This is function is WIP
|
||||||
|
public Stream<DroneDto> droneDetail(int id) {
|
||||||
|
String droneUrl = baseUrl + dronesEndpoint;
|
||||||
|
|
||||||
|
DroneDto[] drones = restTemplate.getForObject(droneUrl, DroneDto[].class);
|
||||||
|
|
||||||
|
if (drones == null) {
|
||||||
|
throw new IllegalArgumentException("drone with that ID cannot be found");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Arrays.stream(drones).
|
||||||
|
filter(drone -> Integer.parseInt(String.valueOf(drone.id())) == id);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue