Implemented pipe response rewriting for match info API (close #814)

Change-Id: I09cb78e1557aa589a576edc37fecb997ef1229ed
diff --git a/src/main/java/de/ids_mannheim/korap/core/service/SearchService.java b/src/main/java/de/ids_mannheim/korap/core/service/SearchService.java
index eeffa13..a139a4d 100644
--- a/src/main/java/de/ids_mannheim/korap/core/service/SearchService.java
+++ b/src/main/java/de/ids_mannheim/korap/core/service/SearchService.java
@@ -517,10 +517,11 @@
 
     public String retrieveMatchInfo (String corpusId, String docId,
             String textId, String matchId, boolean info, Set<String> foundries,
-            String username, HttpHeaders headers, Set<String> layers,
-            boolean spans, boolean snippet, boolean tokens,
-            boolean sentenceExpansion, boolean highlights, boolean isDeprecated)
-            throws KustvaktException {
+            String username, HttpHeaders headers, Set<String> layers, 
+			boolean spans, boolean snippet, boolean tokens,
+			boolean sentenceExpansion, boolean highlights, boolean isDeprecated,
+			String responsePipes)
+			throws KustvaktException {
         String matchid = searchKrill.getMatchId(corpusId, docId, textId,
                 matchId);
 
@@ -563,6 +564,9 @@
         //            throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT,
         //                    e.getMessage());
         //        }
+        
+        results = runPipes(results, responsePipes);
+        
         if (DEBUG) {
             jlog.debug("MatchInfo results: " + results);
         }
@@ -582,7 +586,9 @@
             p = determineAvailabilityPattern(user);
         }
         String textSigle = searchKrill.getTextSigle(corpusId, docId, textId);
-        return searchKrill.getFields(textSigle, fieldList, p);
+        String results = searchKrill.getFields(textSigle, fieldList, p);
+        
+        return results;
     }
 
     public String getCollocationBase (String query) throws KustvaktException {
diff --git a/src/main/java/de/ids_mannheim/korap/core/web/controller/SearchController.java b/src/main/java/de/ids_mannheim/korap/core/web/controller/SearchController.java
index a600c81..6f40ba2 100644
--- a/src/main/java/de/ids_mannheim/korap/core/web/controller/SearchController.java
+++ b/src/main/java/de/ids_mannheim/korap/core/web/controller/SearchController.java
@@ -298,6 +298,7 @@
             @QueryParam("foundry") Set<String> foundries,
             @QueryParam("layer") Set<String> layers,
             @QueryParam("spans") Boolean spans,
+            @QueryParam("response-pipes") String responsePipes,
             @DefaultValue("true") @QueryParam("show-snippet") String snippetStr,
             @DefaultValue("false") @QueryParam("show-tokens") String tokensStr,
             @QueryParam("expand") String expansion,
@@ -336,7 +337,7 @@
             String results = searchService.retrieveMatchInfo(corpusId, docId,
                     textId, matchId, true, foundries,
                     tokenContext.getUsername(), headers, layers, spans, snippet,
-                    tokens, expandToSentence, highlights, true);
+                    tokens, expandToSentence, highlights, true, responsePipes);
             return Response.ok(results).build();
         }
         catch (KustvaktException e) {
@@ -357,6 +358,7 @@
             @QueryParam("foundry") Set<String> foundries,
             @QueryParam("layer") Set<String> layers,
             @QueryParam("spans") Boolean spans,
+            @QueryParam("response-pipes") String responsePipes,
             @DefaultValue("true") @QueryParam("show-snippet") String snippetStr,
             @DefaultValue("false") @QueryParam("show-tokens") String tokensStr,
             @QueryParam("expand") String expansion,
@@ -395,7 +397,7 @@
             String results = searchService.retrieveMatchInfo(corpusId, docId,
                     textId, matchId, true, foundries,
                     tokenContext.getUsername(), headers, layers, spans, snippet,
-                    tokens, expandToSentence, highlights, false);
+                    tokens, expandToSentence, highlights, false, responsePipes);
             return Response.ok(results).build();
         }
         catch (KustvaktException e) {
@@ -415,7 +417,8 @@
     public Response getMetadata (@PathParam("corpusId") String corpusId,
             @PathParam("docId") String docId,
             @PathParam("textId") String textId,
-            @QueryParam("fields") String fields, @Context SecurityContext ctx,
+            @QueryParam("fields") String fields, 
+            @Context SecurityContext ctx,
             @Context HttpHeaders headers) throws KustvaktException {
         TokenContext tokenContext = (TokenContext) ctx.getUserPrincipal();
         try {
diff --git a/src/test/java/de/ids_mannheim/korap/web/controller/SearchPipeTest.java b/src/test/java/de/ids_mannheim/korap/web/controller/SearchPipeTest.java
index 8c938b5..41fe378 100644
--- a/src/test/java/de/ids_mannheim/korap/web/controller/SearchPipeTest.java
+++ b/src/test/java/de/ids_mannheim/korap/web/controller/SearchPipeTest.java
@@ -41,9 +41,11 @@
 
     private int port = 6071;
 
-    private String pipeJson, pipeWithParamJson, pipeTimeout;
+    private String pipeJson, pipeWithParamJson, pipeTimeout, termMapperJson;
 
     private String glemmUri = "http://localhost:" + port + "/glemm";
+	private String termMapperUri = "http://localhost:" + port
+			+ "/term-mapper?foundry=corenlp";
 
     public SearchPipeTest () throws URISyntaxException, IOException {
         pipeJson = IOUtils.toString(
@@ -58,6 +60,11 @@
                 ClassLoader.getSystemResourceAsStream(
                         "pipe-output/with-param.jsonld"),
                 StandardCharsets.UTF_8);
+        
+        termMapperJson = IOUtils.toString(
+                ClassLoader.getSystemResourceAsStream(
+                        "pipe-output/term-mapper.jsonld"),
+                StandardCharsets.UTF_8);
     }
 
     @BeforeEach
@@ -99,6 +106,40 @@
         assertEquals("{test}", br.readLine());
     }
 
+	@Test
+	public void testRetrieveMatchInfoWithResponsePipe ()
+			throws KustvaktException {
+		
+		mockClient.reset()
+        .when(request().withMethod("POST")
+        		.withPath("/term-mapper")
+        		.withQueryStringParameter("foundry", "corenlp")
+                .withHeaders(
+                        new Header("Content-Type",
+                                "application/json; charset=utf-8"),
+                        new Header("Accept", "application/json")))
+        .respond(response()
+                .withHeader(new Header("Content-Type",
+                        "application/json; charset=utf-8"))
+                .withBody(termMapperJson).withStatusCode(200));
+
+		Response response = target().path(API_VERSION).path("corpus")
+				.path("GOE").path("AGA").path("01784").path("p36-37")
+				.queryParam("foundry", "tt")
+				.queryParam("response-pipes", termMapperUri)
+				.request().get();
+		assertEquals(Status.OK.getStatusCode(), response.getStatus());
+		String entity = response.readEntity(String.class);
+		JsonNode node = JsonUtils.readTree(entity);
+		
+		assertTrue(node.at("/snippet").asText().startsWith(
+				"<span class=\"context-left\"></span><span class=\"match\">"
+				+ "<span title=\"corenlp/p:ART\">der</span> <span title="
+				+ "\"corenlp/p:ADJA\">alte</span> <span title="
+				+ "\"corenlp/p:ADJA\">freie</span> <span title="
+				+ "\"corenlp/p:NN\">Weg</span>"));
+	}
+    
     @Test
     public void testSearchWithPipes ()
             throws IOException, KustvaktException, URISyntaxException {
diff --git a/src/test/resources/pipe-output/term-mapper.jsonld b/src/test/resources/pipe-output/term-mapper.jsonld
new file mode 100644
index 0000000..63d5b4a
--- /dev/null
+++ b/src/test/resources/pipe-output/term-mapper.jsonld
@@ -0,0 +1,81 @@
+{
+  "@context" : "http://korap.ids-mannheim.de/ns/KoralQuery/v0.3/context.jsonld",
+  "meta" : {
+    "version" : "Krill-0.64.1"
+  },
+  "hasSnippet" : true,
+  "hasTokens" : false,
+  "matchID" : "match-GOE/AGA/01784-p36-37",
+  "context" : {
+    "left" : [ "token", 0 ],
+    "right" : [ "token", 0 ]
+  },
+  "snippet" : "<span class=\"context-left\"></span><span class=\"match\"><span title=\"corenlp/p:ART\">der</span> <span title=\"corenlp/p:ADJA\">alte</span> <span title=\"corenlp/p:ADJA\">freie</span> <span title=\"corenlp/p:NN\">Weg</span> <span title=\"corenlp/p:APPR\">nach</span> <span title=\"corenlp/p:NE\">Mainz</span> <span title=\"corenlp/p:VAFIN\">war</span> <span title=\"corenlp/p:VVPP\">gesperrt</span>, <span title=\"corenlp/p:PPER\">ich</span> <span title=\"corenlp/p:VMFIN\">mußte</span> <span title=\"corenlp/p:APPR\">über</span> <span title=\"corenlp/p:ART\">die</span> <span title=\"corenlp/p:NN\">Schiffbrücke</span> <span title=\"corenlp/p:APPR\">bei</span> <span title=\"corenlp/p:NE\">Rüsselsheim</span>; <span title=\"corenlp/p:APPR\">in</span> <span title=\"corenlp/p:NE\">Ginsheim</span> <span title=\"corenlp/p:VVFIN\">ward</span> <mark><span title=\"corenlp/p:VVPP\">gefüttert</span></mark>; <span title=\"corenlp/p:ART\">der</span> <span title=\"corenlp/p:NN\">Ort</span> <span title=\"corenlp/p:VAFIN\">ist</span> <span title=\"corenlp/p:ADV\">sehr</span> <span title=\"corenlp/p:ADJA\">zerschossen</span>; <span title=\"corenlp/p:ADV\">dann</span> <span title=\"corenlp/p:APPR\">über</span> <span title=\"corenlp/p:ART\">die</span> <span title=\"corenlp/p:NN\">Schiffbrücke</span> <span title=\"corenlp/p:APPR\">auf</span> <span title=\"corenlp/p:ART\">die</span> <span title=\"corenlp/p:NN\">Nonnenaue</span>, <span title=\"corenlp/p:PWAV\">wo</span> <span title=\"corenlp/p:PIDAT\">viele</span> <span title=\"corenlp/p:NN\">Bäume</span> <span title=\"corenlp/p:VVINF\">niedergehauen</span> <span title=\"corenlp/p:VVFIN\">lagen</span>, <span title=\"corenlp/p:ADV\">sofort</span> <span title=\"corenlp/p:APPR\">auf</span> <span title=\"corenlp/p:ART\">dem</span> <span title=\"corenlp/p:ADJA\">zweiten</span> <span title=\"corenlp/p:NN\">Teil</span> <span title=\"corenlp/p:ART\">der</span> <span title=\"corenlp/p:NN\">Schiffbrücke</span> <span title=\"corenlp/p:APPR\">über</span> <span title=\"corenlp/p:ART\">den</span> <span title=\"corenlp/p:ADJA\">größern</span> <span title=\"corenlp/p:NN\">Arm</span> <span title=\"corenlp/p:ART\">des</span> <span title=\"corenlp/p:NE\">Rheins</span>.</span><span class=\"context-right\"></span>",
+  "fields" : [ {
+    "@type" : "koral:field",
+    "key" : "ID"
+  }, {
+    "@type" : "koral:field",
+    "key" : "textSigle",
+    "type" : "type:string",
+    "value" : "GOE/AGA/01784"
+  }, {
+    "@type" : "koral:field",
+    "key" : "corpusID"
+  }, {
+    "@type" : "koral:field",
+    "key" : "author",
+    "type" : "type:text",
+    "value" : "Goethe, Johann Wolfgang von"
+  }, {
+    "@type" : "koral:field",
+    "key" : "title",
+    "type" : "type:text",
+    "value" : "Belagerung von Mainz"
+  }, {
+    "@type" : "koral:field",
+    "key" : "subTitle"
+  }, {
+    "@type" : "koral:field",
+    "key" : "textClass"
+  }, {
+    "@type" : "koral:field",
+    "key" : "pubPlace",
+    "type" : "type:string",
+    "value" : "München"
+  }, {
+    "@type" : "koral:field",
+    "key" : "pubDate",
+    "type" : "type:date",
+    "value" : "1982"
+  }, {
+    "@type" : "koral:field",
+    "key" : "availability",
+    "type" : "type:string",
+    "value" : "CC-BY-SA"
+  }, {
+    "@type" : "koral:field",
+    "key" : "layerInfos",
+    "type" : "type:store",
+    "value" : "corenlp/c=spans corenlp/p=tokens corenlp/s=spans dereko/s=spans malt/d=rels marmot/m=tokens marmot/p=tokens opennlp/p=tokens opennlp/s=spans tt/l=tokens tt/p=tokens"
+  }, {
+    "@type" : "koral:field",
+    "key" : "docSigle",
+    "type" : "type:string",
+    "value" : "GOE/AGA"
+  }, {
+    "@type" : "koral:field",
+    "key" : "corpusSigle",
+    "type" : "type:string",
+    "value" : "GOE"
+  } ],
+  "textSigle" : "GOE/AGA/01784",
+  "author" : "Goethe, Johann Wolfgang von",
+  "title" : "Belagerung von Mainz",
+  "pubPlace" : "München",
+  "pubDate" : "1982",
+  "availability" : "CC-BY-SA",
+  "layerInfos" : "corenlp/c=spans corenlp/p=tokens corenlp/s=spans dereko/s=spans malt/d=rels marmot/m=tokens marmot/p=tokens opennlp/p=tokens opennlp/s=spans tt/l=tokens tt/p=tokens",
+  "docSigle" : "GOE/AGA",
+  "corpusSigle" : "GOE"
+}
\ No newline at end of file