Merge "Improve test suite"
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 df1590f..96e12b1 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
@@ -44,14 +44,13 @@
return parseQuerySegment((QuerySegment) queryNode);
}
else if (queryNode instanceof QueryGroup) {
- return parseQueryNode(queryNode.getChild(0));
+ return parseQueryGroup((QueryGroup) queryNode);
}
else if (queryNode instanceof QuerySequence) {
return parseSequenceQuery(queryNode.getChildren());
}
else if (queryNode instanceof QueryDisjunction) {
- return parseGroupQuery(queryNode.getChildren(),
- KoralOperation.DISJUNCTION);
+ return parseQueryDisjunction(queryNode.getChildren());
}
else if (queryNode instanceof QueryWithWithin) {
return parseWithinQuery((QueryWithWithin) queryNode);
@@ -69,23 +68,28 @@
private KoralObject parseQuerySegment(QuerySegment segment)
throws KoralException {
- int minOccurs = segment.getMinOccurs();
- int maxOccurs = segment.getMaxOccurs();
-
+ KoralObject object = expressionParser.parseExpression(segment.getExpression());
+ return handleQuantifier(object, segment.getMinOccurs(), segment.getMaxOccurs());
+ }
+
+ private KoralObject parseQueryGroup(QueryGroup group) throws KoralException {
+ KoralObject object = parseQueryNode(group.getFirstChild());
+ return handleQuantifier(object, group.getMinOccurs(), group.getMaxOccurs());
+ }
+
+ private KoralObject handleQuantifier(KoralObject object, int minOccurs, int maxOccurs){
if ((minOccurs == 1) && (maxOccurs == 1)) {
- return expressionParser.parseExpression(segment.getExpression());
+ return object;
}
- else {
- KoralBoundary boundary = new KoralBoundary(minOccurs, maxOccurs);
- List<KoralObject> operand = new ArrayList<KoralObject>(1);
- operand.add(expressionParser.parseExpression(segment
- .getExpression()));
+
+ KoralBoundary boundary = new KoralBoundary(minOccurs, maxOccurs);
+ List<KoralObject> operand = new ArrayList<KoralObject>(1);
+ operand.add(object);
- KoralGroup koralGroup = new KoralGroup(KoralOperation.REPETITION);
- koralGroup.setBoundary(boundary);
- koralGroup.setOperands(operand);
- return koralGroup;
- }
+ KoralGroup koralGroup = new KoralGroup(KoralOperation.REPETITION);
+ koralGroup.setBoundary(boundary);
+ koralGroup.setOperands(operand);
+ return koralGroup;
}
private KoralObject parseWithinQuery(QueryWithWithin queryNode)
@@ -125,9 +129,8 @@
return new KoralSpan(new KoralTerm(contextSpan));
}
- private KoralGroup parseGroupQuery(List<QueryNode> children,
- KoralOperation operation) throws KoralException {
- KoralGroup koralGroup = new KoralGroup(operation);
+ private KoralGroup parseQueryDisjunction(List<QueryNode> children) throws KoralException {
+ KoralGroup koralGroup = new KoralGroup(KoralOperation.DISJUNCTION);
List<KoralObject> operands = new ArrayList<KoralObject>();
for (QueryNode child : children) {
operands.add(parseQueryNode(child));
diff --git a/src/test/java/de/ids_mannheim/korap/query/serialize/FCSQLComplexTest.java b/src/test/java/de/ids_mannheim/korap/query/serialize/FCSQLComplexTest.java
index 47a174e..093d715 100644
--- a/src/test/java/de/ids_mannheim/korap/query/serialize/FCSQLComplexTest.java
+++ b/src/test/java/de/ids_mannheim/korap/query/serialize/FCSQLComplexTest.java
@@ -44,7 +44,7 @@
FCSQLQueryProcessorTest
.validateNode(query, "/query/operands/1", jsonLd);
- // group and sequence
+ // a group contains a sequence
query = "([text=\"blaue\"][pos=\"NN\"])";
jsonLd = "{@type:koral:group,"
+ "operation:operation:sequence,"
@@ -122,11 +122,12 @@
+ "]}";
FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+ // sequence of groups
}
// | simple-query quantifier /* quatification */
@Test
- public void testQueryWithQuantifier() throws IOException {
+ public void testSimpleQueryWithQuantifier() throws IOException {
// repetition
query = "\"die\"{2}";
jsonLd = "{@type:koral:group,"
@@ -163,6 +164,30 @@
query = "\"die\"{0}";
jsonLd = "{@type:koral:boundary,min:0, max:0}";
FCSQLQueryProcessorTest.validateNode(query, "/query/boundary", jsonLd);
+
+ // segment query with quantifier
+ query = "[cnx:pos=\"A\"]*";
+ jsonLd = "{@type:koral:group,"
+ + "operation:operation:repetition,"
+ + "operands:[{@type:koral:token,wrap:{@type:koral:term,key:A,foundry:cnx,layer:p,type:type:regex,match:match:eq}}],"
+ + "boundary:{@type:koral:boundary,min:0}}";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+ }
+
+ @Test
+ public void testGroupQueryWithQuantifier() throws JsonProcessingException {
+ // group with quantifier
+ query = "(\"blaue\"|\"grüne\")*";
+ jsonLd = "{@type:koral:group,"
+ + "operation:operation:repetition,"
+ + "operands:["
+ + "{@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}}"
+ + "]}]," + "boundary:{@type:koral:boundary,min:0}}";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
}
// wildcards
@@ -185,7 +210,7 @@
query = "\"Hund\"[]{2}";
jsonLd = "{@type:koral:group," + "operation:operation:repetition,"
- + "operands:[" + "{@type:koral:token}],"
+ + "operands:[{@type:koral:token}],"
+ "boundary:{@type:koral:boundary,min:2,max:2}}";
FCSQLQueryProcessorTest
.validateNode(query, "/query/operands/1", jsonLd);
@@ -206,24 +231,55 @@
}
@Test
- public void testQueryWithDistance() throws IOException {
+ public void testDistanceQuery() throws IOException {
// distance query
- query = "\"Katze\" []{3} \"Hund\"";
+ query = "\"Katze\" [] \"Hund\"";
jsonLd = "{@type:koral:group,operation:operation:sequence,inOrder:true,"
+ "distances:["
- + "{@type:koral:distance,key:w,boundary:{@type:koral:boundary,min:3,max:3}}"
+ + "{@type:koral:distance,key:w,boundary:{@type:koral:boundary,min:1,max:1}}"
+ "],"
+ "operands:["
+ "{@type:koral:token,wrap:{@type:koral:term,key:Katze,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}},"
+ "{@type:koral:token,wrap:{@type:koral:term,key:Hund,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}}]}";
FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+ }
+ @Test
+ public void testDistanceQueryWithQuantifier() throws IOException {
+ query = "\"Katze\" []* \"Hund\"";
+ jsonLd = "{@type:koral:distance,key:w,boundary:{@type:koral:boundary,min:0}}";
+ FCSQLQueryProcessorTest.validateNode(query, "/query/distances/0",
+ jsonLd);
+
+ query = "\"Katze\" []+ \"Hund\"";
+ jsonLd = "{@type:koral:distance,key:w,boundary:{@type:koral:boundary,min:1}}";
+ FCSQLQueryProcessorTest.validateNode(query, "/query/distances/0",
+ jsonLd);
+
+ query = "\"Katze\" []{3} \"Hund\"";
+ jsonLd = "{@type:koral:distance,key:w,boundary:{@type:koral:boundary,min:3,max:3}}";
+ FCSQLQueryProcessorTest.validateNode(query, "/query/distances/0",
+ jsonLd);
+
+ query = "\"Katze\" []{2,3} \"Hund\"";
+ jsonLd = "{@type:koral:distance,key:w,boundary:{@type:koral:boundary,min:2,max:3}}";
+ FCSQLQueryProcessorTest.validateNode(query, "/query/distances/0",
+ jsonLd);
+ }
+
+ @Test
+ public void testDistanceQueryWithMultipleWildcards() throws IOException {
// sequences of wildcards
query = "\"Katze\" []{3}[] \"Hund\"";
jsonLd = "{@type:koral:distance,key:w,boundary:{@type:koral:boundary,min:4,max:4}}";
FCSQLQueryProcessorTest.validateNode(query, "/query/distances/0",
jsonLd);
+ query = "\"Katze\" []{3}[]? \"Hund\"";
+ jsonLd = "{@type:koral:distance,key:w,boundary:{@type:koral:boundary,min:3,max:4}}";
+ FCSQLQueryProcessorTest.validateNode(query, "/query/distances/0",
+ jsonLd);
+
query = "\"Katze\" []{2}[]{3}[] \"Hund\"";
jsonLd = "{@type:koral:distance,key:w,boundary:{@type:koral:boundary,min:6,max:6}}";
FCSQLQueryProcessorTest.validateNode(query, "/query/distances/0",
@@ -240,15 +296,15 @@
+ "operands:["
+ "{@type:koral:token,wrap:{@type:koral:term,key:Katze,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}},"
+ "{@type:koral:group,"
- + "operation:operation:sequence,"
- + "inOrder:true,"
- + "distances:["
- + "{@type:koral:distance,key:w,boundary:{@type:koral:boundary,min:1,max:2}}"
- + "],"
- + "operands:["
- + "{@type:koral:token,wrap:{@type:koral:term,key:Hund,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}},"
- + "{@type:koral:token,wrap:{@type:koral:term,key:V,foundry:cnx,layer:p,type:type:regex,match:match:eq}}]}"
- +"]}";
+ + "operation:operation:sequence,"
+ + "inOrder:true,"
+ + "distances:["
+ + "{@type:koral:distance,key:w,boundary:{@type:koral:boundary,min:1,max:2}}"
+ + "],"
+ + "operands:["
+ + "{@type:koral:token,wrap:{@type:koral:term,key:Hund,foundry:opennlp,layer:orth,type:type:regex,match:match:eq}},"
+ + "{@type:koral:token,wrap:{@type:koral:term,key:V,foundry:cnx,layer:p,type:type:regex,match:match:eq}}]}"
+ + "]}";
FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
}
@@ -290,17 +346,43 @@
"FCS diagnostic 11: Within scope UTTERANCE is currently unsupported.",
(String) error.get(1));
}
-
+
@Test
- public void testWithinQueryWithEmptyTokens() throws IOException {
+ public void testWithinQueryWithEmptyTokens() throws IOException {
query = "[] within s";
jsonLd = "{@type:koral:group,"
+ "operation:operation:position,"
+ "operands:["
+ "{@type:koral:span,wrap:{@type:koral:term,key:s,foundry:base,layer:s}},"
- + "{@type:koral:token}"
- + "]}";
+ + "{@type:koral:token}" + "]}";
FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+
+ query = "[]+ within s";
+ jsonLd = "{@type:koral:group," + "operation:operation:repetition,"
+ + "operands:[{@type:koral:token}],"
+ + "boundary:{@type:koral:boundary,min:1}}";
+ FCSQLQueryProcessorTest
+ .validateNode(query, "/query/operands/1", jsonLd);
+ }
+
+ @Test
+ public void testWithinQueryWithGroupQuery() throws IOException {
+ query = "(\"blaue\"|\"grüne\")+ within s";
+ jsonLd = "{@type:koral:span,wrap:{@type:koral:term,key:s,foundry:base,layer:s}}";
+ FCSQLQueryProcessorTest
+ .validateNode(query, "/query/operands/0", jsonLd);
+ jsonLd = "{@type:koral:group,"
+ + "operation:operation:repetition,"
+ + "operands:["
+ + "{@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}}"
+ + "]}]," + "boundary:{@type:koral:boundary,min:1}}";
+ FCSQLQueryProcessorTest
+ .validateNode(query, "/query/operands/1", jsonLd);
+
}
@Test
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 9c030de..666bff1 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
@@ -47,8 +47,7 @@
@Test
public void testVersion() throws JsonProcessingException {
- error = getError(new FCSQLQueryProcessor("\"Sonne\"",
- "1.0"));
+ 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));
@@ -103,7 +102,7 @@
+ "key:Fliegen, foundry:opennlp, layer:orth, type:type:regex, match:match:eq}}";
FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
- query = "\"Fliegen\" /i";
+ query = "[text = \"Fliegen\" /i]";
FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
query = "\"Fliegen\" /C";
@@ -114,8 +113,8 @@
FCSQLQueryProcessorTest.validateNode(query, "/query/wrap", jsonLd);
query = "\"Fliegen\" /l";
- error = FCSQLQueryProcessorTest
- .getError(new FCSQLQueryProcessor(query, "2.0"));
+ error = FCSQLQueryProcessorTest.getError(new FCSQLQueryProcessor(query,
+ "2.0"));
assertEquals(306, error.get(0));
String msg = (String) error.get(1);
assertEquals(true, msg.startsWith("SRU diagnostic 48: Regexflags"));
@@ -139,7 +138,6 @@
runAndValidate(query, jsonLd);
}
-
// attribute operator flagged-regexp
// -------------------------------------------------------------------------
// attribute ::= simple-attribute | qualified-attribute
@@ -178,7 +176,6 @@
runAndValidate(query, jsonLd);
}
-
// segment-query ::= "[" expression? "]"
// -------------------------------------------------------------------------
// expression ::= basic-expression
@@ -238,6 +235,19 @@
FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
}
+ @Test
+ public void testMultipleBooleanExpressions() throws IOException {
+ query = "[mate:lemma=\"sein\" & (mate:pos=\"PPOSS\"|mate:pos=\"VAFIN\")]";
+ jsonLd = "{@type: koral:token,"
+ + " wrap: { @type: koral:termGroup,"
+ + "relation: relation:or,"
+ + " operands:["
+ + "{@type: koral:term, key: PPOSS, foundry: mate, layer: p, type:type:regex, match: match:eq},"
+ + "{@type: koral:term, key: VAFIN, foundry: mate, layer: p, type:type:regex, match: match:eq}]}}";
+ FCSQLQueryProcessorTest.validateNode(query, "/query/wrap/operands/1",
+ jsonLd);
+ }
+
// "!" expression /* not */
@Test
public void testExpressionNot() throws IOException {
@@ -259,6 +269,9 @@
+ "{@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}]}}";
FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
+
+ query = "[!(mate:lemma=\"sein\" & mate:pos=\"PPOSS\")]";
+ FCSQLQueryProcessorTest.runAndValidate(query, jsonLd);
}
@Test
@@ -274,10 +287,9 @@
query = "[tt:morph = \"sein\"]";
error = getError(new FCSQLQueryProcessor(query, "2.0"));
assertEquals(306, error.get(0));
- assertEquals(
- "SRU diagnostic 48: Layer morph is unsupported.",
+ assertEquals("SRU diagnostic 48: Layer morph is unsupported.",
error.get(1));
-
+
// unsupported qualifier
query = "[malt:lemma = \"sein\"]";
error = getError(new FCSQLQueryProcessor(query, "2.0"));