general bug fixes; cookie handling for query panel search history; policy database refactoring; custom indexing; resource retrieval updates; authentication providers configuration via configfile; ehcache bug fix; JWT bug fix;
diff --git a/src/main/java/de/ids_mannheim/korap/KorapResult.java b/src/main/java/de/ids_mannheim/korap/KorapResult.java
index e53b7f4..883cec7 100644
--- a/src/main/java/de/ids_mannheim/korap/KorapResult.java
+++ b/src/main/java/de/ids_mannheim/korap/KorapResult.java
@@ -1,18 +1,17 @@
 package de.ids_mannheim.korap;
 
-import java.util.*;
-import de.ids_mannheim.korap.KorapMatch;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.node.ObjectNode;
 import de.ids_mannheim.korap.index.PositionsToOffset;
 import de.ids_mannheim.korap.index.SearchContext;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializationFeature;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.*;
-import com.fasterxml.jackson.annotation.*;
+import java.util.ArrayList;
+import java.util.List;
 
 /*
 TODO: Reuse the KorapSearch code for data serialization!
@@ -34,7 +33,7 @@
     private short itemsPerPage = ITEMS_PER_PAGE;
 
     private String benchmarkSearchResults,
-	           benchmarkHitCounter;
+            benchmarkHitCounter;
     private String error = null;
     private String version;
 
@@ -45,45 +44,48 @@
     private final static Logger log = LoggerFactory.getLogger(KorapMatch.class);
 
     // Empty result
-    public KorapResult () {};
+    public KorapResult() {
+    }
 
 
-    public KorapResult (String query,
-			int startIndex,
-			short itemsPerPage,
-			SearchContext context) {
+    public KorapResult(String query,
+                       int startIndex,
+                       short itemsPerPage,
+                       SearchContext context) {
 
-	mapper.enable(SerializationFeature.INDENT_OUTPUT);
-	// mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
-	mapper.disable(SerializationFeature.WRITE_NULL_MAP_VALUES);
+        mapper.enable(SerializationFeature.INDENT_OUTPUT);
+        // mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
+        mapper.disable(SerializationFeature.WRITE_NULL_MAP_VALUES);
 
-	this.matches = new ArrayList<>(itemsPerPage);
-	this.query = query;
-	this.startIndex = startIndex;
-	this.itemsPerPage = (itemsPerPage > 50 || itemsPerPage < 1) ? ITEMS_PER_PAGE : itemsPerPage;
-	this.context = context;
-    };
+        this.matches = new ArrayList<>(itemsPerPage);
+        this.query = query;
+        this.startIndex = startIndex;
+        this.itemsPerPage = (itemsPerPage > 50 || itemsPerPage < 1) ? ITEMS_PER_PAGE : itemsPerPage;
+        this.context = context;
+    }
 
-    public void add (KorapMatch km) {
-	this.matches.add(km);
-    };
 
-    public KorapMatch addMatch (PositionsToOffset pto, int localDocID, int startPos, int endPos) {
-	KorapMatch km = new KorapMatch(pto, localDocID, startPos, endPos);
+    public void add(KorapMatch km) {
+        this.matches.add(km);
+    }
 
-	// Temporary - should use the same interface like results
-	// in the future:
-	km.setContext(this.context);
 
-	// Add pos for context
-	// That's not really a good position for it,
-	// to be honest ...
-	// But maybe it will make the offset
-	// information in the match be obsolete!
+    public KorapMatch addMatch(PositionsToOffset pto, int localDocID, int startPos, int endPos) {
+        KorapMatch km = new KorapMatch(pto, localDocID, startPos, endPos);
 
-	// TODO:
-	/*
-	if (km.leftTokenContext) {
+        // Temporary - should use the same interface like results
+        // in the future:
+        km.setContext(this.context);
+
+        // Add pos for context
+        // That's not really a good position for it,
+        // to be honest ...
+        // But maybe it will make the offset
+        // information in the match be obsolete!
+
+        // TODO:
+    /*
+    if (km.leftTokenContext) {
 	    pto.add(localDocID, startPos - this.leftContextOffset);
 	};
 	if (km.rightTokenContext) {
@@ -91,129 +93,152 @@
 	};
 	*/
 
-	this.add(km);
-	return km;
-    };
+        this.add(km);
+        return km;
+    }
 
-    public void setTotalResults (int i) {
-	this.totalResults = i;
-    };
 
-    public int getTotalResults () {
-	return this.totalResults;
-    };
+    public void setTotalResults(int i) {
+        this.totalResults = i;
+    }
+
+
+    public int getTotalResults() {
+        return this.totalResults;
+    }
 
 
     @Deprecated
-    public int totalResults () {
-	return this.totalResults;
-    };
+    public int totalResults() {
+        return this.totalResults;
+    }
+
 
     @JsonIgnore
-    public void setVersion (String version) {
-	this.version = version;
-    };
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
 
     @JsonIgnore
-    public String getVersion () {
-	if (this.version == null)
-	    return null;
-	return "lucene-backend-" + this.version;
-    };
-    
-    public short getItemsPerPage () {
-	return this.itemsPerPage;
-    };
+    public String getVersion() {
+        if (this.version == null)
+            return null;
+        return "lucene-backend-" + this.version;
+    }
+
+
+    public short getItemsPerPage() {
+        return this.itemsPerPage;
+    }
+
 
     @Deprecated
-    public short itemsPerPage () {
-	return this.itemsPerPage;
-    };
+    public short itemsPerPage() {
+        return this.itemsPerPage;
+    }
 
-    public String getError () {
-	return this.error;
-    };
 
-    public void setError (String msg) {
-	this.error = msg;
-    };
+    public String getError() {
+        return this.error;
+    }
 
-    public void setRequest (JsonNode request) {
-	this.request = request;
-    };
 
-    public JsonNode getRequest () {
-	return this.request;
-    };
+    public void setError(String msg) {
+        this.error = msg;
+    }
 
-    public void setBenchmarkSearchResults (long t1, long t2) {
-	this.benchmarkSearchResults =
-	    (t2 - t1) < 100_000_000 ? (((double)(t2 - t1) * 1e-6) + " ms") :
-	    (((double)(t2 - t1) / 1000000000.0) + " s");
-    };
 
-    public String getBenchmarkSearchResults () {
-	return this.benchmarkSearchResults;
-    };
+    public void setRequest(JsonNode request) {
+        this.request = request;
+    }
 
-    public void setBenchmarkHitCounter (long t1, long t2) {
-	this.benchmarkHitCounter =
-	    (t2 - t1) < 100_000_000 ? (((double)(t2 - t1) * 1e-6) + " ms") :
-	    (((double)(t2 - t1) / 1000000000.0) + " s");
-    };
 
-    public String getBenchmarkHitCounter () {
-	return this.benchmarkHitCounter;
-    };
+    public JsonNode getRequest() {
+        return this.request;
+    }
 
-    public String getQuery () {
-	return this.query;
-    };
 
-    public KorapMatch getMatch (int index) {
-	return this.matches.get(index);
-    };
+    public void setBenchmarkSearchResults(long t1, long t2) {
+        this.benchmarkSearchResults =
+                (t2 - t1) < 100_000_000 ? (((double) (t2 - t1) * 1e-6) + " ms") :
+                        (((double) (t2 - t1) / 1000000000.0) + " s");
+    }
 
-    public List<KorapMatch> getMatches () {
-	return this.matches;
-    };
+
+    public String getBenchmarkSearchResults() {
+        return this.benchmarkSearchResults;
+    }
+
+
+    public void setBenchmarkHitCounter(long t1, long t2) {
+        this.benchmarkHitCounter =
+                (t2 - t1) < 100_000_000 ? (((double) (t2 - t1) * 1e-6) + " ms") :
+                        (((double) (t2 - t1) / 1000000000.0) + " s");
+    }
+
+
+    public String getBenchmarkHitCounter() {
+        return this.benchmarkHitCounter;
+    }
+
+
+    public String getQuery() {
+        return this.query;
+    }
+
+
+    public KorapMatch getMatch(int index) {
+        return this.matches.get(index);
+    }
+
+
+    public List<KorapMatch> getMatches() {
+        return this.matches;
+    }
+
 
     @Deprecated
-    public KorapMatch match (int index) {
-	return this.matches.get(index);
-    };
-
-    public int getStartIndex () {
-	return startIndex;
-    };
+    public KorapMatch match(int index) {
+        return this.matches.get(index);
+    }
 
 
-    public KorapResult setContext (SearchContext context) {
-	this.context = context;
-	return this;
-    };
+    public int getStartIndex() {
+        return startIndex;
+    }
+
+
+    public KorapResult setContext(SearchContext context) {
+        this.context = context;
+        return this;
+    }
+
 
     @JsonIgnore
-    public SearchContext getContext () {
-	return this.context;
-    };
+    public SearchContext getContext() {
+        return this.context;
+    }
+
 
     // Identical to KorapMatch!
-    public String toJSON () {
-	ObjectNode json =  (ObjectNode) mapper.valueToTree(this);
+    public String toJSON() {
+        ObjectNode json = (ObjectNode) mapper.valueToTree(this);
 
-	json.put("context", this.getContext().toJSON());
+        json.put("context", this.getContext().toJSON());
 
-	if (this.version != null)
-	    json.put("version", this.version);
+        if (this.version != null)
+            json.put("version", this.version);
 
-	try {
-	    return mapper.writeValueAsString(json);
-	}
-	catch (Exception e) {
-	    log.warn(e.getLocalizedMessage());
-	};
+        try {
+            return mapper.writeValueAsString(json);
+        } catch (Exception e) {
+            log.warn(e.getLocalizedMessage());
+        }
 
-	return "{}";
-    };
+
+        return "{}";
+    }
+
+
 };
diff --git a/src/main/java/de/ids_mannheim/korap/KorapSearch.java b/src/main/java/de/ids_mannheim/korap/KorapSearch.java
index 0737415..2a26c7f 100644
--- a/src/main/java/de/ids_mannheim/korap/KorapSearch.java
+++ b/src/main/java/de/ids_mannheim/korap/KorapSearch.java
@@ -1,17 +1,13 @@
 package de.ids_mannheim.korap;
 
-import java.io.*;
-
-import org.apache.lucene.search.spans.SpanQuery;
-import de.ids_mannheim.korap.query.wrap.SpanQueryWrapperInterface;
-import de.ids_mannheim.korap.KorapCollection;
-import de.ids_mannheim.korap.KorapIndex;
-import de.ids_mannheim.korap.KorapResult;
-import de.ids_mannheim.korap.util.QueryException;
-import de.ids_mannheim.korap.index.SearchContext;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import de.ids_mannheim.korap.index.SearchContext;
+import de.ids_mannheim.korap.query.wrap.SpanQueryWrapperInterface;
+import de.ids_mannheim.korap.util.QueryException;
+import org.apache.lucene.search.spans.SpanQuery;
+
+import java.io.IOException;
 
 // Todo: Use configuration file
 
@@ -22,13 +18,13 @@
 
 /**
  * @author Nils Diewald
- *
- * KoraSearch implements an object for all search relevant parameters.
+ *         <p/>
+ *         KoraSearch implements an object for all search relevant parameters.
  */
 public class KorapSearch {
     private int startIndex = 0, limit = 0;
     private short count = 25,
-	          countMax = 50;
+            countMax = 50;
     private boolean cutoff = false;
     private SpanQuery query;
     private KorapCollection collection;
@@ -41,213 +37,241 @@
     private String spanContext;
 
     {
-	context  = new SearchContext();
-    };
+        context = new SearchContext();
+    }
 
-    public KorapSearch (String jsonString) {
-	ObjectMapper mapper = new ObjectMapper();
-	try {
-	    this.request = mapper.readValue(jsonString, JsonNode.class);
-	    
-	    // "query" value
-	    if (this.request.has("query")) {
-		try {
-		    this.query = new KorapQuery("tokens").fromJSON(this.request.get("query")).toQuery();
-		}
-		catch (QueryException q) {
-		    this.error = q.getMessage();
-		};
-	    }
-	    else {
-		this.error = "No query defined";
-	    };
 
-	    // "meta" virtual collections
-	    if (this.request.has("collections"))
-		this.setCollection(new KorapCollection(jsonString));
+    public KorapSearch(String jsonString) {
+        ObjectMapper mapper = new ObjectMapper();
+        try {
+            this.request = mapper.readValue(jsonString, JsonNode.class);
 
-	    if (this.error == null) {
-		if (this.request.has("meta")) {
-		    JsonNode meta = this.request.get("meta");
+            // "query" value
+            if (this.request.has("query")) {
+                try {
+                    this.query = new KorapQuery("tokens").fromJSON(this.request.get("query")).toQuery();
+                } catch (QueryException q) {
+                    this.error = q.getMessage();
+                }
 
-		    // Defined count
-		    if (meta.has("count"))
-			this.setCount(meta.get("count").asInt());
+            } else {
+                this.error = "No query defined";
+            }
 
-		    // Defined startIndex
-		    if (meta.has("startIndex"))
-			this.setStartIndex(meta.get("startIndex").asInt());
 
-		    // Defined startPage
-		    if (meta.has("startPage"))
-			this.setStartPage(meta.get("startPage").asInt());
+            // "meta" virtual collections
+            if (this.request.has("collections"))
+                this.setCollection(new KorapCollection(jsonString));
 
-		    // Defined cutOff
-		    if (meta.has("cutOff"))
-			this.setCutOff(meta.get("cutOff").asBoolean());
+            if (this.error == null) {
+                if (this.request.has("meta")) {
+                    JsonNode meta = this.request.get("meta");
 
-		    // Defined contexts
-		    if (meta.has("context"))
-			this.context.fromJSON(meta.get("context"));
-		};
-	    };
-	}
+                    // Defined count
+                    if (meta.has("count"))
+                        this.setCount(meta.get("count").asInt());
 
-	// Unable to parse JSON
-	catch (IOException e) {
-	    this.error = e.getMessage();
-	};
-    };
+                    // Defined startIndex
+                    if (meta.has("startIndex"))
+                        this.setStartIndex(meta.get("startIndex").asInt());
+
+                    // Defined startPage
+                    if (meta.has("startPage"))
+                        this.setStartPage(meta.get("startPage").asInt());
+
+                    // Defined cutOff
+                    if (meta.has("cutOff"))
+                        this.setCutOff(meta.get("cutOff").asBoolean());
+
+                    // Defined contexts
+                    if (meta.has("context"))
+                        this.context.fromJSON(meta.get("context"));
+                }
+
+            }
+
+        }
+
+        // Unable to parse JSON
+        catch (IOException e) {
+            this.error = e.getMessage();
+        }
+
+    }
 
 
     // Maybe accept queryWrapperStuff
-    public KorapSearch (SpanQueryWrapperInterface sqwi) {
-	this.query = sqwi.toQuery();
-    };
+    public KorapSearch(SpanQueryWrapperInterface sqwi) {
+        this.query = sqwi.toQuery();
+    }
 
-    public KorapSearch (SpanQuery sq) {
-	this.query = sq;
-    };
+
+    public KorapSearch(SpanQuery sq) {
+        this.query = sq;
+    }
+
 
     // Empty constructor
-    public KorapSearch () { };
-
-    public String getError () {
-	return this.error;
-    };
-
-    public SpanQuery getQuery () {
-	return this.query;
-    };
-
-    public JsonNode getRequest () {
-	return this.request;
-    };
-
-    public KorapSearch setQuery (SpanQueryWrapperInterface sqwi) {
-	this.query = sqwi.toQuery();
-	return this;
-    };
-
-    public KorapSearch setQuery (SpanQuery sq) {
-	this.query = sq;
-	return this;
-    };
-
-    public SearchContext getContext () {
-	return this.context;
-    };
+    public KorapSearch() {
+    }
 
 
-    public KorapSearch setContext (SearchContext context) {
-	this.context = context;
-	return this;
-    };
+    public String getError() {
+        return this.error;
+    }
 
-    public int getStartIndex () {
-	return this.startIndex;
-    };
 
-    public KorapSearch setStartIndex (int value) {
-	if (value >= 0) {
-	    this.startIndex = value;
-	}
-	else {
-	    this.startIndex = 0;
-	};
+    public SpanQuery getQuery() {
+        return this.query;
+    }
 
-	return this;
-    };
 
-    public KorapSearch setStartPage (int value) {
-	if (value >= 0) {
-	    this.setStartIndex((value * this.getCount()) - this.getCount());
-	}
-	else {
-	    this.startIndex = 0;
-	};
+    public JsonNode getRequest() {
+        return this.request;
+    }
 
-	return this;
-    };
 
-    public short getCount () {
-	return this.count;
-    };
+    public KorapSearch setQuery(SpanQueryWrapperInterface sqwi) {
+        this.query = sqwi.toQuery();
+        return this;
+    }
 
-    public short getCountMax () {
-	return this.countMax;
-    };
 
-    public int getLimit () {
-	return this.limit;
-    };
+    public KorapSearch setQuery(SpanQuery sq) {
+        this.query = sq;
+        return this;
+    }
 
-    public KorapSearch setLimit (int limit) {
-	if (limit > 0)
-	    this.limit = limit;
-	return this;
-    };
 
-    public boolean doCutOff () {
-	return this.cutoff;
-    };
+    public SearchContext getContext() {
+        return this.context;
+    }
 
-    public KorapSearch setCutOff (boolean cutoff) {
-	this.cutoff = cutoff;
-	return this;
-    };
 
-    public KorapSearch setCount (int value) {
-	// Todo: Maybe update startIndex with known startPage!
-	this.setCount((short) value);
-	return this;
-    };
+    public KorapSearch setContext(SearchContext context) {
+        this.context = context;
+        return this;
+    }
 
-    public KorapSearch setCount (short value) {
-	if (value > 0) {
-	    if (value <= this.countMax)
-		this.count = value;
-	    else
-		this.count = this.countMax;
-	};
-	return this;
-    };
 
-    public KorapSearch setCollection (KorapCollection kc) {
-	this.collection = kc;
-	if (kc.getError() != null)
-	    this.error = kc.getError();
-	return this;
-    };
+    public int getStartIndex() {
+        return this.startIndex;
+    }
 
-    public KorapCollection getCollection () {
-	if (this.collection == null)
-	    this.collection = new KorapCollection();
 
-	return this.collection;
-    };
+    public KorapSearch setStartIndex(int value) {
+        if (value >= 0) {
+            this.startIndex = value;
+        } else {
+            this.startIndex = 0;
+        }
+        return this;
+    }
 
-    public KorapResult run (KorapIndex ki) {
-	if (this.query == null) {
-	    KorapResult kr = new KorapResult();
-	    kr.setRequest(this.request);
-	    if (this.error != null)
-		kr.setError(this.error);
-	    else
-		kr.setError(this.getClass() + " expects a query");
-	    return kr;
-	};
 
-	if (this.error != null) {
-	    KorapResult kr = new KorapResult();
-	    kr.setRequest(this.request);
-	    kr.setError(this.error);
-	    return kr;
-	};
+    public KorapSearch setStartPage(int value) {
+        if (value >= 0) {
+            this.setStartIndex((value * this.getCount()) - this.getCount());
+        } else {
+            this.startIndex = 0;
+        }
+        return this;
+    }
 
-	this.getCollection().setIndex(ki);
-	KorapResult kr = ki.search(this.getCollection(), this);
-	kr.setRequest(this.request);
-	return kr;
-    };
+
+    public short getCount() {
+        return this.count;
+    }
+
+
+    public short getCountMax() {
+        return this.countMax;
+    }
+
+
+    public int getLimit() {
+        return this.limit;
+    }
+
+
+    public KorapSearch setLimit(int limit) {
+        if (limit > 0)
+            this.limit = limit;
+        return this;
+    }
+
+
+    public boolean doCutOff() {
+        return this.cutoff;
+    }
+
+
+    public KorapSearch setCutOff(boolean cutoff) {
+        this.cutoff = cutoff;
+        return this;
+    }
+
+
+    public KorapSearch setCount(int value) {
+        // Todo: Maybe update startIndex with known startPage!
+        this.setCount((short) value);
+        return this;
+    }
+
+
+    public KorapSearch setCount(short value) {
+        if (value > 0) {
+            if (value <= this.countMax)
+                this.count = value;
+            else
+                this.count = this.countMax;
+        }
+
+        return this;
+    }
+
+
+    public KorapSearch setCollection(KorapCollection kc) {
+        this.collection = kc;
+        if (kc.getError() != null)
+            this.error = kc.getError();
+        return this;
+    }
+
+
+    public KorapCollection getCollection() {
+        if (this.collection == null)
+            this.collection = new KorapCollection();
+
+        return this.collection;
+    }
+
+
+    public KorapResult run(KorapIndex ki) {
+        if (this.query == null) {
+            KorapResult kr = new KorapResult();
+            kr.setRequest(this.request);
+            if (this.error != null)
+                kr.setError(this.error);
+            else
+                kr.setError(this.getClass() + " expects a query");
+            return kr;
+        }
+
+
+        if (this.error != null) {
+            KorapResult kr = new KorapResult();
+            kr.setRequest(this.request);
+            kr.setError(this.error);
+            return kr;
+        }
+
+
+        this.getCollection().setIndex(ki);
+        KorapResult kr = ki.search(this.getCollection(), this);
+        kr.setRequest(this.request);
+        return kr;
+    }
+
+
 };