From 64c8fa76870d756b48e45c3bb8562f8033cfdb03 Mon Sep 17 00:00:00 2001
From: Lars Johansson <lars.johansson@ess.eu>
Date: Fri, 15 Jul 2022 12:08:09 +0200
Subject: [PATCH] Update signature of method to search for children of
 structure entries in REST API

Type available as query parameter instead of path parameter.
Update signature to   /children/{uuid}.
Update signature from /children/{type}/{uuid}.
---
 .../names/rest/api/v1/IStructures.java        | 10 +--
 .../rest/controller/StructuresController.java |  4 +-
 .../names/service/StructuresService.java      | 71 +++++++++++++------
 .../names/docker/StructuresDeviceGroupIT.java | 12 ++--
 .../names/docker/StructuresDeviceTypeIT.java  | 19 +++--
 .../names/docker/StructuresDisciplineIT.java  |  7 +-
 .../names/docker/StructuresSubsystemIT.java   | 25 ++++---
 .../names/docker/StructuresSystemGroupIT.java |  7 +-
 .../names/docker/StructuresSystemIT.java      | 14 ++--
 9 files changed, 108 insertions(+), 61 deletions(-)

diff --git a/src/main/java/org/openepics/names/rest/api/v1/IStructures.java b/src/main/java/org/openepics/names/rest/api/v1/IStructures.java
index 6de16ad3..cec024e9 100644
--- a/src/main/java/org/openepics/names/rest/api/v1/IStructures.java
+++ b/src/main/java/org/openepics/names/rest/api/v1/IStructures.java
@@ -101,7 +101,7 @@ public interface IStructures {
            ----------------------------------------------------------------------------------------------------
            read      GET    /structures/{type}                                - readStructures                 (Type, Status[], Boolean, String, String, String, String, String, String, String, FieldStructure, Boolean, Integer, Integer)
            read      GET    /structures/{type}/download                       - readStructuresDownload         (Type, Status[], Boolean, String, String, String, String, String, String, String, FieldStructure, Boolean, Integer, Integer)
-           read      GET    /structures/children/{type}/{uuid}                - readStructuresChildren         (Type, String, Status[], Boolean, String, String, String, String, String, FieldStructure, Boolean, Integer, Integer)
+           read      GET    /structures/children/{uuid}                       - readStructuresChildren         (String, Type, Status[], Boolean, String, String, String, String, String, FieldStructure, Boolean, Integer, Integer)
            read      GET    /structures/mnemonic/{mnemonic}                   - readStructuresMnemonic         (String, FieldStructure, Boolean, Integer, Integer, FieldStructure, Boolean, Integer, Integer)
            read      GET    /structures/mnemonicpath/{mnemonicpath}           - readStructuresMnemonicpath     (String, FieldStructure, Boolean, Integer, Integer, FieldStructure, Boolean, Integer, Integer)
            read      GET    /structures/history/{uuid}                        - readStructuresHistory          (String, Type, FieldStructure, Boolean, Integer, Integer)
@@ -424,11 +424,11 @@ public interface IStructures {
             @Parameter(in = ParameterIn.QUERY, description = "page size, limit") @RequestParam(required = false, defaultValue = DEFAULT_PAGE_SIZE) Integer pageSize);
 
     /**
-     * Find valid children structures by type and parent uuid (exact match).
+     * Find valid children structures by parent uuid (exact match).
      * Return paged list of structure elements.
      *
-     * @param type type of structure
      * @param uuid uuid
+     * @param type type of structure
      * @param statuses statuses for structures
      * @param deleted if deleted-only structures are to be included
      * (false for non-deleted-only structures, true for deleted-only structures, not used for both cases)
@@ -477,11 +477,11 @@ public interface IStructures {
                             schema = @Schema(implementation = Response.class)))
     })
     @GetMapping(
-            value = "/children/{type}/{uuid}",
+            value = "/children/{uuid}",
             produces = {"application/json"})
     public ResponsePageStructureElements readStructuresChildren(
-            @Parameter(in = ParameterIn.PATH,  description = "search by type of structure") @PathVariable("type") Type type,
             @Parameter(in = ParameterIn.PATH,  description = "search by uuid") @PathVariable("uuid") String uuid,
+            @Parameter(in = ParameterIn.QUERY, description = "search by type of structure") @RequestParam(required = false) Type type,
             @Parameter(in = ParameterIn.QUERY, description = "search by statuses") @RequestParam(required = false) Status[] statuses,
             @Parameter(in = ParameterIn.QUERY, description = "if deleted structures are to be included or not, omitted for both deleted and not deleted structures") @RequestParam(required = false) Boolean deleted,
             @Parameter(in = ParameterIn.QUERY, description = "search by name") @RequestParam(required = false) String name,
diff --git a/src/main/java/org/openepics/names/rest/controller/StructuresController.java b/src/main/java/org/openepics/names/rest/controller/StructuresController.java
index 27965f40..7712f0f4 100644
--- a/src/main/java/org/openepics/names/rest/controller/StructuresController.java
+++ b/src/main/java/org/openepics/names/rest/controller/StructuresController.java
@@ -173,11 +173,11 @@ public class StructuresController implements IStructures {
     }
 
     @Override
-    public ResponsePageStructureElements readStructuresChildren(Type type, String uuid, Status[] statuses, Boolean deleted,
+    public ResponsePageStructureElements readStructuresChildren(String uuid, Type type, Status[] statuses, Boolean deleted,
             String name, String mnemonic, String mnemonicequivalence, String mnemonicpath, String description,
             FieldStructure orderBy, Boolean isAsc, Integer page, Integer pageSize) {
         try {
-            return structuresService.readStructuresChildren(type, uuid, statuses, deleted,
+            return structuresService.readStructuresChildren(uuid, type, statuses, deleted,
                     name, mnemonic, mnemonicequivalence, mnemonicpath, description,
                     orderBy, isAsc, page, pageSize);
         } catch (ServiceException e) {
diff --git a/src/main/java/org/openepics/names/service/StructuresService.java b/src/main/java/org/openepics/names/service/StructuresService.java
index 181173c3..6c18ecb2 100644
--- a/src/main/java/org/openepics/names/service/StructuresService.java
+++ b/src/main/java/org/openepics/names/service/StructuresService.java
@@ -391,7 +391,7 @@ public class StructuresService {
         return response;
     }
 
-    public ResponsePageStructureElements readStructuresChildren(Type type, String uuid,
+    public ResponsePageStructureElements readStructuresChildren(String uuid, Type type,
             Status[] statuses, Boolean deleted, String name, String mnemonic, String mnemonicequivalence, String mnemonicpath, String description,
             FieldStructure orderBy, Boolean isAsc, Integer offset, Integer limit) {
 
@@ -402,43 +402,70 @@ public class StructuresService {
         // return
         //     structure elements for structures
 
-        LOGGER.log(Level.FINE, "readStructuresChildren, type: {0}", type);
         LOGGER.log(Level.FINE, "readStructuresChildren, uuid: {0}", uuid);
+        LOGGER.log(Level.FINE, "readStructuresChildren, type: {0}", type);
 
         // validate input
-        ValidateUtil.validateInputType(type);
         ValidateUtil.validateInputUuid(uuid);
 
+        boolean type_systemGroup = type != null && Type.SYSTEMGROUP.equals(type);
+        boolean type_system      = type != null && Type.SYSTEM.equals(type);
+        boolean type_subsystem   = type != null && Type.SUBSYSTEM.equals(type);
+        boolean type_discipline  = type != null && Type.DISCIPLINE.equals(type);
+        boolean type_deviceGroup = type != null && Type.DEVICEGROUP.equals(type);
+        boolean type_deviceType  = type != null && Type.DEVICETYPE.equals(type);
+        boolean type_either      = type_systemGroup || type_system || type_subsystem || type_discipline || type_deviceGroup || type_deviceType;
+
         // do
-        if (Type.SYSTEMGROUP.equals(type)) {
-            return readStructures(Type.SYSTEM, new Status[] {Status.APPROVED}, false,
+        final List<StructureElement> structureElements = Lists.newArrayList();
+        ResponsePageStructureElements response = null;
+        if (type_either) {
+            if (type_systemGroup) {
+                response = readStructures(Type.SYSTEM, new Status[] {Status.APPROVED}, false,
+                        null, uuid, null, null, null, null, null,
+                        orderBy, isAsc, offset, limit);
+            } else if (type_system) {
+                response = readStructures(Type.SUBSYSTEM, new Status[] {Status.APPROVED}, false,
+                        null, uuid, null, null, null, null, null,
+                        orderBy, isAsc, offset, limit);
+            } else if (type_discipline) {
+                response = readStructures(Type.DEVICEGROUP, new Status[] {Status.APPROVED}, false,
+                        null, uuid, null, null, null, null, null,
+                        orderBy, isAsc, offset, limit);
+            } else if (type_deviceGroup) {
+                response = readStructures(Type.DEVICETYPE, new Status[] {Status.APPROVED}, false,
+                        null, uuid, null, null, null, null, null,
+                        orderBy, isAsc, offset, limit);
+            } else {
+                // no children in structures for subsystem and device type
+                response = new ResponsePageStructureElements(structureElements, Long.valueOf(structureElements.size()), structureElements.size(), offset, limit);
+            }
+        } else {
+            // go through all structures and see if / where uuid is found
+            //     uuid in 0 or 1 of structures
+
+            ResponsePageStructureElements responseSystemGroup = readStructures(Type.SYSTEM, new Status[] {Status.APPROVED}, false,
                     null, uuid, null, null, null, null, null,
                     orderBy, isAsc, offset, limit);
-        } else if (Type.SYSTEM.equals(type)) {
-            return readStructures(Type.SUBSYSTEM, new Status[] {Status.APPROVED}, false,
+            ResponsePageStructureElements responseSystem      = readStructures(Type.SUBSYSTEM, new Status[] {Status.APPROVED}, false,
                     null, uuid, null, null, null, null, null,
                     orderBy, isAsc, offset, limit);
-        } else if (Type.SUBSYSTEM.equals(type)) {
-            // no children in structures
-        } else if (Type.DISCIPLINE.equals(type)) {
-            return readStructures(Type.DEVICEGROUP, new Status[] {Status.APPROVED}, false,
+            ResponsePageStructureElements responseDiscipline  = readStructures(Type.DEVICEGROUP, new Status[] {Status.APPROVED}, false,
                     null, uuid, null, null, null, null, null,
                     orderBy, isAsc, offset, limit);
-        } else if (Type.DEVICEGROUP.equals(type)) {
-            return readStructures(Type.DEVICETYPE, new Status[] {Status.APPROVED}, false,
+            ResponsePageStructureElements responseDeviceGroup = readStructures(Type.DEVICETYPE, new Status[] {Status.APPROVED}, false,
                     null, uuid, null, null, null, null, null,
                     orderBy, isAsc, offset, limit);
-        } else if (Type.DEVICETYPE.equals(type)) {
-            // no children in structures
-        }
 
-        ResponsePageStructureElements response = new ResponsePageStructureElements();
-        response.setTotalCount(0L);
-        response.setListSize(0);
-        response.setPage(offset);
-        response.setPageSize(limit);
+            structureElements.addAll(responseSystemGroup.getList());
+            structureElements.addAll(responseSystem.getList());
+            structureElements.addAll(responseDiscipline.getList());
+            structureElements.addAll(responseDeviceGroup.getList());
 
-        return new ResponsePageStructureElements();
+            // uuid is in max one structure
+            response = new ResponsePageStructureElements(structureElements, Long.valueOf(structureElements.size()), structureElements.size(), offset, limit);
+        }
+        return response;
     }
 
     public ResponsePageStructureElements readStructuresMnemonic(String mnemonic,
diff --git a/src/test/java/org/openepics/names/docker/StructuresDeviceGroupIT.java b/src/test/java/org/openepics/names/docker/StructuresDeviceGroupIT.java
index d6de272f..a4d41910 100644
--- a/src/test/java/org/openepics/names/docker/StructuresDeviceGroupIT.java
+++ b/src/test/java/org/openepics/names/docker/StructuresDeviceGroupIT.java
@@ -1824,10 +1824,14 @@ class StructuresDeviceGroupIT {
             ITUtilStructureElement.assertRead("/DEVICEGROUP?description=description", 35, -1);
 
             // children
-            //     /children/{type}/{uuid}
-            //     type, uuid, statuses, deleted, name, mnemonic, mnemonicequivalence, mnemonicpath, description
-            ITUtilStructureElement.assertRead("/children/DEVICEGROUP/" + uuid.toString(),             0);
-            ITUtilStructureElement.assertRead("/children/DISCIPLINE/"  + discipline2Uuid.toString(), 15, -1);
+            //     /children/{uuid}
+            //     uuid, type, statuses, deleted, name, mnemonic, mnemonicequivalence, mnemonicpath, description
+            ITUtilStructureElement.assertRead("/children/" + uuid.toString(),                                   0);
+            ITUtilStructureElement.assertRead("/children/" + discipline2Uuid.toString(),                       15, -1);
+            ITUtilStructureElement.assertRead("/children/" + uuid.toString()            + "?type=DEVICEGROUP",  0);
+            ITUtilStructureElement.assertRead("/children/" + discipline2Uuid.toString() + "?type=DEVICEGROUP",  0);
+            ITUtilStructureElement.assertRead("/children/" + uuid.toString()            + "?type=DISCIPLINE",   0);
+            ITUtilStructureElement.assertRead("/children/" + discipline2Uuid.toString() + "?type=DISCIPLINE",  15, -1);
 
             // mnemonic
             //     /mnemonic/{mnemonic}
diff --git a/src/test/java/org/openepics/names/docker/StructuresDeviceTypeIT.java b/src/test/java/org/openepics/names/docker/StructuresDeviceTypeIT.java
index 4103702c..ced3b2c3 100644
--- a/src/test/java/org/openepics/names/docker/StructuresDeviceTypeIT.java
+++ b/src/test/java/org/openepics/names/docker/StructuresDeviceTypeIT.java
@@ -1842,11 +1842,20 @@ class StructuresDeviceTypeIT {
             ITUtilStructureElement.assertRead("/DEVICETYPE?description=description", 35, -1);
 
             // children
-            //     /children/{type}/{uuid}
-            //     type, uuid, statuses, deleted, name, mnemonic, mnemonicequivalence, mnemonicpath, description
-            ITUtilStructureElement.assertRead("/children/DEVICETYPE/"  + uuid.toString(),            0);
-            ITUtilStructureElement.assertRead("/children/DEVICEGROUP/" + deviceGroupUuid.toString(), 1, -1);
-            ITUtilStructureElement.assertRead("/children/DISCIPLINE/"  + disciplineUuid.toString(),  1, -1);
+            //     /children/{uuid}
+            //     uuid, type, statuses, deleted, name, mnemonic, mnemonicequivalence, mnemonicpath, description
+            ITUtilStructureElement.assertRead("/children/" + uuid.toString(),                                   0);
+            ITUtilStructureElement.assertRead("/children/" + deviceGroupUuid.toString(),                       15, -1);
+            ITUtilStructureElement.assertRead("/children/" + disciplineUuid.toString(),                         1);
+            ITUtilStructureElement.assertRead("/children/" + uuid.toString()            + "?type=DEVICETYPE",   0);
+            ITUtilStructureElement.assertRead("/children/" + deviceGroupUuid.toString() + "?type=DEVICETYPE",   0);
+            ITUtilStructureElement.assertRead("/children/" + disciplineUuid.toString()  + "?type=DEVICETYPE",   0);
+            ITUtilStructureElement.assertRead("/children/" + uuid.toString()            + "?type=DEVICEGROUP",  0);
+            ITUtilStructureElement.assertRead("/children/" + deviceGroupUuid.toString() + "?type=DEVICEGROUP", 15, -1);
+            ITUtilStructureElement.assertRead("/children/" + disciplineUuid.toString()  + "?type=DEVICEGROUP",  0);
+            ITUtilStructureElement.assertRead("/children/" + uuid.toString()            + "?type=DISCIPLINE",   0);
+            ITUtilStructureElement.assertRead("/children/" + deviceGroupUuid.toString() + "?type=DISCIPLINE",   0);
+            ITUtilStructureElement.assertRead("/children/" + disciplineUuid.toString()  + "?type=DISCIPLINE",   1);
 
             // mnemonic
             //     /mnemonic/{mnemonic}
diff --git a/src/test/java/org/openepics/names/docker/StructuresDisciplineIT.java b/src/test/java/org/openepics/names/docker/StructuresDisciplineIT.java
index f18cf5d4..ac24e774 100644
--- a/src/test/java/org/openepics/names/docker/StructuresDisciplineIT.java
+++ b/src/test/java/org/openepics/names/docker/StructuresDisciplineIT.java
@@ -1743,9 +1743,10 @@ class StructuresDisciplineIT {
             ITUtilStructureElement.assertRead("/DISCIPLINE?description=description",       35, -1);
 
             // children
-            //     /children/{type}/{uuid}
-            //     type, uuid, statuses, deleted, name, mnemonic, mnemonicequivalence, mnemonicpath, description
-            ITUtilStructureElement.assertRead("/children/DISCIPLINE/" + uuid.toString(), 0);
+            //     /children/{uuid}
+            //     uuid, type, statuses, deleted, name, mnemonic, mnemonicequivalence, mnemonicpath, description
+            ITUtilStructureElement.assertRead("/children/" + uuid.toString(),                      0);
+            ITUtilStructureElement.assertRead("/children/" + uuid.toString() + "?type=DISCIPLINE", 0);
 
             // mnemonic
             //     /mnemonic/{mnemonic}
diff --git a/src/test/java/org/openepics/names/docker/StructuresSubsystemIT.java b/src/test/java/org/openepics/names/docker/StructuresSubsystemIT.java
index 142a8170..2e7441cb 100644
--- a/src/test/java/org/openepics/names/docker/StructuresSubsystemIT.java
+++ b/src/test/java/org/openepics/names/docker/StructuresSubsystemIT.java
@@ -1894,17 +1894,20 @@ class StructuresSubsystemIT {
             ITUtilStructureElement.assertRead("/SUBSYSTEM?description=description", 35, -1);
 
             // children
-            //     /children/{type}/{uuid}
-            //     type, uuid, statuses, deleted, name, mnemonic, mnemonicequivalence, mnemonicpath, description
-            ITUtilStructureElement.assertRead("/children/SUBSYSTEM/"   + uuid.toString(),            0);
-            ITUtilStructureElement.assertRead("/children/SUBSYSTEM/"   + systemUuid.toString(),      0);
-            ITUtilStructureElement.assertRead("/children/SUBSYSTEM/"   + systemGroupUuid.toString(), 0);
-            ITUtilStructureElement.assertRead("/children/SYSTEM/"      + uuid.toString(),            0);
-            ITUtilStructureElement.assertRead("/children/SYSTEM/"      + systemUuid.toString(),      1, -1);
-            ITUtilStructureElement.assertRead("/children/SYSTEM/"      + systemGroupUuid.toString(), 0);
-            ITUtilStructureElement.assertRead("/children/SYSTEMGROUP/" + uuid.toString(),            0);
-            ITUtilStructureElement.assertRead("/children/SYSTEMGROUP/" + systemUuid.toString(),      0);
-            ITUtilStructureElement.assertRead("/children/SYSTEMGROUP/" + systemGroupUuid.toString(), 1, -1);
+            //     /children/{uuid}
+            //     uuid, type, statuses, deleted, name, mnemonic, mnemonicequivalence, mnemonicpath, description
+            ITUtilStructureElement.assertRead("/children/" + uuid.toString(),                                   0);
+            ITUtilStructureElement.assertRead("/children/" + systemUuid.toString(),                            15, -1);
+            ITUtilStructureElement.assertRead("/children/" + systemGroupUuid.toString(),                        1);
+            ITUtilStructureElement.assertRead("/children/" + uuid.toString()            + "?type=SUBSYSTEM",    0);
+            ITUtilStructureElement.assertRead("/children/" + systemUuid.toString()      + "?type=SUBSYSTEM",    0);
+            ITUtilStructureElement.assertRead("/children/" + systemGroupUuid.toString() + "?type=SUBSYSTEM",    0);
+            ITUtilStructureElement.assertRead("/children/" + uuid.toString()            + "?type=SYSTEM",       0);
+            ITUtilStructureElement.assertRead("/children/" + systemUuid.toString()      + "?type=SYSTEM",      15, -1);
+            ITUtilStructureElement.assertRead("/children/" + systemGroupUuid.toString() + "?type=SYSTEM",       0);
+            ITUtilStructureElement.assertRead("/children/" + uuid.toString()            + "?type=SYSTEMGROUP",  0);
+            ITUtilStructureElement.assertRead("/children/" + systemUuid.toString()      + "?type=SYSTEMGROUP",  0);
+            ITUtilStructureElement.assertRead("/children/" + systemGroupUuid.toString() + "?type=SYSTEMGROUP",  1);
 
             // mnemonic
             //     /mnemonic/{mnemonic}
diff --git a/src/test/java/org/openepics/names/docker/StructuresSystemGroupIT.java b/src/test/java/org/openepics/names/docker/StructuresSystemGroupIT.java
index 543d8afb..88da7e30 100644
--- a/src/test/java/org/openepics/names/docker/StructuresSystemGroupIT.java
+++ b/src/test/java/org/openepics/names/docker/StructuresSystemGroupIT.java
@@ -1787,9 +1787,10 @@ class StructuresSystemGroupIT {
             ITUtilStructureElement.assertRead("/SYSTEMGROUP?description=description",       35, -1);
 
             // children
-            //     /children/{type}/{uuid}
-            //     type, uuid, statuses, deleted, name, mnemonic, mnemonicequivalence, mnemonicpath, description
-            ITUtilStructureElement.assertRead("/children/SYSTEMGROUP/" + uuid.toString(), 0);
+            //     /children/{uuid}
+            //     uuid, type, statuses, deleted, name, mnemonic, mnemonicequivalence, mnemonicpath, description
+            ITUtilStructureElement.assertRead("/children/" + uuid.toString(),                       0);
+            ITUtilStructureElement.assertRead("/children/" + uuid.toString() + "?type=SYSTEMGROUP", 0);
 
             // mnemonic
             //     /mnemonic/{mnemonic}
diff --git a/src/test/java/org/openepics/names/docker/StructuresSystemIT.java b/src/test/java/org/openepics/names/docker/StructuresSystemIT.java
index 0ef774dd..7a73beb4 100644
--- a/src/test/java/org/openepics/names/docker/StructuresSystemIT.java
+++ b/src/test/java/org/openepics/names/docker/StructuresSystemIT.java
@@ -1825,12 +1825,14 @@ class StructuresSystemIT {
             ITUtilStructureElement.assertRead("/SYSTEM?description=description",       35, -1);
 
             // children
-            //     /children/{type}/{uuid}
-            //     type, uuid, statuses, deleted, name, mnemonic, mnemonicequivalence, mnemonicpath, description
-            ITUtilStructureElement.assertRead("/children/SYSTEM/"      + uuid.toString(),            0);
-            ITUtilStructureElement.assertRead("/children/SYSTEM/"      + systemGroupUuid.toString(), 0);
-            ITUtilStructureElement.assertRead("/children/SYSTEMGROUP/" + uuid.toString(),            0);
-            ITUtilStructureElement.assertRead("/children/SYSTEMGROUP/" + systemGroupUuid.toString(), 1, -1);
+            //     /children/{uuid}
+            //     uuid, type, statuses, deleted, name, mnemonic, mnemonicequivalence, mnemonicpath, description
+            ITUtilStructureElement.assertRead("/children/" + uuid.toString(),                                   0);
+            ITUtilStructureElement.assertRead("/children/" + systemGroupUuid.toString(),                       15, -1);
+            ITUtilStructureElement.assertRead("/children/" + uuid.toString()            + "?type=SYSTEM",       0);
+            ITUtilStructureElement.assertRead("/children/" + systemGroupUuid.toString() + "?type=SYSTEM",       0);
+            ITUtilStructureElement.assertRead("/children/" + uuid.toString()            + "?type=SYSTEMGROUP",  0);
+            ITUtilStructureElement.assertRead("/children/" + systemGroupUuid.toString() + "?type=SYSTEMGROUP", 15, -1);
 
             // mnemonic
             //     /mnemonic/{mnemonic}
-- 
GitLab