From f64470e094a4017aab42ff7d15d185a1b825b68d Mon Sep 17 00:00:00 2001 From: David Robinson <14000840+khelwood@users.noreply.github.com> Date: Wed, 9 Oct 2024 12:41:23 +0100 Subject: [PATCH 1/2] x1244 add numStored to graphql location schema Requires corresponding change in storelight --- .../sccp/stan/model/store/BasicLocation.java | 18 +++++++-- .../sccp/stan/model/store/LinkedLocation.java | 14 ++++++- .../sccp/stan/service/store/StoreService.java | 17 +++++++- src/main/resources/schema.graphqls | 4 ++ .../resources/storelight/editLocation.graphql | 5 ++- .../resources/storelight/location.graphql | 5 ++- .../resources/storelight/storeBarcode.graphql | 5 ++- src/main/resources/storelight/stored.graphql | 5 ++- .../storelight/storedBasicLocation.graphql | 2 +- .../integrationtest/TestReleaseMutation.java | 4 +- .../integrationtest/TestStoreMutations.java | 40 ++++++++++++++++++- .../sccp/stan/service/TestReleaseService.java | 2 +- .../stan/service/store/TestStoreService.java | 28 +++++++------ 13 files changed, 117 insertions(+), 32 deletions(-) diff --git a/src/main/java/uk/ac/sanger/sccp/stan/model/store/BasicLocation.java b/src/main/java/uk/ac/sanger/sccp/stan/model/store/BasicLocation.java index 0a18f66f..64fa5d92 100644 --- a/src/main/java/uk/ac/sanger/sccp/stan/model/store/BasicLocation.java +++ b/src/main/java/uk/ac/sanger/sccp/stan/model/store/BasicLocation.java @@ -15,18 +15,20 @@ public class BasicLocation { private String name; private Address address; private Integer addressIndex; + private int numStored; public BasicLocation() {} public BasicLocation(String barcode, Address address) { - this(barcode, null, address, null); + this(barcode, null, address, null, 0); } - public BasicLocation(String barcode, String name, Address address, Integer addressIndex) { + public BasicLocation(String barcode, String name, Address address, Integer addressIndex, int numStored) { this.barcode = barcode; this.name = name; this.address = address; this.addressIndex = addressIndex; + this.numStored = numStored; } public String getBarcode() { @@ -61,6 +63,15 @@ public void setAddressIndex(Integer addressIndex) { this.addressIndex = addressIndex; } + /** The number of items directly stored in this location */ + public int getNumStored() { + return this.numStored; + } + + public void setNumStored(int numStored) { + this.numStored = numStored; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -69,7 +80,8 @@ public boolean equals(Object o) { return (Objects.equals(this.barcode, that.barcode) && Objects.equals(this.name, that.name) && Objects.equals(this.address, that.address) - && Objects.equals(this.addressIndex, that.addressIndex)); + && Objects.equals(this.addressIndex, that.addressIndex) + && this.numStored==that.numStored); } @Override diff --git a/src/main/java/uk/ac/sanger/sccp/stan/model/store/LinkedLocation.java b/src/main/java/uk/ac/sanger/sccp/stan/model/store/LinkedLocation.java index a26ee45a..cc0eefb2 100644 --- a/src/main/java/uk/ac/sanger/sccp/stan/model/store/LinkedLocation.java +++ b/src/main/java/uk/ac/sanger/sccp/stan/model/store/LinkedLocation.java @@ -16,6 +16,7 @@ public class LinkedLocation { private String barcode; private String name; private Address address; + private int numStored; public String getBarcode() { return this.barcode; @@ -96,6 +97,14 @@ private static String sanitise(String string) { return string; } + public int getNumStored() { + return this.numStored; + } + + public void setNumStored(int numStored) { + this.numStored = numStored; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -106,7 +115,9 @@ public boolean equals(Object o) { protected boolean equalsLinkedLocation(LinkedLocation that) { return (Objects.equals(this.barcode, that.barcode) && Objects.equals(this.name, that.name) - && Objects.equals(this.address, that.address)); + && Objects.equals(this.address, that.address) + && this.numStored == that.numStored + ); } @Override @@ -120,6 +131,7 @@ public String toString() { .add("barcode", repr(barcode)) .add("name", repr(name)) .add("address", address) + .add("numStored", numStored) .omitNullValues() .toString(); } diff --git a/src/main/java/uk/ac/sanger/sccp/stan/service/store/StoreService.java b/src/main/java/uk/ac/sanger/sccp/stan/service/store/StoreService.java index d6047592..ff5f109f 100644 --- a/src/main/java/uk/ac/sanger/sccp/stan/service/store/StoreService.java +++ b/src/main/java/uk/ac/sanger/sccp/stan/service/store/StoreService.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.base.Charsets; import com.google.common.io.Resources; import org.apache.commons.lang3.StringUtils; @@ -269,7 +270,7 @@ public UCMap loadBasicLocationsOfItems(Collection itemBar query = query.replace("[]", objectMapper.writeValueAsString(arrayNode)); GraphQLResponse response = storelightClient.postQuery(query, null); checkErrors(response); - var objectData = response.getData(); + ObjectNode objectData = response.getData(); ArrayNode storedData = (ArrayNode) objectData.get("stored"); return makeBasicLocations(storedData); @@ -305,7 +306,8 @@ private UCMap makeBasicLocations(ArrayNode nodes) { address = Address.valueOf(addressString); } Integer addressIndex = integerFromNode(sd.get("addressIndex")); - map.put(itemBarcode, new BasicLocation(locationBarcode, locationName, address, addressIndex)); + int numStored = intFromNode(sd.get("numStored"), 0); + map.put(itemBarcode, new BasicLocation(locationBarcode, locationName, address, addressIndex, numStored)); } return map; } @@ -324,6 +326,17 @@ private static Integer integerFromNode(JsonNode node) { return (value < 0 ? null : (Integer) value); } + /** + * Reads an int from the given node. + * If the node is null or non-numeric, returns the given default value. + * @param node the node to read + * @param defaultValue the value to return if an int cannot be read + * @return the int value from the node, or the default value + */ + private static int intFromNode(JsonNode node, int defaultValue) { + return (node==null ? defaultValue : node.asInt(defaultValue)); + } + /** * Checks if the labware can be stored. * @param barcode the barcode being stored diff --git a/src/main/resources/schema.graphqls b/src/main/resources/schema.graphqls index ccb8e5d3..cdb2f0ae 100644 --- a/src/main/resources/schema.graphqls +++ b/src/main/resources/schema.graphqls @@ -902,6 +902,8 @@ type Location { direction: GridDirection """A combination of this location's name and its parents' names and barcodes.""" qualifiedNameWithFirstBarcode: String + """The number of items directly stored in this location.""" + numStored: Int! } """Information about a storage location, without links to other locations and items.""" @@ -914,6 +916,8 @@ type LinkedLocation { customName: String """The row/column address (if any) of this location in its parent location.""" address: Address + """The number of items directly stored in this location.""" + numStored: Int! } """The result of a request to empty a location.""" diff --git a/src/main/resources/storelight/editLocation.graphql b/src/main/resources/storelight/editLocation.graphql index 1c13eeb4..74c57d06 100644 --- a/src/main/resources/storelight/editLocation.graphql +++ b/src/main/resources/storelight/editLocation.graphql @@ -5,9 +5,10 @@ mutation { name address size { numRows numColumns } - children { barcode name address } + children { barcode name address numStored } stored { barcode address } - parent { barcode name address } + parent { barcode name address numStored } direction + numStored } } \ No newline at end of file diff --git a/src/main/resources/storelight/location.graphql b/src/main/resources/storelight/location.graphql index ddb9aef6..13267047 100644 --- a/src/main/resources/storelight/location.graphql +++ b/src/main/resources/storelight/location.graphql @@ -5,10 +5,11 @@ name address size { numRows numColumns} - children { barcode name address } + children { barcode name address numStored } stored { barcode address } - parent { barcode name address } + parent { barcode name address numStored } direction qualifiedNameWithFirstBarcode + numStored } } \ No newline at end of file diff --git a/src/main/resources/storelight/storeBarcode.graphql b/src/main/resources/storelight/storeBarcode.graphql index 308b867e..c75cdf69 100644 --- a/src/main/resources/storelight/storeBarcode.graphql +++ b/src/main/resources/storelight/storeBarcode.graphql @@ -8,10 +8,11 @@ mutation { name address size { numRows numColumns } - children { barcode name address } + children { barcode name address numStored } stored { barcode address } - parent { barcode name address } + parent { barcode name address numStored } direction + numStored } } } \ No newline at end of file diff --git a/src/main/resources/storelight/stored.graphql b/src/main/resources/storelight/stored.graphql index 856ef2a3..fcc838a7 100644 --- a/src/main/resources/storelight/stored.graphql +++ b/src/main/resources/storelight/stored.graphql @@ -9,11 +9,12 @@ name address size { numRows numColumns} - children { barcode name address } - parent { barcode name address } + children { barcode name address numStored } + parent { barcode name address numStored } stored { barcode address addressIndex } direction qualifiedNameWithFirstBarcode + numStored } } } diff --git a/src/main/resources/storelight/storedBasicLocation.graphql b/src/main/resources/storelight/storedBasicLocation.graphql index 0ec04149..0467c5b4 100644 --- a/src/main/resources/storelight/storedBasicLocation.graphql +++ b/src/main/resources/storelight/storedBasicLocation.graphql @@ -3,6 +3,6 @@ barcode address addressIndex - location { barcode name } + location { barcode name numStored } } } \ No newline at end of file diff --git a/src/test/java/uk/ac/sanger/sccp/stan/integrationtest/TestReleaseMutation.java b/src/test/java/uk/ac/sanger/sccp/stan/integrationtest/TestReleaseMutation.java index b39f5d60..c80a575e 100644 --- a/src/test/java/uk/ac/sanger/sccp/stan/integrationtest/TestReleaseMutation.java +++ b/src/test/java/uk/ac/sanger/sccp/stan/integrationtest/TestReleaseMutation.java @@ -109,8 +109,8 @@ public void testRelease() throws Exception { stubStorelightUnstore(mockStorelightClient); UCMap basicLocationMap = new UCMap<>(2); - basicLocationMap.put("STAN-001", new BasicLocation("STO-1", "Box 1", new Address(1,2), 4)); - basicLocationMap.put("STAN-002", new BasicLocation("STO-1", "Box 1", new Address(3,4), null)); + basicLocationMap.put("STAN-001", new BasicLocation("STO-1", "Box 1", new Address(1,2), 4, 0)); + basicLocationMap.put("STAN-002", new BasicLocation("STO-1", "Box 1", new Address(3,4), null, 0)); stubStorelightBasicLocation(mockStorelightClient, basicLocationMap); Object result = tester.post(mutation); diff --git a/src/test/java/uk/ac/sanger/sccp/stan/integrationtest/TestStoreMutations.java b/src/test/java/uk/ac/sanger/sccp/stan/integrationtest/TestStoreMutations.java index 6a910dbb..888296f1 100644 --- a/src/test/java/uk/ac/sanger/sccp/stan/integrationtest/TestStoreMutations.java +++ b/src/test/java/uk/ac/sanger/sccp/stan/integrationtest/TestStoreMutations.java @@ -92,7 +92,7 @@ public void testStore() throws Exception { List> labwareListData = chainGet(result, "data", "labwareInLocation"); assertThat(labwareListData).hasSize(1); - Map labwareData = labwareListData.get(0); + Map labwareData = labwareListData.getFirst(); assertEquals("STAN-100", labwareData.get("barcode")); assertEquals(sample.getId(), chainGet(labwareData, "slots", 0, "samples", 0, "id")); } @@ -207,6 +207,44 @@ public void testTransfer() throws Exception { verifyStorelightQuery(mockStorelightClient, List.of("store", "STAN-100", "STAN-101", "STO-5"), user.getUsername()); } + @Transactional + @Test + public void testQueryLocation() throws Exception { + ObjectMapper objectMapper = new ObjectMapper(); + ObjectNode locationNode = objectMapper.createObjectNode() + .put("barcode", "STO-A") + .put("name", "Alpha: Beta") + .putNull("address") + .put("numStored", 0) + .set("children", objectMapper.createArrayNode() + .add(objectMapper.createObjectNode() + .put("barcode", "STO-B") + .put("name", "Gamma: Delta") + .put("address", "B3") + .put("numStored", 5)) + ); + GraphQLResponse graphQLResponse = new GraphQLResponse( + objectMapper.createObjectNode().set("location", locationNode), null + ); + when(mockStorelightClient.postQuery(anyString(), any())).thenReturn(graphQLResponse); + Object response = tester.post("query { location(locationBarcode: \"STO-A\") { " + + "barcode fixedName customName address numStored " + + "children { barcode fixedName customName address numStored } } }"); + Map loc = chainGet(response, "data", "location"); + assertEquals("STO-A", loc.get("barcode")); + assertEquals("Alpha", loc.get("fixedName")); + assertEquals("Beta", loc.get("customName")); + assertNull(loc.get("address")); + assertEquals(0, loc.get("numStored")); + assertThat((List) loc.get("children")).hasSize(1); + Map child = chainGet(loc, "children", 0); + assertEquals("STO-B", child.get("barcode")); + assertEquals("Gamma", child.get("fixedName")); + assertEquals("Delta", child.get("customName")); + assertEquals("B3", child.get("address")); + assertEquals(5, child.get("numStored")); + } + @Transactional @Test public void testStoragePath() throws Exception { diff --git a/src/test/java/uk/ac/sanger/sccp/stan/service/TestReleaseService.java b/src/test/java/uk/ac/sanger/sccp/stan/service/TestReleaseService.java index b74260b8..80ab04cc 100644 --- a/src/test/java/uk/ac/sanger/sccp/stan/service/TestReleaseService.java +++ b/src/test/java/uk/ac/sanger/sccp/stan/service/TestReleaseService.java @@ -508,7 +508,7 @@ public void testRecordRelease(String locBarcode, Address address, Integer addres if (locBarcode==null) { loc = null; } else { - loc = new BasicLocation(locBarcode, expectedName, address, addressIndex); + loc = new BasicLocation(locBarcode, expectedName, address, addressIndex, 0); } final int releaseId = 10; diff --git a/src/test/java/uk/ac/sanger/sccp/stan/service/store/TestStoreService.java b/src/test/java/uk/ac/sanger/sccp/stan/service/store/TestStoreService.java index d7cf1dcc..71d1997d 100644 --- a/src/test/java/uk/ac/sanger/sccp/stan/service/store/TestStoreService.java +++ b/src/test/java/uk/ac/sanger/sccp/stan/service/store/TestStoreService.java @@ -158,10 +158,10 @@ public void testStoreBarcode(boolean withAddress) throws IOException { verifyQueryMatches("mutation { storeBarcode(barcode: \""+itemBarcode+"\", location: {barcode: \"" + locationBarcode+"\"}, address: " + quote(address) + ") { barcode address location " + "{ id barcode name address size { numRows numColumns } " + - "children { barcode name address } " + + "children { barcode name address numStored } " + "stored { barcode address }" + - "parent { barcode name address }" + - "direction}}}"); + "parent { barcode name address numStored }" + + "direction numStored}}}"); verify(service).checkErrors(response); assertEquals(item, result); } @@ -361,10 +361,10 @@ public void testSetLocationCustomName(String name, String oldCustomName, String verifyQueryMatches("mutation { editLocation(location:{barcode:"+json(barcode) +"}, change: {name:"+json(alteredLocation.getName())+"}) {" + "id barcode name address size {numRows numColumns } " + - "children { barcode name address }" + + "children { barcode name address numStored }" + "stored { barcode address } " + - "parent { barcode name address }" + - "direction }}"); + "parent { barcode name address numStored }" + + "direction numStored }}"); verify(service).checkErrors(response); assertEquals(alteredLocation, result); assertEquals(newCustomName, alteredLocation.getCustomName()); @@ -402,12 +402,13 @@ public void testGetLocation() throws IOException { " barcode" + " name" + " address" + - " size { numRows numColumns}" + - " children { barcode name address }" + + " size { numRows numColumns }" + + " children { barcode name address numStored }" + " stored { barcode address }" + - " parent { barcode name address }" + + " parent { barcode name address numStored }" + " direction" + " qualifiedNameWithFirstBarcode" + + " numStored" + " }}", null); @@ -495,11 +496,12 @@ public void testGetStored() throws IOException { " name" + " address" + " size { numRows numColumns}" + - " children { barcode name address }" + - " parent { barcode name address }" + + " children { barcode name address numStored }" + + " parent { barcode name address numStored }" + " stored { barcode address addressIndex }" + " direction" + " qualifiedNameWithFirstBarcode" + + " numStored" + " }}}", null); @@ -542,7 +544,7 @@ public void testLoadBasicLocationsOfItems(boolean succeeds) throws IOException { when(mockClient.postQuery(anyString(), isNull())).thenReturn(response); locations = service.loadBasicLocationsOfItems(stanBarcodes); assertThat(locations).hasSize(2); - assertEquals(new BasicLocation("STO-1", "Box 1", new Address(1,2), 4), locations.get("STAN-1")); + assertEquals(new BasicLocation("STO-1", "Box 1", new Address(1,2), 4, 0), locations.get("STAN-1")); assertEquals(new BasicLocation("STO-2", null), locations.get("STAN-2")); assertNull(locations.get("STAN-3")); verify(service).checkErrors(response); @@ -558,7 +560,7 @@ public void testLoadBasicLocationsOfItems(boolean succeeds) throws IOException { " barcode" + " address" + " addressIndex" + - " location { barcode name }" + + " location { barcode name numStored }" + "}}", null); } From 631095adcbf9074e9dd9e5d601b3af15d742b87f Mon Sep 17 00:00:00 2001 From: David Robinson <14000840+khelwood@users.noreply.github.com> Date: Thu, 17 Oct 2024 17:02:47 +0100 Subject: [PATCH 2/2] x1244: add leaf: boolean to location graphql --- .../sccp/stan/model/store/BasicLocation.java | 24 ++++++++++++++--- .../sccp/stan/model/store/LinkedLocation.java | 17 ++++++++++++ .../sccp/stan/service/store/StoreService.java | 3 ++- src/main/resources/schema.graphqls | 4 +++ .../resources/storelight/editLocation.graphql | 5 ++-- .../resources/storelight/location.graphql | 5 ++-- .../resources/storelight/storeBarcode.graphql | 5 ++-- src/main/resources/storelight/stored.graphql | 5 ++-- .../storelight/storedBasicLocation.graphql | 2 +- .../integrationtest/TestReleaseMutation.java | 4 +-- .../integrationtest/TestStoreMutations.java | 18 +++++++++---- .../sccp/stan/service/TestReleaseService.java | 2 +- .../stan/service/store/TestStoreService.java | 26 ++++++++++--------- 13 files changed, 87 insertions(+), 33 deletions(-) diff --git a/src/main/java/uk/ac/sanger/sccp/stan/model/store/BasicLocation.java b/src/main/java/uk/ac/sanger/sccp/stan/model/store/BasicLocation.java index 64fa5d92..e06e6df3 100644 --- a/src/main/java/uk/ac/sanger/sccp/stan/model/store/BasicLocation.java +++ b/src/main/java/uk/ac/sanger/sccp/stan/model/store/BasicLocation.java @@ -1,5 +1,6 @@ package uk.ac.sanger.sccp.stan.model.store; +import com.fasterxml.jackson.annotation.JsonIgnore; import uk.ac.sanger.sccp.stan.model.Address; import java.util.Objects; @@ -16,14 +17,15 @@ public class BasicLocation { private Address address; private Integer addressIndex; private int numStored; + private int numChildren; public BasicLocation() {} public BasicLocation(String barcode, Address address) { - this(barcode, null, address, null, 0); + this(barcode, null, address, null, 0, 0); } - public BasicLocation(String barcode, String name, Address address, Integer addressIndex, int numStored) { + public BasicLocation(String barcode, String name, Address address, Integer addressIndex, int numStored, int numChildren) { this.barcode = barcode; this.name = name; this.address = address; @@ -72,6 +74,20 @@ public void setNumStored(int numStored) { this.numStored = numStored; } + /** The number of locations directly inside this location */ + public int getNumChildren() { + return this.numChildren; + } + + public void setNumChildren(int numChildren) { + this.numChildren = numChildren; + } + + @JsonIgnore + public boolean isLeaf() { + return getNumChildren() == 0; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -81,7 +97,9 @@ public boolean equals(Object o) { && Objects.equals(this.name, that.name) && Objects.equals(this.address, that.address) && Objects.equals(this.addressIndex, that.addressIndex) - && this.numStored==that.numStored); + && this.numStored==that.numStored + && this.numChildren==that.numChildren + ); } @Override diff --git a/src/main/java/uk/ac/sanger/sccp/stan/model/store/LinkedLocation.java b/src/main/java/uk/ac/sanger/sccp/stan/model/store/LinkedLocation.java index cc0eefb2..6085cc04 100644 --- a/src/main/java/uk/ac/sanger/sccp/stan/model/store/LinkedLocation.java +++ b/src/main/java/uk/ac/sanger/sccp/stan/model/store/LinkedLocation.java @@ -1,5 +1,6 @@ package uk.ac.sanger.sccp.stan.model.store; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.google.common.base.MoreObjects; import uk.ac.sanger.sccp.stan.model.Address; @@ -17,6 +18,7 @@ public class LinkedLocation { private String name; private Address address; private int numStored; + private int numChildren; public String getBarcode() { return this.barcode; @@ -105,6 +107,19 @@ public void setNumStored(int numStored) { this.numStored = numStored; } + public int getNumChildren() { + return this.numChildren; + } + + public void setNumChildren(int numChildren) { + this.numChildren = numChildren; + } + + @JsonIgnore + public boolean isLeaf() { + return getNumChildren() == 0; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -117,6 +132,7 @@ protected boolean equalsLinkedLocation(LinkedLocation that) { && Objects.equals(this.name, that.name) && Objects.equals(this.address, that.address) && this.numStored == that.numStored + && this.numChildren == that.numChildren ); } @@ -132,6 +148,7 @@ public String toString() { .add("name", repr(name)) .add("address", address) .add("numStored", numStored) + .add("numChildren", numChildren) .omitNullValues() .toString(); } diff --git a/src/main/java/uk/ac/sanger/sccp/stan/service/store/StoreService.java b/src/main/java/uk/ac/sanger/sccp/stan/service/store/StoreService.java index ff5f109f..a3ba2735 100644 --- a/src/main/java/uk/ac/sanger/sccp/stan/service/store/StoreService.java +++ b/src/main/java/uk/ac/sanger/sccp/stan/service/store/StoreService.java @@ -307,7 +307,8 @@ private UCMap makeBasicLocations(ArrayNode nodes) { } Integer addressIndex = integerFromNode(sd.get("addressIndex")); int numStored = intFromNode(sd.get("numStored"), 0); - map.put(itemBarcode, new BasicLocation(locationBarcode, locationName, address, addressIndex, numStored)); + int numChildren = intFromNode(sd.get("numChildren"), 0); + map.put(itemBarcode, new BasicLocation(locationBarcode, locationName, address, addressIndex, numStored, numChildren)); } return map; } diff --git a/src/main/resources/schema.graphqls b/src/main/resources/schema.graphqls index cdb2f0ae..7a63fbc2 100644 --- a/src/main/resources/schema.graphqls +++ b/src/main/resources/schema.graphqls @@ -904,6 +904,8 @@ type Location { qualifiedNameWithFirstBarcode: String """The number of items directly stored in this location.""" numStored: Int! + """Is this location a leaf (i.e. does not contain other locations)?""" + leaf: Boolean! } """Information about a storage location, without links to other locations and items.""" @@ -918,6 +920,8 @@ type LinkedLocation { address: Address """The number of items directly stored in this location.""" numStored: Int! + """Is this location a leaf (i.e. does not contain other locations)?""" + leaf: Boolean! } """The result of a request to empty a location.""" diff --git a/src/main/resources/storelight/editLocation.graphql b/src/main/resources/storelight/editLocation.graphql index 74c57d06..268f2701 100644 --- a/src/main/resources/storelight/editLocation.graphql +++ b/src/main/resources/storelight/editLocation.graphql @@ -5,10 +5,11 @@ mutation { name address size { numRows numColumns } - children { barcode name address numStored } + children { barcode name address numStored numChildren } stored { barcode address } - parent { barcode name address numStored } + parent { barcode name address numStored numChildren } direction numStored + numChildren } } \ No newline at end of file diff --git a/src/main/resources/storelight/location.graphql b/src/main/resources/storelight/location.graphql index 13267047..72b24ae7 100644 --- a/src/main/resources/storelight/location.graphql +++ b/src/main/resources/storelight/location.graphql @@ -5,11 +5,12 @@ name address size { numRows numColumns} - children { barcode name address numStored } + children { barcode name address numStored numChildren } stored { barcode address } - parent { barcode name address numStored } + parent { barcode name address numStored numChildren } direction qualifiedNameWithFirstBarcode numStored + numChildren } } \ No newline at end of file diff --git a/src/main/resources/storelight/storeBarcode.graphql b/src/main/resources/storelight/storeBarcode.graphql index c75cdf69..808517f0 100644 --- a/src/main/resources/storelight/storeBarcode.graphql +++ b/src/main/resources/storelight/storeBarcode.graphql @@ -8,11 +8,12 @@ mutation { name address size { numRows numColumns } - children { barcode name address numStored } + children { barcode name address numStored numChildren } stored { barcode address } - parent { barcode name address numStored } + parent { barcode name address numStored numChildren } direction numStored + numChildren } } } \ No newline at end of file diff --git a/src/main/resources/storelight/stored.graphql b/src/main/resources/storelight/stored.graphql index fcc838a7..2a36ceb2 100644 --- a/src/main/resources/storelight/stored.graphql +++ b/src/main/resources/storelight/stored.graphql @@ -9,12 +9,13 @@ name address size { numRows numColumns} - children { barcode name address numStored } - parent { barcode name address numStored } + children { barcode name address numStored numChildren } + parent { barcode name address numStored numChildren } stored { barcode address addressIndex } direction qualifiedNameWithFirstBarcode numStored + numChildren } } } diff --git a/src/main/resources/storelight/storedBasicLocation.graphql b/src/main/resources/storelight/storedBasicLocation.graphql index 0467c5b4..2691a97c 100644 --- a/src/main/resources/storelight/storedBasicLocation.graphql +++ b/src/main/resources/storelight/storedBasicLocation.graphql @@ -3,6 +3,6 @@ barcode address addressIndex - location { barcode name numStored } + location { barcode name numStored numChildren } } } \ No newline at end of file diff --git a/src/test/java/uk/ac/sanger/sccp/stan/integrationtest/TestReleaseMutation.java b/src/test/java/uk/ac/sanger/sccp/stan/integrationtest/TestReleaseMutation.java index c80a575e..d6b79e53 100644 --- a/src/test/java/uk/ac/sanger/sccp/stan/integrationtest/TestReleaseMutation.java +++ b/src/test/java/uk/ac/sanger/sccp/stan/integrationtest/TestReleaseMutation.java @@ -109,8 +109,8 @@ public void testRelease() throws Exception { stubStorelightUnstore(mockStorelightClient); UCMap basicLocationMap = new UCMap<>(2); - basicLocationMap.put("STAN-001", new BasicLocation("STO-1", "Box 1", new Address(1,2), 4, 0)); - basicLocationMap.put("STAN-002", new BasicLocation("STO-1", "Box 1", new Address(3,4), null, 0)); + basicLocationMap.put("STAN-001", new BasicLocation("STO-1", "Box 1", new Address(1,2), 4, 0, 0)); + basicLocationMap.put("STAN-002", new BasicLocation("STO-1", "Box 1", new Address(3,4), null, 0, 0)); stubStorelightBasicLocation(mockStorelightClient, basicLocationMap); Object result = tester.post(mutation); diff --git a/src/test/java/uk/ac/sanger/sccp/stan/integrationtest/TestStoreMutations.java b/src/test/java/uk/ac/sanger/sccp/stan/integrationtest/TestStoreMutations.java index 888296f1..ed060d28 100644 --- a/src/test/java/uk/ac/sanger/sccp/stan/integrationtest/TestStoreMutations.java +++ b/src/test/java/uk/ac/sanger/sccp/stan/integrationtest/TestStoreMutations.java @@ -4,6 +4,8 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.mockito.ArgumentMatchers; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; @@ -208,32 +210,37 @@ public void testTransfer() throws Exception { } @Transactional - @Test - public void testQueryLocation() throws Exception { + @ParameterizedTest + @ValueSource(booleans={false,true}) + public void testQueryLocation(boolean leaf) throws Exception { ObjectMapper objectMapper = new ObjectMapper(); ObjectNode locationNode = objectMapper.createObjectNode() .put("barcode", "STO-A") .put("name", "Alpha: Beta") .putNull("address") .put("numStored", 0) + .put("numChildren", 1) .set("children", objectMapper.createArrayNode() .add(objectMapper.createObjectNode() .put("barcode", "STO-B") .put("name", "Gamma: Delta") .put("address", "B3") - .put("numStored", 5)) + .put("numStored", 5) + .put("numChildren", leaf ? 0 : 3) + ) ); GraphQLResponse graphQLResponse = new GraphQLResponse( objectMapper.createObjectNode().set("location", locationNode), null ); when(mockStorelightClient.postQuery(anyString(), any())).thenReturn(graphQLResponse); Object response = tester.post("query { location(locationBarcode: \"STO-A\") { " + - "barcode fixedName customName address numStored " + - "children { barcode fixedName customName address numStored } } }"); + "barcode fixedName customName address numStored leaf " + + "children { barcode fixedName customName address numStored leaf } } }"); Map loc = chainGet(response, "data", "location"); assertEquals("STO-A", loc.get("barcode")); assertEquals("Alpha", loc.get("fixedName")); assertEquals("Beta", loc.get("customName")); + assertEquals(false, loc.get("leaf")); assertNull(loc.get("address")); assertEquals(0, loc.get("numStored")); assertThat((List) loc.get("children")).hasSize(1); @@ -243,6 +250,7 @@ public void testQueryLocation() throws Exception { assertEquals("Delta", child.get("customName")); assertEquals("B3", child.get("address")); assertEquals(5, child.get("numStored")); + assertEquals(leaf, child.get("leaf")); } @Transactional diff --git a/src/test/java/uk/ac/sanger/sccp/stan/service/TestReleaseService.java b/src/test/java/uk/ac/sanger/sccp/stan/service/TestReleaseService.java index 80ab04cc..3ab2ee08 100644 --- a/src/test/java/uk/ac/sanger/sccp/stan/service/TestReleaseService.java +++ b/src/test/java/uk/ac/sanger/sccp/stan/service/TestReleaseService.java @@ -508,7 +508,7 @@ public void testRecordRelease(String locBarcode, Address address, Integer addres if (locBarcode==null) { loc = null; } else { - loc = new BasicLocation(locBarcode, expectedName, address, addressIndex, 0); + loc = new BasicLocation(locBarcode, expectedName, address, addressIndex, 0, 0); } final int releaseId = 10; diff --git a/src/test/java/uk/ac/sanger/sccp/stan/service/store/TestStoreService.java b/src/test/java/uk/ac/sanger/sccp/stan/service/store/TestStoreService.java index 71d1997d..cb35078a 100644 --- a/src/test/java/uk/ac/sanger/sccp/stan/service/store/TestStoreService.java +++ b/src/test/java/uk/ac/sanger/sccp/stan/service/store/TestStoreService.java @@ -158,10 +158,10 @@ public void testStoreBarcode(boolean withAddress) throws IOException { verifyQueryMatches("mutation { storeBarcode(barcode: \""+itemBarcode+"\", location: {barcode: \"" + locationBarcode+"\"}, address: " + quote(address) + ") { barcode address location " + "{ id barcode name address size { numRows numColumns } " + - "children { barcode name address numStored } " + + "children { barcode name address numStored numChildren } " + "stored { barcode address }" + - "parent { barcode name address numStored }" + - "direction numStored}}}"); + "parent { barcode name address numStored numChildren }" + + "direction numStored numChildren }}}"); verify(service).checkErrors(response); assertEquals(item, result); } @@ -361,10 +361,10 @@ public void testSetLocationCustomName(String name, String oldCustomName, String verifyQueryMatches("mutation { editLocation(location:{barcode:"+json(barcode) +"}, change: {name:"+json(alteredLocation.getName())+"}) {" + "id barcode name address size {numRows numColumns } " + - "children { barcode name address numStored }" + + "children { barcode name address numStored numChildren }" + "stored { barcode address } " + - "parent { barcode name address numStored }" + - "direction numStored }}"); + "parent { barcode name address numStored numChildren }" + + "direction numStored numChildren }}"); verify(service).checkErrors(response); assertEquals(alteredLocation, result); assertEquals(newCustomName, alteredLocation.getCustomName()); @@ -403,12 +403,13 @@ public void testGetLocation() throws IOException { " name" + " address" + " size { numRows numColumns }" + - " children { barcode name address numStored }" + + " children { barcode name address numStored numChildren }" + " stored { barcode address }" + - " parent { barcode name address numStored }" + + " parent { barcode name address numStored numChildren }" + " direction" + " qualifiedNameWithFirstBarcode" + " numStored" + + " numChildren" + " }}", null); @@ -496,12 +497,13 @@ public void testGetStored() throws IOException { " name" + " address" + " size { numRows numColumns}" + - " children { barcode name address numStored }" + - " parent { barcode name address numStored }" + + " children { barcode name address numStored numChildren }" + + " parent { barcode name address numStored numChildren }" + " stored { barcode address addressIndex }" + " direction" + " qualifiedNameWithFirstBarcode" + " numStored" + + " numChildren" + " }}}", null); @@ -544,7 +546,7 @@ public void testLoadBasicLocationsOfItems(boolean succeeds) throws IOException { when(mockClient.postQuery(anyString(), isNull())).thenReturn(response); locations = service.loadBasicLocationsOfItems(stanBarcodes); assertThat(locations).hasSize(2); - assertEquals(new BasicLocation("STO-1", "Box 1", new Address(1,2), 4, 0), locations.get("STAN-1")); + assertEquals(new BasicLocation("STO-1", "Box 1", new Address(1,2), 4, 0, 0), locations.get("STAN-1")); assertEquals(new BasicLocation("STO-2", null), locations.get("STAN-2")); assertNull(locations.get("STAN-3")); verify(service).checkErrors(response); @@ -560,7 +562,7 @@ public void testLoadBasicLocationsOfItems(boolean succeeds) throws IOException { " barcode" + " address" + " addressIndex" + - " location { barcode name numStored }" + + " location { barcode name numStored numChildren }" + "}}", null); }