commit c72a4d3d3dc01091f6e43fb20fffcfa15029007c
Author: Jiri Trefil <badjokke@gmail.com>
Date:   Sun May 21 10:48:13 2023 +0200

    #10558 refactor service a controller vrstvy u configuration endpointu.

diff --git a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/controller/ConfigurationController.java b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/controller/ConfigurationController.java
index 9fb21da..146590b 100644
--- a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/controller/ConfigurationController.java
+++ b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/controller/ConfigurationController.java
@@ -1,6 +1,7 @@
 package cz.zcu.fav.kiv.antipatterndetectionapp.v2.controller;
 
 import com.google.gson.Gson;
+import cz.zcu.fav.kiv.antipatterndetectionapp.v2.dials.ConfigurationControllerStatusCodes;
 import cz.zcu.fav.kiv.antipatterndetectionapp.v2.model.*;
 import cz.zcu.fav.kiv.antipatterndetectionapp.v2.service.ConfigService;
 import cz.zcu.fav.kiv.antipatterndetectionapp.v2.utils.JSONBuilder;
@@ -24,22 +25,65 @@ public class ConfigurationController {
     @Autowired
     private ConfigService configurationService;
 
+    /**
+     * Endpoint for user to save his custom configuration
+     * @param userConfiguration Wrapper around http request - contains User and Configuration objects
+     *                          which point to the user uploading the configuration and the definition of his configuration
+     * @return ResponseEntity with json body  appropriate status code indicating result of the operation
+     */
     @PostMapping(value="/upload_configuration")
-    public ResponseEntity<String> test(@RequestBody UserConfiguration userConfiguration) {
-        ResponseEntity<String> response = configurationService.addConfiguration(userConfiguration);
-        return response;
+    public ResponseEntity<String> uploadConfiguration(@RequestBody UserConfiguration userConfiguration) {
+        ConfigurationControllerStatusCodes returnCode = configurationService.addConfiguration(userConfiguration);
+        String message = returnCode.getLabel();
+        Map<String,Object> json = new HashMap<>();
+        json.put("message",message);
+        //ResponseEntity<String> response = configurationService.addConfiguration(userConfiguration);
+        return new ResponseEntity<>(JSONBuilder.buildJSON(json),HttpStatus.valueOf(returnCode.getStatusCode()));
     }
 
+    /**
+     * Endpoint returns the definitions of configurations (ie the json objects) and their names
+     * @param user User querying the configurations
+     * @return ResponseEntity with json body  appropriate status code indicating result of the operation
+     *         200 with requested body if everything is okay
+     *         500 if db server died or no default configurations are present in the database
+     */
     @PostMapping(value="/configuration")
     public ResponseEntity<String> getUserConfigurations(@RequestBody User user) {
-        ResponseEntity<String> response = this.configurationService.getUserConfigurations(user);
-        return response;
+        Map<String, Object> json = new HashMap<>();
+        List<Configuration> configuration = this.configurationService.getUserConfigurations(user);
+        //this can only happen if db server is offline
+        //or no default configuration exists in database
+        if(configuration == null) {
+            json.put("message", "internal sever error");
+            return new ResponseEntity<>(JSONBuilder.buildJSON(json), HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+        //list of configuration definitions
+        List<String> configurationDefinition = new ArrayList<>();
+        //and their names
+        List<String> configurationNames = new ArrayList<>();
+        //hipster syntax for Petr
+        configuration.forEach(cfg -> {
+            configurationDefinition.add(cfg.getConfig());
+            configurationNames.add(cfg.getConfigurationName());
+        });
+        json.put("configuration",configurationDefinition);
+        json.put("configuration_names",configurationNames);
+
+        return new ResponseEntity<>(new Gson().toJson(json),HttpStatus.OK);
     }
 
+    /**
+     * Endpoint which retrieves configuration names and their ids
+     * @param user wrapper around username send in body of the request
+     * @return ResponseEntity with json body  appropriate status code indicating result of the operation
+     */
     @PostMapping(value="/configuration_name")
     public ResponseEntity<String> getConfigurationNames(@RequestBody User user) {
         Map<String, Object> json = new HashMap<>();
-        List<Configuration> configuration = this.configurationService.getConfigurationNamesAndIds(user);
+        List<Configuration> configuration = this.configurationService.getUserConfigurations(user);
+        //this can only happen if db server is offline
+        //or no default configuration exists in database
         if(configuration == null) {
             json.put("message", "internal sever error");
             return new ResponseEntity<>(JSONBuilder.buildJSON(json), HttpStatus.INTERNAL_SERVER_ERROR);
@@ -51,7 +95,7 @@ public class ConfigurationController {
             configurationIds.add(o.getId());
         }
 
-        HashMap<String, Object> toJsonString = new HashMap<>();
+        Map<String, Object> toJsonString = new HashMap<>();
         toJsonString.put("configuration_names", configurationNames);
         toJsonString.put("configuration_ids", configurationIds);
 
@@ -60,9 +104,4 @@ public class ConfigurationController {
 
 
 
-
-
-
-
-
 }
diff --git a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/dials/ConfigurationControllerStatusCodes.java b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/dials/ConfigurationControllerStatusCodes.java
new file mode 100644
index 0000000..527146d
--- /dev/null
+++ b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/dials/ConfigurationControllerStatusCodes.java
@@ -0,0 +1,36 @@
+package cz.zcu.fav.kiv.antipatterndetectionapp.v2.dials;
+
+/**
+ * enum codes for configuration service
+ * this enum is used by configuration controller for the purpose of building response entities
+ */
+public enum ConfigurationControllerStatusCodes {
+
+    EMPTY_CONFIGURATION_DEFINITION("No configuration definition provided",400),
+
+    INSERT_FAILED("Failed to save configuration",500),
+
+    INSERT_SUCCESSFUL("Configuration saved",200),
+
+    CONFIGURATION_PAIRING_EXISTS("Configuration already exists in your collection",400),
+    CONFIGURATION_PAIRING_CREATED("configuration added to collection",200);
+
+
+
+
+    private final String label;
+    private final int statusCode;
+
+    ConfigurationControllerStatusCodes(String s, int i) {
+        this.label = s;
+        this.statusCode = i;
+    }
+
+    public int getStatusCode(){
+        return this.statusCode;
+    }
+    public String getLabel(){
+        return this.label;
+    }
+
+}
diff --git a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/repository/ConfigRepository.java b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/repository/ConfigRepository.java
index 171a6b7..b606dbb 100644
--- a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/repository/ConfigRepository.java
+++ b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/repository/ConfigRepository.java
@@ -12,8 +12,7 @@ import org.springframework.stereotype.Repository;
 import java.util.List;
 @Repository
 public interface ConfigRepository extends JpaRepository<Configuration,Integer> {
-    @Value("${default_user_id}")
-    int defaultUserId = 0;
+
     Configuration findConfigurationById(int id);
     Configuration findConfigurationByConfigHash(String hash);
     //query to get all public configurations
@@ -24,7 +23,6 @@ public interface ConfigRepository extends JpaRepository<Configuration,Integer> {
     @Query("select config, userconfig from Configuration config left join UserConfigurationJoin userconfig on config.id = userconfig.id.configId where userconfig.id.userId = ?1 or config.isDefault = 'Y'")
     List<Object[]> getAllUserConfigurations(int userId);
 
-    //todo default user id parametrem
     @Query("select userconfig.configurationName,userconfig.id.configId from UserConfigurationJoin userconfig where userconfig.id.userId = ?1")
     List<Object[]> getAllUserConfigurationNames(int userId);
 
diff --git a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/service/ConfigService.java b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/service/ConfigService.java
index 033238e..f6bfa29 100644
--- a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/service/ConfigService.java
+++ b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/service/ConfigService.java
@@ -1,19 +1,19 @@
 package cz.zcu.fav.kiv.antipatterndetectionapp.v2.service;
+import cz.zcu.fav.kiv.antipatterndetectionapp.v2.dials.ConfigurationControllerStatusCodes;
 import cz.zcu.fav.kiv.antipatterndetectionapp.v2.model.Configuration;
 import cz.zcu.fav.kiv.antipatterndetectionapp.v2.model.User;
 import cz.zcu.fav.kiv.antipatterndetectionapp.v2.model.UserConfiguration;
-import org.springframework.http.ResponseEntity;
+
 import java.util.List;
 public interface ConfigService {
     //upload configuration
-    ResponseEntity<String> addConfiguration(Configuration cfg);
-    ResponseEntity<String> addConfiguration(UserConfiguration cfg);
+    ConfigurationControllerStatusCodes addConfiguration(Configuration cfg);
+    ConfigurationControllerStatusCodes addConfiguration(UserConfiguration cfg);
+
+    ConfigurationControllerStatusCodes pairConfigurationWithUser(User user, Configuration configuration);
 
-    ResponseEntity<String> pairConfigurationWithUser(User user, Configuration configuration);
-    //get all configurations available to user
-    ResponseEntity<String> getUserConfigurations(User user);
 
-    List<Configuration> getConfigurationNamesAndIds(User user);
+    List<Configuration> getUserConfigurations(User user);
 
     Configuration getConfigurationById(int id);
     String getConfigurationName(int userId, int configurationId);
diff --git a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/service/ConfigurationServiceImplementation.java b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/service/ConfigurationServiceImplementation.java
index f51e03e..44ee7b9 100644
--- a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/service/ConfigurationServiceImplementation.java
+++ b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/service/ConfigurationServiceImplementation.java
@@ -1,20 +1,15 @@
 package cz.zcu.fav.kiv.antipatterndetectionapp.v2.service;
 
-import com.google.gson.Gson;
+import cz.zcu.fav.kiv.antipatterndetectionapp.v2.dials.ConfigurationControllerStatusCodes;
 import cz.zcu.fav.kiv.antipatterndetectionapp.v2.model.*;
 import cz.zcu.fav.kiv.antipatterndetectionapp.v2.repository.ConfigRepository;
 import cz.zcu.fav.kiv.antipatterndetectionapp.v2.repository.UserConfigurationJoinRepository;
 import cz.zcu.fav.kiv.antipatterndetectionapp.v2.utils.Crypto;
-import cz.zcu.fav.kiv.antipatterndetectionapp.v2.utils.JSONBuilder;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Service;
 
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 @Service
 public class ConfigurationServiceImplementation implements ConfigService {
@@ -34,7 +29,7 @@ public class ConfigurationServiceImplementation implements ConfigService {
      * @return ResponseEntity with status code and message with more information about operation
      */
     @Override
-    public ResponseEntity<String> addConfiguration(Configuration cfg) {
+    public ConfigurationControllerStatusCodes addConfiguration(Configuration cfg) {
         return null;
     }
     /**
@@ -44,20 +39,17 @@ public class ConfigurationServiceImplementation implements ConfigService {
      * @return ResponseEntity with status code and message with more information about operation
      */
     @Override
-    public ResponseEntity<String> addConfiguration(UserConfiguration cfg) {
+    public ConfigurationControllerStatusCodes addConfiguration(UserConfiguration cfg) {
         User user = cfg.getUser();
         Configuration configuration = cfg.getConfiguration();
 
-        Map<String,Object> json = new HashMap<>();
         String userName = user.getName();
         //fetch the user from db because user in UserConfiguration does not contain id
         user = this.userService.getUserByName(userName);
         String configurationDefinition = configuration.getConfig();
         //if the request is missing the configuration definition then we kill it
-        if(configurationDefinition == null){
-            json.put("message","no configuration definition provided.");
-            String jsonString = JSONBuilder.buildJSON(json);
-            return new ResponseEntity<>(jsonString,HttpStatus.BAD_REQUEST);
+        if(configurationDefinition == null) {
+            return ConfigurationControllerStatusCodes.EMPTY_CONFIGURATION_DEFINITION;
         }
         //create the hash of the configuration (w/o salting)
         String configHash = Crypto.hashString(configurationDefinition);
@@ -69,14 +61,12 @@ public class ConfigurationServiceImplementation implements ConfigService {
             Configuration tmp = this.configurationRepository.save(configuration);
             //can only happen if db server fails or a constraint is breached
             if(tmp == null){
-                json.put("message","fatal server failure");
-                return new ResponseEntity<>(JSONBuilder.buildJSON(json),HttpStatus.INTERNAL_SERVER_ERROR);
+                return ConfigurationControllerStatusCodes.INSERT_FAILED;
             }
         }
         //pair the configuration to the user
         pairConfigurationWithUser(user,configuration);
-        json.put("message","configuration uploaded successfully");
-        return new ResponseEntity<>(JSONBuilder.buildJSON(json),HttpStatus.OK);
+        return ConfigurationControllerStatusCodes.INSERT_SUCCESSFUL;
 
 
     }
@@ -90,40 +80,29 @@ public class ConfigurationServiceImplementation implements ConfigService {
      * @return ResponseEntity<String> - Http response with status code and message about the operation
      */
     @Override
-    public ResponseEntity<String> pairConfigurationWithUser(User user, Configuration configuration) {
-        Map<String,Object> json = new HashMap<>();
+    public ConfigurationControllerStatusCodes pairConfigurationWithUser(User user, Configuration configuration) {
         final UserConfigKey key = new UserConfigKey(user.getId(),configuration.getId());
         boolean exists = this.userConfigurationJoinRepository.existsById(key);
         //the configuration pairing already exists, we do not have to do anything
         //request like this should not happen from client, something fishy might be going on
         //or the request is a duplicate
-        if(exists){
-            json.put("message","configuration already exists in your collection!");
-            return new ResponseEntity<>(JSONBuilder.buildJSON(json),HttpStatus.BAD_REQUEST);
+        if(exists) {
+            return ConfigurationControllerStatusCodes.CONFIGURATION_PAIRING_EXISTS;
         }
         //save the relation between user and configuration
         this.userConfigurationJoinRepository.save(new UserConfigurationJoin(key,configuration.getConfigurationName()));
-        json.put("message","configuration added to collection.");
-        return new ResponseEntity<>(JSONBuilder.buildJSON(json),HttpStatus.OK);
+        return ConfigurationControllerStatusCodes.CONFIGURATION_PAIRING_CREATED;
     }
 
-    @Override
-    public ResponseEntity<String> getUserConfigurations(User user) {
-        final String userName = user.getName();
-        //client can only send his name - he obviously does not know his id in db, we have to query that
-        User userInfo = this.userService.getUserByName(userName);
-        //fetch all configurations this particular user can see
-        //ie all public configs + configurations uploaded by this particular user
-        List<Object[]> configurations = this.configurationRepository.getAllUserConfigurations(userInfo.getId());
-//        Map<String,Object> json = new HashMap<>();
-//        json.put("message","configuration retrived");
-//        json.put("configurations",configurations);
-//        String jsonString = JSONBuilder.buildJSON(json);
-        return new ResponseEntity<>(new Gson().toJson(configurations),HttpStatus.OK);
-    }
 
+    /**
+     * Method queries db to retrieve all configurations available to @param user
+     * if he/she does not have any of his/her (inclusive for netflix) only default configurations are returned
+     * @param user user querying configuration - ONLY username is valid in this object
+     * @return List<Configuration> list of available configurations
+     */
     @Override
-    public List<Configuration> getConfigurationNamesAndIds(User user) {
+    public List<Configuration> getUserConfigurations(User user) {
         final String userName = user.getName();
         if(userName == null){
             return null;
@@ -144,7 +123,7 @@ public class ConfigurationServiceImplementation implements ConfigService {
         }
         return configurationList;
     }
-
+    //Wrappers around db connection to configuration table
     @Override
     public Configuration getConfigurationById(int id) {
         return this.configurationRepository.findConfigurationById(id);
diff --git a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/service/UserServiceImpl.java b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/service/UserServiceImpl.java
index 1fbdb48..100bce9 100644
--- a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/service/UserServiceImpl.java
+++ b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/service/UserServiceImpl.java
@@ -6,11 +6,6 @@ import cz.zcu.fav.kiv.antipatterndetectionapp.v2.repository.UserRepository;
 import cz.zcu.fav.kiv.antipatterndetectionapp.v2.utils.Crypto;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-
-import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
-import java.nio.charset.StandardCharsets;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
 import java.util.regex.Pattern;
 
 /**
diff --git a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/utils/JSONBuilder.java b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/utils/JSONBuilder.java
index 19919f2..64ae230 100644
--- a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/utils/JSONBuilder.java
+++ b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/utils/JSONBuilder.java
@@ -1,7 +1,5 @@
 package cz.zcu.fav.kiv.antipatterndetectionapp.v2.utils;
-import com.fasterxml.jackson.databind.JsonNode;
 import com.google.gson.Gson;
-import cz.zcu.fav.kiv.antipatterndetectionapp.utils.JsonParser;
 import cz.zcu.fav.kiv.antipatterndetectionapp.v2.model.AntiPatternDto;
 import cz.zcu.fav.kiv.antipatterndetectionapp.v2.model.ConfigurationDto;
 import cz.zcu.fav.kiv.antipatterndetectionapp.v2.model.ThresholdDto;
@@ -10,7 +8,6 @@ import org.json.simple.JSONObject;
 import org.json.simple.parser.JSONParser;
 import org.json.simple.parser.ParseException;
 
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
diff --git a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/utils/RequestBuilder.java b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/utils/RequestBuilder.java
index a39571e..c57b79a 100644
--- a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/utils/RequestBuilder.java
+++ b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/utils/RequestBuilder.java
@@ -1,23 +1,14 @@
 package cz.zcu.fav.kiv.antipatterndetectionapp.v2.utils;
 
 import cz.zcu.fav.kiv.antipatterndetectionapp.v2.httpErrorHandler.CustomErrorHandler;
-import org.json.simple.JSONObject;
 import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
 import org.springframework.stereotype.Component;
-import org.springframework.web.client.HttpClientErrorException;
-import org.springframework.web.client.HttpServerErrorException;
-import org.springframework.web.client.HttpStatusCodeException;
 import org.springframework.web.client.RestTemplate;
-
-import java.util.HashMap;
 import java.util.Map;
-import java.util.Optional;
+import java.util.logging.Level;
 import java.util.logging.Logger;
-
 import org.springframework.http.*;
 
-import javax.servlet.http.HttpServletRequest;
-
 @Component
 public class RequestBuilder {
     private static Logger logger = Logger.getLogger(RequestBuilder.class.getName());
@@ -31,6 +22,8 @@ public class RequestBuilder {
         HttpHeaders headers = new HttpHeaders();
         headers.setContentType(MediaType.APPLICATION_JSON);
         //headers.set("X-spade-request",spadeSignature);
+        logger.log(Level.FINE,"Sending http request with body: \n"+json+"\n to: "+url);
+
         HttpEntity<String> entity = new HttpEntity<>(json, headers);
         return restTemplate.postForEntity(url, entity, String.class);
     }
@@ -45,7 +38,7 @@ public class RequestBuilder {
         headers.setContentType(MediaType.APPLICATION_JSON);
         //headers.set("X-spade-request",spadeSignature);
         headers.set("Authorization", "Bearer " + token);
-
+        logger.log(Level.FINE,"Sending http request with no body to: "+url);
         HttpEntity<String> entity = new HttpEntity<>(null, headers);
         ResponseEntity<String> response = restTemplate.postForEntity(url, entity, String.class);
         return response;
