Improved test coverage for utility classes
diff --git a/Changes b/Changes
index ce82e98..4201e83 100644
--- a/Changes
+++ b/Changes
@@ -1,12 +1,14 @@
 0.49.4 2015-02-04
-        - [documentation] Improved documentation for API classes (diewald)
+        - [documentation] Improved documentation for API classes,
+	  improved test coverage for utility classes (diewald)
    	- [performance] Updated Lucene dependency from 4.5.1 to 4.10.3,
 	  Updated Jackson dependency from 2.4.0 to 2.4.4,
    	  Updated Jersey dependency from 2.4.1 to 2.15 (diewald)
         - [feature] Presorting of element terms in the index for coherent
 	  SpanQuery sorting (diewald)
 	  Warning: This is a breaking change!
-	- [cleanup] Renamed /filter to /collection (diewald)
+	- [cleanup] Renamed /filter to /collection, 
+	  merge KorapHTML and KorapString (diewald)
 
 0.49.3 2015-02-03
         - [documentation] Improved documentation for API classes (diewald)
diff --git a/Readme.md b/Readme.md
index 62dd605..88549de 100644
--- a/Readme.md
+++ b/Readme.md
@@ -1,90 +1,76 @@
-KorAP Lucene Index
-==================
+# Seaweeds
 
-KorAP is available at
-https://korap.ids-mannheim.de/
+Search Engine for General Corpus Queries
 
-Description
------------
+## Synopsis
+
+## Description
+
+Seaweeds is a [Lucene](https://lucene.apache.org/) based search
+engine for large corpora, providing support for complex linguistic queries.
+
+## Features
+
+Seaweeds provides ...
+* fulltext search
+  (/Give me all occurrences of the phrase "tree hug"!/)
+* token-based annotation search
+  (/Give me all plural nouns in accusative!/)
+* span-based annotation search
+  (/Give me all nominal phrases!/)
+* support for multiple annotation sources
+  (/Give me all words marked as a noun by TreeTagger and marked as an adjective by CoreNLP!/)
+* support for complex queries ..
+  Example
+* support for conflicting span-based annotations
+  (i.e. overlapping spans)
+* support for multiple query languages by using
+  the [CoralQuery](https://github.com/KorAP/Koral)
+  protocol
+
+
+## Prerequisites
 ...
 
-Prerequisites
--------------
-...
+## Starting
 
-Installation/Starting
----------------------
+  $ git clone https://github.com/korap/Seaweeds
+  $ cd Seaweeds
 
-To run the test suite, type
+To run the test suite, type ...
 
   $ mvn test
 
-To start the server, type
+To start the server, type ...
 
   $ mvn compile exec:java
 
-To compile the indexer, type
+To compile and run the indexer, type ...
 
   $ mvn compile assembly:single
 
-To run the indexer, type
-
   $ java -jar target/KorAP-lucene-index-X.XX.jar
     src/main/resources/korap.conf
     src/test/resources/examples/
 
-Development
------------
+## Development
 
-For changes of the current version, please consult the
-Changes file.
+For recent changes, please consult the Changes file.
 
-Limitations
------------
+## Reference
 
-### Tokenization
+Authors: Nils Diewald, Eliza Margaretha
 
-The Lucene backend is not character but token based.
-In addition to that it only has support for one single tokenization.
-Although it supports multiple annotations on tokenizations, these
-annotations have to match the basic token's character offsets.
+Copyright 2013-2015, IDS Mannheim, Germany
 
-Token annotations that do not match the basic tokenization are
-not indexed. Span annotations, that span a smaller range than one
-basic token, will not be indexed as well.
+Seaweeds is developed as part of the [KorAP](https://korap.ids-mannheim.de/)
+Corpus Analysis Platform
 
-Tokens are only indexed in case they are word tokens, i.e. not
-punctuations. This limitation is necessary to make distance query
-work on word levels.
+To cite this work, please ...
 
-### Repetitions
+## Bundled Software
 
-The maximum value for repetitions is 100.
-
-### Distances
-
-The maximum value for distance units is 100.
-
-Contribution
-------------
-
-
-Before contribution, please reformat your code according to the korap
-style guideline, provided by means of an Eclipse style sheet
-(korap-style.xml). You can either reformat using Eclipse or using Maven
-with the command
-
-  $ mvn java-formatter:format
-
-Citation
---------
-
-???
-
-Further References
-------------------
-
-Named entities annotated in the test data by CoreNLP was done using
+Named entities annotated in the test data by CoreNLP were using
 models based on:
 
   Manaal Faruqui and Sebastian Padó (2010):
@@ -92,10 +78,3 @@
   Recognizer with Semantic Generalization,
   Proceedings of KONVENS 2010,
   Saarbrücken, Germany
-
-Copyright and License
----------------------
-
-Copyright 2014, IDS Mannheim, Germany
-
-Authors: Nils Diewald, Eliza Margaretha, and contributors.
\ No newline at end of file
diff --git a/src/main/java/de/ids_mannheim/korap/analysis/MultiTermToken.java b/src/main/java/de/ids_mannheim/korap/analysis/MultiTermToken.java
index b3f0375..f923ef7 100644
--- a/src/main/java/de/ids_mannheim/korap/analysis/MultiTermToken.java
+++ b/src/main/java/de/ids_mannheim/korap/analysis/MultiTermToken.java
@@ -20,7 +20,7 @@
  */
 public class MultiTermToken {
     public List<MultiTerm> terms;
-    private static short i = 0;
+    private short i = 0;
     private boolean sorted = false;
 
     /**
diff --git a/src/main/java/de/ids_mannheim/korap/analysis/MultiTermTokenStream.java b/src/main/java/de/ids_mannheim/korap/analysis/MultiTermTokenStream.java
index 521f7b2..d53aac2 100644
--- a/src/main/java/de/ids_mannheim/korap/analysis/MultiTermTokenStream.java
+++ b/src/main/java/de/ids_mannheim/korap/analysis/MultiTermTokenStream.java
@@ -52,7 +52,7 @@
     private List<MultiTermToken> multiTermTokens;
     private int mttIndex   = 0,
                 mtIndex    = 0;
-    private static short i = 0;
+    private short i = 0;
 
     /**
      * Construct a new MultiTermTokenStream object.
diff --git a/src/main/java/de/ids_mannheim/korap/collection/BooleanFilter.java b/src/main/java/de/ids_mannheim/korap/collection/BooleanFilter.java
index cc9eebe..1d755dd 100644
--- a/src/main/java/de/ids_mannheim/korap/collection/BooleanFilter.java
+++ b/src/main/java/de/ids_mannheim/korap/collection/BooleanFilter.java
@@ -200,10 +200,10 @@
     public BooleanFilter date (String dateStr) {
 	KorapDate dateDF = new KorapDate(dateStr);
 
-	if (dateDF.year() == 0)
+	if (dateDF.year == 0)
 	    return this;
 
-	if (dateDF.day() == 0 || dateDF.month() == 0) {
+	if (dateDF.day == 0 || dateDF.month == 0) {
 	    int begin = dateDF.floor();
 	    int end = dateDF.ceil();
 
diff --git a/src/main/java/de/ids_mannheim/korap/match/HighlightCombinatorElement.java b/src/main/java/de/ids_mannheim/korap/match/HighlightCombinatorElement.java
index cafb8f4..6432c0e 100644
--- a/src/main/java/de/ids_mannheim/korap/match/HighlightCombinatorElement.java
+++ b/src/main/java/de/ids_mannheim/korap/match/HighlightCombinatorElement.java
@@ -3,7 +3,7 @@
 import org.apache.lucene.util.FixedBitSet;
 import de.ids_mannheim.korap.KorapMatch;
 import de.ids_mannheim.korap.match.Relation;
-import static de.ids_mannheim.korap.util.KorapHTML.*;
+import static de.ids_mannheim.korap.util.KorapString.*;
 import java.util.*;
 import java.io.*;
 
@@ -108,7 +108,7 @@
 	};
 
 	// HTML encode primary data
-	return encodeHTML(this.characters);
+	return escapeHTML(this.characters);
     };
 
     // Return bracket fragment for this combinator element
diff --git a/src/main/java/de/ids_mannheim/korap/util/KorapArray.java b/src/main/java/de/ids_mannheim/korap/util/KorapArray.java
index 62d1b8c..bc43d54 100644
--- a/src/main/java/de/ids_mannheim/korap/util/KorapArray.java
+++ b/src/main/java/de/ids_mannheim/korap/util/KorapArray.java
@@ -3,9 +3,10 @@
 import java.util.*;
 
 /**
- * @author Nils Diewald
+ * A collection of string array related
+ * utility functions.
  *
- * A collection of Array specific utilities for the Korap project.
+ * @author diewald
  */
 public class KorapArray {
 
@@ -14,19 +15,20 @@
      *
      * @param separator String to separate joined segments
      * @param strings Segments to join
+     * @return The joined string.
      */
     public static String join (String separator, String ... strings) {
-	if (strings.length == 0)
-	    return "";
+        if (strings.length == 0)
+            return "";
 
-	StringBuffer sb = new StringBuffer(strings[0]);
+        StringBuffer sb = new StringBuffer(strings[0]);
 
-	for (int i = 1; i < strings.length; i++) {
-	    sb.append(separator);
-	    sb.append(strings[i]);
-	};
+        for (int i = 1; i < strings.length; i++) {
+            sb.append(separator);
+            sb.append(strings[i]);
+        };
 
-	return sb.toString();
+        return sb.toString();
     };
 
 
@@ -35,18 +37,19 @@
      *
      * @param separator Character to separate joined segments
      * @param strings Segments to join
+     * @return The joined string.
      */
     public static String join (char separator, String ... strings) {
-	if (strings.length == 0)
-	    return "";
+        if (strings.length == 0)
+            return "";
 
-	StringBuffer sb = new StringBuffer(strings[0]);
-
-	for (int i = 1; i < strings.length; i++) {
-	    sb.append(separator);
-	    sb.append(strings[i]);
-	};
-
-	return sb.toString();
+        StringBuffer sb = new StringBuffer(strings[0]);
+        
+        for (int i = 1; i < strings.length; i++) {
+            sb.append(separator);
+            sb.append(strings[i]);
+        };
+        
+        return sb.toString();
     };
 };
diff --git a/src/main/java/de/ids_mannheim/korap/util/KorapByte.java b/src/main/java/de/ids_mannheim/korap/util/KorapByte.java
index 9115ba7..5d9285e 100644
--- a/src/main/java/de/ids_mannheim/korap/util/KorapByte.java
+++ b/src/main/java/de/ids_mannheim/korap/util/KorapByte.java
@@ -2,12 +2,11 @@
 
 import java.util.*;
 
-// Maybe wrong! TEST!
-
 /**
- * @author Nils Diewald
+ * A collection of byte and byte array related
+ * utility functions.
  *
- * A collection of methods to deal with Bytes and Byte arrays.
+ * @author diewald
  */
 public class KorapByte {
 
@@ -15,47 +14,47 @@
      * Convert an integer to a byte array.
      *
      * @param number The number to convert.
+     * @return The translated byte array.
      */
-    // Based on http://www.tutorials.de/java/228129-konvertierung-von-integer-byte-array.html
+    // Based on
+    // http://www.tutorials.de/java/228129-konvertierung-von-integer-byte-array.html
     public static byte[] int2byte (int number) {
-	byte[] data = new byte[4];
-	for (int i = 0; i < 4; ++i) {
-	    int shift = i << 3; // i * 8
-	    data[3-i] = (byte)((number & (0xff << shift)) >>> shift);
-	};
-	return data;
+        byte[] data = new byte[4];
+        for (int i = 0; i < 4; ++i) {
+            int shift = i << 3; // That's identical to i * 8
+            data[3-i] = (byte)((number & (0xff << shift)) >>> shift);
+        };
+        return data;
     };
 
+
     /**
      * Convert a byte array to an integer.
      *
-     * @param number The number to convert.
+     * @param data The byte array to convert.
+     * @return The translated integer.
      */
-    // Based on http://www.tutorials.de/java/228129-konvertierung-von-integer-byte-array.html
-    public static int byte2int (byte[] data, int offset) {
-	int number = 0;   
-	int i = (offset*4);  
-	for (; i < 4; ++i) {
-	    number |= (data[3-i] & 0xff) << (i << 3);
-	};
-	return number;
-    };
-
+    // Based on
+    // http://www.tutorials.de/java/228129-konvertierung-von-integer-byte-array.html
     public static int byte2int (byte[] data) {
-	return byte2int(data, 0);
+        return byte2int(data, 0);
     };
 
-    /*
-    public static short byte2short (byte[] data, int offset) {
-	short number = 0;
-	number |= (data[3-offset] & 0xff) << (offset << 3);
-	offset--;
-	number |= (data[3-offset] & 0xff) << (offset << 3);
-	return number;
-    };
 
-    public static short byte2short (byte[] data) {
-	return byte2short(datam 0);
+    /**
+     * Convert a byte array to an integer.
+     *
+     * @param data The byte array to convert.
+     * @param offset The byte offset.
+     * @return The translated integer.
+     */
+    // Based on
+    // http://www.tutorials.de/java/228129-konvertierung-von-integer-byte-array.html
+    public static int byte2int (byte[] data, int offset) {
+        int number = 0;   
+        int i = (offset * 4);  
+        for (; i < 4; ++i)
+            number |= (data[3-i] & 0xff) << (i << 3);
+        return number;
     };
-    */
 };
diff --git a/src/main/java/de/ids_mannheim/korap/util/KorapDate.java b/src/main/java/de/ids_mannheim/korap/util/KorapDate.java
index 8eafeb4..f17d4f1 100644
--- a/src/main/java/de/ids_mannheim/korap/util/KorapDate.java
+++ b/src/main/java/de/ids_mannheim/korap/util/KorapDate.java
@@ -4,163 +4,249 @@
 import java.util.regex.*;
 
 /**
- * @author Nils Diewald
+ * KorapDate implements a helper object to stringify
+ * and parse date strings optimized
+ * for integer range queries in Lucene.
+ * No support for b.c. dates.
  *
- * KorapDate implements a helper object to stringify and parse date strings implemented
- * for integer range queries.
+ * Strings are parsed and serialized to
+ * {@link http://tools.ietf.org/html/rfc3339 RFC3339}
+ * compatible strings with a day granularity according to
+ * {@link http://www.w3.org/TR/NOTE-datetime W3-DateTimes}.
+ *
+ * <blockquote><pre>
+ *   KorapDate kd = new KorapDate("2005-06-03");
+ *   System.err.println(kd.day());
+ *   // 3
+
+ *   kd = new KorapDate("2005-06");
+ *   System.err.println(kd.month());
+ *   // 6
+ * </pre></blockquote>
+ *
+ * @author diewald
  */
 public class KorapDate {
-    /*
-    protected char[] year  = new char[4];
-    protected char[] month = new char[2];
-    protected char[] day   = new char[2];
-    */
 
-    private int year = 0, month = 0, day = 0;
+    /**
+     * The year of the date.
+     */
+    public int year = 0;
 
+
+    /**
+     * The month of the date.
+     */
+    public int month = 0;
+
+
+    /**
+     * The day of the date.
+     */
+    public int day = 0;
+
+
+    // Date string regex pattern
     private static final Pattern datePattern = Pattern.compile(
-	"(\\d\\d\\d\\d)" +
-        "(?:[-/]?(\\d\\d)" +
-        "(?:[-/]?(\\d\\d))?)?"
+        "\\s*(\\d\\d\\d\\d)" +
+        "(?:\\s*[-/]?\\s*(\\d\\d)" +
+        "(?:\\s*[-/]?\\s*(\\d\\d))?)?\\s*"
     );
 
-    public static int END = 99_999_999;
-    public static int BEGINNING = 0;
+    /**
+     * Static value representing the minimum date.
+     */
+    public static final int BEGINNING = 0;
 
-    public KorapDate (String dateStr) {
-	if (dateStr == null || dateStr.isEmpty())
-	    return;
 
-	Matcher m = datePattern.matcher(dateStr);
-	if (m.matches()) {
-	    this.year = Integer.parseInt(m.group(1));
-	    if (m.group(2) != null)
-		this.month = Integer.parseInt(m.group(2));
-		if (m.group(3) != null)
-		    this.day   = Integer.parseInt(m.group(3));
-	}
-	else {
-	    return;
-	};
+    /**
+     * Static value representing the maximum date.
+     */
+    public static final int END = 99_999_999;
+
+
+    /**
+     * Construct a new KorapDate object.
+     */
+    public KorapDate () { };
+
+
+    /**
+     * Construct a new KorapDate object.
+     *
+     * @param date The date as a string (see synopsis).
+     */
+    public KorapDate (String date) {
+        if (date == null || date.isEmpty())
+            return;
+
+        // Use pattern to split string
+        Matcher m = datePattern.matcher(date);
+        if (m.matches()) {
+            this.year = Integer.parseInt(m.group(1));
+            if (m.group(2) != null)
+                this.month = Integer.parseInt(m.group(2));
+            if (m.group(3) != null)
+                this.day   = Integer.parseInt(m.group(3));
+        };
     };
 
-    private static int ceil (short padding, int nr) {
-	if (nr == 0) {
-	    if (padding == (short) 4) {
-		return 9999;
-	    }
-	    else if (padding == (short) 2) {
-		return 99;
-	    };
-	};
-	return nr;
-    };
 
-    // make yyyy???? become yyyy9999 and yyyymm?? yyyymm99
+    /**
+     * Get the date as an integer with ceiled values for
+     * undefined date segments.
+     *
+     * <blockquote><pre>
+     *   KorapDate kd = new KorapDate("2005-06");
+     *   System.err.println(kd.ceil());
+     *   // 20050699
+     * </pre></blockquote>
+     *
+     * @return ceiled integer value.
+     */
     public int ceil () {
-	return
-	    (ceil((short) 4, this.year) * 10_000) +
-	    (ceil((short) 2, this.month) * 100) +
-	    (ceil((short) 2, this.day));
+        return
+            (ceil((byte) 4, this.year) * 10_000) +
+            (ceil((byte) 2, this.month) * 100) +
+            (ceil((byte) 2, this.day));
     };
 
-    // make yyyy???? become yyyy0000 and yyyymm?? yyyymm00
+
+    /**
+     * Get the date as an integer with floored values for
+     * undefined date segments.
+     *
+     * <blockquote><pre>
+     *   KorapDate kd = new KorapDate("2005-06");
+     *   System.err.println(kd.floor());
+     *   // 20050600
+     * </pre></blockquote>
+     *
+     * @return floored integer value.
+     */
     public int floor () {
-	int floor = 0;
-	if (this.year == 0) {
-	    return 0;
-	}
-	else {
-	    floor = this.year * 10_000;
-	};
-	if (this.month == 0) {
-	    return floor;
-	}
-	else {
-	    floor += this.month * 100;
-	};
-	if (this.day == 0) {
-	    return floor;
-	};
-	return (floor + this.day);
+        int floor = 0;
+        if (this.year == 0)
+            return 0;
+
+        floor = this.year * 10_000;
+
+        if (this.month == 0)
+            return floor;
+
+        floor += this.month * 100;
+
+        if (this.day == 0)
+            return floor;
+
+        return (floor + this.day);
     };
 
 
-    public int year () {
-	return this.year;
-    };
-
-    public int month () {
-	return this.month;
-    };
-
-    public int day () {
-	return this.day;
-    };
-
-
+    /**
+     * Serialize date to string, appended by zeros,
+     * in the form of &quot;20050300&quot;.
+     *
+     * @return The date as a string.
+     */
     public String toString() {
-	StringBuilder sb = this.toStringBuilder();
-	if (sb.length() < 4)
-	    return null;
+        StringBuilder sb = this.toStringBuilder();
+        if (sb.length() < 4)
+            return null;
 
-	if (sb.length() < 8) {
-	    sb.append("00");
-	    if (sb.length() < 8) {
-		sb.append("00");
-	    };
-	};
+        if (sb.length() < 8) {
+            sb.append("00");
+            if (sb.length() < 8) {
+                sb.append("00");
+            };
+        };
 
-	return sb.toString();
+        return sb.toString();
     };
 
-    public String toDisplay() {
-	StringBuilder sb = this.toStringBuilder();
-	if (sb.length() == 8)
-	    sb.insert(6, '-');
 
-	if (sb.length() > 4)
-	    sb.insert(4, '-');
-
-	return sb.toString();
-    };
-
+    /**
+     * Serialize ceiled date to string.
+     *
+     * @return The date as a string.
+     */
     public String toCeilString() {
-	StringBuilder sb = new StringBuilder();
-	return sb.append(this.ceil()).toString();
+        StringBuilder sb = new StringBuilder();
+        return sb.append(this.ceil()).toString();
     };
 
+
+    /**
+     * Serialize floored date to string.
+     *
+     * @return The date as a string.
+     */
     public String toFloorString() {
-	StringBuilder sb = new StringBuilder();
-	return sb.append(this.floor()).toString();
+        StringBuilder sb = new StringBuilder();
+        return sb.append(this.floor()).toString();
     };
 
+
+    /**
+     * Serialize date to displayable string.
+     * See format description in the class description.
+     *
+     * @return The date as a string.
+     */
+    public String toDisplay() {
+        StringBuilder sb = this.toStringBuilder();
+        if (sb.length() == 8)
+            sb.insert(6, '-');
+
+        if (sb.length() > 4)
+            sb.insert(4, '-');
+
+        return sb.toString();
+    };
+
+
+
     // Format date as yyyymmdd
     private StringBuilder toStringBuilder () {
-	StringBuilder sb = new StringBuilder();
-	if (this.year != 0) {
+        StringBuilder sb = new StringBuilder();
 
-	    // Append year
-	    if (this.year < 100)
-		sb.append("20");
+        if (this.year != 0) {
 
-	    sb.append(this.year);
+            // Append year
+            if (this.year < 100)
+                sb.append("20");
+
+            sb.append(this.year);
 	    
-	    if (this.month != 0) {
+            if (this.month != 0) {
+                
+                // Append month
+                if (this.month < 10)
+                    sb.append('0');
 
-		// Append month
-		if (this.month < 10)
-		    sb.append('0');
-		sb.append(this.month);
+                sb.append(this.month);
 
-		if (this.day != 0) {
-		    // Append month
-		    if (this.day < 10)
-			sb.append('0');
-		    sb.append(this.day);
-		};
-	    };
-	};
-	return sb;
+                if (this.day != 0) {
+                    // Append month
+                    if (this.day < 10)
+                        sb.append('0');
+
+                    sb.append(this.day);
+                };
+            };
+        };
+        return sb;
+    };
+
+
+    // Ceil method
+    private static int ceil (byte padding, int nr) {
+        if (nr == 0) {
+            if (padding == (byte) 4)
+                return 9999;
+            else if (padding == (byte) 2)
+                return 99;
+        };
+        return nr;
     };
 };
diff --git a/src/main/java/de/ids_mannheim/korap/util/KorapHTML.java b/src/main/java/de/ids_mannheim/korap/util/KorapHTML.java
deleted file mode 100644
index cadbb11..0000000
--- a/src/main/java/de/ids_mannheim/korap/util/KorapHTML.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package de.ids_mannheim.korap.util;
-
-/**
- * @author Nils Diewald
- *
- * A collection of methods to deal with Bytes and Byte arrays.
- */
-public class KorapHTML {
-
-    /**
-     * Encode a string HTML secure.
-     *
-     * @param text The string to encode.
-     */
-    public static String encodeHTML (String text) {
-	return
-	    text.replace("&", "&amp;")
-	    .replace("<", "&lt;")
-	    .replace(">", "&gt;")
-	    .replace("\"", "&quot;");
-    };
-};
diff --git a/src/main/java/de/ids_mannheim/korap/util/KorapString.java b/src/main/java/de/ids_mannheim/korap/util/KorapString.java
index 2922425..a775dea 100644
--- a/src/main/java/de/ids_mannheim/korap/util/KorapString.java
+++ b/src/main/java/de/ids_mannheim/korap/util/KorapString.java
@@ -7,26 +7,50 @@
 import java.nio.charset.StandardCharsets;
 
 /**
- * @author Nils Diewald
+ * A collection of string related utility
+ * functions.
  *
- * A collection of methods to deal with Strings.
+ * @author diewald
  */
 public class KorapString {
 
     /**
-     * Get String from file
+     * Get String from file.
+     *
+     * @param path The path of the file represented as a string. 
+     * @param path The expected {@link Charset}. 
+     * @return The content of the file
+     * @throws IOException
      */
     public static String StringfromFile (String path, Charset encoding)
-	throws IOException {
-	byte[] encoded = Files.readAllBytes(Paths.get(path));
-	return new String(encoded, encoding);
+        throws IOException {
+        byte[] encoded = Files.readAllBytes(Paths.get(path));
+        return new String(encoded, encoding);
     };
 
 
     /**
-     * Get String from file
+     * Get String from file (expecting UTF-8).
+     *
+     * @param path The path of the file represented as a string. 
+     * @return The content of the file
+     * @throws IOException
      */
     public static String StringfromFile (String path) throws IOException {
-	return StringfromFile(path, StandardCharsets.UTF_8);
+        return StringfromFile(path, StandardCharsets.UTF_8);
+    };
+
+
+    /**
+     * Escape HTML relevant characters as entities.
+     *
+     * @param text The string to escape.
+     * @return The secured string.
+     */
+    public static String escapeHTML (String text) {
+        return text.replace("&", "&amp;")
+            .replace("<", "&lt;")
+            .replace(">", "&gt;")
+            .replace("\"", "&quot;");
     };
 };
diff --git a/src/main/java/de/ids_mannheim/korap/util/QueryException.java b/src/main/java/de/ids_mannheim/korap/util/QueryException.java
index dc9d002..7dca966 100644
--- a/src/main/java/de/ids_mannheim/korap/util/QueryException.java
+++ b/src/main/java/de/ids_mannheim/korap/util/QueryException.java
@@ -1,36 +1,81 @@
 package de.ids_mannheim.korap.util;
 
+/**
+ * Exception class for query processing problems.
+ *
+ * @author diewald
+ */
 public class QueryException extends Exception {
 	
-  int errorCode;
+    private int errorCode = 0;
   
-  public QueryException() {
-      super();
-  }
+    /**
+     * Construct a new QueryException.
+     */
+    public QueryException() {
+        super();
+    };
 
-  public QueryException(String message) {
-      super(message);
-  }
 
-  public QueryException(String message, Throwable cause) {
-      super(message, cause);
-  };
+    /**
+     * Construct a new QueryException.
+     *
+     * @param message Exception message.
+     */
+    public QueryException (String message) {
+        super(message);
+    };
 
-  public QueryException(Throwable cause) {
-      super(cause);
-  };  
+
+    /**
+     * Construct a new QueryException.
+     *
+     * @param code An integer value as an error code.
+     * @param message Exception message.
+     */
+    public QueryException (int code, String message) {	  
+        super(message);
+        this.setErrorCode(code);      
+    };
+
+
+    /**
+     * Construct a new QueryException.
+     *
+     * @param message Exception message.
+     * @param cause A {@link Throwable} object.
+     */
+    public QueryException (String message, Throwable cause) {
+        super(message, cause);
+    };
+
+
+    /**
+     * Construct a new QueryException.
+     *
+     * @param cause A {@link Throwable} object.
+     */    
+    public QueryException (Throwable cause) {
+        super(cause);
+    };  
   
-  public QueryException(int code, String message) {	  
-	  super(message);
-	  setErrorCode(code);      
-  }
 
-  public int getErrorCode() {
-	return errorCode;
-  }
+    /**
+     * Get the error code of the exception.
+     *
+     * @return The error code of the exception as an integer.
+     */
+    public int getErrorCode() {
+        return this.errorCode;
+    };
 
-  public void setErrorCode(int errorCode) {
-	this.errorCode = errorCode;
-  }
 
+    /**
+     * Set the error code of the exception.
+     *
+     * @param code The error code of the exception as an integer.
+     */
+    public void setErrorCode (int code) {
+        this.errorCode = code;
+    };
 };
diff --git a/src/test/java/de/ids_mannheim/korap/util/TestArray.java b/src/test/java/de/ids_mannheim/korap/util/TestArray.java
deleted file mode 100644
index a1935e1..0000000
--- a/src/test/java/de/ids_mannheim/korap/util/TestArray.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package de.ids_mannheim.korap.util;
-
-import java.util.*;
-import static de.ids_mannheim.korap.util.KorapArray.*;
-
-import static org.junit.Assert.*;
-import org.junit.Test;
-import org.junit.Ignore;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-
-@RunWith(JUnit4.class)
-public class TestArray {
-
-    @Test
-    public void StringJoin1 () {
-	String[] test = new String[]{"a", "bc", "def"};
-	assertEquals(join(",", test), "a,bc,def");
-    };
-
-    @Test
-    public void StringJoin2 () {
-	assertEquals(join(",", "a", "bc", "def"), "a,bc,def");
-    };
-
-    @Test
-    public void StringJoin3 () {
-	assertEquals(join(',', "a", "bc", "def"), "a,bc,def");
-    };
-
-    @Test
-    public void StringJoin4 () {
-	assertEquals(join("--", "a", "bc", "def"), "a--bc--def");
-    };
-
-
-};
diff --git a/src/test/java/de/ids_mannheim/korap/util/TestKorapArray.java b/src/test/java/de/ids_mannheim/korap/util/TestKorapArray.java
new file mode 100644
index 0000000..5763a5d
--- /dev/null
+++ b/src/test/java/de/ids_mannheim/korap/util/TestKorapArray.java
@@ -0,0 +1,38 @@
+package de.ids_mannheim.korap.util;
+
+import java.util.*;
+import static de.ids_mannheim.korap.util.KorapArray.*;
+
+import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.Ignore;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * @author diewald
+ */
+@RunWith(JUnit4.class)
+public class TestKorapArray {
+
+    @Test
+    public void StringJoin1 () {
+        String[] test = new String[]{"a", "bc", "def"};
+        assertEquals(join(",", test), "a,bc,def");
+    };
+
+    @Test
+    public void StringJoin2 () {
+        assertEquals(join(",", "a", "bc", "def"), "a,bc,def");
+    };
+
+    @Test
+    public void StringJoin3 () {
+        assertEquals(join(',', "a", "bc", "def"), "a,bc,def");
+    };
+
+    @Test
+    public void StringJoin4 () {
+        assertEquals(join("--", "a", "bc", "def"), "a--bc--def");
+    };
+};
diff --git a/src/test/java/de/ids_mannheim/korap/util/TestKorapByte.java b/src/test/java/de/ids_mannheim/korap/util/TestKorapByte.java
new file mode 100644
index 0000000..e106699
--- /dev/null
+++ b/src/test/java/de/ids_mannheim/korap/util/TestKorapByte.java
@@ -0,0 +1,33 @@
+package de.ids_mannheim.korap.util;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+
+import static de.ids_mannheim.korap.util.KorapByte.*;
+import de.ids_mannheim.korap.util.QueryException;
+import java.nio.ByteBuffer;
+
+/**
+ * @author diewald
+ */
+public class TestKorapByte {
+
+    @Test
+    public void testConversion() {
+        assertEquals(4, byte2int(int2byte(4)));
+        assertEquals(
+            byte2int(ByteBuffer.allocate(4).putInt(4).array()),
+            byte2int(int2byte(4))
+        );
+
+        assertEquals(
+            byte2int(ByteBuffer.allocate(4).putInt(99999).array()),
+            byte2int(int2byte(99999))
+        );
+
+        assertEquals(128, byte2int(int2byte(128)));
+        assertEquals(1024, byte2int(int2byte(1024)));
+        assertEquals(66_666, byte2int(int2byte(66_666)));
+        assertEquals(66_666, byte2int(int2byte(66_666)), 0);
+    };
+};
diff --git a/src/test/java/de/ids_mannheim/korap/util/TestKorapDate.java b/src/test/java/de/ids_mannheim/korap/util/TestKorapDate.java
new file mode 100644
index 0000000..5407e9f
--- /dev/null
+++ b/src/test/java/de/ids_mannheim/korap/util/TestKorapDate.java
@@ -0,0 +1,210 @@
+package de.ids_mannheim.korap.util;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+
+import de.ids_mannheim.korap.util.KorapDate;
+import de.ids_mannheim.korap.util.QueryException;
+
+/**
+ * @author diewald
+ */
+public class TestKorapDate {
+
+    @Test
+    public void testByString() {
+        KorapDate kd = new KorapDate("2005-06-03");
+        assertEquals(2005, kd.year);
+        assertEquals(6, kd.month);
+        assertEquals(3, kd.day);
+
+        kd = new KorapDate("2005-06");
+        assertEquals(2005, kd.year);
+        assertEquals(6, kd.month);
+        assertEquals(0, kd.day);
+
+        kd = new KorapDate("2005");
+        assertEquals(2005, kd.year);
+        assertEquals(0, kd.month);
+        assertEquals(0, kd.day);
+
+        kd = new KorapDate();
+        assertEquals(0, kd.year);
+        assertEquals(0, kd.month);
+        assertEquals(0, kd.day);
+
+        kd = new KorapDate("hui");
+        assertEquals(0, kd.year);
+        assertEquals(0, kd.month);
+        assertEquals(0, kd.day);
+
+        kd = new KorapDate("9999-99-99");
+        assertEquals(9999, kd.year);
+        assertEquals(99, kd.month);
+        assertEquals(99, kd.day);
+    };
+
+
+    @Test
+    public void testWithCeil() {
+        KorapDate kd = new KorapDate("2005-06-03");
+        assertEquals(2005, kd.year);
+        assertEquals(6, kd.month);
+        assertEquals(3, kd.day);
+        assertEquals(20050603, kd.ceil());
+
+        kd = new KorapDate("2005-06");
+        assertEquals(2005, kd.year);
+        assertEquals(6, kd.month);
+        assertEquals(0, kd.day);
+        assertEquals(20050699, kd.ceil());
+
+        kd = new KorapDate("2005");
+        assertEquals(2005, kd.year);
+        assertEquals(0, kd.month);
+        assertEquals(0, kd.day);
+        assertEquals(20059999, kd.ceil());
+
+        kd = new KorapDate();
+        assertEquals(0, kd.year);
+        assertEquals(0, kd.month);
+        assertEquals(0, kd.day);
+        assertEquals(99999999, kd.ceil());
+    };
+
+    @Test
+    public void testWithFloor() {
+        KorapDate kd = new KorapDate("2005-06-03");
+        assertEquals(2005, kd.year);
+        assertEquals(6, kd.month);
+        assertEquals(3, kd.day);
+        assertEquals(20050603, kd.floor());
+
+        kd = new KorapDate("2005-06");
+        assertEquals(2005, kd.year);
+        assertEquals(6, kd.month);
+        assertEquals(0, kd.day);
+        assertEquals(20050600, kd.floor());
+
+        kd = new KorapDate("2005");
+        assertEquals(2005, kd.year);
+        assertEquals(0, kd.month);
+        assertEquals(0, kd.day);
+        assertEquals(20050000, kd.floor());
+
+        kd = new KorapDate();
+        assertEquals(0, kd.year);
+        assertEquals(0, kd.month);
+        assertEquals(0, kd.day);
+        assertEquals(0, kd.floor());
+    };
+
+    @Test
+    public void testToString() {
+        KorapDate kd = new KorapDate("2005-06-03");
+        assertEquals(2005, kd.year);
+        assertEquals(6, kd.month);
+        assertEquals(3, kd.day);
+        assertEquals("20050603", kd.toString());
+
+        kd = new KorapDate("2005-06");
+        assertEquals(2005, kd.year);
+        assertEquals(6, kd.month);
+        assertEquals(0, kd.day);
+        assertEquals("20050600", kd.toString());
+
+        kd = new KorapDate("2005");
+        assertEquals(2005, kd.year);
+        assertEquals(0, kd.month);
+        assertEquals(0, kd.day);
+        assertEquals("20050000", kd.toString());
+
+        kd = new KorapDate();
+        assertEquals(0, kd.year);
+        assertEquals(0, kd.month);
+        assertEquals(0, kd.day);
+        assertEquals(null, kd.toString());
+    };
+
+    @Test
+    public void testToCeilString() {
+        KorapDate kd = new KorapDate("2005-06-03");
+        assertEquals(2005, kd.year);
+        assertEquals(6, kd.month);
+        assertEquals(3, kd.day);
+        assertEquals("20050603", kd.toCeilString());
+
+        kd = new KorapDate("2005-06");
+        assertEquals(2005, kd.year);
+        assertEquals(6, kd.month);
+        assertEquals(0, kd.day);
+        assertEquals("20050699", kd.toCeilString());
+
+        kd = new KorapDate("2005");
+        assertEquals(2005, kd.year);
+        assertEquals(0, kd.month);
+        assertEquals(0, kd.day);
+        assertEquals("20059999", kd.toCeilString());
+
+        kd = new KorapDate();
+        assertEquals(0, kd.year);
+        assertEquals(0, kd.month);
+        assertEquals(0, kd.day);
+        assertEquals("99999999", kd.toCeilString());
+    };
+
+
+    @Test
+    public void testToFloorString() {
+        KorapDate kd = new KorapDate("2005-06-03");
+        assertEquals(2005, kd.year);
+        assertEquals(6, kd.month);
+        assertEquals(3, kd.day);
+        assertEquals("20050603", kd.toFloorString());
+
+        kd = new KorapDate("2005-06");
+        assertEquals(2005, kd.year);
+        assertEquals(6, kd.month);
+        assertEquals(0, kd.day);
+        assertEquals("20050600", kd.toFloorString());
+
+        kd = new KorapDate("2005");
+        assertEquals(2005, kd.year);
+        assertEquals(0, kd.month);
+        assertEquals(0, kd.day);
+        assertEquals("20050000", kd.toFloorString());
+
+        kd = new KorapDate();
+        assertEquals(0, kd.year);
+        assertEquals(0, kd.month);
+        assertEquals(0, kd.day);
+        assertEquals("0", kd.toFloorString());
+    };
+
+    @Test
+    public void testDisplay () {
+        KorapDate kd = new KorapDate("2005-06-03");
+        assertEquals(2005, kd.year);
+        assertEquals(6, kd.month);
+        assertEquals(3, kd.day);
+        assertEquals("2005-06-03", kd.toDisplay());
+
+        kd = new KorapDate("2005-06");
+        assertEquals(2005, kd.year);
+        assertEquals(6, kd.month);
+        assertEquals(0, kd.day);
+        assertEquals("2005-06", kd.toDisplay());
+
+        kd = new KorapDate("2005");
+        assertEquals(2005, kd.year);
+        assertEquals(0, kd.month);
+        assertEquals(0, kd.day);
+        assertEquals("2005", kd.toDisplay());
+
+        kd = new KorapDate();
+        assertEquals(0, kd.year);
+        assertEquals(0, kd.month);
+        assertEquals(0, kd.day);
+        assertEquals("", kd.toDisplay());
+    };
+};
diff --git a/src/test/java/de/ids_mannheim/korap/util/TestKorapString.java b/src/test/java/de/ids_mannheim/korap/util/TestKorapString.java
new file mode 100644
index 0000000..38d3a35
--- /dev/null
+++ b/src/test/java/de/ids_mannheim/korap/util/TestKorapString.java
@@ -0,0 +1,22 @@
+package de.ids_mannheim.korap.util;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+
+import static de.ids_mannheim.korap.util.KorapString.*;
+import de.ids_mannheim.korap.util.QueryException;
+
+/**
+ * @author diewald
+ */
+public class TestKorapString {
+
+    @Test
+    public void testHTMLescape() {
+        assertEquals("Der &amp; Die", escapeHTML("Der & Die"));
+        assertEquals("Der &amp; Die &amp;", escapeHTML("Der & Die &"));
+        assertEquals("&lt;x&gt;Hui&lt;/x&gt;", escapeHTML("<x>Hui</x>"));
+        assertEquals("Er sagte: &quot;Das ist ja toll!&quot;",
+                     escapeHTML("Er sagte: \"Das ist ja toll!\""));
+    };
+};