Implemented publish VC task.

Change-Id: I87ef9042d77036b3640aa2687377d94a99ddb9f5
diff --git a/full/src/main/java/de/ids_mannheim/korap/constant/PredefinedUserGroup.java b/full/src/main/java/de/ids_mannheim/korap/constant/PredefinedUserGroup.java
index 78b39cf..f218ac4 100644
--- a/full/src/main/java/de/ids_mannheim/korap/constant/PredefinedUserGroup.java
+++ b/full/src/main/java/de/ids_mannheim/korap/constant/PredefinedUserGroup.java
@@ -1,15 +1,21 @@
 package de.ids_mannheim.korap.constant;
 
 public enum PredefinedUserGroup {
-    ALL("all users");
+    ALL("all users", 1);
     
     private String value;
+    private int id;
 
-    PredefinedUserGroup (String value) {
+    PredefinedUserGroup (String value, int id) {
         this.value = value;
+        this.id = id;
     }
     
     public String getValue () {
         return value;
     }
+    
+    public int getId () {
+        return id;
+    }
 }
diff --git a/full/src/main/java/de/ids_mannheim/korap/dao/UserGroupDao.java b/full/src/main/java/de/ids_mannheim/korap/dao/UserGroupDao.java
index a1f74e6..cb04594 100644
--- a/full/src/main/java/de/ids_mannheim/korap/dao/UserGroupDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/dao/UserGroupDao.java
@@ -20,6 +20,7 @@
 
 import de.ids_mannheim.korap.constant.GroupMemberStatus;
 import de.ids_mannheim.korap.constant.PredefinedRole;
+import de.ids_mannheim.korap.constant.PredefinedUserGroup;
 import de.ids_mannheim.korap.constant.UserGroupStatus;
 import de.ids_mannheim.korap.constant.VirtualCorpusAccessStatus;
 import de.ids_mannheim.korap.entity.Role;
@@ -39,8 +40,6 @@
 @Repository
 public class UserGroupDao {
 
-    public static final String USER_GROUP_ALL = "all";
-
     @PersistenceContext
     private EntityManager entityManager;
 
@@ -104,7 +103,20 @@
             throws KustvaktException {
         UserGroup group = retrieveGroupById(groupId);
         group.setName(name);
-        entityManager.persist(group);
+        entityManager.merge(group);
+    }
+
+    public UserGroup retrieveAllUserGroup () {
+        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
+        CriteriaQuery<UserGroup> query =
+                criteriaBuilder.createQuery(UserGroup.class);
+
+        Root<UserGroup> root = query.from(UserGroup.class);
+        query.select(root);
+        query.where(criteriaBuilder.equal(root.get(UserGroup_.id),
+                PredefinedUserGroup.ALL.getId()));
+        Query q = entityManager.createQuery(query);
+        return (UserGroup) q.getSingleResult();
     }
 
     /** Retrieves the UserGroup by the given group id. This methods does not 
@@ -128,9 +140,8 @@
         query.where(criteriaBuilder.equal(root.get(UserGroup_.id), groupId));
         Query q = entityManager.createQuery(query);
 
-        UserGroup userGroup;
         try {
-            userGroup = (UserGroup) q.getSingleResult();
+            return (UserGroup) q.getSingleResult();
         }
         catch (NoResultException e) {
             throw new KustvaktException(StatusCodes.NO_RESULT_FOUND,
@@ -138,7 +149,6 @@
                             + groupId,
                     String.valueOf(groupId), e);
         }
-        return userGroup;
     }
 
     public UserGroup retrieveGroupWithMemberById (int groupId)
@@ -156,9 +166,8 @@
         query.where(criteriaBuilder.equal(root.get(UserGroup_.id), groupId));
         Query q = entityManager.createQuery(query);
 
-        UserGroup userGroup;
         try {
-            userGroup = (UserGroup) q.getSingleResult();
+            return (UserGroup) q.getSingleResult();
         }
         catch (NoResultException e) {
             throw new KustvaktException(StatusCodes.NO_RESULT_FOUND,
@@ -166,7 +175,6 @@
                             + groupId,
                     String.valueOf(groupId), e);
         }
-        return userGroup;
     }
 
     /** Retrieves only user-groups that are active (not hidden or deleted).
@@ -199,7 +207,18 @@
         query.select(root);
         query.where(restrictions);
         Query q = entityManager.createQuery(query);
-        return q.getResultList();
+
+        try {
+            return q.getResultList();
+        }
+        catch (NoResultException e) {
+            throw new KustvaktException(StatusCodes.NO_RESULT_FOUND,
+                    "No result found for query: retrieve group by used id "
+                            + userId,
+                    userId, e);
+        }
+
+
     }
 
     public UserGroup retrieveGroupByName (String groupName)
@@ -216,9 +235,8 @@
                 criteriaBuilder.equal(root.get(UserGroup_.name), groupName));
         Query q = entityManager.createQuery(query);
 
-        UserGroup userGroup;
         try {
-            userGroup = (UserGroup) q.getSingleResult();
+            return (UserGroup) q.getSingleResult();
         }
         catch (NoResultException e) {
             throw new KustvaktException(StatusCodes.NO_RESULT_FOUND,
@@ -226,7 +244,6 @@
                             + groupName,
                     groupName, e);
         }
-        return userGroup;
     }
 
     //    public void retrieveGroupByVCId (String vcId) {
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
new file mode 100644
index 0000000..98e7990
--- /dev/null
+++ b/full/src/main/java/de/ids_mannheim/korap/dao/VirtualCorpusAccessDao.java
@@ -0,0 +1,106 @@
+package de.ids_mannheim.korap.dao;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Join;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import de.ids_mannheim.korap.constant.VirtualCorpusAccessStatus;
+import de.ids_mannheim.korap.entity.UserGroup;
+import de.ids_mannheim.korap.entity.VirtualCorpus;
+import de.ids_mannheim.korap.entity.VirtualCorpusAccess;
+import de.ids_mannheim.korap.entity.VirtualCorpusAccess_;
+import de.ids_mannheim.korap.entity.VirtualCorpus_;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.utils.ParameterChecker;
+
+@Transactional
+@Repository
+public class VirtualCorpusAccessDao {
+
+    @PersistenceContext
+    private EntityManager entityManager;
+
+    public List<VirtualCorpusAccess> retrieveAccessByVC (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);
+
+        query.select(access);
+        query.where(builder.equal(accessVC.get(VirtualCorpus_.id), vcId));
+        Query q = entityManager.createQuery(query);
+        return q.getResultList();
+    }
+
+    /** Hidden accesses are only created for published or system VC. 
+     * 
+     * Warn: The actual hidden accesses are not checked.
+     * 
+     * @param vcId vcId 
+     * @return true if there is a hidden access, false otherwise
+     * @throws KustvaktException
+     */
+    public boolean hasHiddenAccess (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.HIDDEN),
+                builder.notEqual(access.get(VirtualCorpusAccess_.deletedBy),
+                        "NULL"));
+
+        query.select(access);
+        query.where(p);
+        try {
+            Query q = entityManager.createQuery(query);
+            List<VirtualCorpusAccess> resultList = q.getResultList();
+            if (resultList.isEmpty()) {
+                return false;
+            }
+            else {
+                return true;
+            }
+        }
+        catch (NoResultException e) {
+            return false;
+        }
+    }
+
+    public void addAccessToVC (VirtualCorpus virtualCorpus, UserGroup userGroup,
+            String createdBy, VirtualCorpusAccessStatus status) {
+        VirtualCorpusAccess vca = new VirtualCorpusAccess();
+        vca.setVirtualCorpus(virtualCorpus);
+        vca.setUserGroup(userGroup);
+        vca.setCreatedBy(createdBy);
+        vca.setStatus(status);
+        entityManager.persist(vca);
+    }
+}
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 936c56f..a7690d7 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
@@ -11,7 +11,6 @@
 import javax.persistence.criteria.CriteriaBuilder;
 import javax.persistence.criteria.CriteriaQuery;
 import javax.persistence.criteria.Join;
-import javax.persistence.criteria.ListJoin;
 import javax.persistence.criteria.Predicate;
 import javax.persistence.criteria.Root;
 
@@ -49,7 +48,7 @@
     private EntityManager entityManager;
 
     public int createVirtualCorpus (String name, VirtualCorpusType type,
-            CorpusAccess requiredAccess, String collectionQuery,
+            CorpusAccess requiredAccess, String corpusQuery,
             String definition, String description, String status,
             String createdBy) throws KustvaktException {
 
@@ -57,7 +56,7 @@
         vc.setName(name);
         vc.setType(type);
         vc.setRequiredAccess(requiredAccess);
-        vc.setCollectionQuery(collectionQuery);
+        vc.setCorpusQuery(corpusQuery);
         vc.setDefinition(definition);
         vc.setDescription(description);
         vc.setStatus(status);
@@ -69,7 +68,7 @@
 
     public void editVirtualCorpus (VirtualCorpus vc, String name,
             VirtualCorpusType type, CorpusAccess requiredAccess,
-            String collectionQuery, String definition, String description,
+            String corpusQuery, String definition, String description,
             String status) throws KustvaktException {
 
         if (name != null && !name.isEmpty()) {
@@ -81,8 +80,8 @@
         if (requiredAccess != null) {
             vc.setRequiredAccess(requiredAccess);
         }
-        if (collectionQuery != null) {
-            vc.setCollectionQuery(collectionQuery);
+        if (corpusQuery != null) {
+            vc.setCorpusQuery(corpusQuery);
         }
         if (definition != null && !definition.isEmpty()) {
             vc.setDefinition(definition);
@@ -101,6 +100,7 @@
         entityManager.remove(vc);
     }
 
+    // for admins
     public List<VirtualCorpus> retrieveVCByType (VirtualCorpusType type)
             throws KustvaktException {
         ParameterChecker.checkObjectValue(type, "type");
@@ -116,7 +116,6 @@
         return q.getResultList();
     }
 
-
     public VirtualCorpus retrieveVCById (int id) throws KustvaktException {
         ParameterChecker.checkIntegerValue(id, "id");
 
@@ -142,8 +141,7 @@
         return vc;
     }
 
-
-    public List<VirtualCorpus> retrievePrivateVC (String userId)
+    public List<VirtualCorpus> retrieveOwnerVC (String userId)
             throws KustvaktException {
         ParameterChecker.checkStringValue(userId, "userId");
 
@@ -159,7 +157,29 @@
         Query q = entityManager.createQuery(query);
         return q.getResultList();
     }
+    
+    public List<VirtualCorpus> retrieveOwnerVCByType (String userId, VirtualCorpusType type)
+            throws KustvaktException {
+        ParameterChecker.checkStringValue(userId, "userId");
 
+        CriteriaBuilder builder = entityManager.getCriteriaBuilder();
+        CriteriaQuery<VirtualCorpus> query =
+                builder.createQuery(VirtualCorpus.class);
+
+        Root<VirtualCorpus> virtualCorpus = query.from(VirtualCorpus.class);
+        query.select(virtualCorpus);
+        
+        Predicate p = builder.and(
+                builder.equal(virtualCorpus.get(VirtualCorpus_.createdBy),
+                        userId),
+                builder.equal(virtualCorpus.get(VirtualCorpus_.type),
+                        type)
+                );
+        query.where(p);
+
+        Query q = entityManager.createQuery(query);
+        return q.getResultList();
+    }
 
     public List<VirtualCorpus> retrieveGroupVCByUser (String userId)
             throws KustvaktException {
@@ -199,7 +219,6 @@
         return q.getResultList();
     }
 
-
     public Set<VirtualCorpus> retrieveVCByUser (String userId)
             throws KustvaktException {
         ParameterChecker.checkStringValue(userId, "userId");
@@ -229,6 +248,7 @@
         return vcSet;
     }
 
+    // for admins
     public List<VirtualCorpus> retrieveVCByGroup (int groupId)
             throws KustvaktException {
         ParameterChecker.checkIntegerValue(groupId, "groupId");
@@ -238,7 +258,7 @@
                 builder.createQuery(VirtualCorpus.class);
 
         Root<VirtualCorpus> virtualCorpus = query.from(VirtualCorpus.class);
-        ListJoin<VirtualCorpus, VirtualCorpusAccess> corpusAccess =
+        Join<VirtualCorpus, VirtualCorpusAccess> corpusAccess =
                 virtualCorpus.join(VirtualCorpus_.virtualCorpusAccess);
         Join<VirtualCorpusAccess, UserGroup> accessGroup =
                 corpusAccess.join(VirtualCorpusAccess_.userGroup);
@@ -249,11 +269,4 @@
         return q.getResultList();
     }
 
-    // EM: what is needed for admin?
-    public List<VirtualCorpus> retrieveVirtualCorpusByAdmin () {
-        return null;
-
-    }
-
-
 }
diff --git a/full/src/main/java/de/ids_mannheim/korap/dto/converter/VirtualCorpusConverter.java b/full/src/main/java/de/ids_mannheim/korap/dto/converter/VirtualCorpusConverter.java
index e05f203..66a74a5 100644
--- a/full/src/main/java/de/ids_mannheim/korap/dto/converter/VirtualCorpusConverter.java
+++ b/full/src/main/java/de/ids_mannheim/korap/dto/converter/VirtualCorpusConverter.java
@@ -23,7 +23,7 @@
         dto.setStatus(vc.getStatus());
         dto.setDescription(vc.getDescription());
         dto.setType(vc.getType().displayName());
-        dto.setKoralQuery(vc.getCollectionQuery());
+        dto.setKoralQuery(vc.getCorpusQuery());
 
         JsonNode node = JsonUtils.readTree(statistics);
         int numberOfDoc = node.at("/documents").asInt();
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 8413c24..e62af0c 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
@@ -46,8 +46,8 @@
     @Enumerated(EnumType.STRING)
     @Column(name = "required_access")
     private CorpusAccess requiredAccess;
-    @Column(name = "collection_query")
-    private String collectionQuery;
+    @Column(name = "corpus_query")
+    private String corpusQuery;
     private String definition;
     @Column(name = "created_by")
     private String createdBy;
@@ -59,7 +59,7 @@
     public String toString () {
         return "id=" + id + ", name= " + name + ", type= " + type + ", status= "
                 + status + ", description=" + description + ", requiredAccess="
-                + requiredAccess + ", collectionQuery= " + collectionQuery
+                + requiredAccess + ", corpusQuery= " + corpusQuery
                 + ", definition= " + definition + ", createdBy= " + createdBy;
     }
     
diff --git a/full/src/main/java/de/ids_mannheim/korap/entity/VirtualCorpusAccess.java b/full/src/main/java/de/ids_mannheim/korap/entity/VirtualCorpusAccess.java
index 873aac7..c3bba6e 100644
--- a/full/src/main/java/de/ids_mannheim/korap/entity/VirtualCorpusAccess.java
+++ b/full/src/main/java/de/ids_mannheim/korap/entity/VirtualCorpusAccess.java
@@ -43,12 +43,12 @@
     @Enumerated(EnumType.STRING)
     private VirtualCorpusAccessStatus status;
 
-    @ManyToOne(fetch=FetchType.LAZY)
+    @ManyToOne(fetch=FetchType.EAGER)
     @JoinColumn(name = "virtual_corpus_id",
             referencedColumnName = "id")
     private VirtualCorpus virtualCorpus;
 
-    @ManyToOne(fetch=FetchType.LAZY)
+    @ManyToOne(fetch=FetchType.EAGER)
     @JoinColumn(name = "user_group_id", referencedColumnName = "id")
     private UserGroup userGroup;
 
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 7751988..77c6554 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
@@ -77,7 +77,15 @@
 
         return dtos;
     }
-
+    
+    public UserGroup retrieveUserGroupById (int groupId)
+            throws KustvaktException {
+        return userGroupDao.retrieveGroupById(groupId);
+    }
+    
+    public UserGroup retrieveAllUserGroup () {
+        return userGroupDao.retrieveAllUserGroup();
+    }
 
     /** Group owner is automatically added when creating a group. 
      *  Do not include owners in group members. 
@@ -131,7 +139,7 @@
     }
 
     public int createAutoHiddenGroup (int vcId) throws KustvaktException {
-        String groupName = "auto-group-VC" + vcId;
+        String groupName = "auto-published-group";
         int groupId = userGroupDao.createGroup(groupName, "system",
                 UserGroupStatus.HIDDEN);
 
@@ -162,4 +170,5 @@
             throws KustvaktException {
         groupMemberDao.deleteMember(username, groupId, true);
     }
+
 }
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 dee1da7..5f8bed0 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,6 +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;
 
@@ -14,12 +16,15 @@
 
 import de.ids_mannheim.korap.config.FullConfiguration;
 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;
 import de.ids_mannheim.korap.dao.VirtualCorpusDao;
 import de.ids_mannheim.korap.dto.VirtualCorpusDto;
 import de.ids_mannheim.korap.dto.converter.VirtualCorpusConverter;
 import de.ids_mannheim.korap.entity.UserGroup;
 import de.ids_mannheim.korap.entity.VirtualCorpus;
+import de.ids_mannheim.korap.entity.VirtualCorpusAccess;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.interfaces.AuthenticationManagerIface;
@@ -34,8 +39,8 @@
 import de.ids_mannheim.korap.web.input.VirtualCorpusJson;
 
 /** VirtualCorpusService handles the logic behind {@link VirtualCorpusController}. 
- *  It communicates with {@link VirtualCorpusDao} and returns DTO to  
- *  {@link VirtualCorpusController}.
+ *  It communicates with {@link VirtualCorpusDao} and returns 
+ *  {@link VirtualCorpusDto} to {@link VirtualCorpusController}.
  * 
  * @author margaretha
  *
@@ -47,7 +52,9 @@
             LoggerFactory.getLogger(VirtualCorpusService.class);
 
     @Autowired
-    private VirtualCorpusDao dao;
+    private VirtualCorpusDao vcDao;
+    @Autowired
+    private VirtualCorpusAccessDao accessDao;
     @Autowired
     private UserGroupService userGroupService;
     @Autowired
@@ -59,13 +66,12 @@
     @Autowired
     private VirtualCorpusConverter converter;
 
-    public void storeVC (VirtualCorpusJson vc, String username)
+    public int storeVC (VirtualCorpusJson vc, String username)
             throws KustvaktException {
 
         ParameterChecker.checkStringValue(vc.getName(), "name");
         ParameterChecker.checkObjectValue(vc.getType(), "type");
-        ParameterChecker.checkStringValue(vc.getCollectionQuery(),
-                "collectionQuery");
+        ParameterChecker.checkStringValue(vc.getCorpusQuery(), "corpusQuery");
         ParameterChecker.checkStringValue(vc.getCreatedBy(), "createdBy");
 
         User user = authManager.getUser(username);
@@ -76,31 +82,25 @@
                     "Unauthorized operation for user: " + username, username);
         }
 
-        String koralQuery = serializeCollectionQuery(vc.getCollectionQuery());
+        String koralQuery = serializeCorpusQuery(vc.getCorpusQuery());
         CorpusAccess requiredAccess = determineRequiredAccess(koralQuery);
 
-        int vcId = dao.createVirtualCorpus(vc.getName(), vc.getType(),
+        int vcId = vcDao.createVirtualCorpus(vc.getName(), vc.getType(),
                 requiredAccess, koralQuery, vc.getDefinition(),
                 vc.getDescription(), vc.getStatus(), vc.getCreatedBy());
 
-        // EM: how about VirtualCorpusType.PUBLISHED?
-        //        if (vc.getType() != null
-        //                && vc.getType().equals(VirtualCorpusType.PUBLISHED)) {
-        //            int groupId = userGroupService.createAutoHiddenGroup(vcId);
-        //            UserGroup allUserGroup = userGroupDao
-        //                    .retrieveGroupByName(PredefinedUserGroup.ALL.getValue());
-        //            int allUserGroupId = allUserGroup.getId();
-        //            // add access to VC for all and auto-group
-        //        }
-
+        if (vc.getType().equals(VirtualCorpusType.PUBLISHED)) {
+            publishVC(vcId);
+        }
         // EM: should this return anything?
+        return vcId;
     }
 
     public void editVC (VirtualCorpusJson vcJson, String username)
             throws KustvaktException {
 
         ParameterChecker.checkIntegerValue(vcJson.getId(), "id");
-        VirtualCorpus vc = dao.retrieveVCById(vcJson.getId());
+        VirtualCorpus vc = vcDao.retrieveVCById(vcJson.getId());
 
         User user = authManager.getUser(username);
 
@@ -111,31 +111,57 @@
 
         String koralQuery = null;
         CorpusAccess requiredAccess = null;
-        if (vcJson.getCollectionQuery() != null
-                && vcJson.getCollectionQuery().isEmpty()) {
-            koralQuery = serializeCollectionQuery(vcJson.getCollectionQuery());
+        if (vcJson.getCorpusQuery() != null
+                && vcJson.getCorpusQuery().isEmpty()) {
+            koralQuery = serializeCorpusQuery(vcJson.getCorpusQuery());
             requiredAccess = determineRequiredAccess(koralQuery);
         }
 
-        dao.editVirtualCorpus(vc, vcJson.getName(), vcJson.getType(), requiredAccess,
-                koralQuery, vcJson.getDefinition(), vcJson.getDescription(),
-                vcJson.getStatus());
-        
-        vc = dao.retrieveVCById(vcJson.getId());
+        vcDao.editVirtualCorpus(vc, vcJson.getName(), vcJson.getType(),
+                requiredAccess, koralQuery, vcJson.getDefinition(),
+                vcJson.getDescription(), vcJson.getStatus());
 
+        if (!vc.getType().equals(VirtualCorpusType.PUBLISHED)
+                && vcJson.getType() != null
+                && vcJson.getType().equals(VirtualCorpusType.PUBLISHED)) {
+            publishVC(vcJson.getId());
+        }
     }
 
-    private String serializeCollectionQuery (String collectionQuery)
+    private void publishVC (int vcId) throws KustvaktException {
+
+        // check if hidden access exists
+        if (!accessDao.hasHiddenAccess(vcId)) {
+            // assign hidden access for all users
+            VirtualCorpus vc = vcDao.retrieveVCById(vcId);
+            UserGroup all = userGroupService.retrieveAllUserGroup();
+            accessDao.addAccessToVC(vc, all, "system",
+                    VirtualCorpusAccessStatus.HIDDEN);
+
+            // create and assign a hidden group
+            int groupId = userGroupService.createAutoHiddenGroup(vcId);
+            UserGroup autoHidden =
+                    userGroupService.retrieveUserGroupById(groupId);
+            accessDao.addAccessToVC(vc, autoHidden, "system",
+                    VirtualCorpusAccessStatus.HIDDEN);
+        }
+        else {
+            jlog.error("Cannot publish VC with id: " + vcId
+                    + ". There have been hidden accesses for the VC already.");
+        }
+    }
+
+    private String serializeCorpusQuery (String corpusQuery)
             throws KustvaktException {
         QuerySerializer serializer = new QuerySerializer();
-        serializer.setCollection(collectionQuery);
+        serializer.setCollection(corpusQuery);
         String koralQuery;
         try {
             koralQuery = serializer.convertCollectionToJson();
         }
         catch (JsonProcessingException e) {
             throw new KustvaktException(StatusCodes.INVALID_ARGUMENT,
-                    "Invalid argument: " + collectionQuery, collectionQuery);
+                    "Invalid argument: " + corpusQuery, corpusQuery);
         }
         jlog.debug(koralQuery);
         return koralQuery;
@@ -169,14 +195,26 @@
         return (numberOfDoc > 0) ? true : false;
     }
 
-    public List<VirtualCorpusDto> retrieveUserVC (String username)
+    public List<VirtualCorpusDto> listOwnerVC (String username)
             throws KustvaktException {
+        List<VirtualCorpus> vcList = vcDao.retrieveOwnerVC(username);
+        return createVCDtos(vcList);
+    }
 
-        Set<VirtualCorpus> vcs = dao.retrieveVCByUser(username);
-        ArrayList<VirtualCorpusDto> dtos = new ArrayList<>(vcs.size());
+    public List<VirtualCorpusDto> listVCByUser (String username)
+            throws KustvaktException {
+        Set<VirtualCorpus> vcSet = vcDao.retrieveVCByUser(username);
+        return createVCDtos(vcSet);
+    }
 
-        for (VirtualCorpus vc : vcs) {
-            String json = vc.getCollectionQuery();
+    private ArrayList<VirtualCorpusDto> createVCDtos (
+            Collection<VirtualCorpus> vcList) throws KustvaktException {
+        ArrayList<VirtualCorpusDto> dtos = new ArrayList<>(vcList.size());
+        VirtualCorpus vc;
+        Iterator<VirtualCorpus> i = vcList.iterator();
+        while (i.hasNext()) {
+            vc = i.next();
+            String json = vc.getCorpusQuery();
             String statistics = krill.getStatistics(json);
             VirtualCorpusDto vcDto =
                     converter.createVirtualCorpusDto(vc, statistics);
@@ -188,8 +226,6 @@
     /** Only admin and the owner of the virtual corpus are allowed to 
      *  delete a virtual corpus.
      *  
-     *  EM: are VC-access admins also allowed to delete?
-     * 
      * @param username username
      * @param vcId virtual corpus id
      * @throws KustvaktException
@@ -197,14 +233,19 @@
     public void deleteVC (String username, int vcId) throws KustvaktException {
 
         User user = authManager.getUser(username);
-        VirtualCorpus vc = dao.retrieveVCById(vcId);
+        VirtualCorpus vc = vcDao.retrieveVCById(vcId);
 
         if (user.isAdmin() || vc.getCreatedBy().equals(username)) {
-            dao.deleteVirtualCorpus(vcId);
+            vcDao.deleteVirtualCorpus(vcId);
         }
         else {
             throw new KustvaktException(StatusCodes.AUTHORIZATION_FAILED,
                     "Unauthorized operation for user: " + username, username);
         }
     }
+
+    public List<VirtualCorpusAccess> retrieveVCAccess (int vcId)
+            throws KustvaktException {
+        return accessDao.retrieveAccessByVC(vcId);
+    }
 }
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 ada1c8f..2e018fe 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
@@ -112,13 +112,35 @@
      */
     @GET
     @Path("list")
-    public Response getUserVC (@Context SecurityContext securityContext) {
+    public Response listVCByUser (@Context SecurityContext securityContext) {
         String result;
         TokenContext context =
                 (TokenContext) securityContext.getUserPrincipal();
         try {
             List<VirtualCorpusDto> dtos =
-                    service.retrieveUserVC(context.getUsername());
+                    service.listVCByUser(context.getUsername());
+            result = JsonUtils.toJSON(dtos);
+        }
+        catch (KustvaktException e) {
+            throw responseHandler.throwit(e);
+        }
+        return Response.ok(result).build();
+    }
+    
+    /** Lists all VCs created by a user
+     * 
+     * @param securityContext
+     * @return a list of VCs created by the user in the security context.
+     */
+    @GET
+    @Path("list/user")
+    public Response listUserVC (@Context SecurityContext securityContext) {
+        String result;
+        TokenContext context =
+                (TokenContext) securityContext.getUserPrincipal();
+        try {
+            List<VirtualCorpusDto> dtos =
+                    service.listOwnerVC(context.getUsername());
             result = JsonUtils.toJSON(dtos);
         }
         catch (KustvaktException e) {
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/input/VirtualCorpusJson.java b/full/src/main/java/de/ids_mannheim/korap/web/input/VirtualCorpusJson.java
index 7038690..2c8b35a 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/input/VirtualCorpusJson.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/input/VirtualCorpusJson.java
@@ -4,7 +4,6 @@
 import de.ids_mannheim.korap.constant.VirtualCorpusType;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.service.VirtualCorpusService;
-import de.ids_mannheim.korap.utils.ParameterChecker;
 import de.ids_mannheim.korap.web.controller.VirtualCorpusController;
 import lombok.Getter;
 import lombok.Setter;
@@ -23,7 +22,7 @@
     // required in creating VCs
     private String name;
     private VirtualCorpusType type;
-    private String collectionQuery;
+    private String corpusQuery;
     private String createdBy;
     
     // required in editing VCs
@@ -35,9 +34,9 @@
     private String status;
 
 
-    public void setCollectionQuery (String collectionQuery)
+    public void setCorpusQuery (String corpusQuery)
             throws KustvaktException {
         
-        this.collectionQuery = collectionQuery;
+        this.corpusQuery = corpusQuery;
     }
 }
\ No newline at end of file