Added annotation description service.

Change-Id: I3c30a2815f63924a89af1ca7d251c46a54a21a7c
diff --git a/src/main/java/de/ids_mannheim/korap/dao/AnnotationDao.java b/src/main/java/de/ids_mannheim/korap/dao/AnnotationDao.java
index ba12856..a6394aa 100644
--- a/src/main/java/de/ids_mannheim/korap/dao/AnnotationDao.java
+++ b/src/main/java/de/ids_mannheim/korap/dao/AnnotationDao.java
@@ -10,13 +10,10 @@
 import javax.persistence.criteria.Predicate;
 import javax.persistence.criteria.Root;
 
-import org.antlr.v4.parse.ANTLRParser.id_return;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
 import org.springframework.stereotype.Component;
 
-import de.ids_mannheim.korap.entity.Annotation;
 import de.ids_mannheim.korap.entity.AnnotationPair;
 
 
@@ -31,21 +28,19 @@
 public class AnnotationDao {
 
     private static Logger jlog = LoggerFactory.getLogger(AnnotationDao.class);
-    private NamedParameterJdbcTemplate jdbcTemplate;
-
     @PersistenceContext
     private EntityManager entityManager;
 
 
     /**
-     * Select all foundry and layer pairs.
+     * Retrieves all foundry-layer pairs.
      * 
-     * @return a list of all foundry and layer pairs.
+     * @return a list of foundry-layer pairs.
      */
     public List<AnnotationPair> getAllFoundryLayerPairs () {
         CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
-        CriteriaQuery<AnnotationPair> query = criteriaBuilder
-                .createQuery(AnnotationPair.class);
+        CriteriaQuery<AnnotationPair> query =
+                criteriaBuilder.createQuery(AnnotationPair.class);
         Root<AnnotationPair> annotationPair = query.from(AnnotationPair.class);
         annotationPair.fetch("annotation1");
         annotationPair.fetch("annotation2");
@@ -53,38 +48,44 @@
         Query q = entityManager.createQuery(query);
         return q.getResultList();
     }
-    
-    public List<AnnotationPair> getAllAnnotationDescriptions () {
-        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
-        CriteriaQuery<AnnotationPair> query = criteriaBuilder
-                .createQuery(AnnotationPair.class);
-        Root<AnnotationPair> annotationPair = query.from(AnnotationPair.class);
-        annotationPair.fetch("annotation1");
-        annotationPair.fetch("annotation2");
-        annotationPair.fetch("values");
-        query.select(annotationPair);
-        Query q = entityManager.createQuery(query);
-        return q.getResultList();
-    }
 
 
     /**
-     * Select foundry and layer pairs' information of the given foundries.
+     * 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.
      * 
-     * @return a list of foundry and layer pairs.
+     * @param foundry a foundry code
+     * @param layer a layer code
+     * @return a list of foundry-layer pairs.
      */
-    public List<AnnotationPair> getFoundryLayerPairs (List<String> foundries) {
+    public List<AnnotationPair> getAnnotationDescriptions (String foundry,
+            String layer) {
+        
         CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
-
         CriteriaQuery<Object> query = criteriaBuilder.createQuery();
-        Root<Annotation> annotation = query.from(Annotation.class);
         Root<AnnotationPair> annotationPair = query.from(AnnotationPair.class);
-        Predicate foundryPredicate = criteriaBuilder.equal(annotation.get("symbol"),
-                foundries);
-        Predicate valuePredicate =  criteriaBuilder.equal(annotationPair.get("value").get("id"),
-                annotation.get("id"));
-        Predicate wherePredicate = criteriaBuilder.and(foundryPredicate,valuePredicate);
-        query.multiselect(annotation, annotationPair).where(wherePredicate);
+        annotationPair.fetch("annotation1");
+        annotationPair.fetch("annotation2");
+        annotationPair.fetch("values");
+        query = query.select(annotationPair);
+        if (!foundry.isEmpty()) {
+            Predicate foundryPredicate = criteriaBuilder.equal(
+                    annotationPair.get("annotation1").get("code"), foundry);
+            if (layer.isEmpty() || layer.equals("*")) {
+                query.where(foundryPredicate);
+            }
+            else {
+                Predicate layerPredicate = criteriaBuilder.equal(
+                        annotationPair.get("annotation2").get("code"), layer);
+                Predicate andPredicate =
+                        criteriaBuilder.and(foundryPredicate, layerPredicate);
+                query.where(andPredicate);
+            }
+        }
+
+        query.distinct(true); 
         Query q = entityManager.createQuery(query);
         return q.getResultList();
     }
diff --git a/src/main/java/de/ids_mannheim/korap/dao/ResourceDao.java b/src/main/java/de/ids_mannheim/korap/dao/ResourceDao.java
index 46c6432..0dd68f8 100644
--- a/src/main/java/de/ids_mannheim/korap/dao/ResourceDao.java
+++ b/src/main/java/de/ids_mannheim/korap/dao/ResourceDao.java
@@ -24,7 +24,7 @@
 @Component
 public class ResourceDao {
 
-    private static Logger jlog = LoggerFactory.getLogger(ResourceDao.class);
+//    private static Logger jlog = LoggerFactory.getLogger(ResourceDao.class);
 
     @PersistenceContext
     private EntityManager entityManager;
diff --git a/src/main/java/de/ids_mannheim/korap/dto/LayerDto.java b/src/main/java/de/ids_mannheim/korap/dto/LayerDto.java
new file mode 100644
index 0000000..4a6c0c7
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/dto/LayerDto.java
@@ -0,0 +1,15 @@
+package de.ids_mannheim.korap.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class LayerDto {
+
+    private int id;
+    private String code;
+    private String layer;
+    private String foundry;
+    private String description;
+}
diff --git a/src/main/java/de/ids_mannheim/korap/dto/ResourceDto.java b/src/main/java/de/ids_mannheim/korap/dto/ResourceDto.java
new file mode 100644
index 0000000..45575df
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/dto/ResourceDto.java
@@ -0,0 +1,27 @@
+package de.ids_mannheim.korap.dto;
+
+import java.util.Map;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Setter
+@Getter
+public class ResourceDto {
+
+    private String resourceId;
+    private String germanTitle;
+    private String englishTitle;
+    private String description;
+    private Map<Integer, String> layers;
+    private Map<String, String> languages;
+
+
+    @Override
+    public String toString () {
+        return "resourceId= " + resourceId + ", germanTitle= " + germanTitle
+                + ", englishTitle= " + englishTitle + ", description= "
+                + description + ", languages= " + languages + ", layers= "
+                + layers;
+    }
+}
diff --git a/src/main/java/de/ids_mannheim/korap/dto/converter/AnnotationConverter.java b/src/main/java/de/ids_mannheim/korap/dto/converter/AnnotationConverter.java
new file mode 100644
index 0000000..61a6f63
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/dto/converter/AnnotationConverter.java
@@ -0,0 +1,34 @@
+package de.ids_mannheim.korap.dto.converter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.stereotype.Component;
+
+import de.ids_mannheim.korap.dto.LayerDto;
+import de.ids_mannheim.korap.entity.AnnotationPair;
+
+@Component
+public class AnnotationConverter {
+
+    public List<LayerDto> convertToLayerDto (List<AnnotationPair> layers) {
+        List<LayerDto> layerDtos = new ArrayList<LayerDto>(layers.size());
+        LayerDto dto;
+        String foundry, layer;
+        for (AnnotationPair l : layers) {
+            dto = new LayerDto();
+            dto.setId(l.getId());
+            dto.setDescription(l.getEnglishDescription());
+
+            foundry = l.getAnnotation1().getCode();
+            dto.setFoundry(foundry);
+
+            layer = l.getAnnotation2().getCode();
+            dto.setLayer(layer);
+            dto.setCode(foundry + "/" + layer);
+            layerDtos.add(dto);
+        }
+        
+        return layerDtos;
+    }
+}
diff --git a/src/main/java/de/ids_mannheim/korap/dto/converter/ResourceConverter.java b/src/main/java/de/ids_mannheim/korap/dto/converter/ResourceConverter.java
new file mode 100644
index 0000000..f79119d
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/dto/converter/ResourceConverter.java
@@ -0,0 +1,49 @@
+package de.ids_mannheim.korap.dto.converter;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.stereotype.Component;
+
+import de.ids_mannheim.korap.dto.ResourceDto;
+import de.ids_mannheim.korap.entity.AnnotationPair;
+import de.ids_mannheim.korap.entity.Resource;
+
+@Component
+public class ResourceConverter {
+
+    public List<ResourceDto> convertToResourcesDto (List<Resource> resources) {
+        List<ResourceDto> resourceDtoList = new ArrayList<ResourceDto>(resources.size());
+        ResourceDto dto;
+        Map<String, String> languages;
+        HashMap<Integer, String> layers;
+        for (Resource r: resources){
+            dto = new ResourceDto();
+            dto.setDescription(r.getEnglishDescription());
+            dto.setEnglishTitle(r.getEnglishTitle());
+            dto.setGermanTitle(r.getGermanTitle());
+            dto.setResourceId(r.getId());
+            
+            languages = new HashMap<String, String>();
+            languages.put("en", r.getEnglishTitle());
+            languages.put("de", r.getGermanTitle());
+            dto.setLanguages(languages);
+            
+            layers = new HashMap<Integer, String>();
+            String foundry, layer, code;
+            for (AnnotationPair annotationPair : r.getLayers()){
+                foundry = annotationPair.getAnnotation1().getCode();
+                layer = annotationPair.getAnnotation2().getCode();
+                code = foundry +"/"+layer;
+                layers.put(annotationPair.getId(), code);
+            }
+            dto.setLayers(layers);
+            
+            resourceDtoList.add(dto);
+        }
+        
+        return resourceDtoList;
+    }
+}
diff --git a/src/main/java/de/ids_mannheim/korap/entity/Annotation.java b/src/main/java/de/ids_mannheim/korap/entity/Annotation.java
index 0dd4546..e63eb74 100644
--- a/src/main/java/de/ids_mannheim/korap/entity/Annotation.java
+++ b/src/main/java/de/ids_mannheim/korap/entity/Annotation.java
@@ -18,13 +18,13 @@
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     private int id;
-    private String symbol;
+    private String code;
     private String type;
     private String description;
 
     @Override
     public String toString () {
-        return "id=" + id + ", symbol= " + symbol + ", type= " + type
+        return "id=" + id + ", code= " + code + ", type= " + type
                 + ", description=" + description;
     }
 }
diff --git a/src/main/java/de/ids_mannheim/korap/entity/AnnotationPair.java b/src/main/java/de/ids_mannheim/korap/entity/AnnotationPair.java
index 3e15d78..ee69da0 100644
--- a/src/main/java/de/ids_mannheim/korap/entity/AnnotationPair.java
+++ b/src/main/java/de/ids_mannheim/korap/entity/AnnotationPair.java
@@ -11,10 +11,12 @@
 import javax.persistence.JoinColumn;
 import javax.persistence.JoinTable;
 import javax.persistence.ManyToMany;
-import javax.persistence.OneToMany;
 import javax.persistence.OneToOne;
 import javax.persistence.Table;
 
+import org.hibernate.annotations.Fetch;
+import org.hibernate.annotations.FetchMode;
+
 import lombok.Getter;
 import lombok.Setter;
 
@@ -35,11 +37,13 @@
     @Column(name = "description")
     private String englishDescription;
 
-    @OneToOne(fetch=FetchType.LAZY)
+    @Fetch(FetchMode.SELECT)
+    @OneToOne
     @JoinColumn(name = "annotation1", insertable = false, updatable = false)
     private Annotation annotation1;
-
-    @OneToOne(fetch=FetchType.LAZY)
+    
+    @Fetch(FetchMode.SELECT)
+    @OneToOne
     @JoinColumn(name = "annotation2", insertable = false, updatable = false)
     private Annotation annotation2;
 
@@ -56,9 +60,8 @@
         return "id=" + id + ", annotation1=" + annotationId1 + ", annotation2="
                 + annotationId1 + ", description=" + englishDescription
                 + ", germanDescription= " + germanDescription 
-                + "annotation1= "+ annotation1
-                + "annotation2= "+ annotation2;
+                + ", annotation1= "+ annotation1
+                + ", annotation2= "+ annotation2;
                 
     }
-
 }
diff --git a/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java b/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
index cea63b1..982026e 100644
--- a/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
+++ b/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
@@ -23,7 +23,7 @@
     public static final int ILLEGAL_ARGUMENT = 104;
     public static final int MISSING_ARGUMENT = 105;
     public static final int CONNECTION_ERROR = 106;
-    public static final int PARAMETER_VALIDATION_ERROR = 107;
+    public static final int PARAMETER_INVALID = 107;
     public static final int NOT_SUPPORTED = 108;
 
     /**
diff --git a/src/main/java/de/ids_mannheim/korap/utils/JsonUtils.java b/src/main/java/de/ids_mannheim/korap/utils/JsonUtils.java
index 835106b..c9f0a25 100644
--- a/src/main/java/de/ids_mannheim/korap/utils/JsonUtils.java
+++ b/src/main/java/de/ids_mannheim/korap/utils/JsonUtils.java
@@ -20,7 +20,6 @@
 public class JsonUtils {
     private static ObjectMapper mapper = new ObjectMapper();
 
-
     private JsonUtils () {}
 
 
@@ -58,7 +57,10 @@
         return mapper.valueToTree(value);
     }
 
-
+    public static <T> T convert (JsonNode json, Class<T> cl) throws IOException {
+        return mapper.convertValue(json, cl);
+    }
+    
     public static <T> T read (String json, Class<T> cl) throws IOException {
         return mapper.readValue(json, cl);
     }
diff --git a/src/main/java/de/ids_mannheim/korap/web/service/full/AnnotationService.java b/src/main/java/de/ids_mannheim/korap/web/service/full/AnnotationService.java
index 06b4299..93afb41 100644
--- a/src/main/java/de/ids_mannheim/korap/web/service/full/AnnotationService.java
+++ b/src/main/java/de/ids_mannheim/korap/web/service/full/AnnotationService.java
@@ -1,12 +1,14 @@
 package de.ids_mannheim.korap.web.service.full;
 
+import java.io.IOException;
+import java.util.ArrayList;
 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.QueryParam;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
@@ -15,14 +17,15 @@
 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.dao.AnnotationDao;
-import de.ids_mannheim.korap.entity.Annotation;
+import de.ids_mannheim.korap.dto.LayerDto;
+import de.ids_mannheim.korap.dto.converter.AnnotationConverter;
 import de.ids_mannheim.korap.entity.AnnotationPair;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.utils.JsonUtils;
-import de.ids_mannheim.korap.web.KustvaktServer;
 import de.ids_mannheim.korap.web.filter.AuthFilter;
 import de.ids_mannheim.korap.web.filter.DemoUserFilter;
 import de.ids_mannheim.korap.web.filter.PiwikFilter;
@@ -40,62 +43,111 @@
 @Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
 public class AnnotationService {
 
-    private static Logger jlog = LoggerFactory
-            .getLogger(AnnotationService.class);
+    private static Logger jlog =
+            LoggerFactory.getLogger(AnnotationService.class);
 
     @Autowired
     private AnnotationDao annotationDao;
-    
-    /** Returns information about all supported layers
+
+    @Autowired
+    private AnnotationConverter annotationConverter;
+
+
+    /**
+     * Returns information about all supported layers
      * 
-     * @return a json serialization of all supported layers 
+     * @return a json serialization of all supported layers
      */
     @GET
     @Path("layers")
     public Response getLayers () {
         List<AnnotationPair> layers = annotationDao.getAllFoundryLayerPairs();
-        String result = JsonUtils.toJSON(layers);
-        jlog.debug("/layers "+layers.toString());
+        List<LayerDto> layerDto = annotationConverter.convertToLayerDto(layers);
+        String result = JsonUtils.toJSON(layerDto);
+        jlog.debug("/layers " + layers.toString());
         return Response.ok(result).build();
     }
 
 
+    /**
+     * Returns descriptions and values of the given foundry-layer
+     * pairs.
+     * 
+     * @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
+     */
     @POST
     @Path("description")
-    public Response getAnnotations (@QueryParam("symbol") List<String> symbols,
-            String language) {
-        List<AnnotationPair> annotationPairs = null;
-        if (language == null || language.isEmpty()) {
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Response getAnnotations (String json) {
+        JsonNode node = JsonUtils.readTree(json);
+        if (node == null) { throw KustvaktResponseHandler.throwit(
+                StatusCodes.MISSING_ARGUMENT, "Missing a json string."); }
+
+        String language;
+        if (!node.has("language")) {
             language = "en";
         }
-        if (symbols == null){
-            throw KustvaktResponseHandler.throwit(StatusCodes.MISSING_ARGUMENT);
-        }
-        if (symbols.isEmpty() || symbols.contains("*")){
-            annotationPairs = annotationDao.getAllAnnotationDescriptions(); 
-        }
         else {
-            String[] annotationSymbols;
-            String foundry, layer;
-            
-            for (String s : symbols){
-                annotationSymbols = s.split("/");
-                if (annotationSymbols.length != 2){
-                    throw KustvaktResponseHandler.throwit(StatusCodes.PARAMETER_VALIDATION_ERROR);
-                }
-                foundry = annotationSymbols[0];
-                layer = annotationSymbols[1];
-                // select
+            language = node.get("language").asText();
+            if (language == null || language.isEmpty()) {
+                language = "en";
             }
         }
-        
-        if (annotationPairs != null && !annotationPairs.isEmpty()){
+
+        List<String> codes;
+        try {
+            codes = JsonUtils.convert(node.get("codes"), List.class);
+        }
+        catch (IOException | NullPointerException e) {
+            throw KustvaktResponseHandler.throwit(StatusCodes.PARAMETER_INVALID,
+                    "Bad parameter:", json);
+        }
+        if (codes == null) { throw KustvaktResponseHandler
+                .throwit(StatusCodes.MISSING_ARGUMENT); }
+
+        List<AnnotationPair> annotationPairs = null;
+        String foundry = "", layer = "";
+        if (codes.contains("*")) {
+            annotationPairs =
+                    annotationDao.getAnnotationDescriptions(foundry, layer);
+        }
+        else {
+            String[] annotationCode;
+            annotationPairs = new ArrayList<AnnotationPair>();
+            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 KustvaktResponseHandler.throwit(
+                            StatusCodes.PARAMETER_INVALID, "Bad parameter:",
+                            code);
+                }
+
+                annotationPairs.addAll(annotationDao
+                        .getAnnotationDescriptions(foundry, layer));
+            }
+        }
+
+        if (annotationPairs != null && !annotationPairs.isEmpty()) {
             String result = JsonUtils.toJSON(annotationPairs);
-            jlog.debug("/layers "+annotationPairs.toString());
+            jlog.debug("/layers " + annotationPairs.toString());
             return Response.ok(result).build();
         }
-        else{
-            return Response.ok().build();
+        else {
+            throw KustvaktResponseHandler.throwit(StatusCodes.NO_VALUE_FOUND,
+                    "No result found.");
         }
     }
 
diff --git a/src/main/java/de/ids_mannheim/korap/web/service/full/ResourceService.java b/src/main/java/de/ids_mannheim/korap/web/service/full/ResourceService.java
index 5407c35..9599b74 100644
--- a/src/main/java/de/ids_mannheim/korap/web/service/full/ResourceService.java
+++ b/src/main/java/de/ids_mannheim/korap/web/service/full/ResourceService.java
@@ -1,13 +1,10 @@
 package de.ids_mannheim.korap.web.service.full;
 
-import java.util.ArrayList;
 import java.util.List;
 
 import javax.ws.rs.GET;
-import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
@@ -15,16 +12,14 @@
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
-import org.springframework.stereotype.Service;
 
 import com.sun.jersey.spi.container.ResourceFilters;
 
 import de.ids_mannheim.korap.dao.ResourceDao;
 import de.ids_mannheim.korap.dto.ResourceDto;
+import de.ids_mannheim.korap.dto.converter.ResourceConverter;
 import de.ids_mannheim.korap.entity.Resource;
 import de.ids_mannheim.korap.utils.JsonUtils;
-import de.ids_mannheim.korap.web.filter.AuthFilter;
-import de.ids_mannheim.korap.web.filter.DemoUserFilter;
 import de.ids_mannheim.korap.web.filter.PiwikFilter;
 
 /**
@@ -35,7 +30,7 @@
  */
 @Controller
 @Path("resource/")
-@ResourceFilters({ AuthFilter.class, DemoUserFilter.class, PiwikFilter.class })
+@ResourceFilters({PiwikFilter.class})
 @Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
 public class ResourceService {
 
@@ -43,14 +38,18 @@
 
     @Autowired
     private ResourceDao resourceDao;
+    @Autowired
+    private ResourceConverter resourceConverter;
+
 
     @GET
     @Path("info")
     public Response getAllResourceInfo () {
         List<Resource> resources = resourceDao.getAllResources();
-        String result = JsonUtils.toJSON(resources);
-        jlog.debug("/info " + resources.toString());
+        List<ResourceDto> resourceDtos = resourceConverter
+                .convertToResourcesDto(resources);
+        String result = JsonUtils.toJSON(resourceDtos);
+        jlog.debug("/info " + resourceDtos.toString());
         return Response.ok(result).build();
     }
-
 }
diff --git a/src/main/resources/db/new-mysql/V1__create_tables.sql b/src/main/resources/db/new-mysql/V1__create_tables.sql
index 926db2a..e68a45f 100644
--- a/src/main/resources/db/new-mysql/V1__create_tables.sql
+++ b/src/main/resources/db/new-mysql/V1__create_tables.sql
@@ -1,10 +1,10 @@
 
 CREATE TABLE IF NOT EXISTS annotation(
 	id INTEGER PRIMARY KEY AUTO_INCREMENT,
-	symbol VARCHAR(20) NOT NULL,
+	code VARCHAR(20) NOT NULL,
 	type VARCHAR(20) NOT NULL,	
 	description VARCHAR(100) NOT NULL,
-	UNIQUE INDEX unique_index (symbol, type)
+	UNIQUE INDEX unique_index (code, type)
 );
 
 CREATE TABLE IF NOT EXISTS annotation_pair(
diff --git a/src/main/resources/db/new-mysql/V2.0__insert_annotations.sql b/src/main/resources/db/new-mysql/V2.0__insert_annotations.sql
index 4131cc4..911f5de 100644
--- a/src/main/resources/db/new-mysql/V2.0__insert_annotations.sql
+++ b/src/main/resources/db/new-mysql/V2.0__insert_annotations.sql
@@ -1,32 +1,33 @@
 --foundries
-INSERT INTO annotation (symbol, type, description) VALUES("base","foundry","Base");
-INSERT INTO annotation (symbol, type, description) VALUES("dereko","foundry","DeReKo");
-INSERT INTO annotation (symbol, type, description) VALUES("corenlp","foundry","CoreNLP");
-INSERT INTO annotation (symbol, type, description) VALUES("cnx","foundry","Connexor");
-INSERT INTO annotation (symbol, type, description) VALUES("drukola","foundry","DruKoLa");
-INSERT INTO annotation (symbol, type, description) VALUES("glemm","foundry","Glemm");
-INSERT INTO annotation (symbol, type, description) VALUES("malt","foundry","Malt");
-INSERT INTO annotation (symbol, type, description) VALUES("marmot","foundry","MarMot");
-INSERT INTO annotation (symbol, type, description) VALUES("mate","foundry","Mate");
-INSERT INTO annotation (symbol, type, description) VALUES("mdp","foundry","MD parser");
-INSERT INTO annotation (symbol, type, description) VALUES("opennlp","foundry","OpenNLP");
-INSERT INTO annotation (symbol, type, description) VALUES("sgbr","foundry","Schreibgebrauch");
-INSERT INTO annotation (symbol, type, description) VALUES("tt","foundry","Tree Tagger");
-INSERT INTO annotation (symbol, type, description) VALUES("xip","foundry","Xerox Incremental Parser");
+INSERT INTO annotation (code, type, description) VALUES("base","foundry","Base");
+INSERT INTO annotation (code, type, description) VALUES("dereko","foundry","DeReKo");
+INSERT INTO annotation (code, type, description) VALUES("corenlp","foundry","CoreNLP");
+INSERT INTO annotation (code, type, description) VALUES("cnx","foundry","Connexor");
+INSERT INTO annotation (code, type, description) VALUES("drukola","foundry","DruKoLa");
+INSERT INTO annotation (code, type, description) VALUES("glemm","foundry","Glemm");
+INSERT INTO annotation (code, type, description) VALUES("malt","foundry","Malt");
+INSERT INTO annotation (code, type, description) VALUES("marmot","foundry","MarMot");
+INSERT INTO annotation (code, type, description) VALUES("mate","foundry","Mate");
+INSERT INTO annotation (code, type, description) VALUES("mdp","foundry","MD parser");
+INSERT INTO annotation (code, type, description) VALUES("opennlp","foundry","OpenNLP");
+INSERT INTO annotation (code, type, description) VALUES("sgbr","foundry","Schreibgebrauch");
+INSERT INTO annotation (code, type, description) VALUES("tt","foundry","Tree Tagger");
+INSERT INTO annotation (code, type, description) VALUES("xip","foundry","Xerox Incremental Parser");
 
 --layers
-INSERT INTO annotation (symbol, type, description) VALUES("c","layer","Constituency");
-INSERT INTO annotation (symbol, type, description) VALUES("d","layer","Dependency");
-INSERT INTO annotation (symbol, type, description) VALUES("p","layer","Part of speech");
-INSERT INTO annotation (symbol, type, description) VALUES("l","layer","Lemma");
-INSERT INTO annotation (symbol, type, description) VALUES("lv","layer","Lemma variant");
-INSERT INTO annotation (symbol, type, description) VALUES("m","layer","Morphology");
-INSERT INTO annotation (symbol, type, description) VALUES("ne","layer","Named entity");
-INSERT INTO annotation (symbol, type, description) VALUES("s","layer","Structure");
-INSERT INTO annotation (symbol, type, description) VALUES("syn","layer","Syntax");
+INSERT INTO annotation (code, type, description) VALUES("c","layer","Constituency");
+INSERT INTO annotation (code, type, description) VALUES("d","layer","Dependency");
+INSERT INTO annotation (code, type, description) VALUES("p","layer","Part of speech");
+INSERT INTO annotation (code, type, description) VALUES("l","layer","Lemma");
+INSERT INTO annotation (code, type, description) VALUES("lv","layer","Lemma variant");
+INSERT INTO annotation (code, type, description) VALUES("m","layer","Morphology");
+INSERT INTO annotation (code, type, description) VALUES("ne","layer","Named entity");
+INSERT INTO annotation (code, type, description) VALUES("s","layer","Structure");
+INSERT INTO annotation (code, type, description) VALUES("syn","layer","Syntax");
 
 --values
-INSERT INTO annotation (symbol, type, description) VALUES("s","value","Sentence");
-INSERT INTO annotation (symbol, type, description) VALUES("p","value","Paragraph");
-INSERT INTO annotation (symbol, type, description) VALUES("t","value","Text");
+INSERT INTO annotation (code, type, description) VALUES("s","value","Sentence");
+INSERT INTO annotation (code, type, description) VALUES("p","value","Paragraph");
+INSERT INTO annotation (code, type, description) VALUES("t","value","Text");
+INSERT INTO annotation (code, type, description) VALUES("ADJA","value","Attributive Adjective");
 
diff --git a/src/main/resources/db/new-mysql/V2.1__insert_annotation_pairs.sql b/src/main/resources/db/new-mysql/V2.1__insert_annotation_pairs.sql
index 62f01e1..3bf0f32 100644
--- a/src/main/resources/db/new-mysql/V2.1__insert_annotation_pairs.sql
+++ b/src/main/resources/db/new-mysql/V2.1__insert_annotation_pairs.sql
@@ -1,180 +1,180 @@
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="base"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="base"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Structure"),
 		"Base structure layer"; 
 
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="dereko"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="dereko"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Structure"),
 		"DeReKo structure layer"; 
 
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="cnx"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="cnx"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Constituency"),
 		"Connexor constituency layer"; 
 
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="cnx"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="cnx"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Syntax"),
 		"Connexor syntax layer"; 
 
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="cnx"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="cnx"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Part of speech"),
 		"Connexor part of speech layer"; 
 
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="cnx"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="cnx"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Lemma"),
 		"Connexor lemma layer"; 
 		
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="cnx"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="cnx"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Morphology"),
 		"Connexor morphology layer"; 
 
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="corenlp"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="corenlp"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Constituency"),
 		"CoreNLP constituency layer"; 
 
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="corenlp"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="corenlp"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Part of speech"),
 		"CoreNLP part of speech layer"; 
 
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="corenlp"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="corenlp"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Structure"),
 		"CoreNLP structure layer"; 
 
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="corenlp"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="corenlp"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Named entity"),
 		"CoreNLP named entity layer"; 
 
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="drukola"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="drukola"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Lemma"),
 		"DruKoLa lemma layer"; 
 
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="drukola"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="drukola"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Part of speech"),
 		"DruKoLa part of speech layer"; 
 		
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="drukola"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="drukola"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Morphology"),
 		"DruKoLa morphology layer"; 
 
 		
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="glemm"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="glemm"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Lemma"),
 		"Glemm lemma layer"; 
 
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="malt"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="malt"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Dependency"),
 		"Malt dependency layer"; 
 		
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="marmot"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="marmot"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Part of speech"),
 		"MarMot part of speech layer"; 
 		
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="marmot"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="marmot"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Morphology"),
 		"MarMot morphology layer"; 
 		
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="mate"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="mate"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Dependency"),
 		"Mate dependency layer";
 		
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="mate"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="mate"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Lemma"),
 		"Mate lemma layer"; 
 
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="mate"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="mate"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Part of speech"),
 		"Mate part of speech layer"; 
 
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="mate"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="mate"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Morphology"),
 		"Mate morphology layer"; 
 
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="mdp"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="mdp"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Dependency"),
 		"MD parser dependency layer"; 
 
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="opennlp"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="opennlp"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Part of speech"),
 		"OpenNLP part of speech layer"; 
 
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="opennlp"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="opennlp"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Structure"),
 		"OpenNLP structure layer"; 
 		
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="sgbr"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="sgbr"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Part of speech"),
 		"Schreibgebrauch part of speech layer"; 
 		
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="sgbr"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="sgbr"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Lemma"),
 		"Schreibgebrauch lemma layer"; 
 
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="sgbr"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="sgbr"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Lemma variant"),
 		"Schreibgebrauch lemma variant layer"; 
 
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="tt"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="tt"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Part of speech"),
 		"Tree Tagger part of speech layer"; 
 		
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="tt"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="tt"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Lemma"),
 		"Tree Tagger lemma layer"; 
 
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="tt"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="tt"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Structure"),
 		"Tree Tagger structure layer"; 
 		
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="xip"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="xip"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Lemma"),
 		"Xerox Incremental Parser lemma layer"; 
 
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="xip"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="xip"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Structure"),
 		"Xerox Incremental Parser structure layer"; 
 		
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="xip"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="xip"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Part of speech"),
 		"Xerox Incremental Parser part of speech layer"; 
 
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="xip"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="xip"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Constituency"),
 		"Xerox Incremental Parser constituency layer"; 
 
 INSERT INTO annotation_pair (annotation1, annotation2, description) 
-	SELECT (SELECT a.id FROM annotation as a WHERE a.symbol="xip"),
+	SELECT (SELECT a.id FROM annotation as a WHERE a.code="xip"),
 		(SELECT a.id FROM annotation as a WHERE a.description="Dependency"),
 		"Xerox Incremental Parser dependency layer"; 
diff --git a/src/main/resources/db/new-mysql/V2.2__insert_annotation_pair_values.sql b/src/main/resources/db/new-mysql/V2.2__insert_annotation_pair_values.sql
index 9d8963d..6f628d2 100644
--- a/src/main/resources/db/new-mysql/V2.2__insert_annotation_pair_values.sql
+++ b/src/main/resources/db/new-mysql/V2.2__insert_annotation_pair_values.sql
@@ -1,13 +1,27 @@
 INSERT INTO annotation_pair_value (pair_id, value_id) 
 	SELECT 
 		(SELECT ap.id FROM annotation_pair as ap WHERE 
-			ap.annotation1 = (SELECT a.id FROM annotation as a WHERE a.symbol="base") AND 
+			ap.annotation1 = (SELECT a.id FROM annotation as a WHERE a.code="opennlp") AND 
 			ap.annotation2 = (SELECT a.id FROM annotation as a WHERE a.description="Structure")), 
 		(SELECT a.id FROM annotation as a WHERE a.description="Sentence");
 		
 INSERT INTO annotation_pair_value (pair_id, value_id) 
 	SELECT 
 		(SELECT ap.id FROM annotation_pair as ap WHERE 
-			ap.annotation1 = (SELECT a.id FROM annotation as a WHERE a.symbol="dereko") AND 
+			ap.annotation1 = (SELECT a.id FROM annotation as a WHERE a.code="opennlp") AND 
+			ap.annotation2 = (SELECT a.id FROM annotation as a WHERE a.description="Structure")), 
+		(SELECT a.id FROM annotation as a WHERE a.description="Paragraph");
+
+INSERT INTO annotation_pair_value (pair_id, value_id) 
+	SELECT 
+		(SELECT ap.id FROM annotation_pair as ap WHERE 
+			ap.annotation1 = (SELECT a.id FROM annotation as a WHERE a.code="opennlp") AND 
+			ap.annotation2 = (SELECT a.id FROM annotation as a WHERE a.description="Part of speech")), 
+		(SELECT a.id FROM annotation as a WHERE a.description="Attributive Adjective");
+
+INSERT INTO annotation_pair_value (pair_id, value_id) 
+	SELECT 
+		(SELECT ap.id FROM annotation_pair as ap WHERE 
+			ap.annotation1 = (SELECT a.id FROM annotation as a WHERE a.code="dereko") AND 
 			ap.annotation2 = (SELECT a.id FROM annotation as a WHERE a.description="Structure")), 
 		(SELECT a.id FROM annotation as a WHERE a.description="Sentence");
diff --git a/src/main/resources/db/new-mysql/V2.3__insert_resources.sql b/src/main/resources/db/new-mysql/V2.3__insert_resources.sql
index 0afba04..55cf005 100644
--- a/src/main/resources/db/new-mysql/V2.3__insert_resources.sql
+++ b/src/main/resources/db/new-mysql/V2.3__insert_resources.sql
@@ -1 +1 @@
-INSERT INTO resource (id, de_title, en_title) VALUES("WPD15","Deutsche Wikipedia Artikel 2015","English Wikipedia Articles 2015");
+INSERT INTO resource (id, de_title, en_title) VALUES("WPD15","Deutsche Wikipedia Artikel 2015","German Wikipedia Articles 2015");
diff --git a/src/main/resources/db/new-mysql/V2.4__insert_resource_layers.sql b/src/main/resources/db/new-mysql/V2.4__insert_resource_layers.sql
index 94ea9a4..98871f7 100644
--- a/src/main/resources/db/new-mysql/V2.4__insert_resource_layers.sql
+++ b/src/main/resources/db/new-mysql/V2.4__insert_resource_layers.sql
@@ -2,5 +2,5 @@
 	SELECT 
 		(SELECT id FROM resource WHERE id = "WPD15"),
 		(SELECT ap.id FROM annotation_pair as ap WHERE 
-			ap.annotation1 = (SELECT a.id FROM annotation as a WHERE a.symbol="opennlp") AND 
+			ap.annotation1 = (SELECT a.id FROM annotation as a WHERE a.code="opennlp") AND 
 			ap.annotation2 = (SELECT a.id FROM annotation as a WHERE a.description="Part of speech"));
\ No newline at end of file