Implemented FCS Group queries and added tests.
Change-Id: Id98662146a13fa3ee2b2dc019e273c501454027c
diff --git a/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/ExpressionParser.java b/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/ExpressionParser.java
index 5d767a9..1dc4a4b 100644
--- a/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/ExpressionParser.java
+++ b/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/ExpressionParser.java
@@ -64,7 +64,8 @@
//
// }
else if (queryNode instanceof ExpressionNot) {
- return parseExpression(queryNode.getChild(0), true, true);
+ boolean negation = isNot ? false : true;
+ return parseExpression(queryNode.getChild(0), negation, isToken);
}
else if (queryNode instanceof ExpressionOr) {
List<QueryNode> operands = queryNode.getChildren();
diff --git a/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/FCSSRUQueryParser.java b/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/FCSSRUQueryParser.java
index a98cc6e..ba440a3 100644
--- a/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/FCSSRUQueryParser.java
+++ b/src/main/java/de/ids_mannheim/korap/query/parse/fcsql/FCSSRUQueryParser.java
@@ -8,6 +8,7 @@
import de.ids_mannheim.korap.query.serialize.FCSQLQueryProcessor;
import de.ids_mannheim.korap.query.serialize.util.StatusCodes;
import eu.clarin.sru.server.fcs.parser.QueryDisjunction;
+import eu.clarin.sru.server.fcs.parser.QueryGroup;
import eu.clarin.sru.server.fcs.parser.QueryNode;
import eu.clarin.sru.server.fcs.parser.QuerySegment;
import eu.clarin.sru.server.fcs.parser.QuerySequence;
@@ -26,8 +27,9 @@
if (queryNode instanceof QuerySegment) {
return parseQuerySegment((QuerySegment) queryNode);
- // } else if (queryNode instanceof QueryGroup) {
- //
+ }
+ else if (queryNode instanceof QueryGroup) {
+ return parseQueryNode(queryNode.getChild(0));
}
else if (queryNode instanceof QuerySequence) {
return parseGroupQuery(queryNode.getChildren(),
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessor.java b/src/main/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessor.java
index 3862664..1e973d8 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessor.java
@@ -56,8 +56,10 @@
public void process(String query) {
if (isVersionValid()) {
FCSSRUQuery fcsSruQuery = parseQueryStringtoFCSQuery(query);
- QueryNode fcsQueryNode = fcsSruQuery.getParsedQuery();
- parseFCSQueryToKoralQuery(fcsQueryNode);
+ if (fcsSruQuery != null) {
+ QueryNode fcsQueryNode = fcsSruQuery.getParsedQuery();
+ parseFCSQueryToKoralQuery(fcsQueryNode);
+ }
}
}
@@ -83,13 +85,19 @@
try {
QueryNode parsedQuery = fcsParser.parse(query);
fcsQuery = new FCSSRUQuery(query, parsedQuery);
+ if (fcsQuery == null) {
+ addError(StatusCodes.UNKNOWN_QUERY_ERROR,
+ "FCS diagnostic 10: Unexpected error while parsing query.");
+ }
}
catch (QueryParserException e) {
- addError(StatusCodes.UNKNOWN_QUERY_ERROR, "FCS diagnostic 10: +"
- + e.getMessage());
+ addError(
+ StatusCodes.UNKNOWN_QUERY_ERROR,
+ "FCS diagnostic 10: Query cannot be parsed, "
+ + e.getMessage());
}
catch (Exception e) {
- addError(StatusCodes.UNKNOWN_QUERY_ERROR, "FCS diagnostic 10: +"
+ addError(StatusCodes.UNKNOWN_QUERY_ERROR, "FCS diagnostic 10: "
+ "Unexpected error while parsing query.");
}
return fcsQuery;
diff --git a/src/test/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessorTest.java b/src/test/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessorTest.java
index cea843f..b9026cb 100644
--- a/src/test/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessorTest.java
+++ b/src/test/java/de/ids_mannheim/korap/query/serialize/FCSQLQueryProcessorTest.java
@@ -25,12 +25,34 @@
assertEquals(jsonLD.replace(" ", ""), serializedQuery.replace("\"", ""));
}
+ private void validateNode(String query, String path, String jsonLd)
+ throws JsonProcessingException, IOException {
+ qs.setQuery(query, "fcsql", "2.0");
+ node = mapper.readTree(qs.toJSON());
+ String serializedQuery = mapper.writeValueAsString(node.at(path));
+ assertEquals(jsonLd.replace(" ", ""), serializedQuery.replace("\"", ""));
+ }
+
private List<Object> getError(FCSQLQueryProcessor processor) {
List<Object> errors = (List<Object>) processor.requestMap.get("errors");
return (List<Object>) errors.get(0);
}
@Test
+ public void testVersion() throws JsonProcessingException {
+ List<Object> error = getError(new FCSQLQueryProcessor("\"Sonne\"",
+ "1.0"));
+ assertEquals(309, error.get(0));
+ assertEquals("SRU diagnostic 5: Only supports SRU version 2.0.",
+ error.get(1));
+
+ error = getError(new FCSQLQueryProcessor("\"Sonne\"", null));
+ assertEquals(309, error.get(0));
+ assertEquals("SRU diagnostic 7: Version number is missing.",
+ error.get(1));
+ }
+
+ @Test
public void testTermQuery() throws JsonProcessingException {
String query = "\"Sonne\"";
String jsonLd = "{@type:koral:token, wrap:{@type:koral:term, key:Sonne, "
@@ -127,7 +149,7 @@
}
@Test
- public void testNot() throws JsonProcessingException {
+ public void testNot() throws IOException {
String query = "[cnx:pos != \"N\"]";
String jsonLd = "{@type:koral:token, wrap:{@type:koral:term, key:N, "
+ "foundry:cnx, layer:p, type:type:regex, match:match:ne}}";
@@ -137,15 +159,47 @@
+ "foundry:tt, layer:p, type:type:regex, match:match:eq}}";
query = "[!pos != \"NN\"]";
runAndValidate(query, jsonLd);
+ query = "[!!pos = \"NN\"]";
+ runAndValidate(query, jsonLd);
+ query = "[!!!pos != \"NN\"]";
+ runAndValidate(query, jsonLd);
- // Not possible
- // query = "![pos != \"NN\"]";
+ query = "[mate:lemma=\"sein\" & !mate:pos=\"PPOSS\"]";
+ jsonLd = "{@type: koral:token,"
+ + " wrap: { "
+ + "@type: koral:termGroup,"
+ + "relation: relation:and,"
+ + " operands:["
+ + "{@type: koral:term, key: sein, foundry: mate, layer: l, type:type:regex, match: match:eq},"
+ + "{@type: koral:term, key: PPOSS, foundry: mate, layer: p, type:type:regex, match: match:ne}]}}";
+ runAndValidate(query, jsonLd);
}
@Test
- public void testSequenceQuery() throws JsonProcessingException {
+ public void testWrongQuery() throws IOException {
+ String query = "!(mate:lemma=\"sein\" | mate:pos=\"PPOSS\")";
+ List<Object> error = getError(new FCSQLQueryProcessor(query, "2.0"));
+ assertEquals(399, error.get(0));
+ assertEquals(true,
+ error.get(1).toString().startsWith("FCS diagnostic 10"));
+
+ query = "![mate:lemma=\"sein\" | mate:pos=\"PPOSS\"]";
+ error = getError(new FCSQLQueryProcessor(query, "2.0"));
+ assertEquals(true,
+ error.get(1).toString().startsWith("FCS diagnostic 10"));
+
+ query = "(\"blaue\"&\"grüne\")";
+ error = getError(new FCSQLQueryProcessor(query, "2.0"));
+ assertEquals(true,
+ error.get(1).toString().startsWith("FCS diagnostic 10"));
+ }
+
+ @Test
+ public void testSequenceQuery() throws IOException {
String query = "\"blaue|grüne\" [pos = \"NN\"]";
- String jsonLd = "{@type:koral:group, operation:operation:sequence, operands:["
+ String jsonLd = "{@type:koral:group, "
+ + "operation:operation:sequence, "
+ + "operands:["
+ "{@type:koral:token, wrap:{@type:koral:term, key:blaue|grüne, foundry:opennlp, layer:orth, type:type:regex, match:match:eq}},"
+ "{@type:koral:token, wrap:{@type:koral:term, key:NN, foundry:tt, layer:p, type:type:regex, match:match:eq}}"
+ "]}";
@@ -153,6 +207,11 @@
query = "[text=\"blaue|grüne\"][pos = \"NN\"]";
runAndValidate(query, jsonLd);
+
+ query = "\"blaue\" \"grüne\" [pos = \"NN\"]";
+ jsonLd = "{@type:koral:token, wrap:{@type:koral:term, key:grüne, foundry:opennlp, layer:orth, type:type:regex, match:match:eq}}";
+ validateNode(query, "/query/operands/1", jsonLd);
+
}
@Test
@@ -167,10 +226,13 @@
runAndValidate(query, jsonLd);
query = "[mate:lemma=\"sein\" | mate:pos=\"PPOSS\"]";
- qs.setQuery(query, "fcsql", "2.0");
- node = mapper.readTree(qs.toJSON());
- assertEquals("relation:or", node.at("/query/wrap/relation").asText());
+ validateNode(query, "/query/wrap/relation", "relation:or");
+ query = "[cnx:lemma=\"sein\" | mate:lemma=\"sein\" | mate:pos=\"PPOSS\"]";
+ jsonLd = "{@type: koral:term, key: sein, foundry: cnx, layer: l, type:type:regex, match: match:eq}";
+ validateNode(query, "/query/wrap/operands/0", jsonLd);
+
+ // group with two tokens
query = "[pos=\"NN\"]|[text=\"Mann\"]";
jsonLd = "{@type:koral:group,"
+ "operation:operation:disjunction,"
@@ -178,27 +240,52 @@
+ "{@type:koral:token, wrap:{@type:koral:term,key:NN,foundry:tt,layer:p,type:type:regex,match:match:eq}},"
+ "{@type:koral:token, wrap:{@type:koral:term,key:Mann,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}}]}";
runAndValidate(query, jsonLd);
+
+ query = "[pos=\"NN\"]&[text=\"Mann\"]";
+ List<Object> error = getError(new FCSQLQueryProcessor(query, "2.0"));
+ assertEquals(399, error.get(0));
+ String msg = (String) error.get(1);
+ assertEquals(true, msg.startsWith("FCS diagnostic 10"));
}
@Test
- public void testGroupQuery() throws JsonProcessingException {
- // String query = "(\"blaue\"|\"grüne\")";
- // runAndValidate(query, jsonLd);
+ public void testGroupQuery() throws IOException {
+ String query = "(\"blaue\"|\"grüne\")";
+ String jsonLd = "{@type:koral:group,"
+ + "operation:operation:disjunction,"
+ + "operands:["
+ + "{@type:koral:token, wrap:{@type:koral:term,key:blaue,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}},"
+ + "{@type:koral:token, wrap:{@type:koral:term,key:grüne,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}}]}";;
+ runAndValidate(query, jsonLd);
- }
+ // group and disjunction
+ query = "([pos=\"NN\"]|[cnx:pos=\"N\"]|[text=\"Mann\"])";
+ jsonLd = "{@type:koral:token,wrap:{@type:koral:term,key:N,foundry:cnx,layer:p,type:type:regex,match:match:eq}}";
+ validateNode(query, "/query/operands/1", jsonLd);
- @Test
- public void testVersion() throws JsonProcessingException {
- List<Object> error = getError(new FCSQLQueryProcessor("\"Sonne\"",
- "1.0"));
- assertEquals(309, error.get(0));
- assertEquals("SRU diagnostic 5: Only supports SRU version 2.0.",
- error.get(1));
+ // sequence and disjunction
+ query = "([pos=\"NN\"]|[cnx:pos=\"N\"])[text=\"Mann\"]";
+ jsonLd = "{@type:koral:group,"
+ + "operation:operation:sequence,"
+ + "operands:["
+ + "{@type:koral:group,"
+ + "operation:operation:disjunction,"
+ + "operands:[{@type:koral:token,wrap:{@type:koral:term,key:NN,foundry:tt,layer:p,type:type:regex,match:match:eq}},"
+ + "{@type:koral:token,wrap:{@type:koral:term,key:N,foundry:cnx,layer:p,type:type:regex,match:match:eq}}"
+ + "]},"
+ + "{@type:koral:token,wrap:{@type:koral:term,key:Mann,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}}"
+ + "]}";
+ runAndValidate(query, jsonLd);
- error = getError(new FCSQLQueryProcessor("\"Sonne\"", null));
- assertEquals(309, error.get(0));
- assertEquals("SRU diagnostic 7: Version number is missing.",
- error.get(1));
+ // group and sequence
+ query = "([text=\"blaue\"][pos=\"NN\"])";
+ jsonLd = "{@type:koral:group,"
+ + "operation:operation:sequence,"
+ + "operands:["
+ + "{@type:koral:token,wrap:{@type:koral:term,key:blaue,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}},"
+ + "{@type:koral:token,wrap:{@type:koral:term,key:NN,foundry:tt,layer:p,type:type:regex,match:match:eq}}"
+ + "]}";
+ runAndValidate(query, jsonLd);
}
}