From 6953c2ab479761d6fcfbfa702bcb0dd79b1d875c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sven=20K=C3=A4stle?= <sven.kaestle@gmx.de>
Date: Tue, 4 Sep 2018 17:02:33 +0200
Subject: [PATCH] feat: Implement server side boundary check for new body
 elements

---
 .../controller/SubmissionController.java      | 151 +++++++++++++++++-
 1 file changed, 148 insertions(+), 3 deletions(-)

diff --git a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/submission/controller/SubmissionController.java b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/submission/controller/SubmissionController.java
index 305311e2..b3b86098 100644
--- a/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/submission/controller/SubmissionController.java
+++ b/gemeinsamforschen/src/main/java/unipotsdam/gf/modules/submission/controller/SubmissionController.java
@@ -116,10 +116,52 @@ public class SubmissionController implements ISubmission {
         String request = "INSERT IGNORE INTO submissionparts (`userId`, `fullSubmissionId`, `category`) VALUES (?,?,?);";
         connection.issueInsertOrDeleteStatement(request, submissionPartPostRequest.getUserId(), submissionPartPostRequest.getFullSubmissionId(), submissionPartPostRequest.getCategory().toString().toUpperCase());
 
-        // build and execute body requests
-        String requestElement = "INSERT IGNORE INTO submissionpartbodyelements (`fullSubmissionId`, `category`, `text`, `startCharacter`, `endCharacter`) VALUES (?,?,?,?,?)";
+        // declare request string
+        String requestElement;
         for (SubmissionPartBodyElement element : submissionPartPostRequest.getBody()) {
-            connection.issueInsertOrDeleteStatement(requestElement, submissionPartPostRequest.getFullSubmissionId(), submissionPartPostRequest.getCategory().toString().toUpperCase(), element.getText(), element.getStartCharacter(), element.getEndCharacter());
+
+            // calculate how many similar elements are next to the new element
+            int similarElements = numOfSimilarBodyElements(submissionPartPostRequest.getFullSubmissionId(), submissionPartPostRequest.getCategory(), element.getStartCharacter(), element.getEndCharacter());
+
+            switch (similarElements) {
+                // similar element on the left side
+                case -1:
+                    requestElement = "UPDATE submissionpartbodyelements SET endCharacter = ? WHERE fullSubmissionId = ? AND category = ? AND endCharacter = ?;";
+                    connection.issueUpdateStatement(requestElement, element.getEndCharacter(), submissionPartPostRequest.getFullSubmissionId(), submissionPartPostRequest.getCategory(), element.getStartCharacter());
+                    break;
+                // no similar element
+                case 0:
+                    if (!hasOverlappingBoundaries(submissionPartPostRequest.getFullSubmissionId(), submissionPartPostRequest.getCategory(), element)) {
+                        requestElement = "INSERT IGNORE INTO submissionpartbodyelements (`fullSubmissionId`, `category`, `text`, `startCharacter`, `endCharacter`) VALUES (?,?,?,?,?);";
+                        connection.issueInsertOrDeleteStatement(requestElement, submissionPartPostRequest.getFullSubmissionId(), submissionPartPostRequest.getCategory().toString().toUpperCase(), element.getText(), element.getStartCharacter(), element.getEndCharacter());
+                    }
+                    break;
+                // similar element on the right side
+                case 1:
+                    requestElement = "UPDATE submissionpartbodyelements SET startCharacter = ? WHERE fullSubmissionId = ? AND category = ? AND startCharacter = ?;";
+                    connection.issueUpdateStatement(requestElement, element.getStartCharacter(), submissionPartPostRequest.getFullSubmissionId(), submissionPartPostRequest.getCategory(), element.getEndCharacter());
+                    break;
+                // similar elements on both sides
+                case 2:
+                    // fetch end character from right element
+                    requestElement = "SELECT endCharacter FROM submissionpartbodyelements WHERE fullSubmissionId = ? AND category = ? AND startCharacter = ?;";
+                    VereinfachtesResultSet rs = connection.issueSelectStatement(requestElement, submissionPartPostRequest.getFullSubmissionId(), submissionPartPostRequest.getCategory(), element.getEndCharacter());
+
+                    // delete right element
+                    String deleteElement = "DELETE FROM submissionpartbodyelements WHERE fullSubmissionId = ? AND category = ? AND startCharacter = ?;";
+                    connection.issueInsertOrDeleteStatement(deleteElement, submissionPartPostRequest.getFullSubmissionId(), submissionPartPostRequest.getCategory(), element.getEndCharacter());
+
+                    if (rs.next()) {
+                        int end = rs.getInt("endCharacter");
+
+                        // update left element
+                        String updateElement = "UPDATE submissionpartbodyelements SET endCharacter = ? WHERE fullSubmissionId = ? AND category = ? AND endCharacter = ?;";
+                        connection.issueUpdateStatement(updateElement, end, submissionPartPostRequest.getFullSubmissionId(), submissionPartPostRequest.getCategory(), element.getStartCharacter());
+
+                    }
+
+            }
+
         }
 
         // get the new submission from database
@@ -329,4 +371,107 @@ public class SubmissionController implements ISubmission {
         return submissionParts;
     }
 
+    /**
+     * Calculates how many similar body elements (based on start and end character) can be found in the database
+     *
+     * @param fullSubmissionId The id of the full submission
+     * @param category The category of the submission part
+     * @param startCharacter The start character of the new element
+     * @param endCharacter The end character of the old element
+     * @return Return 0 if there are no similar elements, 2 if we found two similar elements (right and left side),
+     * 1 if we found a similar element on the right side and -1 if we found a similar element on the left side.
+     */
+    private int numOfSimilarBodyElements(String fullSubmissionId, Category category, int startCharacter, int endCharacter) {
+        // establish connection
+        MysqlConnect connection = new MysqlConnect();
+        connection.connect();
+
+        // build and execute request
+        String request = "SELECT COUNT(*) AS `count` FROM submissionpartbodyelements WHERE fullSubmissionId = ? AND category = ? AND (endCharacter = ? OR startCharacter = ?);";
+        VereinfachtesResultSet rs = connection.issueSelectStatement(request, fullSubmissionId, category.toString().toUpperCase(), startCharacter, endCharacter);
+
+        if (rs.next()) {
+            // save the response
+            int count = rs.getInt("count");
+
+            // found one element; left or right side
+            if (count == 1) {
+
+                // build and execute request to find out on which side we found a similar body element
+                String requestSide = "SELECT COUNT(*) AS `side` FROM submissionpartbodyelements WHERE fullSubmissionId = ? AND category = ? AND endCharacter = ?;";
+                VereinfachtesResultSet rsSide = connection.issueSelectStatement(requestSide, fullSubmissionId, category.toString().toUpperCase(), startCharacter);
+
+                if (rsSide.next()) {
+                    // save the response
+                    int side = rsSide.getInt("side");
+
+                    // close connection
+                    connection.close();
+
+                    if (side == 1) {
+                        return -1;
+                    }
+                    else {
+                        return 1;
+                    }
+
+                }
+            }
+            else {
+                // close connection
+                connection.close();
+
+                return count;
+            }
+        }
+
+        return 0;
+
+    }
+
+    /**
+     * Checks if a new body element has overlapping boundaries with an already existing element
+     *
+     * @param fullSubmissionId The id of the full submission
+     * @param category The category
+     * @param element The new element
+     * @return Returns true if overlapping boundaries have been found
+     */
+    private boolean hasOverlappingBoundaries(String fullSubmissionId, Category category, SubmissionPartBodyElement element) {
+
+        // establish connection
+        MysqlConnect connection = new MysqlConnect();
+        connection.connect();
+
+        // initialize start and end character
+        int start = element.getStartCharacter();
+        int end = element.getEndCharacter();
+
+        // build and execute request
+        String request = "SELECT COUNT(*) > 0 AS `exists` FROM submissionpartbodyelements WHERE fullSubmissionId = ? AND category = ? AND (" +
+                "(startCharacter <= ? AND ? <= endCharacter) OR " + // start character overlapping
+                "(startCharacter <= ? AND ? <= endCharacter));"; // end character overlapping
+        VereinfachtesResultSet rs = connection.issueSelectStatement(request, fullSubmissionId, category.toString(), start, start, end, end);
+
+        if (rs.next()) {
+            // save the response
+            int count = rs.getInt("exists");
+
+            // close connection
+            connection.close();
+
+            // return true if we found the id
+            if (count < 1) {
+                return false;
+            }
+            else {
+                return true;
+            }
+        }
+
+        // something happened
+        return true;
+
+    }
+
 }
-- 
GitLab