feat(queryAsPath): implement endpoints

This commit is contained in:
js0ny 2025-11-21 19:26:38 +00:00
parent 2016f35dcb
commit 4de3f712d2
14 changed files with 295 additions and 9 deletions

View file

@ -29,6 +29,8 @@
podman
podman-compose
newman
gron
fx
];
shellHook = ''
export JAVA_HOME=${pkgs.jdk21}

View file

@ -19,9 +19,9 @@ tests {
expect(res.getBody()).to.be.an('array');
});
test("Array is not empty and contains numbers", function() {
test("Array is not empty and contains Strings", function() {
const data = res.getBody();
expect(data[0]).to.be.a('number'); // data should be in number
expect(data[0]).to.be.a('string'); // data should be in string
});
}

View file

@ -19,9 +19,9 @@ tests {
expect(res.getBody()).to.be.an('array');
});
test("Array is not empty and contains numbers", function() {
test("Array is not empty and contains String", function() {
const data = res.getBody();
expect(data[0]).to.be.a('number'); // data should be in number
expect(data[0]).to.be.a('string'); // data should be in String
});
}

View file

@ -0,0 +1,16 @@
meta {
name: null should return 200
type: http
seq: 4
}
get {
url: {{API_BASE}}/dronesWithCooling/null
body: none
auth: inherit
}
settings {
encodeUrl: true
timeout: 0
}

View file

@ -0,0 +1,35 @@
meta {
name: capacity = 4
type: http
seq: 3
}
get {
url: {{API_BASE}}/queryAsPath/capacity/4
body: none
auth: inherit
}
assert {
res.body: length 2
}
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 Strings", function() {
const data = res.getBody();
expect(data[0]).to.be.a('string'); // data should be in string
});
}
settings {
encodeUrl: true
timeout: 0
}

View file

@ -0,0 +1,35 @@
meta {
name: capacity = 8.0
type: http
seq: 2
}
get {
url: {{API_BASE}}/queryAsPath/capacity/8.0
body: none
auth: inherit
}
assert {
res.body: length 4
}
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 Strings", function() {
const data = res.getBody();
expect(data[0]).to.be.a('string'); // data should be in string
});
}
settings {
encodeUrl: true
timeout: 0
}

View file

@ -0,0 +1,35 @@
meta {
name: capacity = 8
type: http
seq: 1
}
get {
url: {{API_BASE}}/queryAsPath/capacity/8
body: none
auth: inherit
}
assert {
res.body: length 4
}
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 Strings", function() {
const data = res.getBody();
expect(data[0]).to.be.a('string'); // data should be in string
});
}
settings {
encodeUrl: true
timeout: 0
}

View file

@ -0,0 +1,35 @@
meta {
name: cooling = false
type: http
seq: 5
}
get {
url: {{API_BASE}}/queryAsPath/cooling/false
body: none
auth: inherit
}
assert {
res.body: length 6
}
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 Strings", function() {
const data = res.getBody();
expect(data[0]).to.be.a('string'); // data should be in string
});
}
settings {
encodeUrl: true
timeout: 0
}

View file

@ -0,0 +1,8 @@
meta {
name: [GET] queryAsPath
seq: 3
}
auth {
mode: inherit
}

View file

@ -0,0 +1,35 @@
meta {
name: heating = true
type: http
seq: 4
}
get {
url: {{API_BASE}}/queryAsPath/heating/true
body: none
auth: inherit
}
assert {
res.body: length 7
}
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 Strings", function() {
const data = res.getBody();
expect(data[0]).to.be.a('string'); // data should be in string
});
}
settings {
encodeUrl: true
timeout: 0
}

View file

@ -0,0 +1,27 @@
meta {
name: invalid = null
type: http
seq: 7
}
get {
url: {{API_BASE}}/queryAsPath/invalid/null
body: none
auth: inherit
}
assert {
res.status: eq 200
}
tests {
test("Status code is 200", function() {
expect(res.status).to.equal(200);
});
}
settings {
encodeUrl: true
timeout: 0
}

View file

@ -0,0 +1,36 @@
meta {
name: maxMoves = 1000
type: http
seq: 6
}
get {
url: {{API_BASE}}/queryAsPath/maxMoves/1000
body: none
auth: inherit
}
assert {
res.body: length 4
res.status : eq 200
}
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 Strings", function() {
const data = res.getBody();
expect(data[0]).to.be.a('string'); // data should be in string
});
}
settings {
encodeUrl: true
timeout: 0
}

View file

@ -56,7 +56,7 @@ public class DroneController {
*
* @param id The id of the drone to be queried.
* @return 200 with {@link DroneDto}-style json if success, 404 if {@code id}
* not found, 400 otherwise
* not found, 400 otherwise
*/
@GetMapping("/droneDetails/{id}")
public ResponseEntity<DroneDto> getDroneDetail(@PathVariable String id) {
@ -68,6 +68,14 @@ public class DroneController {
}
}
/**
* Handles GET requests to retrieve an array of drone ids that
* {@code capability.attrName = attrVal}
*
* @param attrName The name of the attribute to be queried
* @param attrVal The value of the attribute to be queried
* @return An array of drone id that matches the attribute name and value
*/
@GetMapping("/queryAsPath/{attrName}/{attrVal}")
public String[] getIdByAttrMap(
@PathVariable String attrName,
@ -77,17 +85,17 @@ public class DroneController {
@PostMapping("/query")
public int[] getIdByAttrMapPost(@RequestBody AttrComparatorDto[] attrComparators) {
return new int[] {};
return new int[]{};
}
@PostMapping("/queryAvailableDrones")
public int[] queryAvailableDrones(@RequestBody MedDispathRecDto[] records) {
return new int[] {};
return new int[]{};
}
@PostMapping("/calcDeliveryPath")
public DeliveryPathDto calculateDeliveryPath(@RequestBody MedDispathRecDto[] record) {
return new DeliveryPathDto(0.0f, 0, new DronePathDto[] {});
return new DeliveryPathDto(0.0f, 0, new DronePathDto[]{});
}
@PostMapping("/calcDeliveryPathAsGeoJson")

View file

@ -1,8 +1,10 @@
package io.github.js0ny.ilp_coursework.service;
import io.github.js0ny.ilp_coursework.data.DroneDto;
import java.net.URI;
import java.util.Arrays;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@ -96,6 +98,7 @@ public class DroneInfoService {
*/
public String[] dronesWithAttribute(String attrName, String attrVal) {
URI droneUrl = URI.create(baseUrl).resolve(dronesEndpoint);
// This is required to make sure the response is valid
DroneDto[] drones = restTemplate.getForObject(
droneUrl,
DroneDto[].class);
@ -113,6 +116,7 @@ public class DroneInfoService {
JsonNode node = mapper.valueToTree(drone);
JsonNode attrNode = node.findValue(attrName);
if (attrNode != null) {
// Manually handle different types of JsonNode
return isValueMatched(attrNode, attrVal);
} else {
return false;
@ -122,6 +126,14 @@ public class DroneInfoService {
.toArray(String[]::new);
}
/**
* Helper for dynamic querying, to compare the json value with given value in
* {@code String}.
*
* @param node The {@code JsonNode} to be compared
* @param attrVal The Value passed, in {@code String}
* @return {@code true} if given values are equal, otherwise false.
*/
private boolean isValueMatched(JsonNode node, String attrVal) {
if (node.isTextual()) {
return node.asText().equals(attrVal);
@ -136,5 +148,7 @@ public class DroneInfoService {
public int[] dronesMatchesRequirements() {
return new int[] {};
};
}
;
}