Fixed share VC & delete VC-access; added sort VC by id & test cases.

Change-Id: I0f958a8ae56bcfdbb779cca9a2daf4ae34d7e4d5
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 1913d09..feba49a 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
@@ -190,6 +190,9 @@
     }
 
     public void deleteAccess (VirtualCorpusAccess access) {
+        if (!entityManager.contains(access)){
+            access = entityManager.merge(access);
+        }
         entityManager.remove(access);
     }
 
diff --git a/full/src/main/java/de/ids_mannheim/korap/dao/VirtualCorpusDao.java b/full/src/main/java/de/ids_mannheim/korap/dao/VirtualCorpusDao.java
index 1ca79d4..c0fd186 100644
--- a/full/src/main/java/de/ids_mannheim/korap/dao/VirtualCorpusDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/dao/VirtualCorpusDao.java
@@ -1,5 +1,7 @@
 package de.ids_mannheim.korap.dao;
 
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -220,7 +222,7 @@
         return q.getResultList();
     }
 
-    public Set<VirtualCorpus> retrieveVCByUser (String userId)
+    public List<VirtualCorpus> retrieveVCByUser (String userId)
             throws KustvaktException {
         ParameterChecker.checkStringValue(userId, "userId");
 
@@ -246,7 +248,11 @@
         Set<VirtualCorpus> vcSet = new HashSet<VirtualCorpus>();
         vcSet.addAll(vcList);
         vcSet.addAll(groupVC);
-        return vcSet;
+        
+        List<VirtualCorpus> merger = new ArrayList<VirtualCorpus>(vcSet.size());
+        merger.addAll(vcSet);
+        Collections.sort(merger);
+        return merger;
     }
 
     // for admins
diff --git a/full/src/main/java/de/ids_mannheim/korap/entity/VirtualCorpus.java b/full/src/main/java/de/ids_mannheim/korap/entity/VirtualCorpus.java
index f3060ba..78f9fff 100644
--- a/full/src/main/java/de/ids_mannheim/korap/entity/VirtualCorpus.java
+++ b/full/src/main/java/de/ids_mannheim/korap/entity/VirtualCorpus.java
@@ -34,7 +34,7 @@
 @Getter
 @Entity
 @Table(name = "virtual_corpus")
-public class VirtualCorpus {
+public class VirtualCorpus implements Comparable<VirtualCorpus>{
 
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
@@ -80,4 +80,15 @@
         VirtualCorpus vc = (VirtualCorpus) obj;
         return (this.id == vc.getId()) ? true : false;
     }
+
+    @Override
+    public int compareTo (VirtualCorpus o) {
+        if (this.getId() > o.getId()) {
+            return 1;
+        }
+        else if (this.getId() < o.getId()) {
+            return -1;
+        }
+        return 0;
+    }
 }
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 e7dd923..434bb47 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
@@ -1,10 +1,8 @@
 package de.ids_mannheim.korap.service;
 
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Set;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -78,12 +76,12 @@
 
     public List<VirtualCorpusDto> listVCByUser (String username)
             throws KustvaktException {
-        Set<VirtualCorpus> vcSet = vcDao.retrieveVCByUser(username);
-        return createVCDtos(vcSet);
+        List<VirtualCorpus> vcList = vcDao.retrieveVCByUser(username);
+        return createVCDtos(vcList);
     }
-
+    
     private ArrayList<VirtualCorpusDto> createVCDtos (
-            Collection<VirtualCorpus> vcList) throws KustvaktException {
+            List<VirtualCorpus> vcList) throws KustvaktException {
         ArrayList<VirtualCorpusDto> dtos = new ArrayList<>(vcList.size());
         VirtualCorpus vc;
         Iterator<VirtualCorpus> i = vcList.iterator();
@@ -285,14 +283,14 @@
         User user = authManager.getUser(username);
 
         VirtualCorpus vc = vcDao.retrieveVCById(vcId);
-        if (!username.equals(vc.getCreatedBy()) || !user.isAdmin()) {
+        if (!username.equals(vc.getCreatedBy()) && !user.isAdmin()) {
             throw new KustvaktException(StatusCodes.AUTHORIZATION_FAILED,
                     "Unauthorized operation for user: " + username, username);
         }
 
         UserGroup userGroup = userGroupService.retrieveUserGroupById(groupId);
 
-        if (!user.isAdmin() && !isVCAccessAdmin(userGroup, username)) {
+        if (!isVCAccessAdmin(userGroup, username) && !user.isAdmin()) {
             throw new KustvaktException(StatusCodes.AUTHORIZATION_FAILED,
                     "Unauthorized operation for user: " + username, username);
         }
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 1304b6f..98a45cd 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
@@ -4,6 +4,7 @@
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
+import javax.ws.rs.FormParam;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
@@ -191,9 +192,9 @@
      * @return HTTP status 200, if successful
      */
     @DELETE
-    @Path("delete")
+    @Path("delete/{vcId}")
     public Response deleteVC (@Context SecurityContext securityContext,
-            @QueryParam("vcId") int vcId) {
+            @PathParam("vcId") int vcId) {
         TokenContext context =
                 (TokenContext) securityContext.getUserPrincipal();
         try {
@@ -231,8 +232,9 @@
      */
     @POST
     @Path("access/share")
+    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
     public Response shareVC (@Context SecurityContext securityContext,
-            @QueryParam("vcId") int vcId, @QueryParam("groupId") int groupId) {
+            @FormParam("vcId") int vcId, @FormParam("groupId") int groupId) {
         TokenContext context =
                 (TokenContext) securityContext.getUserPrincipal();
         try {
@@ -251,9 +253,9 @@
      * @return
      */
     @DELETE
-    @Path("access/delete")
+    @Path("access/delete/{accessId}")
     public Response deleteVCAccess (@Context SecurityContext securityContext,
-            @QueryParam("accessId") int accessId) {
+            @PathParam("accessId") int accessId) {
         TokenContext context =
                 (TokenContext) securityContext.getUserPrincipal();
         try {
diff --git a/full/src/main/resources/db/insert/V3.1__insert_virtual_corpus.sql b/full/src/main/resources/db/insert/V3.1__insert_virtual_corpus.sql
index 62e22ed..c708076 100644
--- a/full/src/main/resources/db/insert/V3.1__insert_virtual_corpus.sql
+++ b/full/src/main/resources/db/insert/V3.1__insert_virtual_corpus.sql
@@ -72,7 +72,14 @@
 	VALUES ("published VC", "PUBLISHED", "ALL", "marlin", "test vc", "experimental",
 	'{"collection":{"@type":"koral:doc","value":"GOE","match":"match:eq","key":"corpusSigle"}}');
 
+INSERT INTO virtual_corpus(name, type, required_access, created_by, description, status, corpus_query) 
+	VALUES ("marlin VC", "PRIVATE", "FREE", "marlin", "marlin test share vc", "experimental",
+	'{"collection": { "@type": "koral:docGroup", "operands": [ { "@type": "koral:doc", "key": "corpusSigle", "match": "match:eq", "value": "GOE" }, { "@type": "koral:doc", "key": "creationDate", "match": "match:geq", "type": "type:date", "value": "1820" } ], "operation": "operation:and" }}');
 
+INSERT INTO virtual_corpus(name, type, required_access, created_by, description, status, corpus_query) 
+	VALUES ("nemo VC", "PRIVATE", "ALL", "nemo", "nemo test vc", "experimental",
+	'{"collection":{"@type":"koral:doc","value":"GOE","match":"match:eq","key":"corpusSigle"}}');	
+	
 -- virtual corpus access
 INSERT INTO virtual_corpus_access(virtual_corpus_id, user_group_id, status, created_by) 
 	SELECT 
diff --git a/full/src/main/resources/db/insert/V3.3__insert_member_roles.sql b/full/src/main/resources/db/insert/V3.3__insert_member_roles.sql
index 611c322..9cb523f 100644
--- a/full/src/main/resources/db/insert/V3.3__insert_member_roles.sql
+++ b/full/src/main/resources/db/insert/V3.3__insert_member_roles.sql
@@ -19,7 +19,7 @@
 INSERT INTO group_member_role(group_member_id,role_id)
 SELECT
 	(SELECT id FROM user_group_member WHERE user_id="dory" AND group_id=1),
-	(SELECT id FROM role WHERE name = "vc member");
+	(SELECT id FROM role WHERE name = "vc admin");
 	
 	
 -- dory group
diff --git a/full/src/test/java/de/ids_mannheim/korap/dao/VirtualCorpusDaoTest.java b/full/src/test/java/de/ids_mannheim/korap/dao/VirtualCorpusDaoTest.java
index d7ed3a2..d13216b 100644
--- a/full/src/test/java/de/ids_mannheim/korap/dao/VirtualCorpusDaoTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/dao/VirtualCorpusDaoTest.java
@@ -76,15 +76,15 @@
      */
     @Test
     public void retrieveVCByUserDory () throws KustvaktException {
-        Set<VirtualCorpus> virtualCorpora = dao.retrieveVCByUser("dory");
-        System.out.println(virtualCorpora);
+        List<VirtualCorpus> virtualCorpora = dao.retrieveVCByUser("dory");
+//        System.out.println(virtualCorpora);
         assertEquals(4, virtualCorpora.size());
-        // order is random
-        //        Iterator<VirtualCorpus> i = virtualCorpora.iterator();
-        //        assertEquals("dory VC", i.next().getName());
-        //        assertEquals("system VC", i.next().getName());
-        //        assertEquals("group VC", i.next().getName());
-        //      assertEquals("published VC", i.next().getName());
+        // ordered by id
+        Iterator<VirtualCorpus> i = virtualCorpora.iterator();
+        assertEquals("dory VC", i.next().getName());
+        assertEquals("group VC", i.next().getName());   
+        assertEquals("system VC", i.next().getName());
+        assertEquals("published VC", i.next().getName());
     }
 
 
@@ -94,11 +94,12 @@
      */
     @Test
     public void retrieveVCByUserNemo () throws KustvaktException {
-        Set<VirtualCorpus> virtualCorpora = dao.retrieveVCByUser("nemo");
-        assertEquals(2, virtualCorpora.size());
+        List<VirtualCorpus> virtualCorpora = dao.retrieveVCByUser("nemo");
+        assertEquals(3, virtualCorpora.size());
         Iterator<VirtualCorpus> i = virtualCorpora.iterator();
-        assertEquals("system VC", i.next().getName());
         assertEquals("group VC", i.next().getName());
+        assertEquals("system VC", i.next().getName());
+        assertEquals("nemo VC", i.next().getName());
     }
 
 
@@ -108,11 +109,12 @@
      */
     @Test
     public void retrieveVCByUserMarlin () throws KustvaktException {
-        Set<VirtualCorpus> virtualCorpora = dao.retrieveVCByUser("marlin");
-        assertEquals(2, virtualCorpora.size());
+        List<VirtualCorpus> virtualCorpora = dao.retrieveVCByUser("marlin");
+        assertEquals(3, virtualCorpora.size());
         Iterator<VirtualCorpus> i = virtualCorpora.iterator();
         assertEquals("system VC", i.next().getName());
         assertEquals("published VC", i.next().getName());
+        assertEquals("marlin VC", i.next().getName());
     }
 
 
@@ -123,7 +125,7 @@
      */
     @Test
     public void retrieveVCByUserPearl () throws KustvaktException {
-        Set<VirtualCorpus> virtualCorpora = dao.retrieveVCByUser("pearl");
+        List<VirtualCorpus> virtualCorpora = dao.retrieveVCByUser("pearl");
         assertEquals(2, virtualCorpora.size());
         Iterator<VirtualCorpus> i = virtualCorpora.iterator();
         assertEquals("system VC", i.next().getName());
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerTest.java
index 5b7ca8a..b6a9eae 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerTest.java
@@ -41,9 +41,9 @@
         JsonNode node = JsonUtils.readTree(entity);
 
         JsonNode group;
-        for (int i=0; i< node.size(); i++){
+        for (int i = 0; i < node.size(); i++) {
             group = node.get(i);
-            if (group.at("/id").asInt() == 2){
+            if (group.at("/id").asInt() == 2) {
                 assertEquals("dory group", group.at("/name").asText());
                 assertEquals("dory", group.at("/owner").asText());
                 assertEquals(3, group.at("/members").size());
@@ -87,14 +87,14 @@
         assertEquals(1, node.size());
     }
 
-    
+
     @Test
     public void testRetrieveUserGroupUnauthorized () throws KustvaktException {
         ClientResponse response = resource().path("group").path("list")
                 .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
                 .get(ClientResponse.class);
         String entity = response.getEntity(String.class);
-//                System.out.println(entity);
+        //                System.out.println(entity);
         JsonNode node = JsonUtils.readTree(entity);
 
         assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
@@ -106,7 +106,7 @@
 
     // marlin has GroupMemberStatus.PENDING in dory group
     @Test
-    public void testSubscribeMarlinToDoryGroup () throws KustvaktException {
+    public void testSubscribeUnsubscribeMarlinToDoryGroup () throws KustvaktException {
         MultivaluedMap<String, String> form = new MultivaluedMapImpl();
         form.add("groupId", "2");
 
@@ -117,8 +117,44 @@
                         handler.createBasicAuthorizationHeaderValue("marlin",
                                 "pass"))
                 .entity(form).post(ClientResponse.class);
+
+        assertEquals(Status.OK.getStatusCode(), response.getStatus());
+
+        // retrieve marlin group
+        response = resource().path("group").path("list")
+                .header(Attributes.AUTHORIZATION,
+                        handler.createBasicAuthorizationHeaderValue("marlin",
+                                "pass"))
+                .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+                .get(ClientResponse.class);
         String entity = response.getEntity(String.class);
-        
+
+        assertEquals(Status.OK.getStatusCode(), response.getStatus());
+
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(2, node.size());
+
+        JsonNode group;
+        for (int i = 0; i < node.size(); i++) {
+            group = node.get(i);
+            if (group.at("/id").asInt() == 2) {
+                assertEquals("dory group", group.at("/name").asText());
+                assertEquals("dory", group.at("/owner").asText());
+                // group members are not allowed to see other members
+                assertEquals(0, group.at("/members").size());
+            }
+        }
+
+        // unsubscribe
+        response = resource().path("group").path("unsubscribe")
+                .type(MediaType.APPLICATION_FORM_URLENCODED)
+                .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+                .header(Attributes.AUTHORIZATION,
+                        handler.createBasicAuthorizationHeaderValue("marlin",
+                                "pass"))
+                .entity(form).post(ClientResponse.class);
+        entity = response.getEntity(String.class);
+
         // retrieve marlin group
         response = resource().path("group").path("list")
                 .header(Attributes.AUTHORIZATION,
@@ -129,23 +165,11 @@
         entity = response.getEntity(String.class);
 
         assertEquals(Status.OK.getStatusCode(), response.getStatus());
-        
-        JsonNode node = JsonUtils.readTree(entity);
-        assertEquals(2, node.size());
-        
-        JsonNode group;
-        for (int i=0; i< node.size(); i++){
-            group = node.get(i);
-            if (group.at("/id").asInt() == 2){
-                assertEquals("dory group", group.at("/name").asText());
-                assertEquals("dory", group.at("/owner").asText());
-                // group members are not allowed to see other members
-                assertEquals(0, group.at("/members").size());
-            }
-        }
-            
+
+        node = JsonUtils.readTree(entity);
+        assertEquals(1, node.size());
     }
-    
+
     // pearl has GroupMemberStatus.DELETED in dory group
     @Test
     public void testSubscribePearlToDoryGroup () throws KustvaktException {
@@ -161,14 +185,14 @@
                 .entity(form).post(ClientResponse.class);
         String entity = response.getEntity(String.class);
         JsonNode node = JsonUtils.readTree(entity);
-        
+
         assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
         assertEquals(StatusCodes.NOTHING_CHANGED,
                 node.at("/errors/0/0").asInt());
         assertEquals("Username pearl had been deleted in group 2",
                 node.at("/errors/0/1").asText());
     }
-    
+
     @Test
     public void testSubscribeMissingGroupId () throws KustvaktException {
         ClientResponse response = resource().path("group").path("subscribe")
@@ -199,7 +223,7 @@
                                 "pass"))
                 .entity(form).post(ClientResponse.class);
         String entity = response.getEntity(String.class);
-//        System.out.println(entity);
+        //        System.out.println(entity);
         JsonNode node = JsonUtils.readTree(entity);
 
         assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
@@ -222,7 +246,7 @@
                                 "pass"))
                 .entity(form).post(ClientResponse.class);
         String entity = response.getEntity(String.class);
-//        System.out.println(entity);
+        //        System.out.println(entity);
         JsonNode node = JsonUtils.readTree(entity);
 
         assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
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 8f49630..7e41f90 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
@@ -9,6 +9,10 @@
 import java.io.InputStreamReader;
 import java.util.List;
 import java.util.Map.Entry;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+
 import java.util.Set;
 
 import org.apache.http.entity.ContentType;
@@ -21,6 +25,7 @@
 import com.sun.jersey.api.client.ClientHandlerException;
 import com.sun.jersey.api.client.ClientResponse;
 import com.sun.jersey.api.client.ClientResponse.Status;
+import com.sun.jersey.core.util.MultivaluedMapImpl;
 import com.sun.jersey.api.client.UniformInterfaceException;
 import com.sun.jersey.spi.container.ContainerRequest;
 
@@ -68,7 +73,7 @@
                 .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
                 .get(ClientResponse.class);
         String entity = response.getEntity(String.class);
-//        System.out.println(entity);
+        //        System.out.println(entity);
         assertEquals(Status.OK.getStatusCode(), response.getStatus());
 
         JsonNode node = JsonUtils.readTree(entity);
@@ -166,19 +171,19 @@
             ClientHandlerException, KustvaktException {
         ClientResponse response = resource().path("vc").path("search").path("4")
                 .header(Attributes.AUTHORIZATION,
-                        handler.createBasicAuthorizationHeaderValue("VirtualCorpusControllerTest",
-                                "pass"))
+                        handler.createBasicAuthorizationHeaderValue(
+                                "gill", "pass"))
                 .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
                 .get(ClientResponse.class);
         String entity = response.getEntity(String.class);
-//        System.out.println(entity);
+        //        System.out.println(entity);
         assertEquals(Status.OK.getStatusCode(), response.getStatus());
 
         JsonNode node = JsonUtils.readTree(entity);
         assertEquals("published VC", node.at("/name").asText());
         assertEquals(VirtualCorpusType.PUBLISHED.displayName(),
                 node.at("/type").asText());
-        
+
         // EM: need admin to check if VirtualCorpusControllerTest is added to the hidden group
     }
 
@@ -209,7 +214,7 @@
 
         entity = response.getEntity(String.class);
         node = JsonUtils.readTree(entity);
-        assertEquals(2, node.size());
+        assertEquals(3, node.size());
 
         // pearl
         response = resource().path("vc").path("list")
@@ -270,26 +275,20 @@
                 .get(ClientResponse.class);
         entity = response.getEntity(String.class);
         assertEquals(Status.OK.getStatusCode(), response.getStatus());
-        //        System.out.println(entity);
+                System.out.println(entity);
         JsonNode node = JsonUtils.readTree(entity);
         assertEquals(2, node.size());
-        //        EM: order may be different
-        //        assertEquals("new vc", node.get(0).get("name").asText());
+        assertEquals("new vc", node.get(1).get("name").asText());
 
         String vcId = null;
-        for (int i = 0; i < node.size(); i++) {
-            if (node.get(i).get("name").asText().equals("new vc")) {
-                vcId = node.get(i).get("id").asText();
-            }
-        }
+        vcId = node.get(1).get("id").asText();
 
         // delete new VC
-        resource().path("vc").path("delete").queryParam("vcId", vcId)
+        resource().path("vc").path("delete").path(vcId)
                 .header(Attributes.AUTHORIZATION,
                         handler.createBasicAuthorizationHeaderValue(
                                 "VirtualCorpusControllerTest", "pass"))
                 .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
-
                 .delete(ClientResponse.class);
         //        entity = response.getEntity(String.class);
         assertEquals(Status.OK.getStatusCode(), response.getStatus());
@@ -343,7 +342,7 @@
         String vcId = node.get(0).get("id").asText();
 
         //EM: delete vc
-        resource().path("vc").path("delete").queryParam("vcId", vcId)
+        resource().path("vc").path("delete").path(vcId)
                 .header(Attributes.AUTHORIZATION,
                         handler.createBasicAuthorizationHeaderValue(
                                 "VirtualCorpusControllerTest", "pass"))
@@ -481,7 +480,7 @@
     @Test
     public void testDeleteVCUnauthorized () throws KustvaktException {
         ClientResponse response =
-                resource().path("vc").path("delete").queryParam("vcId", "1")
+                resource().path("vc").path("delete").path("1")
                         .header(Attributes.AUTHORIZATION,
                                 handler.createBasicAuthorizationHeaderValue(
                                         "VirtualCorpusControllerTest", "pass"))
@@ -530,14 +529,7 @@
         assertEquals(Status.OK.getStatusCode(), response.getStatus());
 
         JsonNode node = JsonUtils.readTree(entity);
-
-        for (int i = 0; i < node.size(); i++) {
-            JsonNode n = node.get(i);
-            if (n.get("id").asInt() == 1) {
-                assertEquals("edited vc", n.get("name").asText());
-                break;
-            }
-        }
+        assertEquals("edited vc", node.get(0).get("name").asText());
 
         // 2nd edit
         json = "{\"id\": \"1\", \"name\": \"dory VC\"}";
@@ -565,14 +557,7 @@
 
         entity = response.getEntity(String.class);
         node = JsonUtils.readTree(entity);
-
-        for (int i = 0; i < node.size(); i++) {
-            JsonNode n = node.get(i);
-            if (n.get("id").asInt() == 1) {
-                assertEquals("dory VC", n.get("name").asText());
-                break;
-            }
-        }
+        assertEquals("dory VC", node.get(0).get("name").asText());
     }
 
     @Test
@@ -604,16 +589,10 @@
         assertEquals(Status.OK.getStatusCode(), response.getStatus());
 
         JsonNode node = JsonUtils.readTree(entity);
-
-        for (int i = 0; i < node.size(); i++) {
-            JsonNode n = node.get(i);
-            if (n.get("id").asInt() == 1) {
-                assertEquals("dory published vc", n.get("name").asText());
-                assertEquals(VirtualCorpusType.PUBLISHED.displayName(),
-                        n.get("type").asText());
-                break;
-            }
-        }
+        JsonNode n = node.get(0);
+        assertEquals("dory published vc", n.get("name").asText());
+        assertEquals(VirtualCorpusType.PUBLISHED.displayName(),
+                n.get("type").asText());
     }
 
     @Test
@@ -714,18 +693,156 @@
         assertEquals("dory group", node.at("/0/userGroupName").asText());
     }
 
-    // share VC
-//    @Test
-//    public void testCreateDeleteAccess () {
-//        // create VC
-//        
-//        // create group
-//        
-//        // share VC
-//        
-//        // delete 
-//
-//    }
 
+    @Test
+    public void testCreateDeleteAccess () throws UniformInterfaceException,
+            ClientHandlerException, KustvaktException {
 
+        MultivaluedMap<String, String> form = new MultivaluedMapImpl();
+        // marlin vc
+        form.add("vcId", "5");
+        // marlin group
+        form.add("groupId", "1");
+
+        ClientResponse response;
+        // share VC
+        response = resource().path("vc").path("access").path("share")
+                .type(MediaType.APPLICATION_FORM_URLENCODED)
+                .header(Attributes.AUTHORIZATION,
+                        handler.createBasicAuthorizationHeaderValue("marlin",
+                                "pass"))
+                .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32").entity(form)
+                .post(ClientResponse.class);
+
+        assertEquals(Status.OK.getStatusCode(), response.getStatus());
+
+        // list vc access by marlin
+        response = resource().path("vc").path("access").path("list")
+                .queryParam("vcId", "5")
+                .header(Attributes.AUTHORIZATION,
+                        handler.createBasicAuthorizationHeaderValue("marlin",
+                                "pass"))
+                .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+                .header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON)
+                .get(ClientResponse.class);
+
+        String entity = response.getEntity(String.class);
+        //        System.out.println(entity);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(1, node.size());
+        node = node.get(0);
+        assertEquals(5, node.at("/vcId").asInt());
+        assertEquals("marlin VC", node.at("/vcName").asText());
+        assertEquals(1, node.at("/userGroupId").asInt());
+        assertEquals("marlin group", node.at("/userGroupName").asText());
+
+        String accessId = node.at("/accessId").asText();
+
+        // delete access
+        // unauthorized
+        response = resource().path("vc").path("access").path("delete")
+                .path(accessId)
+                .header(Attributes.AUTHORIZATION,
+                        handler.createBasicAuthorizationHeaderValue(
+                                "VirtualCorpusControllerTest", "pass"))
+                .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+                .delete(ClientResponse.class);
+
+        entity = response.getEntity(String.class);
+        //        System.out.println(entity);
+        node = JsonUtils.readTree(entity);
+        assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
+        assertEquals(StatusCodes.AUTHORIZATION_FAILED,
+                node.at("/errors/0/0").asInt());
+        assertEquals(
+                "Unauthorized operation for user: VirtualCorpusControllerTest",
+                node.at("/errors/0/1").asText());
+
+        // delete access
+        // dory is a vc-admin in marlin group
+        response = resource().path("vc").path("access").path("delete")
+                .path(accessId)
+                .header(Attributes.AUTHORIZATION,
+                        handler.createBasicAuthorizationHeaderValue("dory",
+                                "pass"))
+                .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+                .delete(ClientResponse.class);
+
+        assertEquals(Status.OK.getStatusCode(), response.getStatus());
+
+        // list vc access by dory
+        response = resource().path("vc").path("access").path("list")
+                .queryParam("vcId", "5")
+                .header(Attributes.AUTHORIZATION,
+                        handler.createBasicAuthorizationHeaderValue("dory",
+                                "pass"))
+                .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+                .header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON)
+                .get(ClientResponse.class);
+
+        entity = response.getEntity(String.class);
+        assertEquals("[]", entity);
+        node = JsonUtils.readTree(entity);
+        assertEquals(0, node.size());
+    }
+
+    @Test
+    public void testCreateAccessByVCAButNotVCOwner ()
+            throws UniformInterfaceException, ClientHandlerException,
+            KustvaktException {
+
+        MultivaluedMap<String, String> form = new MultivaluedMapImpl();
+        // marlin vc
+        form.add("vcId", "5");
+        // marlin group
+        form.add("groupId", "1");
+
+        // share VC
+        // dory is VCA in marlin group 
+        ClientResponse response = resource().path("vc").path("access")
+                .path("share").type(MediaType.APPLICATION_FORM_URLENCODED)
+                .header(Attributes.AUTHORIZATION,
+                        handler.createBasicAuthorizationHeaderValue("dory",
+                                "pass"))
+                .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32").entity(form)
+                .post(ClientResponse.class);
+
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
+        assertEquals(StatusCodes.AUTHORIZATION_FAILED,
+                node.at("/errors/0/0").asInt());
+        assertEquals("Unauthorized operation for user: dory",
+                node.at("/errors/0/1").asText());
+    }
+    
+    @Test
+    public void testCreateAccessByNonVCA ()
+            throws UniformInterfaceException, ClientHandlerException,
+            KustvaktException {
+
+        MultivaluedMap<String, String> form = new MultivaluedMapImpl();
+        // nemo vc
+        form.add("vcId", "6");
+        // marlin group
+        form.add("groupId", "1");
+
+        // share VC
+        // nemo is not VCA in marlin group 
+        ClientResponse response = resource().path("vc").path("access")
+                .path("share").type(MediaType.APPLICATION_FORM_URLENCODED)
+                .header(Attributes.AUTHORIZATION,
+                        handler.createBasicAuthorizationHeaderValue("nemo",
+                                "pass"))
+                .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32").entity(form)
+                .post(ClientResponse.class);
+
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
+        assertEquals(StatusCodes.AUTHORIZATION_FAILED,
+                node.at("/errors/0/0").asInt());
+        assertEquals("Unauthorized operation for user: nemo",
+                node.at("/errors/0/1").asText());
+    }
 }