Merge branch 'master' of ssh://korap.ids-mannheim.de:29418/private/Kustvakt-core
LDAP Authentication: finished.
diff --git a/policy.conf b/policy.conf
new file mode 100644
index 0000000..4a6dfd2
--- /dev/null
+++ b/policy.conf
@@ -0,0 +1,55 @@
+# type	id	name	description	condition	permissions
+
+virtualcollection	WPD15-VC	Wikipedia Virtual Collection	German Wikipedia 2015	public	read
+corpus	WPD15	Wikipedia	German Wikipedia 2015	public	read
+corpus	GOE	Goethe	Goethe corpus	public	read
+type	id	name	description	condition	permissions
+foundry	base	base	Base foundry	public	read
+foundry	dereko	dereko	DeReKo foundry	public	read
+foundry	corenlp	corenlp	CoreNLP parser	public	read
+foundry	opennlp	opennlp	OpenNLP parser	public	read
+foundry	malt	malt	MALT parser	public	read
+foundry	mdp	mdp	MD parser	public	read
+foundry	tt	tt	Tree Tagger parser	public	read
+foundry	sgbr	sgbr	Schreibgebrauch	ids	read
+foundry	cnx	cnx	Connexor parser	ids	read
+foundry	drukola	drukola	DruKoLa parser	drukola	read
+foundry	glemm	glemm	Glemm	public	read
+foundry	marmot	marmot	MarMoT parser	public	read
+foundry	mate	mate	Mate parser	public	read
+foundry	xip	xip	Xerox Incremental Parser	ids	read
+layer	cnx/c	cnx/c	Connexor constituency layer	ids	read
+layer	cnx/syn	cnx/syn	Connexor syntax	ids	read
+layer	cnx/p	cnx/p	Connexor part of speech	ids	read
+layer	cnx/l	cnx/l	Connexor lemma	ids	read
+layer	cnx/m	cnx/m	Connexor morphology	ids	read
+layer	corenlp/c	corenlp/c	CoreNLP constituency	public	read
+layer	corenlp/p	corenlp/p	CoreNLP part of speech	public	read
+layer	corenlp/s	corenlp/s	CoreNLP structure	public	read
+layer	corenlp/ne	corenlp/ne	CoreNLP named entities	public	read
+layer	dereko/s	dereko/s	DeReKo structure	public	read
+layer	drukola/l	drukola/l	Drukola lemma	drukola	read
+layer	drukola/p	drukola/p	Drukola part of speech	drukola	read
+layer	drukola/m	drukola/m	Drukola morphology	drukola	read
+layer	glemm/l	glemm/l	GLEMM lemma	public	read
+layer	malt/d	malt/d	MALT dependency	public	read
+layer	marmot/p	marmot/p	Marmot part of speech	public	read
+layer	marmot/m	marmot/m	Marmot morphology	public	read
+layer	mate/d	mate/d	MATE dependency	public	read
+layer	mate/l	mate/l	MATE lemma	public	read
+layer	mate/p	mate/p	MATE part of speech	public	read
+layer	mate/m	mate/m	MATE morphology	public	read
+layer	mdp/d	mdp/d	MDP dependency	public	read
+layer	opennlp/p	opennlp/p	OpenNLP part of speech	public	read
+layer	opennlp/s	opennlp/s	OpenNLP part of speech	public	read
+layer	sgbr/p	sgbr/p	Schreibgebrauchp part of peech	ids	read
+layer	sgbr/l	sgbr/l	Schreibgebrauch lemma	ids	read
+layer	sgbr/lv	sgbr/lv	Schreibgebrauch lemmav ariant	ids	read
+layer	tt/p	tt/p	Tree Tagger part of speech	public	read
+layer	tt/l	tt/l	Tree Tagger lemma	public	read
+layer	tt/s	tt/s	Tree Tagger structure	public	read
+layer	xip/c	xip/c	XIP constituency	ids	read
+layer	xip/d	xip/d	XIP dependency	ids	read
+layer	xip/l	xip/l	XIP lemma	ids	read
+layer	xip/p	xip/p	XIP part of speech	ids	read
+layer	xip/s	xip/s	XIP structure	ids	read
diff --git a/pom.xml b/pom.xml
index 0b43e21..ebbc721 100644
--- a/pom.xml
+++ b/pom.xml
@@ -175,6 +175,7 @@
                     <excludes>
                         <exclude>**/*APITest.java</exclude>
                         <exclude>de/ids_mannheim/korap/suites/*.java</exclude>
+                		<exclude>**/KustvaktServerTest.java</exclude>
                     </excludes>
                     <includes>
                         <include>de/ids_mannheim/korap/**/*.java</include>
@@ -510,6 +511,16 @@
             </exclusions>
         </dependency>
         -->
+        <dependency>
+        	<groupId>org.apache.httpcomponents</groupId>
+        	<artifactId>httpclient</artifactId>
+        	<version>4.3.3</version>
+        </dependency>
+        <dependency>
+        	<groupId>commons-io</groupId>
+        	<artifactId>commons-io</artifactId>
+        	<version>2.4</version>
+        </dependency>
     </dependencies>
 
 </project>
diff --git a/src/main/java/de/ids_mannheim/korap/config/AdminSetup.java b/src/main/java/de/ids_mannheim/korap/config/AdminSetup.java
index 378e015..4d6687f 100644
--- a/src/main/java/de/ids_mannheim/korap/config/AdminSetup.java
+++ b/src/main/java/de/ids_mannheim/korap/config/AdminSetup.java
@@ -1,14 +1,14 @@
 package de.ids_mannheim.korap.config;
 
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.interfaces.EncryptionIface;
+import java.io.File;
+import java.io.FileOutputStream;
 
-import java.io.*;
-import java.security.NoSuchAlgorithmException;
+import de.ids_mannheim.korap.interfaces.EncryptionIface;
 
 /**
  * Created by hanl on 30.05.16.
  */
+@Deprecated
 public class AdminSetup {
 
     private final String token_hash;
diff --git a/src/main/java/de/ids_mannheim/korap/config/Attributes.java b/src/main/java/de/ids_mannheim/korap/config/Attributes.java
index 8775883..16ddfdd 100644
--- a/src/main/java/de/ids_mannheim/korap/config/Attributes.java
+++ b/src/main/java/de/ids_mannheim/korap/config/Attributes.java
@@ -2,6 +2,7 @@
 
 public class Attributes {
 
+	// EM: Use enum for the authentication types
     public static final String AUTHORIZATION = "Authorization";
     public static final String SESSION_AUTHENTICATION = "session_token";
     public static final String API_AUTHENTICATION = "api_token";
@@ -44,7 +45,8 @@
     public static final String ADDRESS = "address";
     public static final String COUNTRY = "country";
     public static final String IPADDRESS = "ipaddress";
-    // deprcated, use created
+    public static final String IS_ADMIN = "admin";
+    // deprecated, use created
     public static final String ACCOUNT_CREATION = "account_creation";
     public static final String ACCOUNTLOCK = "account_lock";
     public static final String ACCOUNTLINK = "account_link";
diff --git a/src/main/java/de/ids_mannheim/korap/config/ContextHolder.java b/src/main/java/de/ids_mannheim/korap/config/ContextHolder.java
index e142def..c0126da 100644
--- a/src/main/java/de/ids_mannheim/korap/config/ContextHolder.java
+++ b/src/main/java/de/ids_mannheim/korap/config/ContextHolder.java
@@ -29,6 +29,7 @@
     public static final String KUSTVAKT_AUTHENTICATION_MANAGER = "kustvakt_authenticationmanager";
     public static final String KUSTVAKT_AUTHPROVIDERS = "kustvakt_authproviders";
     public static final String KUSTVAKT_USERDB = "kustvakt_userdb";
+    public static final String KUSTVAKT_ADMINDB = "kustvakt_admindb";
     public static final String KUSTVAKT_POLICIES = "kustvakt_policies";
 
     private ApplicationContext context = null;
@@ -105,6 +106,10 @@
     public EntityHandlerIface getUserDBHandler () {
         return getBean(KUSTVAKT_USERDB);
     }
+    
+    public AdminHandlerIface getAdminDBHandler () {
+        return getBean(KUSTVAKT_ADMINDB);
+    }
 
 
     public PolicyHandlerIface getPolicyDbProvider () {
diff --git a/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java b/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java
index 1aed56c..6b7f7c2 100644
--- a/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java
+++ b/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java
@@ -19,7 +19,7 @@
  * if configuration class is extended, loadSubTypes method should be
  * overriden
  * 
- * @author hanl
+ * @author hanl, margaretha
  * @date 05/02/2014
  */
 
@@ -28,18 +28,6 @@
 
     public static final Map<String, Object> KUSTVAKT_USER = new HashMap<>();
 
-    static {
-        KUSTVAKT_USER.put(Attributes.ID, 1000);
-        KUSTVAKT_USER.put(Attributes.USERNAME, "kustvakt");
-        KUSTVAKT_USER.put(Attributes.PASSWORD, "kustvakt2015");
-        KUSTVAKT_USER.put(Attributes.EMAIL, "kustvakt@ids-mannheim.de");
-        KUSTVAKT_USER.put(Attributes.COUNTRY, "Germany");
-        KUSTVAKT_USER.put(Attributes.ADDRESS, "Mannheim");
-        KUSTVAKT_USER.put(Attributes.FIRSTNAME, "Kustvakt");
-        KUSTVAKT_USER.put(Attributes.LASTNAME, "KorAP");
-        KUSTVAKT_USER.put(Attributes.INSTITUTION, "IDS Mannheim");
-    }
-
     private static final Logger jlog = LoggerFactory
             .getLogger(KustvaktConfiguration.class);
     private String indexDir;
@@ -83,6 +71,8 @@
     private String default_token;
     private String default_dep;
     private String default_const;
+    
+    private String policyConfig;
 
     // deprec?!
     private final BACKENDS DEFAULT_ENGINE = BACKENDS.LUCENE;
@@ -154,7 +144,19 @@
 
         passcodeSaltField = properties.getProperty("security.passcode.salt",
                 "accountCreation");
-
+        
+        policyConfig = properties.getProperty("policies.config");
+        
+        KUSTVAKT_USER.put(Attributes.ID, Integer.parseInt(properties.getProperty("kustvakt.init.user.id")));
+        KUSTVAKT_USER.put(Attributes.USERNAME, properties.getProperty("kustvakt.init.user.username"));
+        KUSTVAKT_USER.put(Attributes.PASSWORD, properties.getProperty("kustvakt.init.user.password"));
+        KUSTVAKT_USER.put(Attributes.EMAIL, properties.getProperty("kustvakt.init.user.email"));
+        KUSTVAKT_USER.put(Attributes.COUNTRY, properties.getProperty("kustvakt.init.user.country"));
+        KUSTVAKT_USER.put(Attributes.ADDRESS, properties.getProperty("kustvakt.init.user.address"));
+        KUSTVAKT_USER.put(Attributes.FIRSTNAME, properties.getProperty("kustvakt.init.user.firstname"));
+        KUSTVAKT_USER.put(Attributes.LASTNAME, properties.getProperty("kustvakt.init.user.lastname"));
+        KUSTVAKT_USER.put(Attributes.INSTITUTION, properties.getProperty("kustvakt.init.user.institution"));
+        KUSTVAKT_USER.put(Attributes.IS_ADMIN, properties.getProperty("kustvakt.init.user.admin"));
         return properties;
     }
 
diff --git a/src/main/java/de/ids_mannheim/korap/exceptions/dbException.java b/src/main/java/de/ids_mannheim/korap/exceptions/DatabaseException.java
similarity index 74%
rename from src/main/java/de/ids_mannheim/korap/exceptions/dbException.java
rename to src/main/java/de/ids_mannheim/korap/exceptions/DatabaseException.java
index 076797b..702bf4b 100644
--- a/src/main/java/de/ids_mannheim/korap/exceptions/dbException.java
+++ b/src/main/java/de/ids_mannheim/korap/exceptions/DatabaseException.java
@@ -8,17 +8,17 @@
  * @author hanl
  * @date 08/04/2015
  */
-public class dbException extends KustvaktException {
+public class DatabaseException extends KustvaktException {
 
-    private dbException (Object userid, Integer status, String message,
+    private DatabaseException (Object userid, Integer status, String message,
                          String args) {
         super(String.valueOf(userid), status, message, args);
     }
 
 
-    public dbException (Object userid, String target, Integer status,
+    public DatabaseException (Object userid, String target, Integer status, String message,
                         String ... args) {
-        this(userid, status, "", Arrays.asList(args).toString());
+        this(userid, status, message, Arrays.asList(args).toString());
         AuditRecord record = new AuditRecord(AuditRecord.CATEGORY.DATABASE);
         record.setUserid(String.valueOf(userid));
         record.setStatus(status);
@@ -28,7 +28,7 @@
     }
 
 
-    public dbException (KustvaktException e, Integer status, String ... args) {
+    public DatabaseException (KustvaktException e, Integer status, String ... args) {
         this(e.getUserid(), e.getStatusCode(), e.getMessage(), e.getEntity());
         AuditRecord record = AuditRecord.dbRecord(e.getUserid(), status, args);
         record.setField_1(e.string());
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/AdminDao.java b/src/main/java/de/ids_mannheim/korap/handlers/AdminDao.java
new file mode 100644
index 0000000..7237afd
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/handlers/AdminDao.java
@@ -0,0 +1,93 @@
+package de.ids_mannheim.korap.handlers;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.dao.DataAccessException;
+import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
+
+import de.ids_mannheim.korap.config.KustvaktBaseDaoInterface;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.interfaces.db.AdminHandlerIface;
+import de.ids_mannheim.korap.interfaces.db.PersistenceClient;
+import de.ids_mannheim.korap.user.User;
+
+public class AdminDao implements AdminHandlerIface, KustvaktBaseDaoInterface {
+	
+	private static Logger jlog = LoggerFactory.getLogger(AdminDao.class);
+	private NamedParameterJdbcTemplate jdbcTemplate;
+
+	public AdminDao(PersistenceClient client) {
+		this.jdbcTemplate = (NamedParameterJdbcTemplate) client.getSource();
+	}
+	
+	@Override
+	public int addAccount(User user) throws KustvaktException{
+		MapSqlParameterSource params = new MapSqlParameterSource();
+		params.addValue("user_id", user.getId());
+		String query = "INSERT INTO admin_users (user_id) VALUES (:user_id)";
+		try {
+            int r = this.jdbcTemplate.update(query, params);
+            return r;
+        }
+        catch (DataAccessException e) {
+            jlog.warn("Could not add {} as an admin. {} is already an admin.",
+                    user.getUsername());
+//            throw new dbException(user.getId().toString(), "admin_users",
+//                    StatusCodes.ENTRY_EXISTS, user.getId().toString());
+            return 0;
+        }
+	}
+
+	@Override
+	public int size() {
+		final String query = "SELECT COUNT(*) FROM admin_users;";
+		return this.jdbcTemplate.queryForObject(query, new HashMap<String, Object>(), Integer.class);
+	}
+
+	@Override
+	public int truncate() {
+		String sql = "DELETE FROM korap_users;";
+		try {
+			return this.jdbcTemplate.update(sql, new HashMap<String, Object>());
+		} catch (DataAccessException e) {
+			return -1;
+		}
+	}
+
+	@Override
+	public int updateAccount(User user) throws KustvaktException {
+		// TODO Auto-generated method stub
+		return 0;
+	}
+
+	@Override
+	public int deleteAccount(Integer userid) throws KustvaktException {
+		// TODO Auto-generated method stub
+		return 0;
+	}
+
+	@Override
+	public boolean isAdmin(int userId) {
+		Map<String, String> namedParameters = Collections.singletonMap(
+                "user_id", String.valueOf(userId));
+		
+        final String sql = "select id from admin_users where user_id=:user_id;";
+        try {
+            List<Map<String, Object>> ids = this.jdbcTemplate.queryForList(sql, namedParameters);
+            if (ids.isEmpty()){
+            	return false;
+            }
+        }
+        catch (DataAccessException e) {
+            return false;
+        }
+		return true;
+	}
+
+}
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/EntityDao.java b/src/main/java/de/ids_mannheim/korap/handlers/EntityDao.java
index 16279bc..8829064 100644
--- a/src/main/java/de/ids_mannheim/korap/handlers/EntityDao.java
+++ b/src/main/java/de/ids_mannheim/korap/handlers/EntityDao.java
@@ -6,7 +6,7 @@
 import de.ids_mannheim.korap.exceptions.EmptyResultException;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.exceptions.dbException;
+import de.ids_mannheim.korap.exceptions.DatabaseException;
 import de.ids_mannheim.korap.interfaces.db.EntityHandlerIface;
 import de.ids_mannheim.korap.interfaces.db.PersistenceClient;
 import de.ids_mannheim.korap.user.KorAPUser;
@@ -17,6 +17,7 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.dao.DataAccessException;
+import org.springframework.dao.DuplicateKeyException;
 import org.springframework.dao.EmptyResultDataAccessException;
 import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
 import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
@@ -52,8 +53,8 @@
     // usersettings are fetched plus basic account info, no details, since i rarely use them anyway!
     @Override
     public User getAccount (String username) throws KustvaktException {
-        Map<String, String> namedParameters = Collections.singletonMap(
-                "username", username);
+        Map<String, String> namedParameters = Collections
+                .singletonMap("username", username);
         final String sql = "select a.* from korap_users as a where a.username=:username;";
         User user;
         try {
@@ -66,8 +67,10 @@
         }
         catch (DataAccessException e) {
             jlog.error("Could not retrieve user for name: " + username, e);
-            throw new dbException(username, "korap_users",
-                    StatusCodes.DB_GET_FAILED, username);
+            throw new DatabaseException(username, "korap_users",
+                    StatusCodes.DB_GET_FAILED,
+                    "Could not retrieve the user with username: " + username,
+                    username);
         }
         return user;
     }
@@ -122,8 +125,10 @@
             jlog.error(
                     "Could not update user account for user: " + user.getId(),
                     e);
-            throw new dbException(user.getId(), "korap_users",
-                    StatusCodes.DB_UPDATE_FAILED, user.toString());
+            throw new DatabaseException(user.getId(), "korap_users",
+                    StatusCodes.DB_UPDATE_FAILED,
+                    "Could not update user account for user: " + user.getId(),
+                    user.toString());
         }
     }
 
@@ -199,18 +204,26 @@
 
         KeyHolder holder = new GeneratedKeyHolder();
 
+        int r;
         try {
-            int r = this.jdbcTemplate.update(query, np, holder,
+            r = this.jdbcTemplate.update(query, np, holder,
                     new String[] { "id" });
             user.setId(holder.getKey().intValue());
-            return r;
         }
-        catch (DataAccessException e) {
+        catch (DuplicateKeyException e) {
             jlog.error("Could not create user account with username: {}",
                     user.getUsername());
-            throw new dbException(user.getUsername(), "korap_users",
-                    StatusCodes.ENTRY_EXISTS, user.getUsername());
+            throw new DatabaseException(user.getUsername(), "korap_users",
+                    StatusCodes.ENTRY_EXISTS, "Username exists.",
+                    user.getUsername());
         }
+        catch (DataAccessException e) {
+            throw new DatabaseException(user.getUsername(), "korap_users",
+                    StatusCodes.ENTRY_EXISTS, "Username exists.",
+                    user.getUsername());
+        }
+
+        return r;
     }
 
 
@@ -221,8 +234,8 @@
 
         try {
             int r;
-            r = this.jdbcTemplate.update(
-                    "DELETE FROM korap_users WHERE id=:user", s);
+            r = this.jdbcTemplate
+                    .update("DELETE FROM korap_users WHERE id=:user", s);
             //            if (user instanceof KorAPUser)
             //                r = this.jdbcTemplate
             //                        .update("DELETE FROM korap_users WHERE username=:user",
@@ -238,8 +251,10 @@
         catch (DataAccessException e) {
             jlog.error("Could not delete account for user: " + userid, e);
             //            throw new KorAPException(e, StatusCodes.CONNECTION_ERROR);
-            throw new dbException(userid, "korap_users",
-                    StatusCodes.DB_DELETE_FAILED, userid.toString());
+            throw new DatabaseException(userid, "korap_users",
+                    StatusCodes.DB_DELETE_FAILED,
+                    "Could not delete account for user: " + userid,
+                    userid.toString());
         }
 
     }
@@ -273,9 +288,10 @@
         }
         catch (DataAccessException e) {
             jlog.error("Could not reset password for name: " + username, e);
-            throw new dbException(username, "korap_users",
-                    StatusCodes.DB_UPDATE_FAILED, username, uriToken,
-                    passphrase);
+            throw new DatabaseException(username, "korap_users",
+                    StatusCodes.DB_UPDATE_FAILED,
+                    "Could not reset password for username: " + username,
+                    username, uriToken, passphrase);
         }
     }
 
@@ -295,9 +311,12 @@
             return this.jdbcTemplate.update(query, np);
         }
         catch (DataAccessException e) {
-            jlog.error("Could not confirm registration for name " + username, e);
-            throw new dbException(username, "korap_users",
-                    StatusCodes.DB_UPDATE_FAILED, username, uriToken);
+            jlog.error("Could not confirm registration for name " + username,
+                    e);
+            throw new DatabaseException(username, "korap_users",
+                    StatusCodes.DB_UPDATE_FAILED,
+                    "Could not confirm registration for username " + username,
+                    username, uriToken);
         }
     }
 
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/OAuthDb.java b/src/main/java/de/ids_mannheim/korap/handlers/OAuthDb.java
index 0be7418..711e6d8 100644
--- a/src/main/java/de/ids_mannheim/korap/handlers/OAuthDb.java
+++ b/src/main/java/de/ids_mannheim/korap/handlers/OAuthDb.java
@@ -3,7 +3,7 @@
 import de.ids_mannheim.korap.config.ClientInfo;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.exceptions.dbException;
+import de.ids_mannheim.korap.exceptions.DatabaseException;
 import de.ids_mannheim.korap.interfaces.db.PersistenceClient;
 import de.ids_mannheim.korap.config.Attributes;
 import de.ids_mannheim.korap.user.TokenContext;
@@ -245,7 +245,7 @@
         catch (DataAccessException e) {
             e.printStackTrace();
             jlog.error("removing client '{}' failed", info.getClient_id());
-            throw new dbException(new KustvaktException(user.getId(),
+            throw new DatabaseException(new KustvaktException(user.getId(),
                     StatusCodes.ILLEGAL_ARGUMENT, "arguments given not valid",
                     info.toJSON()), StatusCodes.CLIENT_REMOVAL_FAILURE,
                     info.toJSON());
@@ -271,7 +271,7 @@
         catch (DataAccessException e) {
             e.printStackTrace();
             jlog.error("registering client '{}' failed", info.getClient_id());
-            throw new dbException(new KustvaktException(user.getId(),
+            throw new DatabaseException(new KustvaktException(user.getId(),
                     StatusCodes.ILLEGAL_ARGUMENT, "arguments given not valid",
                     info.toJSON()), StatusCodes.CLIENT_REGISTRATION_FAILURE,
                     info.toJSON());
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/ResourceDao.java b/src/main/java/de/ids_mannheim/korap/handlers/ResourceDao.java
index cf5701b..1bbabae 100644
--- a/src/main/java/de/ids_mannheim/korap/handlers/ResourceDao.java
+++ b/src/main/java/de/ids_mannheim/korap/handlers/ResourceDao.java
@@ -1,15 +1,9 @@
 package de.ids_mannheim.korap.handlers;
 
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.exceptions.dbException;
-import de.ids_mannheim.korap.interfaces.db.PersistenceClient;
-import de.ids_mannheim.korap.interfaces.db.ResourceOperationIface;
-import de.ids_mannheim.korap.resources.KustvaktResource;
-import de.ids_mannheim.korap.resources.ResourceFactory;
-import de.ids_mannheim.korap.config.Attributes;
-import de.ids_mannheim.korap.user.User;
-import de.ids_mannheim.korap.utils.SqlBuilder;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.dao.DataAccessException;
@@ -19,16 +13,23 @@
 import org.springframework.jdbc.support.GeneratedKeyHolder;
 import org.springframework.jdbc.support.KeyHolder;
 
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
+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.exceptions.DatabaseException;
+import de.ids_mannheim.korap.interfaces.db.PersistenceClient;
+import de.ids_mannheim.korap.interfaces.db.ResourceOperationIface;
+import de.ids_mannheim.korap.resources.KustvaktResource;
+import de.ids_mannheim.korap.resources.ResourceFactory;
+import de.ids_mannheim.korap.user.User;
+import de.ids_mannheim.korap.utils.SqlBuilder;
 
 /**
  * Created by hanl on 7/21/14.
  */
 //todo: auditing // testing
-public class ResourceDao<T extends KustvaktResource> implements
-        ResourceOperationIface<T> {
+public class ResourceDao<T extends KustvaktResource>
+        implements ResourceOperationIface<T> {
 
     private static Logger log = LoggerFactory.getLogger(ResourceDao.class);
     protected final NamedParameterJdbcTemplate jdbcTemplate;
@@ -58,10 +59,13 @@
                     new RowMapperFactory.ResourceMapper());
         }
         catch (DataAccessException e) {
-            log.error("Exception during database retrieval for ids '" + ids
-                    + "'", e);
-            throw new dbException(user.getId(), "resource_store",
-                    StatusCodes.DB_GET_FAILED, ids.toString());
+            log.error(
+                    "Exception during database retrieval for ids '" + ids + "'",
+                    e);
+            throw new DatabaseException(user.getId(), "resource_store",
+                    StatusCodes.DB_GET_FAILED,
+                    "Exception during database retrieval for ids '" + ids,
+                    ids.toString());
         }
 
     }
@@ -73,17 +77,17 @@
         source.addValue("id", resource.getPersistentID());
         source.addValue("name", resource.getName());
         source.addValue("desc", resource.getDescription());
-        source.addValue("data", resource.getData());
+        source.addValue("data", resource.getStringData());
         final String sql = "UPDATE resource_store set name=:name, data=:data, description=:desc where persistent_id=:id;";
         try {
             return this.jdbcTemplate.update(sql, source);
         }
         catch (DataAccessException e) {
-            log.error(
-                    "Exception during database update for id '"
-                            + resource.getPersistentID() + "'", e);
-            throw new dbException(user.getId(), "resource_store",
-                    StatusCodes.DB_UPDATE_FAILED, resource.toString());
+            log.error("Exception during database update for id '"
+                    + resource.getPersistentID() + "'", e);
+            throw new DatabaseException(user.getId(), "resource_store",
+                    StatusCodes.DB_UPDATE_FAILED, "Exception during database update for id '"
+                            + resource.getPersistentID(), resource.toString());
         }
     }
 
@@ -101,12 +105,14 @@
         MapSqlParameterSource source = new MapSqlParameterSource();
         source.addValue("pid", id);
         String sql = "SELECT rs.*, rt.name_path FROM resource_store as rs inner join resource_tree as rt"
-                + " on rs.id=rt.child_id WHERE rs.persistent_id=:pid group by rs.id;";
+                + " on rs.id=rt.child_id WHERE rs.persistent_id=:pid";
+        //group by rs.id;";
         try {
             return (T) this.jdbcTemplate.queryForObject(sql, source,
                     new RowMapperFactory.ResourceMapper());
         }
         catch (DataAccessException e) {
+            // empty results
             return null;
         }
     }
@@ -167,7 +173,8 @@
         b.insert(Attributes.NAME, Attributes.PARENT_ID,
                 Attributes.PERSISTENT_ID, Attributes.DESCRIPTION,
                 Attributes.CREATOR, Attributes.TYPE, Attributes.CREATED);
-        b.params(":name, :parent, :pid, :desc, :ow, :type, :created, :dtype, :data");
+        b.params(
+                ":name, :parent, :pid, :desc, :ow, :type, :created, :dtype, :data");
 
         if (resource.getParentID() == null) {
             sql = "INSERT INTO resource_store (name, parent_id, persistent_id, description, creator, type, created, data) "
@@ -189,18 +196,20 @@
         source.addValue("type",
                 ResourceFactory.getResourceMapping(resource.getClass()));
         source.addValue("created", System.currentTimeMillis());
-        source.addValue("data", resource.getData());
+        source.addValue("data", resource.getStringData());
 
         try {
-            this.jdbcTemplate
-                    .update(sql, source, holder, new String[] { "id" });
+            this.jdbcTemplate.update(sql, source, holder,
+                    new String[] { "id" });
         }
         catch (DataAccessException e) {
-            log.error(
+            log.error("Exception during database store for id '"
+                    + resource.getPersistentID() + "'", e);
+            throw new DatabaseException(user.getId(), "resource_store",
+                    StatusCodes.DB_INSERT_FAILED,
                     "Exception during database store for id '"
-                            + resource.getPersistentID() + "'", e);
-            throw new dbException(user.getId(), "resource_store",
-                    StatusCodes.DB_INSERT_FAILED, resource.toString());
+                            + resource.getPersistentID(),
+                    resource.toString());
         }
         resource.setId(holder.getKey().intValue());
         return resource.getId();
@@ -216,8 +225,9 @@
             return this.jdbcTemplate.update(sql, source);
         }
         catch (DataAccessException e) {
-            throw new dbException(user.getId(), "resource_store",
-                    StatusCodes.DB_DELETE_FAILED, id);
+            throw new DatabaseException(user.getId(), "resource_store",
+                    StatusCodes.DB_DELETE_FAILED, "Operation DELETE failed.",
+                    id);
         }
     }
 
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/UserDetailsDao.java b/src/main/java/de/ids_mannheim/korap/handlers/UserDetailsDao.java
index ddfe851..0d6004e 100644
--- a/src/main/java/de/ids_mannheim/korap/handlers/UserDetailsDao.java
+++ b/src/main/java/de/ids_mannheim/korap/handlers/UserDetailsDao.java
@@ -2,7 +2,7 @@
 
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.exceptions.dbException;
+import de.ids_mannheim.korap.exceptions.DatabaseException;
 import de.ids_mannheim.korap.interfaces.db.PersistenceClient;
 import de.ids_mannheim.korap.interfaces.db.UserDataDbIface;
 import de.ids_mannheim.korap.user.User;
@@ -70,7 +70,7 @@
 
 
     @Override
-    public UserDetails get (Integer id) throws dbException {
+    public UserDetails get (Integer id) throws DatabaseException {
         String sql = "SELECT * FROM user_details WHERE id=:id;";
         MapSqlParameterSource source = new MapSqlParameterSource();
         source.addValue("id", id);
@@ -95,14 +95,15 @@
             return null;
         }
         catch (DataAccessException e) {
-            throw new dbException(-1, "userDetails",
-                    StatusCodes.REQUEST_INVALID, String.valueOf(id));
+            throw new DatabaseException(-1, "userDetails",
+                    StatusCodes.REQUEST_INVALID, "The request is invalid.",
+                    String.valueOf(id));
         }
     }
 
 
     @Override
-    public UserDetails get (User user) throws dbException {
+    public UserDetails get (User user) throws DatabaseException {
         String sql = "SELECT * FROM user_details WHERE user_id=:userid;";
         MapSqlParameterSource source = new MapSqlParameterSource();
         source.addValue("userid", user.getId());
@@ -126,8 +127,8 @@
             return null;
         }
         catch (DataAccessException e) {
-            throw new dbException(user.getId(), "userDetails",
-                    StatusCodes.REQUEST_INVALID);
+            throw new DatabaseException(user.getId(), "userDetails",
+                    StatusCodes.REQUEST_INVALID, "The request is invalid.");
         }
     }
 
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/UserSettingsDao.java b/src/main/java/de/ids_mannheim/korap/handlers/UserSettingsDao.java
index fdc6ba5..dbd3c25 100644
--- a/src/main/java/de/ids_mannheim/korap/handlers/UserSettingsDao.java
+++ b/src/main/java/de/ids_mannheim/korap/handlers/UserSettingsDao.java
@@ -2,7 +2,7 @@
 
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.exceptions.dbException;
+import de.ids_mannheim.korap.exceptions.DatabaseException;
 import de.ids_mannheim.korap.interfaces.db.PersistenceClient;
 import de.ids_mannheim.korap.interfaces.db.UserDataDbIface;
 import de.ids_mannheim.korap.user.User;
@@ -76,7 +76,7 @@
 
 
     @Override
-    public UserSettings get (Integer id) throws dbException {
+    public UserSettings get (Integer id) throws DatabaseException {
         String sql = "SELECT * FROM user_settings WHERE id=:id;";
         MapSqlParameterSource source = new MapSqlParameterSource();
         source.addValue("id", id);
@@ -88,8 +88,8 @@
                         @Override
                         public UserSettings mapRow (ResultSet rs, int rowNum)
                                 throws SQLException {
-                            UserSettings details = new UserSettings(rs
-                                    .getInt("user_id"));
+                            UserSettings details = new UserSettings(
+                                    rs.getInt("user_id"));
                             details.setId(rs.getInt("id"));
                             details.setData(rs.getString("data"));
                             return details;
@@ -101,14 +101,15 @@
             return null;
         }
         catch (DataAccessException e) {
-            throw new dbException(-1, "userSettings",
-                    StatusCodes.REQUEST_INVALID, String.valueOf(id));
+            throw new DatabaseException(-1, "userSettings",
+                    StatusCodes.REQUEST_INVALID, "The request is invalid.",
+                    String.valueOf(id));
         }
     }
 
 
     @Override
-    public UserSettings get (User user) throws dbException {
+    public UserSettings get (User user) throws DatabaseException {
         String sql = "SELECT * FROM user_settings WHERE user_id=:userid;";
         MapSqlParameterSource source = new MapSqlParameterSource();
         source.addValue("userid", user.getId());
@@ -120,8 +121,8 @@
                         @Override
                         public UserSettings mapRow (ResultSet rs, int rowNum)
                                 throws SQLException {
-                            UserSettings details = new UserSettings(rs
-                                    .getInt("user_id"));
+                            UserSettings details = new UserSettings(
+                                    rs.getInt("user_id"));
                             details.setId(rs.getInt("id"));
                             details.setData(rs.getString("data"));
                             return details;
@@ -133,8 +134,8 @@
             return null;
         }
         catch (DataAccessException e) {
-            throw new dbException(-1, "userSettings",
-                    StatusCodes.REQUEST_INVALID);
+            throw new DatabaseException(-1, "userSettings",
+                    StatusCodes.REQUEST_INVALID, "The request is invalid.");
         }
     }
 
diff --git a/src/main/java/de/ids_mannheim/korap/interfaces/ValidatorIface.java b/src/main/java/de/ids_mannheim/korap/interfaces/ValidatorIface.java
index 7fe20c6..e8fb3c6 100644
--- a/src/main/java/de/ids_mannheim/korap/interfaces/ValidatorIface.java
+++ b/src/main/java/de/ids_mannheim/korap/interfaces/ValidatorIface.java
@@ -10,7 +10,7 @@
 public interface ValidatorIface {
 
 
-    Map<String, Object> validateMap (Map<String, Object> map);
+    Map<String, Object> validateMap (Map<String, Object> map) throws KustvaktException;
 
 
     String validateEntry (String input, String type)
diff --git a/src/main/java/de/ids_mannheim/korap/interfaces/db/AdminHandlerIface.java b/src/main/java/de/ids_mannheim/korap/interfaces/db/AdminHandlerIface.java
new file mode 100644
index 0000000..f9f56d6
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/interfaces/db/AdminHandlerIface.java
@@ -0,0 +1,24 @@
+package de.ids_mannheim.korap.interfaces.db;
+
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.user.User;
+
+/**
+ * @author margaretha
+ */
+public interface AdminHandlerIface {
+
+    int updateAccount (User user) throws KustvaktException;
+
+
+    int addAccount (User user) throws KustvaktException;
+
+
+    int deleteAccount (Integer userid) throws KustvaktException;
+
+
+    int truncate () throws KustvaktException;
+
+	boolean isAdmin(int userId);
+
+}
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/interfaces/defaults/ApacheValidator.java b/src/main/java/de/ids_mannheim/korap/interfaces/defaults/ApacheValidator.java
index 8d420ec..1b9477a 100644
--- a/src/main/java/de/ids_mannheim/korap/interfaces/defaults/ApacheValidator.java
+++ b/src/main/java/de/ids_mannheim/korap/interfaces/defaults/ApacheValidator.java
@@ -21,14 +21,16 @@
 
     private static Logger jlog = LoggerFactory.getLogger(ApacheValidator.class);
 
-    private static final String STRING_PATTERN ="^[\\.;:,&\\|@\\[\\]\\=\\*\\/\\/_()\\-0-9\\p{L}\\p{Space}]{0,1024}$";
+    private static final String STRING_PATTERN = "^[\\.;:,&\\|@\\[\\]\\=\\*\\/\\/_()\\-0-9\\p{L}\\p{Space}]{0,1024}$";
 
     private Map<String, RegexValidator> validators;
 
+
     public ApacheValidator () throws IOException {
         this.validators = load();
     }
 
+
     private static Map<String, RegexValidator> load () throws IOException {
         Map<String, RegexValidator> validatorMap = new HashMap<>();
         Properties p = ConfigLoader.loadProperties("validation.properties");
@@ -36,7 +38,8 @@
         for (String property : p.stringPropertyNames()) {
             if (property.startsWith("Validator")) {
                 String name = property.replace("Validator.", "");
-                RegexValidator v = new RegexValidator(p.get(property).toString());
+                RegexValidator v = new RegexValidator(
+                        p.get(property).toString());
                 validatorMap.put(name, v);
             }
         }
@@ -46,31 +49,38 @@
 
 
     @Override
-    public Map<String, Object> validateMap (Map<String, Object> map) {
+    public Map<String, Object> validateMap (Map<String, Object> map)
+            throws KustvaktException {
         Map<String, Object> safeMap = new HashMap<>();
         KustvaktMap kmap = new KustvaktMap(map);
 
         if (map != null) {
-                loop : for (String key : kmap.keySet()) {
-                    Object value = kmap.getRaw(key);
-                    if (value instanceof List) {
-                        List list = (List) value;
-                        for (int i =0;i<list.size();i++) {
-                            if (!isValid(String.valueOf(list.get(i)), key))
-                                list.remove(i);
+            loop: for (String key : kmap.keySet()) {
+                Object value = kmap.getRaw(key);
+                if (value instanceof List) {
+                    List list = (List) value;
+                    for (int i = 0; i < list.size(); i++) {
+                        if (!isValid(String.valueOf(list.get(i)), key)) {
+                            //                                list.remove(i);
+                            throw new KustvaktException(
+                                    StatusCodes.ILLEGAL_ARGUMENT,
+                                    "The value for the parameter " + key
+                                            + " is not valid or acceptable.");
                         }
-
-                        if (list.size() == 1)
-                            value = list.get(0);
-                        else
-                            value = list;
-                    } else {
-                        if (!isValid(kmap.get(key), key))
-                          continue loop;
                     }
-                    safeMap.put(key, value);
+
+                    if (list.size() == 1)
+                        value = list.get(0);
+                    else
+                        value = list;
                 }
+                else {
+                    if (!isValid(kmap.get(key), key))
+                        continue loop;
+                }
+                safeMap.put(key, value);
             }
+        }
         return safeMap;
     }
 
@@ -84,26 +94,31 @@
         return input;
     }
 
+
     @Override
-    public boolean isValid(String input, String type) {
+    public boolean isValid (String input, String type) {
         boolean valid = false;
         RegexValidator validator = this.validators.get(type);
         if (validator != null) {
             valid = validator.isValid(input);
-        } else {
+        }
+        else {
             if (Attributes.EMAIL.equals(type)) {
                 valid = EmailValidator.getInstance().isValid(input);
-            } else if ("date".equals(type)) {
+            }
+            else if ("date".equals(type)) {
                 valid = DateValidator.getInstance().isValid(input);
-            } else if ("string".equals(type) && !this.validators.containsKey("string")) {
+            }
+            else if ("string".equals(type)
+                    && !this.validators.containsKey("string")) {
                 RegexValidator regex = new RegexValidator(STRING_PATTERN);
                 valid = regex.isValid(input);
             }
             else
                 return this.isValid(input, "string");
         }
-        jlog.debug("validating entry '{}' of type '{}': {}",
-                input, type, valid ? "Is valid!" : "Is not valid!");
+        jlog.debug("validating entry '{}' of type '{}': {}", input, type,
+                valid ? "Is valid!" : "Is not valid!");
         return valid;
     }
 }
diff --git a/src/main/java/de/ids_mannheim/korap/resources/ResourceFactory.java b/src/main/java/de/ids_mannheim/korap/resources/ResourceFactory.java
index 21ceaa7..76cc144 100644
--- a/src/main/java/de/ids_mannheim/korap/resources/ResourceFactory.java
+++ b/src/main/java/de/ids_mannheim/korap/resources/ResourceFactory.java
@@ -2,6 +2,8 @@
 
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
+import de.ids_mannheim.korap.utils.JsonUtils;
+
 import org.apache.commons.codec.digest.DigestUtils;
 
 import java.util.ArrayList;
@@ -65,15 +67,21 @@
 
 
     public static <T extends KustvaktResource> T createID (T resource) {
-        if (resource.getData() != null && !resource.getStringData().isEmpty())
-            resource.setPersistentID(DigestUtils.sha1Hex(resource
-                    .getStringData()));
+        if (resource.getData() != null && !resource.getStringData().isEmpty()){
+        	resource.setPersistentID(DigestUtils.sha1Hex(JsonUtils.toJSON(resource)));        	
+        }
         return resource;
     }
 
 
     public static <T extends KustvaktResource> Class<T> getResourceClass (
             String type) throws KustvaktException {
+        
+        if (type == null || type.isEmpty()){
+            throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT, 
+                    "resource type could not be identified!");
+        }
+        
         for (Class value : subTypes) {
             if (value == VirtualCollection.class
                     && type.equalsIgnoreCase("collection"))
@@ -86,7 +94,8 @@
             }
         }
         // todo: throw exception in case of missing parameter!
-        throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT, "resource type could not be identified!");
+        throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT, 
+                "resource type could not be identified!");
     }
 
 
diff --git a/src/main/java/de/ids_mannheim/korap/resources/VirtualCollection.java b/src/main/java/de/ids_mannheim/korap/resources/VirtualCollection.java
index cf87bff..bda1eea 100644
--- a/src/main/java/de/ids_mannheim/korap/resources/VirtualCollection.java
+++ b/src/main/java/de/ids_mannheim/korap/resources/VirtualCollection.java
@@ -38,8 +38,9 @@
         if (resource == null | !(resource instanceof VirtualCollection))
             return;
         VirtualCollection other = (VirtualCollection) resource;
-        this.setFields(this.getFields() == null ? other.getFields() : this
-                .getFields());
+        if (this.getFields() == null || this.getFields().isEmpty()){
+        	setFields(other.getFields());
+        }
     }
 
 
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 a9bcf3a..72b52bc 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
@@ -2,9 +2,10 @@
 
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.exceptions.dbException;
+import de.ids_mannheim.korap.exceptions.DatabaseException;
 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;
@@ -65,16 +66,19 @@
                 + " SELECT id, :creator, :cr, :posix, :en, :exp, :ip FROM resource_store WHERE persistent_id=:target;";
 
         if (policy.getTarget() == null)
-            throw new dbException(user.getId(), "policy_store",
-                    StatusCodes.NO_POLICY_TARGET, policy.toString());
+            throw new DatabaseException(user.getId(), "policy_store",
+                    StatusCodes.NO_POLICY_TARGET, "Persistent id is missing.",
+                    policy.toString());
 
         if (policy.getConditions().isEmpty())
-            throw new dbException(user.getId(), "policy_store",
-                    StatusCodes.NO_POLICY_CONDITION);
+            throw new DatabaseException(user.getId(), "policy_store",
+                    StatusCodes.NO_POLICY_CONDITION,
+                    "Policy conditions are missing.");
 
         if (policy.getPermissionByte() == 0)
-            throw new dbException(user.getId(), "policy_store",
-                    StatusCodes.NO_POLICY_PERMISSION);
+            throw new DatabaseException(user.getId(), "policy_store",
+                    StatusCodes.NO_POLICY_PERMISSION,
+                    "Policy permissions are missing.");
 
         KeyHolder keyHolder = new GeneratedKeyHolder();
         MapSqlParameterSource np = new MapSqlParameterSource();
@@ -98,10 +102,9 @@
         }
         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",
+            throw new DatabaseException(user.getId(), "policy_store",
                     StatusCodes.DB_INSERT_FAILED, policy.toString());
         }
     }
@@ -117,7 +120,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 +132,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 +147,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 +178,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,15 +196,19 @@
                     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(
                         "Operation (SELECT) not possible for '{}' for user '{}'",
                         policy.getTarget(), user.getId());
-                throw new dbException(user.getId(), "policy_store",
-                        StatusCodes.DB_GET_FAILED, policy.toString());
+                throw new DatabaseException(user.getId(), "policy_store",
+                        StatusCodes.DB_GET_FAILED,
+                        "Operation (SELECT) is not possible for "
+                                + policy.getTarget() + " for user "
+                                + user.getUsername(),
+                        policy.toString());
             }
         }
     }
@@ -213,7 +222,7 @@
         param.addValue("target", target);
         param.addValue("userid", user.getId());
         param.addValue("perm", perm);
-        param.addValue("en", new Timestamp(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 \n"
                 + "where child_id=rh.child_id) as max_depth from policy_view as pv "
@@ -252,7 +261,7 @@
         param.addValue("cond", condition.getSpecifier());
         param.addValue("perm", perm);
         param.addValue("type", ResourceFactory.getResourceMapping(clazz));
-        param.addValue("en", new Timestamp(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 "
                 + "where child_id=rh.child_id) as max_depth from policy_view as pv "
@@ -283,6 +292,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,
             Byte perm) {
@@ -290,7 +343,7 @@
         param.addValue("target", target);
         param.addValue("userid", user.getId());
         param.addValue("perm", perm);
-        param.addValue("en", new Timestamp(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 "
@@ -331,7 +384,7 @@
         param.addValue("path", StringUtils.buildSQLRegex(path));
         param.addValue("userid", user.getId());
         param.addValue("perm", perm);
-        param.addValue("en", new Timestamp(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 "
@@ -424,8 +477,11 @@
             jlog.error(
                     "Permission Denied for retrieval for path '{}' for user '{}'",
                     path, user.getId());
-            throw new dbException(user.getId(), "policy_store",
-                    StatusCodes.DB_GET_FAILED, path, clazz.toString());
+            throw new DatabaseException(user.getId(), "policy_store",
+                    StatusCodes.DB_GET_FAILED,
+                    "Permission is denied for retrieval for path " + path
+                            + " for user " + user.getUsername(),
+                    path, clazz.toString());
         }
     }
 
@@ -481,8 +537,11 @@
             jlog.error(
                     "Permission Denied for retrieval for path '{}' for user '{}'",
                     name, user.getId());
-            throw new dbException(user.getId(), "policy_store",
-                    StatusCodes.DB_GET_FAILED, name, clazz.toString());
+            throw new DatabaseException(user.getId(), "policy_store",
+                    StatusCodes.DB_GET_FAILED,
+                    "Permission is denied for retrieval for path " + name
+                            + "for user" + user.getUsername() + ".",
+                    name, clazz.toString());
         }
     }
 
@@ -491,6 +550,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,17 +559,18 @@
         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());
+            throw new DatabaseException(user.getId(), "policy_store, group_ref",
+                    StatusCodes.DB_DELETE_FAILED,
+                    "Operation (DELETE) is not possible for user.",
+                    policy.toString());
         }
     }
 
@@ -524,11 +585,13 @@
             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);
+            throw new DatabaseException(user.getId(), "policy_store",
+                    StatusCodes.DB_DELETE_FAILED,
+                    "Operation (DELETE) is not possible for user "
+                            + user.getUsername(),
+                    id);
         }
     }
 
@@ -549,11 +612,13 @@
             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());
+            throw new DatabaseException(user.getId(), "policy_store",
+                    StatusCodes.DB_UPDATE_FAILED,
+                    "Operation (UPDATE) on " + policy.toString()
+                            + " is not possible for user" + user.getUsername(),
+                    policy.toString());
         }
     }
 
@@ -572,11 +637,13 @@
             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());
+            throw new DatabaseException(user.getId(), "policy_store",
+                    StatusCodes.DB_GET_FAILED,
+                    "Operation (SELECT) on " + policy.getTarget()
+                            + " is not possible for user " + user.getUsername(),
+                    policy.toString());
         }
     }
 
@@ -614,11 +681,13 @@
             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);
+            throw new DatabaseException(user.getId(), "policy_store",
+                    StatusCodes.DB_GET_FAILED,
+                    "Operation (SELECT) is not possible for user "
+                            + user.getUsername(),
+                    group);
         }
     }
 
@@ -633,15 +702,17 @@
         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) {
             jlog.error("Operation (INSERT) not possible for '{}'",
                     condition.toString());
-            throw new dbException(user.getId(), "group_store",
-                    StatusCodes.DB_INSERT_FAILED, condition.toString());
+            throw new DatabaseException(user.getId(), "group_store",
+                    StatusCodes.DB_INSERT_FAILED,
+                    "Operation (INSERT) is not possible for",
+                    condition.toString());
         }
     }
 
@@ -662,12 +733,16 @@
         }
         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);
-                throw new dbException(null, "group_store",
-                        StatusCodes.DB_INSERT_FAILED, condition.toString());
+                throw new DatabaseException(null, "group_store",
+                        StatusCodes.DB_INSERT_FAILED,
+                        "Operation (INSERT) on " + condition.toString()
+                                + " is not possible for user " + username,
+                        condition.toString());
             }
             return 0;
         }
@@ -731,8 +806,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 +834,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 +887,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 +934,4 @@
             return 0;
         }
     }
-
 }
diff --git a/src/main/java/de/ids_mannheim/korap/security/ac/PolicyEvaluator.java b/src/main/java/de/ids_mannheim/korap/security/ac/PolicyEvaluator.java
index 0fbe1d1..928ca77 100644
--- a/src/main/java/de/ids_mannheim/korap/security/ac/PolicyEvaluator.java
+++ b/src/main/java/de/ids_mannheim/korap/security/ac/PolicyEvaluator.java
@@ -172,7 +172,8 @@
 
 
     public boolean isManaged () {
-        return getOwner(this.policies[0]) == KorAPUser.ADMINISTRATOR_ID;
+        //return getOwner(this.policies[0]) == KorAPUser.ADMINISTRATOR_ID;
+    	return false;
     }
 
 
diff --git a/src/main/java/de/ids_mannheim/korap/security/ac/ResourceFinder.java b/src/main/java/de/ids_mannheim/korap/security/ac/ResourceFinder.java
index c319145..380481d 100644
--- a/src/main/java/de/ids_mannheim/korap/security/ac/ResourceFinder.java
+++ b/src/main/java/de/ids_mannheim/korap/security/ac/ResourceFinder.java
@@ -4,6 +4,7 @@
 import de.ids_mannheim.korap.config.BeansFactory;
 import de.ids_mannheim.korap.exceptions.EmptyResultException;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.interfaces.db.PolicyHandlerIface;
 import de.ids_mannheim.korap.interfaces.db.ResourceOperationIface;
 import de.ids_mannheim.korap.resources.KustvaktResource;
@@ -101,7 +102,37 @@
         return searchPublicFiltered(clazz);
     }
 
-
+    public static <T extends KustvaktResource> Set<T> searchPublicFilteredIntId (
+            Class<T> clazz, int ... ids) throws KustvaktException {
+        
+        overrideProviders(null);
+        Set<T> sets = new HashSet<>();
+       
+        List<SecurityPolicy> policies = policydao.getPolicies(
+                new PolicyCondition(Attributes.PUBLIC_GROUP), clazz,
+                Permissions.Permission.READ.toByte());
+        ArrayList<Integer> id_set = new ArrayList<>(ids.length);
+        for(int id : ids){
+            id_set.add(id);
+        }
+        
+        for (SecurityPolicy policy : policies) {
+            jlog.debug("PolicyID retrieved: "+policy.getID()+" "+policy.getTarget());
+            if (id_set.isEmpty() || id_set.contains(policy.getID())) {
+                @SuppressWarnings("unchecked")
+                T r = (T) resourcedaos.get(KustvaktResource.class).findbyId(
+                        policy.getID(), User.UserFactory.getDemoUser());
+                sets.add(r);
+            }
+        }
+        
+        if (sets.isEmpty()){
+            throw new KustvaktException(StatusCodes.NO_VALUE_FOUND, 
+                    "Cannot found public resources with ids: "+id_set.toString());
+        }
+        return sets;
+    }
+    
     public static <T extends KustvaktResource> Set<T> searchPublicFiltered (
             Class<T> clazz, String ... ids) throws KustvaktException {
         overrideProviders(null);
@@ -113,14 +144,17 @@
         List<String> id_set = Arrays.asList(ids);
         for (SecurityPolicy policy : policies) {
             if (id_set.isEmpty() || id_set.contains(policy.getTarget())) {
+                @SuppressWarnings("unchecked")
                 T r = (T) resourcedaos.get(KustvaktResource.class).findbyId(
                         policy.getTarget(), User.UserFactory.getDemoUser());
                 sets.add(r);
             }
         }
 
-        if (sets.isEmpty())
-            throw new EmptyResultException(Arrays.asList(ids).toString());
+        if (sets.isEmpty()){
+            throw new KustvaktException(StatusCodes.NO_VALUE_FOUND, 
+                    "Cannot found public resources with ids: "+id_set.toString());
+        }
         return sets;
     }
 
diff --git a/src/main/java/de/ids_mannheim/korap/security/ac/SecurityManager.java b/src/main/java/de/ids_mannheim/korap/security/ac/SecurityManager.java
index 7e750f9..6a71682 100644
--- a/src/main/java/de/ids_mannheim/korap/security/ac/SecurityManager.java
+++ b/src/main/java/de/ids_mannheim/korap/security/ac/SecurityManager.java
@@ -131,8 +131,7 @@
 
 
     public static SecurityManager findbyPath (String path, User user,
-            Permissions.Permission ... perms) throws NotAuthorizedException,
-            EmptyResultException {
+            Permissions.Permission ... perms) throws KustvaktException {
         SecurityManager manager = new SecurityManager(user);
         manager.findPolicies(path, true, perms);
         //fixme: need a match count. if match not unique, exception. also, does parent -child relation match hold up here?
@@ -141,8 +140,7 @@
 
 
     public static SecurityManager init (String id, User user,
-            Permissions.Permission ... perms) throws NotAuthorizedException,
-            EmptyResultException {
+            Permissions.Permission ... perms) throws KustvaktException  {
         SecurityManager p = new SecurityManager(user);
         p.findPolicies(id, false, perms);
         return p;
@@ -216,7 +214,7 @@
 
     // todo: type should be deprecated and return type of policies should be containers!
     private boolean findPolicies (Object id, boolean path,
-            Permissions.Permission ... perms) throws EmptyResultException {
+            Permissions.Permission ... perms) throws KustvaktException {
         PermissionsBuffer b = new PermissionsBuffer();
         if (perms.length == 0)
             b.addPermission(Permissions.Permission.READ.toByte());
@@ -231,12 +229,14 @@
         if (id instanceof Integer)
             this.policies = policydao.getPolicies((Integer) id, this.user,
                     b.getPbyte());
+        
         this.evaluator = new PolicyEvaluator(this.user, this.policies);
 
         if (this.policies == null) {
             jlog.error("No policies found for resource id '{}' for user '{}'",
                     id, user.getId());
-            throw new EmptyResultException(String.valueOf(id));
+            throw new KustvaktException(StatusCodes.NO_VALUE_FOUND, "Resource not found!",
+                    String.valueOf(id));
         }
         return true;
     }
diff --git a/src/main/java/de/ids_mannheim/korap/security/auth/KustvaktAuthenticationManager.java b/src/main/java/de/ids_mannheim/korap/security/auth/KustvaktAuthenticationManager.java
index 3f04e5b..483f292 100644
--- a/src/main/java/de/ids_mannheim/korap/security/auth/KustvaktAuthenticationManager.java
+++ b/src/main/java/de/ids_mannheim/korap/security/auth/KustvaktAuthenticationManager.java
@@ -11,6 +11,7 @@
 import de.ids_mannheim.korap.interfaces.AuthenticationManagerIface;
 import de.ids_mannheim.korap.interfaces.EncryptionIface;
 import de.ids_mannheim.korap.interfaces.ValidatorIface;
+import de.ids_mannheim.korap.interfaces.db.AdminHandlerIface;
 import de.ids_mannheim.korap.interfaces.db.AuditingIface;
 import de.ids_mannheim.korap.interfaces.db.EntityHandlerIface;
 import de.ids_mannheim.korap.interfaces.db.UserDataDbIface;
@@ -46,18 +47,21 @@
             .getLogger(KustvaktAuthenticationManager.class);
     private EncryptionIface crypto;
     private EntityHandlerIface entHandler;
+    private AdminHandlerIface adminHandler;
     private AuditingIface auditing;
     private KustvaktConfiguration config;
     private Collection userdatadaos;
     private LoginCounter counter;
     private ValidatorIface validator;
 
-    public KustvaktAuthenticationManager (EntityHandlerIface userdb,
+    public KustvaktAuthenticationManager (EntityHandlerIface userdb, 
+    									  AdminHandlerIface admindb,
                                           EncryptionIface crypto,
                                           KustvaktConfiguration config,
                                           AuditingIface auditer,
                                           Collection<UserDataDbIface> userdatadaos) {
         this.entHandler = userdb;
+        this.adminHandler = admindb;
         this.config = config;
         this.crypto = crypto;
         this.auditing = auditer;
@@ -268,7 +272,11 @@
                         attributes.toString());
             }
         }
+        
+        boolean isAdmin = adminHandler.isAdmin(unknown.getId());
+        unknown.setAdmin(isAdmin);
         jlog.trace("Authentication: found username " + unknown.getUsername());
+        
         if (unknown instanceof KorAPUser) {
             if (password == null || password.isEmpty())
                 throw new WrappedException(new KustvaktException(
@@ -692,6 +700,11 @@
             user.addField(param);
         }
         user.setPassword(hash);
+        
+        String o = (String) attributes.get(Attributes.IS_ADMIN);
+		boolean b = Boolean.parseBoolean(o);
+		user.setAdmin(b);
+        
         try {
             UserDetails details = new UserDetails();
             details.read(safeMap, true);
@@ -702,6 +715,9 @@
             jlog.info("Creating new user account for user {}",
                     user.getUsername());
             entHandler.createAccount(user);
+            if (user.isAdmin() && user instanceof KorAPUser){
+            	adminHandler.addAccount(user);
+            }
             details.setUserId(user.getId());
             settings.setUserId(user.getId());
 
diff --git a/src/main/java/de/ids_mannheim/korap/user/DataFactory.java b/src/main/java/de/ids_mannheim/korap/user/DataFactory.java
index 0e59f53..5d3f85f 100644
--- a/src/main/java/de/ids_mannheim/korap/user/DataFactory.java
+++ b/src/main/java/de/ids_mannheim/korap/user/DataFactory.java
@@ -50,7 +50,7 @@
 
     public abstract Collection<Object> values (Object data);
 
-    public abstract Object validate(Object data, ValidatorIface validator);
+    public abstract Object validate(Object data, ValidatorIface validator) throws KustvaktException;
 
     @Deprecated
     public abstract Map<String, Object> fields (Object data);
@@ -123,7 +123,7 @@
         }
 
         @Override
-        public Object validate(Object data, ValidatorIface validator) {
+        public Object validate(Object data, ValidatorIface validator) throws KustvaktException {
             if (checkDataType(data) && ((JsonNode) data).isObject()) {
                 try {
                     Map mdata = JsonUtils.read(toStringValue(data), HashMap.class);
diff --git a/src/main/java/de/ids_mannheim/korap/user/User.java b/src/main/java/de/ids_mannheim/korap/user/User.java
index 7cf211d..53c3d1e 100644
--- a/src/main/java/de/ids_mannheim/korap/user/User.java
+++ b/src/main/java/de/ids_mannheim/korap/user/User.java
@@ -21,8 +21,8 @@
 @Data
 public abstract class User implements Serializable {
 
-    public static final int ADMINISTRATOR_ID = 34349733;
-    public static final String ADMINISTRATOR_NAME = "admin";
+//    public static final int ADMINISTRATOR_ID = 34349733;
+//    public static final String ADMINISTRATOR_NAME = "admin";
 
     private Integer id;
     // in local its username, in shib it's edupersonPrincipalName
@@ -44,6 +44,7 @@
 
     private List<Userdata> userdata;
 
+    private boolean isAdmin;
 
     protected User () {
         this.fields = new ParamFields();
@@ -134,10 +135,9 @@
         return true;
     }
 
-
-    public boolean isAdmin () {
-        return this.getUsername().equals(ADMINISTRATOR_ID);
-    }
+//    public boolean isAdmin () {
+//        return this.getUsername().equals(ADMINISTRATOR_ID);
+//    }
 
 
     protected abstract User clone ();
@@ -164,10 +164,9 @@
             return user;
         }
 
-
-        public static KorAPUser getAdmin () {
-            return new KorAPUser(ADMINISTRATOR_ID, ADMINISTRATOR_NAME);
-        }
+//        public static KorAPUser getAdmin () {
+//            return new KorAPUser(ADMINISTRATOR_ID, ADMINISTRATOR_NAME);
+//        }
 
 
         public static DemoUser getDemoUser () {
diff --git a/src/main/java/de/ids_mannheim/korap/utils/UserPropertyReader.java b/src/main/java/de/ids_mannheim/korap/utils/UserPropertyReader.java
index 544ceef..d98de46 100644
--- a/src/main/java/de/ids_mannheim/korap/utils/UserPropertyReader.java
+++ b/src/main/java/de/ids_mannheim/korap/utils/UserPropertyReader.java
@@ -21,6 +21,8 @@
 /**
  * @author hanl
  * @date 30/09/2014
+ * 
+ * EM: where is this used?
  */
 public class UserPropertyReader extends PropertyReader {
 
@@ -70,23 +72,23 @@
     private User createUser (String username, Properties p)
             throws KustvaktException {
         KorAPUser user;
-        if (username.equals(User.ADMINISTRATOR_NAME)) {
-            user = User.UserFactory.getAdmin();
-
-            String pass = p.getProperty(username + ".password", null);
-            if (pass == null)
-                throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT);
-
-            try {
-                pass = crypto.secureHash(pass);
-            }
-            catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
-                throw new KustvaktException(StatusCodes.REQUEST_INVALID);
-            }
-            user.setPassword(pass);
-            iface.createAccount(user);
-        }
-        else {
+//        if (username.equals(User.ADMINISTRATOR_NAME)) {
+//            user = User.UserFactory.getAdmin();
+//
+//            String pass = p.getProperty(username + ".password", null);
+//            if (pass == null)
+//                throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT);
+//
+//            try {
+//                pass = crypto.secureHash(pass);
+//            }
+//            catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
+//                throw new KustvaktException(StatusCodes.REQUEST_INVALID);
+//            }
+//            user.setPassword(pass);
+//            iface.createAccount(user);
+//        }
+//        else {
             user = User.UserFactory.getUser(username);
             Map<String, Object> vals = new HashMap<>();
             for (Map.Entry e : p.entrySet()) {
@@ -132,7 +134,7 @@
                     BeansFactory.getKustvaktContext().getUserDataProviders(),
                     UserSettings.class);
             dao.store(set);
-        }
+//        }
 
         jlog.info("successfully created account for user {}",
                 user.getUsername());
diff --git a/src/main/java/de/ids_mannheim/korap/web/KustvaktBaseServer.java b/src/main/java/de/ids_mannheim/korap/web/KustvaktBaseServer.java
index 85e4bc5..13b6d23 100644
--- a/src/main/java/de/ids_mannheim/korap/web/KustvaktBaseServer.java
+++ b/src/main/java/de/ids_mannheim/korap/web/KustvaktBaseServer.java
@@ -107,15 +107,15 @@
 
 	            server.setHandler(contextHandler);
 
-            if (kargs.sslContext != null) {
-                SslSocketConnector sslConnector = new SslSocketConnector(
-                        kargs.sslContext);
-                sslConnector.setPort(8443);
-                sslConnector.setMaxIdleTime(60000);
-                server.setConnectors(new Connector[] { connector, sslConnector });
-            }
-            else
-                server.setConnectors(new Connector[] { connector });
+//            if (kargs.sslContext != null) {
+//                SslSocketConnector sslConnector = new SslSocketConnector(
+//                        kargs.sslContext);
+//                sslConnector.setPort(8443);
+//                sslConnector.setMaxIdleTime(60000);
+//                server.setConnectors(new Connector[] { connector, sslConnector });
+//            }
+//            else
+            server.setConnectors(new Connector[] { connector });
 
             server.start();
             server.join();
diff --git a/src/main/java/de/ids_mannheim/korap/web/SearchKrill.java b/src/main/java/de/ids_mannheim/korap/web/SearchKrill.java
index 16f4506..7441edd 100644
--- a/src/main/java/de/ids_mannheim/korap/web/SearchKrill.java
+++ b/src/main/java/de/ids_mannheim/korap/web/SearchKrill.java
@@ -1,21 +1,21 @@
 // Connector to the Lucene Backend
 package de.ids_mannheim.korap.web;
 
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Paths;
+import java.util.List;
+
+import org.apache.lucene.store.MMapDirectory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import de.ids_mannheim.korap.Krill;
 import de.ids_mannheim.korap.KrillCollection;
 import de.ids_mannheim.korap.KrillIndex;
 import de.ids_mannheim.korap.response.Match;
 import de.ids_mannheim.korap.response.Result;
 import de.ids_mannheim.korap.util.QueryException;
-import de.ids_mannheim.korap.utils.KustvaktLogger;
-import org.apache.lucene.store.MMapDirectory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.nio.file.Paths;
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
 
 /**
  * The SearchKrill class allows for searching in the
@@ -24,7 +24,6 @@
  * @author Nils Diewald
  */
 public class SearchKrill {
-    private final static Logger qlog = KustvaktLogger.getLogger("queryLogger");
     private final static Logger jlog = LoggerFactory
             .getLogger(SearchKrill.class);
 
@@ -34,7 +33,6 @@
     String klinux10 = "/vol/work/hanl/indices";
     private KrillIndex index;
 
-
     /**
      * Constructor
      */
@@ -61,7 +59,6 @@
         };
     };
 
-
     public KrillIndex getIndex () {
         return this.index;
     };
@@ -75,7 +72,7 @@
      *            filters.
      */
     public String search (String json) {
-        qlog.trace(json);
+        jlog.trace(json);
         if (this.index != null)
             return new Krill(json).apply(this.index).toJsonString();
         Result kr = new Result();
@@ -93,7 +90,7 @@
      */
     @Deprecated
     public String searchTokenList (String json) {
-        qlog.trace(json);
+        jlog.trace(json);
         if (this.index != null)
             return new Krill(json).apply(this.index).toTokenListJsonString();
         Result kr = new Result();
@@ -205,7 +202,7 @@
      */
     @Deprecated
     public String getStatistics (String json) {
-        qlog.trace(json);
+        jlog.trace(json);
         if (this.index == null) {
             return "{\"documents\" : -1, error\" : \"No index given\" }";
         };
@@ -232,24 +229,19 @@
         return sb.toString();
     };
 
+
     /**
-	 * Return the match identifier as a string.
-	 * This is a convenient method to deal with legacy instantiation of the
-	 * code.
-	 */
-    public String getMatchId (String corpusID, String docID, String matchID) {
-		String docIDtextID [] = docID.split("\\.", 2);
-
-		// Create a string representation of the match 
-		StringBuilder sb = new StringBuilder()
-			.append("match-")
-			.append(corpusID).append('/')
-			.append(docIDtextID[0]);
-
-		// The docID was split
-		if (docIDtextID.length == 2)
-			sb.append('/').append(docIDtextID[1]);
-
-		return sb.append('-').append(matchID).toString();
+     * Return the match identifier as a string.
+     * This is a convenient method to deal with legacy instantiation
+     * of the
+     * code.
+     */
+    public String getMatchId (String corpusID, String docID, String textID,
+            String matchID) {
+        // Create a string representation of the match 
+        StringBuilder sb = new StringBuilder();
+        sb.append("match-").append(corpusID).append('/').append(docID)
+                .append('/').append(textID).append('-').append(matchID);
+        return sb.toString();
     };
 };
diff --git a/src/main/java/de/ids_mannheim/korap/web/filter/AdminFilter.java b/src/main/java/de/ids_mannheim/korap/web/filter/AdminFilter.java
index dc60e89..bfd12f9 100644
--- a/src/main/java/de/ids_mannheim/korap/web/filter/AdminFilter.java
+++ b/src/main/java/de/ids_mannheim/korap/web/filter/AdminFilter.java
@@ -1,67 +1,89 @@
 package de.ids_mannheim.korap.web.filter;
 
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.ext.Provider;
+
 import com.sun.jersey.spi.container.ContainerRequest;
 import com.sun.jersey.spi.container.ContainerRequestFilter;
 import com.sun.jersey.spi.container.ContainerResponseFilter;
 import com.sun.jersey.spi.container.ResourceFilter;
-import de.ids_mannheim.korap.config.AdminSetup;
+
+import de.ids_mannheim.korap.config.Attributes;
 import de.ids_mannheim.korap.config.BeansFactory;
-import de.ids_mannheim.korap.interfaces.EncryptionIface;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.interfaces.AuthenticationManagerIface;
+import de.ids_mannheim.korap.security.auth.BasicHttpAuth;
 import de.ids_mannheim.korap.user.TokenContext;
 import de.ids_mannheim.korap.user.User;
-import de.ids_mannheim.korap.utils.NamingUtils;
 import de.ids_mannheim.korap.utils.StringUtils;
 import de.ids_mannheim.korap.web.utils.KustvaktContext;
 import de.ids_mannheim.korap.web.utils.KustvaktResponseHandler;
 
-import javax.ws.rs.ext.Provider;
-
 /**
- * @author hanl
- * @date 17/06/2014
+ * @author hanl, margaretha
+ * @date 04/2017
  */
 @Provider
 public class AdminFilter implements ContainerRequestFilter, ResourceFilter {
 
-    @Override
-    public ContainerRequest filter (ContainerRequest cr) {
-        // todo:
-        String host = cr.getHeaderValue(ContainerRequest.HOST);
-        String ua = cr.getHeaderValue(ContainerRequest.USER_AGENT);
+	private static AuthenticationManagerIface authManager = BeansFactory.getKustvaktContext()
+			.getAuthenticationManager();
 
-        String authentication = cr
-                .getHeaderValue(ContainerRequest.AUTHORIZATION);
+	@Override
+	public ContainerRequest filter(ContainerRequest cr) {
+		String authentication = cr.getHeaderValue(ContainerRequest.AUTHORIZATION);
+		if (authentication == null) {
+			throw KustvaktResponseHandler.throwAuthenticationException("The authorization header value is missing.");
+		}
 
-        //if (authentication != null
-        //        && authentication.endsWith(BeansFactory.getKustvaktContext()
-        //                .getConfiguration().getAdminToken())) {
-        if (authentication != null && cr.isSecure()) {
-            String token = StringUtils.stripTokenType(authentication);
-            EncryptionIface crypto = BeansFactory.getKustvaktContext()
-                    .getEncryption();
+		// decode password
+		String authenticationType = StringUtils.getTokenType(authentication);
+		String authenticationCode = StringUtils.stripTokenType(authentication);
+		String username = null, token = null;
+		int tokenType = 0;
+		
+		if (authenticationType.equals(Attributes.BASIC_AUTHENTICATION)) {
+			String[] authContent = BasicHttpAuth.decode(authenticationCode);
+			username = authContent[0];
+			token = authContent[1];
+		}
+		
+		String host = cr.getHeaderValue(ContainerRequest.HOST);
+		String agent = cr.getHeaderValue(ContainerRequest.USER_AGENT);
+		Map<String, Object> attributes = new HashMap<>();
+		attributes.put(Attributes.HOST, host);
+		attributes.put(Attributes.USER_AGENT, agent);
+		try {
+			User user = authManager.authenticate(tokenType, username, token, attributes);
+			if (!user.isAdmin()){
+				throw KustvaktResponseHandler.throwAuthenticationException("Admin authentication failed.");
+			}
+			Map<String, Object> properties = cr.getProperties();
+			properties.put("user", user);
+		} catch (KustvaktException e) {
+			throw KustvaktResponseHandler.throwAuthenticationException("User authentication failed.");
+		}
 
-            if (crypto.checkHash(token, AdminSetup.getInstance().getHash())) {
-                TokenContext c = new TokenContext();
-                c.setUsername(User.ADMINISTRATOR_NAME);
-                c.setTokenType(StringUtils.getTokenType(authentication));
-                c.setToken(StringUtils.stripTokenType(authentication));
-                cr.setSecurityContext(new KustvaktContext(c));
-            }
-        }
-        else
-            throw KustvaktResponseHandler.throwAuthenticationException("");
-        return cr;
-    }
+		TokenContext c = new TokenContext();
+		c.setUsername(username);
+		c.setTokenType(authenticationType);
+		c.setToken(token);
+		c.setHostAddress(host);
+		c.setUserAgent(agent);
+		cr.setSecurityContext(new KustvaktContext(c));
 
+		return cr;
+	}
 
-    @Override
-    public ContainerRequestFilter getRequestFilter () {
-        return this;
-    }
+	@Override
+	public ContainerRequestFilter getRequestFilter() {
+		return this;
+	}
 
-
-    @Override
-    public ContainerResponseFilter getResponseFilter () {
-        return null;
-    }
+	@Override
+	public ContainerResponseFilter getResponseFilter() {
+		return null;
+	}
 }
diff --git a/src/main/java/de/ids_mannheim/korap/web/service/CollectionLoader.java b/src/main/java/de/ids_mannheim/korap/web/service/CollectionLoader.java
index 084a686..514afcf 100644
--- a/src/main/java/de/ids_mannheim/korap/web/service/CollectionLoader.java
+++ b/src/main/java/de/ids_mannheim/korap/web/service/CollectionLoader.java
@@ -1,22 +1,30 @@
 package de.ids_mannheim.korap.web.service;
 
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
 import de.ids_mannheim.korap.config.ContextHolder;
 import de.ids_mannheim.korap.config.KustvaktConfiguration;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.resources.Permissions;
+import de.ids_mannheim.korap.resources.KustvaktResource;
+import de.ids_mannheim.korap.resources.Permissions.Permission;
 import de.ids_mannheim.korap.resources.VirtualCollection;
 import de.ids_mannheim.korap.security.ac.PolicyBuilder;
 import de.ids_mannheim.korap.security.ac.ResourceFinder;
 import de.ids_mannheim.korap.security.ac.SecurityManager;
-import de.ids_mannheim.korap.config.Attributes;
 import de.ids_mannheim.korap.user.User;
-import de.ids_mannheim.korap.utils.KoralCollectionQueryBuilder;
 import de.ids_mannheim.korap.utils.JsonUtils;
+import de.ids_mannheim.korap.utils.KoralCollectionQueryBuilder;
 
 /**
- * @author hanl
+ * @author hanl, margaretha
  * @date 12/01/2016
+ * @lastupdate 19/04/2017
  */
 public class CollectionLoader implements BootableBeanInterface {
 
@@ -28,41 +36,114 @@
         User user = User.UserFactory
                 .toUser(KustvaktConfiguration.KUSTVAKT_USER);
 
-        KoralCollectionQueryBuilder bui = new KoralCollectionQueryBuilder();
-        bui.with("creationDate since 1775 & corpusSigle=GOE");
+        KustvaktConfiguration config = beans.getConfiguration();
 
-        VirtualCollection c1 = new VirtualCollection();
-        c1.setName("Weimarer Werke");
+        //        KoralCollectionQueryBuilder bui = new KoralCollectionQueryBuilder();
+        //        bui.with("creationDate since 1775 & corpusSigle=GOE");
+        //
+        //        VirtualCollection c1 = new VirtualCollection();
+        //        c1.setName("Weimarer Werke");
+        //
+        //        c1.setFields(bui.toJSON());
+        //
+        //        c1.setDescription("Goethe-Werke in Weimar (seit 1775)");
+        //
+        //        bui = new KoralCollectionQueryBuilder();
+        //        bui.with("textType=Aphorismus");
+        //
+        //        VirtualCollection c2 = new VirtualCollection();
+        //        c2.setName("Aphorismen");
+        //        c2.setFields(bui.toJSON());
+        //        c2.setDescription("Aphorismentexte Goethes");
+        //
+        //        bui = new KoralCollectionQueryBuilder();
+        //        bui.with("title ~ \"Werther\"");
+        //
+        //        VirtualCollection c3 = new VirtualCollection();
+        //        c3.setName("Werther");
+        //        c3.setFields(bui.toJSON());
+        //        c3.setDescription("Goethe - Die Leiden des jungen Werther");
 
-        c1.setFields(bui.toJSON());
+        PolicyBuilder builder = new PolicyBuilder(user);
+        String result = null;
+        BufferedReader br;
+        try {
+            File f = new File(config.getPolicyConfig());
+            br = new BufferedReader(
+                    new InputStreamReader(new FileInputStream(f)));
+        }
+        catch (FileNotFoundException e) {
+            throw new KustvaktException("Policy config file: "
+                    + config.getPolicyConfig() + " does not exists!",
+                    e.getCause(), 101);
+        }
+        String policy = null, collectionQuery = null;
+        String[] policyData = null;
+        String type, id, name, description, condition;
+        String[] permissions;
+        try {
+            while ((policy = br.readLine()) != null) {
+                if (policy.startsWith("#") || policy.isEmpty())
+                    continue;
+                policyData = policy.split("\t");
+                type = policyData[0];
+                id = policyData[1];
+                name = policyData[2];
+                description = policyData[3];
+                condition = policyData[4];
+                permissions = policyData[5].split(",");
+                if (policyData.length > 6)
+                    collectionQuery = policyData[6];
 
-        c1.setDescription("Goethe-Werke in Weimar (seit 1775)");
+                Permission[] permissionArr = new Permission[permissions.length];
+                for (int i = 0; i < permissions.length; i++) {
+                    if (permissions[i].equals("read")) {
+                        permissionArr[i] = Permission.READ;
+                    }
+                }
 
-        bui = new KoralCollectionQueryBuilder();
-        bui.with("textType=Aphorismus");
+                KustvaktResource resource = createResource(type, id, name,
+                        description, collectionQuery);
+                if (resource != null) {
+                    builder = new PolicyBuilder(user);
+                    builder.addCondition(condition);
+                    builder.setResources(resource);
+                    builder.setPermissions(permissionArr);
+                    result = builder.create();
+                    if (JsonUtils.readTree(result).size() > 0)
+                        throw new KustvaktException(StatusCodes.REQUEST_INVALID,
+                                "creating collections caused errors", result);
+                }
+            }
+            br.close();
+        }
+        catch (IOException e) {
+            throw new KustvaktException("Failed creating virtual collections.",
+                    e.getCause(), 100);
+        }
+    }
 
-        VirtualCollection c2 = new VirtualCollection();
-        c2.setName("Aphorismen");
-        c2.setFields(bui.toJSON());
-        c2.setDescription("Aphorismentexte Goethes");
 
-        bui = new KoralCollectionQueryBuilder();
-        bui.with("title ~ \"Werther\"");
+    private KustvaktResource createResource (String type, String id,
+            String name, String description, String docQuery) {
+        KoralCollectionQueryBuilder builder;
+        KustvaktResource resource = null;
+        if (type.equals("virtualcollection")) {
+            resource = new VirtualCollection(id);
+            if (!name.isEmpty()) {
+                resource.setName(name);
+            }
+            if (!description.isEmpty()) {
+                resource.setDescription(description);
+            }
+            if (docQuery != null && !docQuery.isEmpty()) {
+                builder = new KoralCollectionQueryBuilder();
+                builder.with(docQuery);
+                resource.setFields(builder.toJSON());
+            }
+        }
 
-        VirtualCollection c3 = new VirtualCollection();
-        c3.setName("Werther");
-        c3.setFields(bui.toJSON());
-        c3.setDescription("Goethe - Die Leiden des jungen Werther");
-
-        PolicyBuilder b = new PolicyBuilder(user);
-        b.setPermissions(Permissions.Permission.READ);
-        b.setResources(c1, c2, c3);
-        b.setConditions("public");
-        String result = b.create();
-
-        if (JsonUtils.readTree(result).size() > 0)
-            throw new KustvaktException(StatusCodes.REQUEST_INVALID,
-                    "creating collections caused errors", result);
+        return resource;
     }
 
 
diff --git a/src/main/java/de/ids_mannheim/korap/web/service/PolicyLoader.java b/src/main/java/de/ids_mannheim/korap/web/service/PolicyLoader.java
index 5765778..aba7506 100644
--- a/src/main/java/de/ids_mannheim/korap/web/service/PolicyLoader.java
+++ b/src/main/java/de/ids_mannheim/korap/web/service/PolicyLoader.java
@@ -1,12 +1,20 @@
 package de.ids_mannheim.korap.web.service;
 
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
 import de.ids_mannheim.korap.config.ContextHolder;
 import de.ids_mannheim.korap.config.KustvaktConfiguration;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 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.Layer;
+import de.ids_mannheim.korap.resources.Permissions.Permission;
 import de.ids_mannheim.korap.security.ac.PolicyBuilder;
 import de.ids_mannheim.korap.security.ac.ResourceFinder;
 import de.ids_mannheim.korap.security.ac.SecurityManager;
@@ -18,38 +26,87 @@
  */
 public class PolicyLoader implements BootableBeanInterface {
 
-    @Override
-    public void load (ContextHolder beans) throws KustvaktException {
-        SecurityManager.overrideProviders(beans);
-        ResourceFinder.overrideProviders(beans);
+	@Override
+	public void load(ContextHolder beans) throws KustvaktException {
+		SecurityManager.overrideProviders(beans);
+		ResourceFinder.overrideProviders(beans);
 
-        User user = User.UserFactory
-                .toUser(KustvaktConfiguration.KUSTVAKT_USER);
-        PolicyBuilder builder = new PolicyBuilder(user);
-        builder.addCondition("public");
-        builder.setResources(new Corpus("GOE"));
-        builder.setPermissions(Permissions.Permission.READ);
-        builder.create();
+		User user = User.UserFactory.toUser(KustvaktConfiguration.KUSTVAKT_USER);
+		KustvaktConfiguration config = beans.getConfiguration();
+		PolicyBuilder builder = new PolicyBuilder(user);
+		BufferedReader br;
+		try {
+			File f = new File(config.getPolicyConfig());
+			br = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
+		} catch (FileNotFoundException e) {
+			throw new KustvaktException("Policy config file: " + config.getPolicyConfig() + " does not exists!",
+					e.getCause(), 101);
+		}
+		String policy = null;
+		String[] policyData = null;
+		String type, id, name, description, condition;
+		String[] permissions;
+		try {
+			while ((policy = br.readLine()) != null) {
+				if (policy.startsWith("#") || policy.isEmpty()) continue;
+				
+				policyData = policy.split("\t");
+				type = policyData[0];
+				id = policyData[1];
+				name = policyData[2];
+				description = policyData[3];
+				condition = policyData[4];
+				permissions = policyData[5].split(",");
 
-        builder = new PolicyBuilder(user);
-        builder.addCondition("public");
-        builder.setResources(new Corpus("WPD"));
-        builder.setPermissions(Permissions.Permission.READ);
-        builder.create();
+				Permission[] permissionArr = new Permission[permissions.length];
+				for (int i = 0; i < permissions.length; i++) {
+					if (permissions[i].equals("read")) {
+						permissionArr[i] = Permission.READ;
+					}
+				}
+				KustvaktResource resource = createResource(type, id, name, description);
+				if (resource != null) {
+					builder.addCondition(condition);
+					builder.setResources(resource);
+					builder.setPermissions(permissionArr);
+					builder.create();
+				}
+			}
+			br.close();
+		} catch (IOException e) {
+			throw new KustvaktException("Failed creating policies.", e.getCause(), 100);
+		}
+	}
 
-        KustvaktResource tt = new Foundry("tt");
-        tt.setName("TreeTagger");
-        tt.setDescription("todo ...");
-        builder = new PolicyBuilder(user);
-        builder.addCondition("public");
-        builder.setResources(tt);
-        builder.setPermissions(Permissions.Permission.READ);
-        builder.create();
-    }
+	private KustvaktResource createResource(String type, String id, String name, String description) {
 
+		KustvaktResource resource = null;
+		if (type.equals("corpus")) {
+			resource = new Corpus(id);
+		} else if (type.equals("foundry")) {
+			resource = new Foundry(id);
+		} else if (type.equals("layer")) {
+			resource = new Layer(id);
+		}
+//			else if (type.equals("virtualcollection")) {
+//			resource = new VirtualCollection(id);
+//		}
+		else{
+			return resource;
+		}
 
-    @Override
-    public Class<? extends BootableBeanInterface>[] getDependencies () {
-        return new Class[] { UserLoader.class };
-    }
+		if (!name.isEmpty()) {
+			resource.setName(name);
+		}
+		if (!description.isEmpty()) {
+			resource.setDescription(description);
+		}
+
+		return resource;
+	}
+
+	@Override
+	public Class<? extends BootableBeanInterface>[] getDependencies() {
+		return new Class[] { UserLoader.class };
+	}
 }
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 77f6a8c..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,13 +1,31 @@
 package de.ids_mannheim.korap.web.service.full;
 
+import java.util.List;
+import java.util.Locale;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sun.jersey.api.core.HttpContext;
 import com.sun.jersey.spi.container.ResourceFilters;
+
 import de.ids_mannheim.korap.auditing.AuditRecord;
 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.db.AuditingIface;
-import de.ids_mannheim.korap.interfaces.AuthenticationManagerIface;
 import de.ids_mannheim.korap.resources.Document;
 import de.ids_mannheim.korap.resources.KustvaktResource;
 import de.ids_mannheim.korap.resources.Permissions;
@@ -16,27 +34,16 @@
 import de.ids_mannheim.korap.security.ac.PolicyBuilder;
 import de.ids_mannheim.korap.user.User;
 import de.ids_mannheim.korap.utils.JsonUtils;
-import de.ids_mannheim.korap.utils.KustvaktLogger;
 import de.ids_mannheim.korap.utils.TimeUtils;
 import de.ids_mannheim.korap.web.KustvaktServer;
 import de.ids_mannheim.korap.web.filter.AdminFilter;
 import de.ids_mannheim.korap.web.filter.PiwikFilter;
 import de.ids_mannheim.korap.web.utils.KustvaktResponseHandler;
-import org.joda.time.DateTime;
-import org.joda.time.format.DateTimeFormat;
-import org.joda.time.format.DateTimeFormatter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.ws.rs.*;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.util.List;
-import java.util.Locale;
 
 /**
- * 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 })
@@ -45,7 +52,6 @@
 
     private static Logger jlog = LoggerFactory.getLogger(AdminService.class);
 
-    private AuthenticationManagerIface controller;
     private AuditingIface auditingController;
     private DocumentDao documentDao;
 
@@ -53,13 +59,11 @@
     public AdminService () {
         this.auditingController = BeansFactory.getKustvaktContext()
                 .getAuditingProvider();
-        this.controller = 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,
@@ -100,7 +104,41 @@
             @QueryParam("description") String description,
             @QueryParam("group") String group,
             @QueryParam("perm") List<String> permissions,
-            @QueryParam("loc") String loc, @QueryParam("expire") String duration) {
+            @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);
@@ -108,20 +146,25 @@
             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]));
 
-            PolicyBuilder cr = new PolicyBuilder(User.UserFactory.getAdmin())
-                    .setConditions(new PolicyCondition(group)).setResources(
-                            resource);
-            if (loc != null && !loc.isEmpty())
-                cr.setLocation(loc);
+            User user = (User) context.getProperties().get("user");
 
-            if (duration != null && duration.isEmpty())
-                cr.setContext(TimeUtils.getNow().getMillis(),
-                        TimeUtils.convertTimeToSeconds(duration));
+            PolicyBuilder pb = new PolicyBuilder(user)
+                    .setConditions(new PolicyCondition(group))
+                    .setResources(resource);
 
-            cr.setPermissions(p).create();
+            if (loc != null && !loc.isEmpty()){
+                pb.setLocation(loc);
+            }
+            if (duration != null && !duration.isEmpty()){
+                long now = TimeUtils.getNow().getMillis();
+                pb.setContext(now,
+                        now + TimeUtils.convertTimeToSeconds(duration));
+            }
+            pb.setPermissions(p);
+            pb.create();
         }
         catch (KustvaktException e) {
             throw KustvaktResponseHandler.throwit(e);
diff --git a/src/main/java/de/ids_mannheim/korap/web/service/full/ResourceService.java b/src/main/java/de/ids_mannheim/korap/web/service/full/ResourceService.java
index 0db2b48..4f384c7 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
@@ -1,11 +1,37 @@
 package de.ids_mannheim.korap.web.service.full;//package de.ids_mannheim.korap.ext.web;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriBuilder;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import com.fasterxml.jackson.databind.JsonNode;
 import com.sun.jersey.core.util.MultivaluedMapImpl;
 import com.sun.jersey.spi.container.ResourceFilters;
+
 import de.ids_mannheim.korap.config.Attributes;
 import de.ids_mannheim.korap.config.BeansFactory;
 import de.ids_mannheim.korap.config.KustvaktConfiguration;
+import de.ids_mannheim.korap.config.KustvaktConfiguration.BACKENDS;
 import de.ids_mannheim.korap.exceptions.EmptyResultException;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.NotAuthorizedException;
@@ -13,36 +39,40 @@
 import de.ids_mannheim.korap.interfaces.AuthenticationManagerIface;
 import de.ids_mannheim.korap.query.serialize.MetaQueryBuilder;
 import de.ids_mannheim.korap.query.serialize.QuerySerializer;
-import de.ids_mannheim.korap.resource.rewrite.*;
-import de.ids_mannheim.korap.resources.*;
+import de.ids_mannheim.korap.resource.rewrite.RewriteHandler;
+import de.ids_mannheim.korap.resources.Corpus;
+import de.ids_mannheim.korap.resources.KustvaktResource;
+import de.ids_mannheim.korap.resources.Layer;
+import de.ids_mannheim.korap.resources.Permissions;
+import de.ids_mannheim.korap.resources.ResourceFactory;
+import de.ids_mannheim.korap.resources.VirtualCollection;
 import de.ids_mannheim.korap.security.ac.ResourceFinder;
 import de.ids_mannheim.korap.security.ac.ResourceHandler;
 import de.ids_mannheim.korap.security.ac.SecurityManager;
+import de.ids_mannheim.korap.user.DemoUser;
 import de.ids_mannheim.korap.user.TokenContext;
 import de.ids_mannheim.korap.user.User;
-import de.ids_mannheim.korap.utils.*;
+import de.ids_mannheim.korap.user.User.UserFactory;
+import de.ids_mannheim.korap.utils.JsonUtils;
+import de.ids_mannheim.korap.utils.KoralCollectionQueryBuilder;
+import de.ids_mannheim.korap.utils.KustvaktLogger;
+import de.ids_mannheim.korap.utils.StringUtils;
 import de.ids_mannheim.korap.web.ClientsHandler;
 import de.ids_mannheim.korap.web.KustvaktServer;
 import de.ids_mannheim.korap.web.SearchKrill;
 import de.ids_mannheim.korap.web.TRACE;
 import de.ids_mannheim.korap.web.filter.AuthFilter;
-import de.ids_mannheim.korap.web.filter.BlockingFilter;
 import de.ids_mannheim.korap.web.filter.DemoUserFilter;
 import de.ids_mannheim.korap.web.filter.PiwikFilter;
 import de.ids_mannheim.korap.web.utils.KustvaktResponseHandler;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.ws.rs.*;
-import javax.ws.rs.core.*;
-import java.util.*;
 
 /**
- * @author hanl
+ * @author hanl, margaretha
  * @date 29/01/2014
+ * @lastUpdate 04/2017
  */
 @Path(KustvaktServer.API_VERSION + "/")
-@ResourceFilters({ AuthFilter.class, DemoUserFilter.class, PiwikFilter.class})
+@ResourceFilters({ AuthFilter.class, DemoUserFilter.class, PiwikFilter.class })
 @Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
 public class ResourceService {
 
@@ -72,9 +102,10 @@
 
 
     /**
-     * retrieve resources dependent by type. determines based on
-     * the user's permission or resource owner if the user can access
-     * the resource.
+     * 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
@@ -92,7 +123,8 @@
         try {
             Class cl_type = ResourceFactory.getResourceClass(type);
             if (cl_type == null)
-                throw KustvaktResponseHandler.throwit(StatusCodes.MISSING_ARGUMENT,
+                throw KustvaktResponseHandler.throwit(
+                        StatusCodes.MISSING_ARGUMENT,
                         "Resource type not available!", "");
 
             User user = controller.getUser(ctx.getUsername());
@@ -142,131 +174,132 @@
             if (ctx.isDemo()) {
                 Set set = ResourceFinder.searchPublicFiltered(cl_type, id);
                 resource = (KustvaktResource) set.toArray()[0];
-            } else {
+            }
+            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);
+                    resource = resourceHandler.findbyStrId(id, user, cl_type);
             }
         }
         catch (KustvaktException e) {
-            //if (e.getStatusCode() != StatusCodes.ACCESS_DENIED)
+            // 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);
-            //}
+            // try {
+            // Set set = ResourceFinder.searchPublicFiltered(cl_type, id);
+            // resource = (KustvaktResource) set.toArray()[0];
+            // }
+            // catch (KustvaktException e1) {
+            // throw KustvaktResponseHandler.throwit(e);
+            // }
         }
         return Response.ok(JsonUtils.toJSON(resource.toMap())).build();
     }
 
+    // @GET
+    // @Path("colloc")
+    // public Response getCollocationsAll(@Context SecurityContext ctx,
+    // @Context Locale locale, @QueryParam("props") String properties,
+    // @QueryParam("sfskip") Integer sfs,
+    // @QueryParam("sflimit") Integer limit, @QueryParam("q") String query,
+    // @QueryParam("ql") String ql, @QueryParam("context") Integer context,
+    // @QueryParam("foundry") String foundry,
+    // @QueryParam("paths") Boolean wPaths) {
+    // TokenContext tokenContext = (TokenContext) ctx.getUserPrincipal();
+    // ColloQuery.ColloQueryBuilder builder;
+    // KoralCollectionQueryBuilder cquery = new KoralCollectionQueryBuilder();
+    // String result;
+    // try {
+    // User user = controller.getUser(tokenContext.getUsername());
+    // Set<VirtualCollection> resources = ResourceFinder
+    // .search(user, VirtualCollection.class);
+    // for (KustvaktResource c : resources)
+    // cquery.addResource(((VirtualCollection) c).getQuery());
+    //
+    // builder = functions
+    // .buildCollocations(query, ql, properties, context, limit,
+    // sfs, foundry, new ArrayList<Dependency>(), wPaths,
+    // cquery);
+    //
+    // result = graphDBhandler
+    // .getResponse("distCollo", "q", builder.build().toJSON());
+    // }catch (KustvaktException e) {
+    // throw KustvaktResponseHandler.throwit(e);
+    // }catch (JsonProcessingException e) {
+    // throw KustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT);
+    // }
+    // return Response.ok(result).build();
+    // }
 
-    //    @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());
+    // /**
+    // * @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);
+    // 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);
+    // 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);
-    //            }
+    // }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);
+    // builder = functions
+    // .buildCollocations(query, ql, properties, context, limit,
+    // sfs, foundry, new ArrayList<Dependency>(), wPaths,
+    // cquery);
     //
-    //            result = graphDBhandler
-    //                    .getResponse("distCollo", "q", builder.build().toJSON());
+    // result = graphDBhandler
+    // .getResponse("distCollo", "q", builder.build().toJSON());
     //
-    //        }catch (JsonProcessingException e) {
-    //            throw KustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT);
-    //        }catch (KustvaktException e) {
-    //            throw KustvaktResponseHandler.throwit(e);
-    //        }
+    // }catch (JsonProcessingException e) {
+    // throw KustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT);
+    // }catch (KustvaktException e) {
+    // throw KustvaktResponseHandler.throwit(e);
+    // }
     //
-    //        return Response.ok(result).build();
-    //    }
+    // return Response.ok(result).build();
+    // }
     @POST
     @Path("colloc")
     public Response getCollocationBase (@QueryParam("q") String query) {
@@ -281,35 +314,20 @@
     }
 
 
-    @Deprecated
-    public Response postMatchFavorite () {
-        return Response.ok().build();
-    }
-
-
     // ref query parameter removed!
     @TRACE
     @Path("search")
     public Response buildQuery (@Context Locale locale,
-            @Context SecurityContext securityContext,
-            @QueryParam("q") String q, @QueryParam("ql") String ql,
-            @QueryParam("v") String v, @QueryParam("context") String context,
+            @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) {
+            @QueryParam("page") Integer startPage,
+            @QueryParam("cq") String cq) {
         TokenContext ctx = (TokenContext) securityContext.getUserPrincipal();
-        QuerySerializer ss;
-
-        //User user;
-        //try {
-        //    user = controller.getUser(ctx.getUsername());
-        //}
-        //catch (KustvaktException e) {
-        //    throw KustvaktResponseHandler.throwit(e);
-        //}
-
-        ss = new QuerySerializer().setQuery(q, ql, v);
+        QuerySerializer ss = new QuerySerializer().setQuery(q, ql, v);
         if (cq != null)
             ss.setCollection(cq);
 
@@ -343,13 +361,14 @@
      * @return
      */
 
-    //todo: does cq have any sensible worth here? --> would say no! --> is useful in non type/id scenarios
+    // 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,
+            @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,
@@ -378,7 +397,6 @@
         KoralCollectionQueryBuilder cquery = new KoralCollectionQueryBuilder();
         cquery.setBaseQuery(ss.toJSON());
 
-
         String query = "";
         KustvaktResource resource;
         try {
@@ -387,17 +405,19 @@
                 Set set = ResourceFinder.searchPublicFiltered(
                         ResourceFactory.getResourceClass(type), id);
                 resource = (KustvaktResource) set.toArray()[0];
-            } else {
+            }
+            else {
                 User user = controller.getUser(ctx.getUsername());
                 if (StringUtils.isInteger(id))
-                    resource = this.resourceHandler.findbyIntId(
-                            Integer.valueOf(id), user);
+                    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
+        // 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);
@@ -405,8 +425,8 @@
 
         if (resource != null) {
             if (resource instanceof VirtualCollection)
-                query = JsonUtils.toJSON(cquery.and().mergeWith(
-                        resource.getData()));
+                query = JsonUtils
+                        .toJSON(cquery.and().mergeWith(resource.getData()));
             else if (resource instanceof Corpus) {
                 cquery.and().with(Attributes.CORPUS_SIGLE, "=",
                         resource.getPersistentID());
@@ -424,10 +444,11 @@
             String jsonld) {
         TokenContext ctx = (TokenContext) context.getUserPrincipal();
 
-        // todo: should be possible to add the meta part to the query serialization
+        // 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);
+            // jsonld = this.processor.processQuery(jsonld, user);
         }
         catch (KustvaktException e) {
             throw KustvaktResponseHandler.throwit(e);
@@ -441,6 +462,7 @@
     }
 
 
+    @SuppressWarnings("unchecked")
     @GET
     @Path("search")
     public Response searchbyNameAll (@Context SecurityContext securityContext,
@@ -460,16 +482,37 @@
             user = controller.getUser(context.getUsername());
         }
         catch (KustvaktException e) {
-            jlog.error("Exception encountered: {}", e.string());
+            jlog.error("Failed retrieving user in the search service: {}",
+                    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 = createMetaQuery(pageIndex, pageInteger, ctx,
+                pageLength, cutoff);
+        serializer.setMeta(meta.raw());
+
+        String query;
+        try {
+            query = this.processor.processQuery(serializer.toJSON(), user);
+            jlog.info("the serialized query {}", query);
+        }
+        catch (KustvaktException e) {
+            throw KustvaktResponseHandler.throwit(e);
+        }
+
+        String result = doSearch(eng, query, pageLength, meta);
+        return Response.ok(result).build();
+    }
+
+
+    private MetaQueryBuilder createMetaQuery (Integer pageIndex,
+            Integer pageInteger, String ctx, Integer pageLength,
+            Boolean cutoff) {
         MetaQueryBuilder meta = new MetaQueryBuilder();
         meta.addEntry("startIndex", pageIndex);
         meta.addEntry("startPage", pageInteger);
@@ -477,51 +520,61 @@
         meta.addEntry("count", pageLength);
         // todo: what happened to cutoff?
         meta.addEntry("cutoff", cutoff);
-        //        meta.addMeta(pageIndex, pageInteger, pageLength, ctx, 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();
+        // meta.addEntry("itemsPerResource", 1);
+        return meta;
     }
 
 
+    private String doSearch (BACKENDS eng, String query, Integer pageLength,
+            MetaQueryBuilder meta) {
+        String result;
+        if (eng.equals(KustvaktConfiguration.BACKENDS.NEO4J)) {
+            result = searchNeo4J(query, pageLength, meta,false);
+        }
+        else {
+            result = searchKrill.search(query);
+        }
+        KustvaktLogger.QUERY_LOGGER.trace("The result set: {}", result);
+        return result;
+
+    }
+
+    private String searchNeo4J (String query, int pageLength,
+            MetaQueryBuilder meta, boolean raw) {
+        
+        if (raw){
+            throw KustvaktResponseHandler.throwit(
+                    StatusCodes.ILLEGAL_ARGUMENT,
+                    "raw not supported!", null);
+        }
+        
+        MultivaluedMap<String, String> 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 {
+            return this.graphDBhandler.getResponse(map, "distKwic");
+        }
+        catch (KustvaktException e) {
+            jlog.error("Failed searching in Neo4J: {}", e.string());
+            throw KustvaktResponseHandler.throwit(e);
+        }
+
+    }
+
     /**
-     * String search, String ql, List<String> parents,
-     * String cli, String cri, int cls, int crs,
-     * int num, int page, boolean cutoff)
-     * param context will be like this: context: "3-t,2-c"
+     * 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
+     * which case a
+     * type reference is required
      * 
      * @param securityContext
      * @param locale
@@ -537,9 +590,9 @@
             @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("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
@@ -551,74 +604,37 @@
 
         try {
             User user = controller.getUser(context.getUsername());
-            MetaQueryBuilder meta = new MetaQueryBuilder();
+            MetaQueryBuilder meta;
 
+            // EM: shouldnt this be the same as buildQueryWithId() ?
             if (!raw) {
+                meta = createMetaQuery(pageIndex, pageInteger, ctx, pageLength,
+                        cutoff);
+                
                 QuerySerializer s = new QuerySerializer();
                 s.setQuery(query, ql, v);
-
+                
+                // add collection query
                 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();
+                builder.setBaseQuery(s.toJSON());
+                query = createQuery(user, type, id, builder);
+                
             }
-            String result;
-            try {
+            else {
+                meta = new MetaQueryBuilder();
+            }
 
+            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);
+            catch (KustvaktException e) {
+                jlog.error("Failed in rewriting query: " + query, e);
+                throw KustvaktResponseHandler.throwit(500, e.getMessage(),
+                        null);
             }
 
+            String result = doSearch(eng, query, pageLength, meta);
             KustvaktLogger.QUERY_LOGGER.trace("The result set: {}", result);
             return Response.ok(result).build();
         }
@@ -630,6 +646,59 @@
     }
 
 
+    private String createQuery (User user, String type, String id,
+            KoralCollectionQueryBuilder builder) {
+        KustvaktResource resource = null;
+        try {
+            // EM: this doesn't look like very useful since the id is :
+            // 1. auto-generated 
+            // 2. random
+            // 3. not really known.
+            if (user instanceof DemoUser) {
+                Set<KustvaktResource> set = null;
+                if (StringUtils.isInteger(id)) {
+                    set = ResourceFinder.searchPublicFilteredIntId(
+                            ResourceFactory.getResourceClass(type),
+                            Integer.parseInt(id));
+                }
+                else {
+                    set = ResourceFinder.searchPublicFiltered(
+                            ResourceFactory.getResourceClass(type), id);
+                }
+                resource = (KustvaktResource) set.toArray()[0];
+            }
+            else if (StringUtils.isInteger(id)) {
+                resource = this.resourceHandler.findbyIntId(Integer.valueOf(id),
+                        user);
+            }
+            else {
+                resource = this.resourceHandler.findbyStrId(id, user,
+                        ResourceFactory.getResourceClass(type));
+            }
+        }
+        catch (KustvaktException e) {
+            jlog.error("Failed retrieving resource: {}", e.string());
+            throw KustvaktResponseHandler.throwit(e);
+        }
+
+        if (resource instanceof VirtualCollection) {
+            // test this
+            //builder.setBaseQuery(resource.getData());
+            return JsonUtils
+                    .toJSON(builder.and().mergeWith(resource.getData()));
+        }
+        else if (resource instanceof Corpus) {
+            builder.and().with(Attributes.CORPUS_SIGLE, "=",
+                    resource.getPersistentID());
+            return builder.toJSON();
+        }
+        else {
+            throw KustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT,
+                    "Type parameter not supported", type);
+        }
+    }
+
+
     @POST
     @Path("stats")
     public Response getStats (@Context SecurityContext context,
@@ -664,23 +733,23 @@
         type = StringUtils.normalize(type);
         id = StringUtils.decodeHTML(id);
 
-
         try {
             Class sl = ResourceFactory.getResourceClass(type);
             if (!VirtualCollection.class.equals(sl) & !Corpus.class.equals(sl))
-                throw KustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT,
+                throw KustvaktResponseHandler.throwit(
+                        StatusCodes.ILLEGAL_ARGUMENT,
                         "Requested Resource type not supported", type);
 
             User user = controller.getUser(ctx.getUsername());
             KustvaktResource resource;
             if (StringUtils.isInteger(id))
-                resource = this.resourceHandler.findbyIntId(
-                        Integer.valueOf(id), user);
+                resource = this.resourceHandler.findbyIntId(Integer.valueOf(id),
+                        user);
             else
                 resource = this.resourceHandler.findbyStrId(id, user,
                         ResourceFactory.getResourceClass(type));
 
-            //todo ?!
+            // todo ?!
             KoralCollectionQueryBuilder query = new KoralCollectionQueryBuilder();
             if (resource instanceof VirtualCollection) {
                 query.setBaseQuery(resource.getData());
@@ -705,7 +774,7 @@
      * @param json
      * @return
      */
-    //todo: rename
+    // todo: rename
     @POST
     @Path("collection_raw")
     public Response createRawCollection (@Context SecurityContext context,
@@ -749,26 +818,42 @@
     @Path("{type}/{id}")
     public Response updateResource (@Context SecurityContext context,
             @Context Locale locale, @PathParam("type") String type,
-            @PathParam("id") String id, String json) {
+            @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));
-            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);
+            if (name != null && !name.isEmpty()) {
+                if (description == null) {
+                    if (name.equals(resource.getName())) {
+                        throw new KustvaktException(StatusCodes.NOTHING_CHANGED,
+                                "No change has found.");
+                    }
+                    resource.setName(name);
+                }
+                else if (name.equals(resource.getName())
+                        && description.equals(resource.getDescription())) {
+                    throw new KustvaktException(StatusCodes.NOTHING_CHANGED,
+                            "No change has found.");
+                }
+                else {
+                    resource.setName(name);
+                    resource.setDescription(description);
+                }
+            }
+            else if (description != null && !description.isEmpty()) {
+                resource.setDescription(description);
+            }
+            else {
+                throw new KustvaktException(StatusCodes.NOTHING_CHANGED,
+                        "The given resource name and description are the same as already stored.");
             }
 
-            if (node.isObject() && !node.path("description").isMissingNode())
-                resource.setDescription(node.path("description").asText());
+
             this.resourceHandler.updateResources(user, resource);
         }
         catch (KustvaktException e) {
@@ -779,15 +864,15 @@
     }
 
 
-    //todo: change or deprecate
+    // todo: change or deprecate
     @POST
     @Path("nv/{type}")
     public Response storeResource (@Context SecurityContext context,
-            @Context Locale locale,
-            @PathParam("type") String type,
+            @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
+            // 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) {
@@ -799,8 +884,7 @@
         User user;
         Class ctype;
         try {
-            ctype = ResourceFactory
-                    .getResourceClass(type);
+            ctype = ResourceFactory.getResourceClass(type);
             user = controller.getUser(ctx.getUsername());
         }
         catch (KustvaktException e) {
@@ -863,15 +947,21 @@
 
 
     /**
-     * store a virtual collection. Retrieve cached entry first and
-     * then store collection
+     * 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,
@@ -890,8 +980,7 @@
         User user;
         Class ctype;
         try {
-            ctype = ResourceFactory
-                    .getResourceClass(type);
+            ctype = ResourceFactory.getResourceClass(type);
 
             user = controller.getUser(ctx.getUsername());
         }
@@ -927,6 +1016,8 @@
             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())) {
@@ -972,7 +1063,7 @@
             User user = controller.getUser(ctx.getUsername());
             KustvaktResource r = ResourceFactory.getResource(type);
             r.setPersistentID(id);
-            //todo: eliminate the need to find the resource first!
+            // todo: eliminate the need to find the resource first!
             resourceHandler.deleteResources(user, r);
         }
         catch (KustvaktException e) {
@@ -984,19 +1075,23 @@
     }
 
 
-    //fixme: only allowed for corpus?!
+    // fixme: only allowed for corpus?!
     @GET
-    @Path("/corpus/{id}/{docid}/{rest}/matchInfo")
+    @Path("/corpus/{corpusId}/{docId}/{textId}/{matchId}/matchInfo")
     public Response getMatchInfo (@Context SecurityContext ctx,
-            @Context Locale locale, @PathParam("id") String id,
-            @PathParam("docid") String docid, @PathParam("rest") String rest,
+            @Context Locale locale, @PathParam("corpusId") String corpusId,
+            @PathParam("docId") String docId,
+            @PathParam("textId") String textId,
+            @PathParam("matchId") String matchId,
             @QueryParam("foundry") Set<String> foundries,
             @QueryParam("layer") Set<String> layers,
-            @QueryParam("spans") Boolean spans) {
+            @QueryParam("spans") Boolean spans) throws KustvaktException {
+
         TokenContext tokenContext = (TokenContext) ctx.getUserPrincipal();
         spans = spans != null ? spans : false;
-        String matchid = searchKrill.getMatchId(id, docid, rest);
 
+        String matchid = searchKrill.getMatchId(corpusId, docId, textId,
+                matchId);
         if (layers == null || layers.isEmpty())
             layers = new HashSet<>();
 
@@ -1007,8 +1102,8 @@
             user = controller.getUser(tokenContext.getUsername());
         }
         catch (KustvaktException e) {
-
-            jlog.error("Exception encountered: {}", e.string());
+            jlog.error("Failed getting user in the matchInfo service: {}",
+                    e.string());
             throw KustvaktResponseHandler.throwit(e);
         }
 
@@ -1022,8 +1117,8 @@
 
             for (String spl : new ArrayList<>(foundries)) {
                 try {
-                    de.ids_mannheim.korap.security.ac.SecurityManager manager = SecurityManager
-                            .init(spl, user, Permissions.Permission.READ);
+                    SecurityManager<?> manager = SecurityManager.init(spl, user,
+                            Permissions.Permission.READ);
                     if (!manager.isAllowed())
                         continue;
 
@@ -1032,19 +1127,14 @@
                         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);
+                    results = searchKrill.getMatch(matchid,
+                            new ArrayList<>(f_list), new ArrayList<>(l_list),
+                            spans, false, true);
                 }
                 catch (NotAuthorizedException e) {
                     throw KustvaktResponseHandler.throwit(
                             StatusCodes.ACCESS_DENIED, "Permission denied",
-                            id);
+                            matchid);
                 }
 
             }
@@ -1073,9 +1163,9 @@
         }
         try {
             if (!match_only)
-                results = searchKrill
-                        .getMatch(matchid, new ArrayList<>(foundries),
-                                new ArrayList<>(layers), spans, false, true);
+                results = searchKrill.getMatch(matchid,
+                        new ArrayList<>(foundries), new ArrayList<>(layers),
+                        spans, false, true);
             else
                 results = searchKrill.getMatch(matchid);
         }
@@ -1098,14 +1188,14 @@
         TokenContext ctx = (TokenContext) context.getUserPrincipal();
         // save match for user and later retrieval!
 
-        //        KustvaktResource match = new QueryMatch(id);
-        //        match.setDescription(description);
-        //        match.setCreated(TimeUtils.getNow().getMillis());
-        //        try {
-        //            this.resourceHandler.storeResources(controller.getUser(ctx), match);
-        //        } catch (KustvaktException | NotAuthorizedException e) {
-        //            throw MappedHTTPResponse.throwit(e);
-        //        }
+        // 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();
     }
@@ -1116,8 +1206,9 @@
     @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)
+        // todo save match for user and later retrieval!
+        // todo: retrieve matches in range! --choices: date, document, id
+        // (matchid)
         return Response.ok().build();
     }
 
diff --git a/src/main/java/de/ids_mannheim/korap/web/service/full/UserService.java b/src/main/java/de/ids_mannheim/korap/web/service/full/UserService.java
index c998e31..74f3cf5 100644
--- a/src/main/java/de/ids_mannheim/korap/web/service/full/UserService.java
+++ b/src/main/java/de/ids_mannheim/korap/web/service/full/UserService.java
@@ -20,7 +20,6 @@
 import de.ids_mannheim.korap.web.filter.BlockingFilter;
 import de.ids_mannheim.korap.web.filter.DemoUserFilter;
 import de.ids_mannheim.korap.web.filter.PiwikFilter;
-import de.ids_mannheim.korap.web.utils.FormRequestWrapper;
 import de.ids_mannheim.korap.web.utils.KustvaktResponseHandler;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -30,8 +29,8 @@
 import java.util.*;
 
 /**
- * @author hanl
- * @date 29/01/2014
+ * @author hanl, margaretha
+ * @lastUpdate 04/2017
  */
 @Path(KustvaktServer.API_VERSION + "/user")
 @Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
@@ -41,8 +40,7 @@
     private static Logger jlog = LoggerFactory.getLogger(UserService.class);
     private AuthenticationManagerIface controller;
 
-    private @Context
-    UriInfo info;
+    private @Context UriInfo info;
 
 
     public UserService () {
@@ -52,6 +50,9 @@
 
 
     // fixme: json contains password in clear text. Encrypt request?
+    // EM: no encryption is needed for communications over https. 
+    // It should not be necessary in IDS internal network. 
+    
     // fixme: should also collect service exception, not just db exception!
     @POST
     @Path("register")
@@ -76,21 +77,24 @@
         }
         URIParam uri = user.getField(URIParam.class);
         if (uri.hasValues()) {
-            uriBuilder.queryParam(Attributes.QUERY_PARAM_URI,
-                    uri.getUriFragment()).queryParam(
-                    Attributes.QUERY_PARAM_USER, user.getUsername());
+            uriBuilder
+                    .queryParam(Attributes.QUERY_PARAM_URI,
+                            uri.getUriFragment())
+                    .queryParam(Attributes.QUERY_PARAM_USER,
+                            user.getUsername());
             jlog.info("registration was successful for user '{}'",
-                    values.get(Attributes.USERNAME));
-            Map object = new HashMap();
+                    user.getUsername());
+            Map<String, Object> object = new HashMap<String, Object>();
             object.put("confirm_uri", uriBuilder.build());
             object.put("uri_expiration",
                     TimeUtils.format(uri.getUriExpiration()));
             return Response.ok(JsonUtils.toJSON(object)).build();
         }
         else {
-            // todo: return error or warning
+            jlog.error("Failed creating confirmation and expiry tokens.");
+            // EM: why illegal argument when uri fragment/param is self-generated 
             throw KustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT,
-                    "failed to validate uri paramter", "confirmation fragment");
+                    "failed to validate uri parameter", "confirmation fragment");
         }
 
     }
@@ -100,8 +104,8 @@
     @POST
     @Path("update")
     @Consumes(MediaType.APPLICATION_JSON)
-    @ResourceFilters({ AuthFilter.class,
-            PiwikFilter.class, BlockingFilter.class })
+    @ResourceFilters({ AuthFilter.class, PiwikFilter.class,
+            BlockingFilter.class })
     public Response updateAccount (@Context SecurityContext ctx, String json) {
         TokenContext context = (TokenContext) ctx.getUserPrincipal();
         try {
@@ -149,7 +153,8 @@
     @POST
     @Path("requestReset")
     @Produces(MediaType.TEXT_HTML)
-    @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_FORM_URLENCODED})
+    @Consumes({ MediaType.APPLICATION_JSON,
+            MediaType.APPLICATION_FORM_URLENCODED })
     public Response requestPasswordReset (@Context Locale locale, String json) {
         JsonNode node = JsonUtils.readTree(json);
         StringBuilder builder = new StringBuilder();
@@ -192,7 +197,8 @@
     @POST
     @Path("reset")
     @Produces(MediaType.TEXT_HTML)
-    @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_FORM_URLENCODED})
+    @Consumes({ MediaType.APPLICATION_JSON,
+            MediaType.APPLICATION_FORM_URLENCODED })
     public Response resetPassword (
             @QueryParam(Attributes.QUERY_PARAM_URI) String uri,
             @QueryParam(Attributes.QUERY_PARAM_USER) String username,
@@ -211,8 +217,8 @@
     // todo: refactor and make something out of if --> needs to give some sort of feedback!
     @GET
     @Path("info")
-    @ResourceFilters({ AuthFilter.class,
-            PiwikFilter.class, BlockingFilter.class })
+    @ResourceFilters({ AuthFilter.class, PiwikFilter.class,
+            BlockingFilter.class })
     public Response getStatus (@Context SecurityContext context,
             @QueryParam("scopes") String scopes) {
         TokenContext ctx = (TokenContext) context.getUserPrincipal();
@@ -228,7 +234,8 @@
             m = Scopes.mapScopes(scopes, data);
         }
         catch (KustvaktException e) {
-            throw KustvaktResponseHandler.throwAuthenticationException(ctx.getUsername());
+            throw KustvaktResponseHandler
+                    .throwAuthenticationException(ctx.getUsername());
         }
         return Response.ok(m.toEntity()).build();
     }
@@ -258,9 +265,9 @@
 
     @POST
     @Path("settings")
-    @Consumes({MediaType.APPLICATION_JSON})
-    @ResourceFilters({ AuthFilter.class,
-            PiwikFilter.class, BlockingFilter.class })
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @ResourceFilters({ AuthFilter.class, PiwikFilter.class,
+            BlockingFilter.class })
     public Response updateSettings (@Context SecurityContext context,
             @Context Locale locale, Map settings) {
         TokenContext ctx = (TokenContext) context.getUserPrincipal();
@@ -321,9 +328,9 @@
 
     @POST
     @Path("details")
-    @Consumes({MediaType.APPLICATION_JSON})
-    @ResourceFilters({ AuthFilter.class,
-            PiwikFilter.class, BlockingFilter.class })
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @ResourceFilters({ AuthFilter.class, PiwikFilter.class,
+            BlockingFilter.class })
     public Response updateDetails (@Context SecurityContext context,
             @Context Locale locale, Map details) {
         TokenContext ctx = (TokenContext) context.getUserPrincipal();
@@ -355,9 +362,10 @@
     @POST
     @Path("queries")
     @Consumes(MediaType.APPLICATION_JSON)
-    @ResourceFilters({ AuthFilter.class,
-            PiwikFilter.class, BlockingFilter.class })
-    public Response updateQueries (@Context SecurityContext context, String json) {
+    @ResourceFilters({ AuthFilter.class, PiwikFilter.class,
+            BlockingFilter.class })
+    public Response updateQueries (@Context SecurityContext context,
+            String json) {
         TokenContext ctx = (TokenContext) context.getUserPrincipal();
         Collection<UserQuery> add = new HashSet<>();
         try {
@@ -407,8 +415,8 @@
 
 
     @DELETE
-    @ResourceFilters({ AuthFilter.class,
-            PiwikFilter.class, BlockingFilter.class })
+    @ResourceFilters({ AuthFilter.class, PiwikFilter.class,
+            BlockingFilter.class })
     public Response deleteUser (@Context SecurityContext context) {
         TokenContext ctx = (TokenContext) context.getUserPrincipal();
         try {
diff --git a/src/main/java/de/ids_mannheim/korap/web/service/light/LightService.java b/src/main/java/de/ids_mannheim/korap/web/service/light/LightService.java
index 1003e0d..5bb3fa6 100644
--- a/src/main/java/de/ids_mannheim/korap/web/service/light/LightService.java
+++ b/src/main/java/de/ids_mannheim/korap/web/service/light/LightService.java
@@ -297,13 +297,15 @@
 	 * "getMatchID()" for a workaround, but this should be fixed.
 	 */
     @GET
-    @Path("/corpus/{id}/{docid}/{rest}/matchInfo")
-    public Response getMatchInfo (@PathParam("id") String id,
-								  @PathParam("docid") String docid, @PathParam("rest") String rest,
+    @Path("/corpus/{corpusId}/{docId}/{textId}/{matchId}/matchInfo")
+    public Response getMatchInfo (@PathParam("corpusId") String corpusId,
+            @PathParam("docId") String docId,
+            @PathParam("textId") String textId, 
+            @PathParam("matchId") String matchId,
             @QueryParam("foundry") Set<String> foundries,
             @QueryParam("layer") Set<String> layers,
             @QueryParam("spans") Boolean spans) {
-        String matchid = searchKrill.getMatchId(id, docid, rest);
+        String matchid = searchKrill.getMatchId(corpusId, docId, textId, matchId);
         List<String> f_list = null;
         List<String> l_list = null;
         if (layers != null && !layers.isEmpty())
diff --git a/src/main/java/de/ids_mannheim/korap/web/utils/KustvaktResponseHandler.java b/src/main/java/de/ids_mannheim/korap/web/utils/KustvaktResponseHandler.java
index df5cd42..086336b 100644
--- a/src/main/java/de/ids_mannheim/korap/web/utils/KustvaktResponseHandler.java
+++ b/src/main/java/de/ids_mannheim/korap/web/utils/KustvaktResponseHandler.java
@@ -84,9 +84,9 @@
     private static Response.Status getStatus (int code) {
         Response.Status status = Response.Status.BAD_REQUEST;
         switch (code) {
-            case StatusCodes.NO_VALUE_FOUND:
-                status = Response.Status.NO_CONTENT;
-                break;
+//            case StatusCodes.NO_VALUE_FOUND:
+//                status = Response.Status.NO_CONTENT;
+//                break;
             case StatusCodes.ILLEGAL_ARGUMENT:
                 status = Response.Status.NOT_ACCEPTABLE;
                 break;
diff --git a/src/main/resources/db/mysql/V0.1__userdatabase.sql b/src/main/resources/db/mysql/V0.1__userdatabase.sql
index 09b1591..c069b6e 100644
--- a/src/main/resources/db/mysql/V0.1__userdatabase.sql
+++ b/src/main/resources/db/mysql/V0.1__userdatabase.sql
@@ -14,6 +14,13 @@
     account_link VARCHAR(100)
 );
 
+CREATE TABLE IF NOT EXISTS admin_users (
+    id INTEGER PRIMARY KEY AUTO_INCREMENT,
+    user_id INTEGER NOT NULL,
+    foreign key (user_id)
+    references korap_users (id)
+);
+
 CREATE TABLE IF NOT EXISTS shib_users (
     id INTEGER PRIMARY KEY AUTO_INCREMENT,
     username VARCHAR(100) NOT NULL UNIQUE,
diff --git a/src/main/resources/db/mysql/mysql_schema_comp.sql b/src/main/resources/db/mysql/mysql_schema_comp.sql
index 6ee11c5..44ec4de 100644
--- a/src/main/resources/db/mysql/mysql_schema_comp.sql
+++ b/src/main/resources/db/mysql/mysql_schema_comp.sql
@@ -22,6 +22,13 @@
     accountLink VARCHAR(100)
 )$$
 
+CREATE TABLE IF NOT EXISTS admin_users (
+    id INTEGER PRIMARY KEY AUTO_INCREMENT,
+    user_id INTEGER NOT NULL,
+    foreign key (user_id)
+    references korap_users (id)
+)$$
+
 CREATE TABLE IF NOT EXISTS user_details (
     Id INTEGER PRIMARY KEY AUTO_INCREMENT,
     userID INTEGER NOT NULL UNIQUE,
diff --git a/src/main/resources/db/sqlite/V1__Initial_version.sql b/src/main/resources/db/sqlite/V1__Initial_version.sql
index eaa32ff..943d3cd 100644
--- a/src/main/resources/db/sqlite/V1__Initial_version.sql
+++ b/src/main/resources/db/sqlite/V1__Initial_version.sql
@@ -11,6 +11,13 @@
 account_link VARCHAR(100)
 );
 
+CREATE TABLE IF NOT EXISTS admin_users (
+id INTEGER PRIMARY KEY AUTOINCREMENT,
+user_id INTEGER NOT NULL,
+foreign key (user_id)
+references korap_users (id)
+);
+
 CREATE TABLE IF NOT EXISTS shib_users (
 id INTEGER PRIMARY KEY AUTOINCREMENT,
 username VARCHAR(150) NOT NULL UNIQUE,
diff --git a/src/main/resources/default-config.xml b/src/main/resources/default-config.xml
index 62d5997..0a95416 100644
--- a/src/main/resources/default-config.xml
+++ b/src/main/resources/default-config.xml
@@ -56,19 +56,22 @@
 
     <!--class="org.apache.commons.dbcp2.BasicDataSource"-->
     <!-- org.springframework.jdbc.datasource.SingleConnectionDataSource -->
-    <bean id="dataSource"
-          class="org.springframework.jdbc.datasource.SingleConnectionDataSource"
+    <bean id="dataSource"	
+          class="org.apache.commons.dbcp2.BasicDataSource"
           lazy-init="true">
         <property name="driverClassName" value="${jdbc.driverClassName}"/>
         <property name="url" value="${jdbc.url}"/>
         <property name="username" value="${jdbc.username}"/>
         <property name="password" value="${jdbc.password}"/>
         <!-- relevant for single connection datasource and sqlite -->
-        <property name="suppressClose">
+        <!-- <property name="suppressClose">
             <value>true</value>
-        </property>
+        </property> -->
         <!--<property name="initialSize" value="2"/>-->
-        <!--<property name="maxIdle" value="2"/>-->
+        <property name="maxTotal" value="4"/>
+        <property name="maxIdle" value="2"/>
+        <property name="minIdle" value="1"/>
+        <property name="maxWaitMillis" value="15000"/>
         <!--<property name="poolPreparedStatements" value="true"/>-->
     </bean>
 
@@ -96,7 +99,12 @@
           class="de.ids_mannheim.korap.handlers.EntityDao">
         <constructor-arg ref="kustvakt_db"/>
     </bean>
-
+	
+	<bean id="kustvakt_admindb"
+          class="de.ids_mannheim.korap.handlers.AdminDao">
+        <constructor-arg ref="kustvakt_db"/>
+    </bean>
+    
     <bean id="resource_provider"
           class="de.ids_mannheim.korap.handlers.ResourceDao">
         <constructor-arg ref="kustvakt_db"/>
@@ -189,6 +197,9 @@
         <constructor-arg
                 type="de.ids_mannheim.korap.interfaces.db.EntityHandlerIface"
                 ref="kustvakt_userdb"/>
+        <constructor-arg
+                type="de.ids_mannheim.korap.interfaces.db.AdminHandlerIface"
+                ref="kustvakt_admindb"/>
         <constructor-arg type="de.ids_mannheim.korap.interfaces.EncryptionIface"
                          ref="kustvakt_encryption"/>
         <constructor-arg ref="kustvakt_config"/>
diff --git a/src/main/resources/index-goe-lucene5/_0.cfe b/src/main/resources/index-goe-lucene5/_0.cfe
deleted file mode 100644
index 72246bc..0000000
--- a/src/main/resources/index-goe-lucene5/_0.cfe
+++ /dev/null
Binary files differ
diff --git a/src/main/resources/index-goe-lucene5/_0.cfs b/src/main/resources/index-goe-lucene5/_0.cfs
deleted file mode 100644
index d15185a..0000000
--- a/src/main/resources/index-goe-lucene5/_0.cfs
+++ /dev/null
Binary files differ
diff --git a/src/main/resources/index-goe-lucene5/_0.si b/src/main/resources/index-goe-lucene5/_0.si
deleted file mode 100644
index d66ea34..0000000
--- a/src/main/resources/index-goe-lucene5/_0.si
+++ /dev/null
Binary files differ
diff --git a/src/main/resources/index-goe-lucene5/_1.cfe b/src/main/resources/index-goe-lucene5/_1.cfe
deleted file mode 100644
index 221e372..0000000
--- a/src/main/resources/index-goe-lucene5/_1.cfe
+++ /dev/null
Binary files differ
diff --git a/src/main/resources/index-goe-lucene5/_1.cfs b/src/main/resources/index-goe-lucene5/_1.cfs
deleted file mode 100644
index 6b998a4..0000000
--- a/src/main/resources/index-goe-lucene5/_1.cfs
+++ /dev/null
Binary files differ
diff --git a/src/main/resources/index-goe-lucene5/_1.si b/src/main/resources/index-goe-lucene5/_1.si
deleted file mode 100644
index 18b647a..0000000
--- a/src/main/resources/index-goe-lucene5/_1.si
+++ /dev/null
Binary files differ
diff --git a/src/main/resources/index-goe-lucene5/_2.cfe b/src/main/resources/index-goe-lucene5/_2.cfe
deleted file mode 100644
index 0b8386b..0000000
--- a/src/main/resources/index-goe-lucene5/_2.cfe
+++ /dev/null
Binary files differ
diff --git a/src/main/resources/index-goe-lucene5/_2.cfs b/src/main/resources/index-goe-lucene5/_2.cfs
deleted file mode 100644
index f9828fd..0000000
--- a/src/main/resources/index-goe-lucene5/_2.cfs
+++ /dev/null
Binary files differ
diff --git a/src/main/resources/index-goe-lucene5/_2.si b/src/main/resources/index-goe-lucene5/_2.si
deleted file mode 100644
index ddcd167..0000000
--- a/src/main/resources/index-goe-lucene5/_2.si
+++ /dev/null
Binary files differ
diff --git a/src/main/resources/index-goe-lucene5/_3.cfe b/src/main/resources/index-goe-lucene5/_3.cfe
deleted file mode 100644
index 2eaa97b..0000000
--- a/src/main/resources/index-goe-lucene5/_3.cfe
+++ /dev/null
Binary files differ
diff --git a/src/main/resources/index-goe-lucene5/_3.cfs b/src/main/resources/index-goe-lucene5/_3.cfs
deleted file mode 100644
index f2ec38e..0000000
--- a/src/main/resources/index-goe-lucene5/_3.cfs
+++ /dev/null
Binary files differ
diff --git a/src/main/resources/index-goe-lucene5/_3.si b/src/main/resources/index-goe-lucene5/_3.si
deleted file mode 100644
index c1fbcdf..0000000
--- a/src/main/resources/index-goe-lucene5/_3.si
+++ /dev/null
Binary files differ
diff --git a/src/main/resources/index-goe-lucene5/_4.cfe b/src/main/resources/index-goe-lucene5/_4.cfe
deleted file mode 100644
index 34cda7d..0000000
--- a/src/main/resources/index-goe-lucene5/_4.cfe
+++ /dev/null
Binary files differ
diff --git a/src/main/resources/index-goe-lucene5/_4.cfs b/src/main/resources/index-goe-lucene5/_4.cfs
deleted file mode 100644
index 224beae..0000000
--- a/src/main/resources/index-goe-lucene5/_4.cfs
+++ /dev/null
Binary files differ
diff --git a/src/main/resources/index-goe-lucene5/_4.si b/src/main/resources/index-goe-lucene5/_4.si
deleted file mode 100644
index 84a3366..0000000
--- a/src/main/resources/index-goe-lucene5/_4.si
+++ /dev/null
Binary files differ
diff --git a/src/main/resources/index-goe-lucene5/segments_1 b/src/main/resources/index-goe-lucene5/segments_1
deleted file mode 100644
index 1cb809a..0000000
--- a/src/main/resources/index-goe-lucene5/segments_1
+++ /dev/null
Binary files differ
diff --git a/src/main/resources/index-goe-lucene5/write.lock b/src/main/resources/index-goe-lucene5/write.lock
deleted file mode 100644
index e69de29..0000000
--- a/src/main/resources/index-goe-lucene5/write.lock
+++ /dev/null
diff --git a/src/test/java/de/ids_mannheim/korap/config/BeanConfigTest.java b/src/test/java/de/ids_mannheim/korap/config/BeanConfigTest.java
index 0309437..4407fb6 100644
--- a/src/test/java/de/ids_mannheim/korap/config/BeanConfigTest.java
+++ b/src/test/java/de/ids_mannheim/korap/config/BeanConfigTest.java
@@ -1,11 +1,8 @@
 package de.ids_mannheim.korap.config;
 
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import net.jcip.annotations.NotThreadSafe;
+import static org.junit.Assert.assertNotNull;
+
 import org.apache.log4j.Logger;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.runner.RunWith;
 import org.junit.runner.notification.RunNotifier;
 import org.junit.runners.model.InitializationError;
@@ -15,10 +12,8 @@
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
-import javax.annotation.PostConstruct;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import net.jcip.annotations.NotThreadSafe;
 
 /**
  * @author hanl
diff --git a/src/test/java/de/ids_mannheim/korap/config/BeanInjectTest.java b/src/test/java/de/ids_mannheim/korap/config/BeanInjectTest.java
index cd2f480..f840d71 100644
--- a/src/test/java/de/ids_mannheim/korap/config/BeanInjectTest.java
+++ b/src/test/java/de/ids_mannheim/korap/config/BeanInjectTest.java
@@ -25,7 +25,7 @@
 
     @Test
     public void testUserBeans () {
-        BeansFactory.loadClasspathContext("default-config.xml");
+        BeansFactory.loadClasspathContext("test-default-config.xml");
         Collection coll = BeansFactory.getKustvaktContext()
                 .getUserDataProviders();
         assertFalse(coll.isEmpty());
@@ -42,7 +42,7 @@
 
     @Test
     public void testResourceBeans () {
-        BeansFactory.loadClasspathContext("default-config.xml");
+        BeansFactory.loadClasspathContext("test-default-config.xml");
         Collection coll = BeansFactory.getKustvaktContext()
                 .getResourceProviders();
         assertFalse(coll.isEmpty());
diff --git a/src/test/java/de/ids_mannheim/korap/config/TestBeans.java b/src/test/java/de/ids_mannheim/korap/config/TestBeans.java
index 7d33ba2..8c96bc4 100644
--- a/src/test/java/de/ids_mannheim/korap/config/TestBeans.java
+++ b/src/test/java/de/ids_mannheim/korap/config/TestBeans.java
@@ -1,5 +1,6 @@
 package de.ids_mannheim.korap.config;
 
+import de.ids_mannheim.korap.handlers.AdminDao;
 import de.ids_mannheim.korap.interfaces.AuthenticationManagerIface;
 import de.ids_mannheim.korap.interfaces.EncryptionIface;
 import de.ids_mannheim.korap.interfaces.db.*;
@@ -13,35 +14,29 @@
  */
 public abstract class TestBeans {
 
-    protected PersistenceClient dataSource;
+	protected PersistenceClient dataSource;
 
+	public abstract PolicyHandlerIface getPolicyDao();
 
-    public abstract PolicyHandlerIface getPolicyDao ();
+	public abstract KustvaktConfiguration getConfig();
 
+	public abstract EntityHandlerIface getUserDao();
+	
+	public abstract AdminHandlerIface getAdminDao();
 
-    public abstract KustvaktConfiguration getConfig ();
+	public abstract AuditingIface getAuditingDao();
 
+	public abstract List<ResourceOperationIface> getResourceDaos();
 
-    public abstract EntityHandlerIface getUserDao ();
+	public abstract List<UserDataDbIface> getUserdataDaos();
 
+	public abstract EncryptionIface getCrypto();
 
-    public abstract AuditingIface getAuditingDao ();
+	public abstract AuthenticationManagerIface getAuthManager();
 
+	@Bean(name = "kustvakt_db")
+	public PersistenceClient getDataSource() {
+		return this.dataSource;
+	}
 
-    public abstract List<ResourceOperationIface> getResourceDaos ();
-
-
-    public abstract List<UserDataDbIface> getUserdataDaos ();
-
-
-    public abstract EncryptionIface getCrypto ();
-
-
-    public abstract AuthenticationManagerIface getAuthManager ();
-
-
-    @Bean(name = "kustvakt_db")
-    public PersistenceClient getDataSource () {
-        return this.dataSource;
-    }
 }
diff --git a/src/test/java/de/ids_mannheim/korap/config/TestHelper.java b/src/test/java/de/ids_mannheim/korap/config/TestHelper.java
index 96aaf94..50b1e6e 100644
--- a/src/test/java/de/ids_mannheim/korap/config/TestHelper.java
+++ b/src/test/java/de/ids_mannheim/korap/config/TestHelper.java
@@ -1,31 +1,9 @@
 package de.ids_mannheim.korap.config;
 
-import de.ids_mannheim.korap.exceptions.EmptyResultException;
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.handlers.*;
-import de.ids_mannheim.korap.interfaces.AuthenticationIface;
-import de.ids_mannheim.korap.interfaces.AuthenticationManagerIface;
-import de.ids_mannheim.korap.interfaces.EncryptionIface;
-import de.ids_mannheim.korap.interfaces.db.*;
-import de.ids_mannheim.korap.interfaces.defaults.KustvaktEncryption;
-import de.ids_mannheim.korap.resources.KustvaktResource;
-import de.ids_mannheim.korap.security.ac.PolicyDao;
-import de.ids_mannheim.korap.security.auth.*;
-import de.ids_mannheim.korap.user.User;
-import de.ids_mannheim.korap.utils.TimeUtils;
-import de.ids_mannheim.korap.web.service.BootableBeanInterface;
-import org.apache.commons.collections.map.HashedMap;
-import org.apache.commons.dbcp2.BasicDataSource;
-import org.flywaydb.core.Flyway;
-import org.joda.time.DateTime;
-import org.junit.Assert;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.annotation.Bean;
-import org.springframework.jdbc.core.RowCallbackHandler;
-import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
-import org.springframework.jdbc.datasource.SingleConnectionDataSource;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 
 import java.io.File;
 import java.io.IOException;
@@ -34,9 +12,56 @@
 import java.security.NoSuchAlgorithmException;
 import java.sql.ResultSet;
 import java.sql.SQLException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
-import static org.junit.Assert.*;
+import org.apache.commons.dbcp2.BasicDataSource;
+import org.flywaydb.core.Flyway;
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.jdbc.core.RowCallbackHandler;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
+import org.springframework.jdbc.datasource.SingleConnectionDataSource;
+
+import de.ids_mannheim.korap.exceptions.EmptyResultException;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.handlers.AdminDao;
+import de.ids_mannheim.korap.handlers.DocumentDao;
+import de.ids_mannheim.korap.handlers.EntityDao;
+import de.ids_mannheim.korap.handlers.JDBCAuditing;
+import de.ids_mannheim.korap.handlers.JDBCClient;
+import de.ids_mannheim.korap.handlers.ResourceDao;
+import de.ids_mannheim.korap.handlers.UserDetailsDao;
+import de.ids_mannheim.korap.handlers.UserSettingsDao;
+import de.ids_mannheim.korap.interfaces.AuthenticationIface;
+import de.ids_mannheim.korap.interfaces.AuthenticationManagerIface;
+import de.ids_mannheim.korap.interfaces.EncryptionIface;
+import de.ids_mannheim.korap.interfaces.db.AdminHandlerIface;
+import de.ids_mannheim.korap.interfaces.db.AuditingIface;
+import de.ids_mannheim.korap.interfaces.db.EntityHandlerIface;
+import de.ids_mannheim.korap.interfaces.db.PersistenceClient;
+import de.ids_mannheim.korap.interfaces.db.PolicyHandlerIface;
+import de.ids_mannheim.korap.interfaces.db.ResourceOperationIface;
+import de.ids_mannheim.korap.interfaces.db.UserDataDbIface;
+import de.ids_mannheim.korap.interfaces.defaults.KustvaktEncryption;
+import de.ids_mannheim.korap.resources.KustvaktResource;
+import de.ids_mannheim.korap.security.ac.PolicyDao;
+import de.ids_mannheim.korap.security.auth.APIAuthentication;
+import de.ids_mannheim.korap.security.auth.BasicHttpAuth;
+import de.ids_mannheim.korap.security.auth.KustvaktAuthenticationManager;
+import de.ids_mannheim.korap.security.auth.OpenIDconnectAuthentication;
+import de.ids_mannheim.korap.security.auth.SessionAuthentication;
+import de.ids_mannheim.korap.user.User;
+import de.ids_mannheim.korap.utils.TimeUtils;
+import de.ids_mannheim.korap.web.service.BootableBeanInterface;
 
 /**
  * creates a test user that can be used to access protected functions
@@ -46,6 +71,7 @@
  */
 public class TestHelper {
 
+    private static String mainConfigurationFile = "kustvakt-test.conf";
     private static Logger jlog = LoggerFactory.getLogger(TestHelper.class);
     private static final Map<String, Object> data = new HashMap<>();
     static  {
@@ -414,12 +440,17 @@
             return new EntityDao(this.dataSource);
         }
 
-
+        @Bean(name = ContextHolder.KUSTVAKT_ADMINDB)
+        @Override
+        public AdminHandlerIface getAdminDao () {
+            return new AdminDao(this.dataSource);
+        }
+        
         @Bean(name = ContextHolder.KUSTVAKT_CONFIG)
         @Override
         public KustvaktConfiguration getConfig () {
             KustvaktConfiguration c = new KustvaktConfiguration();
-            InputStream s = ConfigLoader.loadConfigStream("kustvakt.conf");
+            InputStream s = ConfigLoader.loadConfigStream(mainConfigurationFile);
             if (s != null)
                 c.setPropertiesAsStream(s);
             else {
@@ -468,7 +499,7 @@
         @Override
         public AuthenticationManagerIface getAuthManager () {
             AuthenticationManagerIface manager = new KustvaktAuthenticationManager(
-                    getUserDao(), getCrypto(), getConfig(), getAuditingDao(),
+                    getUserDao(), getAdminDao(), getCrypto(), getConfig(), getAuditingDao(),
                     getUserdataDaos());
             Set<AuthenticationIface> pro = new HashSet<>();
             pro.add(new BasicHttpAuth());
diff --git a/src/test/java/de/ids_mannheim/korap/handlers/ResourceDaoTest.java b/src/test/java/de/ids_mannheim/korap/handlers/ResourceDaoTest.java
index 15bdd4f..02bfe4a 100644
--- a/src/test/java/de/ids_mannheim/korap/handlers/ResourceDaoTest.java
+++ b/src/test/java/de/ids_mannheim/korap/handlers/ResourceDaoTest.java
@@ -1,5 +1,18 @@
 package de.ids_mannheim.korap.handlers;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Assert;
+import org.junit.Test;
+
 import de.ids_mannheim.korap.config.Attributes;
 import de.ids_mannheim.korap.config.BeanConfigTest;
 import de.ids_mannheim.korap.config.KustvaktClassLoader;
@@ -8,15 +21,6 @@
 import de.ids_mannheim.korap.resources.KustvaktResource;
 import de.ids_mannheim.korap.resources.VirtualCollection;
 import de.ids_mannheim.korap.user.User;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import static org.junit.Assert.*;
-import static org.junit.Assert.assertNotEquals;
 
 /**
  * @author hanl
@@ -26,20 +30,28 @@
 
     private static List<Integer> ids = new ArrayList<>();
 
+//    @Autowired
+//    private TransactionTemplate txTemplate;
+//    
+//    @Autowired
+//    private ResourceDao<KustvaktResource> resourceDao;
 
     @Override
     public void initMethod () {
         helper().setupAccount();
 
-        List classes = new ArrayList<>(
+        List<Class<? extends KustvaktResource>> classes = new ArrayList<>(
                 KustvaktClassLoader.loadSubTypes(KustvaktResource.class));
         int size = classes.size();
         for (int i = 0; i < size; i++) {
-            Class s = (Class) classes.get(i < classes.size() ? i : 0);
+            Class<? extends KustvaktResource> s = classes.get(i < classes.size() ? i : 0);
             try {
                 KustvaktResource r = (KustvaktResource) s.newInstance();
                 r.setName("resource_" + i);
                 r.setPersistentID(r.getName());
+                Map<String, Object> map = new HashMap<>();
+                map.put("testVar", "testVal_" + i);
+				r.setFields(map);
                 int id = helper().setupResource(r);
                 ids.add(id);
                 assertNotEquals(0, new ResourceDao<>(helper().getContext()
@@ -55,7 +67,6 @@
         }
     }
 
-
     @Test
     public void testBatchGetResources () throws KustvaktException {
         ResourceDao dao = new ResourceDao(helper().getContext()
@@ -68,7 +79,7 @@
 
     @Test
     public void testGetResource () throws KustvaktException {
-        ResourceDao dao = new ResourceDao(helper().getContext()
+        ResourceDao<?> dao = new ResourceDao<>(helper().getContext()
                 .getPersistenceClient());
         assertEquals("sqlite", helper().getContext().getPersistenceClient()
                 .getDatabase());
@@ -77,6 +88,7 @@
         KustvaktResource res = dao.findbyId(ids.get(0),
                 User.UserFactory.getDemoUser());
         assertNotNull(res);
+        Assert.assertEquals(true,res.getField("testVar").toString().startsWith("testVal_"));
     }
 
 
diff --git a/src/test/java/de/ids_mannheim/korap/security/ResourceFinderTest.java b/src/test/java/de/ids_mannheim/korap/security/ResourceFinderTest.java
index 5da39a4..ce7be2b 100644
--- a/src/test/java/de/ids_mannheim/korap/security/ResourceFinderTest.java
+++ b/src/test/java/de/ids_mannheim/korap/security/ResourceFinderTest.java
@@ -24,7 +24,7 @@
         Set<VirtualCollection> resources = ResourceFinder
                 .searchPublic(VirtualCollection.class);
         assertFalse(resources.isEmpty());
-        assertEquals(3, resources.size());
+        assertEquals(1, resources.size());
     }
 
 
@@ -38,11 +38,11 @@
     @Test
     public void testResourcesDemoFiltered () throws KustvaktException {
         Set<Corpus> resources = ResourceFinder.searchPublicFiltered(
-                Corpus.class, "WPD");
+                Corpus.class, "WPD13");
         assertNotEquals(0, resources.size());
         assertEquals(1, resources.size());
 
-        resources = ResourceFinder.searchPublicFiltered(Corpus.class, "WPD",
+        resources = ResourceFinder.searchPublicFiltered(Corpus.class, "WPD13",
                 "GOE");
         assertNotEquals(0, resources.size());
         assertEquals(2, resources.size());
diff --git a/src/test/java/de/ids_mannheim/korap/security/ResourcesTest.java b/src/test/java/de/ids_mannheim/korap/security/ResourcesTest.java
index 99fd537..fb83bb4 100644
--- a/src/test/java/de/ids_mannheim/korap/security/ResourcesTest.java
+++ b/src/test/java/de/ids_mannheim/korap/security/ResourcesTest.java
@@ -103,13 +103,13 @@
         Set s = ResourceFinder.searchPublic(Corpus.class);
         assertEquals(2, s.size());
         s = ResourceFinder.searchPublic(Foundry.class);
-        assertEquals(1, s.size());
+        assertEquals(10, s.size());
     }
 
 
     @Test
     public void getDemoResourceFiltered () throws KustvaktException {
-        Set s = ResourceFinder.searchPublicFiltered(Corpus.class, "WPD");
+        Set s = ResourceFinder.searchPublicFiltered(Corpus.class, "WPD13");
         assertEquals(1, s.size());
     }
 
diff --git a/src/test/java/de/ids_mannheim/korap/user/UserdataTest.java b/src/test/java/de/ids_mannheim/korap/user/UserdataTest.java
index 072f702..017abba 100644
--- a/src/test/java/de/ids_mannheim/korap/user/UserdataTest.java
+++ b/src/test/java/de/ids_mannheim/korap/user/UserdataTest.java
@@ -6,7 +6,7 @@
 import de.ids_mannheim.korap.config.BeanConfigTest;
 import de.ids_mannheim.korap.config.BeansFactory;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.exceptions.dbException;
+import de.ids_mannheim.korap.exceptions.DatabaseException;
 import de.ids_mannheim.korap.handlers.UserDetailsDao;
 import de.ids_mannheim.korap.handlers.UserSettingsDao;
 import de.ids_mannheim.korap.interfaces.db.UserDataDbIface;
diff --git a/src/test/java/de/ids_mannheim/korap/web/service/FastJerseyTest.java b/src/test/java/de/ids_mannheim/korap/web/service/FastJerseyTest.java
index b1a1371..87457bd 100644
--- a/src/test/java/de/ids_mannheim/korap/web/service/FastJerseyTest.java
+++ b/src/test/java/de/ids_mannheim/korap/web/service/FastJerseyTest.java
@@ -37,11 +37,12 @@
 
     private static TestContainer testContainer;
 
-    private static Client client;
+    protected static Client client;
     private static String[] classPackages = null;
 
     private static int PORT = 8089; // FB, was: 9000;
     private static int PORT_IT = 1;
+    protected static String containerURI = "http://localhost/";
 
 
     public static void addClass (Class<?> resourceClass) {
@@ -108,7 +109,7 @@
                 tcf = new GrizzlyWebTestContainerFactory();
         }
 
-        testContainer = tcf.create(UriBuilder.fromUri("http://localhost/")
+        testContainer = tcf.create(UriBuilder.fromUri(containerURI)
                 .port(port).build(), ad);
         client = testContainer.getClient();
         if (client == null) {
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
new file mode 100644
index 0000000..a5e91da
--- /dev/null
+++ b/src/test/java/de/ids_mannheim/korap/web/service/full/KustvaktServerTest.java
@@ -0,0 +1,375 @@
+package de.ids_mannheim.korap.web.service.full;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.util.List;
+import java.util.UUID;
+
+import javax.net.ssl.SSLContext;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.config.Registry;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLContexts;
+import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.io.Files;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.core.util.MultivaluedMapImpl;
+
+import de.ids_mannheim.korap.config.Attributes;
+import de.ids_mannheim.korap.config.BeanConfigTest;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.handlers.ResourceDao;
+import de.ids_mannheim.korap.resources.KustvaktResource;
+import de.ids_mannheim.korap.resources.Permissions.Permission;
+import de.ids_mannheim.korap.security.auth.BasicHttpAuth;
+import de.ids_mannheim.korap.user.User;
+import de.ids_mannheim.korap.utils.JsonUtils;
+
+/**
+ * This class tests services of a running Kustvakt server with a MySQL
+ * database.
+ * Please check the database configuration in
+ * src/main/resources/jdbc.properties
+ * and run the server before running the tests.
+ * 
+ * See {@link ResourceServiceTest} for tests using an in-memory
+ * database.
+ * 
+ * @author margaretha
+ *
+ */
+public class KustvaktServerTest extends BeanConfigTest {
+    private static ObjectMapper mapper = new ObjectMapper();
+
+
+    @Test
+    public void testRegisterBadPassword ()
+            throws URISyntaxException, ClientProtocolException, IOException {
+        HttpClient httpClient = HttpClients.createDefault();
+
+        MultivaluedMap<String, String> map = new MultivaluedMapImpl();
+        map.putSingle("username", "kusvakt");
+        map.putSingle("email", "kustvakt@ids-mannheim.de");
+        map.putSingle("password", "password");
+        map.putSingle("firstName", "kustvakt");
+        map.putSingle("lastName", "user");
+        map.putSingle("address", "Mannheim");
+
+        URIBuilder builder = new URIBuilder();
+        builder.setScheme("http").setHost("localhost").setPort(8089)
+                .setPath("/api/v0.1/user/register");
+        URI uri = builder.build();
+        HttpPost httppost = new HttpPost(uri);
+        StringEntity entity = new StringEntity(JsonUtils.toJSON(map));
+        httppost.setEntity(entity);
+        httppost.addHeader(HttpHeaders.CONTENT_TYPE,
+                MediaType.APPLICATION_JSON);
+        httppost.addHeader(HttpHeaders.USER_AGENT, "Apache HTTP Client");
+        httppost.addHeader(HttpHeaders.HOST, "localhost");
+
+        HttpResponse response = httpClient.execute(httppost);
+        assertEquals(ClientResponse.Status.NOT_ACCEPTABLE.getStatusCode(),
+                response.getStatusLine().getStatusCode());
+
+        HttpEntity responseEntity = response.getEntity();
+        JsonNode errorNode = mapper.readTree(responseEntity.getContent());
+        assertEquals(
+                "[The value for the parameter password is not valid or acceptable.]",
+                errorNode.get("errors").get(0).get(2).asText());
+
+    }
+
+
+    @Test
+    public void testRegisterExistingUsername ()
+            throws URISyntaxException, ClientProtocolException, IOException {
+        HttpClient httpClient = HttpClients.createDefault();
+
+        MultivaluedMap<String, String> map = new MultivaluedMapImpl();
+        map.putSingle("username", "kustvakt");
+        map.putSingle("email", "kustvakt@ids-mannheim.de");
+        map.putSingle("password", "password1234");
+        map.putSingle("firstName", "kustvakt");
+        map.putSingle("lastName", "user");
+        map.putSingle("address", "Mannheim");
+
+        URIBuilder builder = new URIBuilder();
+        builder.setScheme("http").setHost("localhost").setPort(8089)
+                .setPath("/api/v0.1/user/register");
+        URI uri = builder.build();
+        HttpPost httppost = new HttpPost(uri);
+        StringEntity entity = new StringEntity(JsonUtils.toJSON(map));
+        httppost.setEntity(entity);
+        httppost.addHeader(HttpHeaders.CONTENT_TYPE,
+                MediaType.APPLICATION_JSON);
+        httppost.addHeader(HttpHeaders.USER_AGENT, "Apache HTTP Client");
+        httppost.addHeader(HttpHeaders.HOST, "localhost");
+
+        HttpResponse response = httpClient.execute(httppost);
+        assertEquals(ClientResponse.Status.BAD_REQUEST.getStatusCode(),
+                response.getStatusLine().getStatusCode());
+
+        HttpEntity responseEntity = response.getEntity();
+        JsonNode errorNode = mapper.readTree(responseEntity.getContent());
+        assertEquals(
+                "[The value for the parameter password is not valid or acceptable.]",
+                errorNode.get("errors").asText());
+    }
+
+
+    @Test
+    public void testRegisterUser ()
+            throws URISyntaxException, ClientProtocolException, IOException {
+        HttpClient httpClient = HttpClients.createDefault();
+
+        MultivaluedMap<String, String> map = new MultivaluedMapImpl();
+        map.putSingle("username", "testUser");
+        map.putSingle("email", "testUser@ids-mannheim.de");
+        map.putSingle("password", "testPassword1234");
+        map.putSingle("firstName", "test");
+        map.putSingle("lastName", "user");
+        map.putSingle("address", "Mannheim");
+
+        URIBuilder builder = new URIBuilder();
+        builder.setScheme("http").setHost("localhost").setPort(8089)
+                .setPath("/api/v0.1/user/register");
+        URI uri = builder.build();
+        HttpPost httppost = new HttpPost(uri);
+        StringEntity entity = new StringEntity(JsonUtils.toJSON(map));
+        httppost.setEntity(entity);
+        httppost.addHeader(HttpHeaders.CONTENT_TYPE,
+                MediaType.APPLICATION_JSON);
+        httppost.addHeader(HttpHeaders.USER_AGENT, "Apache HTTP Client");
+        httppost.addHeader(HttpHeaders.HOST, "localhost");
+
+        HttpResponse response = httpClient.execute(httppost);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatusLine().getStatusCode());
+
+    }
+
+
+    @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", "");
+
+        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 testCreatePolicyForFoundry ()
+            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", "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");
+
+        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 testCreatePolicyWithMultiplePermissions ()
+            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", "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");
+
+        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 {
+
+        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);
+
+    }
+    
+    @Test
+    public void testResourceUpdate ()
+            throws IOException, URISyntaxException {
+
+        HttpClient httpclient = HttpClients.createDefault();
+        URIBuilder builder = new URIBuilder();
+        builder.setScheme("http").setHost("localhost").setPort(8089)
+                .setPath("/api/v0.1/virtualcollection/00df953b-2227-4c23-84c1-5532c07bf8ce")
+                .setParameter("name", "Goethe collection")
+                .setParameter("description", "Goethe collection");
+        URI uri = builder.build();
+        HttpPost httppost = new HttpPost(uri);
+        httppost.addHeader(Attributes.AUTHORIZATION,
+                BasicHttpAuth.encode("kustvakt", "kustvakt2015"));
+        HttpResponse response = 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/LightServiceTest.java b/src/test/java/de/ids_mannheim/korap/web/service/full/LightServiceTest.java
index 8a94c44..522d3b3 100644
--- a/src/test/java/de/ids_mannheim/korap/web/service/full/LightServiceTest.java
+++ b/src/test/java/de/ids_mannheim/korap/web/service/full/LightServiceTest.java
@@ -145,11 +145,10 @@
 
 	@Test
 	public void testMatchInfoGet1 () {
-		// match-WPD_AAA.00001-p4-5
         ClientResponse response = resource()
 			.path(getAPIVersion())
-			//.path("corpus/GOE/AGI.00200/p13576-13577/matchInfo")
-			.path("corpus/WPD/AAA.00001/p4-5/matchInfo")
+			.path("corpus/GOE/AGI/04846/p36875-36876/matchInfo")
+			//.path("corpus/WPD/AAA.00001/p4-5/matchInfo")
 			.queryParam("foundry", "*")
 			.queryParam("spans", "false")
 			.get(ClientResponse.class);
@@ -158,16 +157,16 @@
         String ent = response.getEntity(String.class);
         JsonNode node = JsonUtils.readTree(ent);
         assertNotNull(node);
-        assertEquals("WPD/AAA/00001", node.at("/textSigle").asText());
+        assertEquals("GOE/AGI/04846", node.at("/textSigle").asText());
+        assertEquals("Zweiter römischer Aufenthalt", node.at("/title").asText());
 	};
 
 	@Test
 	public void testMatchInfoGet2 () {
-		// match-WPD_AAA.00001-p4-5
         ClientResponse response = resource()
 			.path(getAPIVersion())
-			//.path("corpus/GOE/AGI.00200/p13576-13577/matchInfo")
-			.path("corpus/WPD/AAA.00001/p4-5/matchInfo")
+			.path("corpus/GOE/AGI/04846/p36875-36876/matchInfo")
+			//.path("corpus/WPD/AAA.00001/p4-5/matchInfo")
 			.queryParam("foundry", "*")
 			.get(ClientResponse.class);
         assertEquals(ClientResponse.Status.OK.getStatusCode(),
@@ -175,7 +174,8 @@
         String ent = response.getEntity(String.class);
         JsonNode node = JsonUtils.readTree(ent);
         assertNotNull(node);
-        assertEquals("WPD/AAA/00001", node.at("/textSigle").asText());
+        assertEquals("GOE/AGI/04846", node.at("/textSigle").asText());
+        assertEquals("Zweiter römischer Aufenthalt", node.at("/title").asText());
 	};
 
     @Test
diff --git a/src/test/java/de/ids_mannheim/korap/web/service/full/MatchInfoServiceTest.java b/src/test/java/de/ids_mannheim/korap/web/service/full/MatchInfoServiceTest.java
new file mode 100644
index 0000000..c3f3724
--- /dev/null
+++ b/src/test/java/de/ids_mannheim/korap/web/service/full/MatchInfoServiceTest.java
@@ -0,0 +1,103 @@
+package de.ids_mannheim.korap.web.service.full;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.sun.jersey.api.client.ClientResponse;
+
+import de.ids_mannheim.korap.config.Attributes;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.security.auth.BasicHttpAuth;
+import de.ids_mannheim.korap.utils.JsonUtils;
+import de.ids_mannheim.korap.web.service.FastJerseyTest;
+
+public class MatchInfoServiceTest 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");
+    }
+
+
+    @Test
+    public void testGetMatchInfoPublicCorpus () {
+
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("corpus").path("GOE").path("AGI").path("04846")
+                .path("p36875-36876").path("matchInfo")
+                .queryParam("foundry", "*")
+                .get(ClientResponse.class);
+
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertNotNull(node);
+        assertEquals("GOE/AGI/04846", node.at("/textSigle").asText());
+        assertEquals("Zweiter römischer Aufenthalt",
+                node.at("/title").asText());
+        assertEquals("vom Juni 1787 bis April 1788",
+                node.at("/subTitle").asText());
+        assertEquals("Goethe, Johann Wolfgang von",
+                node.at("/author").asText());
+        assertTrue(node.at("/snippet").asText()
+                .startsWith("<span class=\"context-left\"></span>"
+                        + "<span class=\"match\"><span title=\"corenlp/p:ADV\">"
+                        + "<span title=\"opennlp/p:ADV\">"
+                        + "<span title=\"tt/l:fern\">"
+                        ));
+    }
+
+    @Test
+    public void testGetMatchInfoWithAuthentication () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("corpus").path("WPD15").path("B07").path("51608")
+                .path("p46-57").path("matchInfo")
+                .queryParam("foundry", "*")
+                .header(Attributes.AUTHORIZATION,
+                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
+                .get(ClientResponse.class);
+
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String entity = response.getEntity(String.class);
+//        System.out.println(entity);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertNotNull(node);
+        assertEquals("WPD15/B07/51608", node.at("/textSigle").asText());
+        assertEquals("Betty Allen",
+                node.at("/title").asText());
+        assertEquals("Monsieurbecker, u.a.",
+                node.at("/author").asText());
+        assertTrue(!node.at("/snippet").asText().isEmpty());
+    }
+//    @Test
+//    public void testMatchInfoSave () {
+//
+//    }
+//
+//
+//    @Test
+//    public void testMatchInfoDelete () {
+//
+//    }
+//
+//
+//    @Test
+//    public void testGetMatches () {
+//
+//    }
+
+
+    @Override
+    public void initMethod () throws KustvaktException {
+        helper().runBootInterfaces();
+    }
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..c48f40c
--- /dev/null
+++ b/src/test/java/de/ids_mannheim/korap/web/service/full/PolicyServiceTest.java
@@ -0,0 +1,177 @@
+package de.ids_mannheim.korap.web.service.full;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.UUID;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.sun.jersey.api.client.ClientResponse;
+
+import de.ids_mannheim.korap.config.Attributes;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.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;
+import de.ids_mannheim.korap.resources.VirtualCollection;
+import de.ids_mannheim.korap.security.PolicyCondition;
+import de.ids_mannheim.korap.security.SecurityPolicy;
+import de.ids_mannheim.korap.security.auth.BasicHttpAuth;
+import de.ids_mannheim.korap.user.User;
+import de.ids_mannheim.korap.user.User.UserFactory;
+import de.ids_mannheim.korap.web.service.FastJerseyTest;
+
+/**
+ * @author margaretha
+ */
+public class PolicyServiceTest extends FastJerseyTest {
+
+    private User user = UserFactory.getDemoUser();
+
+
+    @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("expire", "")
+                .header(Attributes.AUTHORIZATION,
+                        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(
+                new PolicyCondition("public"), VirtualCollection.class,
+                Permissions.Permission.READ.toByte());
+        assertEquals(2, policies.size());
+        
+        policies = dao.getPoliciesByPersistentId(
+                new PolicyCondition("public"), VirtualCollection.class,
+                Permissions.Permission.READ.toByte(),id);
+        assertEquals(1, policies.size());
+        assertEquals(id, policies.get(0).getTarget());
+
+        // 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/QuerySerializationServiceTest.java b/src/test/java/de/ids_mannheim/korap/web/service/full/QuerySerializationServiceTest.java
new file mode 100644
index 0000000..5fa2cd0
--- /dev/null
+++ b/src/test/java/de/ids_mannheim/korap/web/service/full/QuerySerializationServiceTest.java
@@ -0,0 +1,251 @@
+package de.ids_mannheim.korap.web.service.full;
+/**
+ * @author hanl, margaretha
+ * @lastUpdate 19/04/2017
+ *
+ */
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Iterator;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.sun.jersey.api.client.ClientResponse;
+
+import de.ids_mannheim.korap.config.Attributes;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.security.auth.BasicHttpAuth;
+import de.ids_mannheim.korap.utils.JsonUtils;
+import de.ids_mannheim.korap.web.service.FastJerseyTest;
+
+public class QuerySerializationServiceTest extends FastJerseyTest {
+
+    @Override
+    public void initMethod () throws KustvaktException {
+        helper().runBootInterfaces();
+    }
+
+
+    @BeforeClass
+    public static void configure () throws Exception {
+        FastJerseyTest.setPackages("de.ids_mannheim.korap.web.service.full",
+                "de.ids_mannheim.korap.web.filter",
+                "de.ids_mannheim.korap.web.utils");
+    }
+    
+    @Test
+    public void testQuerySerializationFilteredPublic () {
+        ClientResponse response = resource()
+                .path(getAPIVersion())
+                .path("corpus/WPD13/search")
+                .queryParam("q", "[orth=der]")
+                .queryParam("ql", "poliqarp")
+                .queryParam("context", "base/s:s")
+                .method("TRACE", ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertEquals("corpusSigle", node.at("/collection/key").asText());
+        assertEquals("WPD13", node.at("/collection/value").asText());
+    }
+    
+    
+
+    @Test
+    public void testQuerySerializationUnexistingResource () {
+        ClientResponse response = resource()
+                .path(getAPIVersion())
+                .path("corpus/ZUW19/search")
+                .queryParam("q", "[orth=der]")
+                .queryParam("ql", "poliqarp")
+                .queryParam("context", "base/s:s")
+                .method("TRACE", ClientResponse.class);
+        assertEquals(ClientResponse.Status.BAD_REQUEST.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertEquals(101, node.at("/errors/0/0").asInt());
+        assertEquals("[Cannot found public resources with ids: [ZUW19]]",
+                node.at("/errors/0/2").asText());
+    }
+    
+    @Test
+    public void testQuerySerializationWithNonPublicCorpus () {
+        ClientResponse response = resource()
+                .path(getAPIVersion())
+                .path("corpus/BRZ10/search")
+                .queryParam("q", "[orth=der]")
+                .queryParam("ql", "poliqarp")
+                .queryParam("context", "base/s:s")
+                .method("TRACE", ClientResponse.class);
+        assertEquals(ClientResponse.Status.BAD_REQUEST.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertEquals(101, node.at("/errors/0/0").asInt());
+        assertEquals("[Cannot found public resources with ids: [BRZ10]]",
+                node.at("/errors/0/2").asText());
+    }
+
+    @Test
+    public void testQuerySerializationWithAuthentication () {
+        ClientResponse response = resource()
+                .path(getAPIVersion())
+                .path("corpus/BRZ10/search")
+                .queryParam("q", "[orth=der]")
+                .queryParam("ql", "poliqarp")
+                .header(Attributes.AUTHORIZATION,
+                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
+                .method("TRACE", ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertEquals("koral:doc", node.at("/collection/@type").asText());
+        assertEquals("corpusSigle", node.at("/collection/key").asText());
+        assertEquals("BRZ10", node.at("/collection/value").asText());
+    }
+
+    @Test
+    public void testQuerySerializationWithNewCollection () {
+        // Add Virtual Collection
+        ClientResponse response = resource()
+                .path(getAPIVersion())
+                .path("virtualcollection")
+                .queryParam("filter", "false")
+                .queryParam("name", "Weimarer Werke")
+                .queryParam("description", "Goethe-Werke in Weimar (seit 1775)")
+                .header(Attributes.AUTHORIZATION,
+                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
+                .post(ClientResponse.class, "creationDate since 1775 & corpusSigle=GOE");
+        
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        
+        String ent = response.getEntity(String.class);
+        
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertTrue(node.isObject());
+        assertEquals("Weimarer Werke", node.path("name").asText());
+
+        // Get virtual collections
+        response = resource()
+                .path(getAPIVersion())
+                .path("collection")
+                .header(Attributes.AUTHORIZATION,
+                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        ent = response.getEntity(String.class);
+        node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+
+        Iterator<JsonNode> it = node.elements();
+        String id = null;
+        while (it.hasNext()) {
+            JsonNode next = (JsonNode) it.next();
+            if ("Weimarer Werke".equals(next.path("name").asText()))
+                id = next.path("id").asText();
+        }
+        assertNotNull(id);
+        assertFalse(id.isEmpty());
+
+        // query serialization service
+        response = resource()
+                .path(getAPIVersion())
+                .path("collection")
+                .path(id)
+                .path("search")
+                .queryParam("q", "[orth=der]")
+                .queryParam("ql", "poliqarp")
+                .queryParam("context", "base/s:s")
+                .header(Attributes.AUTHORIZATION,
+                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
+                .method("TRACE", ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        ent = response.getEntity(String.class);
+        node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+
+        assertEquals("koral:docGroup", node.at("/collection/@type").asText());
+        assertEquals("koral:doc", node.at("/collection/operands/0/@type")
+                .asText());
+        assertEquals("creationDate", node.at("/collection/operands/0/key")
+                .asText());
+        assertEquals("1775", node.at("/collection/operands/0/value")
+                .asText());
+        assertEquals("type:date", node.at("/collection/operands/0/type")
+                .asText());
+        assertEquals("match:geq", node.at("/collection/operands/0/match")
+                .asText());
+        
+        assertEquals("koral:doc", node.at("/collection/operands/1/@type")
+                .asText());
+        assertEquals("corpusSigle", node.at("/collection/operands/1/key")
+                .asText());
+        assertEquals("GOE", node.at("/collection/operands/1/value")
+                .asText());
+        assertEquals("match:eq", node.at("/collection/operands/1/match")
+                .asText());
+    }
+    
+    @Test
+    public void testQuerySerializationOfVirtualCollection () {
+        ClientResponse response = resource()
+                .path(getAPIVersion())
+                .path("collection/GOE-VC/search")
+                .queryParam("q", "[orth=der]")
+                .queryParam("ql", "poliqarp")
+                .queryParam("context", "base/s:s")
+                .method("TRACE", ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertEquals("koral:doc", node.at("/collection/operands/0/@type")
+                .asText());
+        assertEquals("corpusSigle", node.at("/collection/operands/0/key").asText());
+        assertEquals("GOE", node.at("/collection/operands/0/value").asText());
+        assertEquals("koral:doc", node.at("/collection/operands/1/@type")
+                .asText());
+        assertEquals("creationDate", node.at("/collection/operands/1/key").asText());
+        assertEquals("1810-01-01", node.at("/collection/operands/1/value").asText());
+
+    }
+    
+    @Test
+    public void testMetaQuerySerialization () {
+        ClientResponse response = resource()
+                .path(getAPIVersion())
+                .path("search")
+                .queryParam("context", "sentence")
+                .queryParam("count", "20")
+                .queryParam("page", "5")
+                .queryParam("q", "[pos=ADJA]")
+                .queryParam("ql", "poliqarp")
+                .method("TRACE", ClientResponse.class);
+        assertEquals(response.getStatus(),
+                ClientResponse.Status.OK.getStatusCode());
+        
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        
+        assertEquals("sentence", node.at("/meta/context").asText());
+        assertEquals(20, node.at("/meta/count").asInt());
+        assertEquals(5, node.at("/meta/startPage").asInt());
+    }
+
+
+}
diff --git a/src/test/java/de/ids_mannheim/korap/web/service/full/ResourceInfoServiceTest.java b/src/test/java/de/ids_mannheim/korap/web/service/full/ResourceInfoServiceTest.java
new file mode 100644
index 0000000..a7689ca
--- /dev/null
+++ b/src/test/java/de/ids_mannheim/korap/web/service/full/ResourceInfoServiceTest.java
@@ -0,0 +1,207 @@
+package de.ids_mannheim.korap.web.service.full;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.sun.jersey.api.client.ClientResponse;
+
+import de.ids_mannheim.korap.config.Attributes;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.security.auth.BasicHttpAuth;
+import de.ids_mannheim.korap.utils.JsonUtils;
+import de.ids_mannheim.korap.web.service.FastJerseyTest;
+/**
+ * @author hanl, margaretha
+ * @lastUpdate 19/04/2017
+ *
+ */
+public class ResourceInfoServiceTest extends FastJerseyTest {
+
+    @Override
+    public void initMethod () throws KustvaktException {
+        helper().runBootInterfaces();
+    }
+
+
+    @BeforeClass
+    public static void configure () throws Exception {
+        FastJerseyTest.setPackages("de.ids_mannheim.korap.web.service.full",
+                "de.ids_mannheim.korap.web.filter",
+                "de.ids_mannheim.korap.web.utils");
+    }
+
+
+    @Test
+    public void testGetPublicVirtualCollectionInfo () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("collection").get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertNotNull(node);
+        assertEquals(1, node.size());
+    }
+
+
+    @Test
+    public void testGetVirtualCollectionInfoWithAuthentication () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("collection")
+                .header(Attributes.AUTHORIZATION,
+                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+
+        JsonNode node = JsonUtils.readTree(response.getEntity(String.class));
+        assertNotNull(node);
+        assertTrue(node.isArray());
+        assertEquals(3, node.size());
+    }
+
+
+    @Test
+    public void testGetVirtualCollectionInfoById () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("collection").path("GOE-VC").get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertNotEquals(0, node.size());
+        assertEquals("Goethe Virtual Collection",
+                node.path("name").asText());
+        assertEquals("Goethe works from 1810",
+                node.path("description").asText());
+    }
+    
+    @Test
+    public void testGetVirtualCollectionInfoByIdUnauthorized () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("collection").path("WPD15-VC").get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.BAD_REQUEST.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertNotEquals(0, node.size());
+        assertEquals(101, node.at("/errors/0/0").asInt());
+        assertEquals("[Cannot found public resources with ids: [WPD15-VC]]",
+                node.at("/errors/0/2").asText());
+    }
+    
+    @Test
+    public void testGetPublicCorporaInfo () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("corpus").get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertTrue(node.isArray());
+        assertEquals(2, node.size());
+    }
+
+
+    @Test
+    public void testGetCorpusInfoById () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("corpus").path("WPD13").get(ClientResponse.class);
+        
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+//        System.out.println(ent);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertTrue(node.isObject());
+        assertEquals("WPD13", node.path("id").asText());
+    }
+
+
+    @Test
+    public void testGetCorpusInfoById2 () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("corpus").path("GOE").get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertTrue(node.isObject());
+        assertEquals("GOE", node.path("id").asText());
+    }
+
+
+    @Test
+    public void testGetPublicFoundriesInfo () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("foundry").get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertTrue(node.isArray());
+        assertEquals(10, node.size());
+    }
+
+
+    @Test
+    public void testGetFoundryInfoById () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("foundry").path("tt").get(ClientResponse.class);
+        String ent = response.getEntity(String.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertNotEquals(0, node.size());
+    }
+
+
+    @Test
+    public void testGetUnexistingCorpusInfo () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("corpus").path("ZUW19").get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.BAD_REQUEST.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertNotEquals(0, node.size());
+        assertEquals(101, node.at("/errors/0/0").asInt());
+        assertEquals("[Cannot found public resources with ids: [ZUW19]]",
+                node.at("/errors/0/2").asText());
+    }
+
+
+    // EM: queries for an unauthorized corpus get the same responses / treatment as 
+    // asking for an unexisting corpus info. Does it need a specific exception instead?
+    @Test
+    public void testGetUnauthorizedCorpusInfo () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("corpus").path("BRZ10").get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.BAD_REQUEST.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertNotEquals(0, node.size());
+        assertEquals(101, node.at("/errors/0/0").asInt());
+        assertEquals("[Cannot found public resources with ids: [BRZ10]]",
+                node.at("/errors/0/2").asText());
+    }
+
+
+}
diff --git a/src/test/java/de/ids_mannheim/korap/web/service/full/ResourceServiceTest.java b/src/test/java/de/ids_mannheim/korap/web/service/full/ResourceServiceTest.java
index c541e7a..4b4840d 100644
--- a/src/test/java/de/ids_mannheim/korap/web/service/full/ResourceServiceTest.java
+++ b/src/test/java/de/ids_mannheim/korap/web/service/full/ResourceServiceTest.java
@@ -1,32 +1,37 @@
 package de.ids_mannheim.korap.web.service.full;
 
-import com.fasterxml.jackson.databind.JsonNode;
-import com.sun.jersey.api.client.ClientResponse;
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.query.serialize.QuerySerializer;
-import de.ids_mannheim.korap.resources.Corpus;
-import de.ids_mannheim.korap.resources.KustvaktResource;
-import de.ids_mannheim.korap.security.ac.ResourceHandler;
-import de.ids_mannheim.korap.security.auth.BasicHttpAuth;
-import de.ids_mannheim.korap.config.Attributes;
-import de.ids_mannheim.korap.user.User;
-import de.ids_mannheim.korap.utils.JsonUtils;
-import de.ids_mannheim.korap.web.service.FastJerseyTest;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.apache.http.HttpStatus;
+import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Ignore;
 import org.junit.Test;
 
-import java.util.Iterator;
-import java.util.Set;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.sun.jersey.api.client.ClientResponse;
 
-import static org.junit.Assert.*;
+import de.ids_mannheim.korap.config.Attributes;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.handlers.ResourceDao;
+import de.ids_mannheim.korap.resources.KustvaktResource;
+import de.ids_mannheim.korap.security.auth.BasicHttpAuth;
+import de.ids_mannheim.korap.user.User;
+import de.ids_mannheim.korap.utils.JsonUtils;
+import de.ids_mannheim.korap.web.service.FastJerseyTest;
 
 /**
  * @author hanl
  * @date 14/01/2016
  */
 public class ResourceServiceTest extends FastJerseyTest {
-
+    
     @BeforeClass
     public static void configure () throws Exception {
         FastJerseyTest.setPackages("de.ids_mannheim.korap.web.service.full",
@@ -34,177 +39,6 @@
                 "de.ids_mannheim.korap.web.utils");
     }
 
-
-    @Test
-    public void testSearchSimpleAuthorized () {
-        ClientResponse response = resource()
-                .path(getAPIVersion())
-                .path("search")
-                .queryParam("q", "[orth=die]")
-                .queryParam("ql", "poliqarp")
-                .header(Attributes.AUTHORIZATION,
-                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
-                .get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-
-        JsonNode node = JsonUtils.readTree(response.getEntity(String.class));
-        assertNotNull(node);
-        assertNotEquals(0, node.path("matches").size());
-    }
-
-
-    @Test
-    public void testSearchSimpleWithCQAuthorized () {
-        ClientResponse response = resource()
-                .path(getAPIVersion())
-                .path("search")
-                .queryParam("q", "[orth=das]")
-                .queryParam("ql", "poliqarp")
-                .queryParam("cq", "textClass=politik & corpusSigle=WPD")
-                .header(Attributes.AUTHORIZATION,
-                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
-                .get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-
-        JsonNode node = JsonUtils.readTree(response.getEntity(String.class));
-        assertNotNull(node);
-        assertEquals(2, node.at("/collection/operands").size());
-        assertEquals("textClass", node.at("/collection/operands/0/key")
-                .asText());
-        assertEquals("corpusSigle", node.at("/collection/operands/1/key")
-                .asText());
-        assertEquals("koral:token", node.at("/query/@type").asText());
-    }
-
-
-    @Test
-    public void testSearchSimpleDemo () {
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("search").queryParam("q", "[orth=der]")
-                .queryParam("ql", "poliqarp").get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String ent = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertNotEquals(0, node.path("matches").size());
-    }
-
-
-    @Test
-    public void testSearchSentenceMeta () {
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("search").queryParam("q", "[orth=der]")
-                .queryParam("ql", "poliqarp").queryParam("context", "sentence")
-                .get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String ent = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertNotEquals(0, node.path("matches").size());
-        assertEquals("base/s:s", node.at("/meta/context").asText());
-        assertNotEquals("${project.version}", "/meta/version");
-    }
-
-
-    @Test
-    public void testSearchSimpleCQL () {
-        QuerySerializer s = new QuerySerializer();
-        s.setQuery("(der) or (das)", "CQL");
-
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("search").post(ClientResponse.class, s.toJSON());
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String ent = response.getEntity(String.class);
-
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertNotEquals(0, node.path("matches").size());
-    }
-
-
-    @Test
-    public void testSearchRawQuery () {
-        QuerySerializer s = new QuerySerializer();
-        s.setQuery("[orth=der]", "poliqarp");
-        //        s.setCollection("corpusSigle=WPD");
-
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("search").post(ClientResponse.class, s.toJSON());
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String ent = response.getEntity(String.class);
-
-
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertNotEquals(0, node.path("matches").size());
-    }
-
-
-    @Test
-    public void testCollectionsGetPublic () {
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("collection").get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-
-        JsonNode node = JsonUtils.readTree(response.getEntity(String.class));
-        assertNotNull(node);
-        assertNotEquals(0, node.size());
-    }
-
-
-    @Test
-    public void testCollectionsGet () {
-        ClientResponse response = resource()
-                .path(getAPIVersion())
-                .path("collection")
-                .header(Attributes.AUTHORIZATION,
-                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
-                .get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-
-        JsonNode node = JsonUtils.readTree(response.getEntity(String.class));
-        assertNotNull(node);
-        assertTrue(node.isArray());
-        assertNotEquals(0, node.size());
-    }
-
-
-    @Test
-    public void testCorporaGet () {
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("corpus").get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String ent = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertTrue(node.isArray());
-        assertNotEquals(0, node.size());
-    }
-
-
-    @Test
-    public void testFoundriesGet () {
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("foundry").get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String ent = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertTrue(node.isArray());
-        assertNotEquals(0, node.size());
-    }
-
-
     // create a simple test collection for user kustvakt, otherwise test fails
     @Test
     @Ignore
@@ -242,236 +76,106 @@
         assertTrue(docs < 15);
     }
 
-
-    // todo:
+    // EM: The test covers multiple operations because it deals with 
+    // the same resource and needs an order to operate (store followed by
+    // update followed by delete).
     @Test
-    @Ignore
-    public void testCollecionGet () {
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("collection").path("id").get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String ent = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertNotEquals(0, node.size());
-    }
-
-
-    @Test
-    public void testCorpusGet () {
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("corpus").path("WPD").get(ClientResponse.class);
-        String ent = response.getEntity(String.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertTrue(node.isObject());
-        assertEquals("WPD", node.path("id").asText());
-    }
-
-
-    @Test
-    public void testCorpusGet2 () {
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("corpus").path("GOE").get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String ent = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertTrue(node.isObject());
-        assertEquals("GOE", node.path("id").asText());
-    }
-
-
-    @Test
-    @Ignore
-    public void testCorpusGetUnauthorized () {
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("corpus").path("BRZ20").get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.UNAUTHORIZED.getStatusCode(),
-                response.getStatus());
-        String ent = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertTrue(node.isObject());
-        assertNotNull(node);
-    }
-
-
-    @Test
-    public void testFoundryGet () {
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("foundry").path("tt").get(ClientResponse.class);
-        String ent = response.getEntity(String.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertNotEquals(0, node.size());
-    }
-
-
-    @Test
-    public void testResourceStore () {
-
-    }
-
-
-    @Test
-    public void testResourceDelete () {
-
-    }
-
-
-    @Test
-    public void testSerializationQueryWithCorpusThroughFilteredPublic () {
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("corpus/WPD/search").queryParam("q", "[orth=der]")
-                .queryParam("ql", "poliqarp").queryParam("context", "base/s:s")
-                .method("TRACE", ClientResponse.class);
-        String ent = response.getEntity(String.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        //String ent = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertEquals("corpusSigle", node.at("/collection/key").asText());
-        assertEquals("WPD", node.at("/collection/value").asText());
-    }
-
-
-    @Test
-    public void testSerializationQueryWithCorpus () {
+    public void testVirtualCollectionStoreUpdateDelete() throws KustvaktException, 
+        JsonProcessingException, IOException {
+    	// resource store service
         ClientResponse response = resource()
                 .path(getAPIVersion())
-                .path("corpus/WPD/search")
-                .queryParam("q", "[orth=der]")
-                .queryParam("ql", "poliqarp")
+                .path("virtualcollection")
+                .queryParam("filter", "false")
+                .queryParam("name", "Goethe")
+                .queryParam("description", "Goethe corpus")
                 .header(Attributes.AUTHORIZATION,
                         BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
-                .method("TRACE", ClientResponse.class);
+                .post(ClientResponse.class);
+        
         assertEquals(ClientResponse.Status.OK.getStatusCode(),
                 response.getStatus());
+        
         String ent = response.getEntity(String.class);
         JsonNode node = JsonUtils.readTree(ent);
         assertNotNull(node);
-        assertEquals("koral:doc", node.at("/collection/@type").asText());
-        assertEquals("corpusSigle", node.at("/collection/key").asText());
-    }
+        assertTrue(node.isObject());
+        assertEquals("Goethe", node.path("name").asText());
+        assertEquals("Goethe corpus", node.path("description").asText());
 
+        String id = node.path("id").asText();
+        		
+        // check if the resource is in the db
+        ResourceDao<?> dao = new ResourceDao<>(helper().getContext()
+                .getPersistenceClient());
+        assertEquals("sqlite", helper().getContext().getPersistenceClient()
+                .getDatabase());
 
-    @Test
-    public void testSerializationQueryWithCollection () {
-        ClientResponse response = resource()
-                .path(getAPIVersion())
-                .path("collection")
-                .header(Attributes.AUTHORIZATION,
-                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
-                .get(ClientResponse.class);
-        assertEquals(ClientResponse.Status.OK.getStatusCode(),
-                response.getStatus());
-        String ent = response.getEntity(String.class);
-        JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-
-        Iterator it = node.elements();
-        String id = null;
-        while (it.hasNext()) {
-            JsonNode next = (JsonNode) it.next();
-            if ("Weimarer Werke".equals(next.path("name").asText()))
-                id = next.path("id").asText();
-        }
-        assertNotNull(id);
-        assertFalse(id.isEmpty());
-
+        assertNotEquals(0, dao.size());
+        KustvaktResource res = dao.findbyId(id,
+                User.UserFactory.getDemoUser());
+        assertNotNull(res);
+        Assert.assertEquals("Goethe",res.getName().toString());
+        
+        // no update resource service
         response = resource()
                 .path(getAPIVersion())
-                .path("collection")
+                .path("virtualcollection")
                 .path(id)
-                .path("search")
-                .queryParam("q", "[orth=der]")
-                .queryParam("ql", "poliqarp")
-                .queryParam("context", "base/s:s")
+                .queryParam("name", "Goethe")
                 .header(Attributes.AUTHORIZATION,
                         BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
-                .method("TRACE", ClientResponse.class);
+                .post(ClientResponse.class);
+        
+        assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatus());
+        
+        node = JsonUtils.readTree(response.getEntity(String.class));
+        assertEquals(
+                "[No change has found.]",
+                node.get("errors").get(0).get(2).asText());
+        
+        // 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);
+        
         assertEquals(ClientResponse.Status.OK.getStatusCode(),
                 response.getStatus());
-        ent = response.getEntity(String.class);
-        node = JsonUtils.readTree(ent);
-        assertNotNull(node);
+        
+        res = dao.findbyId(id,
+                User.UserFactory.getDemoUser());
+        assertNotNull(res);
+        Assert.assertEquals("Goethe collection",res.getName().toString());
+        
+        
+        // delete resource service
+    	response = resource()
+                .path(getAPIVersion())
+                .path("virtualcollection")
+                .path(id)
+                .header(Attributes.AUTHORIZATION,
+                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
+                .delete(ClientResponse.class);
+        
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        
+        // check if the resource is *not* in the db anymore
+        dao = new ResourceDao<>(helper().getContext()
+                .getPersistenceClient());
+        assertEquals("sqlite", helper().getContext().getPersistenceClient()
+                .getDatabase());
 
-        assertEquals("koral:docGroup", node.at("/collection/@type").asText());
-        assertEquals("koral:doc", node.at("/collection/operands/0/@type")
-                .asText());
-        assertEquals("koral:doc", node.at("/collection/operands/1/@type")
-                .asText());
-        assertEquals("creationDate", node.at("/collection/operands/0/key")
-                .asText());
-        assertEquals("corpusSigle", node.at("/collection/operands/1/key")
-                .asText());
-
+        res = dao.findbyId(id,
+                User.UserFactory.getDemoUser());
+        assertEquals(null,res);
     }
 
-
-    @Test
-    public void testSearchQueryPublicCorpora () {
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("search").queryParam("q", "[orth=der]")
-                .queryParam("ql", "poliqarp").get(ClientResponse.class);
-        assertEquals(response.getStatus(),
-                ClientResponse.Status.OK.getStatusCode());
-        String ent = response.getEntity(String.class);
-		JsonNode node = JsonUtils.readTree(ent);
-        assertNotNull(node);
-        assertEquals("koral:docGroup", node.at("/collection/@type").asText());
-        assertEquals("operation:or", node.at("/collection/operation").asText());
-        assertNotEquals(0, node.at("/collection/operands").size());
-    }
-
-
-    // use trace for this
-    @Test
-    @Ignore
-    public void testSerializationMeta () {
-        ClientResponse response = resource().path(getAPIVersion())
-                .path("search").queryParam("context", "sentence")
-                .queryParam("q", "[pos=ADJA]").queryParam("ql", "poliqarp")
-
-                .method("TRACE", ClientResponse.class);
-        assertEquals(response.getStatus(),
-                ClientResponse.Status.OK.getStatusCode());
-    }
-
-
-    @Test
-    public void testMatchInfoGet () {
-    }
-
-
-    @Test
-    public void testMatchInfoSave () {
-
-    }
-
-
-    @Test
-    public void testMatchInfoDelete () {
-
-    }
-
-
-    @Test
-    public void testGetMatches () {
-
-    }
-
-
     @Override
     public void initMethod () throws KustvaktException {
         helper().runBootInterfaces();
diff --git a/src/test/java/de/ids_mannheim/korap/web/service/full/SearchServiceTest.java b/src/test/java/de/ids_mannheim/korap/web/service/full/SearchServiceTest.java
new file mode 100644
index 0000000..bad37ca
--- /dev/null
+++ b/src/test/java/de/ids_mannheim/korap/web/service/full/SearchServiceTest.java
@@ -0,0 +1,298 @@
+package de.ids_mannheim.korap.web.service.full;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Iterator;
+import java.util.Set;
+
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.sun.jersey.api.client.ClientResponse;
+
+import de.ids_mannheim.korap.config.Attributes;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.query.serialize.QuerySerializer;
+import de.ids_mannheim.korap.resources.Corpus;
+import de.ids_mannheim.korap.security.ac.ResourceFinder;
+import de.ids_mannheim.korap.security.auth.BasicHttpAuth;
+import de.ids_mannheim.korap.utils.JsonUtils;
+import de.ids_mannheim.korap.web.service.FastJerseyTest;
+
+/**
+ * @author hanl, margaretha
+ * @lastUpdate 21/04/2017
+ *
+ */
+public class SearchServiceTest extends FastJerseyTest {
+
+    @Override
+    public void initMethod () throws KustvaktException {
+        helper().runBootInterfaces();
+    }
+
+
+    @BeforeClass
+    public static void configure () throws Exception {
+        FastJerseyTest.setPackages("de.ids_mannheim.korap.web.service.full",
+                "de.ids_mannheim.korap.web.filter",
+                "de.ids_mannheim.korap.web.utils");
+    }
+
+    @Test
+    public void testSearchQueryPublicCorpora () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("search").queryParam("q", "[orth=der]")
+                .queryParam("ql", "poliqarp").get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertEquals("koral:docGroup", node.at("/collection/@type").asText());
+        assertEquals("operation:or", node.at("/collection/operation").asText());
+        assertNotEquals(0, node.at("/collection/operands").size());
+        assertEquals("corpusSigle([GOE, WPD13])",
+                node.at("/collection/rewrites/0/scope").asText());
+        assertEquals(6218, node.at("/meta/totalResults").asInt());
+    }
+
+    @Test
+    public void testSearchQueryAuthorized () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("search").queryParam("q", "[orth=die]")
+                .queryParam("ql", "poliqarp")
+                .header(Attributes.AUTHORIZATION,
+                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertNotNull(node);
+        assertNotEquals(0, node.path("matches").size());
+        assertEquals("corpusSigle([GOE, WPD13, WPD15, BRZ10])",
+                node.at("/collection/rewrites/0/scope").asText());
+        assertEquals(7665, node.at("/meta/totalResults").asInt());
+    }
+
+
+    @Test
+    public void testSearchQueryWithCollectionQueryAuthorized () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("search").queryParam("q", "[orth=das]")
+                .queryParam("ql", "poliqarp")
+                .queryParam("cq", "textClass=politik & corpusSigle=BRZ10")
+                .header(Attributes.AUTHORIZATION,
+                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+
+        JsonNode node = JsonUtils.readTree(response.getEntity(String.class));
+        assertNotNull(node);
+        assertEquals(2, node.at("/collection/operands").size());
+        assertEquals("textClass",
+                node.at("/collection/operands/0/key").asText());
+        assertEquals("corpusSigle",
+                node.at("/collection/operands/1/key").asText());
+        assertEquals("koral:token", node.at("/query/@type").asText());
+    }
+
+    @Test
+    public void testSearchForPublicCorpusWithStringId () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("corpus").path("GOE").path("search")
+                .queryParam("q", "blau").queryParam("ql", "poliqarp")
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertEquals("koral:doc", node.at("/collection/@type").asText());
+        assertEquals("corpusSigle", node.at("/collection/key").asText());
+        assertEquals("GOE", node.at("/collection/value").asText());
+        assertNotEquals(0, node.path("matches").size());
+        assertEquals(32, node.at("/meta/totalResults").asInt());
+    }
+    
+    @Test
+    public void testSearchForVirtualCollectionWithStringId () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("collection").path("GOE-VC").path("search")
+                .queryParam("q", "blau").queryParam("ql", "poliqarp")
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        System.out.println(ent);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertEquals("koral:docGroup", node.at("/collection/@type").asText());
+        assertEquals("operation:and", node.at("/collection/operation").asText());
+        assertNotEquals(0, node.at("/collection/operands").size());
+        assertEquals("corpusSigle",
+                node.at("/collection/operands/0/key").asText());
+        assertEquals("GOE",
+                node.at("/collection/operands/0/value").asText());
+        assertEquals("creationDate",
+                node.at("/collection/operands/1/key").asText());
+        assertEquals("1810-01-01",
+                node.at("/collection/operands/1/value").asText());
+        assertEquals(1, node.at("/meta/totalResults").asInt());
+    }
+
+    
+    @Test
+    public void testSearchForPublicCorpusWithIntegerId () throws KustvaktException {
+        Set<Corpus> publicCorpora = ResourceFinder.searchPublic(Corpus.class);
+        Iterator<Corpus> i = publicCorpora.iterator();
+        String id = null;
+        while (i.hasNext()){
+            Corpus c = i.next();
+            if (c.getName().equals("Goethe")){
+                id =c.getId().toString();
+            }
+        }
+            
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("corpus").path(id).path("search")
+                .queryParam("q", "blau").queryParam("ql", "poliqarp")
+                .get(ClientResponse.class);
+        
+        String ent = response.getEntity(String.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertEquals("koral:doc", node.at("/collection/@type").asText());
+        assertEquals("corpusSigle", node.at("/collection/key").asText());
+        assertEquals("GOE", node.at("/collection/value").asText());
+        assertNotEquals(0, node.path("matches").size());
+    }
+    
+    @Test
+    public void testSearchForCorpusWithStringIdUnauthorized () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("corpus").path("WPD15").path("search")
+                .queryParam("q", "blau").queryParam("ql", "poliqarp")
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.BAD_REQUEST.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode error = JsonUtils.readTree(ent).get("errors").get(0);
+        assertEquals(101, error.get(0).asInt());
+        assertEquals("[Cannot found public resources with ids: [WPD15]]",
+                error.get(2).asText());
+    }
+    
+    @Test
+    public void testSearchForOwnersCorpusWithStringId () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("corpus").path("WPD15").path("search")
+                .queryParam("q", "[orth=das]")
+                .queryParam("ql", "poliqarp")
+                .header(Attributes.AUTHORIZATION,
+                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertNotNull(node);
+        assertEquals("koral:doc", node.at("/collection/@type").asText());
+        assertEquals("corpusSigle", node.at("/collection/key").asText());
+        assertEquals("WPD15", node.at("/collection/value").asText());
+        assertNotEquals(0, node.path("matches").size());
+    }
+    
+    @Test
+    public void testSearchForOwnersCorpusWithIntegerId () throws KustvaktException {
+        Set<Corpus> publicCorpora = ResourceFinder.searchPublic(Corpus.class);
+        Iterator<Corpus> i = publicCorpora.iterator();
+        String id = null;
+        while (i.hasNext()){
+            Corpus c = i.next();
+            if (c.getPersistentID().equals("WPD15")){
+                id =c.getId().toString();
+            }
+        }
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("corpus").path("5").path("search")
+                .queryParam("q", "[orth=das]")
+                .queryParam("ql", "poliqarp")
+                .header(Attributes.AUTHORIZATION,
+                        BasicHttpAuth.encode("kustvakt", "kustvakt2015"))
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertNotNull(node);
+        assertEquals("koral:doc", node.at("/collection/@type").asText());
+        assertEquals("corpusSigle", node.at("/collection/key").asText());
+        assertEquals("WPD15", node.at("/collection/value").asText());
+        assertNotEquals(0, node.path("matches").size());
+    }
+
+    @Test
+    public void testSearchSentenceMeta () {
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("search").queryParam("q", "[orth=der]")
+                .queryParam("ql", "poliqarp").queryParam("context", "sentence")
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertNotEquals(0, node.path("matches").size());
+        assertEquals("base/s:s", node.at("/meta/context").asText());
+        assertNotEquals("${project.version}", "/meta/version");
+    }
+
+
+    @Test
+    public void testSearchSimpleCQL () {
+        QuerySerializer s = new QuerySerializer();
+        s.setQuery("(der) or (das)", "CQL");
+
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("search").post(ClientResponse.class, s.toJSON());
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertNotEquals(0, node.path("matches").size());
+        //        assertEquals(17027, node.at("/meta/totalResults").asInt());
+    }
+
+
+    @Test
+    public void testSearchRawQuery () {
+        QuerySerializer s = new QuerySerializer();
+        s.setQuery("[orth=der]", "poliqarp");
+        s.setCollection("corpusSigle=GOE");
+
+        ClientResponse response = resource().path(getAPIVersion())
+                .path("search").post(ClientResponse.class, s.toJSON());
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String ent = response.getEntity(String.class);
+
+
+        JsonNode node = JsonUtils.readTree(ent);
+        assertNotNull(node);
+        assertNotEquals(0, node.path("matches").size());
+        //        assertEquals(10993, node.at("/meta/totalResults").asInt());
+    }
+
+}
diff --git a/src/test/resources/default-config.xml b/src/test/resources/default-config.xml
deleted file mode 100644
index 3ad0aeb..0000000
--- a/src/test/resources/default-config.xml
+++ /dev/null
@@ -1,246 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xmlns:p="http://www.springframework.org/schema/p"
-       xmlns:util="http://www.springframework.org/schema/util"
-       xmlns:aop="http://www.springframework.org/schema/aop"
-       xmlns:tx="http://www.springframework.org/schema/tx"
-       xmlns="http://www.springframework.org/schema/beans"
-       xmlns:cache="http://www.springframework.org/schema/cache"
-       xsi:schemaLocation="http://www.springframework.org/schema/beans
-                            http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
-                            http://www.springframework.org/schema/tx
-                            http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
-
-
-                            http://www.springframework.org/schema/aop
-                            http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
-                            http://www.springframework.org/schema/cache
-                            http://www.springframework.org/schema/cache/spring-cache-4.0.xsd
-
-
-                            http://www.springframework.org/schema/util
-                            http://www.springframework.org/schema/util/spring-util-4.0.xsd">
-
-    <bean id="props"
-          class="org.springframework.beans.factory.config.PropertiesFactoryBean">
-        <property name="ignoreResourceNotFound" value="true"/>
-        <property name="locations">
-            <array>
-                <value>classpath:kustvakt.conf</value>
-                <value>file:./kustvakt.conf</value>
-            </array>
-        </property>
-    </bean>
-
-    <bean id="jdbc_props"
-          class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
-        <property name="ignoreResourceNotFound" value="true"/>
-        <property name="locations">
-            <array>
-                <value>classpath:jdbc.properties</value>
-                <value>file:./jdbc_tests.properties</value>
-            </array>
-        </property>
-    </bean>
-
-    <bean id='cacheManager'
-          class='org.springframework.cache.ehcache.EhCacheCacheManager'
-          p:cacheManager-ref='ehcache'/>
-
-    <bean id='ehcache'
-          class='org.springframework.cache.ehcache.EhCacheManagerFactoryBean'
-          p:configLocation='classpath:ehcache.xml'
-          p:shared='true'/>
-
-    <!-- props are injected from default-config.xml -->
-    <bean id="kustvakt_config"
-          class="de.ids_mannheim.korap.config.KustvaktConfiguration">
-        <property name="properties" ref="props"/>
-    </bean>
-
-    <!--class="org.apache.commons.dbcp2.BasicDataSource"-->
-    <!-- org.springframework.jdbc.datasource.SingleConnectionDataSource -->
-    <!-- org.springframework.jdbc.datasource.DriverManagerDataSource -->
-    <bean id="dataSource"
-          class="org.springframework.jdbc.datasource.SingleConnectionDataSource"
-          lazy-init="false">
-        <property name="driverClassName" value="org.sqlite.JDBC"/>
-        <property name="url" value="jdbc:sqlite::memory:"/>
-        <!--<property name="initialSize" value="1" />-->
-        <!--<property name="maxTotal" value="1" />-->
-        <!--<property name="maxIdle" value="1" />-->
-        <!--<property name="username" value="${jdbc.username}"/>-->
-        <!--<property name="password" value="${jdbc.password}"/>-->
-        <!-- relevant for single connection datasource and sqlite -->
-        <property name="suppressClose">
-            <value>true</value>
-        </property>
-        <!--<property name="initialSize" value="2"/>-->
-        <!--<property name="maxIdle" value="2"/>-->
-        <!--<property name="poolPreparedStatements" value="true"/>-->
-    </bean>
-
-    <!-- to configure database for sqlite, mysql, etc. migrations -->
-    <bean id="flyway" class="org.flywaydb.core.Flyway" init-method="migrate">
-        <property name="baselineOnMigrate" value="false"/>
-        <property name="locations"
-                  value="classpath:db.sqlite"/>
-        <property name="dataSource" ref="dataSource"/>
-    </bean>
-
-    <bean id="kustvakt_db"
-          class="de.ids_mannheim.korap.handlers.JDBCClient">
-        <constructor-arg index="0" ref="dataSource"/>
-        <property name="database" value="jdbc:sqlite::memory:"/>
-    </bean>
-
-    <bean id="kustvakt_userdetails"
-          class="de.ids_mannheim.korap.handlers.UserDetailsDao">
-        <constructor-arg ref="kustvakt_db"/>
-    </bean>
-
-    <bean id="kustvakt_usersettings"
-          class="de.ids_mannheim.korap.handlers.UserSettingsDao">
-        <constructor-arg ref="kustvakt_db"/>
-    </bean>
-
-    <bean id="kustvakt_auditing"
-          class="de.ids_mannheim.korap.handlers.JDBCAuditing">
-        <constructor-arg ref="kustvakt_db"/>
-    </bean>
-
-    <bean id="kustvakt_userdb"
-          class="de.ids_mannheim.korap.handlers.EntityDao">
-        <constructor-arg ref="kustvakt_db"/>
-    </bean>
-
-    <bean id="resource_provider"
-          class="de.ids_mannheim.korap.handlers.ResourceDao">
-        <constructor-arg ref="kustvakt_db"/>
-    </bean>
-
-    <bean id="document_provider"
-          class="de.ids_mannheim.korap.handlers.DocumentDao">
-        <constructor-arg ref="kustvakt_db"/>
-    </bean>
-
-    <bean id="kustvakt_policies"
-          class="de.ids_mannheim.korap.security.ac.PolicyDao">
-        <constructor-arg ref="kustvakt_db"/>
-    </bean>
-
-    <bean name="kustvakt_encryption"
-          class="de.ids_mannheim.korap.interfaces.defaults.KustvaktEncryption">
-        <constructor-arg ref="kustvakt_config"/>
-    </bean>
-
-    <!-- authentication providers to use -->
-    <bean id="api_auth"
-          class="de.ids_mannheim.korap.security.auth.APIAuthentication">
-        <constructor-arg
-                type="de.ids_mannheim.korap.config.KustvaktConfiguration"
-                ref="kustvakt_config"/>
-    </bean>
-
-    <bean id="openid_auth"
-          class="de.ids_mannheim.korap.security.auth.OpenIDconnectAuthentication">
-        <constructor-arg
-                type="de.ids_mannheim.korap.config.KustvaktConfiguration"
-                ref="kustvakt_config"/>
-        <constructor-arg
-                type="de.ids_mannheim.korap.interfaces.db.PersistenceClient"
-                ref="kustvakt_db"/>
-    </bean>
-
-    <bean id="basic_auth"
-          class="de.ids_mannheim.korap.security.auth.BasicHttpAuth"/>
-
-
-    <bean id="session_auth"
-          class="de.ids_mannheim.korap.security.auth.SessionAuthentication">
-        <constructor-arg
-                type="de.ids_mannheim.korap.config.KustvaktConfiguration"
-                ref="kustvakt_config"/>
-        <constructor-arg
-                type="de.ids_mannheim.korap.interfaces.EncryptionIface"
-                ref="kustvakt_encryption"/>
-    </bean>
-
-    <util:list id="kustvakt_authproviders"
-               value-type="de.ids_mannheim.korap.interfaces.AuthenticationIface">
-        <ref bean="basic_auth"/>
-        <ref bean="session_auth"/>
-        <ref bean="api_auth"/>
-        <ref bean="openid_auth"/>
-    </util:list>
-
-    <bean id="userdata_details"
-          class="de.ids_mannheim.korap.handlers.UserDetailsDao">
-        <constructor-arg
-                type="de.ids_mannheim.korap.interfaces.db.PersistenceClient"
-                ref="kustvakt_db"/>
-    </bean>
-    <bean id="userdata_settings"
-          class="de.ids_mannheim.korap.handlers.UserSettingsDao">
-        <constructor-arg
-                type="de.ids_mannheim.korap.interfaces.db.PersistenceClient"
-                ref="kustvakt_db"/>
-    </bean>
-
-    <util:list id="kustvakt_userdata"
-               value-type="de.ids_mannheim.korap.interfaces.db.UserdataDbIface">
-        <ref bean="userdata_details"/>
-        <ref bean="userdata_settings"/>
-    </util:list>
-
-    <util:list id="kustvakt_resources"
-               value-type="de.ids_mannheim.korap.interfaces.db.ResourceOperationIface">
-        <ref bean="document_provider"/>
-        <ref bean="resource_provider"/>
-    </util:list>
-
-
-    <!-- specify type for constructor argument -->
-    <bean id="kustvakt_authenticationmanager"
-          class="de.ids_mannheim.korap.security.auth.KustvaktAuthenticationManager">
-        <constructor-arg
-                type="de.ids_mannheim.korap.interfaces.db.EntityHandlerIface"
-                ref="kustvakt_userdb"/>
-        <constructor-arg type="de.ids_mannheim.korap.interfaces.EncryptionIface"
-                         ref="kustvakt_encryption"/>
-        <constructor-arg ref="kustvakt_config"/>
-        <constructor-arg
-                type="de.ids_mannheim.korap.interfaces.db.AuditingIface"
-                ref="kustvakt_auditing"/>
-        <constructor-arg ref="kustvakt_userdata"/>
-        <!-- inject authentication providers to use -->
-        <property name="providers" ref="kustvakt_authproviders"/>
-    </bean>
-
-    <!-- todo: if db interfaces not loaded via spring, does transaction even work then? -->
-    <!-- the transactional advice (i.e. what 'happens'; see the <aop:advisor/> bean below) -->
-    <tx:advice id="txAdvice" transaction-manager="txManager">
-        <!-- the transactional semantics... -->
-        <tx:attributes>
-            <!-- all methods starting with 'get' are read-only -->
-            <tx:method name="get*" read-only="true"
-                       rollback-for="KorAPException"/>
-            <!-- other methods use the default transaction settings (see below) -->
-            <tx:method name="*" rollback-for="KorAPException"/>
-        </tx:attributes>
-    </tx:advice>
-
-    <!-- ensure that the above transactional advice runs for any execution
-        of an operation defined by the service interface -->
-    <aop:config>
-        <aop:pointcut id="service"
-                      expression="execution(* de.ids_mannheim.korap.interfaces.db.*.*(..))"/>
-        <aop:advisor advice-ref="txAdvice" pointcut-ref="service"/>
-    </aop:config>
-
-    <!-- similarly, don't forget the PlatformTransactionManager -->
-    <bean id="txManager"
-          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
-        <property name="dataSource" ref="dataSource"/>
-    </bean>
-</beans>
\ No newline at end of file
diff --git a/src/test/resources/index-kustvakt-example/_0.cfe b/src/test/resources/index-kustvakt-example/_0.cfe
deleted file mode 100644
index 0ab94f8..0000000
--- a/src/test/resources/index-kustvakt-example/_0.cfe
+++ /dev/null
Binary files differ
diff --git a/src/test/resources/index-kustvakt-example/_0.cfs b/src/test/resources/index-kustvakt-example/_0.cfs
deleted file mode 100644
index 0577152..0000000
--- a/src/test/resources/index-kustvakt-example/_0.cfs
+++ /dev/null
Binary files differ
diff --git a/src/test/resources/index-kustvakt-example/_0.si b/src/test/resources/index-kustvakt-example/_0.si
deleted file mode 100644
index 50e865c..0000000
--- a/src/test/resources/index-kustvakt-example/_0.si
+++ /dev/null
Binary files differ
diff --git a/src/test/resources/index-kustvakt-example/segments_1 b/src/test/resources/index-kustvakt-example/segments_1
deleted file mode 100644
index b6b0a45..0000000
--- a/src/test/resources/index-kustvakt-example/segments_1
+++ /dev/null
Binary files differ
diff --git a/src/test/resources/policy-test.conf b/src/test/resources/policy-test.conf
new file mode 100644
index 0000000..35b0fd9
--- /dev/null
+++ b/src/test/resources/policy-test.conf
@@ -0,0 +1,58 @@
+# type	id	name	description	condition	permissions	collectionQuery
+
+virtualcollection	WPD15-VC	Wikipedia Virtual Collection	German Wikipedia 2015	ids	read	corpusSigle=WPD15 & creationDate since 2014-04-01	
+virtualcollection	GOE-VC	Goethe Virtual Collection	Goethe works from 1810	public	read	corpusSigle=GOE & creationDate since 1810-01-01
+virtualcollection	BRZ10-PC	Braunschweiger Collection	Selected Braunschweiger Zeitung	ids	read	corpusSigle=BRZ10 & foundries ~ Connexor
+corpus	WPD13	Wikipedia 2013	Public German Wikipedia 2013	public	read
+corpus	WPD15	Wikipedia 2015	IDS German Wikipedia 2015	ids	read
+corpus	GOE	Goethe	Goethe corpus	public	read
+corpus	BRZ10	Braunschweiger	Braunschweiger Zeitung 2010	ids	read
+foundry	base	base	Base foundry	public	read
+foundry	dereko	dereko	DeReKo foundry	public	read
+foundry	corenlp	corenlp	CoreNLP parser	public	read
+foundry	opennlp	opennlp	OpenNLP parser	public	read
+foundry	malt	malt	MALT parser	public	read
+foundry	mdp	mdp	MD parser	public	read
+foundry	tt	tt	Tree Tagger parser	public	read
+foundry	sgbr	sgbr	Schreibgebrauch	ids	read
+foundry	cnx	cnx	Connexor parser	ids	read
+foundry	drukola	drukola	DruKoLa parser	drukola	read
+foundry	glemm	glemm	Glemm	public	read
+foundry	marmot	marmot	MarMoT parser	public	read
+foundry	mate	mate	Mate parser	public	read
+foundry	xip	xip	Xerox Incremental Parser	ids	read
+layer	cnx/c	cnx/c	Connexor constituency layer	ids	read
+layer	cnx/syn	cnx/syn	Connexor syntax	ids	read
+layer	cnx/p	cnx/p	Connexor part of speech	ids	read
+layer	cnx/l	cnx/l	Connexor lemma	ids	read
+layer	cnx/m	cnx/m	Connexor morphology	ids	read
+layer	corenlp/c	corenlp/c	CoreNLP constituency	public	read
+layer	corenlp/p	corenlp/p	CoreNLP part of speech	public	read
+layer	corenlp/s	corenlp/s	CoreNLP structure	public	read
+layer	corenlp/ne	corenlp/ne	CoreNLP named entities	public	read
+layer	dereko/s	dereko/s	DeReKo structure	public	read
+layer	drukola/l	drukola/l	Drukola lemma	drukola	read
+layer	drukola/p	drukola/p	Drukola part of speech	drukola	read
+layer	drukola/m	drukola/m	Drukola morphology	drukola	read
+layer	glemm/l	glemm/l	GLEMM lemma	public	read
+layer	malt/d	malt/d	MALT dependency	public	read
+layer	marmot/p	marmot/p	Marmot part of speech	public	read
+layer	marmot/m	marmot/m	Marmot morphology	public	read
+layer	mate/d	mate/d	MATE dependency	public	read
+layer	mate/l	mate/l	MATE lemma	public	read
+layer	mate/p	mate/p	MATE part of speech	public	read
+layer	mate/m	mate/m	MATE morphology	public	read
+layer	mdp/d	mdp/d	MDP dependency	public	read
+layer	opennlp/p	opennlp/p	OpenNLP part of speech	public	read
+layer	opennlp/s	opennlp/s	OpenNLP part of speech	public	read
+layer	sgbr/p	sgbr/p	Schreibgebrauchp part of peech	ids	read
+layer	sgbr/l	sgbr/l	Schreibgebrauch lemma	ids	read
+layer	sgbr/lv	sgbr/lv	Schreibgebrauch lemmav ariant	ids	read
+layer	tt/p	tt/p	Tree Tagger part of speech	public	read
+layer	tt/l	tt/l	Tree Tagger lemma	public	read
+layer	tt/s	tt/s	Tree Tagger structure	public	read
+layer	xip/c	xip/c	XIP constituency	ids	read
+layer	xip/d	xip/d	XIP dependency	ids	read
+layer	xip/l	xip/l	XIP lemma	ids	read
+layer	xip/p	xip/p	XIP part of speech	ids	read
+layer	xip/s	xip/s	XIP structure	ids	read
diff --git a/src/test/resources/sample-index/_0.cfe b/src/test/resources/sample-index/_0.cfe
new file mode 100644
index 0000000..8abc486
--- /dev/null
+++ b/src/test/resources/sample-index/_0.cfe
Binary files differ
diff --git a/src/test/resources/sample-index/_0.cfs b/src/test/resources/sample-index/_0.cfs
new file mode 100644
index 0000000..63efeb7
--- /dev/null
+++ b/src/test/resources/sample-index/_0.cfs
Binary files differ
diff --git a/src/test/resources/sample-index/_0.si b/src/test/resources/sample-index/_0.si
new file mode 100644
index 0000000..fe1bebe
--- /dev/null
+++ b/src/test/resources/sample-index/_0.si
Binary files differ
diff --git a/src/test/resources/sample-index/_1.cfe b/src/test/resources/sample-index/_1.cfe
new file mode 100644
index 0000000..a515fac
--- /dev/null
+++ b/src/test/resources/sample-index/_1.cfe
Binary files differ
diff --git a/src/test/resources/sample-index/_1.cfs b/src/test/resources/sample-index/_1.cfs
new file mode 100644
index 0000000..be27ceb
--- /dev/null
+++ b/src/test/resources/sample-index/_1.cfs
Binary files differ
diff --git a/src/test/resources/sample-index/_1.si b/src/test/resources/sample-index/_1.si
new file mode 100644
index 0000000..5764d53
--- /dev/null
+++ b/src/test/resources/sample-index/_1.si
Binary files differ
diff --git a/src/test/resources/sample-index/segments_1 b/src/test/resources/sample-index/segments_1
new file mode 100644
index 0000000..b1944d5
--- /dev/null
+++ b/src/test/resources/sample-index/segments_1
Binary files differ
diff --git a/src/test/resources/index-kustvakt-example/write.lock b/src/test/resources/sample-index/write.lock
similarity index 100%
rename from src/test/resources/index-kustvakt-example/write.lock
rename to src/test/resources/sample-index/write.lock
diff --git a/src/test/resources/test-default-config.xml b/src/test/resources/test-default-config.xml
new file mode 100644
index 0000000..19f7e89
--- /dev/null
+++ b/src/test/resources/test-default-config.xml
@@ -0,0 +1,225 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util"
+	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
+	xmlns="http://www.springframework.org/schema/beans" xmlns:cache="http://www.springframework.org/schema/cache"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans
+                            http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
+                            http://www.springframework.org/schema/tx
+                            http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
+
+
+                            http://www.springframework.org/schema/aop
+                            http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
+                            http://www.springframework.org/schema/cache
+                            http://www.springframework.org/schema/cache/spring-cache-4.0.xsd
+
+
+                            http://www.springframework.org/schema/util
+                            http://www.springframework.org/schema/util/spring-util-4.0.xsd">
+
+	<bean id="props"
+		class="org.springframework.beans.factory.config.PropertiesFactoryBean">
+		<property name="ignoreResourceNotFound" value="true" />
+		<property name="locations">
+			<array>
+				<value>classpath:kustvakt-test.conf</value>
+				<value>file:./kustvakt-test.conf</value>
+			</array>
+		</property>
+	</bean>
+
+	<bean id="jdbc_props"
+		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
+		<property name="ignoreResourceNotFound" value="true" />
+		<property name="locations">
+			<array>
+				<value>classpath:jdbc.properties</value>
+				<value>file:./jdbc_tests.properties</value>
+			</array>
+		</property>
+	</bean>
+
+	<bean id='cacheManager' class='org.springframework.cache.ehcache.EhCacheCacheManager'
+		p:cacheManager-ref='ehcache' />
+
+	<bean id='ehcache'
+		class='org.springframework.cache.ehcache.EhCacheManagerFactoryBean'
+		p:configLocation='classpath:ehcache.xml' p:shared='true' />
+
+	<!-- props are injected from default-config.xml -->
+	<bean id="kustvakt_config" class="de.ids_mannheim.korap.config.KustvaktConfiguration">
+		<property name="properties" ref="props" />
+	</bean>
+
+	<!--class="org.apache.commons.dbcp2.BasicDataSource" -->
+	<!-- org.springframework.jdbc.datasource.SingleConnectionDataSource -->
+	<!-- org.springframework.jdbc.datasource.DriverManagerDataSource -->
+	<bean id="dataSource"
+		class="org.springframework.jdbc.datasource.SingleConnectionDataSource"
+		lazy-init="false">
+		<property name="driverClassName" value="org.sqlite.JDBC" />
+		<property name="url" value="jdbc:sqlite::memory:" />
+		<!--<property name="initialSize" value="1" /> -->
+		<!--<property name="maxTotal" value="1" /> -->
+		<!--<property name="maxIdle" value="1" /> -->
+		<!--<property name="username" value="${jdbc.username}"/> -->
+		<!--<property name="password" value="${jdbc.password}"/> -->
+		<!-- relevant for single connection datasource and sqlite -->
+		<property name="suppressClose">
+			<value>true</value>
+		</property>
+		<!--<property name="initialSize" value="2"/> -->
+		<!--<property name="maxIdle" value="2"/> -->
+		<!--<property name="poolPreparedStatements" value="true"/> -->
+	</bean>
+
+	<!-- to configure database for sqlite, mysql, etc. migrations -->
+	<bean id="flyway" class="org.flywaydb.core.Flyway" init-method="migrate">
+		<property name="baselineOnMigrate" value="false" />
+		<property name="locations" value="classpath:db.sqlite" />
+		<property name="dataSource" ref="dataSource" />
+	</bean>
+
+	<bean id="kustvakt_db" class="de.ids_mannheim.korap.handlers.JDBCClient">
+		<constructor-arg index="0" ref="dataSource" />
+		<property name="database" value="jdbc:sqlite::memory:" />
+	</bean>
+
+	<bean id="kustvakt_userdetails" class="de.ids_mannheim.korap.handlers.UserDetailsDao">
+		<constructor-arg ref="kustvakt_db" />
+	</bean>
+
+	<bean id="kustvakt_usersettings" class="de.ids_mannheim.korap.handlers.UserSettingsDao">
+		<constructor-arg ref="kustvakt_db" />
+	</bean>
+
+	<bean id="kustvakt_auditing" class="de.ids_mannheim.korap.handlers.JDBCAuditing">
+		<constructor-arg ref="kustvakt_db" />
+	</bean>
+
+	<bean id="kustvakt_userdb" class="de.ids_mannheim.korap.handlers.EntityDao">
+		<constructor-arg ref="kustvakt_db" />
+	</bean>
+
+	<bean id="kustvakt_admindb" class="de.ids_mannheim.korap.handlers.AdminDao">
+		<constructor-arg ref="kustvakt_db" />
+	</bean>
+
+	<bean id="resource_provider" class="de.ids_mannheim.korap.handlers.ResourceDao">
+		<constructor-arg ref="kustvakt_db" />
+	</bean>
+
+	<bean id="document_provider" class="de.ids_mannheim.korap.handlers.DocumentDao">
+		<constructor-arg ref="kustvakt_db" />
+	</bean>
+
+	<bean id="kustvakt_policies" class="de.ids_mannheim.korap.security.ac.PolicyDao">
+		<constructor-arg ref="kustvakt_db" />
+	</bean>
+
+	<bean name="kustvakt_encryption"
+		class="de.ids_mannheim.korap.interfaces.defaults.KustvaktEncryption">
+		<constructor-arg ref="kustvakt_config" />
+	</bean>
+
+	<!-- authentication providers to use -->
+	<bean id="api_auth" class="de.ids_mannheim.korap.security.auth.APIAuthentication">
+		<constructor-arg type="de.ids_mannheim.korap.config.KustvaktConfiguration"
+			ref="kustvakt_config" />
+	</bean>
+
+	<bean id="openid_auth"
+		class="de.ids_mannheim.korap.security.auth.OpenIDconnectAuthentication">
+		<constructor-arg type="de.ids_mannheim.korap.config.KustvaktConfiguration"
+			ref="kustvakt_config" />
+		<constructor-arg
+			type="de.ids_mannheim.korap.interfaces.db.PersistenceClient" ref="kustvakt_db" />
+	</bean>
+
+	<bean id="basic_auth" class="de.ids_mannheim.korap.security.auth.BasicHttpAuth" />
+
+
+	<bean id="session_auth"
+		class="de.ids_mannheim.korap.security.auth.SessionAuthentication">
+		<constructor-arg type="de.ids_mannheim.korap.config.KustvaktConfiguration"
+			ref="kustvakt_config" />
+		<constructor-arg type="de.ids_mannheim.korap.interfaces.EncryptionIface"
+			ref="kustvakt_encryption" />
+	</bean>
+
+	<util:list id="kustvakt_authproviders"
+		value-type="de.ids_mannheim.korap.interfaces.AuthenticationIface">
+		<ref bean="basic_auth" />
+		<ref bean="session_auth" />
+		<ref bean="api_auth" />
+		<ref bean="openid_auth" />
+	</util:list>
+
+	<bean id="userdata_details" class="de.ids_mannheim.korap.handlers.UserDetailsDao">
+		<constructor-arg
+			type="de.ids_mannheim.korap.interfaces.db.PersistenceClient" ref="kustvakt_db" />
+	</bean>
+	<bean id="userdata_settings" class="de.ids_mannheim.korap.handlers.UserSettingsDao">
+		<constructor-arg
+			type="de.ids_mannheim.korap.interfaces.db.PersistenceClient" ref="kustvakt_db" />
+	</bean>
+
+	<util:list id="kustvakt_userdata"
+		value-type="de.ids_mannheim.korap.interfaces.db.UserdataDbIface">
+		<ref bean="userdata_details" />
+		<ref bean="userdata_settings" />
+	</util:list>
+
+	<util:list id="kustvakt_resources"
+		value-type="de.ids_mannheim.korap.interfaces.db.ResourceOperationIface">
+		<ref bean="document_provider" />
+		<ref bean="resource_provider" />
+	</util:list>
+
+
+	<!-- specify type for constructor argument -->
+	<bean id="kustvakt_authenticationmanager"
+		class="de.ids_mannheim.korap.security.auth.KustvaktAuthenticationManager">
+		<constructor-arg
+			type="de.ids_mannheim.korap.interfaces.db.EntityHandlerIface" ref="kustvakt_userdb" />
+		<constructor-arg
+			type="de.ids_mannheim.korap.interfaces.db.AdminHandlerIface" ref="kustvakt_admindb" />
+		<constructor-arg type="de.ids_mannheim.korap.interfaces.EncryptionIface"
+			ref="kustvakt_encryption" />
+		<constructor-arg ref="kustvakt_config" />
+		<constructor-arg type="de.ids_mannheim.korap.interfaces.db.AuditingIface"
+			ref="kustvakt_auditing" />
+		<constructor-arg ref="kustvakt_userdata" />
+		<!-- inject authentication providers to use -->
+		<property name="providers" ref="kustvakt_authproviders" />
+	</bean>
+
+	<!-- todo: if db interfaces not loaded via spring, does transaction even 
+		work then? -->
+	<!-- the transactional advice (i.e. what 'happens'; see the <aop:advisor/> 
+		bean below) -->
+	<tx:advice id="txAdvice" transaction-manager="txManager">
+		<!-- the transactional semantics... -->
+		<tx:attributes>
+			<!-- all methods starting with 'get' are read-only -->
+			<tx:method name="get*" read-only="true" rollback-for="KorAPException" />
+			<!-- other methods use the default transaction settings (see below) -->
+			<tx:method name="*" rollback-for="KorAPException" />
+		</tx:attributes>
+	</tx:advice>
+
+	<!-- ensure that the above transactional advice runs for any execution of 
+		an operation defined by the service interface -->
+	<aop:config>
+		<aop:pointcut id="service"
+			expression="execution(* de.ids_mannheim.korap.interfaces.db.*.*(..))" />
+		<aop:advisor advice-ref="txAdvice" pointcut-ref="service" />
+	</aop:config>
+
+	<!-- similarly, don't forget the PlatformTransactionManager -->
+	<bean id="txManager"
+		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
+		<property name="dataSource" ref="dataSource" />
+	</bean>
+</beans>
\ No newline at end of file