Fixed the order of annotation keys and values, and added tests.

Change-Id: I1e6a9f27cea2f395bb7c5f27967e5a2d891420ba
diff --git a/full/Changes b/full/Changes
index effcc1c..bef9e7c 100644
--- a/full/Changes
+++ b/full/Changes
@@ -4,6 +4,9 @@
     - Updated annotation tables & implemented key-value structure (margaretha)
     - Added annotation parser for annotation data from kalamar (margaretha)
     - Implemented parsing free resource info from json (margaretha)
+22/10/2018
+    - Updated jetty, spring and hibernate versions (margaretha)
+    - Fixed annotation order & added tests (margaretha)
 
 # version 0.61.2
 12/09/2018
diff --git a/full/pom.xml b/full/pom.xml
index 5edfc7f..f92fe29 100644
--- a/full/pom.xml
+++ b/full/pom.xml
@@ -7,11 +7,10 @@
 	<properties>
 		<java.version>1.8</java.version>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-		<spring-framework.version>5.0.3.RELEASE</spring-framework.version>
-		<spring-security.version>4.2.3.RELEASE</spring-security.version>
-		<jetty.version>9.4.8.v20171121</jetty.version>
+		<spring-framework.version>5.1.1.RELEASE</spring-framework.version>
+		<jetty.version>9.4.12.v20180830</jetty.version>
 		<jersey.version>1.19.4</jersey.version>
-		<hibernate.version>5.1.11.Final</hibernate.version>
+		<hibernate.version>5.3.7.Final</hibernate.version>
 	</properties>
 	<build>
 		<!-- <resources>
@@ -39,6 +38,7 @@
 				<includes>
 					<include>**/*.info</include>
 					<include>**/*.properties</include>
+					<include>**/*.json</include>
 				</includes>
 			</testResource>
 		</testResources>
@@ -151,7 +151,7 @@
 		<dependency>
 			<groupId>de.ids_mannheim.korap</groupId>
 			<artifactId>Kustvakt-core</artifactId>
-			<version>0.61.2</version>
+			<version>0.61.3</version>
 		</dependency>
 		<!-- LDAP -->
 		<dependency>
@@ -191,7 +191,7 @@
 		<dependency>
 		    <groupId>org.hibernate</groupId>
 		    <artifactId>hibernate-c3p0</artifactId>
-		    <version>5.3.5.Final</version>
+		    <version>${hibernate.version}</version>
 		</dependency>
 		
 		<dependency>
@@ -241,12 +241,12 @@
 		<dependency>
 			<groupId>org.springframework.security</groupId>
 			<artifactId>spring-security-core</artifactId>
-			<version>${spring-security.version}</version>
+			<version>${spring-framework.version}</version>
 		</dependency>
 		<dependency>
 			<groupId>org.springframework.security</groupId>
 			<artifactId>spring-security-web</artifactId>
-			<version>${spring-security.version}</version>
+			<version>${spring-framework.version}</version>
 		</dependency>
 
 		<!-- velocity -->
diff --git a/full/src/main/java/de/ids_mannheim/korap/annotation/AnnotationParser.java b/full/src/main/java/de/ids_mannheim/korap/annotation/AnnotationParser.java
index ab3cd02..c05ae6b 100644
--- a/full/src/main/java/de/ids_mannheim/korap/annotation/AnnotationParser.java
+++ b/full/src/main/java/de/ids_mannheim/korap/annotation/AnnotationParser.java
@@ -141,18 +141,19 @@
             if (layer == null) {
                 computeLayer(annotationCode);
             }
-            String code = array.get(1);
-            if (code.endsWith("=") || code.endsWith(":")) {
-                code = code.substring(0, code.length() - 1);
-            }
+
             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(code, annotationType,
-                        array.get(1), array.get(2));
+                annotation = retrieveOrCreateAnnotation(array.get(0),
+                        annotationType, array.get(1), array.get(2));
             }
             if (annotation != null) {
                 AnnotationKey annotationKey =
@@ -167,8 +168,7 @@
             if (this.key == null) {
                 computeKey(annotationCode);
             }
-            String valueCode = array.get(0);
-            Annotation value = retrieveOrCreateAnnotation(valueCode,
+            Annotation value = retrieveOrCreateAnnotation(array.get(0),
                     AnnotationType.VALUE, array.get(1), array.get(2));
             if (value != null) {
                 values.add(value);
diff --git a/full/src/main/java/de/ids_mannheim/korap/config/Initializator.java b/full/src/main/java/de/ids_mannheim/korap/config/Initializator.java
index 1cccb4f..e6347e8 100644
--- a/full/src/main/java/de/ids_mannheim/korap/config/Initializator.java
+++ b/full/src/main/java/de/ids_mannheim/korap/config/Initializator.java
@@ -45,8 +45,10 @@
         resourceParser.run();
     }
 
-    public void initTest () {
+    public void initTest () throws IOException, KustvaktException {
         setInitialAccessScope();
+        annotationParser.run();
+        resourceParser.run();
     }
 
     private void setInitialAccessScope () {
diff --git a/full/src/main/java/de/ids_mannheim/korap/dto/FoundryDto.java b/full/src/main/java/de/ids_mannheim/korap/dto/FoundryDto.java
index aa6ef2f..26cf383 100644
--- a/full/src/main/java/de/ids_mannheim/korap/dto/FoundryDto.java
+++ b/full/src/main/java/de/ids_mannheim/korap/dto/FoundryDto.java
@@ -2,6 +2,7 @@
 
 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;
@@ -36,14 +37,14 @@
     public class Layer {
         private String code;
         private String description;
-        private List<Key> keys;
+        private Set<Key> keys;
     }
 
     @Getter
     @Setter
     @JsonInclude(Include.NON_EMPTY)
     @JsonSerialize(include=Inclusion.NON_EMPTY) // old codehouse annotation used by jersey
-    public class Key {
+    public class Key implements Comparable<Key>{
 
         private String code;
         private String description;
@@ -52,5 +53,10 @@
         public Key (String code) {
             this.code = code;
         }
+        
+        @Override
+        public int compareTo (Key k) {
+            return this.code.compareTo(k.code); 
+        }
     }
 }
diff --git a/full/src/main/java/de/ids_mannheim/korap/dto/converter/AnnotationConverter.java b/full/src/main/java/de/ids_mannheim/korap/dto/converter/AnnotationConverter.java
index 272d4c8..efe1c43 100644
--- a/full/src/main/java/de/ids_mannheim/korap/dto/converter/AnnotationConverter.java
+++ b/full/src/main/java/de/ids_mannheim/korap/dto/converter/AnnotationConverter.java
@@ -4,6 +4,9 @@
 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;
 
@@ -86,11 +89,12 @@
                 }
 
                 Annotation layer = f.getLayer();
-                List<Key> keys = new ArrayList<>();
+                Set<Key> keys = new TreeSet<>();
 
                 for (AnnotationKey ak : f.getKeys()) {
                     Annotation a = ak.getKey();
-                    Map<String, String> values = new HashMap<>();
+                    Map<String, String> values = new TreeMap<>();
+                    
                     Key key = dto.new Key(a.getCode());
                     if (language.equals("de")) {
                         key.setDescription(a.getGermanDescription());
diff --git a/full/src/main/java/de/ids_mannheim/korap/entity/Annotation.java b/full/src/main/java/de/ids_mannheim/korap/entity/Annotation.java
index f644b25..35ee11d 100644
--- a/full/src/main/java/de/ids_mannheim/korap/entity/Annotation.java
+++ b/full/src/main/java/de/ids_mannheim/korap/entity/Annotation.java
@@ -23,15 +23,6 @@
 @Table(name = "annotation")
 public class Annotation {
 
-    public Annotation () {}
-
-    public Annotation (String code, String type, String text, String description) {
-        this.code = code;
-        this.type = type;
-        this.text = text;
-        this.description = description;
-    }
-
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     private int id;
@@ -42,6 +33,16 @@
     @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
diff --git a/full/src/main/resources/default-config.xml b/full/src/main/resources/default-config.xml
index e5f2c1e..c653150 100644
--- a/full/src/main/resources/default-config.xml
+++ b/full/src/main/resources/default-config.xml
@@ -5,15 +5,15 @@
 	xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
 	xmlns:cache="http://www.springframework.org/schema/cache"
 	xsi:schemaLocation="http://www.springframework.org/schema/beans
-           http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
+           http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/tx
-           http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
+           http://www.springframework.org/schema/tx/spring-tx.xsd
            http://www.springframework.org/schema/aop
-           http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
+           http://www.springframework.org/schema/aop/spring-aop.xsd
            http://www.springframework.org/schema/context
-           http://www.springframework.org/schema/context/spring-context-4.0.xsd
+           http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/util
-           http://www.springframework.org/schema/util/spring-util-4.0.xsd">
+           http://www.springframework.org/schema/util/spring-util.xsd">
 
 	<context:component-scan base-package="de.ids_mannheim.korap" />
 	<context:annotation-config />
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/AnnotationControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/AnnotationControllerTest.java
new file mode 100644
index 0000000..0b37968
--- /dev/null
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/AnnotationControllerTest.java
@@ -0,0 +1,99 @@
+package de.ids_mannheim.korap.web.controller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Iterator;
+import java.util.Map.Entry;
+
+import javax.ws.rs.core.MediaType;
+
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.sun.jersey.api.client.ClientResponse;
+
+import de.ids_mannheim.korap.config.SpringJerseyTest;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.utils.JsonUtils;
+
+public class AnnotationControllerTest extends SpringJerseyTest {
+    @Test
+    public void testAnnotationLayers () throws KustvaktException {
+        ClientResponse response = resource().path(API_VERSION)
+                .path("annotation").path("layers").get(ClientResponse.class);
+
+        String entity = response.getEntity(String.class);
+        JsonNode n = JsonUtils.readTree(entity);
+
+        assertEquals(31, n.size());
+        n = n.get(0);
+        assertEquals(1, n.get("id").asInt());
+        assertEquals("opennlp/p", n.get("code").asText());
+        assertEquals("p", n.get("layer").asText());
+        assertEquals("opennlp", n.get("foundry").asText());
+        assertNotNull(n.get("description"));
+    }
+
+    @Test
+    public void testAnnotationFoundry () throws KustvaktException {
+        ClientResponse response =
+                resource().path(API_VERSION).path("annotation")
+                        .path("description").type(MediaType.APPLICATION_JSON)
+                        .entity("{\"codes\":[\"opennlp/*\"], \"language\":\"en\"}")
+                        .post(ClientResponse.class);
+
+        String entity = response.getEntity(String.class);
+        JsonNode n = JsonUtils.readTree(entity);
+
+        n = n.get(0);
+        assertEquals("opennlp", n.get("code").asText());
+        assertEquals("OpenNLP", n.get("description").asText());
+        assertEquals(1, n.get("layers").size());
+
+        n = n.get("layers").get(0);
+        assertEquals("p", n.get("code").asText());
+        assertEquals("Part-of-Speech", n.get("description").asText());
+        assertEquals(52, n.get("keys").size());
+
+        n = n.get("keys").get(0);
+        assertEquals("ADJA", n.get("code").asText());
+        assertEquals("Attributive Adjective", n.get("description").asText());
+        assertTrue(n.get("values") == null);
+    }
+
+    @Test
+    public void testAnnotationValues () throws KustvaktException {
+        ClientResponse response =
+                resource().path(API_VERSION).path("annotation")
+                        .path("description").type(MediaType.APPLICATION_JSON)
+                        .entity("{\"codes\":[\"mate/m\"], \"language\":\"en\"}")
+                        .post(ClientResponse.class);
+
+        String entity = response.getEntity(String.class);
+        JsonNode n = JsonUtils.readTree(entity);
+
+        n = n.get(0);
+        assertEquals("mate", n.get("code").asText());
+        assertEquals("Mate", n.get("description").asText());
+        assertEquals(1, n.get("layers").size());
+
+        n = n.get("layers").get(0);
+        assertEquals("m", n.get("code").asText());
+        assertEquals("Morphology", n.get("description").asText());
+        assertEquals(8, n.get("keys").size());
+
+        n = n.get("keys").get(1);
+        assertEquals("case", n.get("code").asText());
+        assertEquals("Case", n.get("description").asText());
+        assertEquals(5, n.get("values").size());
+
+        n = n.get("values");
+        Iterator<Entry<String, JsonNode>> fields = n.fields();
+        Entry<String, JsonNode> e = fields.next();
+        assertEquals("*", e.getKey());
+        assertEquals("Undefined", e.getValue().asText());
+    }
+
+}
diff --git a/full/src/test/resources/test-config.xml b/full/src/test/resources/test-config.xml
index 7a4b439..26dc607 100644
--- a/full/src/test/resources/test-config.xml
+++ b/full/src/test/resources/test-config.xml
@@ -5,15 +5,15 @@
 	xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
 	xmlns:cache="http://www.springframework.org/schema/cache"
 	xsi:schemaLocation="http://www.springframework.org/schema/beans
-           http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
+           http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/tx
-           http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
+           http://www.springframework.org/schema/tx/spring-tx.xsd
            http://www.springframework.org/schema/aop
-           http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
+           http://www.springframework.org/schema/aop/spring-aop.xsd
            http://www.springframework.org/schema/context
-           http://www.springframework.org/schema/context/spring-context-4.0.xsd
+           http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/util
-           http://www.springframework.org/schema/util/spring-util-4.0.xsd">
+           http://www.springframework.org/schema/util/spring-util.xsd">
 
 	<context:component-scan base-package="de.ids_mannheim.korap" />
 	<context:annotation-config />