Integrated lite and full services and controllers in core.

Change-Id: I34914c89c2266fa02bee1a5b0522c46139b13966
diff --git a/core/Changes b/core/Changes
index 68eb797..be27ad5 100644
--- a/core/Changes
+++ b/core/Changes
@@ -1,3 +1,7 @@
+version 0.61.4
+14/11/2018
+   - Integrated lite and full services and controllers in core (margaretha)
+
 version 0.61.3
 22/10/2018
    - Updated jetty, spring and hibernate versions (margaretha)
diff --git a/core/pom.xml b/core/pom.xml
index abe02bb..253b616 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -3,7 +3,7 @@
 	<modelVersion>4.0.0</modelVersion>
 	<groupId>de.ids_mannheim.korap</groupId>
 	<artifactId>Kustvakt-core</artifactId>
-	<version>0.61.3</version>
+	<version>0.61.4</version>
 
 	<properties>
 		<java.version>1.8</java.version>
@@ -17,36 +17,14 @@
 		<resources>
 			<resource>
 				<directory>src/main/resources</directory>
-				<filtering>true</filtering>
-				<includes>
-					<include>**/*.info</include>
-					<include>**/*.xml</include>
-					<include>**/*.conf</include>
-					<include>**/*.kustvakt</include>
-					<include>**/*.properties</include>
-					<include>**/*.sql</include>
-				</includes>
 			</resource>
 		</resources>
 		<testResources>
 			<testResource>
 				<directory>src/test/resources</directory>
-				<filtering>true</filtering>
-				<includes>
-					<include>**/*.prop</include>
-					<include>**/*.xml</include>
-					<include>**/*.conf</include>
-					<include>**/*.info</include>
-					<include>**/*.properties</include>
-				</includes>
 			</testResource>
 			<testResource>
 				<directory>src/main/resources</directory>
-				<filtering>true</filtering>
-				<includes>
-					<include>**/*.info</include>
-					<include>**/*.properties</include>
-				</includes>
 			</testResource>
 		</testResources>
 		<plugins>
@@ -73,12 +51,20 @@
 					<compilerVersion>${java.version}</compilerVersion>
 					<source>${java.version}</source>
 					<target>${java.version}</target>
+					<processors>
+						<processor>lombok.launch.AnnotationProcessorHider$AnnotationProcessor</processor>
+						<processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
+					</processors>
 				</configuration>
 			</plugin>
 
 			<!-- build tests jar, so extensions can use fastjerseytest class to build 
 				rest tests -->
-			<!-- <plugin>
+			<!-- <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> 
+				<version>3.0.1</version> <executions> <execution> <id>attach-sources</id> 
+				<goals> <goal>jar</goal> </goals> </execution> </executions> </plugin> -->
+			<!-- Generate source jar -->
+			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
 				<artifactId>maven-source-plugin</artifactId>
 				<version>3.0.1</version>
@@ -90,43 +76,17 @@
 						</goals>
 					</execution>
 				</executions>
-			</plugin> -->
-			<!-- Generate source jar -->
-		    <plugin>
-		      <groupId>org.apache.maven.plugins</groupId>
-		      <artifactId>maven-source-plugin</artifactId>
-		      <version>3.0.1</version>
-		      <executions>
-		        <execution>
-		          <id>attach-sources</id>
-		          <goals>
-		            <goal>jar</goal>
-		          </goals>
-		        </execution>
-		      </executions>
-		    </plugin>
-			<!-- <plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-surefire-plugin</artifactId>
-				<version>2.20.1</version>
-
-				<configuration>
-					<reuseForks>false</reuseForks>
-					<forkCount>2</forkCount>
-					<threadCount>10</threadCount>
-					<argLine>-Xmx1024m -XX:MaxPermSize=256m</argLine>
-
-					<excludes>
-						<exclude>**/*APITest.java</exclude>
-					</excludes>
-					<includes>
-						<include>de/ids_mannheim/korap/**/*.java</include>
-					</includes>
-				</configuration>
-			</plugin> -->
+			</plugin>
+			<!-- <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> 
+				<version>2.20.1</version> <configuration> <reuseForks>false</reuseForks> 
+				<forkCount>2</forkCount> <threadCount>10</threadCount> <argLine>-Xmx1024m 
+				-XX:MaxPermSize=256m</argLine> <excludes> <exclude>**/*APITest.java</exclude> 
+				</excludes> <includes> <include>de/ids_mannheim/korap/**/*.java</include> 
+				</includes> </configuration> </plugin> -->
 		</plugins>
 	</build>
 	<dependencies>
+		<!-- Jersey -->
 		<dependency>
 			<groupId>com.sun.jersey</groupId>
 			<artifactId>jersey-bundle</artifactId>
@@ -170,20 +130,27 @@
 				</exclusion>
 			</exclusions>
 		</dependency>
-		<!-- EM:done -->
+
+		<!-- JSON -->
 		<dependency>
-			<groupId>com.sun.jersey.jersey-test-framework</groupId>
-			<artifactId>jersey-test-framework-core</artifactId>
+			<groupId>com.sun.jersey</groupId>
+			<artifactId>jersey-json</artifactId>
 			<version>${jersey.version}</version>
-			<scope>test</scope>
 		</dependency>
 		<dependency>
-			<groupId>com.sun.jersey.jersey-test-framework</groupId>
-			<artifactId>jersey-test-framework-grizzly</artifactId>
-			<version>${jersey.version}</version>
-			<scope>test</scope>
+			<groupId>net.minidev</groupId>
+			<artifactId>json-smart</artifactId>
+			<version>1.0.9</version>
 		</dependency>
-		<!-- EM: Logging -->
+
+		<!-- Flyway -->
+		<dependency>
+			<groupId>org.flywaydb</groupId>
+			<artifactId>flyway-core</artifactId>
+			<version>4.0</version>
+		</dependency>
+
+		<!-- Logging -->
 		<dependency>
 			<groupId>org.apache.logging.log4j</groupId>
 			<artifactId>log4j-api</artifactId>
@@ -195,26 +162,36 @@
 			<version>2.11.0</version>
 		</dependency>
 		<dependency>
-		    <groupId>org.apache.logging.log4j</groupId>
-		    <artifactId>log4j-slf4j-impl</artifactId>
-		    <version>2.11.0</version>
+			<groupId>org.apache.logging.log4j</groupId>
+			<artifactId>log4j-slf4j-impl</artifactId>
+			<version>2.11.0</version>
 		</dependency>
 		<dependency>
-		    <groupId>org.apache.logging.log4j</groupId>
-		    <artifactId>log4j-jul</artifactId>
-		    <version>2.11.0</version>
-		    <exclusions>
-		    	<exclusion>
+			<groupId>org.apache.logging.log4j</groupId>
+			<artifactId>log4j-jul</artifactId>
+			<version>2.11.0</version>
+			<exclusions>
+				<exclusion>
 					<groupId>org.slf4j</groupId>
 					<artifactId>slf4j-api</artifactId>
 				</exclusion>
-		    </exclusions>
+			</exclusions>
 		</dependency>
 		<dependency>
 			<groupId>org.slf4j</groupId>
 			<artifactId>slf4j-api</artifactId>
-		    <version>1.7.25</version>
+			<version>1.7.25</version>
 		</dependency>
+		
+		<!-- Java Assist -->
+		<dependency>
+			<groupId>org.javassist</groupId>
+			<artifactId>javassist</artifactId>
+			<version>3.22.0-GA</version>
+		</dependency>
+
+		<!-- EM:done -->
+
 		<dependency>
 			<groupId>junit</groupId>
 			<artifactId>junit</artifactId>
@@ -233,7 +210,7 @@
 		<dependency>
 			<groupId>de.ids_mannheim.korap</groupId>
 			<artifactId>Koral</artifactId>
-			<version>0.31</version>
+			<version>[0.31,)</version>
 			<exclusions>
 				<exclusion>
 					<groupId>org.eclipse.jetty</groupId>
@@ -285,7 +262,7 @@
 		<dependency>
 			<groupId>de.ids_mannheim.korap</groupId>
 			<artifactId>Krill</artifactId>
-			<version>0.58.1</version>
+			<version>[0.58.1,)</version>
 			<exclusions>
 				<exclusion>
 					<groupId>org.xerial</groupId>
@@ -314,6 +291,8 @@
 			<artifactId>reflections</artifactId>
 			<version>0.9.10</version>
 		</dependency>
+
+		<!-- Spring -->
 		<dependency>
 			<groupId>org.springframework</groupId>
 			<artifactId>spring-core</artifactId>
@@ -334,6 +313,27 @@
 			<artifactId>spring-orm</artifactId>
 			<version>${spring-framework.version}</version>
 		</dependency>
+
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-jdbc</artifactId>
+			<version>${spring-framework.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-tx</artifactId>
+			<version>${spring-framework.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.security</groupId>
+			<artifactId>spring-security-core</artifactId>
+			<version>${spring-framework.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.security</groupId>
+			<artifactId>spring-security-web</artifactId>
+			<version>${spring-framework.version}</version>
+		</dependency>
 		<!-- EM: done -->
 		<dependency>
 			<groupId>org.springframework</groupId>
@@ -407,34 +407,15 @@
 			<version>3.2.1</version>
 		</dependency>
 
-		<!-- not part of public release
-		<dependency>
-			<groupId>KorAP-graphDB</groupId>
-			<artifactId>KorAP-graphDB</artifactId>
-			<version>1.0-SNAPSHOT</version>
-			<exclusions>
-				<exclusion>
-					<groupId>org.antlr</groupId>
-					<artifactId>antlr4-runtime</artifactId>
-				</exclusion>
-				<exclusion>
-					<groupId>org.glassfish.jersey.core</groupId>
-					<artifactId>jersey-client</artifactId>
-				</exclusion>
-				<exclusion>
-					<groupId>org.glassfish.jersey.containers</groupId>
-					<artifactId>jersey-container-grizzly2-http</artifactId>
-				</exclusion>
-				<exclusion>
-					<groupId>org.glassfish.jersey.core</groupId>
-					<artifactId>jersey-common</artifactId>
-				</exclusion>
-				<exclusion>
-					<groupId>org.glassfish.jersey.core</groupId>
-					<artifactId>jersey-server</artifactId>
-				</exclusion>
-			</exclusions>
-		</dependency> -->
+		<!-- not part of public release <dependency> <groupId>KorAP-graphDB</groupId> 
+			<artifactId>KorAP-graphDB</artifactId> <version>1.0-SNAPSHOT</version> <exclusions> 
+			<exclusion> <groupId>org.antlr</groupId> <artifactId>antlr4-runtime</artifactId> 
+			</exclusion> <exclusion> <groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-client</artifactId> 
+			</exclusion> <exclusion> <groupId>org.glassfish.jersey.containers</groupId> 
+			<artifactId>jersey-container-grizzly2-http</artifactId> </exclusion> <exclusion> 
+			<groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-common</artifactId> 
+			</exclusion> <exclusion> <groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-server</artifactId> 
+			</exclusion> </exclusions> </dependency> -->
 		<dependency>
 			<groupId>org.apache.httpcomponents</groupId>
 			<artifactId>httpclient</artifactId>
@@ -446,12 +427,20 @@
 			<version>2.6</version>
 		</dependency>
 
+		<!-- Hibernate -->
 		<dependency>
 			<groupId>org.hibernate</groupId>
 			<artifactId>hibernate-ehcache</artifactId>
 			<version>${hibernate.version}</version>
 		</dependency>
 		<dependency>
+			<groupId>org.hibernate</groupId>
+			<artifactId>hibernate-jpamodelgen</artifactId>
+			<version>${hibernate.version}</version>
+			<scope>provided</scope>
+		</dependency>
+		
+		<dependency>
 			<groupId>javax.servlet</groupId>
 			<artifactId>javax.servlet-api</artifactId>
 			<version>4.0.1</version>
diff --git a/core/src/main/java/de/ids_mannheim/de/init/Initializator.java b/core/src/main/java/de/ids_mannheim/de/init/Initializator.java
new file mode 100644
index 0000000..0ef9dbb
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/de/init/Initializator.java
@@ -0,0 +1,19 @@
+package de.ids_mannheim.de.init;
+
+import java.io.IOException;
+
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.util.QueryException;
+
+/** Init methods run after spring dependency injection 
+ *  
+ * @author margaretha
+ *
+ */
+public interface Initializator {
+
+    void init () throws IOException, QueryException, KustvaktException;
+
+    void initTest () throws IOException, KustvaktException;
+
+}
\ No newline at end of file
diff --git a/core/src/main/java/de/ids_mannheim/korap/annotation/AnnotationParser.java b/core/src/main/java/de/ids_mannheim/korap/annotation/AnnotationParser.java
new file mode 100644
index 0000000..b6fd448
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/annotation/AnnotationParser.java
@@ -0,0 +1,241 @@
+package de.ids_mannheim.korap.annotation;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.stereotype.Component;
+
+import de.ids_mannheim.korap.constant.AnnotationType;
+import de.ids_mannheim.korap.dao.AnnotationDao;
+import de.ids_mannheim.korap.entity.Annotation;
+import de.ids_mannheim.korap.entity.AnnotationKey;
+import de.ids_mannheim.korap.entity.AnnotationLayer;
+
+@Component
+public class AnnotationParser {
+
+    private Logger log = LogManager.getLogger(AnnotationDao.class);
+
+    public static final Pattern quotePattern = Pattern.compile("\"([^\"]*)\"");
+
+    @Autowired
+    private AnnotationDao annotationDao;
+
+    private Annotation foundry = null;
+    private AnnotationLayer layer = null;
+    private AnnotationKey key = null;
+
+    private Set<AnnotationKey> keys = new HashSet<>();
+    private Set<Annotation> values = new HashSet<>();
+
+    public void run () throws IOException {
+        PathMatchingResourcePatternResolver resolver =
+                new PathMatchingResourcePatternResolver(
+                        getClass().getClassLoader());
+        Resource[] resources = resolver
+                .getResources("classpath:annotation-scripts/foundries/*.js");
+
+        if (resources.length < 1) return;
+
+        for (Resource r : resources) {
+            log.debug(r.getFilename());
+            readFile(r.getInputStream());
+        }
+    }
+
+    private void readFile (InputStream inputStream) throws IOException {
+        BufferedReader br =
+                new BufferedReader(new InputStreamReader(inputStream), 1024);
+
+        foundry = null;
+
+        String line, annotationCode = "", annotationType = "";
+        Matcher m;
+        ArrayList<String> array;
+        while ((line = br.readLine()) != null) {
+            line = line.trim();
+            if (line.startsWith("ah")) {
+                m = quotePattern.matcher(line);
+                if (m.find()) {
+                    annotationCode = m.group(1);
+                    annotationType = computeAnnotationType(annotationCode);
+                }
+                m.reset();
+            }
+            else if (line.startsWith("];")) {
+                if (!keys.isEmpty()) {
+                    layer.setKeys(keys);
+                    annotationDao.updateAnnotationLayer(layer);
+                }
+                if (!values.isEmpty()) {
+                    key.setValues(values);
+                    annotationDao.updateAnnotationKey(key);
+                }
+                keys.clear();
+                values.clear();
+                layer = null;
+                key = null;
+            }
+            else if (line.startsWith("[")) {
+                array = computeValues(line);
+                parseArray(annotationCode, annotationType, array);
+            }
+
+        }
+        br.close();
+    }
+
+    public static ArrayList<String> computeValues (String line) {
+        ArrayList<String> values;
+        Matcher m = quotePattern.matcher(line);
+        values = new ArrayList<String>();
+        while (m.find()) {
+            values.add(m.group(1));
+        }
+        return values;
+    }
+
+    private void parseArray (String annotationCode, String annotationType,
+            ArrayList<String> array) {
+        if (annotationType.equals(AnnotationType.FOUNDRY)) {
+            String code = array.get(1).substring(0, array.get(1).length() - 1);
+            foundry = retrieveOrCreateAnnotation(code, AnnotationType.FOUNDRY,
+                    null, array.get(0));
+        }
+        else if (annotationType.equals(AnnotationType.LAYER)) {
+            String code = array.get(1);
+            if (code.endsWith("=")) {
+                code = code.substring(0, code.length() - 1);
+            }
+            Annotation layer = retrieveOrCreateAnnotation(code, annotationType,
+                    null, array.get(0));
+            try {
+                AnnotationLayer annotationLayer =
+                        annotationDao.retrieveAnnotationLayer(foundry.getCode(),
+                                layer.getCode());
+                if (annotationLayer == null) {
+                    annotationDao.createAnnotationLayer(foundry, layer);
+                }
+            }
+            catch (Exception e) {
+                log.debug("Duplicate annotation layer: " + foundry.getCode()
+                        + "/" + layer.getCode());
+            }
+        }
+        else if (annotationType.equals(AnnotationType.KEY))
+
+        {
+            if (layer == null) {
+                computeLayer(annotationCode);
+            }
+
+            Annotation annotation = null;
+            if (array.size() == 2) {
+                String code = array.get(1);
+                if (code.endsWith("=") || code.endsWith(":")) {
+                    code = code.substring(0, code.length() - 1);
+                }
+                annotation = retrieveOrCreateAnnotation(code, annotationType,
+                        null, array.get(0));
+            }
+            else if (array.size() == 3) {
+                annotation = retrieveOrCreateAnnotation(array.get(0),
+                        annotationType, array.get(1), array.get(2));
+            }
+            if (annotation != null) {
+                AnnotationKey annotationKey =
+                        annotationDao.retrieveAnnotationKey(layer, annotation);
+                if (annotationKey == null) {
+                    annotationDao.createAnnotationKey(layer, annotation);
+                }
+                this.keys.add(annotationKey);
+            }
+        }
+        else if (annotationType.equals(AnnotationType.VALUE)) {
+            if (this.key == null) {
+                computeKey(annotationCode);
+            }
+            Annotation value = retrieveOrCreateAnnotation(array.get(0),
+                    AnnotationType.VALUE, array.get(1), array.get(2));
+            if (value != null) {
+                values.add(value);
+            }
+        }
+    }
+
+    private void computeKey (String code) {
+        String[] codes = code.split("=");
+        if (codes.length > 1) {
+            computeLayer(codes[0]);
+            String keyCode = codes[1];
+            if (keyCode.endsWith(":") || keyCode.endsWith("-")) {
+                keyCode = keyCode.substring(0, keyCode.length() - 1);
+            }
+            Annotation key = annotationDao.retrieveAnnotation(keyCode,
+                    AnnotationType.KEY);
+            this.key = annotationDao.retrieveAnnotationKey(layer, key);
+        }
+
+    }
+
+    private void computeLayer (String code) {
+        String[] codes = code.split("/");
+        if (codes.length > 1) {
+            String layerCode = codes[1];
+            if (layerCode.endsWith("=")) {
+                layerCode = layerCode.substring(0, layerCode.length() - 1);
+            }
+            this.layer =
+                    annotationDao.retrieveAnnotationLayer(codes[0], layerCode);
+            if (layer == null) {
+                log.warn("Layer is null for " + code);
+            }
+        }
+    }
+
+    private Annotation retrieveOrCreateAnnotation (String code, String type,
+            String text, String description) {
+        Annotation annotation = annotationDao.retrieveAnnotation(code, type);
+        if (annotation == null) {
+            annotation = annotationDao.createAnnotation(code, type, text,
+                    description);
+        }
+        return annotation;
+    }
+
+    private String computeAnnotationType (String code) {
+        String[] codes = code.split("/");
+        if (codes.length == 1) {
+            if (codes[0].equals("-")) {
+                return AnnotationType.FOUNDRY;
+            }
+            return AnnotationType.LAYER;
+        }
+        else if (codes.length == 2) {
+            if (codes[1].endsWith(":") || codes[1].endsWith("-")) {
+                return AnnotationType.VALUE;
+            }
+            else {
+                return AnnotationType.KEY;
+            }
+        }
+
+        return "unknown";
+    }
+
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/annotation/ArrayVariables.java b/core/src/main/java/de/ids_mannheim/korap/annotation/ArrayVariables.java
new file mode 100644
index 0000000..55f476a
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/annotation/ArrayVariables.java
@@ -0,0 +1,94 @@
+package de.ids_mannheim.korap.annotation;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import de.ids_mannheim.korap.constant.AnnotationType;
+import de.ids_mannheim.korap.entity.Annotation;
+
+/**
+ * Helper class to parse annotation scripts variables. It prints out
+ * corenlp constituency layer for each negranodes.
+ * 
+ * @author margaretha
+ *
+ */
+public class ArrayVariables {
+
+    public static HashMap<String, List<Annotation>> annotationMap =
+            new HashMap<>();
+
+    public static void main (String[] args) throws IOException {
+        ArrayVariables variables = new ArrayVariables();
+        variables.extractVariables();
+
+        List<Annotation> negranodes = annotationMap.get("negranodes");
+        for (Annotation n : negranodes) {
+            System.out.println("ah[\"corenlp/c=" + n.getCode() + "-\"] = [");
+            int i = 1;
+            List<Annotation> negraedges = annotationMap.get("negraedges");
+            for (Annotation edge : negraedges) {
+                System.out.print(
+                        "  [\"" + edge.getCode() + "\", \"" + edge.getText()
+                                + "\", \"" + edge.getDescription() + "\"]");
+                if (i < negraedges.size()) {
+                    System.out.println(",");
+                }
+                else {
+                    System.out.println();
+                }
+                i++;
+            }
+            System.out.println("];");
+            System.out.println();
+        }
+    }
+
+    public void extractVariables () throws IOException {
+        String dir = "annotation-scripts/variables";
+        if (dir.isEmpty()) return;
+
+        File d = new File(dir);
+        if (!d.isDirectory()) {
+            throw new IOException("Directory " + dir + " is not valid");
+        }
+
+        for (File file : d.listFiles()) {
+            if (!file.exists()) {
+                throw new IOException("File " + file + " is not found.");
+            }
+            readFile(file);
+        }
+
+    }
+
+    private void readFile (File file) throws IOException {
+        BufferedReader br = new BufferedReader(
+                new InputStreamReader(new FileInputStream(file)));
+
+        String line;
+        ArrayList<String> values;
+        List<Annotation> annotations = new ArrayList<>();
+        while ((line = br.readLine()) != null) {
+            line = line.trim();
+            if (line.startsWith("[")) {
+                values = AnnotationParser.computeValues(line);
+
+                Annotation annotation = new Annotation(values.get(0),
+                        AnnotationType.VALUE, values.get(1), values.get(2));
+                annotations.add(annotation);
+            }
+        }
+        br.close();
+
+        String filename = file.getName();
+        filename = filename.substring(0, filename.length() - 3);
+        annotationMap.put(filename, annotations);
+    }
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/authentication/AuthenticationIface.java b/core/src/main/java/de/ids_mannheim/korap/authentication/AuthenticationIface.java
new file mode 100644
index 0000000..47d0738
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/authentication/AuthenticationIface.java
@@ -0,0 +1,27 @@
+package de.ids_mannheim.korap.authentication;
+
+import java.util.Map;
+
+import de.ids_mannheim.korap.constant.TokenType;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.security.context.TokenContext;
+import de.ids_mannheim.korap.user.User;
+
+public interface AuthenticationIface {
+
+    public TokenContext getTokenContext(String authToken) throws KustvaktException;
+
+
+    public TokenContext createTokenContext(User user, Map<String, Object> attr)
+            throws KustvaktException;
+
+
+    void removeUserSession (String token) throws KustvaktException;
+
+
+    public TokenContext refresh (TokenContext context) throws KustvaktException;
+
+
+    public TokenType getTokenType ();
+
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/authentication/AuthenticationManager.java b/core/src/main/java/de/ids_mannheim/korap/authentication/AuthenticationManager.java
new file mode 100644
index 0000000..a56cc76
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/authentication/AuthenticationManager.java
@@ -0,0 +1,106 @@
+package de.ids_mannheim.korap.authentication;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.ws.rs.core.HttpHeaders;
+
+import de.ids_mannheim.korap.config.KustvaktCacheable;
+import de.ids_mannheim.korap.constant.AuthenticationMethod;
+import de.ids_mannheim.korap.constant.TokenType;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.security.context.TokenContext;
+import de.ids_mannheim.korap.user.User;
+import de.ids_mannheim.korap.user.Userdata;
+
+/**
+ * @author hanl
+ * @date 15/06/2015
+ */
+public abstract class AuthenticationManager extends KustvaktCacheable {
+
+    private Map<TokenType, AuthenticationIface> providers;
+
+    public AuthenticationManager () {
+        super();
+    }
+    
+    public AuthenticationManager (String cache) {
+        super(cache, "key:"+cache);
+        this.providers = new HashMap<>();
+    }
+
+    public void setProviders (Set<AuthenticationIface> providers) {
+        for (AuthenticationIface i : providers) {
+            this.providers.put(i.getTokenType(), i);
+        }
+    }
+
+    protected AuthenticationIface getProvider (TokenType scheme,
+            TokenType default_iface) {
+
+        // Debug FB: loop a Map
+
+        /*for (Map.Entry<String, AuthenticationIface> entry : this.providers.entrySet()) 
+        {
+        System.out.println("Debug: provider: Key : " + entry.getKey() + " Value : " + entry.getValue());
+        }
+        */
+        // todo: configurable authentication schema
+        if (scheme == null) {
+            return this.providers.get(default_iface);
+        }
+        else {
+            return this.providers.get(scheme);
+        }
+    }
+
+    public abstract TokenContext getTokenContext (TokenType type, String token,
+            String host, String useragent) throws KustvaktException;
+
+    public abstract User getUser (String username) throws KustvaktException;
+
+    public abstract boolean isRegistered (String id);
+
+    public abstract User authenticate (AuthenticationMethod method,
+            String username, String password, Map<String, Object> attributes)
+            throws KustvaktException;
+
+    public abstract TokenContext createTokenContext (User user,
+            Map<String, Object> attr, TokenType type) throws KustvaktException;
+
+    public abstract void setAccessAndLocation (User user, HttpHeaders headers);
+
+    public abstract void logout (TokenContext context) throws KustvaktException;
+
+    public abstract void lockAccount (User user) throws KustvaktException;
+
+    public abstract User createUserAccount (Map<String, Object> attributes,
+            boolean confirmation_required) throws KustvaktException;
+
+    public abstract boolean deleteAccount (User user) throws KustvaktException;
+
+    public abstract <T extends Userdata> T getUserData (User user,
+            Class<T> clazz) throws KustvaktException;
+
+    public abstract void updateUserData (Userdata data)
+            throws KustvaktException;
+
+    public abstract Object[] validateResetPasswordRequest (String username,
+            String email) throws KustvaktException;
+
+    public abstract void resetPassword (String uriFragment, String username,
+            String newPassphrase) throws KustvaktException;
+
+    public abstract void confirmRegistration (String uriFragment,
+            String username) throws KustvaktException;
+
+    public String providerList () {
+        return "provider list: " + this.providers.toString();
+    }
+
+    public abstract User getUser (String username, String method)
+            throws KustvaktException;
+
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/authentication/http/AuthorizationData.java b/core/src/main/java/de/ids_mannheim/korap/authentication/http/AuthorizationData.java
new file mode 100644
index 0000000..236f26a
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/authentication/http/AuthorizationData.java
@@ -0,0 +1,22 @@
+package de.ids_mannheim.korap.authentication.http;
+
+import de.ids_mannheim.korap.constant.AuthenticationScheme;
+import lombok.Getter;
+import lombok.Setter;
+
+/** Describes the values stored in Authorization header of HTTP requests. 
+ * 
+ * @author margaretha
+ *
+ */
+@Getter
+@Setter
+public class AuthorizationData {
+
+    private String token;
+    private AuthenticationScheme authenticationScheme;
+    private String username;
+    private String password;
+
+}
+
diff --git a/core/src/main/java/de/ids_mannheim/korap/authentication/http/HttpAuthorizationHandler.java b/core/src/main/java/de/ids_mannheim/korap/authentication/http/HttpAuthorizationHandler.java
new file mode 100644
index 0000000..5eed64f
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/authentication/http/HttpAuthorizationHandler.java
@@ -0,0 +1,58 @@
+package de.ids_mannheim.korap.authentication.http;
+
+import org.springframework.stereotype.Component;
+
+import de.ids_mannheim.korap.constant.AuthenticationScheme;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
+import de.ids_mannheim.korap.utils.ParameterChecker;
+
+/** Implementation of Basic HTTP authentication scheme (see RFC 7253 
+ *  and 7617) for client asking for authorization and sending user 
+ *  data.  
+ * 
+ * @author margaretha
+ * 
+ */
+@Component
+public class HttpAuthorizationHandler {
+
+    public static String createBasicAuthorizationHeaderValue (String username, 
+            String password) throws KustvaktException {
+        ParameterChecker.checkStringValue(username, "username");
+        ParameterChecker.checkStringValue(password, "password");
+
+        String credentials = TransferEncoding.encodeBase64(username, password);
+        return AuthenticationScheme.BASIC.displayName()+" " + credentials;
+    }
+
+    public AuthorizationData parseAuthorizationHeaderValue (
+            String authorizationHeader) throws KustvaktException {
+        ParameterChecker.checkStringValue(authorizationHeader,
+                "authorization header");
+
+        String[] values = authorizationHeader.split(" ");
+        if (values.length != 2) {
+            throw new KustvaktException(StatusCodes.AUTHENTICATION_FAILED,
+                    "Cannot parse authorization header value "
+                            + authorizationHeader
+                            + ". Use this format: [authentication "
+                            + "scheme] [Base64-encoded token]",
+                    authorizationHeader);
+        }
+
+        AuthorizationData data = new AuthorizationData();
+        data.setAuthenticationScheme(
+                AuthenticationScheme.valueOf(values[0].toUpperCase()));
+        data.setToken(values[1]);
+        return data;
+    }
+
+    public AuthorizationData parseBasicToken (AuthorizationData data)
+            throws KustvaktException {
+        String[] credentials = TransferEncoding.decodeBase64(data.getToken());
+        data.setUsername(credentials[0]);
+        data.setPassword(credentials[1]);
+        return data;
+    }
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/authentication/http/TransferEncoding.java b/core/src/main/java/de/ids_mannheim/korap/authentication/http/TransferEncoding.java
new file mode 100644
index 0000000..52d1a90
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/authentication/http/TransferEncoding.java
@@ -0,0 +1,53 @@
+package de.ids_mannheim.korap.authentication.http;
+
+import org.apache.commons.codec.binary.Base64;
+import org.springframework.stereotype.Component;
+
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.utils.ParameterChecker;
+
+/** TransferEncoding contains encoding and decoding methods for data transfer, 
+ *  e.g. transfering credentials using basic Http authentication.  
+ *   
+ * @author margaretha
+ *
+ */
+@Component
+public class TransferEncoding {
+
+    /** Encodes username and password using Base64.
+     * 
+     * @param username username
+     * @param password password
+     * @return
+     */
+    public static String encodeBase64 (String username, String password) {
+        String s = username + ":" + password;
+        return new String(Base64.encodeBase64(s.getBytes()));
+    }
+
+    /** Decodes the given string using Base64.
+     * 
+     * @param encodedStr 
+     * @return username and password as an array of strings.
+     * @throws KustvaktException 
+     */
+    public static String[] decodeBase64 (String encodedStr)
+            throws KustvaktException {
+
+        ParameterChecker.checkStringValue(encodedStr, "encoded string");
+        String decodedStr = new String(Base64.decodeBase64(encodedStr));
+
+        if (decodedStr.contains(":") && decodedStr.split(":").length == 2) {
+            String[] strArr = decodedStr.split(":");
+            if ((strArr[0] != null && !strArr[0].isEmpty())
+                    && (strArr[1] != null && !strArr[1].isEmpty())) {
+                return decodedStr.split(":");
+            }
+
+        }
+
+        throw new IllegalArgumentException(
+                "Unknown Base64 encoding format: " + decodedStr);
+    }
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/config/KustvaktCacheable.java b/core/src/main/java/de/ids_mannheim/korap/config/KustvaktCacheable.java
index dfe6443..b22cb70 100644
--- a/core/src/main/java/de/ids_mannheim/korap/config/KustvaktCacheable.java
+++ b/core/src/main/java/de/ids_mannheim/korap/config/KustvaktCacheable.java
@@ -29,6 +29,10 @@
         this.prefix = prefix;
         this.name = cache_name;
     }
+    
+    public KustvaktCacheable () {
+        // TODO Auto-generated constructor stub
+    }
 
     private static Cache getCache(String name) {
         return CacheManager.getInstance().getCache(name);
diff --git a/core/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java b/core/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java
index 5ff29ea..7aab419 100644
--- a/core/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java
+++ b/core/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java
@@ -5,6 +5,7 @@
 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.Properties;
@@ -111,8 +112,8 @@
         currentVersion = properties.getProperty("current.api.version", "v1.0");
         String supportedVersions =
                 properties.getProperty("supported.api.version", "");
-        this.supportedVersions = Arrays.stream(supportedVersions.split(" "))
-                .collect(Collectors.toSet());
+        
+        this.supportedVersions = new HashSet<>(Arrays.asList(supportedVersions.split(" ")));
         this.supportedVersions.add(currentVersion);
 
         baseURL = properties.getProperty("kustvakt.base.url", "/api/*");
diff --git a/core/src/main/java/de/ids_mannheim/korap/constant/AnnotationType.java b/core/src/main/java/de/ids_mannheim/korap/constant/AnnotationType.java
new file mode 100644
index 0000000..560d401
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/constant/AnnotationType.java
@@ -0,0 +1,8 @@
+package de.ids_mannheim.korap.constant;
+
+public class AnnotationType {
+    public static String FOUNDRY = "foundry";
+    public static String LAYER = "layer";
+    public static String KEY = "key";
+    public static String VALUE = "value";
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/constant/AuthenticationMethod.java b/core/src/main/java/de/ids_mannheim/korap/constant/AuthenticationMethod.java
new file mode 100644
index 0000000..7c7dbae
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/constant/AuthenticationMethod.java
@@ -0,0 +1,14 @@
+package de.ids_mannheim.korap.constant;
+
+/** Lists possible actual authentication methods. Multiple 
+ *  {@link AuthenticationScheme} may use an identical 
+ *  authentication method. 
+ * 
+ * @author margaretha
+ * 
+ * @see AuthenticationScheme 
+ *
+ */
+public enum AuthenticationMethod {
+    LDAP, SHIBBOLETH, DATABASE, TEST; 
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/constant/AuthenticationScheme.java b/core/src/main/java/de/ids_mannheim/korap/constant/AuthenticationScheme.java
new file mode 100644
index 0000000..3db6a3e
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/constant/AuthenticationScheme.java
@@ -0,0 +1,21 @@
+package de.ids_mannheim.korap.constant;
+
+import org.apache.commons.lang.WordUtils;
+
+/** Lists possible authentication schemes used in the Authorization header 
+ *  of HTTP requests.  
+ * 
+ * @author margaretha
+ *
+ */
+public enum AuthenticationScheme {
+    // standard http
+    BASIC, BEARER,
+    // custom
+    // SESSION, has not been supported yet 
+    API;
+
+    public String displayName () {
+        return WordUtils.capitalizeFully(name());
+    }
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/constant/OAuth2Scope.java b/core/src/main/java/de/ids_mannheim/korap/constant/OAuth2Scope.java
new file mode 100644
index 0000000..5cd1293
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/constant/OAuth2Scope.java
@@ -0,0 +1,44 @@
+package de.ids_mannheim.korap.constant;
+
+public enum OAuth2Scope {
+    
+    ALL, 
+    ADMIN,
+    
+    OPENID, 
+    AUTHORIZE,
+    
+    CLIENT_INFO,
+    REGISTER_CLIENT,
+    DEREGISTER_CLIENT,
+    RESET_CLIENT_SECRET,
+    
+    SEARCH, 
+    SERIALIZE_QUERY,
+    MATCH_INFO, 
+    
+    USER_GROUP_INFO, 
+    CREATE_USER_GROUP, 
+    DELETE_USER_GROUP, 
+    
+    DELETE_USER_GROUP_MEMBER, 
+    ADD_USER_GROUP_MEMBER, 
+    
+    EDIT_USER_GROUP_MEMBER_ROLE,
+    ADD_USER_GROUP_MEMBER_ROLE,
+    DELETE_USER_GROUP_MEMBER_ROLE, 
+           
+    CREATE_VC, 
+    VC_INFO,
+    EDIT_VC, 
+    DELETE_VC, 
+    
+    SHARE_VC, 
+    DELETE_VC_ACCESS, 
+    VC_ACCESS_INFO;
+
+    @Override
+    public String toString () {
+        return super.toString().toLowerCase();
+    }
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/constant/TokenType.java b/core/src/main/java/de/ids_mannheim/korap/constant/TokenType.java
new file mode 100644
index 0000000..418be0b
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/constant/TokenType.java
@@ -0,0 +1,17 @@
+package de.ids_mannheim.korap.constant;
+
+import org.apache.commons.lang.StringUtils;
+
+public enum TokenType {
+    BASIC, API, SESSION, 
+    // openid token, e.g. within oauth2 response (json body)
+    ID_TOKEN,
+    // OAuth2 access_token
+    BEARER,
+    // OAuth2 client
+    CLIENT; 
+
+    public String displayName () {
+        return StringUtils.capitalize(name().toLowerCase());
+    }
+}
\ No newline at end of file
diff --git a/core/src/main/java/de/ids_mannheim/korap/dao/AdminDao.java b/core/src/main/java/de/ids_mannheim/korap/dao/AdminDao.java
new file mode 100644
index 0000000..fcf32d0
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/dao/AdminDao.java
@@ -0,0 +1,11 @@
+package de.ids_mannheim.korap.dao;
+
+import de.ids_mannheim.korap.user.User;
+
+public interface AdminDao {
+
+    void addAccount (User user);
+
+    boolean isAdmin (String userId);
+
+}
\ No newline at end of file
diff --git a/core/src/main/java/de/ids_mannheim/korap/dao/AnnotationDao.java b/core/src/main/java/de/ids_mannheim/korap/dao/AnnotationDao.java
new file mode 100644
index 0000000..ef54fda
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/dao/AnnotationDao.java
@@ -0,0 +1,215 @@
+package de.ids_mannheim.korap.dao;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import de.ids_mannheim.korap.constant.AnnotationType;
+import de.ids_mannheim.korap.entity.Annotation;
+import de.ids_mannheim.korap.entity.AnnotationKey;
+import de.ids_mannheim.korap.entity.AnnotationKey_;
+import de.ids_mannheim.korap.entity.AnnotationLayer;
+import de.ids_mannheim.korap.entity.AnnotationLayer_;
+import de.ids_mannheim.korap.entity.Annotation_;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.utils.ParameterChecker;
+
+/**
+ * AnnotationDao manages SQL queries regarding annotations including
+ * foundry and layer pairs.
+ * 
+ * @author margaretha
+ *
+ */
+@Repository
+@Transactional
+public class AnnotationDao {
+
+    @PersistenceContext
+    private EntityManager entityManager;
+
+    /**
+     * Retrieves all foundry-layer pairs.
+     * 
+     * @return a list of foundry-layer pairs.
+     */
+    @SuppressWarnings("unchecked")
+    public List<AnnotationLayer> getAllFoundryLayerPairs () {
+        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
+        CriteriaQuery<AnnotationLayer> query =
+                criteriaBuilder.createQuery(AnnotationLayer.class);
+        Root<AnnotationLayer> layer = query.from(AnnotationLayer.class);
+        layer.fetch(AnnotationLayer_.foundry);
+        layer.fetch(AnnotationLayer_.layer);
+        query.select(layer);
+        Query q = entityManager.createQuery(query);
+        return q.getResultList();
+    }
+
+    /**
+     * Retrieves foundry-layer pairs and their values for the given
+     * foundry and layer. If layer is empty, retrieves data for all
+     * layer in the given foundry. If foundry is empty, retrieves data
+     * for all foundry and layer pairs.
+     * 
+     * @param foundry
+     *            a foundry code
+     * @param layer
+     *            a layer code
+     * @return a list of foundry-layer pairs.
+     */
+    @SuppressWarnings("unchecked")
+    public List<AnnotationLayer> getAnnotationDescriptions (String foundry,
+            String layer) {
+
+        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
+        CriteriaQuery<Object> query = criteriaBuilder.createQuery();
+        Root<AnnotationLayer> annotationPair =
+                query.from(AnnotationLayer.class);
+        annotationPair.fetch(AnnotationLayer_.foundry);
+        annotationPair.fetch(AnnotationLayer_.layer);
+        annotationPair.fetch(AnnotationLayer_.keys);
+
+        // EM: Hibernate bug in join n:m (see AnnotationPair.values).
+        // There should not be any redundant AnnotationPair.
+        // The redundancy can be also avoided with
+        // fetch=FetchType.EAGER
+        // because Hibernate does 2 selects.
+        query.distinct(true);
+        query = query.select(annotationPair);
+
+        if (!foundry.isEmpty()) {
+            Predicate foundryPredicate = criteriaBuilder.equal(annotationPair
+                    .get(AnnotationLayer_.foundry).get(Annotation_.code),
+                    foundry);
+            if (layer.isEmpty() || layer.equals("*")) {
+                query.where(foundryPredicate);
+            }
+            else {
+                Predicate layerPredicate = criteriaBuilder.equal(annotationPair
+                        .get(AnnotationLayer_.layer).get(Annotation_.code),
+                        layer);
+                Predicate andPredicate =
+                        criteriaBuilder.and(foundryPredicate, layerPredicate);
+                query.where(andPredicate);
+            }
+        }
+
+        Query q = entityManager.createQuery(query);
+        return q.getResultList();
+    }
+
+    public Annotation retrieveAnnotation (String code, String type) {
+        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
+        CriteriaQuery<Annotation> query =
+                criteriaBuilder.createQuery(Annotation.class);
+
+        Root<Annotation> annotation = query.from(Annotation.class);
+        Predicate predicates = criteriaBuilder.and(
+                criteriaBuilder.equal(annotation.get(Annotation_.code), code),
+                criteriaBuilder.equal(annotation.get(Annotation_.type), type));
+        query.select(annotation).where(predicates);
+        Query q = entityManager.createQuery(query);
+        try {
+            return (Annotation) q.getSingleResult();
+        }
+        catch (NoResultException e) {
+            return null;
+        }
+    }
+
+    public AnnotationLayer retrieveAnnotationLayer (String foundry,
+            String layer) {
+        Annotation ann1 = retrieveAnnotation(foundry, AnnotationType.FOUNDRY);
+        Annotation ann2 = retrieveAnnotation(layer, AnnotationType.LAYER);
+
+        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
+        CriteriaQuery<AnnotationLayer> query =
+                criteriaBuilder.createQuery(AnnotationLayer.class);
+
+        Root<AnnotationLayer> annotation = query.from(AnnotationLayer.class);
+        Predicate predicates = criteriaBuilder.and(
+                criteriaBuilder.equal(annotation.get(AnnotationLayer_.foundry),
+                        ann1),
+                criteriaBuilder.equal(annotation.get(AnnotationLayer_.layer),
+                        ann2));
+        query.select(annotation).where(predicates);
+        Query q = entityManager.createQuery(query);
+        try {
+            return (AnnotationLayer) q.getSingleResult();
+        }
+        catch (NoResultException e) {
+            return null;
+        }
+
+    }
+
+    public Annotation createAnnotation (String code, String type, String text,
+            String description) {
+        Annotation ann = new Annotation(code, type, text, description);
+        entityManager.persist(ann);
+        return ann;
+    }
+
+    public AnnotationLayer createAnnotationLayer (Annotation foundry,
+            Annotation layer) throws KustvaktException {
+        ParameterChecker.checkObjectValue(foundry, "foundry");
+        ParameterChecker.checkObjectValue(layer, "layer");
+
+        AnnotationLayer annotationLayer = new AnnotationLayer();
+        annotationLayer.setFoundryId(foundry.getId());
+        annotationLayer.setLayerId(layer.getId());
+        annotationLayer.setDescription(
+                foundry.getDescription() + " " + layer.getDescription());
+        entityManager.persist(annotationLayer);
+        return annotationLayer;
+    }
+
+    public void updateAnnotationLayer (AnnotationLayer layer) {
+        entityManager.merge(layer);
+    }
+
+    public void updateAnnotationKey (AnnotationKey key) {
+        entityManager.merge(key);
+    }
+
+    public AnnotationKey createAnnotationKey (AnnotationLayer layer,
+            Annotation key) {
+        AnnotationKey annotation =
+                new AnnotationKey(layer.getId(), key.getId());
+        entityManager.persist(annotation);
+        return annotation;
+    }
+
+    public AnnotationKey retrieveAnnotationKey (AnnotationLayer layer,
+            Annotation key) {
+
+        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
+        CriteriaQuery<AnnotationKey> query =
+                criteriaBuilder.createQuery(AnnotationKey.class);
+
+        Root<AnnotationKey> annotation = query.from(AnnotationKey.class);
+        Predicate predicates = criteriaBuilder.and(
+                criteriaBuilder.equal(annotation.get(AnnotationKey_.layer),
+                        layer),
+                criteriaBuilder.equal(annotation.get(AnnotationKey_.key), key));
+        query.select(annotation).where(predicates);
+        Query q = entityManager.createQuery(query);
+        try {
+            return (AnnotationKey) q.getSingleResult();
+        }
+        catch (NoResultException e) {
+            return null;
+        }
+    }
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/dao/ResourceDao.java b/core/src/main/java/de/ids_mannheim/korap/dao/ResourceDao.java
new file mode 100644
index 0000000..d12ff3f
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/dao/ResourceDao.java
@@ -0,0 +1,82 @@
+package de.ids_mannheim.korap.dao;
+
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+import javax.persistence.TypedQuery;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Root;
+
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import de.ids_mannheim.korap.entity.AnnotationLayer;
+import de.ids_mannheim.korap.entity.Resource;
+import de.ids_mannheim.korap.entity.Resource_;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.utils.ParameterChecker;
+
+/**
+ * ResourceDao manages SQL queries regarding resource info and layers.
+ * 
+ * @author margaretha
+ *
+ */
+@Transactional
+@Repository
+public class ResourceDao {
+
+    @PersistenceContext
+    private EntityManager entityManager;
+
+    /**
+     * Select all from the resource table
+     * 
+     * @return a list of resources
+     */
+    public List<Resource> getAllResources () {
+        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
+        CriteriaQuery<Resource> query =
+                criteriaBuilder.createQuery(Resource.class);
+        Root<Resource> resource = query.from(Resource.class);
+        query.select(resource);
+
+        TypedQuery<Resource> q = entityManager.createQuery(query);
+        return q.getResultList();
+    }
+
+    public Resource retrieveResource (String id) {
+        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
+        CriteriaQuery<Resource> query =
+                criteriaBuilder.createQuery(Resource.class);
+        Root<Resource> resource = query.from(Resource.class);
+        query.select(resource);
+        query.where(criteriaBuilder.equal(resource.get(Resource_.id), id));
+
+        Query q = entityManager.createQuery(query);
+        try {
+            return (Resource) q.getSingleResult();
+        }
+        catch (NoResultException e) {
+            return null;
+        }
+    }
+
+    public void createResource (String id, String germanTitle,
+            String englishTitle, String englishDescription,
+            Set<AnnotationLayer> layers) throws KustvaktException {
+        ParameterChecker.checkStringValue(id, "id");
+        ParameterChecker.checkStringValue(englishTitle, "en_title");
+        ParameterChecker.checkStringValue(germanTitle, "de_title");
+
+        Resource r = new Resource(id, germanTitle, englishTitle,
+                englishDescription, layers);
+        entityManager.persist(r);
+
+    }
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/dto/FoundryDto.java b/core/src/main/java/de/ids_mannheim/korap/dto/FoundryDto.java
new file mode 100644
index 0000000..26cf383
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/dto/FoundryDto.java
@@ -0,0 +1,62 @@
+package de.ids_mannheim.korap.dto;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * Data transfer object for annotation descriptions (e.g. for
+ * Kalamar).
+ * 
+ * @author margaretha
+ * 
+ */
+@Getter
+@Setter
+@JsonInclude(Include.NON_EMPTY) // new fasterxml annotation, not used by current jersey version
+@JsonSerialize(include=Inclusion.NON_EMPTY) // old codehouse annotation, used by jersey
+public class FoundryDto {
+
+    private String code;
+    private String description;
+    private List<Layer> layers;
+
+    @Getter
+    @Setter
+    @JsonInclude(Include.NON_EMPTY)
+    @JsonSerialize(include=Inclusion.NON_EMPTY) // old codehouse annotation used by jersey
+    public class Layer {
+        private String code;
+        private String description;
+        private Set<Key> keys;
+    }
+
+    @Getter
+    @Setter
+    @JsonInclude(Include.NON_EMPTY)
+    @JsonSerialize(include=Inclusion.NON_EMPTY) // old codehouse annotation used by jersey
+    public class Key implements Comparable<Key>{
+
+        private String code;
+        private String description;
+        private Map<String, String> values;
+
+        public Key (String code) {
+            this.code = code;
+        }
+        
+        @Override
+        public int compareTo (Key k) {
+            return this.code.compareTo(k.code); 
+        }
+    }
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/dto/LayerDto.java b/core/src/main/java/de/ids_mannheim/korap/dto/LayerDto.java
new file mode 100644
index 0000000..b9884d8
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/dto/LayerDto.java
@@ -0,0 +1,21 @@
+package de.ids_mannheim.korap.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * Data transfer object for layer description (e.g. for KorapSRU).
+ * 
+ * @author margaretha
+ *
+ */
+@Getter
+@Setter
+public class LayerDto {
+
+    private int id;
+    private String code;
+    private String layer;
+    private String foundry;
+    private String description;
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/dto/converter/AnnotationConverter.java b/core/src/main/java/de/ids_mannheim/korap/dto/converter/AnnotationConverter.java
new file mode 100644
index 0000000..efe1c43
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/dto/converter/AnnotationConverter.java
@@ -0,0 +1,156 @@
+package de.ids_mannheim.korap.dto.converter;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import org.springframework.stereotype.Component;
+
+import de.ids_mannheim.korap.dto.FoundryDto;
+import de.ids_mannheim.korap.dto.FoundryDto.Key;
+import de.ids_mannheim.korap.dto.FoundryDto.Layer;
+import de.ids_mannheim.korap.dto.LayerDto;
+import de.ids_mannheim.korap.entity.Annotation;
+import de.ids_mannheim.korap.entity.AnnotationKey;
+import de.ids_mannheim.korap.entity.AnnotationLayer;
+
+/**
+ * AnnotationConverter prepares data transfer objects (DTOs) from
+ * entities. The DTOs, for instance, are serialized into JSON in the
+ * controller classes and then sent as the response entity.
+ * 
+ * @author margaretha
+ *
+ */
+@Component
+public class AnnotationConverter {
+
+    /**
+     * Returns layer descriptions in a list of {@link LayerDto}s.
+     * 
+     * @param pairs
+     *            a list of {@link AnnotationLayer}s
+     * @return a list of {@link LayerDto}s
+     */
+    public List<LayerDto> convertToLayerDto (List<AnnotationLayer> pairs) {
+        List<LayerDto> layerDtos = new ArrayList<LayerDto>(pairs.size());
+        LayerDto dto;
+        String foundry, layer;
+        for (AnnotationLayer p : pairs) {
+            dto = new LayerDto();
+            dto.setId(p.getId());
+            dto.setDescription(p.getDescription());
+
+            foundry = p.getFoundry().getCode();
+            dto.setFoundry(foundry);
+
+            layer = p.getLayer().getCode();
+            dto.setLayer(layer);
+            dto.setCode(foundry + "/" + layer);
+            layerDtos.add(dto);
+        }
+
+        return layerDtos;
+    }
+
+    /**
+     * Returns foundry description in {@link FoundryDto}s
+     * 
+     * @param pairs
+     *            a list of {@link AnnotationLayer}s
+     * @param language
+     * @return a list of {@link FoundryDto}s
+     */
+    public List<FoundryDto> convertToFoundryDto (List<AnnotationLayer> pairs,
+            String language) {
+        List<FoundryDto> foundryDtos = new ArrayList<FoundryDto>(pairs.size());
+        Map<String, List<AnnotationLayer>> foundryMap = createFoundryMap(pairs);
+
+        for (String foundryCode : foundryMap.keySet()) {
+            List<AnnotationLayer> foundries = foundryMap.get(foundryCode);
+            List<Layer> layers = new ArrayList<Layer>(foundries.size());
+            FoundryDto dto = null;
+
+            for (AnnotationLayer f : foundries) {
+                if (dto == null) {
+                    Annotation foundry = f.getFoundry();
+                    dto = new FoundryDto();
+                    if (language.equals("de")) {
+                        dto.setDescription(foundry.getGermanDescription());
+                    }
+                    else {
+                        dto.setDescription(foundry.getDescription());
+                    }
+                    dto.setCode(foundry.getCode());
+                }
+
+                Annotation layer = f.getLayer();
+                Set<Key> keys = new TreeSet<>();
+
+                for (AnnotationKey ak : f.getKeys()) {
+                    Annotation a = ak.getKey();
+                    Map<String, String> values = new TreeMap<>();
+                    
+                    Key key = dto.new Key(a.getCode());
+                    if (language.equals("de")) {
+                        key.setDescription(a.getGermanDescription());
+                        for (Annotation v : ak.getValues()) {
+                            values.put(v.getCode(), v.getGermanDescription());
+                        }
+
+                    }
+                    else {
+                        key.setDescription(a.getDescription());
+                        for (Annotation v : ak.getValues()) {
+                            values.put(v.getCode(), v.getDescription());
+                        }
+                    }
+                    key.setValues(values);
+                    keys.add(key);
+                }
+
+                Layer l = dto.new Layer();
+                l.setCode(layer.getCode());
+
+                if (language.equals("de")) {
+                    l.setDescription(layer.getGermanDescription());
+                }
+                else {
+                    l.setDescription(layer.getDescription());
+                }
+
+                l.setKeys(keys);
+                layers.add(l);
+            }
+
+            dto.setLayers(layers);
+            foundryDtos.add(dto);
+        }
+
+        return foundryDtos;
+    }
+
+    private Map<String, List<AnnotationLayer>> createFoundryMap (
+            List<AnnotationLayer> pairs) {
+        Map<String, List<AnnotationLayer>> foundries =
+                new HashMap<String, List<AnnotationLayer>>();
+        for (AnnotationLayer p : pairs) {
+            String foundryCode = p.getFoundry().getCode();
+            if (foundries.containsKey(foundryCode)) {
+                foundries.get(foundryCode).add(p);
+            }
+            else {
+                List<AnnotationLayer> foundryList =
+                        new ArrayList<AnnotationLayer>();
+                foundryList.add(p);
+                foundries.put(foundryCode, foundryList);
+            }
+        }
+
+        return foundries;
+    }
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/encryption/RandomCodeGenerator.java b/core/src/main/java/de/ids_mannheim/korap/encryption/RandomCodeGenerator.java
new file mode 100644
index 0000000..ea451aa
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/encryption/RandomCodeGenerator.java
@@ -0,0 +1,71 @@
+package de.ids_mannheim.korap.encryption;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.UUID;
+
+import javax.annotation.PostConstruct;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.lang.ArrayUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import de.ids_mannheim.korap.config.KustvaktConfiguration;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
+
+/**
+ * Generates a random string that can be used for tokens, client id,
+ * client secret, etc.
+ * 
+ * @author margaretha
+ *
+ */
+@Component
+public class RandomCodeGenerator {
+
+    @Autowired
+    public KustvaktConfiguration config;
+
+    public static SecureRandom secureRandom;
+
+    @PostConstruct
+    public void init () throws NoSuchAlgorithmException {
+        secureRandom =
+                SecureRandom.getInstance(config.getSecureRandomAlgorithm());
+    }
+
+    public String createRandomCode (KustvaktConfiguration c)
+            throws KustvaktException, NoSuchAlgorithmException {
+        config = c;
+        init();
+        return createRandomCode();
+    }
+
+    public String createRandomCode () throws KustvaktException {
+        UUID randomUUID = UUID.randomUUID();
+        byte[] uuidBytes = randomUUID.toString().getBytes();
+        byte[] secureBytes = new byte[3];
+        secureRandom.nextBytes(secureBytes);
+
+        byte[] bytes = ArrayUtils.addAll(uuidBytes, secureBytes);
+
+        try {
+            MessageDigest md = MessageDigest
+                    .getInstance(config.getMessageDigestAlgorithm());
+            md.update(bytes);
+            byte[] digest = md.digest();
+            String code = Base64.encodeBase64URLSafeString(digest);
+            md.reset();
+            return code;
+        }
+        catch (NoSuchAlgorithmException e) {
+            throw new KustvaktException(StatusCodes.INVALID_ALGORITHM,
+                    config.getMessageDigestAlgorithm()
+                            + "is not a valid MessageDigest algorithm");
+        }
+    }
+
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/entity/Annotation.java b/core/src/main/java/de/ids_mannheim/korap/entity/Annotation.java
new file mode 100644
index 0000000..35ee11d
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/entity/Annotation.java
@@ -0,0 +1,52 @@
+package de.ids_mannheim.korap.entity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * Describes annotation tags available in the system / used in
+ * annotating corpus data.
+ * 
+ * @author margaretha
+ *
+ */
+@Setter
+@Getter
+@Entity
+@Table(name = "annotation")
+public class Annotation {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private int id;
+    private String code;
+    private String type;
+    private String text;
+    private String description;
+    @Column(name = "de_description")
+    private String germanDescription;
+
+    public Annotation () {}
+
+    public Annotation (String code, String type, String text,
+                       String description) {
+        this.code = code;
+        this.type = type;
+        this.text = text;
+        this.description = description;
+    }
+
+    @Override
+    public String toString () {
+        return "id=" + id + ", code= " + code + ", type= " + type
+                + ", description=" + description + ", germanDescription="
+                + germanDescription;
+    }
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/entity/AnnotationKey.java b/core/src/main/java/de/ids_mannheim/korap/entity/AnnotationKey.java
new file mode 100644
index 0000000..d65ffb2
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/entity/AnnotationKey.java
@@ -0,0 +1,61 @@
+package de.ids_mannheim.korap.entity;
+
+import java.util.Set;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Setter
+@Getter
+@Entity
+@Table(name = "annotation_key", uniqueConstraints = @UniqueConstraint(
+        columnNames = { "layer_id", "key_id" }))
+public class AnnotationKey {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private int id;
+    @Column(name = "key_id")
+    private int keyId;
+    @Column(name = "layer_id")
+    private int layerId;
+
+    @ManyToOne(fetch = FetchType.EAGER)
+    @JoinColumn(name = "layer_id", insertable = false, updatable = false)
+    private AnnotationLayer layer;
+
+    @ManyToOne(fetch = FetchType.EAGER)
+    @JoinColumn(name = "key_id", insertable = false, updatable = false)
+    private Annotation key;
+
+    @ManyToMany(fetch = FetchType.EAGER)
+    @JoinTable(name = "annotation_value",
+            joinColumns = @JoinColumn(name = "key_id",
+                    referencedColumnName = "id"),
+            inverseJoinColumns = @JoinColumn(name = "value_id",
+                    referencedColumnName = "id"),
+            uniqueConstraints = @UniqueConstraint(
+                    columnNames = { "key_id", "value_id" }))
+    private Set<Annotation> values;
+
+    public AnnotationKey () {}
+
+    public AnnotationKey (int layerId, int keyId) {
+        this.layerId = layerId;
+        this.keyId = keyId;
+    }
+
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/entity/AnnotationLayer.java b/core/src/main/java/de/ids_mannheim/korap/entity/AnnotationLayer.java
new file mode 100644
index 0000000..c16abec
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/entity/AnnotationLayer.java
@@ -0,0 +1,68 @@
+package de.ids_mannheim.korap.entity;
+
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+import org.hibernate.annotations.Fetch;
+import org.hibernate.annotations.FetchMode;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * Describes annotations as a pair, e.g. foundry and layer where
+ * foundry denotes where the annotation comes from e.g. Tree tagger
+ * parser, and layer denotes the annotation layer e.g. part of speech.
+ * 
+ * @author margaretha
+ * @see Annotation
+ */
+@Setter
+@Getter
+@Entity
+@Table(name = "annotation_layer", uniqueConstraints = @UniqueConstraint(
+        columnNames = { "foundry_id", "layer_id" }))
+public class AnnotationLayer {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private int id;
+    @Column(name = "foundry_id")
+    private int foundryId;
+    @Column(name = "layer_id")
+    private int layerId;
+    @Column(name = "description")
+    private String description;
+
+    @Fetch(FetchMode.SELECT)
+    @ManyToOne // (fetch=FetchType.LAZY)
+    @JoinColumn(name = "foundry_id", insertable = false, updatable = false)
+    private Annotation foundry;
+
+    @Fetch(FetchMode.SELECT)
+    @ManyToOne // (fetch=FetchType.LAZY)
+    @JoinColumn(name = "layer_id", insertable = false, updatable = false)
+    private Annotation layer;
+
+    @OneToMany(mappedBy = "layer", fetch = FetchType.EAGER,
+            cascade = CascadeType.REMOVE)
+    private Set<AnnotationKey> keys;
+
+    @Override
+    public String toString () {
+        return "id=" + id + ", foundry=" + foundry + ", layer=" + layer
+                + ", description=" + description + ", keys= " + keys;
+
+    }
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/entity/Resource.java b/core/src/main/java/de/ids_mannheim/korap/entity/Resource.java
new file mode 100644
index 0000000..813adc5
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/entity/Resource.java
@@ -0,0 +1,69 @@
+package de.ids_mannheim.korap.entity;
+
+import java.util.Set;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.Table;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * Describes resources having free licenses. Primarily for
+ * accommodating
+ * clients in providing data without login such as KorapSRU.
+ * 
+ * @author margaretha
+ *
+ */
+@Getter
+@Setter
+@Entity
+@Table(name = "resource")
+public class Resource {
+
+    @Id
+    private String id;
+
+    @Column(name = "de_title")
+    private String germanTitle;
+
+    @Column(name = "en_title")
+    private String englishTitle;
+
+    @Column(name = "en_description")
+    private String englishDescription;
+
+    @ManyToMany(fetch = FetchType.EAGER)
+    @JoinTable(name = "resource_layer",
+            joinColumns = @JoinColumn(name = "resource_id",
+                    referencedColumnName = "id"),
+            inverseJoinColumns = @JoinColumn(name = "layer_id",
+                    referencedColumnName = "id"))
+    private Set<AnnotationLayer> layers;
+
+    public Resource () {}
+
+    public Resource (String id, String germanTitle, String englishTitle,
+                     String englishDescription, Set<AnnotationLayer> layers) {
+        this.id = id;
+        this.germanTitle = germanTitle;
+        this.englishTitle = englishTitle;
+        this.englishDescription = englishDescription;
+        this.layers = layers;
+    }
+
+    @Override
+    public String toString () {
+        return "id=" + id + ", germanTitle=" + germanTitle + ", englishTitle="
+                + englishTitle + ", description=" + englishDescription
+                + ", layers= " + layers;
+    }
+
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/interfaces/EncryptionIface.java b/core/src/main/java/de/ids_mannheim/korap/interfaces/EncryptionIface.java
new file mode 100644
index 0000000..134ebdb
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/interfaces/EncryptionIface.java
@@ -0,0 +1,76 @@
+package de.ids_mannheim.korap.interfaces;
+
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.user.User;
+
+import java.io.UnsupportedEncodingException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Map;
+
+public interface EncryptionIface {
+
+    public enum Encryption {
+                @Deprecated
+        SIMPLE, ESAPICYPHER, BCRYPT
+    }
+
+
+    /**
+     * One-way hashing of String input. Used to canonicalize
+     * 
+     * @param input
+     * @param salt
+     * @return
+     */
+    public String secureHash (String input, String salt)
+            throws KustvaktException;
+
+
+    public String secureHash (String input) throws NoSuchAlgorithmException,
+            UnsupportedEncodingException, KustvaktException;
+
+
+    /**
+     * @param plain
+     * @param hash
+     * @param salt
+     * @return
+     */
+    public boolean checkHash (String plain, String hash, String salt);
+
+
+    public boolean checkHash (String plain, String hash);
+
+
+    /**
+     * create random String to be used as authentication token
+     * 
+     * @return
+     */
+    public String createToken (boolean hash, Object ... obj);
+
+
+    public String createToken ();
+
+
+    /**
+     * create a random Integer to be used as ID for databases
+     * 
+     * @return
+     */
+    public String createRandomNumber (Object ... obj);
+
+
+    public String encodeBase ();
+
+
+   // @Deprecated
+    //public Map<String, Object> validateMap (Map<String, Object> map)
+    //        throws KustvaktException;
+
+
+    //@Deprecated
+    //public String validateEntry (String input, String type)
+    //        throws KustvaktException;
+
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/interfaces/EntityHandlerIface.java b/core/src/main/java/de/ids_mannheim/korap/interfaces/EntityHandlerIface.java
new file mode 100644
index 0000000..9bcf614
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/interfaces/EntityHandlerIface.java
@@ -0,0 +1,36 @@
+package de.ids_mannheim.korap.interfaces;
+
+import de.ids_mannheim.korap.exceptions.EmptyResultException;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.user.User;
+
+/**
+ * User: hanl
+ * Date: 8/19/13
+ * Time: 11:04 AM
+ */
+public interface EntityHandlerIface {
+
+    User getAccount (String username) throws EmptyResultException,
+            KustvaktException;
+
+
+    int updateAccount (User user) throws KustvaktException;
+
+
+    int createAccount (User user) throws KustvaktException;
+
+
+    int deleteAccount (Integer userid) throws KustvaktException;
+
+
+    int truncate () throws KustvaktException;
+
+
+    int resetPassphrase (String username, String uriToken, String passphrase)
+            throws KustvaktException;
+
+
+    int activateAccount (String username, String uriToken)
+            throws KustvaktException;
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2ScopeService.java b/core/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2ScopeService.java
new file mode 100644
index 0000000..da12bfd
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2ScopeService.java
@@ -0,0 +1,13 @@
+package de.ids_mannheim.korap.oauth2.service;
+
+import de.ids_mannheim.korap.constant.OAuth2Scope;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.security.context.TokenContext;
+
+public interface OAuth2ScopeService {
+
+    
+    void verifyScope (TokenContext context, OAuth2Scope requiredScope)
+            throws KustvaktException;
+
+}
\ No newline at end of file
diff --git a/core/src/main/java/de/ids_mannheim/korap/security/context/KustvaktContext.java b/core/src/main/java/de/ids_mannheim/korap/security/context/KustvaktContext.java
new file mode 100644
index 0000000..6d36199
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/security/context/KustvaktContext.java
@@ -0,0 +1,46 @@
+package de.ids_mannheim.korap.security.context;
+
+import javax.ws.rs.core.SecurityContext;
+
+import java.security.Principal;
+
+/**
+ * @author hanl
+ * @date 13/05/2014
+ * 
+ *       wrapper for REST security context
+ * 
+ */
+public class KustvaktContext implements SecurityContext {
+
+    private TokenContext user;
+
+
+    public KustvaktContext (final TokenContext user) {
+        this.user = user;
+    }
+
+
+    @Override
+    public Principal getUserPrincipal () {
+        return this.user;
+    }
+
+
+    @Override
+    public boolean isUserInRole (String role) {
+        throw new UnsupportedOperationException();
+    }
+
+
+    @Override
+    public boolean isSecure () {
+        return false;
+    }
+
+
+    @Override
+    public String getAuthenticationScheme () {
+        return SecurityContext.BASIC_AUTH;
+    }
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/security/context/TokenContext.java b/core/src/main/java/de/ids_mannheim/korap/security/context/TokenContext.java
new file mode 100644
index 0000000..b31c643
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/security/context/TokenContext.java
@@ -0,0 +1,173 @@
+package de.ids_mannheim.korap.security.context;
+
+import java.io.Serializable;
+import java.time.ZonedDateTime;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+import de.ids_mannheim.korap.config.Attributes;
+import de.ids_mannheim.korap.constant.TokenType;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.user.User;
+import de.ids_mannheim.korap.utils.JsonUtils;
+import de.ids_mannheim.korap.utils.TimeUtils;
+import lombok.AccessLevel;
+import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * EM: 
+ * - change datatype of tokenType from string to enum
+ * - added authenticationTime
+ * 
+ * @author hanl
+ * @date 27/01/2014
+ */
+@Data
+public class TokenContext implements java.security.Principal, Serializable {
+
+    private ZonedDateTime authenticationTime;
+    /**
+     * session relevant data. Are never persisted into a database
+     */
+    private String username;
+    private long expirationTime;
+    // either "session_token " / "api_token
+    private TokenType tokenType;
+    private String token;
+    private boolean secureRequired;
+
+//    @Getter(AccessLevel.PRIVATE)
+    @Setter(AccessLevel.PRIVATE)
+    private Map<String, Object> parameters;
+    private String hostAddress;
+    private String userAgent;
+
+
+    public TokenContext () {
+        this.parameters = new HashMap<>();
+        this.setUsername("");
+        this.setToken("");
+        this.setSecureRequired(false);
+        this.setExpirationTime(-1);
+    }
+
+
+    private Map statusMap () {
+        Map m = new HashMap();
+        if (username != null && !username.isEmpty())
+            m.put(Attributes.USERNAME, username);
+        m.put(Attributes.TOKEN_EXPIRATION,
+                TimeUtils.format(this.expirationTime));
+        m.put(Attributes.TOKEN, this.token);
+        m.put(Attributes.TOKEN_TYPE, this.tokenType);
+        return m;
+    }
+
+
+    public Map<String, Object> params () {
+        return new HashMap<>(parameters);
+    }
+    
+    public boolean match (TokenContext other) {
+        if (other.getToken().equals(this.token))
+            if (this.getHostAddress().equals(this.hostAddress))
+                // user agent should be irrelvant -- what about os
+                // system version?
+                // if (other.getUserAgent().equals(this.userAgent))
+                return true;
+        return false;
+    }
+
+
+    public void addContextParameter (String key, String value) {
+        this.parameters.put(key, value);
+    }
+
+
+    public void addParams (Map<String, Object> map) {
+        for (Map.Entry<String, Object> e : map.entrySet())
+            this.parameters.put(e.getKey(), String.valueOf(e.getValue()));
+    }
+
+
+    public void removeContextParameter (String key) {
+        this.parameters.remove(key);
+    }
+
+
+    public void setExpirationTime (long date) {
+        this.expirationTime = date;
+    }
+
+
+    // todo: complete
+    public static TokenContext fromJSON (String s) throws KustvaktException {
+        JsonNode node = JsonUtils.readTree(s);
+        TokenContext c = new TokenContext();
+        if (node != null) {
+            c.setUsername(node.path(Attributes.USERNAME).asText());
+            c.setToken(node.path(Attributes.TOKEN).asText());
+        }
+        return c;
+    }
+
+
+    public static TokenContext fromOAuth2 (String s) throws KustvaktException {
+        JsonNode node = JsonUtils.readTree(s);
+        TokenContext c = new TokenContext();
+        if (node != null) {
+            c.setToken(node.path("token").asText());
+            c.setTokenType(TokenType.valueOf(node.path("token_type").asText()));
+            c.setExpirationTime(node.path("expires_in").asLong());
+            c.addContextParameter("refresh_token",
+                    node.path("refresh_token").asText());
+
+        }
+        return c;
+    }
+
+
+    public boolean isValid () {
+        return (this.username != null && !this.username.isEmpty())
+                && (this.token != null && !this.token.isEmpty())
+                && (this.tokenType != null);
+    }
+
+
+    public String getToken () {
+        return token;
+    }
+
+
+    public String toJson () throws KustvaktException {
+        return JsonUtils.toJSON(this.statusMap());
+    }
+
+
+    public boolean isDemo () {
+        return User.UserFactory.isDemo(this.username);
+    }
+
+
+
+    @Override
+    public String getName () {
+        return this.getUsername();
+    }
+
+
+    public ZonedDateTime getAuthenticationTime () {
+        return authenticationTime;
+    }
+
+
+    public void setAuthenticationTime (ZonedDateTime authTime) {
+        this.authenticationTime = authTime;
+    }
+
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/server/KustvaktBaseServer.java b/core/src/main/java/de/ids_mannheim/korap/server/KustvaktBaseServer.java
new file mode 100644
index 0000000..2af1912
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/server/KustvaktBaseServer.java
@@ -0,0 +1,139 @@
+package de.ids_mannheim.korap.server;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+import java.security.NoSuchAlgorithmException;
+
+import javax.servlet.ServletContextListener;
+
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.handler.HandlerList;
+import org.eclipse.jetty.server.handler.ShutdownHandler;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.springframework.web.context.ContextLoaderListener;
+
+import com.sun.jersey.spi.spring.container.servlet.SpringServlet;
+
+import de.ids_mannheim.korap.config.KustvaktConfiguration;
+import de.ids_mannheim.korap.encryption.RandomCodeGenerator;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author hanl
+ * @date 01/06/2015
+ */
+public abstract class KustvaktBaseServer {
+
+    protected static KustvaktConfiguration config;
+
+    protected static String rootPackages;
+    protected static KustvaktArgs kargs;
+
+    public KustvaktBaseServer () {}
+
+    protected KustvaktArgs readAttributes (String[] args) {
+        KustvaktArgs kargs = new KustvaktArgs();
+        for (int i = 0; i < args.length; i++) {
+            switch ((args[i])) {
+                case "--spring-config":
+                    kargs.setSpringConfig(args[i + 1]);
+                    break;
+                case "--port":
+                    kargs.setPort(Integer.valueOf(args[i + 1]));
+                    break;
+                case "--help":
+                    StringBuffer b = new StringBuffer();
+
+                    b.append("Parameter description: \n")
+                            .append("--spring-config  <Spring XML configuration filename in classpath>\n")
+                            .append("--port  <Server port number>\n")
+                            .append("--help : This help menu\n");
+                    System.out.println(b.toString());
+                    System.out.println();
+                    return (KustvaktArgs) null;
+            }
+        }
+        return kargs;
+    }
+
+    protected void start ()
+            throws KustvaktException, IOException, NoSuchAlgorithmException {
+
+        if (kargs.port == -1) {
+            kargs.setPort(config.getPort());
+        }
+
+        Server server = new Server();
+
+        ServletContextHandler contextHandler =
+                new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
+        contextHandler.setContextPath("/");
+        contextHandler.setInitParameter("contextConfigLocation",
+                "classpath:" + kargs.getSpringConfig());
+
+        ServletContextListener listener = new ContextLoaderListener();
+        contextHandler.addEventListener(listener);
+
+        ServletHolder servletHolder = new ServletHolder(new SpringServlet());
+        servletHolder.setInitParameter(
+                "com.sun.jersey.config.property.packages", rootPackages);
+        servletHolder.setInitParameter(
+                "com.sun.jersey.api.json.POJOMappingFeature", "true");
+        servletHolder.setInitOrder(1);
+        contextHandler.addServlet(servletHolder, config.getBaseURL());
+
+        ServerConnector connector = new ServerConnector(server);
+        connector.setPort(kargs.port);
+        connector.setIdleTimeout(60000);
+
+        RandomCodeGenerator random = new RandomCodeGenerator();
+        String shutdownToken = random.createRandomCode(config);
+        ShutdownHandler shutdownHandler = new ShutdownHandler(shutdownToken,true,true);
+
+        FileOutputStream fos = new FileOutputStream(new File("shutdownToken"));
+        OutputStreamWriter writer =
+                new OutputStreamWriter(fos, StandardCharsets.UTF_8.name());
+        writer.write(shutdownToken);
+        writer.flush();
+        writer.close();
+
+        HandlerList handlers = new HandlerList();
+        handlers.addHandler(shutdownHandler);
+        handlers.addHandler(contextHandler);
+
+        server.setHandler(handlers);
+
+        server.setConnectors(new Connector[] { connector });
+        try {
+            server.start();
+            server.join();
+        }
+        catch (Exception e) {
+            System.out.println("Server could not be started!");
+            System.out.println(e.getMessage());
+            e.printStackTrace();
+            System.exit(-1);
+        }
+    }
+
+    @Setter
+    public static class KustvaktArgs {
+
+        @Getter
+        private String springConfig;
+        private int port;
+
+        public KustvaktArgs () {
+            this.port = -1;
+            this.springConfig = null;
+        }
+    }
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/service/AnnotationService.java b/core/src/main/java/de/ids_mannheim/korap/service/AnnotationService.java
new file mode 100644
index 0000000..3e384ec
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/service/AnnotationService.java
@@ -0,0 +1,88 @@
+package de.ids_mannheim.korap.service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import de.ids_mannheim.korap.dao.AnnotationDao;
+import de.ids_mannheim.korap.dto.FoundryDto;
+import de.ids_mannheim.korap.dto.LayerDto;
+import de.ids_mannheim.korap.dto.converter.AnnotationConverter;
+import de.ids_mannheim.korap.entity.AnnotationLayer;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
+import de.ids_mannheim.korap.web.controller.AnnotationController;
+
+/** AnnotationService defines the logic behind {@link AnnotationController}.
+ * 
+ * @author margaretha
+ *
+ */
+@Service
+public class AnnotationService {
+
+    private static Logger jlog =
+            LogManager.getLogger(AnnotationService.class);
+
+    @Autowired
+    private AnnotationDao annotationDao;
+
+    @Autowired
+    private AnnotationConverter annotationConverter;
+
+    public List<LayerDto> getLayerDtos () {
+        List<AnnotationLayer> layers = annotationDao.getAllFoundryLayerPairs();
+        jlog.debug("/layers " + layers.toString());
+        List<LayerDto> layerDto = annotationConverter.convertToLayerDto(layers);
+        return layerDto;
+    }
+
+    public List<FoundryDto> getFoundryDtos (List<String> codes, String language)
+            throws KustvaktException {
+        List<AnnotationLayer> annotationPairs = null;
+        String foundry = "", layer = "";
+        if (codes.contains("*")) {
+            annotationPairs =
+                    annotationDao.getAnnotationDescriptions(foundry, layer);
+        }
+        else {
+            String[] annotationCode;
+            annotationPairs = new ArrayList<AnnotationLayer>();
+            for (String code : codes) {
+                jlog.debug("code " + code);
+                annotationCode = code.split("/");
+                if (annotationCode.length == 1) {
+                    foundry = annotationCode[0];
+                }
+                else if (annotationCode.length == 2) {
+                    foundry = annotationCode[0];
+                    layer = annotationCode[1];
+                }
+                else {
+                    jlog.error("Annotation code is wrong: " + annotationCode);
+                    throw new KustvaktException(StatusCodes.INVALID_ATTRIBUTE,
+                            "Bad attribute:", code);
+                }
+
+                annotationPairs.addAll(annotationDao
+                        .getAnnotationDescriptions(foundry, layer));
+            }
+        }
+
+        if (annotationPairs != null && !annotationPairs.isEmpty()) {
+            List<FoundryDto> foundryDtos = annotationConverter
+                    .convertToFoundryDto(annotationPairs, language);
+            jlog.debug("/description " + annotationPairs.toString());
+            return foundryDtos;
+        }
+        else {
+            throw new KustvaktException(StatusCodes.NO_RESULT_FOUND,
+                    "No result found.", "");
+        }
+
+    }
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/service/SearchService.java b/core/src/main/java/de/ids_mannheim/korap/service/SearchService.java
new file mode 100644
index 0000000..6e7c17e
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/service/SearchService.java
@@ -0,0 +1,243 @@
+package de.ids_mannheim.korap.service;
+
+import java.util.ArrayList;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import javax.annotation.PostConstruct;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.UriBuilder;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.sun.jersey.core.util.MultivaluedMapImpl;
+
+import de.ids_mannheim.korap.authentication.AuthenticationManager;
+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.query.serialize.MetaQueryBuilder;
+import de.ids_mannheim.korap.query.serialize.QuerySerializer;
+import de.ids_mannheim.korap.resource.rewrite.RewriteHandler;
+import de.ids_mannheim.korap.user.User;
+import de.ids_mannheim.korap.user.User.CorpusAccess;
+import de.ids_mannheim.korap.web.ClientsHandler;
+import de.ids_mannheim.korap.web.SearchKrill;
+
+@Service
+public class SearchService {
+
+    private static Logger jlog = LogManager.getLogger(SearchService.class);
+
+    @Autowired
+    private KustvaktConfiguration config;
+
+    @Autowired
+    private AuthenticationManager authenticationManager;
+
+    @Autowired
+    private RewriteHandler rewriteHandler;
+
+    @Autowired
+    private SearchKrill searchKrill;
+
+    private ClientsHandler graphDBhandler;
+
+    @PostConstruct
+    private void doPostConstruct () {
+        this.rewriteHandler.defaultRewriteConstraints();
+
+        UriBuilder builder = UriBuilder.fromUri("http://10.0.10.13").port(9997);
+        this.graphDBhandler = new ClientsHandler(builder.build());
+    }
+
+    @SuppressWarnings("unchecked")
+    public String serializeQuery (String q, String ql, String v, String cq,
+            Integer pageIndex, Integer startPage, Integer pageLength,
+            String context, Boolean cutoff) throws KustvaktException {
+        QuerySerializer ss = new QuerySerializer().setQuery(q, ql, v);
+        if (cq != null) ss.setCollection(cq);
+
+        MetaQueryBuilder meta = new MetaQueryBuilder();
+        if (pageIndex != null) meta.addEntry("startIndex", pageIndex);
+        if (pageIndex == null && startPage != null)
+            meta.addEntry("startPage", startPage);
+        if (pageLength != null) meta.addEntry("count", pageLength);
+        if (context != null) meta.setSpanContext(context);
+        meta.addEntry("cutOff", cutoff);
+
+        ss.setMeta(meta.raw());
+        // return ss.toJSON();
+
+        String query = ss.toJSON();
+        query = rewriteHandler.processQuery(ss.toJSON(), null);
+        return query;
+    }
+
+    private User createUser (String username, HttpHeaders headers)
+            throws KustvaktException {
+        User user = authenticationManager.getUser(username);
+        authenticationManager.setAccessAndLocation(user, headers);
+        if (user != null) {
+            jlog.debug(
+                    "Debug: /getMatchInfo/: location=" + user.locationtoString()
+                            + ", access=" + user.accesstoString());
+        }
+        return user;
+    }
+
+    public String search (String jsonld) {
+        // MH: todo: should be possible to add the meta part to
+        // the query serialization
+        // User user = controller.getUser(ctx.getUsername());
+        // jsonld = this.processor.processQuery(jsonld, user);
+        return searchKrill.search(jsonld);
+    }
+
+    @SuppressWarnings("unchecked")
+    public String search (String engine, String username, HttpHeaders headers,
+            String q, String ql, String v, String cq, Set<String> fields,
+            Integer pageIndex, Integer pageInteger, String ctx,
+            Integer pageLength, Boolean cutoff) throws KustvaktException {
+
+        KustvaktConfiguration.BACKENDS eng = this.config.chooseBackend(engine);
+        User user = createUser(username, headers);
+
+        QuerySerializer serializer = new QuerySerializer();
+        serializer.setQuery(q, ql, v);
+        if (cq != null) serializer.setCollection(cq);
+
+        MetaQueryBuilder meta = createMetaQuery(pageIndex, pageInteger, ctx,
+                pageLength, cutoff);
+        if (fields != null && !fields.isEmpty())
+            meta.addEntry("fields", fields);
+        serializer.setMeta(meta.raw());
+
+        // There is an error in query processing
+        // - either query, corpus or meta
+        if (serializer.hasErrors()) {
+            throw new KustvaktException(serializer.toJSON());
+        }
+
+        String query =
+                this.rewriteHandler.processQuery(serializer.toJSON(), user);
+        jlog.info("the serialized query " + query);
+
+        String result;
+        if (eng.equals(KustvaktConfiguration.BACKENDS.NEO4J)) {
+            result = searchNeo4J(query, pageLength, meta, false);
+        }
+        else {
+            result = searchKrill.search(query);
+        }
+        // jlog.debug("Query result: " + result);
+        return result;
+
+    }
+
+    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);
+        meta.setSpanContext(ctx);
+        meta.addEntry("count", pageLength);
+        // todo: what happened to cutoff?
+        meta.addEntry("cutOff", cutoff);
+        // meta.addMeta(pageIndex, pageInteger, pageLength, ctx,
+        // cutoff);
+        // fixme: should only apply to CQL queries per default!
+        // meta.addEntry("itemsPerResource", 1);
+        return meta;
+    }
+
+    private String searchNeo4J (String query, int pageLength,
+            MetaQueryBuilder meta, boolean raw) throws KustvaktException {
+
+        if (raw) {
+            throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT,
+                    "raw not supported!");
+        }
+
+        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()));
+        return this.graphDBhandler.getResponse(map, "distKwic");
+
+    }
+
+    public String retrieveMatchInfo (String corpusId, String docId,
+            String textId, String matchId, Set<String> foundries,
+            String username, HttpHeaders headers, Set<String> layers,
+            boolean spans, boolean highlights) throws KustvaktException {
+        String matchid =
+                searchKrill.getMatchId(corpusId, docId, textId, matchId);
+
+        User user = createUser(username, headers);
+        Pattern p = null;
+        if (user != null) {
+            CorpusAccess corpusAccess = user.getCorpusAccess();
+            switch (corpusAccess) {
+                case PUB:
+                    p = config.getPublicLicensePattern();
+                    break;
+                case ALL:
+                    p = config.getAllLicensePattern();
+                    break;
+                default: // FREE
+                    p = config.getFreeLicensePattern();
+                    break;
+            }
+        }
+        boolean match_only = foundries == null || foundries.isEmpty();
+        String results;
+        try {
+            if (!match_only) {
+
+                ArrayList<String> foundryList = new ArrayList<String>();
+                ArrayList<String> layerList = new ArrayList<String>();
+
+                // EM: now without user, just list all foundries and
+                // layers
+                if (foundries.contains("*")) {
+                    foundryList = config.getFoundries();
+                    layerList = config.getLayers();
+                }
+                else {
+                    foundryList.addAll(foundries);
+                    layerList.addAll(layers);
+                }
+
+                results = searchKrill.getMatch(matchid, foundryList, layerList,
+                        spans, highlights, true, p);
+            }
+            else {
+                results = searchKrill.getMatch(matchid, p);
+            }
+        }
+        catch (Exception e) {
+            jlog.error("Exception in the MatchInfo service encountered!", e);
+            throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT,
+                    e.getMessage());
+        }
+        jlog.debug("MatchInfo results: " + results);
+        return results;
+    }
+
+    public String retrieveDocMetadata (String corpusId, String docId,
+            String textId) {
+        String textSigle = searchKrill.getTextSigle(corpusId, docId, textId);
+        return searchKrill.getFields(textSigle);
+    }
+
+    public String getCollocationBase (String query) throws KustvaktException {
+        return graphDBhandler.getResponse("distCollo", "q", query);
+    }
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/web/KustvaktResponseHandler.java b/core/src/main/java/de/ids_mannheim/korap/web/KustvaktResponseHandler.java
new file mode 100644
index 0000000..bce194c
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/web/KustvaktResponseHandler.java
@@ -0,0 +1,68 @@
+package de.ids_mannheim.korap.web;
+
+import java.util.EnumSet;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+
+import de.ids_mannheim.korap.constant.AuthenticationScheme;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
+import de.ids_mannheim.korap.interfaces.db.AuditingIface;
+
+/**
+ * KustvaktResponseHandler includes exceptions regarding
+ * authorization.
+ * 
+ * @author margaretha
+ *
+ */
+public class KustvaktResponseHandler extends CoreResponseHandler {
+
+    public KustvaktResponseHandler (AuditingIface iface) {
+        super(iface);
+    }
+
+    @Override
+    public WebApplicationException throwit (KustvaktException e) {
+        Response r;
+
+        // KustvaktException just wraps another exception
+        if (e.getStatusCode() == null && e.hasNotification()) {
+            r = Response.status(Response.Status.BAD_REQUEST)
+                    .entity(e.getNotification()).build();
+        }
+        else if (e.getStatusCode() == StatusCodes.USER_REAUTHENTICATION_REQUIRED
+                || e.getStatusCode() == StatusCodes.AUTHORIZATION_FAILED
+                || e.getStatusCode() >= StatusCodes.AUTHENTICATION_FAILED) {
+            String notification = buildNotification(e.getStatusCode(),
+                    e.getMessage(), e.getEntity());
+            r = createUnauthenticatedResponse(notification);
+        }
+        else if (e.hasNotification()) {
+            r = Response.status(getStatus(e.getStatusCode()))
+                    .entity(e.getNotification()).build();
+        }
+        else {
+            String notification = buildNotification(e.getStatusCode(),
+                    e.getMessage(), e.getEntity());
+            r = Response.status(getStatus(e.getStatusCode()))
+                    .entity(notification).build();
+        }
+        return new WebApplicationException(r);
+    }
+
+    public Response createUnauthenticatedResponse (String notification) {
+        ResponseBuilder builder = Response.status(Response.Status.UNAUTHORIZED);
+
+        for (AuthenticationScheme s : EnumSet
+                .allOf(AuthenticationScheme.class)) {
+            builder = builder.header(HttpHeaders.WWW_AUTHENTICATE,
+                    s.displayName() + " realm=\"Kustvakt\"");
+        }
+
+        return builder.entity(notification).build();
+    }
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/web/controller/AnnotationController.java b/core/src/main/java/de/ids_mannheim/korap/web/controller/AnnotationController.java
new file mode 100644
index 0000000..06b9957
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/web/controller/AnnotationController.java
@@ -0,0 +1,131 @@
+package de.ids_mannheim.korap.web.controller;
+
+import java.io.IOException;
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.sun.jersey.spi.container.ResourceFilters;
+
+import de.ids_mannheim.korap.dto.FoundryDto;
+import de.ids_mannheim.korap.dto.LayerDto;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
+import de.ids_mannheim.korap.service.AnnotationService;
+import de.ids_mannheim.korap.utils.JsonUtils;
+import de.ids_mannheim.korap.web.KustvaktResponseHandler;
+import de.ids_mannheim.korap.web.APIVersionFilter;
+import de.ids_mannheim.korap.web.filter.DemoUserFilter;
+import de.ids_mannheim.korap.web.filter.PiwikFilter;
+
+/**
+ * Provides services regarding annotation related information.
+ * 
+ * @author margaretha
+ *
+ */
+@Controller
+@Path("/{version}/annotation/")
+@ResourceFilters({APIVersionFilter.class, DemoUserFilter.class, PiwikFilter.class })
+@Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
+public class AnnotationController {
+
+    @Autowired
+    private KustvaktResponseHandler kustvaktResponseHandler;
+
+    @Autowired
+    private AnnotationService annotationService;
+
+    /**
+     * Returns information about all supported layers
+     * 
+     * @return a json serialization of all supported layers
+     */
+    @GET
+    @Path("layers")
+    public List<LayerDto> getLayers () {
+        return annotationService.getLayerDtos();
+    }
+
+
+    /**
+     * Returns a list of foundry descriptions.
+     * 
+     * @param codes
+     *            foundry-layer code or a Kleene-star
+     * @param language
+     *            2-letter language code (description language)
+     * @return a list of foundry, layer, value information in json
+     */
+    @SuppressWarnings("unchecked")
+    @POST
+    @Path("description")
+    @Consumes(MediaType.APPLICATION_JSON)
+    public List<FoundryDto> getFoundryDescriptions (String json) {
+        if (json == null || json.isEmpty()) {
+            throw kustvaktResponseHandler
+                    .throwit(new KustvaktException(StatusCodes.MISSING_PARAMETER,
+                            "Missing a json string.", ""));
+        }
+
+        JsonNode node;
+        try {
+            node = JsonUtils.readTree(json);
+        }
+        catch (KustvaktException e1) {
+            throw kustvaktResponseHandler.throwit(e1);
+        }
+
+        String language;
+        if (!node.has("language")) {
+            language = "en";
+        }
+        else {
+            language = node.get("language").asText();
+            if (language == null || language.isEmpty()) {
+                language = "en";
+            }
+            else if (!(language.equals("en") || language.equals("de"))) {
+                throw kustvaktResponseHandler.throwit(
+                        new KustvaktException(StatusCodes.UNSUPPORTED_VALUE,
+                                "Unsupported value:", language));
+            }
+        }
+
+        List<String> codes;
+        try {
+            codes = JsonUtils.convert(node.get("codes"), List.class);
+        }
+        catch (IOException | NullPointerException e) {
+            throw kustvaktResponseHandler.throwit(new KustvaktException(
+                    StatusCodes.INVALID_ARGUMENT, "Bad argument:", json));
+        }
+        if (codes == null) {
+            throw kustvaktResponseHandler.throwit(
+                    new KustvaktException(StatusCodes.MISSING_ATTRIBUTE,
+                            "Missing attribute:", "codes"));
+        }
+        else if (codes.isEmpty()) {
+            throw kustvaktResponseHandler
+                    .throwit(new KustvaktException(StatusCodes.NO_RESULT_FOUND,
+                            "No result found.", "codes:[]"));
+        }
+
+        try {
+            return annotationService.getFoundryDtos(codes, language);
+        }
+        catch (KustvaktException e) {
+            throw kustvaktResponseHandler.throwit(e);
+        }
+    }
+}
+
diff --git a/core/src/main/java/de/ids_mannheim/korap/web/controller/SearchController.java b/core/src/main/java/de/ids_mannheim/korap/web/controller/SearchController.java
new file mode 100644
index 0000000..90e9435
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/web/controller/SearchController.java
@@ -0,0 +1,327 @@
+package de.ids_mannheim.korap.web.controller;// package
+                                             // de.ids_mannheim.korap.ext.web;
+
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Set;
+
+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.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.SecurityContext;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+
+import com.sun.jersey.spi.container.ResourceFilters;
+
+import de.ids_mannheim.korap.constant.OAuth2Scope;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.oauth2.service.OAuth2ScopeService;
+import de.ids_mannheim.korap.security.context.TokenContext;
+import de.ids_mannheim.korap.service.SearchService;
+import de.ids_mannheim.korap.web.APIVersionFilter;
+import de.ids_mannheim.korap.web.KustvaktResponseHandler;
+import de.ids_mannheim.korap.web.filter.AuthenticationFilter;
+import de.ids_mannheim.korap.web.filter.DemoUserFilter;
+import de.ids_mannheim.korap.web.filter.PiwikFilter;
+
+/**
+ * 
+ * @author hanl, margaretha, diewald
+ * @date 29/01/2014
+ * @lastUpdate 09/07/2018
+ * 
+ */
+@Controller
+@Path("/")
+@ResourceFilters({ APIVersionFilter.class, AuthenticationFilter.class,
+        DemoUserFilter.class, PiwikFilter.class })
+@Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
+public class SearchController {
+
+    private static Logger jlog = LogManager.getLogger(SearchController.class);
+
+    @Autowired
+    private KustvaktResponseHandler kustvaktResponseHandler;
+
+    @Autowired
+    private SearchService searchService;
+    @Autowired
+    private OAuth2ScopeService scopeService;
+
+    /**
+     * Builds a json query serialization from the given parameters.
+     * 
+     * @param locale
+     * @param securityContext
+     * @param q
+     *            query string
+     * @param ql
+     *            query language
+     * @param v
+     *            version
+     * @param context
+     * @param cutoff
+     *            true if the number of results should be limited
+     * @param pageLength
+     *            number of results per page
+     * @param pageIndex
+     * @param startPage
+     * @param cq
+     *            corpus query
+     * @return
+     */
+    // ref query parameter removed!
+    @GET
+    @Path("{version}/query")
+    public Response serializeQuery (@Context Locale locale,
+            @Context SecurityContext securityContext, @QueryParam("q") String q,
+            @QueryParam("ql") String ql, @QueryParam("v") String v,
+            @QueryParam("context") String context,
+            @QueryParam("cutoff") Boolean cutoff,
+            @QueryParam("count") Integer pageLength,
+            @QueryParam("offset") Integer pageIndex,
+            @QueryParam("page") Integer startPage,
+            @QueryParam("cq") String cq) {
+        TokenContext ctx = (TokenContext) securityContext.getUserPrincipal();
+        try {
+            scopeService.verifyScope(ctx, OAuth2Scope.SERIALIZE_QUERY);
+            String result = searchService.serializeQuery(q, ql, v, cq,
+                    pageIndex, startPage, pageLength, context, cutoff);
+            jlog.debug("Query: " + result);
+            return Response.ok(result).build();
+        }
+        catch (KustvaktException e) {
+            throw kustvaktResponseHandler.throwit(e);
+        }
+    }
+
+    @POST
+    @Path("{version}/search")
+    public Response searchPost (@Context SecurityContext context,
+            @Context Locale locale, @QueryParam("engine") String engine,
+            String jsonld) {
+        TokenContext ctx = (TokenContext) context.getUserPrincipal();
+        try {
+            scopeService.verifyScope(ctx, OAuth2Scope.SEARCH);
+        }
+        catch (KustvaktException e) {
+            throw kustvaktResponseHandler.throwit(e);
+        }
+
+        jlog.debug("Serialized search: " + jsonld);
+        String result = searchService.search(jsonld);
+        jlog.debug("The result set: " + result);
+        return Response.ok(result).build();
+    }
+
+    @GET
+    @Path("{version}/search")
+    public Response searchGet (@Context SecurityContext securityContext,
+            @Context HttpHeaders headers, @Context Locale locale,
+            @QueryParam("q") String q, @QueryParam("ql") String ql,
+            @QueryParam("v") String v, @QueryParam("context") String ctx,
+            @QueryParam("cutoff") Boolean cutoff,
+            @QueryParam("count") Integer pageLength,
+            @QueryParam("offset") Integer pageIndex,
+            @QueryParam("page") Integer pageInteger,
+            @QueryParam("fields") Set<String> fields,
+            @QueryParam("cq") String cq, @QueryParam("engine") String engine) {
+
+        TokenContext context =
+                (TokenContext) securityContext.getUserPrincipal();
+
+        String result;
+        try {
+            scopeService.verifyScope(context, OAuth2Scope.SEARCH);
+            result = searchService.search(engine, context.getUsername(),
+                    headers, q, ql, v, cq, fields, pageIndex, pageInteger, ctx,
+                    pageLength, cutoff);
+        }
+        catch (KustvaktException e) {
+            throw kustvaktResponseHandler.throwit(e);
+        }
+
+        return Response.ok(result).build();
+    }
+
+    @GET
+    @Path("{version}/corpus/{corpusId}/{docId}/{textId}/{matchId}/matchInfo")
+    public Response getMatchInfo (@Context SecurityContext ctx,
+            @Context HttpHeaders headers, @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, 
+            // Highlights may also be a list of valid highlight classes
+            @QueryParam("hls") Boolean highlights) throws KustvaktException {
+
+        TokenContext tokenContext = (TokenContext) ctx.getUserPrincipal();
+        scopeService.verifyScope(tokenContext, OAuth2Scope.MATCH_INFO);
+        spans = spans != null ? spans : false;
+        highlights = highlights != null ? highlights : false;
+        if (layers == null || layers.isEmpty()) layers = new HashSet<>();
+
+        String results = searchService.retrieveMatchInfo(corpusId, docId,
+                textId, matchId, foundries, tokenContext.getUsername(), headers,
+                layers, spans, highlights);
+        return Response.ok(results).build();
+    }
+
+    /*
+     * Returns the meta data fields of a certain document
+     */
+    // This is currently identical to LiteService#getMeta(),
+    // but may need auth code to work following policies
+    @GET
+    @Path("{version}/corpus/{corpusId}/{docId}/{textId}")
+    public Response getMetadata (@PathParam("corpusId") String corpusId,
+            @PathParam("docId") String docId, @PathParam("textId") String textId
+    // @QueryParam("fields") Set<String> fields
+    ) throws KustvaktException {
+        String results =
+                searchService.retrieveDocMetadata(corpusId, docId, textId);
+        return Response.ok(results).build();
+    }
+
+    @POST
+    @Path("{version}/colloc")
+    public Response getCollocationBase (@QueryParam("q") String query) {
+        String result;
+        try {
+            result = searchService.getCollocationBase(query);
+        }
+        catch (KustvaktException e) {
+            throw kustvaktResponseHandler.throwit(e);
+        }
+        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());
+    //
+    // KustvaktResource resource = this.resourceHandler
+    // .findbyStrId(id, user, type);
+    //
+    // if (resource instanceof VirtualCollection)
+    // cquery.addResource(
+    // ((VirtualCollection) resource).getQuery());
+    // else if (resource instanceof Corpus)
+    // cquery.addMetaFilter("corpusID",
+    // resource.getPersistentID());
+    // else
+    // throw KustvaktResponseHandler
+    // .throwit(StatusCodes.ILLEGAL_ARGUMENT,
+    // "Type parameter not supported", type);
+    //
+    // }catch (KustvaktException e) {
+    // throw KustvaktResponseHandler.throwit(e);
+    // }catch (NumberFormatException ex) {
+    // throw KustvaktResponseHandler
+    // .throwit(StatusCodes.ILLEGAL_ARGUMENT);
+    // }
+    //
+    // builder = functions
+    // .buildCollocations(query, ql, properties, context, limit,
+    // sfs, foundry, new ArrayList<Dependency>(), wPaths,
+    // cquery);
+    //
+    // result = graphDBhandler
+    // .getResponse("distCollo", "q", builder.build().toJSON());
+    //
+    // }catch (JsonProcessingException e) {
+    // throw
+    // KustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT);
+    // }catch (KustvaktException e) {
+    // throw KustvaktResponseHandler.throwit(e);
+    // }
+    //
+    // return Response.ok(result).build();
+    // }
+
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/web/controller/StatisticController.java b/core/src/main/java/de/ids_mannheim/korap/web/controller/StatisticController.java
new file mode 100644
index 0000000..43970be
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/web/controller/StatisticController.java
@@ -0,0 +1,94 @@
+package de.ids_mannheim.korap.web.controller;
+
+import java.util.Locale;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+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 javax.ws.rs.core.SecurityContext;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+
+import com.sun.jersey.spi.container.ResourceFilters;
+
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
+import de.ids_mannheim.korap.utils.KoralCollectionQueryBuilder;
+import de.ids_mannheim.korap.web.CoreResponseHandler;
+import de.ids_mannheim.korap.web.SearchKrill;
+import de.ids_mannheim.korap.web.APIVersionFilter;
+import de.ids_mannheim.korap.web.filter.PiwikFilter;
+
+/**
+ * Web services related to statistics
+ * 
+ * @author hanl
+ * @author margaretha
+ *
+ * @date 08/11/2017
+ * 
+ */
+@Controller
+@Path("{version}/statistics/")
+@ResourceFilters({APIVersionFilter.class, PiwikFilter.class })
+@Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
+public class StatisticController {
+
+
+    private static Logger jlog =
+            LogManager.getLogger(StatisticController.class);
+    @Autowired
+    private CoreResponseHandler kustvaktResponseHandler;
+    @Autowired
+    private SearchKrill searchKrill;
+
+
+    /**
+     * Returns statistics of the virtual corpus defined by the given
+     * corpusQuery parameter.
+     * 
+     * @param context
+     *            SecurityContext
+     * @param locale
+     *            Locale
+     * @param corpusQuery
+     *            a collection query specifying a virtual corpus
+     * @return statistics of the virtual corpus defined by the given
+     *         corpusQuery parameter.
+     */
+    @GET
+    public Response getStatistics (@Context SecurityContext context,
+            @Context Locale locale,
+            @QueryParam("corpusQuery") String corpusQuery) {
+
+        KoralCollectionQueryBuilder builder = new KoralCollectionQueryBuilder();
+
+		String stats;
+		if (corpusQuery != null && !corpusQuery.isEmpty()) {
+			builder.with(corpusQuery);
+			String json = null;
+			try {
+				json = builder.toJSON();
+			}
+			catch (KustvaktException e) {
+				throw kustvaktResponseHandler.throwit(e);
+			}
+			stats = searchKrill.getStatistics(json);
+		}
+		else {
+			stats = searchKrill.getStatistics(null);
+		};
+
+        if (stats.contains("-1"))
+            throw kustvaktResponseHandler.throwit(StatusCodes.NO_RESULT_FOUND);
+        jlog.debug("Stats: " + stats);
+        return Response.ok(stats).build();
+    }
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/web/filter/AuthenticationFilter.java b/core/src/main/java/de/ids_mannheim/korap/web/filter/AuthenticationFilter.java
new file mode 100644
index 0000000..d0e4562
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/web/filter/AuthenticationFilter.java
@@ -0,0 +1,132 @@
+package de.ids_mannheim.korap.web.filter;
+
+import javax.ws.rs.ext.Provider;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+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.authentication.AuthenticationManager;
+import de.ids_mannheim.korap.authentication.http.AuthorizationData;
+import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
+import de.ids_mannheim.korap.constant.TokenType;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
+import de.ids_mannheim.korap.security.context.KustvaktContext;
+import de.ids_mannheim.korap.security.context.TokenContext;
+import de.ids_mannheim.korap.utils.TimeUtils;
+import de.ids_mannheim.korap.web.KustvaktResponseHandler;
+
+/**
+ * @author hanl, margaretha
+ * @date 28/01/2014
+ * @last update 12/2017
+ */
+@Component
+@Provider
+public class AuthenticationFilter
+        implements ContainerRequestFilter, ResourceFilter {
+
+    @Autowired
+    private HttpAuthorizationHandler authorizationHandler;
+
+    @Autowired
+    private AuthenticationManager authenticationManager;
+
+    @Autowired
+    private KustvaktResponseHandler kustvaktResponseHandler;
+
+    @Override
+    public ContainerRequest filter (ContainerRequest request) {
+        String host = request.getHeaderValue(ContainerRequest.HOST);
+        String ua = request.getHeaderValue(ContainerRequest.USER_AGENT);
+
+        String authorization =
+                request.getHeaderValue(ContainerRequest.AUTHORIZATION);
+
+        if (authorization != null && !authorization.isEmpty()) {
+            TokenContext context = null;
+            AuthorizationData authData;
+            try {
+                authData = authorizationHandler
+                        .parseAuthorizationHeaderValue(authorization);
+
+                switch (authData.getAuthenticationScheme()) {
+                    // EM: For testing only, must be disabled for
+                    // production
+                    case BASIC:
+                        context = authenticationManager.getTokenContext(
+                                TokenType.BASIC, authData.getToken(), host, ua);
+                        break;
+                    // EM: has not been tested yet
+                    // case SESSION:
+                    // context =
+                    // authenticationManager.getTokenContext(
+                    // TokenType.SESSION, authData.getToken(), host,
+                    // ua);
+                    // break;
+
+                    // OAuth2 authentication scheme
+                    case BEARER:
+                        context = authenticationManager.getTokenContext(
+                                TokenType.BEARER, authData.getToken(), host,
+                                ua);
+                        break;
+                    // EM: JWT token-based authentication scheme
+                    case API:
+                        context = authenticationManager.getTokenContext(
+                                TokenType.API, authData.getToken(), host, ua);
+                        break;
+                    default:
+                        throw new KustvaktException(
+                                StatusCodes.AUTHENTICATION_FAILED,
+                                "Authentication scheme is not supported.");
+                }
+                checkContext(context, request);
+                request.setSecurityContext(new KustvaktContext(context));
+            }
+            catch (KustvaktException e) {
+                throw kustvaktResponseHandler.throwit(e);
+            }
+        }
+        return request;
+    }
+
+
+    private void checkContext (TokenContext context, ContainerRequest request)
+            throws KustvaktException {
+        if (context == null) {
+            throw new KustvaktException(StatusCodes.AUTHENTICATION_FAILED,
+                    "Context is null.");
+        }
+        else if (!context.isValid()) {
+            throw new KustvaktException(StatusCodes.AUTHENTICATION_FAILED,
+                    "Context is not valid: "
+                            + "missing username, password or authentication scheme.");
+        }
+        else if (context.isSecureRequired() && !request.isSecure()) {
+            throw new KustvaktException(StatusCodes.AUTHENTICATION_FAILED,
+                    "Request is not secure.");
+        }
+        else if (TimeUtils.isExpired(context.getExpirationTime())) {
+            throw new KustvaktException(StatusCodes.EXPIRED,
+                    "Access token is expired");
+        }
+    }
+
+
+    @Override
+    public ContainerRequestFilter getRequestFilter () {
+        return this;
+    }
+
+
+    @Override
+    public ContainerResponseFilter getResponseFilter () {
+        return null;
+    }
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/web/filter/BlockingFilter.java b/core/src/main/java/de/ids_mannheim/korap/web/filter/BlockingFilter.java
new file mode 100644
index 0000000..8375b62
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/web/filter/BlockingFilter.java
@@ -0,0 +1,65 @@
+package de.ids_mannheim.korap.web.filter;
+
+import javax.ws.rs.ext.Provider;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+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.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
+import de.ids_mannheim.korap.security.context.TokenContext;
+import de.ids_mannheim.korap.web.KustvaktResponseHandler;
+
+/**
+ * @author hanl
+ * @date 11/12/2014
+ *       <p/>
+ *       endpoint filter to block access to an endpoint, in case no
+ *       anonymous access should be allowed!
+ */
+@Component
+@Provider
+public class BlockingFilter implements ContainerRequestFilter, ResourceFilter {
+
+    @Autowired
+    private KustvaktResponseHandler kustvaktResponseHandler;
+
+    @Override
+    public ContainerRequest filter (ContainerRequest request) {
+        TokenContext context;
+
+        try {
+            context = (TokenContext) request.getUserPrincipal();
+        }
+        catch (UnsupportedOperationException e) {
+            throw kustvaktResponseHandler.throwit(new KustvaktException(
+                    StatusCodes.UNSUPPORTED_OPERATION, e.getMessage(), e));
+        }
+
+        if (context == null || context.isDemo()) {
+            throw kustvaktResponseHandler.throwit(new KustvaktException(
+                    StatusCodes.AUTHORIZATION_FAILED,
+                    "Unauthorized operation for user: guest", "guest"));
+        }
+
+
+        return request;
+    }
+
+
+    @Override
+    public ContainerRequestFilter getRequestFilter () {
+        return this;
+    }
+
+
+    @Override
+    public ContainerResponseFilter getResponseFilter () {
+        return null;
+    }
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/web/filter/DemoFilter.java b/core/src/main/java/de/ids_mannheim/korap/web/filter/DemoFilter.java
new file mode 100644
index 0000000..b15f5e3
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/web/filter/DemoFilter.java
@@ -0,0 +1,67 @@
+package de.ids_mannheim.korap.web.filter;
+
+import javax.ws.rs.core.SecurityContext;
+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.authentication.http.HttpAuthorizationHandler;
+import de.ids_mannheim.korap.constant.TokenType;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.security.context.KustvaktContext;
+import de.ids_mannheim.korap.security.context.TokenContext;
+
+/**
+ * @author hanl
+ * @date 08/02/2016
+ */
+@Provider
+public class DemoFilter implements ContainerRequestFilter, ResourceFilter {
+
+    @Override
+    public ContainerRequest filter (ContainerRequest request) {
+        String authentication =
+                request.getHeaderValue(ContainerRequest.AUTHORIZATION);
+        if (authentication == null || authentication.isEmpty()) {
+            try {
+                request.getUserPrincipal();
+            }
+            catch (UnsupportedOperationException e) {
+                request.setSecurityContext(createContext());
+            }
+        }
+        return request;
+    }
+
+
+    private SecurityContext createContext () {
+        TokenContext context = new TokenContext();
+        String token = null;
+        try {
+            token = HttpAuthorizationHandler
+                    .createBasicAuthorizationHeaderValue("demo", "demo2015");
+        }
+        catch (KustvaktException e) {
+            e.printStackTrace();
+        }
+        context.setToken(token);
+        context.setTokenType(TokenType.BASIC);
+        context.setUsername("demo");
+        return new KustvaktContext(context);
+    }
+
+
+    @Override
+    public ContainerRequestFilter getRequestFilter () {
+        return this;
+    }
+
+
+    @Override
+    public ContainerResponseFilter getResponseFilter () {
+        return null;
+    }
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/web/filter/DemoUserFilter.java b/core/src/main/java/de/ids_mannheim/korap/web/filter/DemoUserFilter.java
new file mode 100644
index 0000000..e546c12
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/web/filter/DemoUserFilter.java
@@ -0,0 +1,86 @@
+package de.ids_mannheim.korap.web.filter;
+
+import java.security.Principal;
+
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.Provider;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+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.KustvaktConfiguration;
+import de.ids_mannheim.korap.constant.TokenType;
+import de.ids_mannheim.korap.security.context.KustvaktContext;
+import de.ids_mannheim.korap.security.context.TokenContext;
+import de.ids_mannheim.korap.user.User;
+import de.ids_mannheim.korap.utils.TimeUtils;
+
+/**
+ * Created by hanl on 7/15/14.
+ */
+@Provider
+@Component
+public class DemoUserFilter implements ContainerRequestFilter, ResourceFilter {
+
+    @Context
+    UriInfo info;
+    @Autowired
+    private KustvaktConfiguration config;
+
+
+    @Override
+    public ContainerRequest filter (ContainerRequest request) {
+        String host = request.getHeaderValue(ContainerRequest.HOST);
+        String ua = request.getHeaderValue(ContainerRequest.USER_AGENT);
+        String authentication = request
+                .getHeaderValue(ContainerRequest.AUTHORIZATION);
+
+        // means that this is the public service
+        if (authentication == null || authentication.isEmpty()) {
+            Principal pr = null;
+            try {
+                pr = request.getUserPrincipal();
+            }
+            catch (UnsupportedOperationException e) {
+                // do nothing
+            }
+            if (pr == null)
+                request.setSecurityContext(new KustvaktContext(
+                        createShorterToken(host, ua)));
+
+        }
+        return request;
+    }
+
+
+    private TokenContext createShorterToken (String host, String agent) {
+        User demo = User.UserFactory.getDemoUser();
+        TokenContext c = new TokenContext();
+        c.setUsername(demo.getUsername());
+        c.setHostAddress(host);
+        c.setUserAgent(agent);
+        c.setExpirationTime(TimeUtils.plusSeconds(
+                config
+                        .getShortTokenTTL()).getMillis());
+        c.setTokenType(TokenType.BASIC);
+        return c;
+    }
+
+
+    @Override
+    public ContainerRequestFilter getRequestFilter () {
+        return this;
+    }
+
+
+    @Override
+    public ContainerResponseFilter getResponseFilter () {
+        return null;
+    }
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/web/filter/NonDemoBlockingFilter.java b/core/src/main/java/de/ids_mannheim/korap/web/filter/NonDemoBlockingFilter.java
new file mode 100644
index 0000000..47cd086
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/web/filter/NonDemoBlockingFilter.java
@@ -0,0 +1,65 @@
+package de.ids_mannheim.korap.web.filter;
+
+import javax.ws.rs.ext.Provider;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+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.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
+import de.ids_mannheim.korap.security.context.TokenContext;
+import de.ids_mannheim.korap.web.KustvaktResponseHandler;
+
+/**
+ * EM: pretty much identical to {@link BlockingFilter}, should be deleted? 
+ * 
+ * @author hanl
+ * @date 11/12/2014
+ *       <p/>
+ *       endpoint filter to block access to an endpoint, in case no
+ *       anonymous access should be allowed!
+ */
+@Component
+@Provider
+public class NonDemoBlockingFilter
+        implements ContainerRequestFilter, ResourceFilter {
+
+    @Autowired
+    private KustvaktResponseHandler kustvaktResponseHandler;
+
+    @Override
+    public ContainerRequest filter (ContainerRequest request) {
+        TokenContext context;
+        try {
+            context = (TokenContext) request.getUserPrincipal();
+        }
+        catch (UnsupportedOperationException e) {
+            throw kustvaktResponseHandler.throwit(new KustvaktException(
+                    StatusCodes.UNSUPPORTED_OPERATION, e.getMessage(), e));
+        }
+
+        if (context == null || context.isDemo()) {
+            throw kustvaktResponseHandler.throwit(
+                    new KustvaktException(StatusCodes.AUTHORIZATION_FAILED,
+                            "Operation is not permitted for guest users"));
+        }
+        return request;
+    }
+
+
+    @Override
+    public ContainerRequestFilter getRequestFilter () {
+        return this;
+    }
+
+
+    @Override
+    public ContainerResponseFilter getResponseFilter () {
+        return null;
+    }
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/web/filter/PiwikFilter.java b/core/src/main/java/de/ids_mannheim/korap/web/filter/PiwikFilter.java
new file mode 100644
index 0000000..122f717
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/korap/web/filter/PiwikFilter.java
@@ -0,0 +1,164 @@
+package de.ids_mannheim.korap.web.filter;
+
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Random;
+
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.ext.Provider;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.api.client.config.ClientConfig;
+import com.sun.jersey.api.client.config.DefaultClientConfig;
+import com.sun.jersey.api.client.filter.LoggingFilter;
+import com.sun.jersey.core.util.MultivaluedMapImpl;
+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.authentication.AuthenticationManager;
+import de.ids_mannheim.korap.config.Attributes;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.security.context.TokenContext;
+import de.ids_mannheim.korap.user.User;
+import de.ids_mannheim.korap.user.UserSettings;
+import de.ids_mannheim.korap.user.Userdata;
+import net.minidev.json.JSONArray;
+
+/**
+ * @author hanl
+ * @date 13/05/2014
+ */
+@Component
+@Provider
+public class PiwikFilter implements ContainerRequestFilter, ResourceFilter {
+
+    private WebResource service;
+    //    private static final String SERVICE = "http://localhost:8888";
+    private static final String SERVICE = "http://10.0.10.13";
+    private static Logger jlog = LogManager.getLogger(PiwikFilter.class);
+    public static boolean ENABLED = false;
+    private Map<String, String> customVars;
+    @Autowired
+    private AuthenticationManager authenticationManager;
+
+
+    public PiwikFilter () {
+//        controller = BeansFactory.getKustvaktContext()
+//                .getAuthenticationManager();
+        ClientConfig config = new DefaultClientConfig();
+        Client client = Client.create(config);
+        if (jlog.isDebugEnabled())
+            client.addFilter(new LoggingFilter());
+        UriBuilder b = UriBuilder.fromUri(SERVICE);
+        service = client.resource(b.build());
+        this.customVars = new HashMap<>();
+    }
+
+
+    private void send (ContainerRequest request) {
+        Random random = new SecureRandom();
+        MultivaluedMap<String, String> params = new MultivaluedMapImpl();
+        params.add("idsite", "2");
+        params.add("rec", "1");
+        if (!customVars.isEmpty())
+            params.add("_cvar", translateCustomData());
+        params.add("cip", request.getHeaderValue("Host"));
+        params.add("cookie", "false");
+        params.add("r", String.valueOf(random.nextDouble()));
+        params.add("action_name", request.getRequestUri().toASCIIString());
+
+        Locale l = null;
+        if (request.getAcceptableLanguages() != null)
+            l = request.getAcceptableLanguages().get(0);
+        try {
+            service.path("piwik/piwik.php")
+                    .queryParam("idsite", "2")
+                    .queryParam("rec", "1")
+                    //todo check for empty container
+                    .queryParam("_cvar", translateCustomData())
+                    .queryParam("cip", request.getHeaderValue("Host"))
+                    .queryParam("cookie", "false")
+                    .queryParam("r", String.valueOf(random.nextDouble()))
+                    .queryParam("action_name",
+                            request.getRequestUri().toASCIIString())
+                    .queryParams(params).accept("text/html")
+                    .header("Host", request.getHeaderValue("Host"))
+                    .header("User-Agent", request.getHeaderValue("User-Agent"))
+                    .acceptLanguage(l).method("GET");
+        }
+        catch (Exception e) {
+            // do nothing if piwik not available!
+        }
+    }
+
+
+    private String translateCustomData () {
+        final Map<String, List<String>> customVariables = new HashMap<String, List<String>>();
+        int i = 0;
+        for (final Map.Entry<String, String> entry : this.customVars.entrySet()) {
+            i++;
+            final List<String> list = new ArrayList<String>();
+            list.add(entry.getKey());
+            list.add(entry.getValue());
+            customVariables.put(Integer.toString(i), list);
+        }
+
+        final JSONArray json = new JSONArray();
+        json.add(customVariables);
+
+        // remove unnecessary parent square brackets from JSON-string
+        String jsonString = json.toString().substring(1,
+                json.toString().length() - 1);
+        customVars.clear();
+        return jsonString;
+    }
+
+
+    @Override
+    public ContainerRequest filter (ContainerRequest request) {
+        if (ENABLED) {
+            try {
+                TokenContext context = (TokenContext) request
+                        .getUserPrincipal();
+                if (context.getUsername() != null){
+                    // since this is cached, not very expensive!
+                    User user = authenticationManager.getUser(context.getUsername());
+                    Userdata data = authenticationManager
+                            .getUserData(user, UserSettings.class);
+                    if ((Boolean) data.get(Attributes.COLLECT_AUDITING_DATA))
+                        customVars.put("username", context.getUsername());
+                }
+            }
+            catch (KustvaktException | UnsupportedOperationException e) {
+                //do nothing
+            }
+            send(request);
+        }
+        return request;
+    }
+
+
+    @Override
+    public ContainerRequestFilter getRequestFilter () {
+        return this;
+    }
+
+
+    @Override
+    public ContainerResponseFilter getResponseFilter () {
+        return null;
+    }
+}
diff --git a/core/src/main/resources/annotation-scripts/foundries/base.js b/core/src/main/resources/annotation-scripts/foundries/base.js
new file mode 100644
index 0000000..a21cce6
--- /dev/null
+++ b/core/src/main/resources/annotation-scripts/foundries/base.js
@@ -0,0 +1,15 @@
+define(["hint/foundries"], function (ah) {
+  ah["-"].push(
+    ["Base Annotation", "base/", "Structure"]
+  );
+  
+  ah["base/"] = [
+	["Structure", "s="]
+  ];
+  
+  ah["base/s="] = [
+    ["s", "s", "Sentence"],
+    ["p", "p", "Paragraph"],
+    ["t", "t", "Text"]
+  ];
+});
diff --git a/core/src/main/resources/annotation-scripts/foundries/cnx.js b/core/src/main/resources/annotation-scripts/foundries/cnx.js
new file mode 100644
index 0000000..9316cbd
--- /dev/null
+++ b/core/src/main/resources/annotation-scripts/foundries/cnx.js
@@ -0,0 +1,63 @@
+define(["hint/foundries"], function (ah) {
+  ah["-"].push(
+    ["Connexor", "cnx/", "Constituency, Lemma, Morphology, Part-of-Speech, Syntax"]
+  );
+
+  ah["cnx/"] = [
+    ["Constituency", "c="],
+    ["Lemma", "l="],
+    ["Morphology", "m="],
+    ["Part-of-Speech", "p="],
+    ["Syntax", "syn="]
+  ];
+
+  ah["cnx/c="] = [
+    ["np", "np ", "Nominal Phrase"]
+  ];
+
+  // http://www.ids-mannheim.de/cosmas2/projekt/referenz/connexor/morph.html
+  ah["cnx/m="] = [
+    ["Abbr","Abbr ", "Nouns: Abbreviation"],
+    ["CMP","CMP ", "Adjective: Comparative"],
+    ["IMP", "IMP ", "Mood: Imperative"],
+    ["IND", "IND ", "Mood: Indicative"],
+    ["INF", "INF ", "Infinitive"],
+    ["ORD","ORD ", "Numeral: Ordinal"],
+    ["PAST", "PAST ", "Tense: past"],
+    ["PCP", "PCP ", "Participle"],
+    ["PERF", "PERF ", "Perfective Participle"],
+    ["PL","PL ", "Nouns: Plural"],
+    ["PRES", "PRES ", "Tense: present"],
+    ["PROG", "PROG ", "Progressive Participle"],
+    ["Prop","Prop ", "Nouns: Proper Noun"],
+    ["SUB", "SUB ", "Mood: Subjunctive"],
+    ["SUP","SUP ", "Adjective: Superlative"]
+  ];
+
+  // http://www.ids-mannheim.de/cosmas2/projekt/referenz/connexor/morph.html
+  ah["cnx/p="] = [
+    ["A", "A ", "Adjective"],
+    ["ADV", "ADV ", "Adverb"],
+    ["CC", "CC ", "Coordination Marker"],
+    ["CS", "CS ", "Clause Marker"],
+    ["DET", "DET ", "Determiner"],
+    ["INTERJ", "INTERJ ", "Interjection"],
+    ["N", "N ", "Noun"],
+    ["NUM", "NUM ", "Numeral"],
+    ["PREP", "PREP ", "Preposition"],
+    ["PRON", "PRON ", "Pro-Nominal"],
+    ["V", "V ", "Verb"]
+  ];
+
+  // http://www.ids-mannheim.de/cosmas2/projekt/referenz/connexor/syntax.html
+  ah["cnx/syn="] = [
+    ["@ADVL", "@ADVL ", "Adverbial Head"],
+    ["@AUX", "@AUX ", "Auxiliary Verb"],
+    ["@CC", "@CC ", "Coordination"]
+    ["@MAIN", "@MAIN ", "Main Verb"],
+    ["@NH", "@NH ", "Nominal Head"],
+    ["@POSTMOD", "@POSTMOD ", "Postmodifier"],
+    ["@PREMARK", "@PREMARK ", "Preposed Marker"],
+    ["@PREMOD", "@PREMOD ", "Premodifier"]
+  ];
+});
diff --git a/core/src/main/resources/annotation-scripts/foundries/corenlp.js b/core/src/main/resources/annotation-scripts/foundries/corenlp.js
new file mode 100644
index 0000000..ff3b44a
--- /dev/null
+++ b/core/src/main/resources/annotation-scripts/foundries/corenlp.js
@@ -0,0 +1,1374 @@
+define(["hint/foundries","hint/foundries/stts","hint/foundries/negranodes","hint/foundries/negraedges"],
+       function (ah, sttsArray, negraNodesArray, negraEdgesArray) {
+
+  ah["-"].push(
+    ["CoreNLP", "corenlp/", "Constituency, Named Entities, Part-of-Speech"]
+  );
+
+  ah["corenlp/"] = [
+    ["Constituency", "c="],
+    ["Named Entity", "ne=" , "Combined"],
+    ["Named Entity", "ne_dewac_175m_600=" , "ne_dewac_175m_600"],
+    ["Named Entity", "ne_hgc_175m_600=",    "ne_hgc_175m_600"],
+    ["Part-of-Speech", "p="]
+  ];
+
+  ah["corenlp/ne="] = [
+	["I-LOC",  "I-LOC ",  "Location"],
+	["I-MISC", "I-MISC ", "Miscellaneous"],
+	["I-ORG",  "I-ORG ",  "Organization"],
+	["I-PER",  "I-PER ",  "Person"]
+  ];
+  
+  ah["corenlp/ne_dewac_175m_600="] = [
+	["I-LOC",  "I-LOC ",  "Location"],
+	["I-MISC", "I-MISC ", "Miscellaneous"],
+	["I-ORG",  "I-ORG ",  "Organization"],
+	["I-PER",  "I-PER ",  "Person"]
+  ];
+	  
+  ah["corenlp/ne_hgc_175m_600="] = [
+	["I-LOC",  "I-LOC ",  "Location"],
+	["I-MISC", "I-MISC ", "Miscellaneous"],
+	["I-ORG",  "I-ORG ",  "Organization"],
+	["I-PER",  "I-PER ",  "Person"]
+  ];
+	  
+  ah["corenlp/p="] = [
+    ["ADJA","ADJA ", "Attributive Adjective"],
+    ["ADJD","ADJD ", "Predicative Adjective"],
+    ["ADV","ADV ", "Adverb"],
+    ["APPO","APPO ", "Postposition"],
+    ["APPR","APPR ", "Preposition"],
+    ["APPRART","APPRART ", "Preposition with Determiner"],
+    ["APZR","APZR ","Right Circumposition"],
+    ["ART","ART ", "Determiner"],
+    ["CARD","CARD ", "Cardinal Number"],
+    ["FM","FM ", "Foreign Material"],
+    ["ITJ","ITJ ", "Interjection"],
+    ["KOKOM","KOKOM ", "Comparison Particle"],
+    ["KON","KON ", "Coordinating Conjuncion"],
+    ["KOUI","KOUI ", "Subordinating Conjunction with 'zu'"],
+    ["KOUS","KOUS ", "Subordinating Conjunction with Sentence"],
+    ["NE","NE ", "Named Entity"],
+    ["NN","NN ", "Normal Nomina"],
+    ["PAV", "PAV ", "Pronominal Adverb"],
+    ["PDAT","PDAT ","Attributive Demonstrative Pronoun"],
+    ["PDS","PDS ", "Substitutive Demonstrative Pronoun"],
+    ["PIAT","PIAT ", "Attributive Indefinite Pronoun without Determiner"],
+    ["PIDAT","PIDAT ", "Attributive Indefinite Pronoun with Determiner"],
+    ["PIS","PIS ", "Substitutive Indefinite Pronoun"],
+    ["PPER","PPER ", "Personal Pronoun"],
+    ["PPOSAT","PPOSAT ", "Attributive Possessive Pronoun"],
+    ["PPOSS","PPOSS ", "Substitutive Possessive Pronoun"],
+    ["PRELAT","PRELAT ", "Attributive Relative Pronoun"],
+    ["PRELS","PRELS ", "Substitutive Relative Pronoun"],
+    ["PRF","PRF ", "Reflexive Pronoun"],
+    ["PROAV","PROAV ", "Pronominal Adverb"],
+    ["PTKA","PTKA ","Particle with Adjective"],
+    ["PTKANT","PTKANT ", "Answering Particle"],
+    ["PTKNEG","PTKNEG ", "Negation Particle"],
+    ["PTKVZ","PTKVZ ", "Separated Verbal Particle"],
+    ["PTKZU","PTKZU ", "'zu' Particle"],
+    ["PWAT","PWAT ", "Attributive Interrogative Pronoun"],
+    ["PWAV","PWAV ", "Adverbial Interrogative Pronoun"],
+    ["PWS","PWS ", "Substitutive Interrogative Pronoun"],
+    ["TRUNC","TRUNC ","Truncated"],
+    ["VAFIN","VAFIN ", "Auxiliary Finite Verb"],
+    ["VAIMP","VAIMP ", "Auxiliary Finite Imperative Verb"],
+    ["VAINF","VAINF ", "Auxiliary Infinite Verb"],
+    ["VAPP","VAPP ", "Auxiliary Perfect Participle"],
+    ["VMFIN","VMFIN ", "Modal Finite Verb"],
+    ["VMINF","VMINF ", "Modal Infinite Verb"],
+    ["VMPP","VMPP ", "Modal Perfect Participle"],
+    ["VVFIN","VVFIN ","Finite Verb"],
+    ["VVIMP","VVIMP ", "Finite Imperative Verb"],
+    ["VVINF","VVINF ", "Infinite Verb"],
+    ["VVIZU","VVIZU ", "Infinite Verb with 'zu'"],
+    ["VVPP","VVPP ", "Perfect Participle"],
+    ["XY", "XY ", "Non-Word"]
+  ];
+  
+  ah["corenlp/c="] = [
+    ["AA", "AA", "superlative phrase with 'am'"],
+    ["AP","AP", "adjektive phrase"],
+    ["AVP","AVP", "adverbial phrase"],
+    ["CAP","CAP", "coordinated adjektive phrase"],
+    ["CAVP","CAVP", "coordinated adverbial phrase"],
+    ["CAC","CAC", "coordinated adposition"],
+    ["CCP","CCP", "coordinated complementiser"],
+    ["CH","CH", "chunk"],
+    ["CNP","CNP", "coordinated noun phrase"],
+    ["CO","CO", "coordination"],
+    ["CPP","CPP", "coordinated adpositional phrase"],
+    ["CS","CS", "coordinated sentence"],
+    ["CVP","CVP", "coordinated verb phrase (non-finite)"],
+    ["CVZ","CVZ", "coordinated zu-marked infinitive"],
+    ["DL","DL", "discourse level constituent"],
+    ["ISU","ISU", "idiosyncratis unit"],
+    ["MPN","MPN", "multi-word proper noun"],
+    ["MTA","MTA", "multi-token adjective"],
+    ["NM","NM", "multi-token number"],
+    ["NP","NP", "noun phrase"],
+    ["PP","PP", "adpositional phrase"],
+    ["QL","QL", "quasi-languag"],
+    ["ROOT","ROOT", "root node"],
+    ["S","S", "sentence"],
+    ["VP","VP", "verb phrase (non-finite)"],
+    ["VZ","VZ", "zu-marked infinitive"]
+  ];
+  
+  ah["corenlp/c=AA-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+	ah["corenlp/c=AP-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+	ah["corenlp/c=AVP-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+	ah["corenlp/c=CAP-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+	ah["corenlp/c=CAVP-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+	ah["corenlp/c=CAC-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+	ah["corenlp/c=CCP-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+	ah["corenlp/c=CH-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+	ah["corenlp/c=CNP-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+	ah["corenlp/c=CO-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+	ah["corenlp/c=CPP-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+	ah["corenlp/c=CS-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+	ah["corenlp/c=CVP-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+	ah["corenlp/c=CVZ-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+	ah["corenlp/c=DL-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+	ah["corenlp/c=ISU-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+	ah["corenlp/c=MPN-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+	ah["corenlp/c=MTA-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+	ah["corenlp/c=NM-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+	ah["corenlp/c=NP-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+	ah["corenlp/c=PP-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+	ah["corenlp/c=QL-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+	ah["corenlp/c=ROOT-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+	ah["corenlp/c=S-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+	ah["corenlp/c=VP-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+	ah["corenlp/c=VZ-"] = [
+	  ["AC", "AC ", "adpositional case marker"],
+	  ["ADC", "ADC ", "adjective component"],
+	  ["AMS", "AMS ", "measure argument of adj"],
+	  ["APP", "APP ", "apposition"],
+	  ["AVC", "AVC ", "adverbial phrase component"],
+	  ["CC", "CC ", "comparative complement"],
+	  ["CD", "CD ", "coordinating conjunction"],
+	  ["CJ", "CJ ", "conjunct"],
+	  ["CM", "CM ", "comparative concjunction"],
+	  ["CP", "CP ", "complementizer"],
+	  ["DA", "DA ", "dative"],
+	  ["DH", "DH ", "discourse-level head"],
+	  ["DM", "DM ", "discourse marker"],
+	  ["GL", "GL ", "prenominal genitive"],
+	  ["GR", "GR ", "postnominal genitive"],
+	  ["HD", "HD ", "head"],
+	  ["JU", "JU ", "junctor"],
+	  ["MC", "MC ", "comitative"],
+	  ["MI", "MI ", "instrumental"],
+	  ["ML", "ML ", "locative"],
+	  ["MNR", "MNR ", "postnominal modifier"],
+	  ["MO", "MO ", "modifier"],
+	  ["MR", "MR ", "rhetorical modifier"],
+	  ["MW", "MW ", "way (directional modifier)"],
+	  ["NG", "NG ", "negation"],
+	  ["NK", "NK ", "noun kernel modifier"],
+	  ["NMC", "NMC ", "numerical component"],
+	  ["OA", "OA ", "accusative object"],
+	  ["OA2", "OA2 ", "second accusative object"],
+	  ["OC", "OC ", "clausal object"],
+	  ["OG", "OG ", "genitive object"],
+	  ["PD", "PD ", "predicate"],
+	  ["PG", "PG ", "pseudo-genitive"],
+	  ["PH", "PH ", "placeholder"],
+	  ["PM", "PM ", "morphological particle"],
+	  ["PNC", "PNC ", "proper noun component"],
+	  ["RC", "RC ", "relative clause"],
+	  ["RE", "RE ", "repeated element"],
+	  ["RS", "RS ", "reported speech"],
+	  ["SB", "SB ", "subject"],
+	  ["SBP", "SBP ", "passivised subject (PP)"],
+	  ["SP", "SP ", "subject or predicate"],
+	  ["SVP", "SVP ", "separable verb prefix"],
+	  ["UC", "UC ", "(idiosyncratic) unit component"],
+	  ["VO", "VO ", "vocative"]
+	];
+
+
+  
+//  for (var i in negraNodesArray) {
+//    ah["corenlp/c=" + negraNodesArray[i][0] + '-'] = negraEdgesArray;
+//  };
+});
diff --git a/core/src/main/resources/annotation-scripts/foundries/dereko.js b/core/src/main/resources/annotation-scripts/foundries/dereko.js
new file mode 100644
index 0000000..e31f42e
--- /dev/null
+++ b/core/src/main/resources/annotation-scripts/foundries/dereko.js
@@ -0,0 +1,9 @@
+define(["hint/foundries"], function (ah) {
+  ah["-"].push(
+    ["DeReKo", "dereko/", "Structure"]
+  );
+  
+  ah["dereko/"] = [
+	["Structure", "s="]
+  ];
+});
diff --git a/core/src/main/resources/annotation-scripts/foundries/drukola.js b/core/src/main/resources/annotation-scripts/foundries/drukola.js
new file mode 100644
index 0000000..b57f8a4
--- /dev/null
+++ b/core/src/main/resources/annotation-scripts/foundries/drukola.js
@@ -0,0 +1,104 @@
+define(["hint/foundries"], function (ah) {
+  ah["-"].push(
+    ["DRuKoLa", "drukola/", "Lemma, Morphology, Part-of-Speech"]
+  );
+
+  ah["drukola/"] = [
+    ["Lemma", "l="],
+    ["Morphology", "m="],
+    ["Part-of-Speech", "p="]      
+  ];
+
+  ah["drukola/m="] =  [
+    ["CTAG", "ctag:"]
+  ];
+
+  ah["drukola/m=ctag:"] = [
+    ["A","a ","Adjective"],
+    ["Y","y ","Abbreviation"],
+    ["AN","an ","Adjective, Indefinite"],
+    ["APRY","apry ","Adjective, Plural, Direct, Definite"],
+    ["APN","apn ","Adjective, Plural, Indefinite"],
+    ["APOY","apoy ","Adjective, Plural, Oblique, Definite"],
+    ["APON","apon ","Adjective, Plural, Oblique, Indefinite"],
+    ["ASRY","asry ","Adjective, Singular, Direct, Definite"],
+    ["ASN","asn ","Adjective, Singular, Indefinite"],
+    ["ASOY","asoy ","Adjective, Singular, Oblique, Definite"],
+    ["ASON","ason ","Adjective, Singular, Oblique, Indefinite"],
+    ["ASVY","asvy ","Adjective, Singular, Vocative, Definite"],
+    ["ASVN","asvn ","Adjective, Singular, Vocative, Indefinite"],
+    ["R","r ","Adverb"],
+    ["RC","rc ","Adverb, Portmanteau"],
+    ["TS","ts ","Article, Definite or Possessive, Singular"],
+    ["TP","tp ","Article, Indefinite or Possessive, Plural"],
+    ["TPR","tpr ","Article, non-Possessive, Plural, Direct"],
+    ["TPO","tpo ","Article, non-Possessive, Plural, Oblique"],
+    ["TSR","tsr ","Article, non-Possessive, Singular, Direct"],
+    ["TSO","tso ","Article, non-Possessive, Singular, Oblique"],
+    ["NPRY","npry ","Common Noun, Plural, Direct, Definite"],
+    ["NPN","npn ","Common Noun, Plural, Indefinite"],
+    ["NPOY","npoy ","Common Noun, Plural, Oblique, Definite"],
+    ["NPVY","npvy ","Common Noun, Plural, Vocative, Definite"],
+    ["NN","nn ","Common Noun, singular"],
+    ["NSY","nsy ","Common Noun, Singular, Definite"],
+    ["NSRY","nsry ","Common Noun, Singular, Direct, Definite"],
+    ["NSRN","nsrn ","Common Noun, Singular, Direct, Indefinite"],
+    ["NSN","nsn ","Common Noun, Singular, Indefinite"],
+    ["NSOY","nsoy ","Common Noun, Singular, Oblique, Definite"],
+    ["NSON","nson ","Common Noun, Singular, Oblique, Indefinite"],
+    ["NSVY","nsvy ","Common Noun, Singular, Vocative, Definite"],
+    ["NSVN","nsvn ","Common Noun, Singular, Vocative, Indefinite"],
+    ["CR","cr ","Conjunctio, portmanteau"],
+    ["C","c ","Conjunction"],
+    ["QF","qf ","Future Particle"],
+    ["QN","qn ","Infinitival Particle"],
+    ["I","i ","Interjection"],
+    ["QZ","qz ","Negative Particle"],
+    ["M","m ","Numeral"],
+    ["PP","pp ","Personal Pronoun"],
+    ["PPP","ppp ","Personal Pronoun, Plural"],
+    ["PPPA","pppa ","Personal Pronoun, Plural, Acc."],
+    ["PPPD","pppd ","Personal Pronoun, Plural, Dative"],
+    ["PPPR","pppr ","Personal Pronoun, Plural, Direct"],
+    ["PPPO","pppo ","Personal Pronoun, Plural, Oblique"],
+    ["PPS","pps ","Personal Pronoun, Singular"],
+    ["PPSA","ppsa ","Personal Pronoun, Singular, Accusative"],
+    ["PPSD","ppsd ","Personal Pronoun, Singular, Dative"],
+    ["PPSR","ppsr ","Personal Pronoun, Singular, Direct"],
+    ["PPSN","ppsn ","Personal Pronoun, Singular, Nominative"],
+    ["PPSO","ppso ","Personal Pronoun, Singular, Oblique"],
+    ["S","s ","Preposition"],
+    ["DMPR","dmpr ","Pronoun or Determiner, Demonstrative, Plural, Direct"],
+    ["DMPO","dmpo ","Pronoun or Determiner, Demonstrative, Plural, Oblique"],
+    ["DMSR","dmsr ","Pronoun or Determiner, Demonstrative, Singular, Direct"],
+    ["DMSO","dmso ","Pronoun or Determiner, Demonstrative, Singular, Oblique"],
+    ["PS","ps ","Pronoun or Determiner, Poss or Emph"],
+    ["PSS","pss ","Pronoun or Determiner, Poss or Emph, Singular"],
+    ["RELR","relr ","Pronoun or Determiner, Relative, Direct"],
+    ["RELO","relo ","Pronoun or Determiner, Relative, Oblique"],
+    ["NP","np ","Proper Noun"],
+    ["PI","pi ","Quantifier Pronoun or Determiner"],
+    ["PXA","pxa ","Reflexive Pronoun, Accusative"],
+    ["PXD","pxd ","Reflexive Pronoun, Dative"],
+    ["X","x ","Residual"],
+    ["QS","qs ","Subjunctive Particle"],
+    ["VA","va ","Verb, Auxiliary"],
+    ["VA1","va1 ","Verb, Auxiliary, 1st person"],
+    ["VA2P","va2p ","Verb, Auxiliary, 2nd person, Plural"],
+    ["VA2S","va2s ","Verb, Auxiliary, 2nd person, Singular"],
+    ["VA3","va3 ","Verb, Auxiliary, 3rd person"],
+    ["VA3P","va3p ","Verb, Auxiliary, 3rd person, Plural"],
+    ["VA3S","va3s ","Verb, Auxiliary, 3rd person, Singular"],
+    ["VA1P","va1p ","Verb, Auxiliary,1st person, Plural"],
+    ["VA1S","va1s ","Verb, Auxiliary,1st person, Singular"],
+    ["VG","vg ","Verb, Gerund"],
+    ["VN","vn ","Verb, Infinitive"],
+    ["V1","v1 ","Verb, Main, 1st person"],
+    ["V2","v2 ","Verb, Main, 2nd person"],
+    ["V3","v3 ","Verb, Main, 3rd person"],
+    ["VPPF","vppf ","Verb, Participle, Plural, Feminine"],
+    ["VPPM","vppm ","Verb, Participle, Plural, Masculine"],
+    ["VPSF","vpsf ","Verb, Participle, Singular, Feminine"],
+    ["VPSM","vpsm ","Verb, Participle, Singular, Masculine"]
+  ];
+});
diff --git a/core/src/main/resources/annotation-scripts/foundries/lwc.js b/core/src/main/resources/annotation-scripts/foundries/lwc.js
new file mode 100644
index 0000000..600bc57
--- /dev/null
+++ b/core/src/main/resources/annotation-scripts/foundries/lwc.js
@@ -0,0 +1,57 @@
+define(["hint/foundries","hint/foundries/negraedges"], function (ah, negraEdgesArray) {
+  ah["-"].push(
+    ["LWC", "lwc/", "Dependency"]
+  );
+
+  ah["lwc/"] = [
+    ["Dependency", "d="]
+  ];
+
+  ah["lwc/d="] = [
+	["AC","AC ","adpositional case marker"],
+    ["ADC","ADC ","adjective component"],
+    ["AMS","AMS ","measure argument of adj"],
+    ["APP","APP ","apposition"],
+    ["AVC","AVC ","adverbial phrase component"],
+    ["CC","CC ","comparative complement"],
+    ["CD","CD ","coordinating conjunction"],
+    ["CJ","CJ ","conjunct"],
+    ["CM","CM ","comparative concjunction"],
+    ["CP","CP ","complementizer"],
+    ["DA","DA ","dative"],
+    ["DH","DH ","discourse-level head"],
+    ["DM","DM ","discourse marker"],
+    ["GL","GL ","prenominal genitive"],
+    ["GR","GR ","postnominal genitive"],
+    ["HD","HD ","head"],
+    ["JU","JU ","junctor"],
+    ["MC","MC ","comitative"],
+    ["MI","MI ","instrumental"],
+    ["ML","ML ","locative"],
+    ["MNR","MNR ","postnominal modifier"],
+    ["MO","MO ","modifier"],
+    ["MR","MR ","rhetorical modifier"],
+    ["MW","MW ","way (directional modifier)"],
+    ["NG","NG ","negation"],
+    ["NK","NK ","noun kernel modifier"],
+    ["NMC","NMC ","numerical component"], 
+    ["OA","OA ","accusative object"],
+    ["OA2","OA2 ","second accusative object"], 
+    ["OC","OC ","clausal object"],
+    ["OG","OG ","genitive object"], 
+    ["PD","PD ","predicate"],
+    ["PG","PG ","pseudo-genitive"],
+    ["PH","PH ","placeholder"],
+    ["PM","PM ","morphological particle"],
+    ["PNC","PNC ","proper noun component"], 
+    ["RC","RC ","relative clause"],
+    ["RE","RE ","repeated element"],
+    ["RS","RS ","reported speech"],
+    ["SB","SB ","subject"],
+    ["SBP","SBP ","passivised subject (PP)"], 
+    ["SP","SP ","subject or predicate"],
+    ["SVP","SVP ","separable verb prefix"],
+    ["UC","UC ","(idiosyncratic) unit component"], 
+    ["VO","VO ","vocative"]
+  ];
+});
diff --git a/core/src/main/resources/annotation-scripts/foundries/malt.js b/core/src/main/resources/annotation-scripts/foundries/malt.js
new file mode 100644
index 0000000..c8c837b
--- /dev/null
+++ b/core/src/main/resources/annotation-scripts/foundries/malt.js
@@ -0,0 +1,47 @@
+define(["hint/foundries"], function (ah) {
+  ah["-"].push(
+    ["Malt", "malt/", "Dependency"]
+  );
+
+  ah["malt/"] = [
+    ["Dependency", "d="]
+  ];
+
+  ah["malt/d="] = [
+    ["-PUNCT-", "-PUNCT- ",""],
+    ["-UNKNOWN-","-UNKNOWN- ",""],
+    ["ADV","ADV ",""],
+    ["APP","APP ",""],
+    ["ATTR","ATTR ",""],
+    ["AUX","AUX ",""],
+    ["AVZ","AVZ ",""],
+    ["CJ","CJ ",""],
+    ["DET","DET ",""],
+    ["EXPL","EXPL ",""],
+    ["GMOD","GMOD ",""],
+    ["GRAD","GRAD ",""],
+    ["KOM","KOM ",""],
+    ["KON","KON ",""],
+    ["KONJ","KONJ ",""],
+    ["NEB","NEB ",""],
+    ["OBJA","OBJA ",""],
+    ["OBJC","OBJC ",""],
+    ["OBJD","OBJD ",""],
+    ["OBJG","OBJG ",""],
+    ["OBJI","OBJI ",""],
+    ["OBJP","OBJP ",""],
+    ["PAR","PAR ",""],
+    ["PART","PART ",""],
+    ["PN","PN ",""],
+    ["PP","PP ",""],
+    ["PRED","PRED ",""],
+    ["REL","REL ",""],
+    ["ROOT","ROOT ",""],
+    ["S","S ",""],
+    ["SUBJ","SUBJ ",""],
+    ["SUBJC","SUBJC ",""],
+    ["ZEIT","ZEIT ",""],
+    ["gmod-app","gmod-app ",""],
+    ["koord","koord ",""]
+  ];
+});
diff --git a/core/src/main/resources/annotation-scripts/foundries/marmot.js b/core/src/main/resources/annotation-scripts/foundries/marmot.js
new file mode 100644
index 0000000..a6e5b61
--- /dev/null
+++ b/core/src/main/resources/annotation-scripts/foundries/marmot.js
@@ -0,0 +1,120 @@
+define(["hint/foundries","hint/foundries/stts"], function (ah, sttsArray) {
+  ah["-"].push(
+    ["MarMoT", "marmot/", "Morphology, Part-of-Speech"]
+  );
+
+  ah["marmot/"] = [
+    ["Morphology", "m="],
+    ["Part-of-Speech", "p="]
+  ];
+
+  ah["marmot/p="] = [
+	["ADJA","ADJA ", "Attributive Adjective"],
+    ["ADJD","ADJD ", "Predicative Adjective"],
+    ["ADV","ADV ", "Adverb"],
+    ["APPO","APPO ", "Postposition"],
+    ["APPR","APPR ", "Preposition"],
+    ["APPRART","APPRART ", "Preposition with Determiner"],
+    ["APZR","APZR ","Right Circumposition"],
+    ["ART","ART ", "Determiner"],
+    ["CARD","CARD ", "Cardinal Number"],
+    ["FM","FM ", "Foreign Material"],
+    ["ITJ","ITJ ", "Interjection"],
+    ["KOKOM","KOKOM ", "Comparison Particle"],
+    ["KON","KON ", "Coordinating Conjuncion"],
+    ["KOUI","KOUI ", "Subordinating Conjunction with 'zu'"],
+    ["KOUS","KOUS ", "Subordinating Conjunction with Sentence"],
+    ["NE","NE ", "Named Entity"],
+    ["NN","NN ", "Normal Nomina"],
+    ["PAV", "PAV ", "Pronominal Adverb"],
+    ["PDAT","PDAT ","Attributive Demonstrative Pronoun"],
+    ["PDS","PDS ", "Substitutive Demonstrative Pronoun"],
+    ["PIAT","PIAT ", "Attributive Indefinite Pronoun without Determiner"],
+    ["PIDAT","PIDAT ", "Attributive Indefinite Pronoun with Determiner"],
+    ["PIS","PIS ", "Substitutive Indefinite Pronoun"],
+    ["PPER","PPER ", "Personal Pronoun"],
+    ["PPOSAT","PPOSAT ", "Attributive Possessive Pronoun"],
+    ["PPOSS","PPOSS ", "Substitutive Possessive Pronoun"],
+    ["PRELAT","PRELAT ", "Attributive Relative Pronoun"],
+    ["PRELS","PRELS ", "Substitutive Relative Pronoun"],
+    ["PRF","PRF ", "Reflexive Pronoun"],
+    ["PROAV","PROAV ", "Pronominal Adverb"],
+    ["PTKA","PTKA ","Particle with Adjective"],
+    ["PTKANT","PTKANT ", "Answering Particle"],
+    ["PTKNEG","PTKNEG ", "Negation Particle"],
+    ["PTKVZ","PTKVZ ", "Separated Verbal Particle"],
+    ["PTKZU","PTKZU ", "'zu' Particle"],
+    ["PWAT","PWAT ", "Attributive Interrogative Pronoun"],
+    ["PWAV","PWAV ", "Adverbial Interrogative Pronoun"],
+    ["PWS","PWS ", "Substitutive Interrogative Pronoun"],
+    ["TRUNC","TRUNC ","Truncated"],
+    ["VAFIN","VAFIN ", "Auxiliary Finite Verb"],
+    ["VAIMP","VAIMP ", "Auxiliary Finite Imperative Verb"],
+    ["VAINF","VAINF ", "Auxiliary Infinite Verb"],
+    ["VAPP","VAPP ", "Auxiliary Perfect Participle"],
+    ["VMFIN","VMFIN ", "Modal Finite Verb"],
+    ["VMINF","VMINF ", "Modal Infinite Verb"],
+    ["VMPP","VMPP ", "Modal Perfect Participle"],
+    ["VVFIN","VVFIN ","Finite Verb"],
+    ["VVIMP","VVIMP ", "Finite Imperative Verb"],
+    ["VVINF","VVINF ", "Infinite Verb"],
+    ["VVIZU","VVIZU ", "Infinite Verb with 'zu'"],
+    ["VVPP","VVPP ", "Perfect Participle"],
+    ["XY", "XY ", "Non-Word"]
+  ];	  
+
+  ah["marmot/m="] = [
+    ["Case", "case:"],
+    ["Degree", "degree:"],
+    ["Gender", "gender:"],
+    ["Mood", "mood:"],
+    ["Number", "number:"],
+    ["Person", "person:"],
+    ["Tense","tense:"],
+    ["No type", "<no-type> "]
+  ];
+
+  ah["marmot/m=case:"] = [
+    ["acc", "acc ", "Accusative"],
+    ["dat","dat ", "Dative"],
+    ["gen", "gen ","Genitive"],
+    ["nom","nom ", "Nominative"],
+    ["*","* ", "Undefined"]
+  ];
+
+  ah["marmot/m=degree:"] = [
+    ["comp","comp ", "Comparative"],
+    ["pos","pos ", "Positive"],
+    ["sup","sup ", "Superative"]
+  ];
+  
+  ah["marmot/m=gender:"] = [
+    ["fem", "fem ", "Feminium"],
+    ["masc", "masc ", "Masculinum"],
+    ["neut","neut ", "Neuter"],
+    ["*","* ","Undefined"]
+  ];
+
+  ah["marmot/m=mood:"] = [
+    ["imp","imp ", "Imperative"],
+    ["ind","ind ", "Indicative"],
+    ["subj","subj ", "Subjunctive"]
+  ];
+
+  ah["marmot/m=number:"] = [
+    ["pl","pl ","Plural"],
+    ["sg","sg ","Singular"],
+    ["*","* ","Undefined"]
+  ];
+
+  ah["marmot/m=person:"] = [
+    ["1","1 ", "First Person"],
+    ["2","2 ", "Second Person"],
+    ["3","3 ", "Third Person"]
+  ];
+
+  ah["marmot/m=tense:"] = [
+    ["past","past ", "Past"],
+    ["pres","pres ", "Present"]
+  ];
+});
diff --git a/core/src/main/resources/annotation-scripts/foundries/mate.js b/core/src/main/resources/annotation-scripts/foundries/mate.js
new file mode 100644
index 0000000..f0d5c12
--- /dev/null
+++ b/core/src/main/resources/annotation-scripts/foundries/mate.js
@@ -0,0 +1,130 @@
+define(["hint/foundries","hint/foundries/stts"], function (ah, sttsArray) {
+//  var mateSttsArray = sttsArray.slice(0);
+//  mateSttsArray.push(
+//    ["<root-POS>","<root-POS>","Root Part of Speech"]
+//  );
+
+  var ah = KorAP.annotationHelper = KorAP.annotationHelper || { "-" : [] };
+
+  ah["-"].push(
+    ["Mate", "mate/", "Lemma, Morphology, Part-of-Speech"]
+  );
+
+  ah["mate/"] = [
+    // Inactive: "d" : ["d=", "Dependency"],
+    ["Lemma", "l="],
+    ["Morphology", "m="],
+    ["Part-of-Speech", "p="]
+  ];
+
+  // Inactive: mate/d=
+  ah["mate/p="] = [
+	["ADJA","ADJA ", "Attributive Adjective"],
+    ["ADJD","ADJD ", "Predicative Adjective"],
+    ["ADV","ADV ", "Adverb"],
+    ["APPO","APPO ", "Postposition"],
+    ["APPR","APPR ", "Preposition"],
+    ["APPRART","APPRART ", "Preposition with Determiner"],
+    ["APZR","APZR ","Right Circumposition"],
+    ["ART","ART ", "Determiner"],
+    ["CARD","CARD ", "Cardinal Number"],
+    ["FM","FM ", "Foreign Material"],
+    ["ITJ","ITJ ", "Interjection"],
+    ["KOKOM","KOKOM ", "Comparison Particle"],
+    ["KON","KON ", "Coordinating Conjuncion"],
+    ["KOUI","KOUI ", "Subordinating Conjunction with 'zu'"],
+    ["KOUS","KOUS ", "Subordinating Conjunction with Sentence"],
+    ["NE","NE ", "Named Entity"],
+    ["NN","NN ", "Normal Nomina"],
+    ["PAV", "PAV ", "Pronominal Adverb"],
+    ["PDAT","PDAT ","Attributive Demonstrative Pronoun"],
+    ["PDS","PDS ", "Substitutive Demonstrative Pronoun"],
+    ["PIAT","PIAT ", "Attributive Indefinite Pronoun without Determiner"],
+    ["PIDAT","PIDAT ", "Attributive Indefinite Pronoun with Determiner"],
+    ["PIS","PIS ", "Substitutive Indefinite Pronoun"],
+    ["PPER","PPER ", "Personal Pronoun"],
+    ["PPOSAT","PPOSAT ", "Attributive Possessive Pronoun"],
+    ["PPOSS","PPOSS ", "Substitutive Possessive Pronoun"],
+    ["PRELAT","PRELAT ", "Attributive Relative Pronoun"],
+    ["PRELS","PRELS ", "Substitutive Relative Pronoun"],
+    ["PRF","PRF ", "Reflexive Pronoun"],
+    ["PROAV","PROAV ", "Pronominal Adverb"],
+    ["PTKA","PTKA ","Particle with Adjective"],
+    ["PTKANT","PTKANT ", "Answering Particle"],
+    ["PTKNEG","PTKNEG ", "Negation Particle"],
+    ["PTKVZ","PTKVZ ", "Separated Verbal Particle"],
+    ["PTKZU","PTKZU ", "'zu' Particle"],
+    ["PWAT","PWAT ", "Attributive Interrogative Pronoun"],
+    ["PWAV","PWAV ", "Adverbial Interrogative Pronoun"],
+    ["PWS","PWS ", "Substitutive Interrogative Pronoun"],
+    ["TRUNC","TRUNC ","Truncated"],
+    ["VAFIN","VAFIN ", "Auxiliary Finite Verb"],
+    ["VAIMP","VAIMP ", "Auxiliary Finite Imperative Verb"],
+    ["VAINF","VAINF ", "Auxiliary Infinite Verb"],
+    ["VAPP","VAPP ", "Auxiliary Perfect Participle"],
+    ["VMFIN","VMFIN ", "Modal Finite Verb"],
+    ["VMINF","VMINF ", "Modal Infinite Verb"],
+    ["VMPP","VMPP ", "Modal Perfect Participle"],
+    ["VVFIN","VVFIN ","Finite Verb"],
+    ["VVIMP","VVIMP ", "Finite Imperative Verb"],
+    ["VVINF","VVINF ", "Infinite Verb"],
+    ["VVIZU","VVIZU ", "Infinite Verb with 'zu'"],
+    ["VVPP","VVPP ", "Perfect Participle"],
+    ["XY", "XY ", "Non-Word"],
+    ["<root-POS>","<root-POS>","Root Part of Speech"]
+  ];
+
+  ah["mate/m="] = [
+    ["Case", "case:"],
+    ["Degree", "degree:"],
+    ["Gender", "gender:"],
+    ["Mood", "mood:"],
+    ["Number", "number:"],
+    ["Person", "person:"],
+    ["Tense","tense:"],
+    ["No type", "<no-type> "]
+  ];
+
+  ah["mate/m=case:"] = [
+    ["acc", "acc ", "Accusative"],
+    ["dat","dat ", "Dative"],
+    ["gen", "gen ","Genitive"],
+    ["nom","nom ", "Nominative"],
+    ["*","* ", "Undefined"]
+  ];
+
+  ah["mate/m=degree:"] = [
+    ["comp","comp ", "Comparative"],
+    ["pos","pos ", "Positive"],
+    ["sup","sup ", "Superative"]
+  ];
+
+  ah["mate/m=gender:"] = [
+    ["fem", "fem ", "Feminium"],
+    ["masc", "masc ", "Masculinum"],
+    ["neut","neut ", "Neuter"],
+    ["*","* ","Undefined"]
+  ];
+
+  ah["mate/m=mood:"] = [
+    ["imp","imp ", "Imperative"],
+    ["ind","ind ", "Indicative"],
+    ["subj","subj ", "Subjunctive"]
+  ];
+
+  ah["mate/m=number:"] = [
+    ["pl","pl ","Plural"],
+    ["sg","sg ","Singular"],
+    ["*","* ","Undefined"]
+  ];
+
+  ah["mate/m=person:"] = [
+    ["1","1 ", "First Person"],
+    ["2","2 ", "Second Person"],
+    ["3","3 ", "Third Person"]
+  ];
+  ah["mate/m=tense:"] = [
+    ["past","past ", "Past"],
+    ["pres","pres ", "Present"]
+  ];
+});
diff --git a/core/src/main/resources/annotation-scripts/foundries/opennlp.js b/core/src/main/resources/annotation-scripts/foundries/opennlp.js
new file mode 100644
index 0000000..d790eba
--- /dev/null
+++ b/core/src/main/resources/annotation-scripts/foundries/opennlp.js
@@ -0,0 +1,65 @@
+define(["hint/foundries","hint/foundries/stts"], function (ah, sttsArray) {
+  ah["-"].push(
+    ["OpenNLP", "opennlp/", "Part-of-Speech"]
+  );
+
+  ah["opennlp/"] = [
+    ["Part-of-Speech", "p="]
+  ];
+
+//  ah["opennlp/p="] = sttsArray;
+  ah["opennlp/p="] = [
+	  ["ADJA","ADJA ", "Attributive Adjective"],
+	  ["ADJD","ADJD ", "Predicative Adjective"],
+	  ["ADV","ADV ", "Adverb"],
+	  ["APPO","APPO ", "Postposition"],
+	  ["APPR","APPR ", "Preposition"],
+	  ["APPRART","APPRART ", "Preposition with Determiner"],
+	  ["APZR","APZR ","Right Circumposition"],
+	  ["ART","ART ", "Determiner"],
+	  ["CARD","CARD ", "Cardinal Number"],
+	  ["FM","FM ", "Foreign Material"],
+	  ["ITJ","ITJ ", "Interjection"],
+	  ["KOKOM","KOKOM ", "Comparison Particle"],
+	  ["KON","KON ", "Coordinating Conjuncion"],
+	  ["KOUI","KOUI ", "Subordinating Conjunction with 'zu'"],
+	  ["KOUS","KOUS ", "Subordinating Conjunction with Sentence"],
+	  ["NE","NE ", "Named Entity"],
+	  ["NN","NN ", "Normal Nomina"],
+	  ["PAV", "PAV ", "Pronominal Adverb"],
+	  ["PDAT","PDAT ","Attributive Demonstrative Pronoun"],
+	  ["PDS","PDS ", "Substitutive Demonstrative Pronoun"],
+	  ["PIAT","PIAT ", "Attributive Indefinite Pronoun without Determiner"],
+	  ["PIDAT","PIDAT ", "Attributive Indefinite Pronoun with Determiner"],
+	  ["PIS","PIS ", "Substitutive Indefinite Pronoun"],
+	  ["PPER","PPER ", "Personal Pronoun"],
+	  ["PPOSAT","PPOSAT ", "Attributive Possessive Pronoun"],
+	  ["PPOSS","PPOSS ", "Substitutive Possessive Pronoun"],
+	  ["PRELAT","PRELAT ", "Attributive Relative Pronoun"],
+	  ["PRELS","PRELS ", "Substitutive Relative Pronoun"],
+	  ["PRF","PRF ", "Reflexive Pronoun"],
+	  ["PROAV","PROAV ", "Pronominal Adverb"],
+	  ["PTKA","PTKA ","Particle with Adjective"],
+	  ["PTKANT","PTKANT ", "Answering Particle"],
+	  ["PTKNEG","PTKNEG ", "Negation Particle"],
+	  ["PTKVZ","PTKVZ ", "Separated Verbal Particle"],
+	  ["PTKZU","PTKZU ", "'zu' Particle"],
+	  ["PWAT","PWAT ", "Attributive Interrogative Pronoun"],
+	  ["PWAV","PWAV ", "Adverbial Interrogative Pronoun"],
+	  ["PWS","PWS ", "Substitutive Interrogative Pronoun"],
+	  ["TRUNC","TRUNC ","Truncated"],
+	  ["VAFIN","VAFIN ", "Auxiliary Finite Verb"],
+	  ["VAIMP","VAIMP ", "Auxiliary Finite Imperative Verb"],
+	  ["VAINF","VAINF ", "Auxiliary Infinite Verb"],
+	  ["VAPP","VAPP ", "Auxiliary Perfect Participle"],
+	  ["VMFIN","VMFIN ", "Modal Finite Verb"],
+	  ["VMINF","VMINF ", "Modal Infinite Verb"],
+	  ["VMPP","VMPP ", "Modal Perfect Participle"],
+	  ["VVFIN","VVFIN ","Finite Verb"],
+	  ["VVIMP","VVIMP ", "Finite Imperative Verb"],
+	  ["VVINF","VVINF ", "Infinite Verb"],
+	  ["VVIZU","VVIZU ", "Infinite Verb with 'zu'"],
+	  ["VVPP","VVPP ", "Perfect Participle"],
+	  ["XY", "XY ", "Non-Word"]
+	];
+});
diff --git a/core/src/main/resources/annotation-scripts/foundries/schreibgebrauch.js b/core/src/main/resources/annotation-scripts/foundries/schreibgebrauch.js
new file mode 100644
index 0000000..850617f
--- /dev/null
+++ b/core/src/main/resources/annotation-scripts/foundries/schreibgebrauch.js
@@ -0,0 +1,117 @@
+define(["hint/foundries","hint/foundries/stts"], function (ah, sttsArray) {
+//  var sgbrSttsArray = sttsArray.slice(0);
+
+  // Push specific information for Schreibgebrauch
+//  sgbrSttsArray.push(
+//    ["NNE", "NNE", "Normal Nomina with Named Entity"],
+//    ["ADVART","ADVART",   "Adverb with Article"],
+//    ["EMOASC","EMOASC",   "ASCII emoticon"],
+//    ["EMOIMG","EMOIMG",   "Graphic emoticon"],
+//    ["ERRTOK","ERRTOK",   "Tokenisation Error"],
+//    ["HST",     "HST",      "Hashtag"],
+//    ["KOUSPPER","KOUSPPER", "Subordinating Conjunction (with Sentence) with Personal Pronoun"],
+//    ["ONO",     "ONO",      "Onomatopoeia"],
+//    ["PPERPPER","PPERPPER", "Personal Pronoun with Personal Pronoun"],
+//    ["URL",     "URL",      "Uniform Resource Locator"],
+//    ["VAPPER",  "VAPPER",   "Finite Auxiliary Verb with Personal Pronoun"],
+//    ["VMPPER",  "VMPPER",   "Fintite Modal Verb with Personal Pronoun"],
+//    ["VVPPER",  "VVPPER",   "Finite Full Verb with Personal Pronoun"],
+//    ["AW", "AW", "Interaction Word"],
+//    ["ADR", "ADR", "Addressing Term"],
+//    ["AWIND", "AWIND", "Punctuation Indicating Addressing Term"],
+//    ["ERRAW","ERRAW", "Part of Erroneously Separated Compound"]
+//    /*
+//      As KorAP currently doesn't support these tags, they could also be ommited
+//      ["_KOMMA", "_KOMMA", "Comma"],
+//      ["_SONST", "_SONST", "Intrasentential Punctuation Mark"],
+//      ["_ENDE", "_ENDE", "Punctuation Mark at the end of the Sentence"]
+//    */
+//  );
+
+  // Sort by tag
+  sgbrSttsArray.sort(function (a,b) { return a[0].localeCompare(b[0]) });
+
+  
+  ah["-"].push(
+    ["Schreibgebrauch", "sgbr/", "Lemma, Lemma Variants, Part-of-Speech"]
+  );
+
+  ah["sgbr/"] = [
+    ["Lemma", "l="],
+    ["Lemma Variants", "lv="],
+    ["Part-of-Speech", "p="]
+  ];
+
+//  ah["sgbr/p="] = sgbrSttsArray;
+  ah["sgbr/p="] = [
+    ["ADJA","ADJA ", "Attributive Adjective"],
+    ["ADJD","ADJD ", "Predicative Adjective"],
+    ["ADV","ADV ", "Adverb"],
+    ["APPO","APPO ", "Postposition"],
+    ["APPR","APPR ", "Preposition"],
+    ["APPRART","APPRART ", "Preposition with Determiner"],
+    ["APZR","APZR ","Right Circumposition"],
+    ["ART","ART ", "Determiner"],
+    ["CARD","CARD ", "Cardinal Number"],
+    ["FM","FM ", "Foreign Material"],
+    ["ITJ","ITJ ", "Interjection"],
+    ["KOKOM","KOKOM ", "Comparison Particle"],
+    ["KON","KON ", "Coordinating Conjuncion"],
+    ["KOUI","KOUI ", "Subordinating Conjunction with 'zu'"],
+    ["KOUS","KOUS ", "Subordinating Conjunction with Sentence"],
+    ["NE","NE ", "Named Entity"],
+    ["NN","NN ", "Normal Nomina"],
+    ["PAV", "PAV ", "Pronominal Adverb"],
+    ["PDAT","PDAT ","Attributive Demonstrative Pronoun"],
+    ["PDS","PDS ", "Substitutive Demonstrative Pronoun"],
+    ["PIAT","PIAT ", "Attributive Indefinite Pronoun without Determiner"],
+    ["PIDAT","PIDAT ", "Attributive Indefinite Pronoun with Determiner"],
+    ["PIS","PIS ", "Substitutive Indefinite Pronoun"],
+    ["PPER","PPER ", "Personal Pronoun"],
+    ["PPOSAT","PPOSAT ", "Attributive Possessive Pronoun"],
+    ["PPOSS","PPOSS ", "Substitutive Possessive Pronoun"],
+    ["PRELAT","PRELAT ", "Attributive Relative Pronoun"],
+    ["PRELS","PRELS ", "Substitutive Relative Pronoun"],
+    ["PRF","PRF ", "Reflexive Pronoun"],
+    ["PROAV","PROAV ", "Pronominal Adverb"],
+    ["PTKA","PTKA ","Particle with Adjective"],
+    ["PTKANT","PTKANT ", "Answering Particle"],
+    ["PTKNEG","PTKNEG ", "Negation Particle"],
+    ["PTKVZ","PTKVZ ", "Separated Verbal Particle"],
+    ["PTKZU","PTKZU ", "'zu' Particle"],
+    ["PWAT","PWAT ", "Attributive Interrogative Pronoun"],
+    ["PWAV","PWAV ", "Adverbial Interrogative Pronoun"],
+    ["PWS","PWS ", "Substitutive Interrogative Pronoun"],
+    ["TRUNC","TRUNC ","Truncated"],
+    ["VAFIN","VAFIN ", "Auxiliary Finite Verb"],
+    ["VAIMP","VAIMP ", "Auxiliary Finite Imperative Verb"],
+    ["VAINF","VAINF ", "Auxiliary Infinite Verb"],
+    ["VAPP","VAPP ", "Auxiliary Perfect Participle"],
+    ["VMFIN","VMFIN ", "Modal Finite Verb"],
+    ["VMINF","VMINF ", "Modal Infinite Verb"],
+    ["VMPP","VMPP ", "Modal Perfect Participle"],
+    ["VVFIN","VVFIN ","Finite Verb"],
+    ["VVIMP","VVIMP ", "Finite Imperative Verb"],
+    ["VVINF","VVINF ", "Infinite Verb"],
+    ["VVIZU","VVIZU ", "Infinite Verb with 'zu'"],
+    ["VVPP","VVPP ", "Perfect Participle"],
+    ["XY", "XY ", "Non-Word"],
+    ["NNE", "NNE", "Normal Nomina with Named Entity"],
+    ["ADVART","ADVART",   "Adverb with Article"],
+    ["EMOASC","EMOASC",   "ASCII emoticon"],
+    ["EMOIMG","EMOIMG",   "Graphic emoticon"],
+    ["ERRTOK","ERRTOK",   "Tokenisation Error"],
+    ["HST",     "HST",      "Hashtag"],
+    ["KOUSPPER","KOUSPPER", "Subordinating Conjunction (with Sentence) with Personal Pronoun"],
+    ["ONO",     "ONO",      "Onomatopoeia"],
+    ["PPERPPER","PPERPPER", "Personal Pronoun with Personal Pronoun"],
+    ["URL",     "URL",      "Uniform Resource Locator"],
+    ["VAPPER",  "VAPPER",   "Finite Auxiliary Verb with Personal Pronoun"],
+    ["VMPPER",  "VMPPER",   "Fintite Modal Verb with Personal Pronoun"],
+    ["VVPPER",  "VVPPER",   "Finite Full Verb with Personal Pronoun"],
+    ["AW", "AW", "Interaction Word"],
+    ["ADR", "ADR", "Addressing Term"],
+    ["AWIND", "AWIND", "Punctuation Indicating Addressing Term"],
+    ["ERRAW","ERRAW", "Part of Erroneously Separated Compound"]
+  ];
+});
diff --git a/core/src/main/resources/annotation-scripts/foundries/treetagger.js b/core/src/main/resources/annotation-scripts/foundries/treetagger.js
new file mode 100644
index 0000000..78a692a
--- /dev/null
+++ b/core/src/main/resources/annotation-scripts/foundries/treetagger.js
@@ -0,0 +1,66 @@
+define(["hint/foundries","hint/foundries/stts"], function (ah, sttsArray) {
+  ah["-"].push(
+    ["TreeTagger", "tt/", "Lemma, Part-of-Speech"]
+  );
+
+  ah["tt/"] = [
+    ["Lemma", "l="],
+    ["Part-of-Speech", "p="]
+  ];
+
+//  ah["tt/p="] = sttsArray;
+  ah["tt/p="] = [
+    ["ADJA","ADJA ", "Attributive Adjective"],
+    ["ADJD","ADJD ", "Predicative Adjective"],
+    ["ADV","ADV ", "Adverb"],
+    ["APPO","APPO ", "Postposition"],
+    ["APPR","APPR ", "Preposition"],
+    ["APPRART","APPRART ", "Preposition with Determiner"],
+    ["APZR","APZR ","Right Circumposition"],
+    ["ART","ART ", "Determiner"],
+    ["CARD","CARD ", "Cardinal Number"],
+    ["FM","FM ", "Foreign Material"],
+    ["ITJ","ITJ ", "Interjection"],
+    ["KOKOM","KOKOM ", "Comparison Particle"],
+    ["KON","KON ", "Coordinating Conjuncion"],
+    ["KOUI","KOUI ", "Subordinating Conjunction with 'zu'"],
+    ["KOUS","KOUS ", "Subordinating Conjunction with Sentence"],
+    ["NE","NE ", "Named Entity"],
+    ["NN","NN ", "Normal Nomina"],
+    ["PAV", "PAV ", "Pronominal Adverb"],
+    ["PDAT","PDAT ","Attributive Demonstrative Pronoun"],
+    ["PDS","PDS ", "Substitutive Demonstrative Pronoun"],
+    ["PIAT","PIAT ", "Attributive Indefinite Pronoun without Determiner"],
+    ["PIDAT","PIDAT ", "Attributive Indefinite Pronoun with Determiner"],
+    ["PIS","PIS ", "Substitutive Indefinite Pronoun"],
+    ["PPER","PPER ", "Personal Pronoun"],
+    ["PPOSAT","PPOSAT ", "Attributive Possessive Pronoun"],
+    ["PPOSS","PPOSS ", "Substitutive Possessive Pronoun"],
+    ["PRELAT","PRELAT ", "Attributive Relative Pronoun"],
+    ["PRELS","PRELS ", "Substitutive Relative Pronoun"],
+    ["PRF","PRF ", "Reflexive Pronoun"],
+    ["PROAV","PROAV ", "Pronominal Adverb"],
+    ["PTKA","PTKA ","Particle with Adjective"],
+    ["PTKANT","PTKANT ", "Answering Particle"],
+    ["PTKNEG","PTKNEG ", "Negation Particle"],
+    ["PTKVZ","PTKVZ ", "Separated Verbal Particle"],
+    ["PTKZU","PTKZU ", "'zu' Particle"],
+    ["PWAT","PWAT ", "Attributive Interrogative Pronoun"],
+    ["PWAV","PWAV ", "Adverbial Interrogative Pronoun"],
+    ["PWS","PWS ", "Substitutive Interrogative Pronoun"],
+    ["TRUNC","TRUNC ","Truncated"],
+    ["VAFIN","VAFIN ", "Auxiliary Finite Verb"],
+    ["VAIMP","VAIMP ", "Auxiliary Finite Imperative Verb"],
+    ["VAINF","VAINF ", "Auxiliary Infinite Verb"],
+    ["VAPP","VAPP ", "Auxiliary Perfect Participle"],
+    ["VMFIN","VMFIN ", "Modal Finite Verb"],
+    ["VMINF","VMINF ", "Modal Infinite Verb"],
+    ["VMPP","VMPP ", "Modal Perfect Participle"],
+    ["VVFIN","VVFIN ","Finite Verb"],
+    ["VVIMP","VVIMP ", "Finite Imperative Verb"],
+    ["VVINF","VVINF ", "Infinite Verb"],
+    ["VVIZU","VVIZU ", "Infinite Verb with 'zu'"],
+    ["VVPP","VVPP ", "Perfect Participle"],
+    ["XY", "XY ", "Non-Word"]
+  ];
+});
diff --git a/core/src/main/resources/annotation-scripts/foundries/xip.js b/core/src/main/resources/annotation-scripts/foundries/xip.js
new file mode 100644
index 0000000..ff7ac5e
--- /dev/null
+++ b/core/src/main/resources/annotation-scripts/foundries/xip.js
@@ -0,0 +1,12 @@
+define(["hint/foundries"], function (ah) {
+  ah["-"].push(
+    ["Xerox Parser", "xip/", "Constituency, Lemma, Part-of-Speech"]
+  );
+
+  ah["xip/"] = [
+    ["Constituency", "c="],
+    // Inactive: ["Dependency", "d="],
+    ["Lemma", "l="],
+    ["Part-of-Speech", "p="]
+  ];
+});
diff --git a/core/src/main/resources/annotation-scripts/variables/negraedges.js b/core/src/main/resources/annotation-scripts/variables/negraedges.js
new file mode 100644
index 0000000..7dc9b0f
--- /dev/null
+++ b/core/src/main/resources/annotation-scripts/variables/negraedges.js
@@ -0,0 +1,51 @@
+define(function () {
+  // http://www.coli.uni-saarland.de/projects/sfb378/negra-corpus/negra-corpus.html
+  // http://www.coli.uni-saarland.de/projects/sfb378/negra-corpus/kanten.html
+  return [
+    ["AC","AC ","adpositional case marker"],
+    ["ADC","ADC ","adjective component"],
+    ["AMS","AMS ","measure argument of adj"],
+    ["APP","APP ","apposition"],
+    ["AVC","AVC ","adverbial phrase component"],
+    ["CC","CC ","comparative complement"],
+    ["CD","CD ","coordinating conjunction"],
+    ["CJ","CJ ","conjunct"],
+    ["CM","CM ","comparative concjunction"],
+    ["CP","CP ","complementizer"],
+    ["DA","DA ","dative"],
+    ["DH","DH ","discourse-level head"],
+    ["DM","DM ","discourse marker"],
+    ["GL","GL ","prenominal genitive"],
+    ["GR","GR ","postnominal genitive"],
+    ["HD","HD ","head"],
+    ["JU","JU ","junctor"],
+    ["MC","MC ","comitative"],
+    ["MI","MI ","instrumental"],
+    ["ML","ML ","locative"],
+    ["MNR","MNR ","postnominal modifier"],
+    ["MO","MO ","modifier"],
+    ["MR","MR ","rhetorical modifier"],
+    ["MW","MW ","way (directional modifier)"],
+    ["NG","NG ","negation"],
+    ["NK","NK ","noun kernel modifier"],
+    ["NMC","NMC ","numerical component"], 
+    ["OA","OA ","accusative object"],
+    ["OA2","OA2 ","second accusative object"], 
+    ["OC","OC ","clausal object"],
+    ["OG","OG ","genitive object"], 
+    ["PD","PD ","predicate"],
+    ["PG","PG ","pseudo-genitive"],
+    ["PH","PH ","placeholder"],
+    ["PM","PM ","morphological particle"],
+    ["PNC","PNC ","proper noun component"], 
+    ["RC","RC ","relative clause"],
+    ["RE","RE ","repeated element"],
+    ["RS","RS ","reported speech"],
+    ["SB","SB ","subject"],
+    ["SBP","SBP ","passivised subject (PP)"], 
+    ["SP","SP ","subject or predicate"],
+    ["SVP","SVP ","separable verb prefix"],
+    ["UC","UC ","(idiosyncratic) unit component"], 
+    ["VO","VO ","vocative"]
+  ];
+});
diff --git a/core/src/main/resources/annotation-scripts/variables/negranodes.js b/core/src/main/resources/annotation-scripts/variables/negranodes.js
new file mode 100644
index 0000000..b6be581
--- /dev/null
+++ b/core/src/main/resources/annotation-scripts/variables/negranodes.js
@@ -0,0 +1,32 @@
+define(function () {
+  // http://www.coli.uni-saarland.de/projects/sfb378/negra-corpus/negra-corpus.html
+  // http://www.coli.uni-saarland.de/projects/sfb378/negra-corpus/knoten.html
+  return [
+    ["AA", "AA", "superlative phrase with 'am'"],
+    ["AP","AP", "adjektive phrase"],
+    ["AVP","AVP", "adverbial phrase"],
+    ["CAP","CAP", "coordinated adjektive phrase"],
+    ["CAVP","CAVP", "coordinated adverbial phrase"],
+    ["CAC","CAC", "coordinated adposition"],
+    ["CCP","CCP", "coordinated complementiser"],
+    ["CH","CH", "chunk"],
+    ["CNP","CNP", "coordinated noun phrase"],
+    ["CO","CO", "coordination"],
+    ["CPP","CPP", "coordinated adpositional phrase"],
+    ["CS","CS", "coordinated sentence"],
+    ["CVP","CVP", "coordinated verb phrase (non-finite)"],
+    ["CVZ","CVZ", "coordinated zu-marked infinitive"],
+    ["DL","DL", "discourse level constituent"],
+    ["ISU","ISU", "idiosyncratis unit"],
+    ["MPN","MPN", "multi-word proper noun"],
+    ["MTA","MTA", "multi-token adjective"],
+    ["NM","NM", "multi-token number"],
+    ["NP","NP", "noun phrase"],
+    ["PP","PP", "adpositional phrase"],
+    ["QL","QL", "quasi-languag"],
+    ["ROOT","ROOT", "root node"],
+    ["S","S", "sentence"],
+    ["VP","VP", "verb phrase (non-finite)"],
+    ["VZ","VZ", "zu-marked infinitive"]
+  ]
+});
diff --git a/core/src/main/resources/annotation-scripts/variables/stts.js b/core/src/main/resources/annotation-scripts/variables/stts.js
new file mode 100644
index 0000000..f7d3b62
--- /dev/null
+++ b/core/src/main/resources/annotation-scripts/variables/stts.js
@@ -0,0 +1,59 @@
+define(function () {
+  return [
+    // http://www.ids-mannheim.de/cosmas2/projekt/referenz/stts/morph.html
+    // http://nachhalt.sfb632.uni-potsdam.de/owl-docu/stts.html
+    // "$.", "$(", "$,"
+    ["ADJA","ADJA ", "Attributive Adjective"],
+    ["ADJD","ADJD ", "Predicative Adjective"],
+    ["ADV","ADV ", "Adverb"],
+    ["APPO","APPO ", "Postposition"],
+    ["APPR","APPR ", "Preposition"],
+    ["APPRART","APPRART ", "Preposition with Determiner"],
+    ["APZR","APZR ","Right Circumposition"],
+    ["ART","ART ", "Determiner"],
+    ["CARD","CARD ", "Cardinal Number"],
+    ["FM","FM ", "Foreign Material"],
+    ["ITJ","ITJ ", "Interjection"],
+    ["KOKOM","KOKOM ", "Comparison Particle"],
+    ["KON","KON ", "Coordinating Conjuncion"],
+    ["KOUI","KOUI ", "Subordinating Conjunction with 'zu'"],
+    ["KOUS","KOUS ", "Subordinating Conjunction with Sentence"],
+    ["NE","NE ", "Named Entity"],
+    ["NN","NN ", "Normal Nomina"],
+    ["PAV", "PAV ", "Pronominal Adverb"],
+    ["PDAT","PDAT ","Attributive Demonstrative Pronoun"],
+    ["PDS","PDS ", "Substitutive Demonstrative Pronoun"],
+    ["PIAT","PIAT ", "Attributive Indefinite Pronoun without Determiner"],
+    ["PIDAT","PIDAT ", "Attributive Indefinite Pronoun with Determiner"],
+    ["PIS","PIS ", "Substitutive Indefinite Pronoun"],
+    ["PPER","PPER ", "Personal Pronoun"],
+    ["PPOSAT","PPOSAT ", "Attributive Possessive Pronoun"],
+    ["PPOSS","PPOSS ", "Substitutive Possessive Pronoun"],
+    ["PRELAT","PRELAT ", "Attributive Relative Pronoun"],
+    ["PRELS","PRELS ", "Substitutive Relative Pronoun"],
+    ["PRF","PRF ", "Reflexive Pronoun"],
+    ["PROAV","PROAV ", "Pronominal Adverb"],
+    ["PTKA","PTKA ","Particle with Adjective"],
+    ["PTKANT","PTKANT ", "Answering Particle"],
+    ["PTKNEG","PTKNEG ", "Negation Particle"],
+    ["PTKVZ","PTKVZ ", "Separated Verbal Particle"],
+    ["PTKZU","PTKZU ", "'zu' Particle"],
+    ["PWAT","PWAT ", "Attributive Interrogative Pronoun"],
+    ["PWAV","PWAV ", "Adverbial Interrogative Pronoun"],
+    ["PWS","PWS ", "Substitutive Interrogative Pronoun"],
+    ["TRUNC","TRUNC ","Truncated"],
+    ["VAFIN","VAFIN ", "Auxiliary Finite Verb"],
+    ["VAIMP","VAIMP ", "Auxiliary Finite Imperative Verb"],
+    ["VAINF","VAINF ", "Auxiliary Infinite Verb"],
+    ["VAPP","VAPP ", "Auxiliary Perfect Participle"],
+    ["VMFIN","VMFIN ", "Modal Finite Verb"],
+    ["VMINF","VMINF ", "Modal Infinite Verb"],
+    ["VMPP","VMPP ", "Modal Perfect Participle"],
+    ["VVFIN","VVFIN ","Finite Verb"],
+    ["VVIMP","VVIMP ", "Finite Imperative Verb"],
+    ["VVINF","VVINF ", "Infinite Verb"],
+    ["VVIZU","VVIZU ", "Infinite Verb with 'zu'"],
+    ["VVPP","VVPP ", "Perfect Participle"],
+    ["XY", "XY ", "Non-Word"]
+  ];
+});