Fixed list access services and added tests.

Change-Id: Idf460f41c09393231d5b83d8d20c245c9eaa34d2
diff --git a/core/pom.xml b/core/pom.xml
index e82c424..4c5d03c 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -93,6 +93,7 @@
 		    <plugin>
 		      <groupId>org.apache.maven.plugins</groupId>
 		      <artifactId>maven-source-plugin</artifactId>
+		      <version>3.0.1</version>
 		      <executions>
 		        <execution>
 		          <id>attach-sources</id>
diff --git a/core/src/main/java/de/ids_mannheim/korap/utils/ParameterChecker.java b/core/src/main/java/de/ids_mannheim/korap/utils/ParameterChecker.java
index a1e2a51..6d928f4 100644
--- a/core/src/main/java/de/ids_mannheim/korap/utils/ParameterChecker.java
+++ b/core/src/main/java/de/ids_mannheim/korap/utils/ParameterChecker.java
@@ -12,22 +12,23 @@
                     "null");
         }
     }
-    
+
     public static void checkStringValue (String string, String name)
             throws KustvaktException {
-        if (string == null ) {
+        if (string == null) {
             throw new KustvaktException(StatusCodes.INVALID_ARGUMENT, name,
                     "null");
         }
-        else if (string.isEmpty()){
+        else if (string.isEmpty()) {
             throw new KustvaktException(StatusCodes.INVALID_ARGUMENT, name,
                     "empty");
         }
     }
 
-    public static void checkIntegerValue (int integer, String name) throws KustvaktException {
+    public static void checkIntegerValue (int integer, String name)
+            throws KustvaktException {
         if (integer == 0) {
-            throw new KustvaktException(StatusCodes.INVALID_ARGUMENT, name,
+            throw new KustvaktException(StatusCodes.MISSING_ARGUMENT, name,
                     "0");
         }
     }
diff --git a/full/pom.xml b/full/pom.xml
index 17df97e..23aaa71 100644
--- a/full/pom.xml
+++ b/full/pom.xml
@@ -65,15 +65,21 @@
 			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
 				<artifactId>maven-compiler-plugin</artifactId>
-				<version>3.3</version>
+				<version>3.7.0</version>
 				<configuration>
 					<compilerVersion>${java.version}</compilerVersion>
 					<source>${java.version}</source>
 					<target>${java.version}</target>
-					<processors>
+					<verbose>true</verbose>
+          			<fork>true</fork>
+					<!-- <compilerArguments>
 						<processor>lombok.launch.AnnotationProcessorHider$AnnotationProcessor</processor>
 						<processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
-					</processors>
+					</compilerArguments> -->
+					<!-- <processors>
+						<processor>lombok.launch.AnnotationProcessorHider$AnnotationProcessor</processor>
+						<processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
+					</processors> -->
 				</configuration>
 			</plugin>
 			<plugin>
@@ -86,12 +92,11 @@
 					<threadCount>10</threadCount>
 
 					<excludes>
-						<exclude>de/ids_mannheim/korap/suites/*.java</exclude>
-						<exclude>de/ids_mannheim/korap/dao/*.java</exclude>
+						<!-- <exclude>de/ids_mannheim/korap/suites/*.java</exclude> -->
+						<!-- <exclude>de/ids_mannheim/korap/dao/*.java</exclude> -->
 						<exclude>de/ids_mannheim/korap/authentication/*.java</exclude>
-						<exclude>**/KustvaktServerTest.java</exclude>
-						<exclude>**/ResourceServiceTest.java</exclude>
-						<exclude>**/ResourceInfoServiceTest.java</exclude>
+						<!-- <exclude>**/ResourceServiceTest.java</exclude> -->
+						<!-- <exclude>**/ResourceInfoServiceTest.java</exclude> -->
 						<exclude>**/PolicyServiceTest.java</exclude>
 					</excludes>
 					<includes>
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 35bc6cc..02c1bc0 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
@@ -123,8 +123,8 @@
         Predicate predicate = criteriaBuilder.and(
                 criteriaBuilder.equal(root.get(UserGroupMember_.group),
                         groupId),
-                criteriaBuilder.notEqual(root.get(UserGroupMember_.status),
-                        GroupMemberStatus.DELETED),
+                criteriaBuilder.equal(root.get(UserGroupMember_.status),
+                        GroupMemberStatus.ACTIVE),
                 criteriaBuilder.equal(memberRole.get(Role_.id), roleId));
 
         query.select(root);
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 7db9a28..d5dc9b1 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,7 +33,32 @@
     @PersistenceContext
     private EntityManager entityManager;
 
-    public List<VirtualCorpusAccess> retrieveAccessByVC (int vcId)
+    // for vca admins
+    public List<VirtualCorpusAccess> retrieveActiveAccessByVC (int vcId)
+            throws KustvaktException {
+        ParameterChecker.checkIntegerValue(vcId, "vcId");
+
+        CriteriaBuilder builder = entityManager.getCriteriaBuilder();
+        CriteriaQuery<VirtualCorpusAccess> query =
+                builder.createQuery(VirtualCorpusAccess.class);
+
+        Root<VirtualCorpusAccess> access =
+                query.from(VirtualCorpusAccess.class);
+        Join<VirtualCorpusAccess, VirtualCorpus> accessVC =
+                access.join(VirtualCorpusAccess_.virtualCorpus);
+
+        Predicate p = builder.and(
+                builder.equal(accessVC.get(VirtualCorpus_.id), vcId),
+                builder.equal(access.get(VirtualCorpusAccess_.status),
+                        VirtualCorpusAccessStatus.ACTIVE));
+        query.select(access);
+        query.where(p);
+        Query q = entityManager.createQuery(query);
+        return q.getResultList();
+    }
+    
+    // for system admins
+    public List<VirtualCorpusAccess> retrieveAllAccessByVC (int vcId)
             throws KustvaktException {
         ParameterChecker.checkIntegerValue(vcId, "vcId");
 
@@ -51,8 +76,8 @@
         Query q = entityManager.createQuery(query);
         return q.getResultList();
     }
-    
-    public List<VirtualCorpusAccess> retrieveAccessByGroup (int groupId)
+
+    public List<VirtualCorpusAccess> retrieveAllAccessByGroup (int groupId)
             throws KustvaktException {
         ParameterChecker.checkIntegerValue(groupId, "groupId");
 
@@ -70,6 +95,30 @@
         Query q = entityManager.createQuery(query);
         return q.getResultList();
     }
+    
+    public List<VirtualCorpusAccess> retrieveActiveAccessByGroup (int groupId)
+            throws KustvaktException {
+        ParameterChecker.checkIntegerValue(groupId, "groupId");
+
+        CriteriaBuilder builder = entityManager.getCriteriaBuilder();
+        CriteriaQuery<VirtualCorpusAccess> query =
+                builder.createQuery(VirtualCorpusAccess.class);
+
+        Root<VirtualCorpusAccess> access =
+                query.from(VirtualCorpusAccess.class);
+        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));
+        
+        query.select(access);
+        query.where(p);
+        Query q = entityManager.createQuery(query);
+        return q.getResultList();
+    }
 
     /** Hidden accesses are only created for published or system VC. 
      * 
@@ -110,9 +159,10 @@
             return new ArrayList<>();
         }
     }
-    
-    public void createAccessToVC (VirtualCorpus virtualCorpus, UserGroup userGroup,
-            String createdBy, VirtualCorpusAccessStatus status) {
+
+    public void createAccessToVC (VirtualCorpus virtualCorpus,
+            UserGroup userGroup, String createdBy,
+            VirtualCorpusAccessStatus status) {
         VirtualCorpusAccess vca = new VirtualCorpusAccess();
         vca.setVirtualCorpus(virtualCorpus);
         vca.setUserGroup(userGroup);
diff --git a/full/src/main/java/de/ids_mannheim/korap/dto/VirtualCorpusAccessDto.java b/full/src/main/java/de/ids_mannheim/korap/dto/VirtualCorpusAccessDto.java
new file mode 100644
index 0000000..93875ee
--- /dev/null
+++ b/full/src/main/java/de/ids_mannheim/korap/dto/VirtualCorpusAccessDto.java
@@ -0,0 +1,15 @@
+package de.ids_mannheim.korap.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class VirtualCorpusAccessDto {
+    private int accessId;
+    private String createdBy;
+    private int vcId;
+    private String vcName;
+    private int userGroupId;
+    private String userGroupName;
+}
diff --git a/full/src/main/java/de/ids_mannheim/korap/dto/converter/VirtualCorpusAccessConverter.java b/full/src/main/java/de/ids_mannheim/korap/dto/converter/VirtualCorpusAccessConverter.java
new file mode 100644
index 0000000..3d9e3de
--- /dev/null
+++ b/full/src/main/java/de/ids_mannheim/korap/dto/converter/VirtualCorpusAccessConverter.java
@@ -0,0 +1,32 @@
+package de.ids_mannheim.korap.dto.converter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.stereotype.Component;
+
+import de.ids_mannheim.korap.dto.VirtualCorpusAccessDto;
+import de.ids_mannheim.korap.entity.VirtualCorpusAccess;
+
+@Component
+public class VirtualCorpusAccessConverter {
+
+    public List<VirtualCorpusAccessDto> createVCADto (List<VirtualCorpusAccess> accessList) {
+        List<VirtualCorpusAccessDto> dtos = new ArrayList<>(accessList.size());
+        for (VirtualCorpusAccess access : accessList){
+            VirtualCorpusAccessDto dto = new VirtualCorpusAccessDto();
+            dto.setAccessId(access.getId());
+            dto.setCreatedBy(access.getCreatedBy());
+            
+            dto.setVcId(access.getVirtualCorpus().getId());
+            dto.setVcName(access.getVirtualCorpus().getName());
+            
+            dto.setUserGroupId(access.getUserGroup().getId());
+            dto.setUserGroupName(access.getUserGroup().getName());
+            
+            dtos.add(dto);
+        }
+        return dtos;
+    }
+    
+}
diff --git a/full/src/main/java/de/ids_mannheim/korap/entity/UserGroupMember.java b/full/src/main/java/de/ids_mannheim/korap/entity/UserGroupMember.java
index 2bda7aa..6e7f874 100644
--- a/full/src/main/java/de/ids_mannheim/korap/entity/UserGroupMember.java
+++ b/full/src/main/java/de/ids_mannheim/korap/entity/UserGroupMember.java
@@ -51,7 +51,7 @@
     @Enumerated(EnumType.STRING)
     private GroupMemberStatus status;
 
-    @ManyToOne(fetch = FetchType.LAZY)
+    @ManyToOne(fetch = FetchType.EAGER)
     @JoinColumn(name = "group_id")
     private UserGroup group;
 
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 8d11bf3..56ebc87 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
@@ -19,7 +19,9 @@
 import de.ids_mannheim.korap.constant.VirtualCorpusType;
 import de.ids_mannheim.korap.dao.VirtualCorpusAccessDao;
 import de.ids_mannheim.korap.dao.VirtualCorpusDao;
+import de.ids_mannheim.korap.dto.VirtualCorpusAccessDto;
 import de.ids_mannheim.korap.dto.VirtualCorpusDto;
+import de.ids_mannheim.korap.dto.converter.VirtualCorpusAccessConverter;
 import de.ids_mannheim.korap.dto.converter.VirtualCorpusConverter;
 import de.ids_mannheim.korap.entity.Role;
 import de.ids_mannheim.korap.entity.UserGroup;
@@ -66,6 +68,8 @@
     private AuthenticationManagerIface authManager;
     @Autowired
     private VirtualCorpusConverter converter;
+    @Autowired
+    private VirtualCorpusAccessConverter accessConverter;
 
     public List<VirtualCorpusDto> listOwnerVC (String username)
             throws KustvaktException {
@@ -128,7 +132,7 @@
         ParameterChecker.checkIntegerValue(vcJson.getId(), "id");
         User user = authManager.getUser(username);
 
-        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);
         }
@@ -278,9 +282,9 @@
     //
     //    }
 
-    public List<VirtualCorpusAccess> retrieveVCAccess (int vcId)
+    public List<VirtualCorpusAccess> retrieveAllVCAccess (int vcId)
             throws KustvaktException {
-        return accessDao.retrieveAccessByVC(vcId);
+        return accessDao.retrieveAllAccessByVC(vcId);
     }
 
     public void shareVC (String username, int vcId, int groupId)
@@ -333,34 +337,45 @@
         }
     }
 
-    public List<VirtualCorpusAccess> listVCAccessByVC (String username,
+    public List<VirtualCorpusAccessDto> listVCAccessByVC (String username,
             int vcId) throws KustvaktException {
 
-        List<VirtualCorpusAccess> accessList =
-                accessDao.retrieveAccessByVC(vcId);
+        List<VirtualCorpusAccess> accessList;
         User user = authManager.getUser(username);
-        if (user.isAdmin()){
-            return accessList;
+        if (user.isAdmin()) {
+            accessList = accessDao.retrieveAllAccessByVC(vcId);
         }
-
-        List<VirtualCorpusAccess> filteredAccessList = new ArrayList<>();
-        for (VirtualCorpusAccess access : accessList){
-            UserGroup userGroup = access.getUserGroup();
-            if (isVCAccessAdmin(userGroup, username)){
-                filteredAccessList.add(access);
+        else {
+            accessList = accessDao.retrieveActiveAccessByVC(vcId);
+            List<VirtualCorpusAccess> filteredAccessList = new ArrayList<>();
+            for (VirtualCorpusAccess access : accessList) {
+                UserGroup userGroup = access.getUserGroup();
+                if (isVCAccessAdmin(userGroup, username)) {
+                    filteredAccessList.add(access);
+                }
             }
+            accessList = filteredAccessList;
         }
-        return filteredAccessList;
+        return accessConverter.createVCADto(accessList);
     }
 
-    public List<VirtualCorpusAccess> listVCAccessByGroup (String username,
+    public List<VirtualCorpusAccessDto> listVCAccessByGroup (String username,
             int groupId) throws KustvaktException {
         User user = authManager.getUser(username);
         UserGroup userGroup = userGroupService.retrieveUserGroupById(groupId);
-        if (!user.isAdmin() && !isVCAccessAdmin(userGroup, username)) {
+
+        List<VirtualCorpusAccess> accessList;
+        if (user.isAdmin()) {
+            accessList = accessDao.retrieveAllAccessByGroup(groupId);
+        }
+        else if (isVCAccessAdmin(userGroup, username)) {
+            accessList = accessDao.retrieveActiveAccessByGroup(groupId);
+        }
+        else {
             throw new KustvaktException(StatusCodes.AUTHORIZATION_FAILED,
                     "Unauthorized operation for user: " + username, username);
         }
-        return accessDao.retrieveAccessByGroup(groupId);
+
+        return accessConverter.createVCADto(accessList);
     }
 }
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 3914ac7..618b226 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
@@ -21,6 +21,8 @@
 
 import com.sun.jersey.spi.container.ResourceFilters;
 
+import de.ids_mannheim.korap.constant.VirtualCorpusAccessStatus;
+import de.ids_mannheim.korap.dto.VirtualCorpusAccessDto;
 import de.ids_mannheim.korap.dto.VirtualCorpusDto;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.service.VirtualCorpusService;
@@ -211,33 +213,49 @@
         return Response.ok().build();
     }
 
+    /** Lists only active accesses to the specified virtual corpus.
+     * Only available to VCA admins.
+     * 
+     * @see VirtualCorpusAccessStatus
+     * 
+     * @param securityContext
+     * @param vcId virtual corpus id
+     * @return a list of access to the specified virtual corpus
+     */
     @GET
     @Path("access/list")
     public Response listVCAccess (@Context SecurityContext securityContext,
             @QueryParam("vcId") int vcId) {
         TokenContext context =
                 (TokenContext) securityContext.getUserPrincipal();
+        String result;
         try {
-            service.listVCAccessByVC(context.getUsername(), vcId);
+            List<VirtualCorpusAccessDto> dtos =
+                    service.listVCAccessByVC(context.getUsername(), vcId);
+            result = JsonUtils.toJSON(dtos);
         }
         catch (KustvaktException e) {
             throw responseHandler.throwit(e);
         }
-        return Response.ok().build();
+        return Response.ok(result).build();
     }
-    
+
     @GET
     @Path("access/list/byGroup")
-    public Response listVCAccessByGroup (@Context SecurityContext securityContext,
+    public Response listVCAccessByGroup (
+            @Context SecurityContext securityContext,
             @QueryParam("groupId") int groupId) {
         TokenContext context =
                 (TokenContext) securityContext.getUserPrincipal();
+        String result;
         try {
-            service.listVCAccessByGroup(context.getUsername(), groupId);
+            List<VirtualCorpusAccessDto> dtos =
+                    service.listVCAccessByGroup(context.getUsername(), groupId);
+            result = JsonUtils.toJSON(dtos);
         }
         catch (KustvaktException e) {
             throw responseHandler.throwit(e);
         }
-        return Response.ok().build();
+        return Response.ok(result).build();
     }
 }
diff --git a/full/src/test/java/de/ids_mannheim/korap/dao/UserGroupMemberDaoTest.java b/full/src/test/java/de/ids_mannheim/korap/dao/UserGroupMemberDaoTest.java
new file mode 100644
index 0000000..ff86c80
--- /dev/null
+++ b/full/src/test/java/de/ids_mannheim/korap/dao/UserGroupMemberDaoTest.java
@@ -0,0 +1,33 @@
+package de.ids_mannheim.korap.dao;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import de.ids_mannheim.korap.constant.PredefinedRole;
+import de.ids_mannheim.korap.entity.UserGroupMember;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration("classpath:test-config.xml")
+public class UserGroupMemberDaoTest {
+
+    @Autowired
+    private UserGroupMemberDao dao;
+
+    @Test
+    public void testRetrieveMemberByRole () throws KustvaktException {
+        // dory group
+        List<UserGroupMember> vcaAdmins = dao.retrieveMemberByRole(2,
+                PredefinedRole.VC_ACCESS_ADMIN.getId());
+//        System.out.println(vcaAdmins);
+        assertEquals(1, vcaAdmins.size());
+        assertEquals("dory", vcaAdmins.get(0).getUserId());
+    }
+}
diff --git a/full/src/test/java/de/ids_mannheim/korap/dao/VirtualCorpusAccessDaoTest.java b/full/src/test/java/de/ids_mannheim/korap/dao/VirtualCorpusAccessDaoTest.java
index 3d538af..006ca9c 100644
--- a/full/src/test/java/de/ids_mannheim/korap/dao/VirtualCorpusAccessDaoTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/dao/VirtualCorpusAccessDaoTest.java
@@ -29,7 +29,7 @@
 
     @Test
     public void getAccessByVC () throws KustvaktException {
-        List<VirtualCorpusAccess> vcaList = dao.retrieveAccessByVC(2);
+        List<VirtualCorpusAccess> vcaList = dao.retrieveActiveAccessByVC(2);
         VirtualCorpusAccess access = vcaList.get(0);
         assertEquals(VirtualCorpusAccessStatus.ACTIVE, access.getStatus());
         assertEquals("dory", access.getCreatedBy());
@@ -37,4 +37,6 @@
         UserGroup group = access.getUserGroup();
         assertEquals(2, group.getId());
     }
+    
+    
 }
diff --git a/full/src/test/java/de/ids_mannheim/korap/service/VirtualCorpusServiceTest.java b/full/src/test/java/de/ids_mannheim/korap/service/VirtualCorpusServiceTest.java
index ed585f1..c2ca100 100644
--- a/full/src/test/java/de/ids_mannheim/korap/service/VirtualCorpusServiceTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/service/VirtualCorpusServiceTest.java
@@ -12,7 +12,6 @@
 
 import de.ids_mannheim.korap.constant.VirtualCorpusAccessStatus;
 import de.ids_mannheim.korap.constant.VirtualCorpusType;
-import de.ids_mannheim.korap.dto.UserGroupDto;
 import de.ids_mannheim.korap.entity.VirtualCorpusAccess;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.web.input.VirtualCorpusJson;
@@ -34,7 +33,7 @@
         vc.setType(VirtualCorpusType.PUBLISHED);
         int vcId = vcService.storeVC(vc, "VirtualCorpusServiceTest");
 
-        List<VirtualCorpusAccess> accesses = vcService.retrieveVCAccess(vcId);
+        List<VirtualCorpusAccess> accesses = vcService.retrieveAllVCAccess(vcId);
         assertEquals(2, accesses.size());
         for (VirtualCorpusAccess access : accesses) {
             assertEquals(VirtualCorpusAccessStatus.HIDDEN, access.getStatus());
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 e59e6b5..79c5236 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
@@ -168,7 +168,7 @@
         JsonNode node = JsonUtils.readTree(entity);
 
         assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
-        assertEquals(StatusCodes.INVALID_ARGUMENT,
+        assertEquals(StatusCodes.MISSING_ARGUMENT,
                 node.at("/errors/0/0").asInt());
         assertEquals("groupId", node.at("/errors/0/1").asText());
         assertEquals("0", node.at("/errors/0/2").asText());
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 252e39e..4ceca9d 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
@@ -36,7 +36,7 @@
 
     @Autowired
     private HttpAuthorizationHandler handler;
-    
+
     private void checkWWWAuthenticateHeader (ClientResponse response) {
         Set<Entry<String, List<String>>> headers =
                 response.getHeaders().entrySet();
@@ -73,9 +73,8 @@
     }
 
     @Test
-    public void testListVCUnauthorized ()
-            throws UniformInterfaceException, ClientHandlerException,
-            KustvaktException {
+    public void testListVCUnauthorized () throws UniformInterfaceException,
+            ClientHandlerException, KustvaktException {
         ClientResponse response = resource().path("vc").path("list")
                 .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
 
@@ -96,12 +95,12 @@
     public void testCreateDeleteVC () throws KustvaktException {
         String json =
                 "{\"name\": \"new vc\",\"type\": \"PRIVATE\",\"createdBy\": "
-                        + "\"test class\",\"corpusQuery\": \"corpusSigle=GOE\"}";
+                        + "\"VirtualCorpusControllerTest\",\"corpusQuery\": \"corpusSigle=GOE\"}";
 
         ClientResponse response = resource().path("vc").path("create")
                 .header(Attributes.AUTHORIZATION,
                         handler.createBasicAuthorizationHeaderValue(
-                                "test class", "pass"))
+                                "VirtualCorpusControllerTest", "pass"))
                 .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
                 .header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON)
                 .post(ClientResponse.class, json);
@@ -113,24 +112,30 @@
         response = resource().path("vc").path("list")
                 .header(Attributes.AUTHORIZATION,
                         handler.createBasicAuthorizationHeaderValue(
-                                "test class", "pass"))
+                                "VirtualCorpusControllerTest", "pass"))
                 .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
 
                 .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());
-        assertEquals("new vc", node.get(1).get("name").asText());
+//        EM: order may be different
+//        assertEquals("new vc", node.get(0).get("name").asText());
 
-        String vcId = node.get(1).get("id").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();
+            }
+        }         
 
         // delete new VC
         resource().path("vc").path("delete").queryParam("vcId", vcId)
                 .header(Attributes.AUTHORIZATION,
                         handler.createBasicAuthorizationHeaderValue(
-                                "test class", "pass"))
+                                "VirtualCorpusControllerTest", "pass"))
                 .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
 
                 .delete(ClientResponse.class);
@@ -141,7 +146,7 @@
         response = resource().path("vc").path("list")
                 .header(Attributes.AUTHORIZATION,
                         handler.createBasicAuthorizationHeaderValue(
-                                "test class", "pass"))
+                                "VirtualCorpusControllerTest", "pass"))
                 .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
 
                 .get(ClientResponse.class);
@@ -156,53 +161,53 @@
     public void testCreatePublishVC () throws KustvaktException {
         String json =
                 "{\"name\": \"new published vc\",\"type\": \"PUBLISHED\",\"createdBy\": "
-                        + "\"test class\",\"corpusQuery\": \"corpusSigle=GOE\"}";
+                        + "\"VirtualCorpusControllerTest\",\"corpusQuery\": \"corpusSigle=GOE\"}";
         ClientResponse response = resource().path("vc").path("create")
                 .header(Attributes.AUTHORIZATION,
                         handler.createBasicAuthorizationHeaderValue(
-                                "test class", "pass"))
+                                "VirtualCorpusControllerTest", "pass"))
                 .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
                 .header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON)
                 .post(ClientResponse.class, json);
-        
+
         assertEquals(Status.OK.getStatusCode(), response.getStatus());
-        
+
         // test list owner vc
         response = resource().path("vc").path("list").path("user")
                 .header(Attributes.AUTHORIZATION,
                         handler.createBasicAuthorizationHeaderValue(
-                                "test class", "pass"))
+                                "VirtualCorpusControllerTest", "pass"))
                 .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
 
                 .get(ClientResponse.class);
-        
+
         String entity = response.getEntity(String.class);
         System.out.println(entity);
         JsonNode node = JsonUtils.readTree(entity);
         assertEquals(1, node.size());
         assertEquals("new published vc", node.get(0).get("name").asText());
         //EM: cannot explicitly checked hidden groups here
-        
+
         String vcId = node.get(0).get("id").asText();
-        
+
         //EM: delete vc
         resource().path("vc").path("delete").queryParam("vcId", vcId)
-        .header(Attributes.AUTHORIZATION,
-                handler.createBasicAuthorizationHeaderValue(
-                        "test class", "pass"))
-        .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+                .header(Attributes.AUTHORIZATION,
+                        handler.createBasicAuthorizationHeaderValue(
+                                "VirtualCorpusControllerTest", "pass"))
+                .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
 
-        .delete(ClientResponse.class);
-        
+                .delete(ClientResponse.class);
+
         //EM: have to delete the hidden groups as well (admin)
     }
-    
+
     @Test
     public void testCreateVCWithExpiredToken ()
             throws IOException, KustvaktException {
         String json =
                 "{\"name\": \"new vc\",\"type\": \"PRIVATE\",\"createdBy\": "
-                        + "\"test class\",\"corpusQuery\": \"corpusSigle=GOE\"}";
+                        + "\"VirtualCorpusControllerTest\",\"corpusQuery\": \"corpusSigle=GOE\"}";
 
         InputStream is = getClass().getClassLoader()
                 .getResourceAsStream("test-user.token");
@@ -233,7 +238,7 @@
     public void testCreateVCUnauthorized () throws KustvaktException {
         String json =
                 "{\"name\": \"new vc\",\"type\": \"PRIVATE\",\"createdBy\": "
-                        + "\"test class\",\"corpusQuery\": \"creationDate since 1820\"}";
+                        + "\"VirtualCorpusControllerTest\",\"corpusQuery\": \"creationDate since 1820\"}";
 
         ClientResponse response = resource().path("vc").path("create")
                 .header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON)
@@ -255,12 +260,12 @@
     public void testCreateVCWithoutcorpusQuery () throws KustvaktException {
         String json =
                 "{\"name\": \"new vc\",\"type\": \"PRIVATE\",\"createdBy\": "
-                        + "\"test class\"}";
+                        + "\"VirtualCorpusControllerTest\"}";
 
         ClientResponse response = resource().path("vc").path("create")
                 .header(Attributes.AUTHORIZATION,
                         handler.createBasicAuthorizationHeaderValue(
-                                "test class", "pass"))
+                                "VirtualCorpusControllerTest", "pass"))
                 .header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON)
                 .entity(json).post(ClientResponse.class);
         String entity = response.getEntity(String.class);
@@ -277,12 +282,12 @@
     @Test
     public void testCreateVCWithoutType () throws KustvaktException {
         String json = "{\"name\": \"new vc\",\"createdBy\": "
-                + "\"test class\",\"corpusQuery\": \"creationDate since 1820\"}";
+                + "\"VirtualCorpusControllerTest\",\"corpusQuery\": \"creationDate since 1820\"}";
 
         ClientResponse response = resource().path("vc").path("create")
                 .header(Attributes.AUTHORIZATION,
                         handler.createBasicAuthorizationHeaderValue(
-                                "test class", "pass"))
+                                "VirtualCorpusControllerTest", "pass"))
                 .header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON)
                 .entity(json).post(ClientResponse.class);
         String entity = response.getEntity(String.class);
@@ -300,12 +305,12 @@
     public void testCreateVCWithWrongType () throws KustvaktException {
         String json =
                 "{\"name\": \"new vc\",\"type\": \"PRIVAT\",\"createdBy\": "
-                        + "\"test class\",\"corpusQuery\": \"creationDate since 1820\"}";
+                        + "\"VirtualCorpusControllerTest\",\"corpusQuery\": \"creationDate since 1820\"}";
 
         ClientResponse response = resource().path("vc").path("create")
                 .header(Attributes.AUTHORIZATION,
                         handler.createBasicAuthorizationHeaderValue(
-                                "test class", "pass"))
+                                "VirtualCorpusControllerTest", "pass"))
                 .header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON)
                 .entity(json).post(ClientResponse.class);
         String entity = response.getEntity(String.class);
@@ -327,7 +332,7 @@
                 resource().path("vc").path("delete").queryParam("vcId", "1")
                         .header(Attributes.AUTHORIZATION,
                                 handler.createBasicAuthorizationHeaderValue(
-                                        "test class", "pass"))
+                                        "VirtualCorpusControllerTest", "pass"))
                         .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
 
                         .delete(ClientResponse.class);
@@ -338,7 +343,7 @@
         assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
         assertEquals(StatusCodes.AUTHORIZATION_FAILED,
                 node.at("/errors/0/0").asInt());
-        assertEquals("Unauthorized operation for user: test class",
+        assertEquals("Unauthorized operation for user: VirtualCorpusControllerTest",
                 node.at("/errors/0/1").asText());
 
         checkWWWAuthenticateHeader(response);
@@ -346,19 +351,18 @@
 
     @Test
     public void testEditVC () throws KustvaktException {
-        
+
         // 1st edit
-        String json =
-                "{\"id\": \"1\", \"name\": \"edited vc\"}";
+        String json = "{\"id\": \"1\", \"name\": \"edited vc\"}";
 
         ClientResponse response = resource().path("vc").path("edit")
                 .header(Attributes.AUTHORIZATION,
-                        handler.createBasicAuthorizationHeaderValue(
-                                "dory", "pass"))
+                        handler.createBasicAuthorizationHeaderValue("dory",
+                                "pass"))
                 .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
                 .header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON)
                 .post(ClientResponse.class, json);
-        
+
         assertEquals(Status.OK.getStatusCode(), response.getStatus());
 
         // check VC
@@ -373,27 +377,26 @@
         assertEquals(Status.OK.getStatusCode(), response.getStatus());
 
         JsonNode node = JsonUtils.readTree(entity);
-        
-        for (int i=0; i<node.size(); i++){
+
+        for (int i = 0; i < node.size(); i++) {
             JsonNode n = node.get(i);
-            if (n.get("id").asInt() == 1){
+            if (n.get("id").asInt() == 1) {
                 assertEquals("edited vc", n.get("name").asText());
                 break;
             }
         }
-        
+
         // 2nd edit
-        json =
-                "{\"id\": \"1\", \"name\": \"dory VC\"}";
+        json = "{\"id\": \"1\", \"name\": \"dory VC\"}";
 
         response = resource().path("vc").path("edit")
                 .header(Attributes.AUTHORIZATION,
-                        handler.createBasicAuthorizationHeaderValue(
-                                "dory", "pass"))
+                        handler.createBasicAuthorizationHeaderValue("dory",
+                                "pass"))
                 .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
                 .header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON)
                 .post(ClientResponse.class, json);
-        
+
         assertEquals(Status.OK.getStatusCode(), response.getStatus());
 
         // check VC
@@ -404,35 +407,35 @@
                 .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
 
                 .get(ClientResponse.class);
-        
+
         assertEquals(Status.OK.getStatusCode(), response.getStatus());
-        
+
         entity = response.getEntity(String.class);
         node = JsonUtils.readTree(entity);
-        
-        for (int i=0; i<node.size(); i++){
+
+        for (int i = 0; i < node.size(); i++) {
             JsonNode n = node.get(i);
-            if (n.get("id").asInt() == 1){
+            if (n.get("id").asInt() == 1) {
                 assertEquals("dory VC", n.get("name").asText());
                 break;
             }
         }
     }
-    
+
     @Test
     public void testEditPublishVC () throws KustvaktException {
-        
+
         String json =
-                "{\"id\": \"1\", \"name\": \"dory pubished vc\", \"type\": \"PUBLISHED\"}";
+                "{\"id\": \"1\", \"name\": \"dory published vc\", \"type\": \"PUBLISHED\"}";
 
         ClientResponse response = resource().path("vc").path("edit")
                 .header(Attributes.AUTHORIZATION,
-                        handler.createBasicAuthorizationHeaderValue(
-                                "dory", "pass"))
+                        handler.createBasicAuthorizationHeaderValue("dory",
+                                "pass"))
                 .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
                 .header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON)
                 .post(ClientResponse.class, json);
-        
+
         assertEquals(Status.OK.getStatusCode(), response.getStatus());
 
         // check VC
@@ -447,39 +450,119 @@
         assertEquals(Status.OK.getStatusCode(), response.getStatus());
 
         JsonNode node = JsonUtils.readTree(entity);
-        
-        for (int i=0; i<node.size(); i++){
+
+        for (int i = 0; i < node.size(); i++) {
             JsonNode n = node.get(i);
-            if (n.get("id").asInt() == 1){
-                assertEquals("dory pubished vc", n.get("name").asText());
-                assertEquals(VirtualCorpusType.PUBLISHED.displayName(), n.get("type").asText());
+            if (n.get("id").asInt() == 1) {
+                assertEquals("dory published vc", n.get("name").asText());
+                assertEquals(VirtualCorpusType.PUBLISHED.displayName(),
+                        n.get("type").asText());
                 break;
             }
         }
     }
-    
+
     @Test
     public void testEditVCNotOwner () throws KustvaktException {
-        String json =
-                "{\"id\": \"1\", \"name\": \"edited vc\"}";
+        String json = "{\"id\": \"1\", \"name\": \"edited vc\"}";
 
         ClientResponse response = resource().path("vc").path("edit")
                 .header(Attributes.AUTHORIZATION,
                         handler.createBasicAuthorizationHeaderValue(
-                                "test class", "pass"))
+                                "VirtualCorpusControllerTest", "pass"))
                 .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
                 .header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON)
                 .post(ClientResponse.class, json);
         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());
         assertEquals(StatusCodes.AUTHORIZATION_FAILED,
                 node.at("/errors/0/0").asInt());
-        assertEquals("Unauthorized operation for user: test class",
+        assertEquals("Unauthorized operation for user: VirtualCorpusControllerTest",
                 node.at("/errors/0/1").asText());
 
         checkWWWAuthenticateHeader(response);
     }
+
+    @Test
+    public void testlistAccessByVC () throws KustvaktException {
+        ClientResponse response =
+                resource().path("vc").path("access").path("list")
+                        .queryParam("vcId", "2")
+                        .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);
+        String entity = response.getEntity(String.class);
+//        System.out.println(entity);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(1, node.at("/0/accessId").asInt());
+        assertEquals(2, node.at("/0/vcId").asInt());
+        assertEquals("group VC", node.at("/0/vcName").asText());
+        assertEquals(2, node.at("/0/userGroupId").asInt());
+        assertEquals("dory group", node.at("/0/userGroupName").asText());
+        
+    }
+    
+    @Test
+    public void testlistAccessNonVCAAdmin () throws KustvaktException {
+        ClientResponse response =
+                resource().path("vc").path("access").path("list")
+                        .queryParam("vcId", "2")
+                        .header(Attributes.AUTHORIZATION,
+                                handler.createBasicAuthorizationHeaderValue(
+                                        "nemo", "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);
+        assertEquals("[]", entity);       
+    }
+
+    @Test
+    public void testlistAccessMissingId () throws KustvaktException {
+        ClientResponse response =
+                resource().path("vc").path("access").path("list")
+                        .header(Attributes.AUTHORIZATION,
+                                handler.createBasicAuthorizationHeaderValue(
+                                        "VirtualCorpusControllerTest", "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);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+        assertEquals(StatusCodes.MISSING_ARGUMENT,
+                node.at("/errors/0/0").asInt());
+        assertEquals("vcId", node.at("/errors/0/1").asText());
+    }
+
+    @Test
+    public void testlistAccessByGroup () throws KustvaktException {
+        ClientResponse response =
+                resource().path("vc").path("access").path("list").path("byGroup")
+                        .queryParam("groupId", "2")
+                        .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);
+        String entity = response.getEntity(String.class);
+//        System.out.println(entity);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(1, node.at("/0/accessId").asInt());
+        assertEquals(2, node.at("/0/vcId").asInt());
+        assertEquals("group VC", node.at("/0/vcName").asText());
+        assertEquals(2, node.at("/0/userGroupId").asInt());
+        assertEquals("dory group", node.at("/0/userGroupName").asText());
+    }
     
 }