From f4c87d12186a05e7e7373b6656d3676ff9aa37f3 Mon Sep 17 00:00:00 2001
From: BEAUVAIS ANTOINE <antoine.beauvais@etu.unistra.fr>
Date: Tue, 21 Sep 2021 14:40:17 +0200
Subject: [PATCH] Added ability to query items by category.

---
 .../controller/ApiBadRequestException.java    | 18 +++++++
 .../back/api/controller/ApiErrorHandler.java  |  8 +++
 .../controller/ApiRetrieveInfoController.java | 34 ++++++++++--
 .../sil/erp/back/db/DatabaseInterface.java    |  7 +++
 .../sil/erp/back/db/DatabaseSQLiteImpl.java   | 53 +++++++++++++++++++
 5 files changed, 115 insertions(+), 5 deletions(-)
 create mode 100644 src/main/java/fr/unistra/sil/erp/back/api/controller/ApiBadRequestException.java

diff --git a/src/main/java/fr/unistra/sil/erp/back/api/controller/ApiBadRequestException.java b/src/main/java/fr/unistra/sil/erp/back/api/controller/ApiBadRequestException.java
new file mode 100644
index 0000000..645aa79
--- /dev/null
+++ b/src/main/java/fr/unistra/sil/erp/back/api/controller/ApiBadRequestException.java
@@ -0,0 +1,18 @@
+/*
+ * CONTRAT DE LICENCE DE LOGICIEL LIBRE CeCILL-B
+ * https://cecill.info/licences/Licence_CeCILL-B_V1-fr.html
+ */
+package fr.unistra.sil.erp.back.api.controller;
+
+/**
+ * HTTP error 400 Bad Request for the API.
+ * @author BEAUVAIS ANTOINE
+ */
+public class ApiBadRequestException extends Exception {
+    
+    public ApiBadRequestException(String errMsg)
+    {
+        super(errMsg);
+    }
+    
+}
diff --git a/src/main/java/fr/unistra/sil/erp/back/api/controller/ApiErrorHandler.java b/src/main/java/fr/unistra/sil/erp/back/api/controller/ApiErrorHandler.java
index baac2e5..749f936 100644
--- a/src/main/java/fr/unistra/sil/erp/back/api/controller/ApiErrorHandler.java
+++ b/src/main/java/fr/unistra/sil/erp/back/api/controller/ApiErrorHandler.java
@@ -27,4 +27,12 @@ public class ApiErrorHandler {
                 HttpStatus.INTERNAL_SERVER_ERROR);
     }
     
+    @ExceptionHandler(ApiBadRequestException.class)
+    public ResponseEntity<Object> handleBadRequest(Exception ex,
+            HttpServletRequest request, HttpServletResponse response)
+    {
+        return new ResponseEntity<>(new ErrorMessage(ex.getMessage()),
+                HttpStatus.BAD_REQUEST);
+    }
+    
 }
diff --git a/src/main/java/fr/unistra/sil/erp/back/api/controller/ApiRetrieveInfoController.java b/src/main/java/fr/unistra/sil/erp/back/api/controller/ApiRetrieveInfoController.java
index c29bfb6..5607af3 100644
--- a/src/main/java/fr/unistra/sil/erp/back/api/controller/ApiRetrieveInfoController.java
+++ b/src/main/java/fr/unistra/sil/erp/back/api/controller/ApiRetrieveInfoController.java
@@ -12,7 +12,10 @@ import fr.unistra.sil.erp.back.db.DatabaseInterface;
 import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
 /**
@@ -23,12 +26,16 @@ import org.springframework.web.bind.annotation.RestController;
 public class ApiRetrieveInfoController {
     
     /**
-     * Returns an Item as a JSON response.
-     * @return an Item.
+     * Returns all products as a JSON response.
+     * @param cat an optional category.
+     * @return a JSON response.
      * @throws fr.unistra.sil.erp.back.api.controller.ApiServerErrorException
+     * @throws fr.unistra.sil.erp.back.api.controller.ApiBadRequestException
      */
     @GetMapping(MAPPING_RETRIEVEALL)
-    public Object retrieveInfo() throws ApiServerErrorException
+    public ResponseEntity<Object> retrieveInfo(
+            @RequestParam(value = "category", defaultValue = "") String cat
+        ) throws ApiServerErrorException, ApiBadRequestException
     {
         DatabaseInterface db;
         try {
@@ -39,10 +46,27 @@ public class ApiRetrieveInfoController {
             throw new ApiServerErrorException("Failed to connect to database.");
         }
         
-        List<Item> res = db.getAllItems();
+        List<Item> res;
+        if(cat.equals(""))
+            res = db.getAllItems();
+        else
+        {
+            int category;
+            try
+            {
+                category = Integer.parseInt(cat);
+            }
+            catch(NumberFormatException ex)
+            {
+                throw new ApiBadRequestException("Category must be a integer.");
+            }
+            
+            res = db.getItemsFromCategory(category);
+        }
+        
         if(res == null)
             throw new ApiServerErrorException("Failed to query info.");
         
-        return res;
+        return new ResponseEntity<>(res, HttpStatus.OK);
     }
 }
diff --git a/src/main/java/fr/unistra/sil/erp/back/db/DatabaseInterface.java b/src/main/java/fr/unistra/sil/erp/back/db/DatabaseInterface.java
index 7248a26..645037e 100644
--- a/src/main/java/fr/unistra/sil/erp/back/db/DatabaseInterface.java
+++ b/src/main/java/fr/unistra/sil/erp/back/db/DatabaseInterface.java
@@ -23,4 +23,11 @@ public interface DatabaseInterface {
      */
     public List<Item> getAllItems();
     
+    /**
+     * Returns the list of all items for a given category.
+     * @param category the category's identifier.
+     * @return the list of items.
+     */
+    public List<Item> getItemsFromCategory(int category);
+    
 }
diff --git a/src/main/java/fr/unistra/sil/erp/back/db/DatabaseSQLiteImpl.java b/src/main/java/fr/unistra/sil/erp/back/db/DatabaseSQLiteImpl.java
index f0d4f92..e8f5143 100644
--- a/src/main/java/fr/unistra/sil/erp/back/db/DatabaseSQLiteImpl.java
+++ b/src/main/java/fr/unistra/sil/erp/back/db/DatabaseSQLiteImpl.java
@@ -7,6 +7,7 @@ package fr.unistra.sil.erp.back.db;
 import fr.unistra.sil.erp.back.api.model.Item;
 import java.sql.Connection;
 import java.sql.DriverManager;
+import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
@@ -25,6 +26,9 @@ public class DatabaseSQLiteImpl implements DatabaseInterface {
     private static final String SQL_GETALLITEMS = 
             "SELECT ref, name, price, subscriberPrice, category FROM items";
     
+    private static final String SQL_GETITEMSFROMCATEGORY = SQL_GETALLITEMS +
+            " WHERE category = ?";
+    
     private Connection conn;
     
     public DatabaseSQLiteImpl()
@@ -77,5 +81,54 @@ public class DatabaseSQLiteImpl implements DatabaseInterface {
         
         return res;
     }
+
+    @Override
+    public List<Item> getItemsFromCategory(int category) {
+        
+        PreparedStatement ps;
+        try {
+            ps = this.conn.prepareStatement(
+                    SQL_GETITEMSFROMCATEGORY);
+        } catch (SQLException ex) {
+            Logger.getLogger(DatabaseSQLiteImpl.class.getName()).log(
+                    Level.SEVERE, "Failed to connect to database.", ex);
+            return null;
+        }
+        
+        try {
+            ps.setInt(1, category);
+        } catch (SQLException ex) {
+            Logger.getLogger(DatabaseSQLiteImpl.class.getName()).log(
+                    Level.SEVERE, "Failed to set query parameter.", ex);
+            return null;
+        }
+        
+        ResultSet rs;
+        try {
+            rs = ps.executeQuery();
+        } catch (SQLException ex) {
+            Logger.getLogger(DatabaseSQLiteImpl.class.getName()).log(
+                    Level.SEVERE, "Failed to fetch items for category " +
+                            category, ex);
+            return null;
+        }
+        
+        List<Item> res = new ArrayList<>();
+        try {
+            while(rs.next())
+            {
+                Item item = new Item(rs.getInt("ref"), rs.getString("name"),
+                                     rs.getBigDecimal("price"),
+                                     rs.getBigDecimal("subscriberPrice"),
+                                     rs.getInt("category"));
+                res.add(item);
+            }
+        } catch (SQLException ex) {
+            Logger.getLogger(DatabaseSQLiteImpl.class.getName()).log(
+                    Level.SEVERE, "Failed to parse results.", ex);
+        }
+        
+        return res;
+    }
     
 }
-- 
GitLab