Fixed policy validity. Added policy and resource tests.

Change-Id: I4a8f40f0bcfb0d13d2e904a641048d98f6e26d89
diff --git a/pom.xml b/pom.xml
index bab503a..4594c94 100644
--- a/pom.xml
+++ b/pom.xml
@@ -176,7 +176,7 @@
                     <excludes>
                         <exclude>**/*APITest.java</exclude>
                         <exclude>de/ids_mannheim/korap/suites/*.java</exclude>
-                		<exclude>**/ResouceServiceServerTest.java</exclude>
+                		<exclude>**/KustvaktServerTest.java</exclude>
                     </excludes>
                     <includes>
                         <include>de/ids_mannheim/korap/**/*.java</include>
diff --git a/src/main/java/de/ids_mannheim/korap/interfaces/db/PolicyHandlerIface.java b/src/main/java/de/ids_mannheim/korap/interfaces/db/PolicyHandlerIface.java
index 8c55953..fe20a25 100644
--- a/src/main/java/de/ids_mannheim/korap/interfaces/db/PolicyHandlerIface.java
+++ b/src/main/java/de/ids_mannheim/korap/interfaces/db/PolicyHandlerIface.java
@@ -1,6 +1,7 @@
 package de.ids_mannheim.korap.interfaces.db;
 
 import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.resources.Foundry;
 import de.ids_mannheim.korap.resources.KustvaktResource;
 import de.ids_mannheim.korap.security.Parameter;
 import de.ids_mannheim.korap.security.PolicyCondition;
@@ -36,7 +37,9 @@
 
     List<SecurityPolicy> getPolicies (PolicyCondition condition,
             Class<? extends KustvaktResource> clazz, Byte perm);
-
+    
+    List<SecurityPolicy> getPoliciesByPersistentId (PolicyCondition policyCondition,
+            Class<? extends KustvaktResource> clazz, byte perm, String id);
 
     /**
      * @param policy
@@ -196,4 +199,5 @@
 
     int size ();
 
+
 }
diff --git a/src/main/java/de/ids_mannheim/korap/security/ac/PolicyDao.java b/src/main/java/de/ids_mannheim/korap/security/ac/PolicyDao.java
index 6ab19bf..43c4ea9 100644
--- a/src/main/java/de/ids_mannheim/korap/security/ac/PolicyDao.java
+++ b/src/main/java/de/ids_mannheim/korap/security/ac/PolicyDao.java
@@ -5,6 +5,7 @@
 import de.ids_mannheim.korap.exceptions.dbException;
 import de.ids_mannheim.korap.interfaces.db.PersistenceClient;
 import de.ids_mannheim.korap.interfaces.db.PolicyHandlerIface;
+import de.ids_mannheim.korap.resources.Foundry;
 import de.ids_mannheim.korap.resources.KustvaktResource;
 import de.ids_mannheim.korap.resources.ResourceFactory;
 import de.ids_mannheim.korap.security.Parameter;
@@ -98,8 +99,7 @@
         }
         catch (DataAccessException e) {
             e.printStackTrace();
-            jlog.error(
-                    "Operation (INSERT) not possible for '{}' for user '{}'",
+            jlog.error("Operation (INSERT) not possible for '{}' for user '{}'",
                     policy.toString(), user.getId());
             throw new dbException(user.getId(), "policy_store",
                     StatusCodes.DB_INSERT_FAILED, policy.toString());
@@ -117,7 +117,8 @@
      */
     // benchmark this!
     @Override
-    public void mapConstraints (SecurityPolicy policy) throws KustvaktException {
+    public void mapConstraints (SecurityPolicy policy)
+            throws KustvaktException {
         final String cond = "INSERT INTO group_ref (group_id, policy_id) VALUES (:group, :policyID);";
         final String remove = "DELETE FROM group_ref WHERE group_id=:group and policy_id=:policyID;";
         try {
@@ -128,8 +129,8 @@
                         .getRemoved().size()];
                 for (Integer toremove : policy.getRemoved()) {
                     MapSqlParameterSource source = new MapSqlParameterSource();
-                    source.addValue("group", conditions.get(toremove)
-                            .getSpecifier());
+                    source.addValue("group",
+                            conditions.get(toremove).getSpecifier());
                     source.addValue("policyID", policy.getID());
                     sources_removed[idx++] = source;
                 }
@@ -143,7 +144,8 @@
                         .getAdded().size()];
                 for (Integer add : policy.getAdded()) {
                     MapSqlParameterSource source = new MapSqlParameterSource();
-                    source.addValue("group", conditions.get(add).getSpecifier());
+                    source.addValue("group",
+                            conditions.get(add).getSpecifier());
                     source.addValue("policyID", policy.getID());
                     sources[idx++] = source;
                 }
@@ -173,17 +175,17 @@
 
             try {
                 final Integer[] results = new Integer[2];
-                jdbcTemplate
-                        .query("SELECT COUNT(*) as total, (select count(*) from group_users where user_id=:userid and "
+                jdbcTemplate.query(
+                        "SELECT COUNT(*) as total, (select count(*) from group_users where user_id=:userid and "
                                 + "group_id=:name) as users FROM group_store WHERE name=:name",
-                                param, new RowCallbackHandler() {
-                                    @Override
-                                    public void processRow (ResultSet rs)
-                                            throws SQLException {
-                                        results[0] = rs.getInt("total");
-                                        results[1] = rs.getInt("users");
-                                    }
-                                });
+                        param, new RowCallbackHandler() {
+                            @Override
+                            public void processRow (ResultSet rs)
+                                    throws SQLException {
+                                results[0] = rs.getInt("total");
+                                results[1] = rs.getInt("users");
+                            }
+                        });
 
                 boolean admin = false;
                 if (results[0] == 0) {
@@ -191,8 +193,8 @@
                     this.createCondition(cond, user);
                 }
                 if (results[1] == 0)
-                    this.addToCondition(Arrays.asList(user.getUsername()),
-                            cond, admin);
+                    this.addToCondition(Arrays.asList(user.getUsername()), cond,
+                            admin);
             }
             catch (DataAccessException e) {
                 jlog.error(
@@ -282,6 +284,50 @@
         }
     }
 
+    // EM: should only return one policy
+    @Override
+    public List<SecurityPolicy> getPoliciesByPersistentId (
+            PolicyCondition condition, Class<? extends KustvaktResource> clazz, byte perm,
+            String persistentId) {
+
+        MapSqlParameterSource param = new MapSqlParameterSource();
+        param.addValue("cond", condition.getSpecifier());
+        param.addValue("perm", perm);
+        param.addValue("type", ResourceFactory.getResourceMapping(clazz));
+        param.addValue("en", TimeUtils.getNow().getMillis());
+        param.addValue("persistentId", persistentId);
+        String sql_new = "select pv.*, pv.perm & :perm as allowed, "
+                + "rh.depth, (select max(depth) from resource_tree "
+                + "where child_id=rh.child_id) as max_depth from policy_view as pv "
+                + "inner join resource_tree as rh on rh.parent_id=pv.id "
+                + "where "
+                + "pv.persistent_id =:persistentId and "
+                + "pv.enable <= :en and (pv.expire > :en or pv.expire is NULL) and "
+                + "pv.group_id=:cond and pv.type=:type";
+
+        try {
+            return this.jdbcTemplate.query(sql_new, param,
+                    new ResultSetExtractor<List<SecurityPolicy>>() {
+
+                        @Override
+                        public List<SecurityPolicy> extractData (ResultSet rs)
+                                throws SQLException, DataAccessException {
+                            List<SecurityPolicy> policies = SecurityRowMappers
+                                    .mapConditionPolicies(rs);
+                            if (policies.size() > 1)
+                                jlog.warn(
+                                        "Policy ids are not uniques. Found more than one policy for id:"
+                                                + policies.get(0).getID());
+                            return policies;
+                        }
+                    });
+        }
+        catch (DataAccessException e) {
+            jlog.error(e.getLocalizedMessage());
+            return Collections.emptyList();
+        }
+    }
+
 
     @Override
     public List<SecurityPolicy>[] getPolicies (String target, final User user,
@@ -290,7 +336,7 @@
         param.addValue("target", target);
         param.addValue("userid", user.getId());
         param.addValue("perm", perm);
-        param.addValue("en",TimeUtils.getNow().getMillis());
+        param.addValue("en", TimeUtils.getNow().getMillis());
 
         String sql_new = "select pv.*, pv.perm & :perm as allowed, "
                 + "rh.depth, (select max(depth) from resource_tree "
@@ -491,6 +537,7 @@
     // todo: access to leave node also means that the path to the root for that permission is allowed,
     // todo: thus all upper resource access is as well allowed
 
+
     //todo: remove not used context?! --> who is allowed to do so?
     @Override
     public int deletePolicy (SecurityPolicy policy, User user)
@@ -499,14 +546,13 @@
         param.addValue("id", policy.getID());
 
         try {
-            this.jdbcTemplate.update(
-                    "DELETE FROM group_ref WHERE policy_id=:id", param);
-            return this.jdbcTemplate.update(
-                    "DELETE FROM policy_store WHERE id=:id", param);
+            this.jdbcTemplate
+                    .update("DELETE FROM group_ref WHERE policy_id=:id", param);
+            return this.jdbcTemplate
+                    .update("DELETE FROM policy_store WHERE id=:id", param);
         }
         catch (DataAccessException e) {
-            jlog.error(
-                    "Operation (DELETE) not possible for '{}' for user '{}'",
+            jlog.error("Operation (DELETE) not possible for '{}' for user '{}'",
                     policy.toString(), user.getId());
             throw new dbException(user.getId(), "policy_store, group_ref",
                     StatusCodes.DB_DELETE_FAILED, policy.toString());
@@ -524,8 +570,7 @@
             return this.jdbcTemplate.update(sql, param);
         }
         catch (DataAccessException e) {
-            jlog.error(
-                    "Operation (DELETE) not possible for '{}' for user '{}'",
+            jlog.error("Operation (DELETE) not possible for '{}' for user '{}'",
                     id, user.getId());
             throw new dbException(user.getId(), "policy_store",
                     StatusCodes.DB_DELETE_FAILED, id);
@@ -549,8 +594,7 @@
             return result;
         }
         catch (DataAccessException e) {
-            jlog.error(
-                    "Operation (UPDATE) not possible for '{}' for user '{}'",
+            jlog.error("Operation (UPDATE) not possible for '{}' for user '{}'",
                     policy.toString(), user.getId());
             throw new dbException(user.getId(), "policy_store",
                     StatusCodes.DB_UPDATE_FAILED, policy.toString());
@@ -572,8 +616,7 @@
             return this.jdbcTemplate.queryForObject(sql1, param, Integer.class);
         }
         catch (DataAccessException e) {
-            jlog.error(
-                    "Operation (SELECT) not possible for '{}' for user '{}'",
+            jlog.error("Operation (SELECT) not possible for '{}' for user '{}'",
                     policy.getTarget(), user.getId());
             throw new dbException(user.getId(), "policy_store",
                     StatusCodes.DB_GET_FAILED, policy.toString());
@@ -614,8 +657,7 @@
             return this.jdbcTemplate.queryForObject(sql, param, Integer.class);
         }
         catch (DataAccessException e) {
-            jlog.error(
-                    "Operation (SELECT) not possible for '{}' for user '{}'",
+            jlog.error("Operation (SELECT) not possible for '{}' for user '{}'",
                     group, user.getId());
             throw new dbException(user.getId(), "policy_store",
                     StatusCodes.DB_GET_FAILED, group);
@@ -633,8 +675,8 @@
         param.addValue("sy", condition.getFlags().get(Attributes.SYM_USE));
         param.addValue("ex", condition.getFlags().get(Attributes.LICENCE));
         try {
-            this.jdbcTemplate.update(
-                    "INSERT INTO group_store (name, sym_use, export, commercial) "
+            this.jdbcTemplate
+                    .update("INSERT INTO group_store (name, sym_use, export, commercial) "
                             + "VALUES (:name, :sy, :ex, :com);", param);
         }
         catch (DataAccessException e) {
@@ -662,7 +704,8 @@
         }
         catch (DataAccessException e) {
             //todo: test with mysql
-            if (!e.getMessage().toLowerCase().contains("UNIQUE".toLowerCase())) {
+            if (!e.getMessage().toLowerCase()
+                    .contains("UNIQUE".toLowerCase())) {
                 jlog.error(
                         "Operation (INSERT) not possible for '{}' for user '{}'",
                         condition.toString(), username);
@@ -731,8 +774,8 @@
                 throw new KustvaktException(
                         "Operation (INSERT) not possible for '"
                                 + condition.toString() + "' for user '"
-                                + usernames + "'", e,
-                        StatusCodes.CONNECTION_ERROR);
+                                + usernames + "'",
+                        e, StatusCodes.CONNECTION_ERROR);
             }
             return null;
         }
@@ -759,8 +802,7 @@
             this.jdbcTemplate.batchUpdate(del, sources);
         }
         catch (DataAccessException e) {
-            jlog.error(
-                    "Operation (DELETE) not possible for '{}' for user '{}'",
+            jlog.error("Operation (DELETE) not possible for '{}' for user '{}'",
                     condition.toString(), usernames);
             throw new KustvaktException(e, StatusCodes.CONNECTION_ERROR);
         }
@@ -813,7 +855,8 @@
         MapSqlParameterSource source = new MapSqlParameterSource();
         source.addValue("key", key);
         final String select = "SELECT COUNT(*) FROM param_store WHERE p_key=:key;";
-        return this.jdbcTemplate.queryForObject(select, source, Integer.class) == 1;
+        return this.jdbcTemplate.queryForObject(select, source,
+                Integer.class) == 1;
     }
 
 
@@ -859,5 +902,4 @@
             return 0;
         }
     }
-
 }
diff --git a/src/main/java/de/ids_mannheim/korap/web/service/full/AdminService.java b/src/main/java/de/ids_mannheim/korap/web/service/full/AdminService.java
index d1a3162..d3694b8 100644
--- a/src/main/java/de/ids_mannheim/korap/web/service/full/AdminService.java
+++ b/src/main/java/de/ids_mannheim/korap/web/service/full/AdminService.java
@@ -1,9 +1,7 @@
 package de.ids_mannheim.korap.web.service.full;
 
-import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
@@ -14,7 +12,6 @@
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
-import javax.ws.rs.core.SecurityContext;
 
 import org.joda.time.DateTime;
 import org.slf4j.Logger;
@@ -24,12 +21,10 @@
 import com.sun.jersey.spi.container.ResourceFilters;
 
 import de.ids_mannheim.korap.auditing.AuditRecord;
-import de.ids_mannheim.korap.config.Attributes;
 import de.ids_mannheim.korap.config.BeansFactory;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.handlers.DocumentDao;
-import de.ids_mannheim.korap.interfaces.AuthenticationManagerIface;
 import de.ids_mannheim.korap.interfaces.db.AuditingIface;
 import de.ids_mannheim.korap.resources.Document;
 import de.ids_mannheim.korap.resources.KustvaktResource;
@@ -37,7 +32,6 @@
 import de.ids_mannheim.korap.resources.ResourceFactory;
 import de.ids_mannheim.korap.security.PolicyCondition;
 import de.ids_mannheim.korap.security.ac.PolicyBuilder;
-import de.ids_mannheim.korap.user.TokenContext;
 import de.ids_mannheim.korap.user.User;
 import de.ids_mannheim.korap.utils.JsonUtils;
 import de.ids_mannheim.korap.utils.TimeUtils;
@@ -47,7 +41,9 @@
 import de.ids_mannheim.korap.web.utils.KustvaktResponseHandler;
 
 /**
- * Created by hanl on 6/11/14.
+ * @author hanl, margaretha 
+ * Created date 6/11/14. 
+ * Last update: 04/2017
  */
 @Path(KustvaktServer.API_VERSION + "/admin")
 @ResourceFilters({ AdminFilter.class, PiwikFilter.class })
@@ -56,7 +52,6 @@
 
     private static Logger jlog = LoggerFactory.getLogger(AdminService.class);
 
-    private AuthenticationManagerIface authManager;
     private AuditingIface auditingController;
     private DocumentDao documentDao;
 
@@ -64,13 +59,11 @@
     public AdminService () {
         this.auditingController = BeansFactory.getKustvaktContext()
                 .getAuditingProvider();
-        this.authManager = BeansFactory.getKustvaktContext()
-                .getAuthenticationManager();
-        this.documentDao = new DocumentDao(BeansFactory.getKustvaktContext()
-                .getPersistenceClient());
+        this.documentDao = new DocumentDao(
+                BeansFactory.getKustvaktContext().getPersistenceClient());
     }
 
-
+    // EM: not documented and tested, not sure what the purpose of the service is
     @GET
     @Path("audit/{type}")
     public Response getAudits (@PathParam("type") String type,
@@ -111,8 +104,41 @@
             @QueryParam("description") String description,
             @QueryParam("group") String group,
             @QueryParam("perm") List<String> permissions,
-            @QueryParam("loc") String loc, @QueryParam("expire") String duration, 
-            @Context HttpContext context) {
+            @QueryParam("loc") String loc,
+            @QueryParam("expire") String duration, @Context HttpContext context)
+            throws KustvaktException {
+
+        if (type == null | type.isEmpty()) {
+            KustvaktException e = new KustvaktException(
+                    StatusCodes.MISSING_ARGUMENT,
+                    "The value of parameter type is missing.");
+            throw KustvaktResponseHandler.throwit(e);
+        }
+        else if (name == null | name.isEmpty()) {
+            KustvaktException e = new KustvaktException(
+                    StatusCodes.MISSING_ARGUMENT,
+                    "The value of parameter name is missing.");
+            throw KustvaktResponseHandler.throwit(e);
+        }
+        else if (description == null | description.isEmpty()) {
+            KustvaktException e = new KustvaktException(
+                    StatusCodes.MISSING_ARGUMENT,
+                    "The value of parameter description is missing.");
+            throw KustvaktResponseHandler.throwit(e);
+        }
+        else if (group == null | group.isEmpty()) {
+            KustvaktException e = new KustvaktException(
+                    StatusCodes.MISSING_ARGUMENT,
+                    "The value of parameter group is missing.");
+            throw KustvaktResponseHandler.throwit(e);
+        }
+        else if (permissions == null | permissions.isEmpty()) {
+            KustvaktException e = new KustvaktException(
+                    StatusCodes.MISSING_ARGUMENT,
+                    "The value of parameter permissions is missing.");
+            throw KustvaktResponseHandler.throwit(e);
+        }
+
 
         try {
             KustvaktResource resource = ResourceFactory.getResource(type);
@@ -120,22 +146,23 @@
             resource.setDescription(description);
             resource.setName(name);
 
-            Permissions.Permission[] p = Permissions.read(permissions
-                    .toArray(new String[0]));
-          
+            Permissions.Permission[] p = Permissions
+                    .read(permissions.toArray(new String[0]));
+
             User user = (User) context.getProperties().get("user");
-        	
+
             PolicyBuilder pb = new PolicyBuilder(user)
                     .setConditions(new PolicyCondition(group))
                     .setResources(resource);
-            
-            if (loc != null && !loc.isEmpty())
+
+            if (loc != null && !loc.isEmpty()){
                 pb.setLocation(loc);
-
-            if (duration != null && !duration.isEmpty())
-                pb.setContext(TimeUtils.getNow().getMillis(),
-                        TimeUtils.convertTimeToSeconds(duration));
-
+            }
+            if (duration != null && !duration.isEmpty()){
+                long now = TimeUtils.getNow().getMillis();
+                pb.setContext(now,
+                        now + TimeUtils.convertTimeToSeconds(duration));
+            }
             pb.setPermissions(p);
             pb.create();
         }
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 feee22e..5eb8f1b 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
@@ -64,976 +64,1140 @@
 import de.ids_mannheim.korap.web.utils.KustvaktResponseHandler;
 
 /**
- * @author hanl
+ * @author hanl, margaretha
  * @date 29/01/2014
+ *       update 04/2017
  */
 @Path(KustvaktServer.API_VERSION + "/")
 @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());
 
-		this.processor = new RewriteHandler();
-		this.processor.defaultRewriteConstraints();
-		this.processor.insertBeans(BeansFactory.getKustvaktContext());
-	}
+    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());
 
-	/**
-	 * 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);
+        this.processor = new RewriteHandler();
+        this.processor.defaultRewriteConstraints();
+        this.processor.insertBeans(BeansFactory.getKustvaktContext());
+    }
 
-		try {
-			Class cl_type = ResourceFactory.getResourceClass(type);
-			if (cl_type == null)
-				throw KustvaktResponseHandler.throwit(StatusCodes.MISSING_ARGUMENT, "Resource type not available!", "");
 
-			User user = controller.getUser(ctx.getUsername());
+    /**
+     * 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);
 
-			resources = ResourceFinder.search(user, ResourceFactory.getResourceClass(type));
-		} catch (KustvaktException e) {
-			throw KustvaktResponseHandler.throwit(e);
-		}
+        try {
+            Class cl_type = ResourceFactory.getResourceClass(type);
+            if (cl_type == null)
+                throw KustvaktResponseHandler.throwit(
+                        StatusCodes.MISSING_ARGUMENT,
+                        "Resource type not available!", "");
 
-		Set values = new HashSet();
-		for (KustvaktResource resource : resources)
-			values.add(resource.toMap());
-		return Response.ok(JsonUtils.toJSON(values)).build();
-	}
+            User user = controller.getUser(ctx.getUsername());
 
-	@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));
-	}
+            resources = ResourceFinder.search(user,
+                    ResourceFactory.getResourceClass(type));
+        }
+        catch (KustvaktException e) {
+            throw KustvaktResponseHandler.throwit(e);
+        }
 
-	/**
-	 * @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);
+        Set values = new HashSet();
+        for (KustvaktResource resource : resources)
+            values.add(resource.toMap());
+        return Response.ok(JsonUtils.toJSON(values)).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);
 
-			// 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("{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));
+    }
 
-	// @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 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();
-	}
+    /**
+     * @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);
 
-	@Deprecated
-	public Response postMatchFavorite() {
-		return Response.ok().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);
 
-	// 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;
+            // 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();
+    }
 
-		// 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);
 
-		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);
+    // /**
+    // * @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();
+    }
 
-		ss.setMeta(meta.raw());
-		return Response.ok(ss.toJSON()).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
-	 */
+    @Deprecated
+    public Response postMatchFavorite () {
+        return Response.ok().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);
 
-		QuerySerializer ss = new QuerySerializer().setQuery(q, ql, v);
+    // 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;
 
-		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);
+        // User user;
+        // try {
+        // user = controller.getUser(ctx.getUsername());
+        // }
+        // catch (KustvaktException e) {
+        // throw KustvaktResponseHandler.throwit(e);
+        // }
 
-		ss.setMeta(meta.raw());
+        ss = new QuerySerializer().setQuery(q, ql, v);
+        if (cq != null)
+            ss.setCollection(cq);
 
-		KoralCollectionQueryBuilder cquery = new KoralCollectionQueryBuilder();
-		cquery.setBaseQuery(ss.toJSON());
+        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);
 
-		String query = "";
-		KustvaktResource resource;
-		try {
+        ss.setMeta(meta.raw());
+        return Response.ok(ss.toJSON()).build();
+    }
 
-			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 (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();
-	}
+    /**
+     * 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
+     */
 
-	@POST
-	@Path("search")
-	public Response queryRaw(@Context SecurityContext context, @Context Locale locale,
-			@QueryParam("engine") String engine, String jsonld) {
-		TokenContext ctx = (TokenContext) context.getUserPrincipal();
+    // 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);
 
-		// 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);
+        QuerySerializer ss = new QuerySerializer().setQuery(q, ql, v);
 
-		String result = searchKrill.search(jsonld);
-		// todo: logging
-		KustvaktLogger.QUERY_LOGGER.trace("The result set: {}", result);
-		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);
+        if (cutoff != null)
+            meta.addEntry("cutOff", cutoff);
 
-	@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);
+        ss.setMeta(meta.raw());
 
-		if (cq != null)
-			serializer.setCollection(cq);
+        KoralCollectionQueryBuilder cquery = new KoralCollectionQueryBuilder();
+        cquery.setBaseQuery(ss.toJSON());
 
-		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();
+    }
+
+
+    @POST
+    @Path("search")
+    public Response queryRaw (@Context SecurityContext context,
+            @Context Locale locale, @QueryParam("engine") String engine,
+            String jsonld) {
+        TokenContext ctx = (TokenContext) context.getUserPrincipal();
+
+        // 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);
+
+        String result = searchKrill.search(jsonld);
+        // todo: logging
+        KustvaktLogger.QUERY_LOGGER.trace("The result set: {}", result);
+        return Response.ok(result).build();
+    }
+
+
+    @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);
+
+        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);
+        }
+
+        jlog.info("the serialized query {}", 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();
+    }
+
+
+    /**
+     * 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();
+
+            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();
+    }
+
 
-	/**
-	 * 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;
+    @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));
+    }
 
-		try {
-			User user = controller.getUser(context.getUsername());
-			MetaQueryBuilder meta = new MetaQueryBuilder();
 
-			if (!raw) {
-				QuerySerializer s = new QuerySerializer();
-				s.setQuery(query, ql, v);
+    @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);
 
-				KoralCollectionQueryBuilder builder = new KoralCollectionQueryBuilder();
+        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);
 
-				KustvaktResource resource;
-				if (StringUtils.isInteger(id))
-					resource = this.resourceHandler.findbyIntId(Integer.valueOf(id), user);
-				else
-					resource = this.resourceHandler.findbyStrId(id, user, ResourceFactory.getResourceClass(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));
 
-				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);
+            // 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);
+        }
+    }
 
-				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 {
+    /**
+     * @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);
+        }
 
-				// rewrite process
-				query = this.processor.processQuery(query, user);
+        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;
 
-				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);
+        Map vals = new HashMap();
+        vals.put("id", cache.getId());
+        vals.put("statistics", cache.getStats());
+        return Response.ok(JsonUtils.toJSON(vals)).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);
-		}
+    @POST
+    @Path("{type}/{id}")
+    public Response updateResource (@Context SecurityContext context,
+            @Context Locale locale, @PathParam("type") String type,
+            @PathParam("id") String id, @QueryParam("name") String name,
+            @QueryParam("description") String description) {
+        TokenContext ctx = (TokenContext) context.getUserPrincipal();
+        User user;
+        try {
+            user = controller.getUser(ctx.getUsername());
+            KustvaktResource resource = this.resourceHandler.findbyStrId(id,
+                    user, ResourceFactory.getResourceClass(type));
 
-	}
+            if (name != null && !name.isEmpty()) {
+                if (description == null) {
+                    if (name.equals(resource.getName())) {
+                        return Response.notModified("No change has found.")
+                                .build();
+                    }
+                }
+                else if (name.equals(resource.getName())
+                        && description.equals(resource.getDescription())) {
+                    return Response.notModified("No change has found.").build();
+                }
+                else {
+                    resource.setName(name);
+                }
+            }
+            else if (description != null && !description.isEmpty()) {
+                resource.setDescription(description);
+            }
+            else {
+                Response.notModified(
+                        "New name and description are not specified.").build();
+            }
 
-	@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);
+            this.resourceHandler.updateResources(user, resource);
+        }
+        catch (
 
-		return Response.ok(stats).build();
-	}
+        KustvaktException e) {
+            jlog.error("Exception encountered: {}", e.string());
+            throw KustvaktResponseHandler.throwit(e);
+        }
+        return Response.ok().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);
+    // 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;
 
-		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);
+            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 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));
+            }
+            else if (query != null)
+                base = JsonUtils.readTree(query);
+            else
+                // todo: throw exception response for no resource to save!
+                return null;
 
-			// 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);
-		}
-	}
+            KoralCollectionQueryBuilder cquery = new KoralCollectionQueryBuilder();
+            cquery.setBaseQuery(base);
 
-	/**
-	 * @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);
-		}
+            cachetmp = ResourceFactory.getCachedCollection(cquery.toJSON());
 
-		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;
+            // 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));
+            }
 
-		Map vals = new HashMap();
-		vals.put("id", cache.getId());
-		vals.put("statistics", cache.getStats());
-		return Response.ok(JsonUtils.toJSON(vals)).build();
-	}
+            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();
+    }
 
-	@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);
 
-			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);
-			}
+    /**
+     * 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
+     */
+    @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 (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();
-	}
+            user = controller.getUser(ctx.getUsername());
+        }
+        catch (KustvaktException e) {
+            jlog.error("Exception encountered: {}", e.string());
+            throw KustvaktResponseHandler.throwit(e);
+        }
 
-	// 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;
+        if (VirtualCollection.class.equals(ctype)) {
+            VirtualCollection cachetmp, collection;
 
-			JsonNode base;
-			if (reference != null && !reference.equals("null")) {
-				try {
-					base = resourceHandler.findbyStrId(reference, user, VirtualCollection.class).getData();
-				} catch (KustvaktException e) {
-					throw KustvaktResponseHandler.throwit(e);
-				}
+            KoralCollectionQueryBuilder cquery = new KoralCollectionQueryBuilder();
+            if (reference != null && !reference.equals("null")) {
+                try {
+                    cquery.setBaseQuery(resourceHandler.findbyStrId(reference,
+                            user, VirtualCollection.class).getData());
 
-			} else if (query != null)
-				base = JsonUtils.readTree(query);
-			else
-				// todo: throw exception response for no resource to save!
-				return null;
+                }
+                catch (KustvaktException e) {
+                    throw KustvaktResponseHandler.throwit(e);
+                }
+            }
+            if (query != null && !query.isEmpty())
+                cquery.with(query);
 
-			KoralCollectionQueryBuilder cquery = new KoralCollectionQueryBuilder();
-			cquery.setBaseQuery(base);
+            cachetmp = ResourceFactory.getCachedCollection(cquery.toJSON());
 
-			cachetmp = ResourceFactory.getCachedCollection(cquery.toJSON());
+            // see if vc was cached!
+            VirtualCollection tmp = resourceHandler.getCache(cachetmp.getId(),
+                    VirtualCollection.class);
 
-			// 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 not cached, fill with stats values
+            if (tmp == null) {
+                String stats = searchKrill.getStatistics(cquery.toJSON());
+                cachetmp.setStats(JsonUtils.readSimple(stats, Map.class));
+                if (query != null && !query.isEmpty())
+                    cachetmp.setFields(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();
-	}
+            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();
+    }
 
-	/**
-	 * 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);
 
-			user = controller.getUser(ctx.getUsername());
-		} catch (KustvaktException e) {
-			jlog.error("Exception encountered: {}", e.string());
-			throw KustvaktResponseHandler.throwit(e);
-		}
+    @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 (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}")
+    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);
+        }
 
-				} catch (KustvaktException e) {
-					throw KustvaktResponseHandler.throwit(e);
-				}
-			}
-			if (query != null && !query.isEmpty())
-				cquery.with(query);
+        return Response.ok().build();
+    }
 
-			cachetmp = ResourceFactory.getCachedCollection(cquery.toJSON());
-			
-			// see if vc 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 (query != null && !query.isEmpty())
-					cachetmp.setFields(cquery.toJSON());
-			}
-			
-			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();
-	}
 
-	@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));
-	}
+    // 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}")
-	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);
-		}
+        if (layers == null || layers.isEmpty())
+            layers = new HashSet<>();
 
-		return Response.ok().build();
-	}
+        boolean match_only = foundries == null || foundries.isEmpty();
 
-	// 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);
+        User user;
+        try {
+            user = controller.getUser(tokenContext.getUsername());
+        }
+        catch (KustvaktException e) {
 
-		if (layers == null || layers.isEmpty())
-			layers = new HashSet<>();
+            jlog.error("Exception encountered: {}", e.string());
+            throw KustvaktResponseHandler.throwit(e);
+        }
 
-		boolean match_only = foundries == null || foundries.isEmpty();
+        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<>();
 
-		User user;
-		try {
-			user = controller.getUser(tokenContext.getUsername());
-		} catch (KustvaktException e) {
+            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;
 
-			jlog.error("Exception encountered: {}", e.string());
-			throw KustvaktResponseHandler.throwit(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);
+                }
 
-		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<>();
+            }
+            // 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();
+    }
 
-			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;
 
-					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);
-				}
+    // 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!
 
-			}
-			// 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();
-	}
+        // 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);
+        // }
 
-	// 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!
+        return Response.ok().build();
+    }
 
-		// 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);
-		// }
 
-		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();
+    }
 
-	@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/main/resources/db/sqlite/V1__Initial_version.sql b/src/main/resources/db/sqlite/V1__Initial_version.sql
index 55641ae..943d3cd 100644
--- a/src/main/resources/db/sqlite/V1__Initial_version.sql
+++ b/src/main/resources/db/sqlite/V1__Initial_version.sql
@@ -13,7 +13,7 @@
 
 CREATE TABLE IF NOT EXISTS admin_users (
 id INTEGER PRIMARY KEY AUTOINCREMENT,
-user_id INTEGER NOT NULL UNIQUE,
+user_id INTEGER NOT NULL,
 foreign key (user_id)
 references korap_users (id)
 );
diff --git a/src/test/java/de/ids_mannheim/korap/web/service/full/KustvaktServerTest.java b/src/test/java/de/ids_mannheim/korap/web/service/full/KustvaktServerTest.java
index aa99ac9..0226217 100644
--- a/src/test/java/de/ids_mannheim/korap/web/service/full/KustvaktServerTest.java
+++ b/src/test/java/de/ids_mannheim/korap/web/service/full/KustvaktServerTest.java
@@ -55,105 +55,184 @@
 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
+ * 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.
+ * See {@link ResourceServiceTest} for tests using an in-memory
+ * database.
  * 
  * @author margaretha
  *
  */
 public class KustvaktServerTest extends BeanConfigTest {
-	@Test
-	public void testCreatePolicy() throws IOException, URISyntaxException {
-		
-		HttpClient httpClient = HttpClients.createDefault();;
-		
-        String id = UUID.randomUUID().toString();
-		URIBuilder builder = new URIBuilder();
-		builder.setScheme("http")
-			.setHost("localhost")
-			.setPort(8089).setPath("/api/v0.1/admin/createPolicies/" + id)
-			.setParameter("type", "virtualcollection")
-			.setParameter("name", "Goethe VC")
-			.setParameter("description", "Goethe corpus")
-			.setParameter("group", "public")
-			.setParameter("perm", Permission.READ.name())
-			.setParameter("loc", "")
-			.setParameter("expire", "");
+    @Test
+    public void testCreatePolicy () throws IOException, URISyntaxException {
 
-		URI uri = builder.build();
-		HttpPost httppost = new HttpPost(uri);
-		
-		httppost.addHeader(Attributes.AUTHORIZATION, BasicHttpAuth.encode("kustvakt", "kustvakt2015"));
-		HttpResponse response = httpClient.execute(httppost);
-		assertEquals(ClientResponse.Status.OK.getStatusCode(),
+        HttpClient httpClient = HttpClients.createDefault();;
+
+        String id = UUID.randomUUID().toString();
+        URIBuilder builder = new URIBuilder();
+        builder.setScheme("http").setHost("localhost").setPort(8089)
+                .setPath("/api/v0.1/admin/createPolicies/" + id)
+                .setParameter("type", "virtualcollection")
+                .setParameter("name", "Goethe VC")
+                .setParameter("description", "Goethe corpus")
+                .setParameter("group", "public")
+                .setParameter("perm", Permission.READ.name())
+                .setParameter("loc", "")
+                .setParameter("expire", "");
+
+        URI uri = builder.build();
+        HttpPost httppost = new HttpPost(uri);
+
+        httppost.addHeader(Attributes.AUTHORIZATION,
+                BasicHttpAuth.encode("kustvakt", "kustvakt2015"));
+        HttpResponse response = httpClient.execute(httppost);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
                 response.getStatusLine().getStatusCode());
 
-	}
+    }
 
-	@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 {
+    @Test
+    public void testCreatePolicyForFoundry ()
+            throws IOException, URISyntaxException {
 
-		HttpResponse response = testResourceStore("kustvakt2015");
-		HttpEntity entity = response.getEntity();
-		String content = null;
+        HttpClient httpClient = HttpClients.createDefault();;
 
-		if (entity != null) {
-			InputStream is = entity.getContent();
-			try {
-				content = IOUtils.toString(is, "UTF-8");
-			} finally {
-				is.close();
-			}
-		}
+        String id = UUID.randomUUID().toString();
+        URIBuilder builder = new URIBuilder();
+        builder.setScheme("http").setHost("localhost").setPort(8089)
+                .setPath("/api/v0.1/admin/createPolicies/" + id)
+                .setParameter("type", "foundry")
+                .setParameter("name", "stanford")
+                .setParameter("description", "stanford parser")
+                .setParameter("group", "public")
+                .setParameter("perm", Permission.READ.name())
+                .setParameter("loc", "255.255.255.0")
+                .setParameter("expire", "30D");
 
-		assertEquals(ClientResponse.Status.OK.getStatusCode(), response.getStatusLine().getStatusCode());
+        URI uri = builder.build();
+        HttpPost httppost = new HttpPost(uri);
 
-		JsonNode node = JsonUtils.readTree(content);
-		assertNotNull(node);
-		assertTrue(node.isObject());
-		assertEquals("Goethe", node.path("name").asText());
-		assertEquals("Goethe corpus", node.path("description").asText());
+        httppost.addHeader(Attributes.AUTHORIZATION,
+                BasicHttpAuth.encode("kustvakt", "kustvakt2015"));
+        HttpResponse response = httpClient.execute(httppost);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatusLine().getStatusCode());
 
-		// 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);
+    @Test
+    public void testCreatePolicyWithMultiplePermissions ()
+            throws IOException, URISyntaxException {
 
-	}
+        HttpClient httpClient = HttpClients.createDefault();;
 
-	private void checkResourceInDB(String id) throws KustvaktException {
+        String id = UUID.randomUUID().toString();
+        URIBuilder builder = new URIBuilder();
+        builder.setScheme("http").setHost("localhost").setPort(8089)
+                .setPath("/api/v0.1/admin/createPolicies/" + id)
+                .setParameter("type", "corpus").setParameter("name", "Brown")
+                .setParameter("description", "Brown corpus")
+                .setParameter("group", "public")
+                .setParameter("perm", Permission.READ.name())
+                .setParameter("perm", Permission.WRITE.name())
+                .setParameter("perm", Permission.DELETE.name())
+                .setParameter("loc", "255.255.255.0")
+                .setParameter("expire", "30D");
 
-		ResourceDao<?> dao = new ResourceDao<>(helper().getContext().getPersistenceClient());
-		assertEquals("sqlite", helper().getContext().getPersistenceClient().getDatabase());
+        URI uri = builder.build();
+        HttpPost httppost = new HttpPost(uri);
 
-		assertNotEquals(0, dao.size());
-		KustvaktResource res = dao.findbyId(id, User.UserFactory.getDemoUser());
-		assertNotNull(res);
-		Assert.assertEquals(true, res.getField("testVar").toString().startsWith("testVal_"));
-	}
+        httppost.addHeader(Attributes.AUTHORIZATION,
+                BasicHttpAuth.encode("kustvakt", "kustvakt2015"));
+        HttpResponse response = httpClient.execute(httppost);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatusLine().getStatusCode());
 
-	@Override
-	public void initMethod() throws KustvaktException {
-		// TODO Auto-generated method stub
+    }
 
-	}
+
+    @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());
+    }
+
+
+    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/PolicyServiceTest.java b/src/test/java/de/ids_mannheim/korap/web/service/full/PolicyServiceTest.java
index 6959924..c48f40c 100644
--- a/src/test/java/de/ids_mannheim/korap/web/service/full/PolicyServiceTest.java
+++ b/src/test/java/de/ids_mannheim/korap/web/service/full/PolicyServiceTest.java
@@ -15,6 +15,8 @@
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.interfaces.db.PolicyHandlerIface;
 import de.ids_mannheim.korap.interfaces.db.ResourceOperationIface;
+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.Permissions;
 import de.ids_mannheim.korap.resources.Permissions.Permission;
@@ -31,34 +33,36 @@
  */
 public class PolicyServiceTest extends FastJerseyTest {
 
-	@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");
-	}
+    private User user = UserFactory.getDemoUser();
 
-	@Test
-    public void testCreatePolicyForResource() throws IOException, KustvaktException {
-		String id = UUID.randomUUID().toString();
-    	ClientResponse response = resource()
-                .path(getAPIVersion())
-                .path("admin")
-                .path("createPolicies")
-                .path(id)
+
+    @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 testCreatePolicyForVirtualCollection ()
+            throws IOException, KustvaktException {
+        String id = UUID.randomUUID().toString();
+        ClientResponse response = resource().path(getAPIVersion()).path("admin")
+                .path("createPolicies").path(id)
                 .queryParam("type", "virtualcollection")
                 .queryParam("name", "Goethe VC")
                 .queryParam("description", "Goethe corpus")
                 .queryParam("group", "public")
                 .queryParam("perm", Permission.READ.name())
-                .queryParam("loc", "")
                 .queryParam("expire", "")
                 .header(Attributes.AUTHORIZATION,
-                        BasicHttpAuth.encode("kustvakt","kustvakt2015"))
+                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
                 .post(ClientResponse.class);
-        
+
         assertEquals(ClientResponse.Status.OK.getStatusCode(),
                 response.getStatus());
-        
+
         // Check the policies
         PolicyHandlerIface dao = helper().getContext().getPolicyDbProvider();
         List<SecurityPolicy> policies = dao.getPolicies(
@@ -66,18 +70,108 @@
                 Permissions.Permission.READ.toByte());
         assertEquals(2, policies.size());
         
-        // Check resource store
-        List<ResourceOperationIface> providers= (List<ResourceOperationIface>) helper().getContext().getResourceProviders();
-        ResourceOperationIface resourceDao = providers.get(0);
-        
-        User user = UserFactory.getDemoUser();
-		KustvaktResource resource = resourceDao.findbyId(id,user);
-		assertEquals("Goethe VC", resource.getName());
-        	
-	}
+        policies = dao.getPoliciesByPersistentId(
+                new PolicyCondition("public"), VirtualCollection.class,
+                Permissions.Permission.READ.toByte(),id);
+        assertEquals(1, policies.size());
+        assertEquals(id, policies.get(0).getTarget());
 
-	@Override
-	public void initMethod() throws KustvaktException {
-		helper().runBootInterfaces();
-	}
+        // Check the resource
+        List<ResourceOperationIface> providers = (List<ResourceOperationIface>) helper()
+                .getContext().getResourceProviders();
+        ResourceOperationIface resourceDao = providers.get(0);
+
+        User user = UserFactory.getDemoUser();
+        KustvaktResource resource = resourceDao.findbyId(id, user);
+        assertEquals("Goethe VC", resource.getName());
+
+    }
+
+
+    @Test
+    public void testCreatePolicyForFoundry ()
+            throws IOException, KustvaktException {
+        String id = UUID.randomUUID().toString();
+        ClientResponse response = resource().path(getAPIVersion()).path("admin")
+                .path("createPolicies").path(id).queryParam("type", "foundry")
+                .queryParam("name", "stanford")
+                .queryParam("description", "stanford parser")
+                .queryParam("group", "public")
+                .queryParam("perm", Permission.READ.name())
+                .queryParam("loc", "255.255.255.0")
+                .queryParam("expire", "30D")
+                .header(Attributes.AUTHORIZATION,
+                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
+                .post(ClientResponse.class);
+
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+
+        // Check the resource store
+        List<ResourceOperationIface> providers = (List<ResourceOperationIface>) helper()
+                .getContext().getResourceProviders();
+        ResourceOperationIface resourceDao = providers.get(0);
+        KustvaktResource resource = resourceDao.findbyId(id, user);
+        assertEquals("stanford", resource.getName());
+
+        // Check the policies
+        PolicyHandlerIface dao = helper().getContext().getPolicyDbProvider();
+        List<SecurityPolicy> policies = dao.getPoliciesByPersistentId(
+                new PolicyCondition("public"), Foundry.class,
+                Permissions.Permission.READ.toByte(),id);
+        assertEquals(1, policies.size());
+        assertEquals("255.255.255.0",policies.get(0).getContext().getIpmask());
+
+    }
+
+
+    @Test
+    public void testCreatePolicyForMultiplePermissions ()
+            throws IOException, KustvaktException {
+        String id = UUID.randomUUID().toString();
+        ClientResponse response = resource().path(getAPIVersion()).path("admin")
+                .path("createPolicies").path(id).queryParam("type", "corpus")
+                .queryParam("name", "Brown")
+                .queryParam("description", "Brown corpus")
+                .queryParam("group", "public")
+                .queryParam("perm", Permission.READ.name())
+                .queryParam("perm", Permission.WRITE.name())
+                .queryParam("perm", Permission.DELETE.name())
+                .queryParam("expire", "30D")
+                .header(Attributes.AUTHORIZATION,
+                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
+                .post(ClientResponse.class);
+
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+
+        // Check resource store
+        List<ResourceOperationIface> providers = (List<ResourceOperationIface>) helper()
+                .getContext().getResourceProviders();
+        ResourceOperationIface resourceDao = providers.get(0);
+
+        KustvaktResource resource = resourceDao.findbyId(id, user);
+        assertEquals("Brown", resource.getName());
+
+        // Check the policies
+        PolicyHandlerIface dao = helper().getContext().getPolicyDbProvider();
+        List<SecurityPolicy> policies = dao.getPoliciesByPersistentId(
+                new PolicyCondition("public"), Corpus.class,
+                Permissions.Permission.WRITE.toByte(),id);
+        assertEquals(1, policies.size());
+        assertEquals(id, policies.get(0).getTarget());
+        
+        policies = dao.getPoliciesByPersistentId(
+                new PolicyCondition("public"), Corpus.class,
+                Permissions.Permission.DELETE.toByte(),id);
+        assertEquals(1, policies.size());
+        assertEquals(id, policies.get(0).getTarget());
+    }
+
+
+    @Override
+    public void initMethod () throws KustvaktException {
+        helper().runBootInterfaces();
+    }
 }
+
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 d036b57..fed448d 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
@@ -18,6 +18,7 @@
 
 import de.ids_mannheim.korap.config.Attributes;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.handlers.ResourceDao;
 import de.ids_mannheim.korap.query.serialize.QuerySerializer;
 import de.ids_mannheim.korap.resources.KustvaktResource;
@@ -301,7 +302,35 @@
                 User.UserFactory.getDemoUser());
         assertNotNull(res);
         Assert.assertEquals("Goethe",res.getName().toString());
-    
+        
+        // no update resource service
+        response = resource()
+                .path(getAPIVersion())
+                .path("virtualcollection")
+                .path(id)
+                .queryParam("name", "Goethe")
+                .header(Attributes.AUTHORIZATION,
+                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
+                .post(ClientResponse.class);
+        
+        assertEquals(StatusCodes.NOTHING_CHANGED, response.getStatus());
+        
+        // update resource service
+        response = resource()
+                .path(getAPIVersion())
+                .path("virtualcollection")
+                .path(id)
+                .queryParam("name", "Goethe collection")
+                .header(Attributes.AUTHORIZATION,
+                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
+                .post(ClientResponse.class);
+        
+        res = dao.findbyId(id,
+                User.UserFactory.getDemoUser());
+        assertNotNull(res);
+        Assert.assertEquals("Goethe collection",res.getName().toString());
+        
+        
         // delete resource service
     	response = resource()
                 .path(getAPIVersion())
@@ -340,36 +369,6 @@
         assertEquals("WPD15", node.path("id").asText());
     }
 
-    
-
-//    @Test
-//    public void testCreatePolicyForResource() {
-//    	ClientResponse response = resource()
-//                .path(getAPIVersion())
-//                .path("admin")
-//                .path("createPolicies")
-//                .path(UUID.randomUUID().toString())
-//                .queryParam("type", "virtualcollection")
-//                .queryParam("name", "Goethe")
-//                .queryParam("description", "Goethe corpus")
-//                .queryParam("group", "public")
-//                .queryParam("perm", Permission.READ.name())
-//                .queryParam("loc", "")
-//                .queryParam("expire", "")
-//                .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("GOE", node.path("id").asText());
-//	}
-    
     @Test
     public void testCorpusGet2 () {
     	ClientResponse response = resource().path(getAPIVersion())