diff --git a/pom.xml b/pom.xml
index 21c69dd..85e0e3b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -500,6 +500,16 @@
             </exclusions>
         </dependency>
         -->
+        <dependency>
+        	<groupId>org.apache.httpcomponents</groupId>
+        	<artifactId>httpclient</artifactId>
+        	<version>4.3.3</version>
+        </dependency>
+        <dependency>
+        	<groupId>commons-io</groupId>
+        	<artifactId>commons-io</artifactId>
+        	<version>2.4</version>
+        </dependency>
     </dependencies>
 
 </project>
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 21ceaa7..1966e93 100644
--- a/src/main/java/de/ids_mannheim/korap/resources/ResourceFactory.java
+++ b/src/main/java/de/ids_mannheim/korap/resources/ResourceFactory.java
@@ -2,6 +2,8 @@
 
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
+import de.ids_mannheim.korap.utils.JsonUtils;
+
 import org.apache.commons.codec.digest.DigestUtils;
 
 import java.util.ArrayList;
@@ -65,9 +67,9 @@
 
 
     public static <T extends KustvaktResource> T createID (T resource) {
-        if (resource.getData() != null && !resource.getStringData().isEmpty())
-            resource.setPersistentID(DigestUtils.sha1Hex(resource
-                    .getStringData()));
+        if (resource.getData() != null && !resource.getStringData().isEmpty()){
+        	resource.setPersistentID(DigestUtils.sha1Hex(JsonUtils.toJSON(resource)));        	
+        }
         return resource;
     }
 
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 0db2b48..cb0279c 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
@@ -42,1103 +42,970 @@
  * @date 29/01/2014
  */
 @Path(KustvaktServer.API_VERSION + "/")
-@ResourceFilters({ AuthFilter.class, DemoUserFilter.class, PiwikFilter.class})
+@ResourceFilters({ AuthFilter.class, DemoUserFilter.class, PiwikFilter.class })
 @Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
 public class ResourceService {
 
-    private static Logger jlog = LoggerFactory.getLogger(ResourceService.class);
+	private static Logger jlog = LoggerFactory.getLogger(ResourceService.class);
 
-    private SearchKrill searchKrill;
-    private ResourceHandler resourceHandler;
-    private AuthenticationManagerIface controller;
-    private ClientsHandler graphDBhandler;
-    private KustvaktConfiguration config;
-    private RewriteHandler processor;
+	private SearchKrill searchKrill;
+	private ResourceHandler resourceHandler;
+	private AuthenticationManagerIface controller;
+	private ClientsHandler graphDBhandler;
+	private KustvaktConfiguration config;
+	private RewriteHandler processor;
 
+	public ResourceService() {
+		this.controller = BeansFactory.getKustvaktContext().getAuthenticationManager();
+		this.config = BeansFactory.getKustvaktContext().getConfiguration();
+		this.resourceHandler = new ResourceHandler();
+		this.searchKrill = new SearchKrill(config.getIndexDir());
+		UriBuilder builder = UriBuilder.fromUri("http://10.0.10.13").port(9997);
+		this.graphDBhandler = new ClientsHandler(builder.build());
 
-    public ResourceService () {
-        this.controller = BeansFactory.getKustvaktContext()
-                .getAuthenticationManager();
-        this.config = BeansFactory.getKustvaktContext().getConfiguration();
-        this.resourceHandler = new ResourceHandler();
-        this.searchKrill = new SearchKrill(config.getIndexDir());
-        UriBuilder builder = UriBuilder.fromUri("http://10.0.10.13").port(9997);
-        this.graphDBhandler = new ClientsHandler(builder.build());
+		this.processor = new RewriteHandler();
+		this.processor.defaultRewriteConstraints();
+		this.processor.insertBeans(BeansFactory.getKustvaktContext());
+	}
 
-        this.processor = new RewriteHandler();
-        this.processor.defaultRewriteConstraints();
-        this.processor.insertBeans(BeansFactory.getKustvaktContext());
-    }
+	/**
+	 * retrieve resources dependent by type. determines based on the user's
+	 * permission or resource owner if the user can access the resource.
+	 * 
+	 * @param locale
+	 * @param context
+	 * @param type
+	 * @return valid resources in json format
+	 */
+	@GET
+	@Path("{type}")
+	public Response getResources(@Context Locale locale, @Context SecurityContext context,
+			@PathParam("type") String type) {
+		TokenContext ctx = (TokenContext) context.getUserPrincipal();
+		Set<KustvaktResource> resources = new HashSet<>();
+		type = StringUtils.normalize(type);
 
+		try {
+			Class cl_type = ResourceFactory.getResourceClass(type);
+			if (cl_type == null)
+				throw KustvaktResponseHandler.throwit(StatusCodes.MISSING_ARGUMENT, "Resource type not available!", "");
 
-    /**
-     * retrieve resources dependent by type. determines based on
-     * the user's permission or resource owner if the user can access
-     * the resource.
-     * 
-     * @param locale
-     * @param context
-     * @param type
-     * @return valid resources in json format
-     */
-    @GET
-    @Path("{type}")
-    public Response getResources (@Context Locale locale,
-            @Context SecurityContext context, @PathParam("type") String type) {
-        TokenContext ctx = (TokenContext) context.getUserPrincipal();
-        Set<KustvaktResource> resources = new HashSet<>();
-        type = StringUtils.normalize(type);
+			User user = controller.getUser(ctx.getUsername());
 
-        try {
-            Class cl_type = ResourceFactory.getResourceClass(type);
-            if (cl_type == null)
-                throw KustvaktResponseHandler.throwit(StatusCodes.MISSING_ARGUMENT,
-                        "Resource type not available!", "");
+			resources = ResourceFinder.search(user, ResourceFactory.getResourceClass(type));
+		} catch (KustvaktException e) {
+			throw KustvaktResponseHandler.throwit(e);
+		}
 
-            User user = controller.getUser(ctx.getUsername());
+		Set values = new HashSet();
+		for (KustvaktResource resource : resources)
+			values.add(resource.toMap());
+		return Response.ok(JsonUtils.toJSON(values)).build();
+	}
 
-            resources = ResourceFinder.search(user,
-                    ResourceFactory.getResourceClass(type));
-        }
-        catch (KustvaktException e) {
-            throw KustvaktResponseHandler.throwit(e);
-        }
+	@GET
+	@Path("{type}/{id}/{child}")
+	public Response getResource(@Context SecurityContext context, @Context Locale locale,
+			@PathParam("type") String type, @PathParam("id") String id, @PathParam("child") String child) {
+		return getResource(context, locale, type, StringUtils.joinResources(id, child));
+	}
 
-        Set values = new HashSet();
-        for (KustvaktResource resource : resources)
-            values.add(resource.toMap());
-        return Response.ok(JsonUtils.toJSON(values)).build();
-    }
+	/**
+	 * @param context
+	 * @param locale
+	 * @param id
+	 * @param type
+	 * @return
+	 */
+	@GET
+	@Path("{type}/{id}")
+	public Response getResource(@Context SecurityContext context, @Context Locale locale,
+			@PathParam("type") String type, @PathParam("id") String id) {
+		TokenContext ctx = (TokenContext) context.getUserPrincipal();
+		type = StringUtils.normalize(type);
+		KustvaktResource resource;
+		try {
+			Class cl_type = ResourceFactory.getResourceClass(type);
 
+			if (ctx.isDemo()) {
+				Set set = ResourceFinder.searchPublicFiltered(cl_type, id);
+				resource = (KustvaktResource) set.toArray()[0];
+			} else {
+				User user = controller.getUser(ctx.getUsername());
+				if (StringUtils.isInteger(id))
+					resource = resourceHandler.findbyIntId(Integer.valueOf(id), user);
+				else
+					resource = resourceHandler.findbyStrId(id, user, cl_type);
+			}
+		} catch (KustvaktException e) {
+			// if (e.getStatusCode() != StatusCodes.ACCESS_DENIED)
+			throw KustvaktResponseHandler.throwit(e);
 
-    @GET
-    @Path("{type}/{id}/{child}")
-    public Response getResource (@Context SecurityContext context,
-            @Context Locale locale, @PathParam("type") String type,
-            @PathParam("id") String id, @PathParam("child") String child) {
-        return getResource(context, locale, type,
-                StringUtils.joinResources(id, child));
-    }
+			// try {
+			// Set set = ResourceFinder.searchPublicFiltered(cl_type, id);
+			// resource = (KustvaktResource) set.toArray()[0];
+			// }
+			// catch (KustvaktException e1) {
+			// throw KustvaktResponseHandler.throwit(e);
+			// }
+		}
+		return Response.ok(JsonUtils.toJSON(resource.toMap())).build();
+	}
 
+	// @GET
+	// @Path("colloc")
+	// public Response getCollocationsAll(@Context SecurityContext ctx,
+	// @Context Locale locale, @QueryParam("props") String properties,
+	// @QueryParam("sfskip") Integer sfs,
+	// @QueryParam("sflimit") Integer limit, @QueryParam("q") String query,
+	// @QueryParam("ql") String ql, @QueryParam("context") Integer context,
+	// @QueryParam("foundry") String foundry,
+	// @QueryParam("paths") Boolean wPaths) {
+	// TokenContext tokenContext = (TokenContext) ctx.getUserPrincipal();
+	// ColloQuery.ColloQueryBuilder builder;
+	// KoralCollectionQueryBuilder cquery = new KoralCollectionQueryBuilder();
+	// String result;
+	// try {
+	// User user = controller.getUser(tokenContext.getUsername());
+	// Set<VirtualCollection> resources = ResourceFinder
+	// .search(user, VirtualCollection.class);
+	// for (KustvaktResource c : resources)
+	// cquery.addResource(((VirtualCollection) c).getQuery());
+	//
+	// builder = functions
+	// .buildCollocations(query, ql, properties, context, limit,
+	// sfs, foundry, new ArrayList<Dependency>(), wPaths,
+	// cquery);
+	//
+	// result = graphDBhandler
+	// .getResponse("distCollo", "q", builder.build().toJSON());
+	// }catch (KustvaktException e) {
+	// throw KustvaktResponseHandler.throwit(e);
+	// }catch (JsonProcessingException e) {
+	// throw KustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT);
+	// }
+	// return Response.ok(result).build();
+	// }
 
-    /**
-     * @param context
-     * @param locale
-     * @param id
-     * @param type
-     * @return
-     */
-    @GET
-    @Path("{type}/{id}")
-    public Response getResource (@Context SecurityContext context,
-            @Context Locale locale, @PathParam("type") String type,
-            @PathParam("id") String id) {
-        TokenContext ctx = (TokenContext) context.getUserPrincipal();
-        type = StringUtils.normalize(type);
-        KustvaktResource resource;
-        try {
-            Class cl_type = ResourceFactory.getResourceClass(type);
+	// /**
+	// * @param locale
+	// * @param properties a json object string containing field, op and value
+	// for the query
+	// * @param query
+	// * @param context
+	// * @return
+	// */
+	// @GET
+	// @Path("{type}/{id}/colloc")
+	// public Response getCollocations(@Context SecurityContext ctx,
+	// @Context Locale locale, @QueryParam("props") String properties,
+	// @QueryParam("sfskip") Integer sfs,
+	// @QueryParam("sflimit") Integer limit, @QueryParam("q") String query,
+	// @QueryParam("ql") String ql, @QueryParam("context") Integer context,
+	// @QueryParam("foundry") String foundry,
+	// @QueryParam("paths") Boolean wPaths, @PathParam("id") String id,
+	// @PathParam("type") String type) {
+	// ColloQuery.ColloQueryBuilder builder;
+	// type = StringUtils.normalize(type);
+	// id = StringUtils.decodeHTML(id);
+	// TokenContext tokenContext = (TokenContext) ctx.getUserPrincipal();
+	// String result;
+	// try {
+	// KoralCollectionQueryBuilder cquery = new KoralCollectionQueryBuilder();
+	// try {
+	// User user = controller.getUser(tokenContext.getUsername());
+	//
+	// KustvaktResource resource = this.resourceHandler
+	// .findbyStrId(id, user, type);
+	//
+	// if (resource instanceof VirtualCollection)
+	// cquery.addResource(
+	// ((VirtualCollection) resource).getQuery());
+	// else if (resource instanceof Corpus)
+	// cquery.addMetaFilter("corpusID",
+	// resource.getPersistentID());
+	// else
+	// throw KustvaktResponseHandler
+	// .throwit(StatusCodes.ILLEGAL_ARGUMENT,
+	// "Type parameter not supported", type);
+	//
+	// }catch (KustvaktException e) {
+	// throw KustvaktResponseHandler.throwit(e);
+	// }catch (NumberFormatException ex) {
+	// throw KustvaktResponseHandler
+	// .throwit(StatusCodes.ILLEGAL_ARGUMENT);
+	// }
+	//
+	// builder = functions
+	// .buildCollocations(query, ql, properties, context, limit,
+	// sfs, foundry, new ArrayList<Dependency>(), wPaths,
+	// cquery);
+	//
+	// result = graphDBhandler
+	// .getResponse("distCollo", "q", builder.build().toJSON());
+	//
+	// }catch (JsonProcessingException e) {
+	// throw KustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT);
+	// }catch (KustvaktException e) {
+	// throw KustvaktResponseHandler.throwit(e);
+	// }
+	//
+	// return Response.ok(result).build();
+	// }
+	@POST
+	@Path("colloc")
+	public Response getCollocationBase(@QueryParam("q") String query) {
+		String result;
+		try {
+			result = graphDBhandler.getResponse("distCollo", "q", query);
+		} catch (KustvaktException e) {
+			throw KustvaktResponseHandler.throwit(e);
+		}
+		return Response.ok(result).build();
+	}
 
-            if (ctx.isDemo()) {
-                Set set = ResourceFinder.searchPublicFiltered(cl_type, id);
-                resource = (KustvaktResource) set.toArray()[0];
-            } else {
-                User user = controller.getUser(ctx.getUsername());
-                if (StringUtils.isInteger(id))
-                    resource = resourceHandler.findbyIntId(Integer.valueOf(id),
-                            user);
-                else
-                    resource = resourceHandler.findbyStrId(id, user,
-                            cl_type);
-            }
-        }
-        catch (KustvaktException e) {
-            //if (e.getStatusCode() != StatusCodes.ACCESS_DENIED)
-            throw KustvaktResponseHandler.throwit(e);
+	@Deprecated
+	public Response postMatchFavorite() {
+		return Response.ok().build();
+	}
 
-            //try {
-            //    Set set = ResourceFinder.searchPublicFiltered(cl_type, id);
-             //   resource = (KustvaktResource) set.toArray()[0];
-            //}
-            //catch (KustvaktException e1) {
-            //    throw KustvaktResponseHandler.throwit(e);
-            //}
-        }
-        return Response.ok(JsonUtils.toJSON(resource.toMap())).build();
-    }
+	// ref query parameter removed!
+	@TRACE
+	@Path("search")
+	public Response buildQuery(@Context Locale locale, @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, @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);
+		// }
 
-    //    @GET
-    //    @Path("colloc")
-    //    public Response getCollocationsAll(@Context SecurityContext ctx,
-    //            @Context Locale locale, @QueryParam("props") String properties,
-    //            @QueryParam("sfskip") Integer sfs,
-    //            @QueryParam("sflimit") Integer limit, @QueryParam("q") String query,
-    //            @QueryParam("ql") String ql, @QueryParam("context") Integer context,
-    //            @QueryParam("foundry") String foundry,
-    //            @QueryParam("paths") Boolean wPaths) {
-    //        TokenContext tokenContext = (TokenContext) ctx.getUserPrincipal();
-    //        ColloQuery.ColloQueryBuilder builder;
-    //        KoralCollectionQueryBuilder cquery = new KoralCollectionQueryBuilder();
-    //        String result;
-    //        try {
-    //            User user = controller.getUser(tokenContext.getUsername());
-    //            Set<VirtualCollection> resources = ResourceFinder
-    //                    .search(user, VirtualCollection.class);
-    //            for (KustvaktResource c : resources)
-    //                cquery.addResource(((VirtualCollection) c).getQuery());
-    //
-    //            builder = functions
-    //                    .buildCollocations(query, ql, properties, context, limit,
-    //                            sfs, foundry, new ArrayList<Dependency>(), wPaths,
-    //                            cquery);
-    //
-    //            result = graphDBhandler
-    //                    .getResponse("distCollo", "q", builder.build().toJSON());
-    //        }catch (KustvaktException e) {
-    //            throw KustvaktResponseHandler.throwit(e);
-    //        }catch (JsonProcessingException e) {
-    //            throw KustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT);
-    //        }
-    //        return Response.ok(result).build();
-    //    }
+		ss = new QuerySerializer().setQuery(q, ql, v);
+		if (cq != null)
+			ss.setCollection(cq);
 
-    //    /**
-    //     * @param locale
-    //     * @param properties a json object string containing field, op and value for the query
-    //     * @param query
-    //     * @param context
-    //     * @return
-    //     */
-    //    @GET
-    //    @Path("{type}/{id}/colloc")
-    //    public Response getCollocations(@Context SecurityContext ctx,
-    //            @Context Locale locale, @QueryParam("props") String properties,
-    //            @QueryParam("sfskip") Integer sfs,
-    //            @QueryParam("sflimit") Integer limit, @QueryParam("q") String query,
-    //            @QueryParam("ql") String ql, @QueryParam("context") Integer context,
-    //            @QueryParam("foundry") String foundry,
-    //            @QueryParam("paths") Boolean wPaths, @PathParam("id") String id,
-    //            @PathParam("type") String type) {
-    //        ColloQuery.ColloQueryBuilder builder;
-    //        type = StringUtils.normalize(type);
-    //        id = StringUtils.decodeHTML(id);
-    //        TokenContext tokenContext = (TokenContext) ctx.getUserPrincipal();
-    //        String result;
-    //        try {
-    //            KoralCollectionQueryBuilder cquery = new KoralCollectionQueryBuilder();
-    //            try {
-    //                User user = controller.getUser(tokenContext.getUsername());
-    //
-    //                KustvaktResource resource = this.resourceHandler
-    //                        .findbyStrId(id, user, type);
-    //
-    //                if (resource instanceof VirtualCollection)
-    //                    cquery.addResource(
-    //                            ((VirtualCollection) resource).getQuery());
-    //                else if (resource instanceof Corpus)
-    //                    cquery.addMetaFilter("corpusID",
-    //                            resource.getPersistentID());
-    //                else
-    //                    throw KustvaktResponseHandler
-    //                            .throwit(StatusCodes.ILLEGAL_ARGUMENT,
-    //                                    "Type parameter not supported", type);
-    //
-    //            }catch (KustvaktException e) {
-    //                throw KustvaktResponseHandler.throwit(e);
-    //            }catch (NumberFormatException ex) {
-    //                throw KustvaktResponseHandler
-    //                        .throwit(StatusCodes.ILLEGAL_ARGUMENT);
-    //            }
-    //
-    //            builder = functions
-    //                    .buildCollocations(query, ql, properties, context, limit,
-    //                            sfs, foundry, new ArrayList<Dependency>(), wPaths,
-    //                            cquery);
-    //
-    //            result = graphDBhandler
-    //                    .getResponse("distCollo", "q", builder.build().toJSON());
-    //
-    //        }catch (JsonProcessingException e) {
-    //            throw KustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT);
-    //        }catch (KustvaktException e) {
-    //            throw KustvaktResponseHandler.throwit(e);
-    //        }
-    //
-    //        return Response.ok(result).build();
-    //    }
-    @POST
-    @Path("colloc")
-    public Response getCollocationBase (@QueryParam("q") String query) {
-        String result;
-        try {
-            result = graphDBhandler.getResponse("distCollo", "q", query);
-        }
-        catch (KustvaktException e) {
-            throw KustvaktResponseHandler.throwit(e);
-        }
-        return Response.ok(result).build();
-    }
+		MetaQueryBuilder meta = new MetaQueryBuilder();
+		if (pageIndex != null)
+			meta.addEntry("startIndex", pageIndex);
+		if (pageIndex == null && startPage != null)
+			meta.addEntry("startPage", startPage);
+		if (pageLength != null)
+			meta.addEntry("count", pageLength);
+		if (context != null)
+			meta.setSpanContext(context);
+		meta.addEntry("cutOff", cutoff);
 
+		ss.setMeta(meta.raw());
+		return Response.ok(ss.toJSON()).build();
+	}
 
-    @Deprecated
-    public Response postMatchFavorite () {
-        return Response.ok().build();
-    }
+	/**
+	 * 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!
+	 * 
+	 * @param locale
+	 * @param q
+	 * @param ql
+	 * @param v
+	 * @param pageLength
+	 * @param pageIndex
+	 * @return
+	 */
 
+	// todo: does cq have any sensible worth here? --> would say no! --> is
+	// useful in non type/id scenarios
+	@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,
+			@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) {
+		TokenContext ctx = (TokenContext) securityContext.getUserPrincipal();
+		type = StringUtils.normalize(type);
+		id = StringUtils.decodeHTML(id);
 
-    // ref query parameter removed!
-    @TRACE
-    @Path("search")
-    public Response buildQuery (@Context Locale locale,
-            @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, @QueryParam("cq") String cq) {
-        TokenContext ctx = (TokenContext) securityContext.getUserPrincipal();
-        QuerySerializer ss;
+		QuerySerializer ss = new QuerySerializer().setQuery(q, ql, v);
 
-        //User user;
-        //try {
-        //    user = controller.getUser(ctx.getUsername());
-        //}
-        //catch (KustvaktException e) {
-        //    throw KustvaktResponseHandler.throwit(e);
-        //}
+		MetaQueryBuilder meta = new MetaQueryBuilder();
+		if (pageIndex != null)
+			meta.addEntry("startIndex", pageIndex);
+		if (pageIndex == null && startPage != null)
+			meta.addEntry("startPage", startPage);
+		if (pageLength != null)
+			meta.addEntry("count", pageLength);
+		if (context != null)
+			meta.setSpanContext(context);
+		if (cutoff != null)
+			meta.addEntry("cutOff", cutoff);
 
-        ss = new QuerySerializer().setQuery(q, ql, v);
-        if (cq != null)
-            ss.setCollection(cq);
+		ss.setMeta(meta.raw());
 
-        MetaQueryBuilder meta = new MetaQueryBuilder();
-        if (pageIndex != null)
-            meta.addEntry("startIndex", pageIndex);
-        if (pageIndex == null && startPage != null)
-            meta.addEntry("startPage", startPage);
-        if (pageLength != null)
-            meta.addEntry("count", pageLength);
-        if (context != null)
-            meta.setSpanContext(context);
-        meta.addEntry("cutOff", cutoff);
+		KoralCollectionQueryBuilder cquery = new KoralCollectionQueryBuilder();
+		cquery.setBaseQuery(ss.toJSON());
 
-        ss.setMeta(meta.raw());
-        return Response.ok(ss.toJSON()).build();
-    }
+		String query = "";
+		KustvaktResource resource;
+		try {
 
+			if (ctx.isDemo()) {
+				Set set = ResourceFinder.searchPublicFiltered(ResourceFactory.getResourceClass(type), id);
+				resource = (KustvaktResource) set.toArray()[0];
+			} else {
+				User user = controller.getUser(ctx.getUsername());
+				if (StringUtils.isInteger(id))
+					resource = this.resourceHandler.findbyIntId(Integer.valueOf(id), user);
+				else
+					resource = this.resourceHandler.findbyStrId(id, user, ResourceFactory.getResourceClass(type));
+			}
+		}
+		// todo: instead of throwing exception, build notification and rewrites
+		// into result query
+		catch (KustvaktException e) {
+			jlog.error("Exception encountered: {}", e.string());
+			throw KustvaktResponseHandler.throwit(e);
+		}
 
-    /**
-     * 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!
-     * 
-     * @param locale
-     * @param q
-     * @param ql
-     * @param v
-     * @param pageLength
-     * @param pageIndex
-     * @return
-     */
+		if (resource != null) {
+			if (resource instanceof VirtualCollection)
+				query = JsonUtils.toJSON(cquery.and().mergeWith(resource.getData()));
+			else if (resource instanceof Corpus) {
+				cquery.and().with(Attributes.CORPUS_SIGLE, "=", resource.getPersistentID());
+				query = cquery.toJSON();
+			}
+		}
+		return Response.ok(query).build();
+	}
 
-    //todo: does cq have any sensible worth here? --> would say no! --> is useful in non type/id scenarios
-    @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, @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) {
-        TokenContext ctx = (TokenContext) securityContext.getUserPrincipal();
-        type = StringUtils.normalize(type);
-        id = StringUtils.decodeHTML(id);
+	@POST
+	@Path("search")
+	public Response queryRaw(@Context SecurityContext context, @Context Locale locale,
+			@QueryParam("engine") String engine, String jsonld) {
+		TokenContext ctx = (TokenContext) context.getUserPrincipal();
 
-        QuerySerializer ss = new QuerySerializer().setQuery(q, ql, v);
+		// todo: should be possible to add the meta part to the query
+		// serialization
+		try {
+			User user = controller.getUser(ctx.getUsername());
+			// jsonld = this.processor.processQuery(jsonld, user);
+		} catch (KustvaktException e) {
+			throw KustvaktResponseHandler.throwit(e);
+		}
+		jlog.info("Serialized search: {}", jsonld);
 
-        MetaQueryBuilder meta = new MetaQueryBuilder();
-        if (pageIndex != null)
-            meta.addEntry("startIndex", pageIndex);
-        if (pageIndex == null && startPage != null)
-            meta.addEntry("startPage", startPage);
-        if (pageLength != null)
-            meta.addEntry("count", pageLength);
-        if (context != null)
-            meta.setSpanContext(context);
-        if (cutoff != null)
-            meta.addEntry("cutOff", cutoff);
+		String result = searchKrill.search(jsonld);
+		// todo: logging
+		KustvaktLogger.QUERY_LOGGER.trace("The result set: {}", result);
+		return Response.ok(result).build();
+	}
 
-        ss.setMeta(meta.raw());
+	@GET
+	@Path("search")
+	public Response searchbyNameAll(@Context SecurityContext securityContext, @Context Locale locale,
+			@QueryParam("q") String q, @QueryParam("ql") String ql, @QueryParam("v") String v,
+			@QueryParam("context") String ctx, @QueryParam("cutoff") Boolean cutoff,
+			@QueryParam("count") Integer pageLength, @QueryParam("offset") Integer pageIndex,
+			@QueryParam("page") Integer pageInteger, @QueryParam("cq") String cq, @QueryParam("engine") String engine) {
+		TokenContext context = (TokenContext) securityContext.getUserPrincipal();
+		KustvaktConfiguration.BACKENDS eng = this.config.chooseBackend(engine);
+		User user;
+		try {
+			user = controller.getUser(context.getUsername());
+		} catch (KustvaktException e) {
+			jlog.error("Exception encountered: {}", e.string());
+			throw KustvaktResponseHandler.throwit(e);
+		}
+		String result;
+		QuerySerializer serializer = new QuerySerializer();
+		serializer.setQuery(q, ql, v);
 
-        KoralCollectionQueryBuilder cquery = new KoralCollectionQueryBuilder();
-        cquery.setBaseQuery(ss.toJSON());
+		if (cq != null)
+			serializer.setCollection(cq);
 
+		MetaQueryBuilder meta = new MetaQueryBuilder();
+		meta.addEntry("startIndex", pageIndex);
+		meta.addEntry("startPage", pageInteger);
+		meta.setSpanContext(ctx);
+		meta.addEntry("count", pageLength);
+		// todo: what happened to cutoff?
+		meta.addEntry("cutoff", cutoff);
+		// meta.addMeta(pageIndex, pageInteger, pageLength, ctx, cutoff);
+		// fixme: should only apply to CQL queries per default!
+		// meta.addEntry("itemsPerResource", 1);
+		serializer.setMeta(meta.raw());
+		String query;
+		try {
+			query = this.processor.processQuery(serializer.toJSON(), user);
+		} catch (KustvaktException e) {
+			throw KustvaktResponseHandler.throwit(e);
+		}
 
-        String query = "";
-        KustvaktResource resource;
-        try {
+		jlog.info("the serialized query {}", query);
 
-            if (ctx.isDemo()) {
-                Set set = ResourceFinder.searchPublicFiltered(
-                        ResourceFactory.getResourceClass(type), id);
-                resource = (KustvaktResource) set.toArray()[0];
-            } else {
-                User user = controller.getUser(ctx.getUsername());
-                if (StringUtils.isInteger(id))
-                    resource = this.resourceHandler.findbyIntId(
-                            Integer.valueOf(id), user);
-                else
-                    resource = this.resourceHandler.findbyStrId(id, user,
-                            ResourceFactory.getResourceClass(type));
-            }
-        }
-        //todo: instead of throwing exception, build notification and rewrites into result query
-        catch (KustvaktException e) {
-            jlog.error("Exception encountered: {}", e.string());
-            throw KustvaktResponseHandler.throwit(e);
-        }
+		if (eng.equals(KustvaktConfiguration.BACKENDS.NEO4J)) {
+			MultivaluedMap map = new MultivaluedMapImpl();
+			map.add("q", query);
+			map.add("count", String.valueOf(pageLength));
+			map.add("lctxs", String.valueOf(meta.getSpanContext().getLeftSize()));
+			map.add("rctxs", String.valueOf(meta.getSpanContext().getRightSize()));
+			try {
+				result = this.graphDBhandler.getResponse(map, "distKwic");
+			} catch (KustvaktException e) {
+				jlog.error("Exception encountered: {}", e.string());
+				throw KustvaktResponseHandler.throwit(e);
+			}
+		} else
+			result = searchKrill.search(query);
+		KustvaktLogger.QUERY_LOGGER.trace("The result set: {}", result);
+		return Response.ok(result).build();
+	}
 
-        if (resource != null) {
-            if (resource instanceof VirtualCollection)
-                query = JsonUtils.toJSON(cquery.and().mergeWith(
-                        resource.getData()));
-            else if (resource instanceof Corpus) {
-                cquery.and().with(Attributes.CORPUS_SIGLE, "=",
-                        resource.getPersistentID());
-                query = cquery.toJSON();
-            }
-        }
-        return Response.ok(query).build();
-    }
+	/**
+	 * String search, String ql, List<String> parents, String cli, String cri,
+	 * int cls, int crs, int num, int page, boolean cutoff) param context will
+	 * be like this: context: "3-t,2-c"
+	 * <p/>
+	 * id does not have to be an integer. name is also possible, in which case a
+	 * type reference is required
+	 * 
+	 * @param securityContext
+	 * @param locale
+	 * @return
+	 */
+	// todo: remove raw
+	@GET
+	@Path("/{type}/{id}/search")
+	public Response searchbyName(@Context SecurityContext securityContext, @Context Locale locale,
+			@QueryParam("q") String query, @QueryParam("ql") String ql, @QueryParam("v") String v,
+			@QueryParam("context") String ctx, @QueryParam("cutoff") Boolean cutoff,
+			@QueryParam("count") Integer pageLength, @QueryParam("offset") Integer pageIndex,
+			@QueryParam("page") Integer pageInteger, @PathParam("id") String id, @PathParam("type") String type,
+			@QueryParam("cq") String cq, @QueryParam("raw") Boolean raw, @QueryParam("engine") String engine) {
+		// ref is a virtual collection id!
+		TokenContext context = (TokenContext) securityContext.getUserPrincipal();
+		KustvaktConfiguration.BACKENDS eng = this.config.chooseBackend(engine);
+		type = StringUtils.normalize(type);
+		id = StringUtils.decodeHTML(id);
+		raw = raw == null ? false : raw;
 
+		try {
+			User user = controller.getUser(context.getUsername());
+			MetaQueryBuilder meta = new MetaQueryBuilder();
 
-    @POST
-    @Path("search")
-    public Response queryRaw (@Context SecurityContext context,
-            @Context Locale locale, @QueryParam("engine") String engine,
-            String jsonld) {
-        TokenContext ctx = (TokenContext) context.getUserPrincipal();
+			if (!raw) {
+				QuerySerializer s = new QuerySerializer();
+				s.setQuery(query, ql, v);
 
-        // todo: should be possible to add the meta part to the query serialization
-        try {
-            User user = controller.getUser(ctx.getUsername());
-            //jsonld = this.processor.processQuery(jsonld, user);
-        }
-        catch (KustvaktException e) {
-            throw KustvaktResponseHandler.throwit(e);
-        }
-        jlog.info("Serialized search: {}", jsonld);
+				KoralCollectionQueryBuilder builder = new KoralCollectionQueryBuilder();
 
-        String result = searchKrill.search(jsonld);
-        // todo: logging
-        KustvaktLogger.QUERY_LOGGER.trace("The result set: {}", result);
-        return Response.ok(result).build();
-    }
+				KustvaktResource resource;
+				if (StringUtils.isInteger(id))
+					resource = this.resourceHandler.findbyIntId(Integer.valueOf(id), user);
+				else
+					resource = this.resourceHandler.findbyStrId(id, user, ResourceFactory.getResourceClass(type));
 
+				if (resource instanceof VirtualCollection)
+					builder.setBaseQuery(resource.getData());
+				else if (resource instanceof Corpus)
+					builder.with(Attributes.CORPUS_SIGLE + resource.getPersistentID());
+				else
+					throw KustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT, "Type parameter not supported",
+							type);
 
-    @GET
-    @Path("search")
-    public Response searchbyNameAll (@Context SecurityContext securityContext,
-            @Context Locale locale, @QueryParam("q") String q,
-            @QueryParam("ql") String ql, @QueryParam("v") String v,
-            @QueryParam("context") String ctx,
-            @QueryParam("cutoff") Boolean cutoff,
-            @QueryParam("count") Integer pageLength,
-            @QueryParam("offset") Integer pageIndex,
-            @QueryParam("page") Integer pageInteger,
-            @QueryParam("cq") String cq, @QueryParam("engine") String engine) {
-        TokenContext context = (TokenContext) securityContext
-                .getUserPrincipal();
-        KustvaktConfiguration.BACKENDS eng = this.config.chooseBackend(engine);
-        User user;
-        try {
-            user = controller.getUser(context.getUsername());
-        }
-        catch (KustvaktException e) {
-            jlog.error("Exception encountered: {}", e.string());
-            throw KustvaktResponseHandler.throwit(e);
-        }
-        String result;
-        QuerySerializer serializer = new QuerySerializer();
-        serializer.setQuery(q, ql, v);
+				meta.addEntry("startIndex", pageIndex);
+				meta.addEntry("startPage", pageInteger);
+				meta.setSpanContext(ctx);
+				meta.addEntry("count", pageLength);
+				// todo: what happened to cutoff?
+				meta.addEntry("cutoff", cutoff);
+				// should only apply to CQL queries
+				// meta.addEntry("itemsPerResource", 1);
+				s.setMeta(meta.raw());
 
-        if (cq != null)
-            serializer.setCollection(cq);
+				query = s.toJSON();
+			}
+			String result;
+			try {
 
-        MetaQueryBuilder meta = new MetaQueryBuilder();
-        meta.addEntry("startIndex", pageIndex);
-        meta.addEntry("startPage", pageInteger);
-        meta.setSpanContext(ctx);
-        meta.addEntry("count", pageLength);
-        // todo: what happened to cutoff?
-        meta.addEntry("cutoff", cutoff);
-        //        meta.addMeta(pageIndex, pageInteger, pageLength, ctx, cutoff);
-        // fixme: should only apply to CQL queries per default!
-        //        meta.addEntry("itemsPerResource", 1);
-        serializer.setMeta(meta.raw());
-        String query;
-        try {
-            query = this.processor.processQuery(serializer.toJSON(), user);
-        }
-        catch (KustvaktException e) {
-            throw KustvaktResponseHandler.throwit(e);
-        }
+				// rewrite process
+				query = this.processor.processQuery(query, user);
 
-        jlog.info("the serialized query {}", query);
+				if (eng.equals(KustvaktConfiguration.BACKENDS.NEO4J)) {
+					if (raw)
+						throw KustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT, "raw not supported!", null);
+					MultivaluedMap map = new MultivaluedMapImpl();
+					map.add("q", query);
+					map.add("count", String.valueOf(pageLength));
+					map.add("lctxs", String.valueOf(meta.getSpanContext().getLeftSize()));
+					map.add("rctxs", String.valueOf(meta.getSpanContext().getRightSize()));
+					result = this.graphDBhandler.getResponse(map, "distKwic");
+				} else
+					result = searchKrill.search(query);
 
-        if (eng.equals(KustvaktConfiguration.BACKENDS.NEO4J)) {
-            MultivaluedMap map = new MultivaluedMapImpl();
-            map.add("q", query);
-            map.add("count", String.valueOf(pageLength));
-            map.add("lctxs",
-                    String.valueOf(meta.getSpanContext().getLeftSize()));
-            map.add("rctxs",
-                    String.valueOf(meta.getSpanContext().getRightSize()));
-            try {
-                result = this.graphDBhandler.getResponse(map, "distKwic");
-            }
-            catch (KustvaktException e) {
-                jlog.error("Exception encountered: {}", e.string());
-                throw KustvaktResponseHandler.throwit(e);
-            }
-        }
-        else
-            result = searchKrill.search(query);
-        KustvaktLogger.QUERY_LOGGER.trace("The result set: {}", result);
-        return Response.ok(result).build();
-    }
+			} catch (Exception e) {
+				jlog.error("Exception for serialized query: " + query, e);
+				throw KustvaktResponseHandler.throwit(500, e.getMessage(), null);
+			}
 
+			KustvaktLogger.QUERY_LOGGER.trace("The result set: {}", result);
+			return Response.ok(result).build();
+		} catch (KustvaktException e) {
+			jlog.error("Exception encountered: {}", e.string());
+			throw KustvaktResponseHandler.throwit(e);
+		}
 
-    /**
-     * String search, String ql, List<String> parents,
-     * String cli, String cri, int cls, int crs,
-     * int num, int page, boolean cutoff)
-     * param context will be like this: context: "3-t,2-c"
-     * <p/>
-     * id does not have to be an integer. name is also possible, in
-     * which case a type reference is required
-     * 
-     * @param securityContext
-     * @param locale
-     * @return
-     */
-    // todo: remove raw
-    @GET
-    @Path("/{type}/{id}/search")
-    public Response searchbyName (@Context SecurityContext securityContext,
-            @Context Locale locale, @QueryParam("q") String query,
-            @QueryParam("ql") String ql, @QueryParam("v") String v,
-            @QueryParam("context") String ctx,
-            @QueryParam("cutoff") Boolean cutoff,
-            @QueryParam("count") Integer pageLength,
-            @QueryParam("offset") Integer pageIndex,
-            @QueryParam("page") Integer pageInteger,
-            @PathParam("id") String id, @PathParam("type") String type,
-            @QueryParam("cq") String cq, @QueryParam("raw") Boolean raw,
-            @QueryParam("engine") String engine) {
-        // ref is a virtual collection id!
-        TokenContext context = (TokenContext) securityContext
-                .getUserPrincipal();
-        KustvaktConfiguration.BACKENDS eng = this.config.chooseBackend(engine);
-        type = StringUtils.normalize(type);
-        id = StringUtils.decodeHTML(id);
-        raw = raw == null ? false : raw;
+	}
 
-        try {
-            User user = controller.getUser(context.getUsername());
-            MetaQueryBuilder meta = new MetaQueryBuilder();
+	@POST
+	@Path("stats")
+	public Response getStats(@Context SecurityContext context, @Context Locale locale, String json) {
+		KoralCollectionQueryBuilder builder = new KoralCollectionQueryBuilder();
+		builder.with(json);
+		String stats = searchKrill.getStatistics(builder.toJSON());
 
-            if (!raw) {
-                QuerySerializer s = new QuerySerializer();
-                s.setQuery(query, ql, v);
-
-                KoralCollectionQueryBuilder builder = new KoralCollectionQueryBuilder();
-
-                KustvaktResource resource;
-                if (StringUtils.isInteger(id))
-                    resource = this.resourceHandler.findbyIntId(
-                            Integer.valueOf(id), user);
-                else
-                    resource = this.resourceHandler.findbyStrId(id, user,
-                            ResourceFactory.getResourceClass(type));
-
-                if (resource instanceof VirtualCollection)
-                    builder.setBaseQuery(resource.getData());
-                else if (resource instanceof Corpus)
-                    builder.with(Attributes.CORPUS_SIGLE
-                            + resource.getPersistentID());
-                else
-                    throw KustvaktResponseHandler.throwit(
-                            StatusCodes.ILLEGAL_ARGUMENT,
-                            "Type parameter not supported", type);
-
-                meta.addEntry("startIndex", pageIndex);
-                meta.addEntry("startPage", pageInteger);
-                meta.setSpanContext(ctx);
-                meta.addEntry("count", pageLength);
-                // todo: what happened to cutoff?
-                meta.addEntry("cutoff", cutoff);
-                // should only apply to CQL queries
-                //                meta.addEntry("itemsPerResource", 1);
-                s.setMeta(meta.raw());
-
-                query = s.toJSON();
-            }
-            String result;
-            try {
-
-                // rewrite process
-                query = this.processor.processQuery(query, user);
-
-                if (eng.equals(KustvaktConfiguration.BACKENDS.NEO4J)) {
-                    if (raw)
-                        throw KustvaktResponseHandler.throwit(
-                                StatusCodes.ILLEGAL_ARGUMENT,
-                                "raw not supported!", null);
-                    MultivaluedMap map = new MultivaluedMapImpl();
-                    map.add("q", query);
-                    map.add("count", String.valueOf(pageLength));
-                    map.add("lctxs",
-                            String.valueOf(meta.getSpanContext().getLeftSize()));
-                    map.add("rctxs", String.valueOf(meta.getSpanContext()
-                            .getRightSize()));
-                    result = this.graphDBhandler.getResponse(map, "distKwic");
-                }
-                else
-                    result = searchKrill.search(query);
-
-            }
-            catch (Exception e) {
-                jlog.error("Exception for serialized query: " + query, e);
-                throw KustvaktResponseHandler
-                        .throwit(500, e.getMessage(), null);
-            }
-
-            KustvaktLogger.QUERY_LOGGER.trace("The result set: {}", result);
-            return Response.ok(result).build();
-        }
-        catch (KustvaktException e) {
-            jlog.error("Exception encountered: {}", e.string());
-            throw KustvaktResponseHandler.throwit(e);
-        }
-
-    }
-
-
-    @POST
-    @Path("stats")
-    public Response getStats (@Context SecurityContext context,
-            @Context Locale locale, String json) {
-        KoralCollectionQueryBuilder builder = new KoralCollectionQueryBuilder();
-        builder.with(json);
-        String stats = searchKrill.getStatistics(builder.toJSON());
-
-        if (stats.contains("-1"))
-            throw KustvaktResponseHandler.throwit(StatusCodes.NO_VALUE_FOUND);
-
-        return Response.ok(stats).build();
-    }
-
-
-    @GET
-    @Path("{type}/{id}/{child}/stats")
-    public Response getStatisticsbyIdChild (@Context SecurityContext context,
-            @Context Locale locale, @PathParam("type") String type,
-            @PathParam("id") String id, @PathParam("child") String child) {
-        return getStatisticsbyId(context, locale, type,
-                StringUtils.joinResources(id, child));
-    }
-
-
-    @GET
-    @Path("{type}/{id}/stats")
-    public Response getStatisticsbyId (@Context SecurityContext context,
-            @Context Locale locale, @PathParam("type") String type,
-            @PathParam("id") String id) {
-        TokenContext ctx = (TokenContext) context.getUserPrincipal();
-        type = StringUtils.normalize(type);
-        id = StringUtils.decodeHTML(id);
-
-
-        try {
-            Class sl = ResourceFactory.getResourceClass(type);
-            if (!VirtualCollection.class.equals(sl) & !Corpus.class.equals(sl))
-                throw KustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT,
-                        "Requested Resource type not supported", type);
-
-            User user = controller.getUser(ctx.getUsername());
-            KustvaktResource resource;
-            if (StringUtils.isInteger(id))
-                resource = this.resourceHandler.findbyIntId(
-                        Integer.valueOf(id), user);
-            else
-                resource = this.resourceHandler.findbyStrId(id, user,
-                        ResourceFactory.getResourceClass(type));
-
-            //todo ?!
-            KoralCollectionQueryBuilder query = new KoralCollectionQueryBuilder();
-            if (resource instanceof VirtualCollection) {
-                query.setBaseQuery(resource.getData());
-            }
-            else if (resource instanceof Corpus) {
-                query.with(Attributes.CORPUS_SIGLE + "=" + resource.getName());
-            }
-            String res = query.toJSON();
-            String qstr = processor.processQuery(res, user);
-            return Response.ok(searchKrill.getStatistics(qstr)).build();
-        }
-        catch (KustvaktException e) {
-            jlog.error("Exception encountered: {}", e.string());
-            throw KustvaktResponseHandler.throwit(e);
-        }
-    }
-
-
-    /**
-     * @param context
-     * @param locale
-     * @param json
-     * @return
-     */
-    //todo: rename
-    @POST
-    @Path("collection_raw")
-    public Response createRawCollection (@Context SecurityContext context,
-            @Context Locale locale, String json) {
-        TokenContext c = (TokenContext) context.getUserPrincipal();
-        VirtualCollection cache = ResourceFactory.getCachedCollection(json);
-        User user;
-        try {
-            user = controller.getUser(c.getUsername());
-        }
-        catch (KustvaktException e) {
-            jlog.error("Exception encountered: {}", e.string());
-            throw KustvaktResponseHandler.throwit(e);
-        }
-
-        VirtualCollection tmp = resourceHandler.getCache(cache.getId(),
-                VirtualCollection.class);
-        if (tmp == null) {
-            String query;
-            try {
-                query = this.processor.processQuery(cache.getData(), user);
-            }
-            catch (KustvaktException e) {
-                throw KustvaktResponseHandler.throwit(e);
-            }
-            String stats = searchKrill.getStatistics(query);
-            cache.setStats(JsonUtils.readSimple(stats, Map.class));
-            resourceHandler.cache(cache);
-        }
-        else
-            cache = tmp;
-
-        Map vals = new HashMap();
-        vals.put("id", cache.getId());
-        vals.put("statistics", cache.getStats());
-        return Response.ok(JsonUtils.toJSON(vals)).build();
-    }
+		if (stats.contains("-1"))
+			throw KustvaktResponseHandler.throwit(StatusCodes.NO_VALUE_FOUND);
 
+		return Response.ok(stats).build();
+	}
 
-    @POST
-    @Path("{type}/{id}")
-    public Response updateResource (@Context SecurityContext context,
-            @Context Locale locale, @PathParam("type") String type,
-            @PathParam("id") String id, String json) {
-        TokenContext ctx = (TokenContext) context.getUserPrincipal();
-        User user;
-        try {
-            user = controller.getUser(ctx.getUsername());
-            KustvaktResource resource = this.resourceHandler.findbyStrId(id,
-                    user, ResourceFactory.getResourceClass(type));
-            JsonNode node = JsonUtils.readTree(json);
+	@GET
+	@Path("{type}/{id}/{child}/stats")
+	public Response getStatisticsbyIdChild(@Context SecurityContext context, @Context Locale locale,
+			@PathParam("type") String type, @PathParam("id") String id, @PathParam("child") String child) {
+		return getStatisticsbyId(context, locale, type, StringUtils.joinResources(id, child));
+	}
 
-            if (node.isObject() && !node.path("name").isMissingNode()) {
-                String s = node.path("name").asText();
-                if (s.equals("null") || s.isEmpty())
-                    throw KustvaktResponseHandler.throwit(
-                            StatusCodes.ILLEGAL_ARGUMENT, "Name must be set",
-                            "name");
-                resource.setName(s);
-            }
+	@GET
+	@Path("{type}/{id}/stats")
+	public Response getStatisticsbyId(@Context SecurityContext context, @Context Locale locale,
+			@PathParam("type") String type, @PathParam("id") String id) {
+		TokenContext ctx = (TokenContext) context.getUserPrincipal();
+		type = StringUtils.normalize(type);
+		id = StringUtils.decodeHTML(id);
 
-            if (node.isObject() && !node.path("description").isMissingNode())
-                resource.setDescription(node.path("description").asText());
-            this.resourceHandler.updateResources(user, resource);
-        }
-        catch (KustvaktException e) {
-            jlog.error("Exception encountered: {}", e.string());
-            throw KustvaktResponseHandler.throwit(e);
-        }
-        return Response.ok().build();
-    }
+		try {
+			Class sl = ResourceFactory.getResourceClass(type);
+			if (!VirtualCollection.class.equals(sl) & !Corpus.class.equals(sl))
+				throw KustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT,
+						"Requested Resource type not supported", type);
 
+			User user = controller.getUser(ctx.getUsername());
+			KustvaktResource resource;
+			if (StringUtils.isInteger(id))
+				resource = this.resourceHandler.findbyIntId(Integer.valueOf(id), user);
+			else
+				resource = this.resourceHandler.findbyStrId(id, user, ResourceFactory.getResourceClass(type));
 
-    //todo: change or deprecate
-    @POST
-    @Path("nv/{type}")
-    public Response storeResource (@Context SecurityContext context,
-            @Context Locale locale,
-            @PathParam("type") String type,
-            @QueryParam("name") String name,
-            @QueryParam("description") String description,
-            // deprecate -> if you want to store a resource based on another, build the query first yourself or via a function
-            @QueryParam("ref") String reference,
-            @QueryParam("cache") Boolean cache,
-            @QueryParam("query") String query) {
-        TokenContext ctx = (TokenContext) context.getUserPrincipal();
-        cache = cache != null ? cache : false;
-        type = StringUtils.normalize(type);
-        reference = StringUtils.decodeHTML(reference);
-        Map vals = new HashMap();
-        User user;
-        Class ctype;
-        try {
-            ctype = ResourceFactory
-                    .getResourceClass(type);
-            user = controller.getUser(ctx.getUsername());
-        }
-        catch (KustvaktException e) {
-            jlog.error("Exception encountered: {}", e.string());
-            throw KustvaktResponseHandler.throwit(e);
-        }
-        if (VirtualCollection.class.equals(ctype)) {
-            VirtualCollection cachetmp, collection;
+			// todo ?!
+			KoralCollectionQueryBuilder query = new KoralCollectionQueryBuilder();
+			if (resource instanceof VirtualCollection) {
+				query.setBaseQuery(resource.getData());
+			} else if (resource instanceof Corpus) {
+				query.with(Attributes.CORPUS_SIGLE + "=" + resource.getName());
+			}
+			String res = query.toJSON();
+			String qstr = processor.processQuery(res, user);
+			return Response.ok(searchKrill.getStatistics(qstr)).build();
+		} catch (KustvaktException e) {
+			jlog.error("Exception encountered: {}", e.string());
+			throw KustvaktResponseHandler.throwit(e);
+		}
+	}
 
-            JsonNode base;
-            if (reference != null && !reference.equals("null")) {
-                try {
-                    base = resourceHandler.findbyStrId(reference, user,
-                            VirtualCollection.class).getData();
-                }
-                catch (KustvaktException e) {
-                    throw KustvaktResponseHandler.throwit(e);
-                }
+	/**
+	 * @param context
+	 * @param locale
+	 * @param json
+	 * @return
+	 */
+	// todo: rename
+	@POST
+	@Path("collection_raw")
+	public Response createRawCollection(@Context SecurityContext context, @Context Locale locale, String json) {
+		TokenContext c = (TokenContext) context.getUserPrincipal();
+		VirtualCollection cache = ResourceFactory.getCachedCollection(json);
+		User user;
+		try {
+			user = controller.getUser(c.getUsername());
+		} catch (KustvaktException e) {
+			jlog.error("Exception encountered: {}", e.string());
+			throw KustvaktResponseHandler.throwit(e);
+		}
 
-            }
-            else if (query != null)
-                base = JsonUtils.readTree(query);
-            else
-                // todo: throw exception response for no resource to save!
-                return null;
+		VirtualCollection tmp = resourceHandler.getCache(cache.getId(), VirtualCollection.class);
+		if (tmp == null) {
+			String query;
+			try {
+				query = this.processor.processQuery(cache.getData(), user);
+			} catch (KustvaktException e) {
+				throw KustvaktResponseHandler.throwit(e);
+			}
+			String stats = searchKrill.getStatistics(query);
+			cache.setStats(JsonUtils.readSimple(stats, Map.class));
+			resourceHandler.cache(cache);
+		} else
+			cache = tmp;
 
-            KoralCollectionQueryBuilder cquery = new KoralCollectionQueryBuilder();
-            cquery.setBaseQuery(base);
+		Map vals = new HashMap();
+		vals.put("id", cache.getId());
+		vals.put("statistics", cache.getStats());
+		return Response.ok(JsonUtils.toJSON(vals)).build();
+	}
 
-            cachetmp = ResourceFactory.getCachedCollection(cquery.toJSON());
+	@POST
+	@Path("{type}/{id}")
+	public Response updateResource(@Context SecurityContext context, @Context Locale locale,
+			@PathParam("type") String type, @PathParam("id") String id, String json) {
+		TokenContext ctx = (TokenContext) context.getUserPrincipal();
+		User user;
+		try {
+			user = controller.getUser(ctx.getUsername());
+			KustvaktResource resource = this.resourceHandler.findbyStrId(id, user,
+					ResourceFactory.getResourceClass(type));
+			JsonNode node = JsonUtils.readTree(json);
 
-            // see if collection was cached!
-            VirtualCollection tmp = resourceHandler.getCache(cachetmp.getId(),
-                    VirtualCollection.class);
-            // if not cached, fill with stats values
-            if (tmp == null) {
-                String stats = searchKrill.getStatistics(cquery.toJSON());
-                cachetmp.setStats(JsonUtils.readSimple(stats, Map.class));
-            }
+			if (node.isObject() && !node.path("name").isMissingNode()) {
+				String s = node.path("name").asText();
+				if (s.equals("null") || s.isEmpty())
+					throw KustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT, "Name must be set", "name");
+				resource.setName(s);
+			}
 
-            if (!cache) {
-                collection = ResourceFactory.getPermanentCollection(cachetmp,
-                        name, description);
-                vals = collection.toMap();
-                try {
-                    resourceHandler.storeResources(user, collection);
-                }
-                catch (KustvaktException e) {
-                    jlog.error("Exception encountered: {}", e.string());
-                    throw KustvaktResponseHandler.throwit(e);
-                }
-            }
-            else {
-                resourceHandler.cache(cachetmp);
-                vals = cachetmp.toMap();
-            }
-        }
-        return Response.ok(JsonUtils.toJSON(vals)).build();
-    }
+			if (node.isObject() && !node.path("description").isMissingNode())
+				resource.setDescription(node.path("description").asText());
+			this.resourceHandler.updateResources(user, resource);
+		} catch (KustvaktException e) {
+			jlog.error("Exception encountered: {}", e.string());
+			throw KustvaktResponseHandler.throwit(e);
+		}
+		return Response.ok().build();
+	}
 
+	// todo: change or deprecate
+	@POST
+	@Path("nv/{type}")
+	public Response storeResource(@Context SecurityContext context, @Context Locale locale,
+			@PathParam("type") String type, @QueryParam("name") String name,
+			@QueryParam("description") String description,
+			// deprecate -> if you want to store a resource based on another,
+			// build the query first yourself or via a function
+			@QueryParam("ref") String reference, @QueryParam("cache") Boolean cache,
+			@QueryParam("query") String query) {
+		TokenContext ctx = (TokenContext) context.getUserPrincipal();
+		cache = cache != null ? cache : false;
+		type = StringUtils.normalize(type);
+		reference = StringUtils.decodeHTML(reference);
+		Map vals = new HashMap();
+		User user;
+		Class ctype;
+		try {
+			ctype = ResourceFactory.getResourceClass(type);
+			user = controller.getUser(ctx.getUsername());
+		} catch (KustvaktException e) {
+			jlog.error("Exception encountered: {}", e.string());
+			throw KustvaktResponseHandler.throwit(e);
+		}
+		if (VirtualCollection.class.equals(ctype)) {
+			VirtualCollection cachetmp, collection;
 
-    /**
-     * store a virtual collection. Retrieve cached entry first and
-     * then store collection
-     * 
-     * @param context
-     * @param locale
-     * @param query
-     * @return
-     */
-    // todo: testing
-    @POST
-    @Path("{type}")
-    public Response storeResource (@Context SecurityContext context,
-            @Context Locale locale, @PathParam("type") String type,
-            @QueryParam("filter") Boolean filter,
-            @QueryParam("name") String name,
-            @QueryParam("description") String description,
-            @QueryParam("ref") String reference,
-            @QueryParam("cache") Boolean cache, String query) {
-        TokenContext ctx = (TokenContext) context.getUserPrincipal();
-        filter = filter != null ? filter : false;
-        cache = cache != null ? cache : false;
-        type = StringUtils.normalize(type);
-        reference = StringUtils.decodeHTML(reference);
-        Map vals = new HashMap();
-        User user;
-        Class ctype;
-        try {
-            ctype = ResourceFactory
-                    .getResourceClass(type);
+			JsonNode base;
+			if (reference != null && !reference.equals("null")) {
+				try {
+					base = resourceHandler.findbyStrId(reference, user, VirtualCollection.class).getData();
+				} catch (KustvaktException e) {
+					throw KustvaktResponseHandler.throwit(e);
+				}
 
-            user = controller.getUser(ctx.getUsername());
-        }
-        catch (KustvaktException e) {
-            jlog.error("Exception encountered: {}", e.string());
-            throw KustvaktResponseHandler.throwit(e);
-        }
+			} else if (query != null)
+				base = JsonUtils.readTree(query);
+			else
+				// todo: throw exception response for no resource to save!
+				return null;
 
-        if (VirtualCollection.class.equals(ctype)) {
-            VirtualCollection cachetmp, collection;
+			KoralCollectionQueryBuilder cquery = new KoralCollectionQueryBuilder();
+			cquery.setBaseQuery(base);
 
-            KoralCollectionQueryBuilder cquery = new KoralCollectionQueryBuilder();
-            if (reference != null && !reference.equals("null")) {
-                try {
-                    cquery.setBaseQuery(resourceHandler.findbyStrId(reference,
-                            user, VirtualCollection.class).getData());
+			cachetmp = ResourceFactory.getCachedCollection(cquery.toJSON());
 
-                }
-                catch (KustvaktException e) {
-                    throw KustvaktResponseHandler.throwit(e);
-                }
-            }
-            if (query != null && !query.isEmpty())
-                cquery.with(query);
+			// see if collection was cached!
+			VirtualCollection tmp = resourceHandler.getCache(cachetmp.getId(), VirtualCollection.class);
+			// if not cached, fill with stats values
+			if (tmp == null) {
+				String stats = searchKrill.getStatistics(cquery.toJSON());
+				cachetmp.setStats(JsonUtils.readSimple(stats, Map.class));
+			}
 
-            cachetmp = ResourceFactory.getCachedCollection(cquery.toJSON());
+			if (!cache) {
+				collection = ResourceFactory.getPermanentCollection(cachetmp, name, description);
+				vals = collection.toMap();
+				try {
+					resourceHandler.storeResources(user, collection);
+				} catch (KustvaktException e) {
+					jlog.error("Exception encountered: {}", e.string());
+					throw KustvaktResponseHandler.throwit(e);
+				}
+			} else {
+				resourceHandler.cache(cachetmp);
+				vals = cachetmp.toMap();
+			}
+		}
+		return Response.ok(JsonUtils.toJSON(vals)).build();
+	}
 
-            // see if vc was cached!
-            VirtualCollection tmp = resourceHandler.getCache(cachetmp.getId(),
-                    VirtualCollection.class);
+	/**
+	 * EM: store a virtual collection in a database, but /virtualcollection
+	 * service (@see
+	 * {@link #getResource(SecurityContext, Locale, String, String)}) does not
+	 * list it because the collection is not stored in the policy_store table as well.
+	 * 
+	 * Retrieve cached entry first and then store collection
+	 * 
+	 * @param context
+	 * @param locale
+	 * @param query
+	 * @return
+	 */
+	// todo: testing
+	@POST
+	@Path("{type}")
+	public Response storeResource(@Context SecurityContext context, @Context Locale locale,
+			@PathParam("type") String type, @QueryParam("filter") Boolean filter, @QueryParam("name") String name,
+			@QueryParam("description") String description, @QueryParam("ref") String reference,
+			@QueryParam("cache") Boolean cache, String query) {
+		TokenContext ctx = (TokenContext) context.getUserPrincipal();
+		filter = filter != null ? filter : false;
+		cache = cache != null ? cache : false;
+		type = StringUtils.normalize(type);
+		reference = StringUtils.decodeHTML(reference);
+		Map vals = new HashMap();
+		User user;
+		Class ctype;
+		try {
+			ctype = ResourceFactory.getResourceClass(type);
 
-            // if not cached, fill with stats values
-            if (tmp == null) {
-                String stats = searchKrill.getStatistics(cquery.toJSON());
-                cachetmp.setStats(JsonUtils.readSimple(stats, Map.class));
-            }
+			user = controller.getUser(ctx.getUsername());
+		} catch (KustvaktException e) {
+			jlog.error("Exception encountered: {}", e.string());
+			throw KustvaktResponseHandler.throwit(e);
+		}
 
-            if (!cache && !User.UserFactory.isDemo(ctx.getUsername())) {
-                collection = ResourceFactory.getPermanentCollection(cachetmp,
-                        name, description);
-                vals = collection.toMap();
-                try {
-                    resourceHandler.storeResources(user, collection);
-                }
-                catch (KustvaktException e) {
-                    jlog.error("Exception encountered: {}", e.string());
-                    throw KustvaktResponseHandler.throwit(e);
-                }
-            }
-            else {
-                resourceHandler.cache(cachetmp);
-                vals = cachetmp.toMap();
-            }
-        }
-        return Response.ok(JsonUtils.toJSON(vals)).build();
-    }
+		if (VirtualCollection.class.equals(ctype)) {
+			VirtualCollection cachetmp, collection;
 
+			KoralCollectionQueryBuilder cquery = new KoralCollectionQueryBuilder();
+			if (reference != null && !reference.equals("null")) {
+				try {
+					cquery.setBaseQuery(
+							resourceHandler.findbyStrId(reference, user, VirtualCollection.class).getData());
 
-    @DELETE
-    @Path("{type}/{id}/{child}")
-    public Response deleteResourceChild (@Context SecurityContext context,
-            @Context Locale locale, @PathParam("type") String type,
-            @PathParam("id") String id, @PathParam("child") String child) {
-        return deleteResource(context, locale, type,
-                StringUtils.joinResources(id, child));
-    }
+				} catch (KustvaktException e) {
+					throw KustvaktResponseHandler.throwit(e);
+				}
+			}
+			if (query != null && !query.isEmpty())
+				cquery.with(query);
 
+			cachetmp = ResourceFactory.getCachedCollection(cquery.toJSON());
 
-    @DELETE
-    @Path("{type}/{id}")
-    public Response deleteResource (@Context SecurityContext context,
-            @Context Locale locale, @PathParam("type") String type,
-            @PathParam("id") String id) {
-        TokenContext ctx = (TokenContext) context.getUserPrincipal();
-        type = StringUtils.normalizeHTML(type);
-        id = StringUtils.decodeHTML(id);
-        try {
-            User user = controller.getUser(ctx.getUsername());
-            KustvaktResource r = ResourceFactory.getResource(type);
-            r.setPersistentID(id);
-            //todo: eliminate the need to find the resource first!
-            resourceHandler.deleteResources(user, r);
-        }
-        catch (KustvaktException e) {
-            jlog.error("Exception encountered: {}", e.string());
-            throw KustvaktResponseHandler.throwit(e);
-        }
+			// see if vc was cached!
+			VirtualCollection tmp = resourceHandler.getCache(cachetmp.getId(), VirtualCollection.class);
 
-        return Response.ok().build();
-    }
+			// if not cached, fill with stats values
+			if (tmp == null) {
+				String stats = searchKrill.getStatistics(cquery.toJSON());
+				cachetmp.setStats(JsonUtils.readSimple(stats, Map.class));
+			}
 
+			if (!cache && !User.UserFactory.isDemo(ctx.getUsername())) {
+				collection = ResourceFactory.getPermanentCollection(cachetmp, name, description);
+				vals = collection.toMap();
+				try {
+					resourceHandler.storeResources(user, collection);
+				} catch (KustvaktException e) {
+					jlog.error("Exception encountered: {}", e.string());
+					throw KustvaktResponseHandler.throwit(e);
+				}
+			} else {
+				resourceHandler.cache(cachetmp);
+				vals = cachetmp.toMap();
+			}
+		}
+		return Response.ok(JsonUtils.toJSON(vals)).build();
+	}
 
-    //fixme: only allowed for corpus?!
-    @GET
-    @Path("/corpus/{id}/{docid}/{rest}/matchInfo")
-    public Response getMatchInfo (@Context SecurityContext ctx,
-            @Context Locale locale, @PathParam("id") String id,
-            @PathParam("docid") String docid, @PathParam("rest") String rest,
-            @QueryParam("foundry") Set<String> foundries,
-            @QueryParam("layer") Set<String> layers,
-            @QueryParam("spans") Boolean spans) {
-        TokenContext tokenContext = (TokenContext) ctx.getUserPrincipal();
-        spans = spans != null ? spans : false;
-        String matchid = searchKrill.getMatchId(id, docid, rest);
+	@DELETE
+	@Path("{type}/{id}/{child}")
+	public Response deleteResourceChild(@Context SecurityContext context, @Context Locale locale,
+			@PathParam("type") String type, @PathParam("id") String id, @PathParam("child") String child) {
+		return deleteResource(context, locale, type, StringUtils.joinResources(id, child));
+	}
 
-        if (layers == null || layers.isEmpty())
-            layers = new HashSet<>();
+	@DELETE
+	@Path("{type}/{id}")
+	public Response deleteResource(@Context SecurityContext context, @Context Locale locale,
+			@PathParam("type") String type, @PathParam("id") String id) {
+		TokenContext ctx = (TokenContext) context.getUserPrincipal();
+		type = StringUtils.normalizeHTML(type);
+		id = StringUtils.decodeHTML(id);
+		try {
+			User user = controller.getUser(ctx.getUsername());
+			KustvaktResource r = ResourceFactory.getResource(type);
+			r.setPersistentID(id);
+			// todo: eliminate the need to find the resource first!
+			resourceHandler.deleteResources(user, r);
+		} catch (KustvaktException e) {
+			jlog.error("Exception encountered: {}", e.string());
+			throw KustvaktResponseHandler.throwit(e);
+		}
 
-        boolean match_only = foundries == null || foundries.isEmpty();
+		return Response.ok().build();
+	}
 
-        User user;
-        try {
-            user = controller.getUser(tokenContext.getUsername());
-        }
-        catch (KustvaktException e) {
+	// fixme: only allowed for corpus?!
+	@GET
+	@Path("/corpus/{id}/{docid}/{rest}/matchInfo")
+	public Response getMatchInfo(@Context SecurityContext ctx, @Context Locale locale, @PathParam("id") String id,
+			@PathParam("docid") String docid, @PathParam("rest") String rest,
+			@QueryParam("foundry") Set<String> foundries, @QueryParam("layer") Set<String> layers,
+			@QueryParam("spans") Boolean spans) {
+		TokenContext tokenContext = (TokenContext) ctx.getUserPrincipal();
+		spans = spans != null ? spans : false;
+		String matchid = searchKrill.getMatchId(id, docid, rest);
 
-            jlog.error("Exception encountered: {}", e.string());
-            throw KustvaktResponseHandler.throwit(e);
-        }
+		if (layers == null || layers.isEmpty())
+			layers = new HashSet<>();
 
-        String results;
-        // fixme: checks for policy matching
-        // fixme: currently disabled, due to mishab in foundry/layer spec
-        // fixme:
-        if (foundries != null && foundries.size() > 1000) {
-            Set<String> f_list = new HashSet<>();
-            Set<String> l_list = new HashSet<>();
+		boolean match_only = foundries == null || foundries.isEmpty();
 
-            for (String spl : new ArrayList<>(foundries)) {
-                try {
-                    de.ids_mannheim.korap.security.ac.SecurityManager manager = SecurityManager
-                            .init(spl, user, Permissions.Permission.READ);
-                    if (!manager.isAllowed())
-                        continue;
+		User user;
+		try {
+			user = controller.getUser(tokenContext.getUsername());
+		} catch (KustvaktException e) {
 
-                    String[] sep = StringUtils.splitAnnotations(spl);
-                    if (spl != null) {
-                        f_list.add(sep[0]);
-                        l_list.add(sep[1]);
-                    };
-                    results = searchKrill.getMatch(matchid, new ArrayList<>(
-                            f_list), new ArrayList<>(l_list), spans, false,
-                            true);
-                }
-                catch (EmptyResultException e) {
-                    throw KustvaktResponseHandler.throwit(
-                            StatusCodes.NO_VALUE_FOUND, "Resource not found!",
-                            id);
-                }
-                catch (NotAuthorizedException e) {
-                    throw KustvaktResponseHandler.throwit(
-                            StatusCodes.ACCESS_DENIED, "Permission denied",
-                            id);
-                }
+			jlog.error("Exception encountered: {}", e.string());
+			throw KustvaktResponseHandler.throwit(e);
+		}
 
-            }
-            // all foundries shall be returned
-        }
-        else if (foundries != null && foundries.contains("*")) {
-            Set<Layer> resources;
-            try {
-                resources = ResourceFinder.search(user, Layer.class);
-            }
-            catch (KustvaktException e) {
-                jlog.error("Exception encountered: {}", e.string());
-                throw KustvaktResponseHandler.throwit(e);
-            }
-            // returns foundries and layers.
-            // todo: needs testing!
-            foundries = new HashSet<>();
-            layers = new HashSet<>();
-            for (Layer r : resources) {
-                String[] spl = StringUtils.splitAnnotations(r.getName());
-                if (spl != null) {
-                    foundries.add(spl[0]);
-                    layers.add(spl[1]);
-                }
-            }
-        }
-        try {
-            if (!match_only)
-                results = searchKrill
-                        .getMatch(matchid, new ArrayList<>(foundries),
-                                new ArrayList<>(layers), spans, false, true);
-            else
-                results = searchKrill.getMatch(matchid);
-        }
-        catch (Exception e) {
-            jlog.error("Exception encountered!", e);
-            throw KustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT,
-                    e.getMessage(), "");
-        }
-        return Response.ok(results).build();
-    }
+		String results;
+		// fixme: checks for policy matching
+		// fixme: currently disabled, due to mishab in foundry/layer spec
+		// fixme:
+		if (foundries != null && foundries.size() > 1000) {
+			Set<String> f_list = new HashSet<>();
+			Set<String> l_list = new HashSet<>();
 
+			for (String spl : new ArrayList<>(foundries)) {
+				try {
+					de.ids_mannheim.korap.security.ac.SecurityManager manager = SecurityManager.init(spl, user,
+							Permissions.Permission.READ);
+					if (!manager.isAllowed())
+						continue;
 
-    // todo:?!
-    @POST
-    @Path("match/{id}")
-    @Deprecated
-    public Response save (@PathParam("{id}") String id,
-            @QueryParam("d") String description,
-            @Context SecurityContext context) {
-        TokenContext ctx = (TokenContext) context.getUserPrincipal();
-        // save match for user and later retrieval!
+					String[] sep = StringUtils.splitAnnotations(spl);
+					if (spl != null) {
+						f_list.add(sep[0]);
+						l_list.add(sep[1]);
+					}
+					;
+					results = searchKrill.getMatch(matchid, new ArrayList<>(f_list), new ArrayList<>(l_list), spans,
+							false, true);
+				} catch (EmptyResultException e) {
+					throw KustvaktResponseHandler.throwit(StatusCodes.NO_VALUE_FOUND, "Resource not found!", id);
+				} catch (NotAuthorizedException e) {
+					throw KustvaktResponseHandler.throwit(StatusCodes.ACCESS_DENIED, "Permission denied", id);
+				}
 
-        //        KustvaktResource match = new QueryMatch(id);
-        //        match.setDescription(description);
-        //        match.setCreated(TimeUtils.getNow().getMillis());
-        //        try {
-        //            this.resourceHandler.storeResources(controller.getUser(ctx), match);
-        //        } catch (KustvaktException | NotAuthorizedException e) {
-        //            throw MappedHTTPResponse.throwit(e);
-        //        }
+			}
+			// all foundries shall be returned
+		} else if (foundries != null && foundries.contains("*")) {
+			Set<Layer> resources;
+			try {
+				resources = ResourceFinder.search(user, Layer.class);
+			} catch (KustvaktException e) {
+				jlog.error("Exception encountered: {}", e.string());
+				throw KustvaktResponseHandler.throwit(e);
+			}
+			// returns foundries and layers.
+			// todo: needs testing!
+			foundries = new HashSet<>();
+			layers = new HashSet<>();
+			for (Layer r : resources) {
+				String[] spl = StringUtils.splitAnnotations(r.getName());
+				if (spl != null) {
+					foundries.add(spl[0]);
+					layers.add(spl[1]);
+				}
+			}
+		}
+		try {
+			if (!match_only)
+				results = searchKrill.getMatch(matchid, new ArrayList<>(foundries), new ArrayList<>(layers), spans,
+						false, true);
+			else
+				results = searchKrill.getMatch(matchid);
+		} catch (Exception e) {
+			jlog.error("Exception encountered!", e);
+			throw KustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT, e.getMessage(), "");
+		}
+		return Response.ok(results).build();
+	}
 
-        return Response.ok().build();
-    }
+	// todo:?!
+	@POST
+	@Path("match/{id}")
+	@Deprecated
+	public Response save(@PathParam("{id}") String id, @QueryParam("d") String description,
+			@Context SecurityContext context) {
+		TokenContext ctx = (TokenContext) context.getUserPrincipal();
+		// save match for user and later retrieval!
 
+		// KustvaktResource match = new QueryMatch(id);
+		// match.setDescription(description);
+		// match.setCreated(TimeUtils.getNow().getMillis());
+		// try {
+		// this.resourceHandler.storeResources(controller.getUser(ctx), match);
+		// } catch (KustvaktException | NotAuthorizedException e) {
+		// throw MappedHTTPResponse.throwit(e);
+		// }
 
-    @GET
-    @Path("matches")
-    @Deprecated
-    public Response get (@Context SecurityContext context) {
-        TokenContext ctx = (TokenContext) context.getUserPrincipal();
-        //todo save match for user and later retrieval!
-        //todo: retrieve matches in range! --choices: date, document, id (matchid)
-        return Response.ok().build();
-    }
+		return Response.ok().build();
+	}
 
+	@GET
+	@Path("matches")
+	@Deprecated
+	public Response get(@Context SecurityContext context) {
+		TokenContext ctx = (TokenContext) context.getUserPrincipal();
+		// todo save match for user and later retrieval!
+		// todo: retrieve matches in range! --choices: date, document, id
+		// (matchid)
+		return Response.ok().build();
+	}
 
-    @DELETE
-    @Path("match/{id}")
-    @Deprecated
-    public Response remove (@PathParam("{id}") String id,
-            @Context SecurityContext context) {
-        TokenContext ctx = (TokenContext) context.getUserPrincipal();
-        // save match for user and later retrieval!
-        try {
-            this.resourceHandler.deleteResources(
-                    this.controller.getUser(ctx.getUsername()), id);
-        }
-        catch (KustvaktException e) {
-            jlog.error("Exception encountered: {}", e.string());
-            throw KustvaktResponseHandler.throwit(e);
-        }
+	@DELETE
+	@Path("match/{id}")
+	@Deprecated
+	public Response remove(@PathParam("{id}") String id, @Context SecurityContext context) {
+		TokenContext ctx = (TokenContext) context.getUserPrincipal();
+		// save match for user and later retrieval!
+		try {
+			this.resourceHandler.deleteResources(this.controller.getUser(ctx.getUsername()), id);
+		} catch (KustvaktException e) {
+			jlog.error("Exception encountered: {}", e.string());
+			throw KustvaktResponseHandler.throwit(e);
+		}
 
-        return Response.ok().build();
-    }
+		return Response.ok().build();
+	}
 
 }
diff --git a/src/test/java/de/ids_mannheim/korap/web/service/full/ResouceServiceServerTest.java b/src/test/java/de/ids_mannheim/korap/web/service/full/ResouceServiceServerTest.java
new file mode 100644
index 0000000..3e16f22
--- /dev/null
+++ b/src/test/java/de/ids_mannheim/korap/web/service/full/ResouceServiceServerTest.java
@@ -0,0 +1,113 @@
+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 java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.impl.client.HttpClients;
+import org.junit.Assert;
+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.config.BeanConfigTest;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.handlers.ResourceDao;
+import de.ids_mannheim.korap.resources.KustvaktResource;
+import de.ids_mannheim.korap.security.auth.BasicHttpAuth;
+import de.ids_mannheim.korap.user.User;
+import de.ids_mannheim.korap.utils.JsonUtils;
+
+/**
+ * This class tests services of a running Kustvakt server with a MySQL database. 
+ * Please check the database configuration in src/main/resources/jdbc.properties 
+ * and run the server before running the tests.
+ * 
+ * See {@link ResourceServiceTest} for tests using an in-memory database.
+ * 
+ * @author margaretha
+ *
+ */
+public class ResouceServiceServerTest extends BeanConfigTest{
+
+	@Test
+	public void testWrongAuthorization() throws IOException, URISyntaxException {
+		HttpResponse response = testResourceStore("wezrowerowj");
+		assertEquals(ClientResponse.Status.UNAUTHORIZED.getStatusCode(), response.getStatusLine().getStatusCode());
+	}
+
+	@Test
+	public void testCorrectAuthorization() throws IOException, URISyntaxException, KustvaktException {
+
+		HttpResponse response = testResourceStore("kustvakt2015");
+		HttpEntity entity = response.getEntity();
+		String content = null;
+
+		if (entity != null) {
+			InputStream is = entity.getContent();
+			try {
+				content = IOUtils.toString(is, "UTF-8");
+			} finally {
+				is.close();
+			}
+		}
+
+		assertEquals(ClientResponse.Status.OK.getStatusCode(), response.getStatusLine().getStatusCode());
+
+		JsonNode node = JsonUtils.readTree(content);
+		assertNotNull(node);
+		assertTrue(node.isObject());
+		assertEquals("Goethe", node.path("name").asText());
+		assertEquals("Goethe corpus", node.path("description").asText());
+		
+		//checkResourceInDB(node.path("id").asText());
+	}
+
+	public HttpResponse testResourceStore(String password) throws IOException, URISyntaxException {
+
+		HttpClient httpclient = HttpClients.createDefault();
+		URIBuilder builder = new URIBuilder();
+		builder.setScheme("http").setHost("localhost").setPort(8089).setPath("/api/v0.1/virtualcollection")
+				.setParameter("filter", "httpclient").setParameter("name", "Goethe")
+				.setParameter("description", "Goethe corpus");
+		URI uri = builder.build();
+		HttpPost httppost = new HttpPost(uri);
+		httppost.addHeader(Attributes.AUTHORIZATION, BasicHttpAuth.encode("kustvakt", password));
+		return httpclient.execute(httppost);
+
+	}
+	
+	private void checkResourceInDB(String id) throws KustvaktException {
+		
+		ResourceDao<?> dao = new ResourceDao<>(helper().getContext()
+                .getPersistenceClient());
+        assertEquals("sqlite", helper().getContext().getPersistenceClient()
+                .getDatabase());
+
+        assertNotEquals(0, dao.size());
+        KustvaktResource res = dao.findbyId(id,
+                User.UserFactory.getDemoUser());
+        assertNotNull(res);
+        Assert.assertEquals(true,res.getField("testVar").toString().startsWith("testVal_"));
+	}
+
+	@Override
+	public void initMethod() throws KustvaktException {
+		// TODO Auto-generated method stub
+		
+	}
+}
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 c541e7a..07e1382 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
@@ -1,25 +1,26 @@
 package de.ids_mannheim.korap.web.service.full;
 
-import com.fasterxml.jackson.databind.JsonNode;
-import com.sun.jersey.api.client.ClientResponse;
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.query.serialize.QuerySerializer;
-import de.ids_mannheim.korap.resources.Corpus;
-import de.ids_mannheim.korap.resources.KustvaktResource;
-import de.ids_mannheim.korap.security.ac.ResourceHandler;
-import de.ids_mannheim.korap.security.auth.BasicHttpAuth;
-import de.ids_mannheim.korap.config.Attributes;
-import de.ids_mannheim.korap.user.User;
-import de.ids_mannheim.korap.utils.JsonUtils;
-import de.ids_mannheim.korap.web.service.FastJerseyTest;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+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 java.util.Iterator;
-import java.util.Set;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.sun.jersey.api.client.ClientResponse;
 
-import static org.junit.Assert.*;
+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
@@ -319,6 +320,26 @@
     @Test
     public void testResourceStore () {
 
+        ClientResponse response = resource()
+                .path(getAPIVersion())
+                .path("virtualcollection")
+                .queryParam("filter", "false")
+                .queryParam("name", "Goethe")
+                .queryParam("description", "Goethe corpus")
+                .header(Attributes.AUTHORIZATION,
+                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
+                .post(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("Goethe", node.path("name").asText());
+        assertEquals("Goethe corpus", node.path("description").asText());
     }
 
 
