Added search VC by id and delete VC-access tasks.

Change-Id: Ia062b95ec18f22da607e20236f71ff9fb20526c0
diff --git a/full/src/main/java/de/ids_mannheim/korap/dao/VirtualCorpusAccessDao.java b/full/src/main/java/de/ids_mannheim/korap/dao/VirtualCorpusAccessDao.java
index d5dc9b1..adae511 100644
--- a/full/src/main/java/de/ids_mannheim/korap/dao/VirtualCorpusAccessDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/dao/VirtualCorpusAccessDao.java
@@ -33,6 +33,23 @@
     @PersistenceContext
     private EntityManager entityManager;
 
+    public VirtualCorpusAccess retrieveAccessById (int accessId)
+            throws KustvaktException {
+        ParameterChecker.checkIntegerValue(accessId, "accessId");
+
+        CriteriaBuilder builder = entityManager.getCriteriaBuilder();
+        CriteriaQuery<VirtualCorpusAccess> query =
+                builder.createQuery(VirtualCorpusAccess.class);
+
+        Root<VirtualCorpusAccess> access =
+                query.from(VirtualCorpusAccess.class);
+        query.select(access);
+        query.where(
+                builder.equal(access.get(VirtualCorpusAccess_.id), accessId));
+        Query q = entityManager.createQuery(query);
+        return (VirtualCorpusAccess) q.getSingleResult();
+    }
+
     // for vca admins
     public List<VirtualCorpusAccess> retrieveActiveAccessByVC (int vcId)
             throws KustvaktException {
@@ -56,7 +73,7 @@
         Query q = entityManager.createQuery(query);
         return q.getResultList();
     }
-    
+
     // for system admins
     public List<VirtualCorpusAccess> retrieveAllAccessByVC (int vcId)
             throws KustvaktException {
@@ -95,7 +112,7 @@
         Query q = entityManager.createQuery(query);
         return q.getResultList();
     }
-    
+
     public List<VirtualCorpusAccess> retrieveActiveAccessByGroup (int groupId)
             throws KustvaktException {
         ParameterChecker.checkIntegerValue(groupId, "groupId");
@@ -109,11 +126,11 @@
         Join<VirtualCorpusAccess, UserGroup> accessVC =
                 access.join(VirtualCorpusAccess_.userGroup);
 
-        Predicate p = builder.and(
-                builder.equal(accessVC.get(UserGroup_.id), groupId),
-                builder.equal(access.get(VirtualCorpusAccess_.status),
-                        VirtualCorpusAccessStatus.ACTIVE));
-        
+        Predicate p =
+                builder.and(builder.equal(accessVC.get(UserGroup_.id), groupId),
+                        builder.equal(access.get(VirtualCorpusAccess_.status),
+                                VirtualCorpusAccessStatus.ACTIVE));
+
         query.select(access);
         query.where(p);
         Query q = entityManager.createQuery(query);
@@ -170,4 +187,9 @@
         vca.setStatus(status);
         entityManager.persist(vca);
     }
+
+    public void deleteAccess (VirtualCorpusAccess access) {
+        entityManager.remove(access);
+    }
+
 }
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 642d038..8cce326 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
@@ -160,6 +160,25 @@
 
         return groupId;
     }
+    
+    public void addUserToGroup (String username, UserGroup userGroup)
+            throws KustvaktException {
+        
+        List<Role> roles = new ArrayList<Role>(2);
+        roles.add(roleDao
+                .retrieveRoleById(PredefinedRole.USER_GROUP_MEMBER.getId()));
+        roles.add(roleDao
+                .retrieveRoleById(PredefinedRole.VC_ACCESS_MEMBER.getId()));
+        
+        UserGroupMember member = new UserGroupMember();
+        member.setCreatedBy("system");
+        member.setGroup(userGroup);
+        member.setRoles(roles);
+        member.setStatus(GroupMemberStatus.ACTIVE);
+        member.setUserId(username);
+        
+        groupMemberDao.addMember(member);
+    }
 
     /** Updates the {@link GroupMemberStatus} of a pending member 
      * to {@link GroupMemberStatus#ACTIVE}.
diff --git a/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java b/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java
index 56ebc87..5bf6180 100644
--- a/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java
@@ -15,6 +15,8 @@
 import com.fasterxml.jackson.databind.JsonNode;
 
 import de.ids_mannheim.korap.config.FullConfiguration;
+import de.ids_mannheim.korap.constant.GroupMemberStatus;
+import de.ids_mannheim.korap.constant.PredefinedUserGroup;
 import de.ids_mannheim.korap.constant.VirtualCorpusAccessStatus;
 import de.ids_mannheim.korap.constant.VirtualCorpusType;
 import de.ids_mannheim.korap.dao.VirtualCorpusAccessDao;
@@ -378,4 +380,55 @@
 
         return accessConverter.createVCADto(accessList);
     }
+
+    public void deleteVCAccess (String username, int accessId)
+            throws KustvaktException {
+
+        User user = authManager.getUser(username);
+
+        VirtualCorpusAccess access = accessDao.retrieveAccessById(accessId);
+        UserGroup userGroup = access.getUserGroup();
+        if (isVCAccessAdmin(userGroup, username) || user.isAdmin()) {
+            accessDao.deleteAccess(access);
+        }
+        else {
+            throw new KustvaktException(StatusCodes.AUTHORIZATION_FAILED,
+                    "Unauthorized operation for user: " + username, username);
+        }
+
+    }
+
+    public VirtualCorpusDto searchVCById (String username, int vcId)
+            throws KustvaktException {
+        User user = authManager.getUser(username);
+
+        VirtualCorpus vc = vcDao.retrieveVCById(vcId);
+        VirtualCorpusType type = vc.getType();
+
+        if (!user.isAdmin()) {
+            if (type.equals(VirtualCorpusType.PRIVATE)
+                    || type.equals(VirtualCorpusType.PROJECT)) {
+                throw new KustvaktException(StatusCodes.AUTHORIZATION_FAILED,
+                        "Unauthorized operation for user: " + username,
+                        username);
+            }
+            else if (VirtualCorpusType.PUBLISHED.equals(type)) {
+                // add user in auto group 
+                List<VirtualCorpusAccess> hiddenAccessList =
+                        accessDao.retrieveHiddenAccess(vcId);
+                for (VirtualCorpusAccess access : hiddenAccessList) {
+                    if (PredefinedUserGroup.ALL.getId() != access.getUserGroup()
+                            .getId()) {
+                        userGroupService.addUserToGroup(username,
+                                access.getUserGroup());
+                        break;
+                    }
+                }
+            }
+        }
+
+        String json = vc.getCorpusQuery();
+        String statistics = krill.getStatistics(json);
+        return converter.createVirtualCorpusDto(vc, statistics);
+    }
 }
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/StatisticController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/StatisticController.java
index 5f44f84..be74ec8 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/StatisticController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/StatisticController.java
@@ -51,32 +51,32 @@
 
     /**
      * Returns statistics of the virtual corpus defined by the given
-     * collectionQuery parameter.
+     * corpusQuery parameter.
      * 
      * @param context
      *            SecurityContext
      * @param locale
      *            Locale
-     * @param collectionQuery
+     * @param corpusQuery
      *            a collection query specifying a virtual corpus
      * @return statistics of the virtual corpus defined by the given
-     *         collectionQuery parameter.
+     *         corpusQuery parameter.
      */
     @GET
     public Response getStatistics (@Context SecurityContext context,
             @Context Locale locale,
-            @QueryParam("collectionQuery") String collectionQuery) {
+            @QueryParam("corpusQuery") String corpusQuery) {
 
-        if (collectionQuery == null || collectionQuery.isEmpty()) {
+        if (corpusQuery == null || corpusQuery.isEmpty()) {
             throw kustvaktResponseHandler
                     .throwit(new KustvaktException(StatusCodes.MISSING_ARGUMENT,
-                            "Parameter collectionQuery is missing.",
-                            "collectionQuery"));
+                            "Parameter corpusQuery is missing.",
+                            "corpusQuery"));
         }
 
 
         KoralCollectionQueryBuilder builder = new KoralCollectionQueryBuilder();
-        builder.with(collectionQuery);
+        builder.with(corpusQuery);
         String json = null;
         try {
             json = builder.toJSON();
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/VirtualCorpusController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/VirtualCorpusController.java
index 618b226..1c869b3 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/VirtualCorpusController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/VirtualCorpusController.java
@@ -7,6 +7,7 @@
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Context;
@@ -34,10 +35,15 @@
 import de.ids_mannheim.korap.web.filter.PiwikFilter;
 import de.ids_mannheim.korap.web.input.VirtualCorpusJson;
 
-/** VirtualCorpusController defines web APIs related to virtual corpus
+/** VirtualCorpusController defines web APIs related to virtual corpus (VC)
  * such as creating, deleting and listing user virtual corpora.
  * 
- * These APIs are only available to logged-in users.
+ * This class also includes APIs related to virtual corpus access (VCA) 
+ * such as sharing and publishing VCs. When a VC is published, it is shared 
+ * with all users, but not always listed like system VC. It is listed for 
+ * a user, once when he/she have searched for the VC.
+ * 
+ * All the APIs in this class are available to logged-in users.
  * 
  * @author margaretha
  *
@@ -57,7 +63,7 @@
     @Autowired
     private VirtualCorpusService service;
 
-    /** Creates a user VC, also for admins
+    /** Creates a user VC, also for system admins
      * 
      * @param securityContext
      * @param vc a JSON object describing the virtual corpus
@@ -107,6 +113,30 @@
         return Response.ok().build();
     }
 
+    /** Searches for a specific VC.
+     * 
+     * @param securityContext
+     * @param vcId a virtual corpus id
+     * @return a list of VCs
+     */
+    @GET
+    @Path("search/{vcId}")
+    public Response searchVC (@Context SecurityContext securityContext,
+            @PathParam("vcId") int vcId) {
+        String result;
+        TokenContext context =
+                (TokenContext) securityContext.getUserPrincipal();
+        try {
+            VirtualCorpusDto dto =
+                    service.searchVCById(context.getUsername(), vcId);
+            result = JsonUtils.toJSON(dto);
+        }
+        catch (KustvaktException e) {
+            throw responseHandler.throwit(e);
+        }
+        return Response.ok(result).build();
+    }
+
     /** Lists not only private VCs but all VCs available to a user.
      * 
      * @param securityContext
@@ -151,7 +181,7 @@
         return Response.ok(result).build();
     }
 
-    /** Only the VC owner and system admins can delete VCs. VC-access admins 
+    /** Only the VC owner and system admins can delete VCs. VCA admins 
      *  can delete VC-accesses e.g. of project VCs, but not the VCs 
      *  themselves. 
      * 
@@ -190,7 +220,7 @@
     //  }
 
     /** VC can only be shared with a group, not individuals. 
-     *  Only VC Access Admins are allowed to share VCs and 
+     *  Only VCA admins are allowed to share VCs and 
      *  the VCs must have been created by themselves.
      * 
      * @param securityContext
@@ -213,8 +243,30 @@
         return Response.ok().build();
     }
 
+    /** Only VCA Admins and system admins are allowed to delete a VC-access.
+     * 
+     * @param securityContext
+     * @param accessId
+     * @return
+     */
+    @DELETE
+    @Path("access/delete")
+    public Response deleteVCAccess (@Context SecurityContext securityContext,
+            @QueryParam("accessId") int accessId) {
+        TokenContext context =
+                (TokenContext) securityContext.getUserPrincipal();
+        try {
+            service.deleteVCAccess(context.getUsername(), accessId);
+        }
+        catch (KustvaktException e) {
+            throw responseHandler.throwit(e);
+        }
+        return Response.ok().build();
+    }
+
+
     /** Lists only active accesses to the specified virtual corpus.
-     * Only available to VCA admins.
+     * Only available to VCA and system admins.
      * 
      * @see VirtualCorpusAccessStatus
      * 
@@ -240,6 +292,13 @@
         return Response.ok(result).build();
     }
 
+    /** Lists all VC-accesses available for a group. 
+     *  Only available to VCA and system admins.
+     * 
+     * @param securityContext
+     * @param groupId a group id
+     * @return a list of VC-access
+     */
     @GET
     @Path("access/list/byGroup")
     public Response listVCAccessByGroup (
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/StatisticsControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/StatisticsControllerTest.java
index eee4016..b043d69 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/StatisticsControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/StatisticsControllerTest.java
@@ -31,10 +31,10 @@
     @Test
     public void testGetStatisticsNoResource ()
             throws JsonProcessingException, IOException {
-        String collectionQuery = "corpusSigle=WPD15";
+        String corpusQuery = "corpusSigle=WPD15";
         ClientResponse response = resource()
                 .path("statistics")
-                .queryParam("collectionQuery", collectionQuery)
+                .queryParam("corpusQuery", corpusQuery)
                 .get(ClientResponse.class);
 
         assert ClientResponse.Status.OK.getStatusCode() == response.getStatus();
@@ -47,12 +47,12 @@
 
 
     @Test
-    public void testGetStatisticsWithCollectionQuery1 ()
+    public void testGetStatisticsWithcorpusQuery1 ()
             throws JsonProcessingException, IOException {
-        String collectionQuery = "corpusSigle=GOE";
+        String corpusQuery = "corpusSigle=GOE";
         ClientResponse response = resource()
                 .path("statistics")
-                .queryParam("collectionQuery", collectionQuery)
+                .queryParam("corpusQuery", corpusQuery)
                 .get(ClientResponse.class);
 
         assert ClientResponse.Status.OK.getStatusCode() == response.getStatus();
@@ -65,11 +65,11 @@
 
 
     @Test
-    public void testGetStatisticsWithCollectionQuery2 ()
+    public void testGetStatisticsWithcorpusQuery2 ()
             throws JsonProcessingException, IOException {
         ClientResponse response = resource()
                 .path("statistics")
-                .queryParam("collectionQuery", "creationDate since 1810")
+                .queryParam("corpusQuery", "creationDate since 1810")
                 .get(ClientResponse.class);
         String ent = response.getEntity(String.class);
         JsonNode node = mapper.readTree(ent);
@@ -82,11 +82,11 @@
 
 
     @Test
-    public void testGetStatisticsWithWrongCollectionQuery ()
+    public void testGetStatisticsWithWrongcorpusQuery ()
             throws JsonProcessingException, IOException {
         ClientResponse response = resource()
                 .path("statistics")
-                .queryParam("collectionQuery", "creationDate geq 1810")
+                .queryParam("corpusQuery", "creationDate geq 1810")
                 .get(ClientResponse.class);
 
         assert ClientResponse.Status.BAD_REQUEST.getStatusCode() == response
@@ -102,11 +102,11 @@
 
 
     @Test
-    public void testGetStatisticsWithWrongCollectionQuery2 ()
+    public void testGetStatisticsWithWrongcorpusQuery2 ()
             throws JsonProcessingException, IOException {
         ClientResponse response = resource()
                 .path("statistics")
-                .queryParam("collectionQuery", "creationDate >= 1810")
+                .queryParam("corpusQuery", "creationDate >= 1810")
                 .get(ClientResponse.class);
 
         assertEquals(ClientResponse.Status.BAD_REQUEST.getStatusCode(),
@@ -121,7 +121,7 @@
 
     
     @Test
-    public void testGetStatisticsWithoutCollectionQuery ()
+    public void testGetStatisticsWithoutcorpusQuery ()
             throws JsonProcessingException, IOException {
         ClientResponse response = resource()
                 .path("statistics")
@@ -134,7 +134,7 @@
         JsonNode node = mapper.readTree(ent);
         assertEquals(node.at("/errors/0/0").asInt(), 105);
         assertEquals(node.at("/errors/0/1").asText(),
-                "Parameter collectionQuery is missing.");
-        assertEquals(node.at("/errors/0/2").asText(), "collectionQuery");
+                "Parameter corpusQuery is missing.");
+        assertEquals(node.at("/errors/0/2").asText(), "corpusQuery");
     }
 }
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java
index 4ceca9d..f55f0ea 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java
@@ -564,5 +564,13 @@
         assertEquals(2, node.at("/0/userGroupId").asInt());
         assertEquals("dory group", node.at("/0/userGroupName").asText());
     }
+ 
+    // share VC
+    @Test
+    public void testCreateDeleteAccess () {
+        // TODO Auto-generated method stub
+
+    }
+    
     
 }