Added and improved tests, added collectionQuery to CollectionLoader.

Change-Id: I6a10f8b7d0397493417e2e9914895317b46fae78
diff --git a/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java b/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java
index 4bd1605..6b7f7c2 100644
--- a/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java
+++ b/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java
@@ -19,7 +19,7 @@
  * if configuration class is extended, loadSubTypes method should be
  * overriden
  * 
- * @author hanl
+ * @author hanl, margaretha
  * @date 05/02/2014
  */
 
diff --git a/src/main/java/de/ids_mannheim/korap/resources/ResourceFactory.java b/src/main/java/de/ids_mannheim/korap/resources/ResourceFactory.java
index 1966e93..76cc144 100644
--- a/src/main/java/de/ids_mannheim/korap/resources/ResourceFactory.java
+++ b/src/main/java/de/ids_mannheim/korap/resources/ResourceFactory.java
@@ -76,6 +76,12 @@
 
     public static <T extends KustvaktResource> Class<T> getResourceClass (
             String type) throws KustvaktException {
+        
+        if (type == null || type.isEmpty()){
+            throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT, 
+                    "resource type could not be identified!");
+        }
+        
         for (Class value : subTypes) {
             if (value == VirtualCollection.class
                     && type.equalsIgnoreCase("collection"))
@@ -88,7 +94,8 @@
             }
         }
         // todo: throw exception in case of missing parameter!
-        throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT, "resource type could not be identified!");
+        throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT, 
+                "resource type could not be identified!");
     }
 
 
diff --git a/src/main/java/de/ids_mannheim/korap/security/ac/ResourceFinder.java b/src/main/java/de/ids_mannheim/korap/security/ac/ResourceFinder.java
index c319145..06acf52 100644
--- a/src/main/java/de/ids_mannheim/korap/security/ac/ResourceFinder.java
+++ b/src/main/java/de/ids_mannheim/korap/security/ac/ResourceFinder.java
@@ -4,6 +4,7 @@
 import de.ids_mannheim.korap.config.BeansFactory;
 import de.ids_mannheim.korap.exceptions.EmptyResultException;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.interfaces.db.PolicyHandlerIface;
 import de.ids_mannheim.korap.interfaces.db.ResourceOperationIface;
 import de.ids_mannheim.korap.resources.KustvaktResource;
@@ -113,14 +114,17 @@
         List<String> id_set = Arrays.asList(ids);
         for (SecurityPolicy policy : policies) {
             if (id_set.isEmpty() || id_set.contains(policy.getTarget())) {
+                @SuppressWarnings("unchecked")
                 T r = (T) resourcedaos.get(KustvaktResource.class).findbyId(
                         policy.getTarget(), User.UserFactory.getDemoUser());
                 sets.add(r);
             }
         }
 
-        if (sets.isEmpty())
-            throw new EmptyResultException(Arrays.asList(ids).toString());
+        if (sets.isEmpty()){
+            throw new KustvaktException(StatusCodes.NO_VALUE_FOUND, 
+                    "Cannot found public resources with ids: "+id_set.toString());
+        }
         return sets;
     }
 
diff --git a/src/main/java/de/ids_mannheim/korap/web/service/CollectionLoader.java b/src/main/java/de/ids_mannheim/korap/web/service/CollectionLoader.java
index 113df66..514afcf 100644
--- a/src/main/java/de/ids_mannheim/korap/web/service/CollectionLoader.java
+++ b/src/main/java/de/ids_mannheim/korap/web/service/CollectionLoader.java
@@ -11,23 +11,20 @@
 import de.ids_mannheim.korap.config.KustvaktConfiguration;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.resources.Corpus;
-import de.ids_mannheim.korap.resources.Foundry;
 import de.ids_mannheim.korap.resources.KustvaktResource;
-import de.ids_mannheim.korap.resources.Layer;
-import de.ids_mannheim.korap.resources.Permissions;
-import de.ids_mannheim.korap.resources.VirtualCollection;
 import de.ids_mannheim.korap.resources.Permissions.Permission;
+import de.ids_mannheim.korap.resources.VirtualCollection;
 import de.ids_mannheim.korap.security.ac.PolicyBuilder;
 import de.ids_mannheim.korap.security.ac.ResourceFinder;
 import de.ids_mannheim.korap.security.ac.SecurityManager;
 import de.ids_mannheim.korap.user.User;
-import de.ids_mannheim.korap.utils.KoralCollectionQueryBuilder;
 import de.ids_mannheim.korap.utils.JsonUtils;
+import de.ids_mannheim.korap.utils.KoralCollectionQueryBuilder;
 
 /**
- * @author hanl
+ * @author hanl, margaretha
  * @date 12/01/2016
+ * @lastupdate 19/04/2017
  */
 public class CollectionLoader implements BootableBeanInterface {
 
@@ -40,99 +37,114 @@
                 .toUser(KustvaktConfiguration.KUSTVAKT_USER);
 
         KustvaktConfiguration config = beans.getConfiguration();
-        
-//        KoralCollectionQueryBuilder bui = new KoralCollectionQueryBuilder();
-//        bui.with("creationDate since 1775 & corpusSigle=GOE");
-//
-//        VirtualCollection c1 = new VirtualCollection();
-//        c1.setName("Weimarer Werke");
-//
-//        c1.setFields(bui.toJSON());
-//
-//        c1.setDescription("Goethe-Werke in Weimar (seit 1775)");
-//
-//        bui = new KoralCollectionQueryBuilder();
-//        bui.with("textType=Aphorismus");
-//
-//        VirtualCollection c2 = new VirtualCollection();
-//        c2.setName("Aphorismen");
-//        c2.setFields(bui.toJSON());
-//        c2.setDescription("Aphorismentexte Goethes");
-//
-//        bui = new KoralCollectionQueryBuilder();
-//        bui.with("title ~ \"Werther\"");
-//
-//        VirtualCollection c3 = new VirtualCollection();
-//        c3.setName("Werther");
-//        c3.setFields(bui.toJSON());
-//        c3.setDescription("Goethe - Die Leiden des jungen Werther");
-        
+
+        //        KoralCollectionQueryBuilder bui = new KoralCollectionQueryBuilder();
+        //        bui.with("creationDate since 1775 & corpusSigle=GOE");
+        //
+        //        VirtualCollection c1 = new VirtualCollection();
+        //        c1.setName("Weimarer Werke");
+        //
+        //        c1.setFields(bui.toJSON());
+        //
+        //        c1.setDescription("Goethe-Werke in Weimar (seit 1775)");
+        //
+        //        bui = new KoralCollectionQueryBuilder();
+        //        bui.with("textType=Aphorismus");
+        //
+        //        VirtualCollection c2 = new VirtualCollection();
+        //        c2.setName("Aphorismen");
+        //        c2.setFields(bui.toJSON());
+        //        c2.setDescription("Aphorismentexte Goethes");
+        //
+        //        bui = new KoralCollectionQueryBuilder();
+        //        bui.with("title ~ \"Werther\"");
+        //
+        //        VirtualCollection c3 = new VirtualCollection();
+        //        c3.setName("Werther");
+        //        c3.setFields(bui.toJSON());
+        //        c3.setDescription("Goethe - Die Leiden des jungen Werther");
+
         PolicyBuilder builder = new PolicyBuilder(user);
         String result = null;
-		BufferedReader br;
-		try {
-			File f = new File(config.getPolicyConfig());
-			br = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
-		} catch (FileNotFoundException e) {
-			throw new KustvaktException("Policy config file: " + 
-					config.getPolicyConfig() + " does not exists!",
-					e.getCause(), 101);
-		}
-		String policy = null;
-		String[] policyData = null;
-		String type, id, name, description, condition;
-		String[] permissions;
-		try {
-			while ((policy = br.readLine()) != null) {
-				if (policy.startsWith("#") || policy.isEmpty()) continue;
-				policyData = policy.split("\t");
-				type = policyData[0];
-				id = policyData[1];
-				name = policyData[2];
-				description = policyData[3];
-				condition = policyData[4];
-				permissions = policyData[5].split(",");
+        BufferedReader br;
+        try {
+            File f = new File(config.getPolicyConfig());
+            br = new BufferedReader(
+                    new InputStreamReader(new FileInputStream(f)));
+        }
+        catch (FileNotFoundException e) {
+            throw new KustvaktException("Policy config file: "
+                    + config.getPolicyConfig() + " does not exists!",
+                    e.getCause(), 101);
+        }
+        String policy = null, collectionQuery = null;
+        String[] policyData = null;
+        String type, id, name, description, condition;
+        String[] permissions;
+        try {
+            while ((policy = br.readLine()) != null) {
+                if (policy.startsWith("#") || policy.isEmpty())
+                    continue;
+                policyData = policy.split("\t");
+                type = policyData[0];
+                id = policyData[1];
+                name = policyData[2];
+                description = policyData[3];
+                condition = policyData[4];
+                permissions = policyData[5].split(",");
+                if (policyData.length > 6)
+                    collectionQuery = policyData[6];
 
-				Permission[] permissionArr = new Permission[permissions.length];
-				for (int i = 0; i < permissions.length; i++) {
-					if (permissions[i].equals("read")) {
-						permissionArr[i] = Permission.READ;
-					}
-				}
+                Permission[] permissionArr = new Permission[permissions.length];
+                for (int i = 0; i < permissions.length; i++) {
+                    if (permissions[i].equals("read")) {
+                        permissionArr[i] = Permission.READ;
+                    }
+                }
 
-				KustvaktResource resource = createResource(type, id, name, description);
-				if (resource != null) {
-					builder = new PolicyBuilder(user);
-					builder.addCondition(condition);
-					builder.setResources(resource);
-					builder.setPermissions(permissionArr);
-					result = builder.create();
-					if (JsonUtils.readTree(result).size() > 0)
-			            throw new KustvaktException(StatusCodes.REQUEST_INVALID,
-			                    "creating collections caused errors", result);
-				}
-			}
-			br.close();
-		} catch (IOException e) {
-			throw new KustvaktException("Failed creating virtual collections.", e.getCause(), 100);
-		}
+                KustvaktResource resource = createResource(type, id, name,
+                        description, collectionQuery);
+                if (resource != null) {
+                    builder = new PolicyBuilder(user);
+                    builder.addCondition(condition);
+                    builder.setResources(resource);
+                    builder.setPermissions(permissionArr);
+                    result = builder.create();
+                    if (JsonUtils.readTree(result).size() > 0)
+                        throw new KustvaktException(StatusCodes.REQUEST_INVALID,
+                                "creating collections caused errors", result);
+                }
+            }
+            br.close();
+        }
+        catch (IOException e) {
+            throw new KustvaktException("Failed creating virtual collections.",
+                    e.getCause(), 100);
+        }
     }
 
-    private KustvaktResource createResource(String type, String id, String name, String description) {
 
-		KustvaktResource resource = null;
-		if (type.equals("virtualcollection")) {
-			resource = new VirtualCollection(id);
-			if (!name.isEmpty()) {
-				resource.setName(name);
-			}
-			if (!description.isEmpty()) {
-				resource.setDescription(description);
-			}
-		}
+    private KustvaktResource createResource (String type, String id,
+            String name, String description, String docQuery) {
+        KoralCollectionQueryBuilder builder;
+        KustvaktResource resource = null;
+        if (type.equals("virtualcollection")) {
+            resource = new VirtualCollection(id);
+            if (!name.isEmpty()) {
+                resource.setName(name);
+            }
+            if (!description.isEmpty()) {
+                resource.setDescription(description);
+            }
+            if (docQuery != null && !docQuery.isEmpty()) {
+                builder = new KoralCollectionQueryBuilder();
+                builder.with(docQuery);
+                resource.setFields(builder.toJSON());
+            }
+        }
 
-		return resource;
-	}
+        return resource;
+    }
 
 
     @Override
diff --git a/src/main/java/de/ids_mannheim/korap/web/service/full/ResourceService.java b/src/main/java/de/ids_mannheim/korap/web/service/full/ResourceService.java
index ebeb8e2..df35d9b 100644
--- a/src/main/java/de/ids_mannheim/korap/web/service/full/ResourceService.java
+++ b/src/main/java/de/ids_mannheim/korap/web/service/full/ResourceService.java
@@ -66,7 +66,7 @@
 /**
  * @author hanl, margaretha
  * @date 29/01/2014
- *       update 04/2017
+ * @lastUpdate 04/2017
  */
 @Path(KustvaktServer.API_VERSION + "/")
 @ResourceFilters({ AuthFilter.class, DemoUserFilter.class, PiwikFilter.class })
@@ -310,13 +310,6 @@
         return Response.ok(result).build();
     }
 
-
-    @Deprecated
-    public Response postMatchFavorite () {
-        return Response.ok().build();
-    }
-
-
     // ref query parameter removed!
     @TRACE
     @Path("search")
@@ -330,17 +323,7 @@
             @QueryParam("page") Integer startPage,
             @QueryParam("cq") String cq) {
         TokenContext ctx = (TokenContext) securityContext.getUserPrincipal();
-        QuerySerializer ss;
-
-        // User user;
-        // try {
-        // user = controller.getUser(ctx.getUsername());
-        // }
-        // catch (KustvaktException e) {
-        // throw KustvaktResponseHandler.throwit(e);
-        // }
-
-        ss = new QuerySerializer().setQuery(q, ql, v);
+        QuerySerializer ss = new QuerySerializer().setQuery(q, ql, v);
         if (cq != null)
             ss.setCollection(cq);
 
@@ -362,10 +345,8 @@
 
     /**
      * currently only supports either no reference at all in which
-     * case all
-     * corpora are retrieved or a corpus name like "WPD". No virtual
-     * collections
-     * supported!
+     * case all corpora are retrieved or a corpus name like "WPD". 
+     * No virtual collections supported!
      * 
      * @param locale
      * @param q
@@ -381,14 +362,17 @@
     @TRACE
     @Path("{type}/{id}/search")
     public Response buildQueryWithId (@Context Locale locale,
-            @Context SecurityContext securityContext, @QueryParam("q") String q,
-            @QueryParam("ql") String ql, @QueryParam("v") String v,
+            @Context SecurityContext securityContext, 
+            @QueryParam("q") String q,
+            @QueryParam("ql") String ql, 
+            @QueryParam("v") String v,
             @QueryParam("context") String context,
             @QueryParam("cutoff") Boolean cutoff,
             @QueryParam("count") Integer pageLength,
             @QueryParam("offset") Integer pageIndex,
             @QueryParam("page") Integer startPage,
-            @PathParam("type") String type, @PathParam("id") String id) {
+            @PathParam("type") String type, 
+            @PathParam("id") String id) {
         TokenContext ctx = (TokenContext) securityContext.getUserPrincipal();
         type = StringUtils.normalize(type);
         id = StringUtils.decodeHTML(id);
diff --git a/src/main/java/de/ids_mannheim/korap/web/service/full/UserService.java b/src/main/java/de/ids_mannheim/korap/web/service/full/UserService.java
index 84cab21..74f3cf5 100644
--- a/src/main/java/de/ids_mannheim/korap/web/service/full/UserService.java
+++ b/src/main/java/de/ids_mannheim/korap/web/service/full/UserService.java
@@ -20,7 +20,6 @@
 import de.ids_mannheim.korap.web.filter.BlockingFilter;
 import de.ids_mannheim.korap.web.filter.DemoUserFilter;
 import de.ids_mannheim.korap.web.filter.PiwikFilter;
-import de.ids_mannheim.korap.web.utils.FormRequestWrapper;
 import de.ids_mannheim.korap.web.utils.KustvaktResponseHandler;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -30,8 +29,8 @@
 import java.util.*;
 
 /**
- * @author hanl
- * @date 29/01/2014
+ * @author hanl, margaretha
+ * @lastUpdate 04/2017
  */
 @Path(KustvaktServer.API_VERSION + "/user")
 @Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
@@ -51,6 +50,9 @@
 
 
     // fixme: json contains password in clear text. Encrypt request?
+    // EM: no encryption is needed for communications over https. 
+    // It should not be necessary in IDS internal network. 
+    
     // fixme: should also collect service exception, not just db exception!
     @POST
     @Path("register")
@@ -81,17 +83,18 @@
                     .queryParam(Attributes.QUERY_PARAM_USER,
                             user.getUsername());
             jlog.info("registration was successful for user '{}'",
-                    values.get(Attributes.USERNAME));
-            Map object = new HashMap();
+                    user.getUsername());
+            Map<String, Object> object = new HashMap<String, Object>();
             object.put("confirm_uri", uriBuilder.build());
             object.put("uri_expiration",
                     TimeUtils.format(uri.getUriExpiration()));
             return Response.ok(JsonUtils.toJSON(object)).build();
         }
         else {
-            // todo: return error or warning
+            jlog.error("Failed creating confirmation and expiry tokens.");
+            // EM: why illegal argument when uri fragment/param is self-generated 
             throw KustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT,
-                    "failed to validate uri paramter", "confirmation fragment");
+                    "failed to validate uri parameter", "confirmation fragment");
         }
 
     }
diff --git a/src/main/java/de/ids_mannheim/korap/web/utils/KustvaktResponseHandler.java b/src/main/java/de/ids_mannheim/korap/web/utils/KustvaktResponseHandler.java
index df5cd42..086336b 100644
--- a/src/main/java/de/ids_mannheim/korap/web/utils/KustvaktResponseHandler.java
+++ b/src/main/java/de/ids_mannheim/korap/web/utils/KustvaktResponseHandler.java
@@ -84,9 +84,9 @@
     private static Response.Status getStatus (int code) {
         Response.Status status = Response.Status.BAD_REQUEST;
         switch (code) {
-            case StatusCodes.NO_VALUE_FOUND:
-                status = Response.Status.NO_CONTENT;
-                break;
+//            case StatusCodes.NO_VALUE_FOUND:
+//                status = Response.Status.NO_CONTENT;
+//                break;
             case StatusCodes.ILLEGAL_ARGUMENT:
                 status = Response.Status.NOT_ACCEPTABLE;
                 break;
diff --git a/src/test/java/de/ids_mannheim/korap/config/TestHelper.java b/src/test/java/de/ids_mannheim/korap/config/TestHelper.java
index 1f4846d..73324ea 100644
--- a/src/test/java/de/ids_mannheim/korap/config/TestHelper.java
+++ b/src/test/java/de/ids_mannheim/korap/config/TestHelper.java
@@ -1,31 +1,9 @@
 package de.ids_mannheim.korap.config;
 
-import de.ids_mannheim.korap.exceptions.EmptyResultException;
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.handlers.*;
-import de.ids_mannheim.korap.interfaces.AuthenticationIface;
-import de.ids_mannheim.korap.interfaces.AuthenticationManagerIface;
-import de.ids_mannheim.korap.interfaces.EncryptionIface;
-import de.ids_mannheim.korap.interfaces.db.*;
-import de.ids_mannheim.korap.interfaces.defaults.KustvaktEncryption;
-import de.ids_mannheim.korap.resources.KustvaktResource;
-import de.ids_mannheim.korap.security.ac.PolicyDao;
-import de.ids_mannheim.korap.security.auth.*;
-import de.ids_mannheim.korap.user.User;
-import de.ids_mannheim.korap.utils.TimeUtils;
-import de.ids_mannheim.korap.web.service.BootableBeanInterface;
-import org.apache.commons.collections.map.HashedMap;
-import org.apache.commons.dbcp2.BasicDataSource;
-import org.flywaydb.core.Flyway;
-import org.joda.time.DateTime;
-import org.junit.Assert;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.annotation.Bean;
-import org.springframework.jdbc.core.RowCallbackHandler;
-import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
-import org.springframework.jdbc.datasource.SingleConnectionDataSource;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 
 import java.io.File;
 import java.io.IOException;
@@ -34,9 +12,56 @@
 import java.security.NoSuchAlgorithmException;
 import java.sql.ResultSet;
 import java.sql.SQLException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
-import static org.junit.Assert.*;
+import org.apache.commons.dbcp2.BasicDataSource;
+import org.flywaydb.core.Flyway;
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.jdbc.core.RowCallbackHandler;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
+import org.springframework.jdbc.datasource.SingleConnectionDataSource;
+
+import de.ids_mannheim.korap.exceptions.EmptyResultException;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.handlers.AdminDao;
+import de.ids_mannheim.korap.handlers.DocumentDao;
+import de.ids_mannheim.korap.handlers.EntityDao;
+import de.ids_mannheim.korap.handlers.JDBCAuditing;
+import de.ids_mannheim.korap.handlers.JDBCClient;
+import de.ids_mannheim.korap.handlers.ResourceDao;
+import de.ids_mannheim.korap.handlers.UserDetailsDao;
+import de.ids_mannheim.korap.handlers.UserSettingsDao;
+import de.ids_mannheim.korap.interfaces.AuthenticationIface;
+import de.ids_mannheim.korap.interfaces.AuthenticationManagerIface;
+import de.ids_mannheim.korap.interfaces.EncryptionIface;
+import de.ids_mannheim.korap.interfaces.db.AdminHandlerIface;
+import de.ids_mannheim.korap.interfaces.db.AuditingIface;
+import de.ids_mannheim.korap.interfaces.db.EntityHandlerIface;
+import de.ids_mannheim.korap.interfaces.db.PersistenceClient;
+import de.ids_mannheim.korap.interfaces.db.PolicyHandlerIface;
+import de.ids_mannheim.korap.interfaces.db.ResourceOperationIface;
+import de.ids_mannheim.korap.interfaces.db.UserDataDbIface;
+import de.ids_mannheim.korap.interfaces.defaults.KustvaktEncryption;
+import de.ids_mannheim.korap.resources.KustvaktResource;
+import de.ids_mannheim.korap.security.ac.PolicyDao;
+import de.ids_mannheim.korap.security.auth.APIAuthentication;
+import de.ids_mannheim.korap.security.auth.BasicHttpAuth;
+import de.ids_mannheim.korap.security.auth.KustvaktAuthenticationManager;
+import de.ids_mannheim.korap.security.auth.OpenIDconnectAuthentication;
+import de.ids_mannheim.korap.security.auth.SessionAuthentication;
+import de.ids_mannheim.korap.user.User;
+import de.ids_mannheim.korap.utils.TimeUtils;
+import de.ids_mannheim.korap.web.service.BootableBeanInterface;
 
 /**
  * creates a test user that can be used to access protected functions
@@ -46,6 +71,7 @@
  */
 public class TestHelper {
 
+    private static String mainConfigurationFile = "kustvakt-test.conf";
     private static Logger jlog = LoggerFactory.getLogger(TestHelper.class);
     private static final Map<String, Object> data = new HashMap<>();
     static  {
@@ -424,7 +450,7 @@
         @Override
         public KustvaktConfiguration getConfig () {
             KustvaktConfiguration c = new KustvaktConfiguration();
-            InputStream s = ConfigLoader.loadConfigStream("kustvakt.conf");
+            InputStream s = ConfigLoader.loadConfigStream(mainConfigurationFile);
             if (s != null)
                 c.setPropertiesAsStream(s);
             else {
diff --git a/src/test/java/de/ids_mannheim/korap/web/service/full/QuerySerializationServiceTest.java b/src/test/java/de/ids_mannheim/korap/web/service/full/QuerySerializationServiceTest.java
new file mode 100644
index 0000000..ebd094d
--- /dev/null
+++ b/src/test/java/de/ids_mannheim/korap/web/service/full/QuerySerializationServiceTest.java
@@ -0,0 +1,252 @@
+package de.ids_mannheim.korap.web.service.full;
+/**
+ * @author hanl, margaretha
+ * @lastUpdate 19/04/2017
+ *
+ */
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Iterator;
+
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.sun.jersey.api.client.ClientResponse;
+
+import de.ids_mannheim.korap.config.Attributes;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.security.auth.BasicHttpAuth;
+import de.ids_mannheim.korap.utils.JsonUtils;
+import de.ids_mannheim.korap.web.service.FastJerseyTest;
+
+public class QuerySerializationServiceTest extends FastJerseyTest {
+
+    @Override
+    public void initMethod () throws KustvaktException {
+        helper().runBootInterfaces();
+    }
+
+
+    @BeforeClass
+    public static void configure () throws Exception {
+        FastJerseyTest.setPackages("de.ids_mannheim.korap.web.service.full",
+                "de.ids_mannheim.korap.web.filter",
+                "de.ids_mannheim.korap.web.utils");
+    }
+    
+    @Test
+    public void testQuerySerializationFilteredPublic () {
+        ClientResponse response = resource()
+                .path(getAPIVersion())
+                .path("corpus/WPD15/search")
+                .queryParam("q", "[orth=der]")
+                .queryParam("ql", "poliqarp")
+                .queryParam("context", "base/s:s")
+                .method("TRACE", ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertEquals("corpusSigle", node.at("/collection/key").asText());
+        assertEquals("WPD15", node.at("/collection/value").asText());
+    }
+    
+    
+
+    @Test
+    public void testQuerySerializationUnexistingResource () {
+        ClientResponse response = resource()
+                .path(getAPIVersion())
+                .path("corpus/ZUW19/search")
+                .queryParam("q", "[orth=der]")
+                .queryParam("ql", "poliqarp")
+                .queryParam("context", "base/s:s")
+                .method("TRACE", ClientResponse.class);
+        assertEquals(ClientResponse.Status.BAD_REQUEST.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertEquals(101, node.at("/errors/0/0").asInt());
+        assertEquals("[Cannot found public resources with ids: [ZUW19]]",
+                node.at("/errors/0/2").asText());
+    }
+    
+    @Test
+    public void testQuerySerializationWithNonPublicCorpus () {
+        ClientResponse response = resource()
+                .path(getAPIVersion())
+                .path("corpus/BRZ10/search")
+                .queryParam("q", "[orth=der]")
+                .queryParam("ql", "poliqarp")
+                .queryParam("context", "base/s:s")
+                .method("TRACE", ClientResponse.class);
+        assertEquals(ClientResponse.Status.BAD_REQUEST.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertEquals(101, node.at("/errors/0/0").asInt());
+        assertEquals("[Cannot found public resources with ids: [BRZ10]]",
+                node.at("/errors/0/2").asText());
+    }
+
+    @Test
+    public void testQuerySerializationWithAuthentication () {
+        ClientResponse response = resource()
+                .path(getAPIVersion())
+                .path("corpus/BRZ10/search")
+                .queryParam("q", "[orth=der]")
+                .queryParam("ql", "poliqarp")
+                .header(Attributes.AUTHORIZATION,
+                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
+                .method("TRACE", ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertEquals("koral:doc", node.at("/collection/@type").asText());
+        assertEquals("corpusSigle", node.at("/collection/key").asText());
+        assertEquals("BRZ10", node.at("/collection/value").asText());
+    }
+
+    @Test
+    public void testQuerySerializationWithNewCollection () {
+        // Add Virtual Collection
+        ClientResponse response = resource()
+                .path(getAPIVersion())
+                .path("virtualcollection")
+                .queryParam("filter", "false")
+                .queryParam("name", "Weimarer Werke")
+                .queryParam("description", "Goethe-Werke in Weimar (seit 1775)")
+                .header(Attributes.AUTHORIZATION,
+                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
+                .post(ClientResponse.class, "creationDate since 1775 & corpusSigle=GOE");
+        
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        
+        String ent = response.getEntity(String.class);
+        
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertTrue(node.isObject());
+        assertEquals("Weimarer Werke", node.path("name").asText());
+
+        // Get virtual collections
+        response = resource()
+                .path(getAPIVersion())
+                .path("collection")
+                .header(Attributes.AUTHORIZATION,
+                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        ent = response.getEntity(String.class);
+        node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+
+        Iterator<JsonNode> it = node.elements();
+        String id = null;
+        while (it.hasNext()) {
+            JsonNode next = (JsonNode) it.next();
+            if ("Weimarer Werke".equals(next.path("name").asText()))
+                id = next.path("id").asText();
+        }
+        assertNotNull(id);
+        assertFalse(id.isEmpty());
+
+        // query serialization service
+        response = resource()
+                .path(getAPIVersion())
+                .path("collection")
+                .path(id)
+                .path("search")
+                .queryParam("q", "[orth=der]")
+                .queryParam("ql", "poliqarp")
+                .queryParam("context", "base/s:s")
+                .header(Attributes.AUTHORIZATION,
+                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
+                .method("TRACE", ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        ent = response.getEntity(String.class);
+        node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+
+        assertEquals("koral:docGroup", node.at("/collection/@type").asText());
+        assertEquals("koral:doc", node.at("/collection/operands/0/@type")
+                .asText());
+        assertEquals("creationDate", node.at("/collection/operands/0/key")
+                .asText());
+        assertEquals("1775", node.at("/collection/operands/0/value")
+                .asText());
+        assertEquals("type:date", node.at("/collection/operands/0/type")
+                .asText());
+        assertEquals("match:geq", node.at("/collection/operands/0/match")
+                .asText());
+        
+        assertEquals("koral:doc", node.at("/collection/operands/1/@type")
+                .asText());
+        assertEquals("corpusSigle", node.at("/collection/operands/1/key")
+                .asText());
+        assertEquals("GOE", node.at("/collection/operands/1/value")
+                .asText());
+        assertEquals("match:eq", node.at("/collection/operands/1/match")
+                .asText());
+    }
+    
+    @Test
+    public void testQuerySerializationOfVirtualCollection () {
+        ClientResponse response = resource()
+                .path(getAPIVersion())
+                .path("collection/WPD15-VC/search")
+                .queryParam("q", "[orth=der]")
+                .queryParam("ql", "poliqarp")
+                .queryParam("context", "base/s:s")
+                .method("TRACE", ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertEquals("koral:doc", node.at("/collection/operands/0/@type")
+                .asText());
+        assertEquals("corpusSigle", node.at("/collection/operands/0/key").asText());
+        assertEquals("WPD15", node.at("/collection/operands/0/value").asText());
+        assertEquals("koral:doc", node.at("/collection/operands/1/@type")
+                .asText());
+        assertEquals("creationDate", node.at("/collection/operands/1/key").asText());
+        assertEquals("2014-04-01", node.at("/collection/operands/1/value").asText());
+
+    }
+    
+    @Test
+    public void testMetaQuerySerialization () {
+        ClientResponse response = resource()
+                .path(getAPIVersion())
+                .path("search")
+                .queryParam("context", "sentence")
+                .queryParam("count", "20")
+                .queryParam("page", "5")
+                .queryParam("q", "[pos=ADJA]")
+                .queryParam("ql", "poliqarp")
+                .method("TRACE", ClientResponse.class);
+        assertEquals(response.getStatus(),
+                ClientResponse.Status.OK.getStatusCode());
+        
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        
+        assertEquals("sentence", node.at("/meta/context").asText());
+        assertEquals(20, node.at("/meta/count").asInt());
+        assertEquals(5, node.at("/meta/startPage").asInt());
+    }
+
+
+}
diff --git a/src/test/java/de/ids_mannheim/korap/web/service/full/ResourceInfoTest.java b/src/test/java/de/ids_mannheim/korap/web/service/full/ResourceInfoTest.java
new file mode 100644
index 0000000..f7aaaaf
--- /dev/null
+++ b/src/test/java/de/ids_mannheim/korap/web/service/full/ResourceInfoTest.java
@@ -0,0 +1,188 @@
+package de.ids_mannheim.korap.web.service.full;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.sun.jersey.api.client.ClientResponse;
+
+import de.ids_mannheim.korap.config.Attributes;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.security.auth.BasicHttpAuth;
+import de.ids_mannheim.korap.utils.JsonUtils;
+import de.ids_mannheim.korap.web.service.FastJerseyTest;
+/**
+ * @author hanl, margaretha
+ * @lastUpdate 19/04/2017
+ *
+ */
+public class ResourceInfoTest extends FastJerseyTest {
+
+    @Override
+    public void initMethod () throws KustvaktException {
+        helper().runBootInterfaces();
+    }
+
+
+    @BeforeClass
+    public static void configure () throws Exception {
+        FastJerseyTest.setPackages("de.ids_mannheim.korap.web.service.full",
+                "de.ids_mannheim.korap.web.filter",
+                "de.ids_mannheim.korap.web.utils");
+    }
+
+
+    @Test
+    public void testGetPublicVirtualCollections () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("collection").get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+
+        JsonNode node = JsonUtils.readTree(response.getEntity(String.class));
+        assertNotNull(node);
+        assertEquals(1, node.size());
+    }
+
+
+    @Test
+    public void testGetVirtualCollectionsWithAuthentication () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("collection")
+                .header(Attributes.AUTHORIZATION,
+                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+
+        JsonNode node = JsonUtils.readTree(response.getEntity(String.class));
+        assertNotNull(node);
+        assertTrue(node.isArray());
+        assertEquals(2, node.size());
+    }
+
+
+    @Test
+    public void testGetVirtualCollectionById () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("collection").path("WPD15-VC").get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertNotEquals(0, node.size());
+        assertEquals("Wikipedia Virtual Collection",
+                node.path("name").asText());
+        assertEquals("German Wikipedia 2015",
+                node.path("description").asText());
+    }
+
+
+    @Test
+    public void testGetPublicCorpora () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("corpus").get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertTrue(node.isArray());
+        assertEquals(2, node.size());
+    }
+
+
+    @Test
+    public void testGetCorpusById () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("corpus").path("WPD15").get(ClientResponse.class);
+        String ent = response.getEntity(String.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertTrue(node.isObject());
+        assertEquals("WPD15", node.path("id").asText());
+    }
+
+
+    @Test
+    public void testGetCorpusById2 () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("corpus").path("GOE").get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertTrue(node.isObject());
+        assertEquals("GOE", node.path("id").asText());
+    }
+
+
+    @Test
+    public void testGetPublicFoundries () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("foundry").get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertTrue(node.isArray());
+        assertEquals(10, node.size());
+    }
+
+
+    @Test
+    public void testGetFoundryById () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("foundry").path("tt").get(ClientResponse.class);
+        String ent = response.getEntity(String.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertNotEquals(0, node.size());
+    }
+
+
+    @Test
+    public void testGetUnexistingCorpus () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("corpus").path("ZUW19").get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.BAD_REQUEST.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode error = JsonUtils.readTree(ent).get("errors").get(0);
+        assertEquals(101, error.get(0).asInt());
+        assertEquals("[Cannot found public resources with ids: [ZUW19]]",
+                error.get(2).asText());
+    }
+
+
+    // EM: queries for an unauthorized corpus get the same responses / treatment as 
+    // asking for an unexisting corpus. Does it need a specific exception instead?
+    @Test
+    public void testGetUnauthorizedCorpus () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("corpus").path("BRZ10").get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.BAD_REQUEST.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode error = JsonUtils.readTree(ent).get("errors").get(0);
+        assertEquals(101, error.get(0).asInt());
+        assertEquals("[Cannot found public resources with ids: [BRZ10]]",
+                error.get(2).asText());
+    }
+
+
+}
diff --git a/src/test/java/de/ids_mannheim/korap/web/service/full/ResourceServiceTest.java b/src/test/java/de/ids_mannheim/korap/web/service/full/ResourceServiceTest.java
index 544c790..cb642da 100644
--- a/src/test/java/de/ids_mannheim/korap/web/service/full/ResourceServiceTest.java
+++ b/src/test/java/de/ids_mannheim/korap/web/service/full/ResourceServiceTest.java
@@ -42,181 +42,8 @@
         FastJerseyTest.setPackages("de.ids_mannheim.korap.web.service.full",
                 "de.ids_mannheim.korap.web.filter",
                 "de.ids_mannheim.korap.web.utils");
-        
-        //containerURI = "https://localhost/";
     }
 
-
-    @Test
-    public void testSearchSimpleAuthorized () {
-        ClientResponse response = resource()
-                .path(getAPIVersion())
-                .path("search")
-                .queryParam("q", "[orth=die]")
-                .queryParam("ql", "poliqarp")
-                .header(Attributes.AUTHORIZATION,
-                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
-                .get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-
-        JsonNode node = JsonUtils.readTree(response.getEntity(String.class));
-        assertNotNull(node);
-        assertNotEquals(0, node.path("matches").size());
-    }
-
-
-    @Test
-    public void testSearchSimpleWithCQAuthorized () {
-        ClientResponse response = resource()
-                .path(getAPIVersion())
-                .path("search")
-                .queryParam("q", "[orth=das]")
-                .queryParam("ql", "poliqarp")
-                .queryParam("cq", "textClass=politik & corpusSigle=WPD")
-                .header(Attributes.AUTHORIZATION,
-                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
-                .get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-
-        JsonNode node = JsonUtils.readTree(response.getEntity(String.class));
-        assertNotNull(node);
-        assertEquals(2, node.at("/collection/operands").size());
-        assertEquals("textClass", node.at("/collection/operands/0/key")
-                .asText());
-        assertEquals("corpusSigle", node.at("/collection/operands/1/key")
-                .asText());
-        assertEquals("koral:token", node.at("/query/@type").asText());
-    }
-
-
-    @Test
-    public void testSearchSimpleDemo () {
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("search").queryParam("q", "[orth=der]")
-                .queryParam("ql", "poliqarp").get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String ent = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertNotEquals(0, node.path("matches").size());
-    }
-
-
-    @Test
-    public void testSearchSentenceMeta () {
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("search").queryParam("q", "[orth=der]")
-                .queryParam("ql", "poliqarp").queryParam("context", "sentence")
-                .get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String ent = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertNotEquals(0, node.path("matches").size());
-        assertEquals("base/s:s", node.at("/meta/context").asText());
-        assertNotEquals("${project.version}", "/meta/version");
-    }
-
-
-    @Test
-    public void testSearchSimpleCQL () {
-        QuerySerializer s = new QuerySerializer();
-        s.setQuery("(der) or (das)", "CQL");
-
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("search").post(ClientResponse.class, s.toJSON());
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String ent = response.getEntity(String.class);
-
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertNotEquals(0, node.path("matches").size());
-    }
-
-
-    @Test
-    public void testSearchRawQuery () {
-        QuerySerializer s = new QuerySerializer();
-        s.setQuery("[orth=der]", "poliqarp");
-        //        s.setCollection("corpusSigle=WPD");
-
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("search").post(ClientResponse.class, s.toJSON());
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String ent = response.getEntity(String.class);
-
-
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertNotEquals(0, node.path("matches").size());
-    }
-
-
-    @Test
-    public void testCollectionsGetPublic () {
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("collection").get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-
-        JsonNode node = JsonUtils.readTree(response.getEntity(String.class));
-        assertNotNull(node);
-        assertNotEquals(0, node.size());
-    }
-
-
-    @Test
-    public void testCollectionsGet () {
-        ClientResponse response = resource()
-                .path(getAPIVersion())
-                .path("collection")
-                .header(Attributes.AUTHORIZATION,
-                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
-                .get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-
-        JsonNode node = JsonUtils.readTree(response.getEntity(String.class));
-        assertNotNull(node);
-        assertTrue(node.isArray());
-        assertNotEquals(0, node.size());
-    }
-
-
-    @Test
-    public void testCorporaGet () {
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("corpus").get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String ent = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertTrue(node.isArray());
-        assertNotEquals(0, node.size());
-    }
-
-
-    @Test
-    public void testFoundriesGet () {
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("foundry").get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String ent = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertTrue(node.isArray());
-        assertNotEquals(0, node.size());
-    }
-
-
     // create a simple test collection for user kustvakt, otherwise test fails
     @Test
     @Ignore
@@ -254,23 +81,14 @@
         assertTrue(docs < 15);
     }
 
+    
 
-    // todo:
+    // EM: The test covers multiple operations because it deals with 
+    // the same resource and needs an order to operate (store followed by
+    // update followed by delete).
     @Test
-    @Ignore
-    public void testCollecionGet () {
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("collection").path("id").get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String ent = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertNotEquals(0, node.size());
-    }
-
-    @Test
-    public void testResourceStore() throws KustvaktException, JsonProcessingException, IOException {
+    public void testVirtualCollectionStoreUpdateDelete() throws KustvaktException, 
+        JsonProcessingException, IOException {
     	// resource store service
         ClientResponse response = resource()
                 .path(getAPIVersion())
@@ -307,7 +125,7 @@
         assertNotNull(res);
         Assert.assertEquals("Goethe",res.getName().toString());
         
-//         no update resource service
+        // no update resource service
         response = resource()
                 .path(getAPIVersion())
                 .path("virtualcollection")
@@ -366,206 +184,7 @@
     }
 
 
-    @Test
-    public void testCorpusGet () {
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("corpus").path("WPD15").get(ClientResponse.class);
-        String ent = response.getEntity(String.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertTrue(node.isObject());
-        assertEquals("WPD15", node.path("id").asText());
-    }
-
-    @Test
-    public void testCorpusGet2 () {
-    	ClientResponse response = resource().path(getAPIVersion())
-                .path("corpus").path("GOE").get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String ent = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertTrue(node.isObject());
-        assertEquals("GOE", node.path("id").asText());
-    }
     
-    
-    @Test
-    @Ignore
-    public void testCorpusGetUnauthorized () {
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("corpus").path("BRZ20").get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.UNAUTHORIZED.getStatusCode(),
-                response.getStatus());
-        String ent = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertTrue(node.isObject());
-        assertNotNull(node);
-    }
-
-    @Test
-    public void testFoundryGet () {
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("foundry").path("tt").get(ClientResponse.class);
-        String ent = response.getEntity(String.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertNotEquals(0, node.size());
-    }
-
-
-    
-
-    @Test
-    public void testSerializationQueryWithCorpusThroughFilteredPublic () {
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("corpus/WPD15/search").queryParam("q", "[orth=der]")
-                .queryParam("ql", "poliqarp").queryParam("context", "base/s:s")
-                .method("TRACE", ClientResponse.class);
-        String ent = response.getEntity(String.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        //String ent = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertEquals("corpusSigle", node.at("/collection/key").asText());
-        assertEquals("WPD15", node.at("/collection/value").asText());
-    }
-
-
-    @Test
-    public void testSerializationQueryWithCorpus () {
-        ClientResponse response = resource()
-                .path(getAPIVersion())
-                .path("corpus/WPD15/search")
-                .queryParam("q", "[orth=der]")
-                .queryParam("ql", "poliqarp")
-                .header(Attributes.AUTHORIZATION,
-                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
-                .method("TRACE", ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String ent = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertEquals("koral:doc", node.at("/collection/@type").asText());
-        assertEquals("corpusSigle", node.at("/collection/key").asText());
-    }
-
-    @Test
-    public void testSerializationQueryWithCollection () {
-    	// Add Virtual Collection
-    	ClientResponse response = resource()
-                .path(getAPIVersion())
-                .path("virtualcollection")
-                .queryParam("filter", "false")
-                .queryParam("name", "Weimarer Werke")
-                .queryParam("description", "Goethe-Werke in Weimar (seit 1775)")
-                .header(Attributes.AUTHORIZATION,
-                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
-                .post(ClientResponse.class, "creationDate since 1775 & corpusSigle=GOE");
-        
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        
-        String ent = response.getEntity(String.class);
-        
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertTrue(node.isObject());
-        assertEquals("Weimarer Werke", node.path("name").asText());
-
-        // Get virtual collections
-        response = resource()
-                .path(getAPIVersion())
-                .path("collection")
-                .header(Attributes.AUTHORIZATION,
-                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
-                .get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        ent = response.getEntity(String.class);
-        node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-
-        Iterator it = node.elements();
-        String id = null;
-        while (it.hasNext()) {
-            JsonNode next = (JsonNode) it.next();
-            if ("Weimarer Werke".equals(next.path("name").asText()))
-                id = next.path("id").asText();
-        }
-        assertNotNull(id);
-        assertFalse(id.isEmpty());
-
-        response = resource()
-                .path(getAPIVersion())
-                .path("collection")
-                .path(id)
-                .path("search")
-                .queryParam("q", "[orth=der]")
-                .queryParam("ql", "poliqarp")
-                .queryParam("context", "base/s:s")
-                .header(Attributes.AUTHORIZATION,
-                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
-                .method("TRACE", ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        ent = response.getEntity(String.class);
-        node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-
-        assertEquals("koral:docGroup", node.at("/collection/@type").asText());
-        assertEquals("koral:doc", node.at("/collection/operands/0/@type")
-                .asText());
-        assertEquals("koral:doc", node.at("/collection/operands/1/@type")
-                .asText());
-        assertEquals("creationDate", node.at("/collection/operands/0/key")
-                .asText());
-        assertEquals("corpusSigle", node.at("/collection/operands/1/key")
-                .asText());
-
-    }
-
-
-    @Test
-    public void testSearchQueryPublicCorpora () {
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("search").queryParam("q", "[orth=der]")
-                .queryParam("ql", "poliqarp").get(ClientResponse.class);
-        assertEquals(response.getStatus(),
-                ClientResponse.Status.OK.getStatusCode());
-        String ent = response.getEntity(String.class);
-		JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertEquals("koral:docGroup", node.at("/collection/@type").asText());
-        assertEquals("operation:or", node.at("/collection/operation").asText());
-        assertNotEquals(0, node.at("/collection/operands").size());
-    }
-
-
-    // use trace for this
-    @Test
-    @Ignore
-    public void testSerializationMeta () {
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("search").queryParam("context", "sentence")
-                .queryParam("q", "[pos=ADJA]").queryParam("ql", "poliqarp")
-
-                .method("TRACE", ClientResponse.class);
-        assertEquals(response.getStatus(),
-                ClientResponse.Status.OK.getStatusCode());
-    }
-
-
     @Test
     public void testMatchInfoGet () {
     }
diff --git a/src/test/java/de/ids_mannheim/korap/web/service/full/SearchServiceTest.java b/src/test/java/de/ids_mannheim/korap/web/service/full/SearchServiceTest.java
new file mode 100644
index 0000000..e77647a
--- /dev/null
+++ b/src/test/java/de/ids_mannheim/korap/web/service/full/SearchServiceTest.java
@@ -0,0 +1,172 @@
+package de.ids_mannheim.korap.web.service.full;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.sun.jersey.api.client.ClientResponse;
+
+import de.ids_mannheim.korap.config.Attributes;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.query.serialize.QuerySerializer;
+import de.ids_mannheim.korap.security.auth.BasicHttpAuth;
+import de.ids_mannheim.korap.utils.JsonUtils;
+import de.ids_mannheim.korap.web.service.FastJerseyTest;
+
+/**
+ * @author hanl, margaretha
+ * @lastUpdate 19/04/2017
+ *
+ */
+public class SearchServiceTest extends FastJerseyTest {
+
+    @Override
+    public void initMethod () throws KustvaktException {
+        helper().runBootInterfaces();
+    }
+
+
+    @BeforeClass
+    public static void configure () throws Exception {
+        FastJerseyTest.setPackages("de.ids_mannheim.korap.web.service.full",
+                "de.ids_mannheim.korap.web.filter",
+                "de.ids_mannheim.korap.web.utils");
+    }
+
+
+    @Test
+    public void testSearchQueryPublicCorpora () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("search").queryParam("q", "[orth=der]")
+                .queryParam("ql", "poliqarp").get(ClientResponse.class);
+        assertEquals(response.getStatus(),
+                ClientResponse.Status.OK.getStatusCode());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertEquals("koral:docGroup", node.at("/collection/@type").asText());
+        assertEquals("operation:or", node.at("/collection/operation").asText());
+        assertNotEquals(0, node.at("/collection/operands").size());
+        assertEquals("corpusSigle([GOE, WPD15])",
+                node.at("/collection/rewrites/0/scope").asText());
+    }
+
+
+    @Test
+    public void testSearchSimpleAuthorized () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("search").queryParam("q", "[orth=die]")
+                .queryParam("ql", "poliqarp")
+                .header(Attributes.AUTHORIZATION,
+                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+
+        JsonNode node = JsonUtils.readTree(response.getEntity(String.class));
+        assertNotNull(node);
+        assertNotEquals(0, node.path("matches").size());
+        assertEquals("corpusSigle([BRZ10, GOE, WPD15])",
+                node.at("/collection/rewrites/0/scope").asText());
+    }
+
+
+    @Test
+    public void testSearchSimpleWithCQAuthorized () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("search").queryParam("q", "[orth=das]")
+                .queryParam("ql", "poliqarp")
+                .queryParam("cq", "textClass=politik & corpusSigle=BRZ10")
+                .header(Attributes.AUTHORIZATION,
+                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+
+        JsonNode node = JsonUtils.readTree(response.getEntity(String.class));
+        assertNotNull(node);
+        assertEquals(2, node.at("/collection/operands").size());
+        assertEquals("textClass",
+                node.at("/collection/operands/0/key").asText());
+        assertEquals("corpusSigle",
+                node.at("/collection/operands/1/key").asText());
+        assertEquals("koral:token", node.at("/query/@type").asText());
+    }
+
+
+    @Test
+    public void testSearchSimpleDemo () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("search").queryParam("q", "[orth=der]")
+                .queryParam("ql", "poliqarp").get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertNotEquals(0, node.path("matches").size());
+        assertEquals("corpusSigle([GOE, WPD15])",
+                node.at("/collection/rewrites/0/scope").asText());
+    }
+
+
+
+    @Test
+    public void testSearchSentenceMeta () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("search").queryParam("q", "[orth=der]")
+                .queryParam("ql", "poliqarp").queryParam("context", "sentence")
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertNotEquals(0, node.path("matches").size());
+        assertEquals("base/s:s", node.at("/meta/context").asText());
+        assertNotEquals("${project.version}", "/meta/version");
+    }
+
+
+    @Test
+    public void testSearchSimpleCQL () {
+        QuerySerializer s = new QuerySerializer();
+        s.setQuery("(der) or (das)", "CQL");
+
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("search").post(ClientResponse.class, s.toJSON());
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertNotEquals(0, node.path("matches").size());
+        assertEquals(17027, node.at("/meta/totalResults").asInt());
+    }
+
+
+    @Test
+    public void testSearchRawQuery () {
+        QuerySerializer s = new QuerySerializer();
+        s.setQuery("[orth=der]", "poliqarp");
+        s.setCollection("corpusSigle=GOE");
+
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("search").post(ClientResponse.class, s.toJSON());
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+
+
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertNotEquals(0, node.path("matches").size());
+        assertEquals(10993, node.at("/meta/totalResults").asInt());
+    }
+
+}
diff --git a/src/test/resources/policy-test.conf b/src/test/resources/policy-test.conf
new file mode 100644
index 0000000..4156a76
--- /dev/null
+++ b/src/test/resources/policy-test.conf
@@ -0,0 +1,57 @@
+# type	id	name	description	condition	permissions	collectionQuery
+
+virtualcollection	WPD15-VC	Wikipedia Virtual Collection	German Wikipedia 2015	public	read	corpusSigle=WPD15 & creationDate since 2014-04-01	
+virtualcollection	BRZ10-PC	Braunschweiger Collection	Selected Braunschweiger Zeitung	ids	read	corpusSigle=BRZ10 & foundries ~ Connexor
+corpus	WPD15	Wikipedia	German Wikipedia 2015	public	read
+corpus	GOE	Goethe	Goethe corpus	public	read
+corpus	BRZ10	Braunschweiger	Braunschweiger Zeitung 2010	ids	read
+type	id	name	description	condition	permissions
+foundry	base	base	Base foundry	public	read
+foundry	dereko	dereko	DeReKo foundry	public	read
+foundry	corenlp	corenlp	CoreNLP parser	public	read
+foundry	opennlp	opennlp	OpenNLP parser	public	read
+foundry	malt	malt	MALT parser	public	read
+foundry	mdp	mdp	MD parser	public	read
+foundry	tt	tt	Tree Tagger parser	public	read
+foundry	sgbr	sgbr	Schreibgebrauch	ids	read
+foundry	cnx	cnx	Connexor parser	ids	read
+foundry	drukola	drukola	DruKoLa parser	drukola	read
+foundry	glemm	glemm	Glemm	public	read
+foundry	marmot	marmot	MarMoT parser	public	read
+foundry	mate	mate	Mate parser	public	read
+foundry	xip	xip	Xerox Incremental Parser	ids	read
+layer	cnx/c	cnx/c	Connexor constituency layer	ids	read
+layer	cnx/syn	cnx/syn	Connexor syntax	ids	read
+layer	cnx/p	cnx/p	Connexor part of speech	ids	read
+layer	cnx/l	cnx/l	Connexor lemma	ids	read
+layer	cnx/m	cnx/m	Connexor morphology	ids	read
+layer	corenlp/c	corenlp/c	CoreNLP constituency	public	read
+layer	corenlp/p	corenlp/p	CoreNLP part of speech	public	read
+layer	corenlp/s	corenlp/s	CoreNLP structure	public	read
+layer	corenlp/ne	corenlp/ne	CoreNLP named entities	public	read
+layer	dereko/s	dereko/s	DeReKo structure	public	read
+layer	drukola/l	drukola/l	Drukola lemma	drukola	read
+layer	drukola/p	drukola/p	Drukola part of speech	drukola	read
+layer	drukola/m	drukola/m	Drukola morphology	drukola	read
+layer	glemm/l	glemm/l	GLEMM lemma	public	read
+layer	malt/d	malt/d	MALT dependency	public	read
+layer	marmot/p	marmot/p	Marmot part of speech	public	read
+layer	marmot/m	marmot/m	Marmot morphology	public	read
+layer	mate/d	mate/d	MATE dependency	public	read
+layer	mate/l	mate/l	MATE lemma	public	read
+layer	mate/p	mate/p	MATE part of speech	public	read
+layer	mate/m	mate/m	MATE morphology	public	read
+layer	mdp/d	mdp/d	MDP dependency	public	read
+layer	opennlp/p	opennlp/p	OpenNLP part of speech	public	read
+layer	opennlp/s	opennlp/s	OpenNLP part of speech	public	read
+layer	sgbr/p	sgbr/p	Schreibgebrauchp part of peech	ids	read
+layer	sgbr/l	sgbr/l	Schreibgebrauch lemma	ids	read
+layer	sgbr/lv	sgbr/lv	Schreibgebrauch lemmav ariant	ids	read
+layer	tt/p	tt/p	Tree Tagger part of speech	public	read
+layer	tt/l	tt/l	Tree Tagger lemma	public	read
+layer	tt/s	tt/s	Tree Tagger structure	public	read
+layer	xip/c	xip/c	XIP constituency	ids	read
+layer	xip/d	xip/d	XIP dependency	ids	read
+layer	xip/l	xip/l	XIP lemma	ids	read
+layer	xip/p	xip/p	XIP part of speech	ids	read
+layer	xip/s	xip/s	XIP structure	ids	read
diff --git a/src/test/resources/test-default-config.xml b/src/test/resources/test-default-config.xml
index 48e97a8..19f7e89 100644
--- a/src/test/resources/test-default-config.xml
+++ b/src/test/resources/test-default-config.xml
@@ -23,8 +23,8 @@
 		<property name="ignoreResourceNotFound" value="true" />
 		<property name="locations">
 			<array>
-				<value>classpath:kustvakt.conf</value>
-				<value>file:./kustvakt.conf</value>
+				<value>classpath:kustvakt-test.conf</value>
+				<value>file:./kustvakt-test.conf</value>
 			</array>
 		</property>
 	</bean>