Added delete-config & tests; updated lib & java versions; fixed bugs.

Change-Id: I7a2a7d316b28e856062b678a70d9c0d251ed1ee8
diff --git a/full/src/main/java/de/ids_mannheim/korap/config/FullConfiguration.java b/full/src/main/java/de/ids_mannheim/korap/config/FullConfiguration.java
index 8fdf556..7b9c48c 100644
--- a/full/src/main/java/de/ids_mannheim/korap/config/FullConfiguration.java
+++ b/full/src/main/java/de/ids_mannheim/korap/config/FullConfiguration.java
@@ -31,6 +31,10 @@
 
     private String authenticationScheme;
 
+    private boolean isSoftDeleteAutoGroup;
+    private boolean isSoftDeleteGroup;
+    private boolean isSoftDeleteGroupMember;
+
     public FullConfiguration (Properties properties) throws IOException {
         super(properties);
     }
@@ -44,23 +48,35 @@
 
         // EM: pattern for matching availability in Krill matches
         setLicensePatterns(properties);
-
+        setDeleteConfiguration(properties);
         ldapConfig = properties.getProperty("ldap.config");
     }
 
+    private void setDeleteConfiguration (Properties properties) {
+        setSoftDeleteGroup(parseDeleteConfig(properties.getProperty("delete.group", "")));
+        setSoftDeleteAutoGroup(parseDeleteConfig(properties.getProperty("delete.auto.group", "")));
+        setSoftDeleteGroupMember(parseDeleteConfig(
+                properties.getProperty("delete.group.member", "")));
+    }
+
+    private boolean parseDeleteConfig (String deleteConfig) {
+        return deleteConfig.equals("soft") ? true : false;
+    }
+
     private void setLicensePatterns (Properties properties) {
         setFreeLicensePattern(compilePattern(getFreeOnlyRegex()));
-        setPublicLicensePattern(
-                compilePattern(getFreeOnlyRegex() + "|" + getPublicOnlyRegex()));
-        setAllLicensePattern(compilePattern(
-                getFreeOnlyRegex() + "|" + getPublicOnlyRegex() + "|" + getAllOnlyRegex()));
+        setPublicLicensePattern(compilePattern(
+                getFreeOnlyRegex() + "|" + getPublicOnlyRegex()));
+        setAllLicensePattern(compilePattern(getFreeOnlyRegex() + "|"
+                + getPublicOnlyRegex() + "|" + getAllOnlyRegex()));
     }
 
     private void setLicenseRegex (Properties properties) {
         setFreeOnlyRegex(properties.getProperty("availability.regex.free", ""));
         freeRegexList = splitAndAddToList(getFreeOnlyRegex());
 
-        setPublicOnlyRegex(properties.getProperty("availability.regex.public", ""));
+        setPublicOnlyRegex(
+                properties.getProperty("availability.regex.public", ""));
         publicRegexList = splitAndAddToList(getPublicOnlyRegex());
 
         setAllOnlyRegex(properties.getProperty("availability.regex.all", ""));
@@ -76,7 +92,7 @@
                 list.add(s.trim());
             }
         }
-        else{
+        else {
             list = new ArrayList<>(1);
             list.add(regex);
         }
@@ -177,4 +193,28 @@
         this.allOnlyRegex = allOnlyRegex;
     }
 
+    public boolean isSoftDeleteGroup () {
+        return isSoftDeleteGroup;
+    }
+
+    public void setSoftDeleteGroup (boolean isSoftDeleteGroup) {
+        this.isSoftDeleteGroup = isSoftDeleteGroup;
+    }
+
+    public boolean isSoftDeleteGroupMember () {
+        return isSoftDeleteGroupMember;
+    }
+
+    public void setSoftDeleteGroupMember (boolean isSoftDeleteGroupMember) {
+        this.isSoftDeleteGroupMember = isSoftDeleteGroupMember;
+    }
+
+    public boolean isSoftDeleteAutoGroup () {
+        return isSoftDeleteAutoGroup;
+    }
+
+    public void setSoftDeleteAutoGroup (boolean isSoftDeleteAutoGroup) {
+        this.isSoftDeleteAutoGroup = isSoftDeleteAutoGroup;
+    }
+
 }
diff --git a/full/src/main/java/de/ids_mannheim/korap/dao/UserGroupMemberDao.java b/full/src/main/java/de/ids_mannheim/korap/dao/UserGroupMemberDao.java
index aeb413e..9803461 100644
--- a/full/src/main/java/de/ids_mannheim/korap/dao/UserGroupMemberDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/dao/UserGroupMemberDao.java
@@ -60,12 +60,18 @@
         entityManager.persist(member);
     }
 
-    public void deleteMember (String userId, int groupId, String deletedBy, boolean isSoftDelete)
-            throws KustvaktException {
+    public void deleteMember (String userId, int groupId, String deletedBy,
+            boolean isSoftDelete) throws KustvaktException {
         ParameterChecker.checkStringValue(userId, "userId");
         ParameterChecker.checkIntegerValue(groupId, "groupId");
 
         UserGroupMember member = retrieveMemberById(userId, groupId);
+        GroupMemberStatus status = member.getStatus();
+        if (isSoftDelete && status.equals(GroupMemberStatus.DELETED)) {
+            throw new KustvaktException(StatusCodes.DB_ENTRY_DELETED,
+                    userId + " has already been deleted from the group.",
+                    userId);
+        }
 
         if (isSoftDelete) {
             member.setStatus(GroupMemberStatus.DELETED);
diff --git a/full/src/main/java/de/ids_mannheim/korap/handlers/EntityDao.java b/full/src/main/java/de/ids_mannheim/korap/handlers/EntityDao.java
index 3d75697..8577a1b 100644
--- a/full/src/main/java/de/ids_mannheim/korap/handlers/EntityDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/handlers/EntityDao.java
@@ -266,12 +266,12 @@
             jlog.error("Could not create user account with username: {}",
                     user.getUsername());
             throw new DatabaseException(e, user.getUsername(), "korap_users",
-                    StatusCodes.ENTRY_EXISTS, "Username exists.",
+                    StatusCodes.DB_ENTRY_EXISTS, "Username exists.",
                     user.getUsername());
         }
         catch (DataAccessException e) {
             throw new DatabaseException(e, user.getUsername(), "korap_users",
-                    StatusCodes.ENTRY_EXISTS, "Username exists.",
+                    StatusCodes.DB_ENTRY_EXISTS, "Username exists.",
                     user.getUsername());
         }
 
diff --git a/full/src/main/java/de/ids_mannheim/korap/service/UserGroupService.java b/full/src/main/java/de/ids_mannheim/korap/service/UserGroupService.java
index 02cff45..15f6052 100644
--- a/full/src/main/java/de/ids_mannheim/korap/service/UserGroupService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/service/UserGroupService.java
@@ -7,6 +7,7 @@
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import de.ids_mannheim.korap.config.FullConfiguration;
 import de.ids_mannheim.korap.constant.GroupMemberStatus;
 import de.ids_mannheim.korap.constant.PredefinedRole;
 import de.ids_mannheim.korap.constant.UserGroupStatus;
@@ -46,6 +47,8 @@
     private UserGroupConverter converter;
     @Autowired
     private AuthenticationManagerIface authManager;
+    @Autowired
+    private FullConfiguration config;
 
     private static List<Role> memberRoles;
 
@@ -91,7 +94,7 @@
                 break;
             }
         }
-        
+
         return members;
     }
 
@@ -175,7 +178,13 @@
         User user = authManager.getUser(username);
         UserGroup userGroup = userGroupDao.retrieveGroupById(groupId);
         if (userGroup.getCreatedBy().equals(username) || user.isSystemAdmin()) {
-            userGroupDao.deleteGroup(groupId, username, false);
+            // soft delete
+            userGroupDao.deleteGroup(groupId, username,
+                    config.isSoftDeleteGroup());
+        }
+        else {
+            throw new KustvaktException(StatusCodes.AUTHORIZATION_FAILED,
+                    "Unauthorized operation for user: " + username, username);
         }
     }
 
@@ -190,7 +199,7 @@
     public void deleteAutoHiddenGroup (int groupId, String deletedBy)
             throws KustvaktException {
         // default hard delete
-        userGroupDao.deleteGroup(groupId, deletedBy, false);
+        userGroupDao.deleteGroup(groupId, deletedBy, config.isSoftDeleteAutoGroup());
     }
 
     /** Adds a user to the specified usergroup. If the username with 
@@ -216,9 +225,10 @@
         ParameterChecker.checkIntegerValue(groupId, "userGroupId");
 
         if (memberExists(username, groupId, status)) {
-            throw new KustvaktException(StatusCodes.ENTRY_EXISTS,
-                    "Username: " + username + " with status " + status
-                            + " exists in usergroup " + userGroup.getName());
+            throw new KustvaktException(StatusCodes.DB_ENTRY_EXISTS,
+                    "Username " + username + " with status " + status
+                            + " exists in user-group " + userGroup.getName(),
+                    username, status.name(), userGroup.getName());
         }
 
         setMemberRoles();
@@ -250,7 +260,7 @@
             return true;
         }
         else if (existingStatus.equals(GroupMemberStatus.DELETED)) {
-            // hard delete
+            // hard delete, not customizable
             groupMemberDao.deleteMember(username, groupId, "system", false);
         }
 
@@ -312,7 +322,8 @@
      */
     public void unsubscribe (int groupId, String username)
             throws KustvaktException {
-        groupMemberDao.deleteMember(username, groupId, username, true);
+        groupMemberDao.deleteMember(username, groupId, username,
+                config.isSoftDeleteGroupMember());
     }
 
 
@@ -340,7 +351,9 @@
         }
         else if (isUserGroupAdmin(deletedBy, userGroup)
                 || user.isSystemAdmin()) {
-            groupMemberDao.deleteMember(memberId, groupId, deletedBy, false);
+            // soft delete
+            groupMemberDao.deleteMember(memberId, groupId, deletedBy,
+                    config.isSoftDeleteGroupMember());
         }
         else {
             throw new KustvaktException(StatusCodes.AUTHORIZATION_FAILED,
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupController.java
index 2ddec6f..ad92c84 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupController.java
@@ -111,6 +111,12 @@
         }
     }
 
+    /** Only group owner and system admins can delete groups. 
+     * 
+     * @param securityContext
+     * @param groupId
+     * @return HTTP 200, if successful.
+     */
     @DELETE
     @Path("delete")
     @Consumes(MediaType.APPLICATION_JSON)
diff --git a/full/src/main/resources/kustvakt.conf b/full/src/main/resources/kustvakt.conf
index ee3bb7d..d8ff39d 100644
--- a/full/src/main/resources/kustvakt.conf
+++ b/full/src/main/resources/kustvakt.conf
@@ -17,6 +17,11 @@
 default.layer.d = mate
 default.layer.c = corenlp
 
+## delete configuration (default hard)
+# delete.auto.group = hard
+delete.group = soft
+delete.group.member = soft
+
 ## availability regex
 ## only support |
 availability.regex.free = CC-BY.*