From f509c1f52fbb4fc7e9f56b223a813bc2268d0e52 Mon Sep 17 00:00:00 2001
From: ThanKarab <tkarabatsis@hotmail.com>
Date: Wed, 2 Aug 2023 17:26:31 +0300
Subject: [PATCH] Pathologies API refactoring.

Converted all DTOs to records, except from CommonDataElement because we need to modify it.
Created a PathologyService and extracted all complexity from the Controller.
Renamed the MetadataHierarchyDTO to PathologyMetadataDTO.
Created a new PathologyMetadataGroupDTO class for the metadata groups. The PathologyMetadataDTO class has more properties now that were not included previously.
Removed the Exareme2AttributesDTO, getting the internal info hardcoded, maybe we should change that in the future.
---
 .../hbp/mip/controllers/AlgorithmsAPI.java    |   1 +
 .../hbp/mip/controllers/PathologiesAPI.java   | 110 ++---------
 .../models/DTOs/Exareme2AttributesDTO.java    |  19 --
 .../mip/models/DTOs/MetadataHierarchyDTO.java |  94 ---------
 .../hbp/mip/models/DTOs/PathologyDTO.java     |  69 +------
 .../mip/models/DTOs/PathologyMetadataDTO.java |  45 +++++
 .../hbp/mip/services/ActiveUserService.java   |   6 +-
 .../hbp/mip/services/PathologyService.java    | 186 ++++++++++++++++++
 src/main/java/hbp/mip/utils/ClaimUtils.java   |  42 ++--
 src/main/java/hbp/mip/utils/Logger.java       |   4 +-
 10 files changed, 281 insertions(+), 295 deletions(-)
 delete mode 100644 src/main/java/hbp/mip/models/DTOs/Exareme2AttributesDTO.java
 delete mode 100644 src/main/java/hbp/mip/models/DTOs/MetadataHierarchyDTO.java
 create mode 100644 src/main/java/hbp/mip/models/DTOs/PathologyMetadataDTO.java
 create mode 100644 src/main/java/hbp/mip/services/PathologyService.java

diff --git a/src/main/java/hbp/mip/controllers/AlgorithmsAPI.java b/src/main/java/hbp/mip/controllers/AlgorithmsAPI.java
index 18dffdc2c..d67acb120 100644
--- a/src/main/java/hbp/mip/controllers/AlgorithmsAPI.java
+++ b/src/main/java/hbp/mip/controllers/AlgorithmsAPI.java
@@ -19,6 +19,7 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
 public class AlgorithmsAPI {
 
     private final AlgorithmService algorithmService;
+
     private final ActiveUserService activeUserService;
 
     public AlgorithmsAPI(ActiveUserService activeUserService, AlgorithmService algorithmService) {
diff --git a/src/main/java/hbp/mip/controllers/PathologiesAPI.java b/src/main/java/hbp/mip/controllers/PathologiesAPI.java
index da9f6d509..e6b76eabc 100644
--- a/src/main/java/hbp/mip/controllers/PathologiesAPI.java
+++ b/src/main/java/hbp/mip/controllers/PathologiesAPI.java
@@ -1,125 +1,41 @@
 package hbp.mip.controllers;
 
-import com.google.gson.Gson;
-import com.google.gson.reflect.TypeToken;
-import hbp.mip.models.DTOs.Exareme2AttributesDTO;
-import hbp.mip.models.DTOs.Exareme2CommonDataElement;
 import hbp.mip.models.DTOs.PathologyDTO;
 import hbp.mip.services.ActiveUserService;
-import hbp.mip.utils.ClaimUtils;
-import hbp.mip.utils.Exceptions.InternalServerError;
-import hbp.mip.utils.HTTPUtil;
+import hbp.mip.services.PathologyService;
 import hbp.mip.utils.Logger;
-import org.springframework.beans.factory.annotation.Value;
 import org.springframework.http.ResponseEntity;
 import org.springframework.security.core.Authentication;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
-import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
-
-import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
+import java.util.stream.Collectors;
 
 @RestController
-@RequestMapping(value = "/pathologies", produces = {APPLICATION_JSON_VALUE})
+@RequestMapping(value = "/pathologies")
 public class PathologiesAPI {
 
-    private static final Gson gson = new Gson();
+    private final PathologyService pathologyService;
+
     private final ActiveUserService activeUserService;
-    private final ClaimUtils claimUtils;
-    // Enable HBP collab authentication (1) or disable it (0). Default is 1
-    @Value("#{'${authentication.enabled}'}")
-    private boolean authenticationIsEnabled;
-    @Value("#{'${services.exareme2.attributesUrl}'}")
-    private String exareme2AttributesUrl;
-    @Value("#{'${services.exareme2.cdesMetadataUrl}'}")
-    private String exareme2CDEsMetadataUrl;
 
-    public PathologiesAPI(ActiveUserService activeUserService, ClaimUtils claimUtils) {
+    public PathologiesAPI(ActiveUserService activeUserService, PathologyService pathologyService) {
         this.activeUserService = activeUserService;
-        this.claimUtils = claimUtils;
+        this.pathologyService = pathologyService;
     }
 
     @GetMapping
-    public ResponseEntity<String> getPathologies(Authentication authentication) {
+    public ResponseEntity<List<PathologyDTO>> getPathologies(Authentication authentication) {
         Logger logger = new Logger(activeUserService.getActiveUser(authentication).username(), "(GET) /pathologies");
-        logger.LogUserAction("Loading pathologies ...");
-
-        Map<String, List<PathologyDTO.EnumerationDTO>> datasetsPerPathology = getExareme2DatasetsPerPathology(logger);
-
-        Map<String, Exareme2AttributesDTO> exareme2PathologyAttributes = getExareme2PathologyAttributes(logger);
+        List<PathologyDTO> pathologies = pathologyService.getPathologies(authentication, logger);
 
-        List<PathologyDTO> pathologyDTOS = new ArrayList<>();
-        for (String pathology : exareme2PathologyAttributes.keySet()) {
-            PathologyDTO newPathology;
-            try {
-                newPathology = new PathologyDTO(pathology, exareme2PathologyAttributes.get(pathology), datasetsPerPathology.get(pathology));
-            } catch (InternalServerError e) {
-                logger.LogUserAction(e.getMessage());
-                continue;
-            }
+        String userPathologiesSTR = pathologies.stream().map(PathologyDTO::code)
+                .collect(Collectors.joining(", "));
+        logger.LogUserAction("Access given to " + pathologies.size() + " pathologies: [" + userPathologiesSTR + "].");
 
-            pathologyDTOS.add(newPathology);
-        }
-
-        // If authentication is disabled return everything
-        if (!authenticationIsEnabled) {
-            logger.LogUserAction("Successfully loaded " + pathologyDTOS.size() + " pathologies");
-            return ResponseEntity.ok().body(gson.toJson(pathologyDTOS));
-        }
-
-        logger.LogUserAction("Successfully loaded all authorized pathologies");
-        return ResponseEntity.ok().body(gson.toJson(claimUtils.getAuthorizedPathologies(logger, authentication, pathologyDTOS)));
+        return ResponseEntity.ok(pathologies);
     }
 
-    public Map<String, List<PathologyDTO.EnumerationDTO>> getExareme2DatasetsPerPathology(Logger logger) {
-        Map<String, Map<String, Exareme2CommonDataElement>> exareme2CDEsMetadata;
-        // Get Exareme2 algorithms
-        try {
-            StringBuilder response = new StringBuilder();
-            HTTPUtil.sendGet(exareme2CDEsMetadataUrl, response);
-            exareme2CDEsMetadata = gson.fromJson(
-                    response.toString(),
-                    new TypeToken<HashMap<String, Map<String, Exareme2CommonDataElement>>>() {
-                    }.getType()
-            );
-        } catch (Exception e) {
-            logger.LogUserAction("An exception occurred: " + e.getMessage());
-            return null;
-        }
-
-        Map<String, List<PathologyDTO.EnumerationDTO>> datasetsPerPathology = new HashMap<>();
-
-        exareme2CDEsMetadata.forEach((pathology, cdePerDataset) -> {
-            List<PathologyDTO.EnumerationDTO> pathologyDatasetDTOS = new ArrayList<>();
-            Map<String, String> datasetEnumerations = (Map<String, String>) cdePerDataset.get("dataset").getEnumerations();
-            datasetEnumerations.forEach((code, label) -> pathologyDatasetDTOS.add(new PathologyDTO.EnumerationDTO(code, label)));
-            datasetsPerPathology.put(pathology, pathologyDatasetDTOS);
-        });
-
-        return datasetsPerPathology;
-    }
-
-    public Map<String, Exareme2AttributesDTO> getExareme2PathologyAttributes(Logger logger) {
-        Map<String, Exareme2AttributesDTO> exareme2PathologyAttributes;
-        // Get Exareme2 algorithms
-        try {
-            StringBuilder response = new StringBuilder();
-            HTTPUtil.sendGet(exareme2AttributesUrl, response);
-            exareme2PathologyAttributes = gson.fromJson(
-                    response.toString(),
-                    new TypeToken<HashMap<String, Exareme2AttributesDTO>>() {
-                    }.getType()
-            );
-        } catch (Exception e) {
-            logger.LogUserAction("An exception occurred: " + e.getMessage());
-            return null;
-        }
-
-        return exareme2PathologyAttributes;
-    }
 }
diff --git a/src/main/java/hbp/mip/models/DTOs/Exareme2AttributesDTO.java b/src/main/java/hbp/mip/models/DTOs/Exareme2AttributesDTO.java
deleted file mode 100644
index 3755dcdc2..000000000
--- a/src/main/java/hbp/mip/models/DTOs/Exareme2AttributesDTO.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package hbp.mip.models.DTOs;
-
-import com.google.gson.annotations.SerializedName;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-
-import java.util.List;
-import java.util.Map;
-
-@Data
-@AllArgsConstructor
-public class Exareme2AttributesDTO {
-    @SerializedName("properties")
-    private Map<String, List<MetadataHierarchyDTO>> properties;
-
-    @SerializedName("tags")
-    private Object tags;
-
-}
diff --git a/src/main/java/hbp/mip/models/DTOs/MetadataHierarchyDTO.java b/src/main/java/hbp/mip/models/DTOs/MetadataHierarchyDTO.java
deleted file mode 100644
index 0c9100809..000000000
--- a/src/main/java/hbp/mip/models/DTOs/MetadataHierarchyDTO.java
+++ /dev/null
@@ -1,94 +0,0 @@
-package hbp.mip.models.DTOs;
-
-import com.google.gson.annotations.SerializedName;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-
-import java.util.List;
-
-@Data
-@AllArgsConstructor
-public class MetadataHierarchyDTO {
-
-    @SerializedName("variables")
-    private List<CommonDataElement> variables;
-
-    @SerializedName("code")
-    private String code;
-
-    @SerializedName("groups")
-    private List<MetadataHierarchyDTO> groups;
-
-    @SerializedName("label")
-    private String label;
-    @Data
-    @AllArgsConstructor
-    public static class CommonDataElement {
-        @SerializedName("is_categorical")
-        private Boolean is_categorical;
-
-        @SerializedName("code")
-        private String code;
-
-        @SerializedName("sql_type")
-        private String sql_type;
-
-        @SerializedName("description")
-        private String description;
-
-        @SerializedName("enumerations")
-        private List<PathologyDTO.EnumerationDTO> enumerations;
-
-        @SerializedName("label")
-        private String label;
-
-        @SerializedName("units")
-        private String units;
-
-        @SerializedName("type")
-        private String type;
-
-        @SerializedName("methodology")
-        private String methodology;
-
-        @SerializedName("min")
-        private String min;
-
-        @SerializedName("max")
-        private String max;
-    }
-
-
-    public boolean isDatasetCDEPresent(){
-        if (this.variables != null) {
-            for (CommonDataElement variable : this.variables) {
-                if (variable.code.equals("dataset")){
-                    return true;
-                }
-            }
-
-        }
-        if (this.groups != null) {
-            for (MetadataHierarchyDTO group: this.groups){
-                if (group.isDatasetCDEPresent()){
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    public void updateDatasetCde(List<PathologyDTO.EnumerationDTO> pathologyDatasetDTOS){
-        if (this.variables != null) {
-            List<MetadataHierarchyDTO.CommonDataElement> variables = this.variables;
-            variables.stream().filter(cde -> cde.getCode().equals("dataset")).
-                    findAny().ifPresent(cde -> cde.setEnumerations(pathologyDatasetDTOS));
-        }
-
-        if (this.groups != null) {
-            for (MetadataHierarchyDTO group: this.groups){
-                group.updateDatasetCde(pathologyDatasetDTOS);
-            }
-        }
-    }
-}
diff --git a/src/main/java/hbp/mip/models/DTOs/PathologyDTO.java b/src/main/java/hbp/mip/models/DTOs/PathologyDTO.java
index 794a5ee7a..a1364379b 100644
--- a/src/main/java/hbp/mip/models/DTOs/PathologyDTO.java
+++ b/src/main/java/hbp/mip/models/DTOs/PathologyDTO.java
@@ -1,66 +1,17 @@
 package hbp.mip.models.DTOs;
 
-import com.google.gson.annotations.SerializedName;
-import hbp.mip.utils.Exceptions.InternalServerError;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-
-import java.util.Arrays;
 import java.util.List;
 
-@Data
-@AllArgsConstructor
-public class PathologyDTO {
-
-    @SerializedName("code")
-    private String code;
-
-    @SerializedName("version")
-    private String version;
-
-
-    @SerializedName("label")
-    private String label;
-
-    @SerializedName("metadataHierarchy")
-    private MetadataHierarchyDTO metadataHierarchyDTO;
-
-    @SerializedName("datasets")
-    private List<EnumerationDTO> datasets;
-
-    public PathologyDTO(){
 
-    }
-
-
-    public PathologyDTO(String pathology, Exareme2AttributesDTO exareme2AttributesDTO, List<EnumerationDTO> pathologyDatasetDTOS) {
-        MetadataHierarchyDTO metadataHierarchyDTO = exareme2AttributesDTO.getProperties().get("cdes").get(0);
-        if (!metadataHierarchyDTO.isDatasetCDEPresent()) throw new InternalServerError("CommonDataElement Dataset was not present in the pathology:" + pathology);
-        metadataHierarchyDTO.updateDatasetCde(pathologyDatasetDTOS);
-
-        List<String> pathology_info = Arrays.asList(pathology.split(":", 2));
-        this.code = pathology_info.get(0);
-        this.version = pathology_info.get(1);
-        this.metadataHierarchyDTO = metadataHierarchyDTO;
-        this.label = metadataHierarchyDTO.getLabel();
-        this.datasets = pathologyDatasetDTOS;
-    }
-
-    @Data
-    @AllArgsConstructor
-    public static class EnumerationDTO {
-        @SerializedName("code")
-        private String code;
-
-        @SerializedName("label")
-        private String label;
-
-        public String toString() {
-            return code;
-        }
-    }
-
-    public String toString() {
-        return code;
+public record PathologyDTO(
+        String code,
+        String version,
+        String label,
+        Boolean longitudinal,
+        PathologyMetadataDTO metadataHierarchy,
+        List<EnumerationDTO> datasets
+) {
+    public record EnumerationDTO(String code, String label) {
     }
 }
+
diff --git a/src/main/java/hbp/mip/models/DTOs/PathologyMetadataDTO.java b/src/main/java/hbp/mip/models/DTOs/PathologyMetadataDTO.java
new file mode 100644
index 000000000..eb795fb22
--- /dev/null
+++ b/src/main/java/hbp/mip/models/DTOs/PathologyMetadataDTO.java
@@ -0,0 +1,45 @@
+package hbp.mip.models.DTOs;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+public record PathologyMetadataDTO(
+        String code,
+        String version,
+        String label,
+        Boolean longitudinal,
+        List<CommonDataElementDTO> variables,
+        List<PathologyMetadataGroupDTO> groups
+) {
+    public record PathologyMetadataGroupDTO(
+            String code,
+            String label,
+            List<CommonDataElementDTO> variables,
+            List<PathologyMetadataGroupDTO> groups
+    ) {
+    }
+
+    @Data
+    @NoArgsConstructor
+    @AllArgsConstructor
+    public static class CommonDataElementDTO {
+        private String code;
+        private String label;
+        private String description;
+        private String sql_type;
+        private String is_categorical;
+        private List<PathologyDTO.EnumerationDTO> enumerations;
+        private String min;
+        private String max;
+        private String type;
+        private String methodology;
+        private String units;
+
+        public void setEnumerations(List<PathologyDTO.EnumerationDTO> enumerations) {
+            this.enumerations = enumerations;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/hbp/mip/services/ActiveUserService.java b/src/main/java/hbp/mip/services/ActiveUserService.java
index 3b650021f..07d0841d5 100644
--- a/src/main/java/hbp/mip/services/ActiveUserService.java
+++ b/src/main/java/hbp/mip/services/ActiveUserService.java
@@ -9,18 +9,20 @@ import org.springframework.context.annotation.ScopedProxyMode;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
 import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
-import org.springframework.stereotype.Component;
+import org.springframework.stereotype.Service;
 
 import java.util.Objects;
 
 
-@Component
+@Service
 @Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
 public class ActiveUserService {
 
     private final UserRepository userRepository;
     @Value("${authentication.enabled}")
+
     private boolean authenticationIsEnabled;
+
     private UserDTO activeUserDetails;
 
     public ActiveUserService(UserRepository userRepository) {
diff --git a/src/main/java/hbp/mip/services/PathologyService.java b/src/main/java/hbp/mip/services/PathologyService.java
new file mode 100644
index 000000000..ea0ff3090
--- /dev/null
+++ b/src/main/java/hbp/mip/services/PathologyService.java
@@ -0,0 +1,186 @@
+package hbp.mip.services;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import hbp.mip.models.DTOs.Exareme2CommonDataElement;
+import hbp.mip.models.DTOs.PathologyMetadataDTO;
+import hbp.mip.models.DTOs.PathologyDTO;
+import hbp.mip.utils.ClaimUtils;
+import hbp.mip.utils.Exceptions.InternalServerError;
+import hbp.mip.utils.HTTPUtil;
+import hbp.mip.utils.Logger;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.security.core.Authentication;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Service
+public class PathologyService {
+
+    private static final Gson gson = new Gson();
+
+    private final ClaimUtils claimUtils;
+
+    @Value("${authentication.enabled}")
+    private boolean authenticationIsEnabled;
+
+    @Value("${services.exareme2.attributesUrl}")
+    private String exareme2AttributesUrl;
+
+    @Value("${services.exareme2.cdesMetadataUrl}")
+    private String exareme2CDEsMetadataUrl;
+
+    public PathologyService(ClaimUtils claimUtils) {
+        this.claimUtils = claimUtils;
+    }
+
+    public List<PathologyDTO> getPathologies(Authentication authentication, Logger logger) {
+        List<PathologyDTO> allPathologyDTOs = getAggregatedPathologyDTOs(logger);
+
+        if (!authenticationIsEnabled) {
+            return allPathologyDTOs;
+        }
+        return claimUtils.getAuthorizedPathologies(logger, authentication, allPathologyDTOs);
+    }
+
+    /**
+     * This method will fetch all necessary information about pathologies from exareme and then aggregate them.
+     * The information that needs to be aggregated is the dataset CDE enumerations.
+     * Exareme returns the information about the dataset enumerations in a separate endpoint.
+     */
+    private List<PathologyDTO> getAggregatedPathologyDTOs(Logger logger) {
+        Map<String, PathologyMetadataDTO> pathologiesMetadataHierarchy = getExaremePathologiesMetadataHierarchyDTO(logger);
+        Map<String, List<PathologyDTO.EnumerationDTO>> datasetsPerPathology = getExareme2DatasetsPerPathology(logger);
+
+        List<PathologyDTO> allPathologyDTOs = new ArrayList<>();
+        for (String pathology : datasetsPerPathology.keySet()) {
+            PathologyMetadataDTO pathologyMetadata = pathologiesMetadataHierarchy.get(pathology);
+            assert pathologyMetadata != null;
+            List<PathologyDTO.EnumerationDTO> pathologyDatasets = datasetsPerPathology.get(pathology);
+
+            // Exareme collects the dataset CDE enumerations automatically from the nodes when there is an addition/deletion.
+            // Exareme provides that information in a separate endpoint from the rest of the pathologies' metadata.
+            // We need to manually update the dataset CDE enumerations in each pathology's metadata in order to
+            // return the latest information in the frontend, without the need for data aggregation.
+            if (!hasDatasetCDE(pathologyMetadata.variables(), pathologyMetadata.groups()))
+                throw new InternalServerError("CommonDataElement 'dataset' was not present in the pathology's metadata:" + pathologyMetadata);
+            updateDatasetCDEEnumerations(pathologyMetadata.variables(), pathologyMetadata.groups(), pathologyDatasets);
+
+            allPathologyDTOs.add(
+                    new PathologyDTO(
+                            pathologyMetadata.code(),
+                            pathologyMetadata.version(),
+                            pathologyMetadata.label(),
+                            pathologyMetadata.longitudinal(),
+                            pathologyMetadata,
+                            pathologyDatasets
+                    )
+            );
+        }
+        return allPathologyDTOs;
+    }
+
+    private Map<String, List<PathologyDTO.EnumerationDTO>> getExareme2DatasetsPerPathology(Logger logger) {
+        Map<String, Map<String, Exareme2CommonDataElement>> exareme2CDEsMetadata;
+        Type exaremeCDEsMetadataType = new TypeToken<HashMap<String, Map<String, Exareme2CommonDataElement>>>(){}.getType();
+        try {
+            StringBuilder response = new StringBuilder();
+            HTTPUtil.sendGet(exareme2CDEsMetadataUrl, response);
+            exareme2CDEsMetadata = gson.fromJson(response.toString(),exaremeCDEsMetadataType);
+        } catch (IOException e) {
+            logger.LogUserAction("There was a problem communicating with exareme: " + e.getMessage());
+            return new HashMap<>();  // Return empty result
+        }
+
+        // Get the datasets for each pathology
+        Map<String, List<PathologyDTO.EnumerationDTO>> datasetsPerPathology = new HashMap<>();
+        exareme2CDEsMetadata.forEach((pathology, cdePerDataset) -> {
+            List<PathologyDTO.EnumerationDTO> pathologyDatasetDTOS = new ArrayList<>();
+            Map<String, String> datasetEnumerations = (Map<String, String>) cdePerDataset.get("dataset").getEnumerations();
+            datasetEnumerations.forEach((code, label) -> pathologyDatasetDTOS.add(new PathologyDTO.EnumerationDTO(code, label)));
+            datasetsPerPathology.put(pathology, pathologyDatasetDTOS);
+        });
+
+        return datasetsPerPathology;
+    }
+
+    private Map<String, Map<String, Map<String, List<Object>>>> getExareme2PathologyAttributes(Logger logger) {
+        Map<String, Map<String, Map<String, List<Object>>>> exareme2PathologyAttributes;
+        Type pathologyAttributesType = new TypeToken<Map<String, Map<String, Map<String, List<PathologyMetadataDTO>>>>>(){}.getType();
+        try {
+            StringBuilder response = new StringBuilder();
+            HTTPUtil.sendGet(exareme2AttributesUrl, response);
+            exareme2PathologyAttributes = gson.fromJson(response.toString(),pathologyAttributesType);
+        } catch (IOException e) {
+            logger.LogUserAction("There was a problem communicating with exareme: " + e.getMessage());
+            return new HashMap<>();  // Return empty result
+        }
+
+        return exareme2PathologyAttributes;
+    }
+
+    private Map<String, PathologyMetadataDTO> getExaremePathologiesMetadataHierarchyDTO(Logger logger) {
+        Map<String, Map<String, Map<String, List<Object>>>> pathologiesAttributes = getExareme2PathologyAttributes(logger);
+
+        Map<String, PathologyMetadataDTO> pathologiesHierarchies = new HashMap<>();
+        pathologiesAttributes.forEach((pathology, attributes) -> {
+            assert attributes.get("properties") != null;
+            assert attributes.get("properties").get("cdes") != null;
+            assert !attributes.get("properties").get("cdes").isEmpty();
+            pathologiesHierarchies.put(pathology, (PathologyMetadataDTO) attributes.get("properties").get("cdes").get(0));
+        });
+
+        return pathologiesHierarchies;
+    }
+
+
+    private static boolean hasDatasetCDE(
+            List<PathologyMetadataDTO.CommonDataElementDTO> variables,
+            List<PathologyMetadataDTO.PathologyMetadataGroupDTO> groups
+    ) {
+        if (variables != null) {
+            for (PathologyMetadataDTO.CommonDataElementDTO variable : variables) {
+                if (variable.getCode().equals("dataset")){
+                    return true;
+                }
+            }
+
+        }
+        if (groups != null) {
+            for (PathologyMetadataDTO.PathologyMetadataGroupDTO group: groups){
+                if (hasDatasetCDE(group.variables(), group.groups())){
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private static void updateDatasetCDEEnumerations(
+            List<PathologyMetadataDTO.CommonDataElementDTO> variables,
+            List<PathologyMetadataDTO.PathologyMetadataGroupDTO> groups,
+            List<PathologyDTO.EnumerationDTO> datasetEnumerations
+    ){
+        if (variables != null) {
+            variables.stream().filter(cde -> cde.getCode().equals("dataset")).
+                    findAny().ifPresent(cde -> cde.setEnumerations(datasetEnumerations));
+        }
+
+        if (groups != null) {
+            for (PathologyMetadataDTO.PathologyMetadataGroupDTO group: groups){
+                updateDatasetCDEEnumerations(
+                        group.variables(),
+                        group.groups(),
+                        datasetEnumerations
+                );
+            }
+        }
+    }
+
+}
diff --git a/src/main/java/hbp/mip/utils/ClaimUtils.java b/src/main/java/hbp/mip/utils/ClaimUtils.java
index 7b650f17f..dfd2df437 100644
--- a/src/main/java/hbp/mip/utils/ClaimUtils.java
+++ b/src/main/java/hbp/mip/utils/ClaimUtils.java
@@ -70,33 +70,31 @@ public class ClaimUtils {
 
         ArrayList<String> authorities = getAuthorityRoles(authentication);
 
-        List<PathologyDTO> userPathologies = new ArrayList<>();
         if (hasRoleAccess(authorities, allDatasetsAllowedClaim, logger)) {
-            userPathologies = allPathologies;
-
-        } else {
-            for (PathologyDTO curPathology : allPathologies) {
-                List<PathologyDTO.EnumerationDTO> userPathologyDatasets = new ArrayList<>();
-                for (PathologyDTO.EnumerationDTO dataset : curPathology.getDatasets()) {
-                    if (hasRoleAccess(authorities, getDatasetClaim(dataset.getCode()), logger)) {
-                        userPathologyDatasets.add(dataset);
-                    }
-                }
+            return allPathologies;
+        }
 
-                if (!userPathologyDatasets.isEmpty()) {
-                    PathologyDTO userPathology = new PathologyDTO();
-                    userPathology.setCode(curPathology.getCode());
-                    userPathology.setLabel(curPathology.getLabel());
-                    userPathology.setMetadataHierarchyDTO(curPathology.getMetadataHierarchyDTO());
-                    userPathology.setDatasets(userPathologyDatasets);
-                    userPathologies.add(userPathology);
+        List<PathologyDTO> userPathologies = new ArrayList<>();
+        for (PathologyDTO curPathology : allPathologies) {
+            List<PathologyDTO.EnumerationDTO> userPathologyDatasets = new ArrayList<>();
+            for (PathologyDTO.EnumerationDTO dataset : curPathology.datasets()) {
+                if (hasRoleAccess(authorities, getDatasetClaim(dataset.code()), logger)) {
+                    userPathologyDatasets.add(dataset);
                 }
             }
-        }
 
-        String userPathologiesSTR = userPathologies.stream().map(PathologyDTO::toString)
-                .collect(Collectors.joining(", "));
-        logger.LogUserAction("Allowed pathologies: [" + userPathologiesSTR + "]");
+            if (!userPathologyDatasets.isEmpty()) {
+                PathologyDTO userPathology = new PathologyDTO(
+                        curPathology.code(),
+                        curPathology.version(),
+                        curPathology.label(),
+                        curPathology.longitudinal(),
+                        curPathology.metadataHierarchy(),
+                        userPathologyDatasets
+                );
+                userPathologies.add(userPathology);
+            }
+        }
         return userPathologies;
     }
 }
diff --git a/src/main/java/hbp/mip/utils/Logger.java b/src/main/java/hbp/mip/utils/Logger.java
index faeed30ec..553b5a0c5 100644
--- a/src/main/java/hbp/mip/utils/Logger.java
+++ b/src/main/java/hbp/mip/utils/Logger.java
@@ -15,8 +15,8 @@ public class Logger {
     }
 
     public void LogUserAction(String actionInfo) {
-        LOGGER.info(" User -> " + username + " ,"
-                + "Endpoint -> " + endpoint + " ,"
+        LOGGER.info(" User -> " + username + " , "
+                + "Endpoint -> " + endpoint + " , "
                 + "Info ->  " + actionInfo);
     }
 }
-- 
GitLab