Added support for multiple cq parameters.

Change-Id: Ica7effe455cc9320ca0a5cc1c8f730167e78e1d8
diff --git a/lite/Changes b/lite/Changes
index d6991e0..0a06d87 100644
--- a/lite/Changes
+++ b/lite/Changes
@@ -1,6 +1,8 @@
 # version 0.62.3
 03/12/2019
    - Implemented pipe extension in the search API (margaretha)
+12/12/2019
+   - Added support for multiple cq parameters (margaretha, resolved #46)
 
 # version 0.62.2
 13/11/2019
diff --git a/lite/src/main/resources/lite-config.xml b/lite/src/main/resources/lite-config.xml
index e474b65..637977f 100644
--- a/lite/src/main/resources/lite-config.xml
+++ b/lite/src/main/resources/lite-config.xml
@@ -13,7 +13,8 @@
 
 
 	<context:component-scan
-		base-package="de.ids_mannheim.korap.rewrite, 
+		base-package="de.ids_mannheim.korap.rewrite,
+		de.ids_mannheim.korap.service, 
 	    de.ids_mannheim.korap.web.filter, 
 		de.ids_mannheim.korap.web.utils,
 		de.ids_mannheim.korap.authentication.http" />
@@ -159,10 +160,8 @@
 		class="de.ids_mannheim.korap.web.controller.StatisticController" />
 
 	<!-- Services -->
-	<bean id="annotationService" class="de.ids_mannheim.korap.service.AnnotationService"></bean>
 	<bean id="scopeService"
 		class="de.ids_mannheim.korap.oauth2.service.DummyOAuth2ScopeServiceImpl" />
-	<bean id="searchService" class="de.ids_mannheim.korap.service.SearchService"></bean>
 
 	<!-- DAO -->
 	<bean id="adminDao" class="de.ids_mannheim.korap.dao.DummyAdminDaoImpl" />
diff --git a/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteMultipleCorpusQueryTest.java b/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteMultipleCorpusQueryTest.java
new file mode 100644
index 0000000..ea7f964
--- /dev/null
+++ b/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteMultipleCorpusQueryTest.java
@@ -0,0 +1,85 @@
+package de.ids_mannheim.korap.web.service;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.sun.jersey.api.client.ClientHandlerException;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.UniformInterfaceException;
+
+import de.ids_mannheim.korap.config.LiteJerseyTest;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
+import de.ids_mannheim.korap.utils.JsonUtils;
+
+public class LiteMultipleCorpusQueryTest extends LiteJerseyTest {
+
+    @Test
+    public void testSearchGet () throws KustvaktException {
+        ClientResponse response = resource().path(API_VERSION).path("search")
+                .queryParam("q", "das").queryParam("ql", "poliqarp")
+                .queryParam("cq", "pubPlace=München")
+                .queryParam("cq", "textSigle=\"GOE/AGA/01784\"")
+                .get(ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        node = node.at("/collection");
+        assertEquals("koral:docGroup", node.at("/@type").asText());
+        assertEquals("operation:and", node.at("/operation").asText());
+        assertEquals(2, node.at("/operands").size());
+        assertEquals("koral:doc", node.at("/operands/0/@type").asText());
+        assertEquals("match:eq", node.at("/operands/0/match").asText());
+        assertEquals("pubPlace", node.at("/operands/0/key").asText());
+        assertEquals("München", node.at("/operands/0/value").asText());
+        assertEquals("textSigle", node.at("/operands/1/key").asText());
+        assertEquals("GOE/AGA/01784", node.at("/operands/1/value").asText());
+    }
+
+    @Test
+    public void testStatisticsWithMultipleCq ()
+            throws UniformInterfaceException, ClientHandlerException,
+            KustvaktException {
+        ClientResponse response = resource().path(API_VERSION).path("statistics")
+                .queryParam("cq", "textType=Abhandlung")
+                .queryParam("cq", "corpusSigle=GOE")
+                .method("GET", ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(2, node.at("/documents").asInt());
+        assertEquals(138180, node.at("/tokens").asInt());
+        assertEquals(5687, node.at("/sentences").asInt());
+        assertEquals(258, node.at("/paragraphs").asInt());
+
+        assertTrue(node.at("/warnings").isMissingNode());
+    }
+
+    @Test
+    public void testStatisticsWithMultipleCorpusQuery ()
+            throws UniformInterfaceException, ClientHandlerException,
+            KustvaktException {
+        ClientResponse response = resource().path(API_VERSION).path("statistics")
+                .queryParam("corpusQuery", "textType=Autobiographie")
+                .queryParam("corpusQuery", "corpusSigle=GOE")
+                .method("GET", ClientResponse.class);
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(9, node.at("/documents").asInt());
+        assertEquals(527662, node.at("/tokens").asInt());
+        assertEquals(19387, node.at("/sentences").asInt());
+        assertEquals(514, node.at("/paragraphs").asInt());
+
+        assertEquals(StatusCodes.DEPRECATED_PARAMETER,
+                node.at("/warnings/0/0").asInt());
+        assertEquals("Parameter corpusQuery is deprecated in favor of cq.",
+                node.at("/warnings/0/1").asText());
+    }
+}
diff --git a/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteStatisticControllerTest.java b/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteStatisticControllerTest.java
index 268fdb1..0d56d92 100644
--- a/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteStatisticControllerTest.java
+++ b/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteStatisticControllerTest.java
@@ -158,10 +158,10 @@
                      response.getStatus());
         String ent = response.getEntity(String.class);
         JsonNode node = JsonUtils.readTree(ent);
-        assertEquals(node.at("/errors/0/0").asInt(),
-                de.ids_mannheim.korap.util.StatusCodes.UNABLE_TO_PARSE_JSON);
-        assertEquals(node.at("/errors/0/1").asText(),
-                "Unable to parse JSON");
+        assertEquals(StatusCodes.DESERIALIZATION_FAILED,
+                node.at("/errors/0/0").asInt());
+        assertEquals("Failed deserializing json object: { \"collection\" : }",
+                node.at("/errors/0/1").asText());
     }
     
     @Test
diff --git a/lite/src/test/resources/test-config.xml b/lite/src/test/resources/test-config.xml
index ba6713b..cda35c7 100644
--- a/lite/src/test/resources/test-config.xml
+++ b/lite/src/test/resources/test-config.xml
@@ -14,6 +14,7 @@
 
 	<context:component-scan
 		base-package="de.ids_mannheim.korap.rewrite,
+		de.ids_mannheim.korap.service,
 		de.ids_mannheim.korap.web.filter, 
 		de.ids_mannheim.korap.web.utils,
 		de.ids_mannheim.korap.authentication.http" />
@@ -156,10 +157,8 @@
 		class="de.ids_mannheim.korap.web.controller.StatisticController" />
 
 	<!-- Services -->
-	<bean id="annotationService" class="de.ids_mannheim.korap.service.AnnotationService"></bean>
 	<bean id="scopeService"
 		class="de.ids_mannheim.korap.oauth2.service.DummyOAuth2ScopeServiceImpl" />
-	<bean id="searchService" class="de.ids_mannheim.korap.service.SearchService"></bean>
 
 	<!-- DAO -->
 	<bean id="adminDao" class="de.ids_mannheim.korap.dao.DummyAdminDaoImpl" />