Add CSV export
Change-Id: I7706c7ca7caa0a5fef1c282df9bde4ffd3416955
diff --git a/plugin/pom.xml b/plugin/pom.xml
index 546080a..fb0de66 100644
--- a/plugin/pom.xml
+++ b/plugin/pom.xml
@@ -4,7 +4,7 @@
<groupId>de.ids_mannheim.korap</groupId>
<artifactId>KalamarExportPlugin</artifactId>
<packaging>jar</packaging>
- <version>0.1</version>
+ <version>0.2.0</version>
<name>KalamarExportPlugin</name>
<url>http://maven.apache.org</url>
@@ -95,7 +95,7 @@
<version>2.7</version>
<scope>test</scope>
</dependency>
-
+
</dependencies>
<build>
diff --git a/plugin/src/main/java/de/ids_mannheim/korap/plkexport/CsvExporter.java b/plugin/src/main/java/de/ids_mannheim/korap/plkexport/CsvExporter.java
new file mode 100644
index 0000000..5e5b723
--- /dev/null
+++ b/plugin/src/main/java/de/ids_mannheim/korap/plkexport/CsvExporter.java
@@ -0,0 +1,119 @@
+package de.ids_mannheim.korap.plkexport;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.JsonNode;
+import java.io.IOException;
+import java.io.Writer;
+
+/**
+ * Streaming CSV exporter.
+ */
+public class CsvExporter extends MatchAggregator implements Exporter {
+
+ private ObjectMapper mapper = new ObjectMapper();
+
+ @Override
+ public String getMimeType () {
+ return "text/csv";
+ };
+
+
+ @Override
+ public String getSuffix () {
+ return "csv";
+ };
+
+
+ @Override
+ public void writeHeader (Writer w) throws IOException {
+ this.addRecord(
+ w,
+ new String[]{
+ "HasMoreLeft",
+ "leftContext",
+ "Match",
+ "rightContext",
+ "HasMoreRight",
+ "isCutted",
+ "textSigle",
+ "author",
+ "pubDate",
+ "title"
+ }
+ );
+ };
+
+ @Override
+ public void addMatch (JsonNode n, Writer w) throws IOException {
+ MatchExport m = mapper.treeToValue(n, MatchExport.class);
+ Snippet s = m.getSnippetO();
+
+ String left = s.getLeft();
+ String mark = s.getMark();
+ String right = s.getRight();
+
+ if (left != null)
+ left = left.trim();
+
+ if (mark != null)
+ mark = mark.trim();
+
+ if (right != null)
+ right = right.trim();
+
+ this.addRecord(
+ w,
+ new String[]{
+ s.hasMoreLeft() ? "..." : "",
+ left,
+ mark,
+ right,
+ s.hasMoreRight() ? "..." : "",
+ s.isCutted() ? "!" : "",
+ m.getTextSigle(),
+ m.getAuthor(),
+ m.getPubDate(),
+ m.getTitle()
+ });
+ };
+
+
+ // Add a CSV row to the CSV stream
+ private void addRecord (Writer w, String[] ss) throws IOException {
+ this.addCell(w , ss[0]);
+ for (int i = 1; i < 10; i++) {
+ w.append(',');
+ this.addCell(w , ss[i]);
+ };
+ w.append("\n");
+ };
+
+
+ // Add a CSV cell to the CSV row
+ private void addCell (Writer w, String s) throws IOException {
+
+ // If meta characters exist, make a quote
+ if (s.contains(",") ||
+ s.contains("\"") ||
+ s.contains("\n") ||
+ s.contains(" ") ||
+ s.contains("\t") ||
+ s.contains(";")) {
+ w.append('"');
+ for (int i = 0; i < s.length(); i++) {
+ final char c = s.charAt(i);
+ if (c == '"') {
+ w.append('"').append('"');
+ }
+ else {
+ w.append(c);
+ };
+ };
+ w.append('"');
+ }
+
+ else {
+ w.append(s);
+ };
+ };
+};
diff --git a/plugin/src/main/java/de/ids_mannheim/korap/plkexport/ExWSConf.java b/plugin/src/main/java/de/ids_mannheim/korap/plkexport/ExWSConf.java
index 72e9468..b781394 100644
--- a/plugin/src/main/java/de/ids_mannheim/korap/plkexport/ExWSConf.java
+++ b/plugin/src/main/java/de/ids_mannheim/korap/plkexport/ExWSConf.java
@@ -16,8 +16,8 @@
// Version of Export Plugin
public static final int VERSION_MAJOR = 0;
- public static final int VERSION_MINOR = 1;
- public static final int VERSION_PATCHLEVEL= 1;
+ public static final int VERSION_MINOR = 2;
+ public static final int VERSION_PATCHLEVEL= 0;
private static Properties prop;
diff --git a/plugin/src/main/java/de/ids_mannheim/korap/plkexport/IdsExportService.java b/plugin/src/main/java/de/ids_mannheim/korap/plkexport/IdsExportService.java
index eab7f3d..d24f730 100644
--- a/plugin/src/main/java/de/ids_mannheim/korap/plkexport/IdsExportService.java
+++ b/plugin/src/main/java/de/ids_mannheim/korap/plkexport/IdsExportService.java
@@ -5,8 +5,8 @@
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
-import java.lang.Thread;
import java.io.InputStream;
+import java.lang.Thread;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.ArrayList;
@@ -14,9 +14,9 @@
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Properties;
+import java.util.Base64;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import java.util.Base64;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.WebApplicationException;
@@ -50,7 +50,7 @@
* - Delete the temp file of the export at the end
* - Do not expect all meta data per match.
* - Add progress mechanism.
- * - Add CSV export format.
+ * - Upgrade default pageSize to 50.
* - Add loading marker.
* - Add hitc to form.
* - Add infos to JsonExporter.
@@ -61,7 +61,7 @@
@Path("/")
public class IdsExportService {
- Properties properties = ExWSConf.properties(null);
+ Properties prop = ExWSConf.properties(null);
private final ClassLoader cl = Thread.currentThread().getContextClassLoader();
@@ -85,8 +85,7 @@
private final static Base64.Decoder b64Dec = Base64.getDecoder();
@Context
- private HttpServletRequest req;
-
+ private HttpServletRequest req;
/**
* WebService calls Kustvakt Search Webservices and returns
@@ -116,8 +115,8 @@
@FormParam("cq") String cq,
@FormParam("ql") String ql,
@FormParam("cutoff") String cutoffStr,
- // @FormParam("islimit") String il,
@FormParam("hitc") int hitc
+ // @FormParam("islimit") String il
) throws IOException {
// These parameters are required
@@ -151,12 +150,12 @@
Client client = ClientBuilder.newClient();
// Load configuration values
- String scheme = properties.getProperty("api.scheme", "https");
- String port = properties.getProperty("api.port", "8089");
- String host = properties.getProperty("api.host", "localhost");
- String path = properties.getProperty("api.path", "");
- int pageSize = Integer.parseInt(properties.getProperty("conf.page_size", "5"));
- int maxResults = Integer.parseInt(properties.getProperty("conf.max_exp_limit", "10000"));
+ String scheme = prop.getProperty("api.scheme", "https");
+ String port = prop.getProperty("api.port", "8089");
+ String host = prop.getProperty("api.host", "localhost");
+ String path = prop.getProperty("api.path", "");
+ int pageSize = Integer.parseInt(prop.getProperty("conf.page_size", "5"));
+ int maxResults = Integer.parseInt(prop.getProperty("conf.max_exp_limit", "10000"));
// Adjust the number of requested hits
if (hitc > 0 && hitc < maxResults) {
@@ -180,7 +179,8 @@
if (path != "") {
uri = uri.path(path);
};
-
+
+ // Set the page count to the given pagesize
uri = uri.queryParam("count", pageSize);
// Get client IP, in case service is behind a proxy
@@ -198,14 +198,13 @@
String resp;
WebTarget resource;
Invocation.Builder reqBuilder;
-
+
try {
resource = client.target(uri.build());
reqBuilder = resource.request(MediaType.APPLICATION_JSON);
resp = authBuilder(reqBuilder, xff, auth).get(String.class);
} catch (Exception e) {
- System.err.println("Unable to reach: " + uri.build());
throw new WebApplicationException(
responseForm(Status.BAD_GATEWAY, "Unable to reach Backend")
);
@@ -216,6 +215,8 @@
// Choose the correct exporter
if (format.equals("json"))
exp = new JsonExporter();
+ else if (format.equals("csv"))
+ exp = new CsvExporter();
else
exp = new RtfExporter();
@@ -244,15 +245,13 @@
};
- /*
- * Calculate how many results to fetch
- */
+ // Calculate how many results to fetch
int fetchCount = exp.getTotalResults();
if (exp.hasTimeExceeded() || fetchCount > maxResults) {
fetchCount = maxResults;
};
- // The first page was already enough
+ // The first page was already enough - ignore paging
if (fetchCount <= pageSize) {
cutoff = true;
};
@@ -339,7 +338,11 @@
// This is a temporary solution using session riding - only
// valid for the time being
Cookie[] cookies = r.getCookies();
- String cookiePath = properties.getProperty("cookie.path", "");
+
+ if (cookies == null)
+ return "";
+
+ String cookiePath = prop.getProperty("cookie.path", "");
// Iterate through all cookies for a Kalamar session
for (int i = 0; i < cookies.length; i++) {
@@ -390,25 +393,25 @@
StringWriter out = new StringWriter();
HashMap<String, Object> templateData = new HashMap<String, Object>();
- String scheme = properties.getProperty("asset.scheme", "https");
- String port = properties.getProperty("asset.port", "");
- String host = properties.getProperty("asset.host", "korap.ids-mannheim.de");
- String path = properties.getProperty("asset.path", "");
+ // Build uri for assets
+ String scheme = prop.getProperty("asset.scheme", "https");
+ String port = prop.getProperty("asset.port", "");
+ String host = prop.getProperty("asset.host", "korap.ids-mannheim.de");
+ String path = prop.getProperty("asset.path", "");
UriBuilder uri = UriBuilder.fromPath("")
.host(host)
.scheme(scheme);
- if (path != "") {
+ if (path != "")
uri = uri.path(path);
- };
- if (port != "") {
+ if (port != "")
uri = uri.port(Integer.parseInt(port));
- };
templateData.put("assetPath", uri.build());
+ // There is an error code to pass
if (code != null) {
templateData.put("code", code.getStatusCode());
templateData.put("msg", msg);
@@ -419,6 +422,8 @@
Template template = cfg.getTemplate("export.ftl");
template.process(templateData, out);
}
+
+ // Unable to find template
catch (Exception e) {
return Response
.ok(new String("Template not found"))
@@ -428,15 +433,16 @@
ResponseBuilder resp = Response.ok(out.toString(), "text/html");
- if (code != null) {
+ if (code != null)
resp = resp.status(code);
- };
return resp.build();
};
/*
+ * Get the origin user IP.
+ *
* This function is a simplification of
* Mojolicious::Plugin::ClientIP
*/
@@ -447,10 +453,9 @@
String[] ips = xff.split("\\s*,\\s*");
- for (int i = ips.length - 1; i >= 0; i--){
- if (ips[i].matches(ipre)) {
+ for (int i = ips.length - 1; i >= 0; i--) {
+ if (ips[i].matches(ipre))
return ips[i];
- };
};
return "";
diff --git a/plugin/src/main/java/de/ids_mannheim/korap/plkexport/JsonExporter.java b/plugin/src/main/java/de/ids_mannheim/korap/plkexport/JsonExporter.java
index bfe126e..de4ac51 100644
--- a/plugin/src/main/java/de/ids_mannheim/korap/plkexport/JsonExporter.java
+++ b/plugin/src/main/java/de/ids_mannheim/korap/plkexport/JsonExporter.java
@@ -7,10 +7,8 @@
/**
- * This is a streaming exporter class for Json, so it's based on
- * a string buffer.
+ * Streaming JSON exporter.
*/
-
public class JsonExporter extends MatchAggregator implements Exporter {
private boolean firstMatch;
diff --git a/plugin/src/main/java/de/ids_mannheim/korap/plkexport/RtfExporter.java b/plugin/src/main/java/de/ids_mannheim/korap/plkexport/RtfExporter.java
index 7c0f7bc..66f22b0 100644
--- a/plugin/src/main/java/de/ids_mannheim/korap/plkexport/RtfExporter.java
+++ b/plugin/src/main/java/de/ids_mannheim/korap/plkexport/RtfExporter.java
@@ -16,8 +16,7 @@
import java.io.Writer;
/**
- * This is a streaming exporter class for Rtf, so it's based on
- * a string buffer.
+ * Streaming RTF exporter.
*/
/*
* TODO:
diff --git a/plugin/src/main/java/de/ids_mannheim/korap/plkexport/Util.java b/plugin/src/main/java/de/ids_mannheim/korap/plkexport/Util.java
index c60cf27..0ca1a94 100644
--- a/plugin/src/main/java/de/ids_mannheim/korap/plkexport/Util.java
+++ b/plugin/src/main/java/de/ids_mannheim/korap/plkexport/Util.java
@@ -31,5 +31,4 @@
return sb.toString();
}
-
}
diff --git a/plugin/src/main/resources/assets/templates/export.ftl b/plugin/src/main/resources/assets/templates/export.ftl
index 5633e22..d6cb11a 100644
--- a/plugin/src/main/resources/assets/templates/export.ftl
+++ b/plugin/src/main/resources/assets/templates/export.ftl
@@ -21,7 +21,7 @@
<legend>Dateiformat</legend>
<div style="margin-top: 1em">
- <input type="radio" checked="checked" id="formathtml" name="format" value="rtf" style="vertical-align: top">
+ <input type="radio" checked="checked" id="formatrtf" name="format" value="rtf" style="vertical-align: top">
<label for="formatrtf">
RTF
<br /><span style="font-size:8pt">Rich Text Format (Word etc.)</span>
@@ -29,10 +29,18 @@
</div>
<div style="margin-top: 1em">
+ <input type="radio" id="formatcsv" name="format" value="csv" style="vertical-align: top">
+ <label for="formatcsv">
+ CSV
+ <br /><span style="font-size:8pt">Comma-separated Values (Excel etc.)</span>
+ </label>
+ </div>
+
+ <div style="margin-top: 1em">
<input type="radio" id="formatjson" name="format" value="json" style="vertical-align: top">
<label for="formatjson">
JSON
- <br /><span style="font-size:8pt">Programmierung (JavaScript etc.)</span>
+ <br /><span style="font-size:8pt">JavaScript Object Notation (JavaScript etc.)</span>
</label>
</div>
</fieldset>
diff --git a/plugin/src/test/java/de/ids_mannheim/korap/plkexport/CsvExportTest.java b/plugin/src/test/java/de/ids_mannheim/korap/plkexport/CsvExportTest.java
new file mode 100644
index 0000000..076451d
--- /dev/null
+++ b/plugin/src/test/java/de/ids_mannheim/korap/plkexport/CsvExportTest.java
@@ -0,0 +1,67 @@
+package de.ids_mannheim.korap.plkexport;
+
+import java.io.IOException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
+import org.junit.Test;
+
+import javax.ws.rs.core.Response;
+
+public class CsvExportTest {
+
+ @Test
+ public void testInit () throws IOException {
+ CsvExporter csv = new CsvExporter();
+ csv.init("{\"query\":\"cool\"}");
+
+ Response resp = csv.serve().build();
+ String x = (String) resp.getEntity();
+ resp.close();
+ assertEquals(x, "HasMoreLeft,leftContext,Match,rightContext,HasMoreRight,"+
+ "isCutted,textSigle,author,pubDate,title\n");
+ };
+
+ @Test
+ public void testInitFull () throws IOException {
+ CsvExporter csv = new CsvExporter();
+ csv.init("{\"meta\":\"ja\",\"collection\":\"hm\",\"query\":\"cool\"," +
+ "\"matches\":["+
+ "{\"author\":\"Goethe\","+
+ "\"title\":\"Title1\","+
+ "\"pubDate\":\"20051103\","+
+ "\"textSigle\":\"RTF/G59/34284\","+
+ "\"snippet\":\"Simple <mark>match1</mark> Snippet\"}"+
+ ","+
+ "{\"author\":\"Schiller\","+
+ "\"title\":\"Title2, the\","+
+ "\"pubDate\":\"20051104\","+
+ "\"textSigle\":\"RTF/G59/34285\","+
+ "\"snippet\":\"<span class=\\\"context-left\\\"><span class=\\\"more\\\"></span>"+
+ "Simpler, \\\"faster\\\" </span><span class=\\\"match\\\"><mark>"match2"</mark></span>"+
+ "<span class=\\\"context-right\\\"> Snippet"+
+ "<span class=\\\"more\\\"></span></span>\"}"+
+ "]}");
+
+ Response resp = csv.serve().build();
+ String x = (String) resp.getEntity();
+ resp.close();
+ String[] lines = x.split("\n");
+ assertEquals(lines[0],"HasMoreLeft,leftContext,Match,rightContext,HasMoreRight,isCutted,textSigle,author,pubDate,title");
+ assertEquals(lines[1],",Simple,match1,Snippet,,,RTF/G59/34284,Goethe,20051103,Title1");
+ assertEquals(lines[2],"...,\"Simpler, \"\"faster\"\"\",\"\"\"match2\"\"\",Snippet,...,,RTF/G59/34285,Schiller,20051104,\"Title2, the\"");
+ assertEquals(lines.length,3);
+ };
+
+ @Test
+ public void testAttributes () throws IOException {
+ CsvExporter csv = new CsvExporter();
+ csv.setFileName("Beispiel");
+ assertEquals(csv.getFileName(),"Beispiel");
+ assertEquals(csv.getMimeType(),"text/csv");
+ assertEquals(csv.getSuffix(),"csv");
+ };
+};
diff --git a/plugin/src/test/java/de/ids_mannheim/korap/plkexport/IdsExportServiceTest.java b/plugin/src/test/java/de/ids_mannheim/korap/plkexport/IdsExportServiceTest.java
index 995304b..0827f05 100644
--- a/plugin/src/test/java/de/ids_mannheim/korap/plkexport/IdsExportServiceTest.java
+++ b/plugin/src/test/java/de/ids_mannheim/korap/plkexport/IdsExportServiceTest.java
@@ -151,7 +151,7 @@
}
@Test
- public void testFormHTML () {
+ public void testFormHtml () {
Response responsehtml = target("/export").request()
.get();
assertEquals("HTTP Code",
@@ -164,7 +164,7 @@
}
@Test
- public void testFormHTML2 () {
+ public void testFormHtmlAssets () {
Properties properties = ExWSConf.properties(null);
String hostTemp = properties.getProperty("asset.host");
String pathTemp = properties.getProperty("asset.path");
@@ -185,6 +185,23 @@
properties.setProperty("asset.path", pathTemp != null ? pathTemp : "");
}
+ @Test
+ public void testFormHtmlExporters () {
+ Response responsehtml = target("/export").request()
+ .get();
+ assertEquals("HTTP Code",
+ Status.OK.getStatusCode(), responsehtml.getStatus());
+ String str = responsehtml.readEntity(String.class);
+ assertTrue("HTTP Body", str.contains("<title>Export</title>"));
+ assertTrue("RTF", str.contains("id=\"formatrtf\""));
+ assertTrue("RTF-Label", str.contains("for=\"formatrtf\""));
+ assertTrue("JSON", str.contains("id=\"formatjson\""));
+ assertTrue("JSON-Label", str.contains("for=\"formatjson\""));
+ assertTrue("CSV", str.contains("id=\"formatcsv\""));
+ assertTrue("CSV-Label", str.contains("for=\"formatcsv\""));
+ assertFalse("DOC", str.contains("id=\"formatdoc\""));
+ }
+
@Test
public void testJS () {
@@ -652,6 +669,73 @@
@Test
+ public void testExportWsCsvPaging () throws IOException {
+
+ mockClient.reset().when(
+ request()
+ .withMethod("GET")
+ .withPath("/api/v1.0/search")
+ .withQueryStringParameter("q", "Plagegeist")
+ .withQueryStringParameter("count", "5")
+ .withQueryStringParameter("offset", "5")
+ )
+ .respond(
+ response()
+ .withHeader("Content-Type: application/json; charset=utf-8")
+ .withBody(getFixture("response_plagegeist_2.json"))
+ .withStatusCode(200)
+ );
+
+ mockClient.when(
+ request()
+ .withMethod("GET")
+ .withPath("/api/v1.0/search")
+ .withQueryStringParameter("q", "Plagegeist")
+ )
+ .respond(
+ response()
+ .withHeader("Content-Type: application/json; charset=utf-8")
+ .withBody(getFixture("response_plagegeist_1.json"))
+ .withStatusCode(200)
+ );
+
+ MultivaluedHashMap<String, String> frmap = new MultivaluedHashMap<String, String>();
+ frmap.add("format", "csv");
+ frmap.add("q", "Plagegeist");
+ frmap.add("ql", "poliqarp");
+ frmap.add("hitc", "30");
+ String filenamer = "dateiPagingCsv";
+ frmap.putSingle("fname", filenamer);
+
+ Response responsecsv = target("/export").request()
+ .post(Entity.form(frmap));
+ assertEquals("Request CSV: Http Response should be 200: ",
+ Status.OK.getStatusCode(), responsecsv.getStatus());
+
+ String str = responsecsv.readEntity(String.class);
+ String[] lines = str.split("\n");
+
+ assertEquals(lines.length,10);
+ assertEquals(lines[0],"HasMoreLeft,leftContext,Match,rightContext,HasMoreRight,isCutted,textSigle,author,pubDate,title");
+ assertEquals(lines[1],"...,\"1 Tag gesperrt. 24h Urlaub.^^ LG;-- 17:40, 11. Jan. 2011 (CET) Danke ich habe die nahezu zeitgleichen VMs von Dir und Ironhoof gesehen. Ob es ein Grund zum Jubeln ist, sei dahin gestellt. Immerhin habe ich für 24 Stunden einen \"\"\",Plagegeist,\"\"\" weniger. Sag mal, zum Kölner Stammtisch isses doch nicht so weit ... wie wär's ? Besten 17:49, 11. Jan. 2011 (CET) Er wurde gesperrt. Nach dem Theater hier zurecht. ABER: auch deine Beiträge hier, die er versuchte zu löschen, sorgen nicht für\",...,,WUD17/G59/34284,\"Umherirrender, u.a.\",2017-07-01,\"Benutzer Diskussion:Gruß Tom/Archiv/2011\"");
+
+ frmap.putSingle("hitc", "7");
+
+ responsecsv = target("/export").request()
+ .post(Entity.form(frmap));
+ assertEquals("Request CSV: Http Response should be 200: ",
+ Status.OK.getStatusCode(), responsecsv.getStatus());
+
+ str = responsecsv.readEntity(String.class);
+ lines = str.split("\n");
+
+ assertEquals(lines.length,8);
+ assertEquals(lines[0],"HasMoreLeft,leftContext,Match,rightContext,HasMoreRight,isCutted,textSigle,author,pubDate,title");
+ assertEquals(lines[7],"...,\"vielleicht eine neue Schloss-Einstein-Antragswelle unterbinden.-- 07:36, 23. Jun. 2008 (CEST) Mentor Lieber Kriddl, als ich mir die Liste der Mentoren anschaute, fiel mein Augenmerk auf Dich als Jurist. Könntest Du mir jungen Wikipedianer (aber nicht jung an Jahren) helfen, einen\",Plagegeist,\", der mich seit meiner ersten Teilnahme als IP mobbt, helfen? Wenn ja, so schau Dir doch als Einstieg bitte meinen Wiederherstellungs-Antrag zum Artikel Meton-Periode an: WP:LP, 26.Juni 08. Dort ist nicht nur der Sachverhalt, in den man sich nicht\",...,,WUD17/K35/39955,\"TaxonBot, u.a.\",2017-07-01,\"Benutzer Diskussion:Kriddl/Archiv\"");
+ };
+
+
+ @Test
public void testExportWsJsonWithMaxHitcFirstPage () throws IOException {
// This should ensure here to check that page 2 is not loaded
diff --git a/plugin/src/test/java/de/ids_mannheim/korap/plkexport/JsonExportTest.java b/plugin/src/test/java/de/ids_mannheim/korap/plkexport/JsonExportTest.java
index 73bd736..4f5e284 100644
--- a/plugin/src/test/java/de/ids_mannheim/korap/plkexport/JsonExportTest.java
+++ b/plugin/src/test/java/de/ids_mannheim/korap/plkexport/JsonExportTest.java
@@ -14,8 +14,6 @@
import javax.ws.rs.core.Response;
-import de.ids_mannheim.korap.plkexport.JsonExporter;
-
public class JsonExportTest {
@Test
diff --git a/plugin/src/test/java/de/ids_mannheim/korap/plkexport/RtfExportTest.java b/plugin/src/test/java/de/ids_mannheim/korap/plkexport/RtfExportTest.java
index 359b8ca..33eb787 100644
--- a/plugin/src/test/java/de/ids_mannheim/korap/plkexport/RtfExportTest.java
+++ b/plugin/src/test/java/de/ids_mannheim/korap/plkexport/RtfExportTest.java
@@ -11,8 +11,6 @@
import javax.ws.rs.core.Response;
-import de.ids_mannheim.korap.plkexport.JsonExporter;
-
public class RtfExportTest {
@Test