Updated the distance query with optionality.
Change-Id: I27a2722a1d985de4867013b2a5dd4e4b3652f4f5
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessor.java b/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessor.java
index 89fe13f..10268a1 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessor.java
@@ -264,28 +264,30 @@
sequence.put("distances", distances);
// Check optionality
- ParseTree lastChildNode = node.getChild(node.getChildCount() - 1);
- if (getNodeCat(lastChildNode).equals("segment")) {
- ParseTree quantification = getFirstChildWithCat(lastChildNode,
- "repetition");
- if (quantification != null) {
- minmax = parseRepetition(quantification);
- if (minmax[0] == 0 && minmax[1] == 1) {
- visited.add(quantification);
- processDisjunction();
- // create expansion
- isExpansion = true;
- LinkedHashMap<String, Object> expansionSequence = KoralObjectGenerator
- .makeGroup("sequence");
- putIntoSuperObject(expansionSequence);
- objectStack.push(expansionSequence);
- processNode(node.getChild(0));
- processNode(distanceNode.getChild(0));
- isExpansion = false;
- objectStack.pop();
- }
+ ParseTree operand1 = node.getChild(0);
+ ParseTree operand2 = node.getChild(node.getChildCount() - 1);
+ isExpansion = true;
+ if (checkOptionality(operand1)) {
+ processDisjunction();
+ // create expansion
+ if (checkOptionality(operand2)) {
+ createDisjunctionForDistanceWithOptionality(operand2, operand1,
+ distanceNode, false);
+ objectStack.pop();
+ putIntoSuperObject(KoralObjectGenerator.makeToken());
}
+ createDisjunctionForDistanceWithOptionality(operand1, operand2,
+ distanceNode, true);
+ objectStack.pop();
+
}
+ else if (checkOptionality(operand2)){
+ processDisjunction();
+ createDisjunctionForDistanceWithOptionality(operand2, operand1,
+ distanceNode, false);
+ objectStack.pop();
+ }
+ isExpansion = false;
// don't re-visit the emptyTokenSequence node
visited.add(distanceNode.getChild(0));
}
@@ -295,6 +297,37 @@
}
+ private boolean checkOptionality (ParseTree node) {
+ ParseTree quantification = getFirstChildWithCat(node, "repetition");
+ if (quantification != null) {
+ Integer[] minmax = parseRepetition(quantification);
+ if (minmax[0] == 0 && minmax[1] == 1) {
+ visited.add(quantification);
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ private void createDisjunctionForDistanceWithOptionality (
+ ParseTree operand1, ParseTree operand2, ParseTree distanceNode,
+ boolean isCheckingFirstOperand) {
+ LinkedHashMap<String, Object> expansionSequence = KoralObjectGenerator
+ .makeGroup("sequence");
+ putIntoSuperObject(expansionSequence);
+ objectStack.push(expansionSequence);
+ if (isCheckingFirstOperand) {
+ processNode(distanceNode.getChild(0));
+ processNode(operand2);
+ }
+ else {
+ processNode(operand2);
+ processNode(distanceNode.getChild(0));
+ }
+ }
+
+
@SuppressWarnings("unchecked")
/**
* empty tokens at beginning/end of sequence
diff --git a/src/test/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessorTest.java b/src/test/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessorTest.java
index 57ea313..1f16a02 100644
--- a/src/test/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessorTest.java
+++ b/src/test/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessorTest.java
@@ -827,7 +827,7 @@
@Test
- public void testDistanceWithEmptyTokenAndOptionality ()
+ public void testDistanceWithOptionality ()
throws JsonProcessingException, IOException {
query = "[base=der][][base=Mann]?";
qs.setQuery(query, "poliqarpplus");
@@ -841,6 +841,7 @@
assertEquals("operation:sequence", res.at(disjunctionOperand1+"operation").asText());
assertEquals("der", res.at(disjunctionOperand1+"operands/0/wrap/key").asText());
assertEquals("koral:token", res.at(disjunctionOperand1+"operands/1/@type").asText());
+ assertEquals(true, res.at(disjunctionOperand1+"operands/1/wrap/key").isMissingNode());
String disjunctionOperand2 = "/query/operands/1/";
assertEquals("operation:sequence", res.at(disjunctionOperand2+"operation").asText());
@@ -852,7 +853,7 @@
}
@Test
- public void testDistanceWithEmptyTokenAndOptionality2 ()
+ public void testDistanceWithOptionalityAndMultipleSequences ()
throws JsonProcessingException, IOException {
query = "[base=der][base=bose][][base=Mann]?";
qs.setQuery(query, "poliqarpplus");
@@ -872,6 +873,7 @@
assertEquals("operation:sequence", res.at(disjunctionOperand1+"operation").asText());
assertEquals("bose", res.at(disjunctionOperand1+"operands/0/wrap/key").asText());
assertEquals("koral:token", res.at(disjunctionOperand1+"operands/1/@type").asText());
+ assertEquals(true, res.at(disjunctionOperand1+"operands/1/wrap/key").isMissingNode());
String disjunctionOperand2 = "/query/operands/1/operands/1/";
assertEquals("operation:sequence", res.at(disjunctionOperand2+"operation").asText());
@@ -880,7 +882,97 @@
assertEquals("1", res.at(disjunctionOperand2+"distances/0/boundary/min").asText());
assertEquals("1", res.at(disjunctionOperand2+"distances/0/boundary/max").asText());
}
+
+ @Test
+ public void testDistanceWithOptionalityAndMultipleEmptyToken ()
+ throws JsonProcessingException, IOException {
+ query = "[base=der][][][base=Mann]?";
+ qs.setQuery(query, "poliqarpplus");
+ String koralQuery = qs.toJSON();
+ res = mapper.readTree(koralQuery);
+ assertEquals("koral:group", res.at("/query/@type").asText());
+ assertEquals("operation:disjunction", res.at("/query/operation").asText());
+
+ String disjunctionOperand1 = "/query/operands/0/";
+ assertEquals("operation:sequence", res.at(disjunctionOperand1+"operation").asText());
+ assertEquals("der", res.at(disjunctionOperand1+"operands/0/wrap/key").asText());
+
+ String emptyTokenOperand = disjunctionOperand1+"operands/1/";
+ assertEquals("koral:group", res.at(emptyTokenOperand+"@type").asText());
+ assertEquals("koral:token", res.at(emptyTokenOperand+"operands/0/@type").asText());
+ assertEquals(true, res.at(emptyTokenOperand+"operands/0/wrap/key").isMissingNode());
+ assertEquals("2", res.at(emptyTokenOperand+"boundary/min").asText());
+ assertEquals("2", res.at(emptyTokenOperand+"boundary/max").asText());
+
+ String disjunctionOperand2 = "/query/operands/1/";
+ assertEquals("operation:sequence", res.at(disjunctionOperand2+"operation").asText());
+ assertEquals("der", res.at(disjunctionOperand2+"operands/0/wrap/key").asText());
+ assertEquals("Mann", res.at(disjunctionOperand2+"operands/1/wrap/key").asText());
+ assertEquals("2", res.at(disjunctionOperand2+"distances/0/boundary/min").asText());
+ assertEquals("2", res.at(disjunctionOperand2+"distances/0/boundary/max").asText());
+
+ }
+
+ @Test
+ public void testDistanceWithOptionalityOnTheLeft ()
+ throws JsonProcessingException, IOException {
+ query = "[base=der][base=bose]?[][base=Mann]";
+ qs.setQuery(query, "poliqarpplus");
+ String koralQuery = qs.toJSON();
+ res = mapper.readTree(koralQuery);
+
+ assertEquals("koral:group", res.at("/query/operands/1/@type").asText());
+ assertEquals("operation:disjunction", res.at("/query/operands/1/operation").asText());
+
+ String disjunctionOperand1 = "/query/operands/1/operands/0/";
+ assertEquals("operation:sequence", res.at(disjunctionOperand1+"operation").asText());
+ assertEquals("koral:token", res.at(disjunctionOperand1+"operands/0/@type").asText());
+ assertEquals(true, res.at(disjunctionOperand1+"operands/0/key").isMissingNode());
+ assertEquals("Mann", res.at(disjunctionOperand1+"operands/1/wrap/key").asText());
+
+ String disjunctionOperand2 = "/query/operands/1/operands/1/";
+ assertEquals("operation:sequence", res.at(disjunctionOperand2+"operation").asText());
+ assertEquals("bose", res.at(disjunctionOperand2+"operands/0/wrap/key").asText());
+ assertEquals("Mann", res.at(disjunctionOperand2+"operands/1/wrap/key").asText());
+ assertEquals("1", res.at(disjunctionOperand2+"distances/0/boundary/min").asText());
+ assertEquals("1", res.at(disjunctionOperand2+"distances/0/boundary/max").asText());
+ }
+ @Test
+ public void testDistanceWithOptionalityOnBothOperands()
+ throws JsonProcessingException, IOException {
+ query = "[base=der]?[][base=Mann]?";
+ qs.setQuery(query, "poliqarpplus");
+ String koralQuery = qs.toJSON();
+ res = mapper.readTree(koralQuery);
+
+ assertEquals("koral:group", res.at("/query/@type").asText());
+ assertEquals("operation:disjunction", res.at("/query/operation").asText());
+
+ String disjunctionOperand1 = "/query/operands/0/";
+ assertEquals("operation:sequence", res.at(disjunctionOperand1+"operation").asText());
+ assertEquals("der", res.at(disjunctionOperand1+"operands/0/wrap/key").asText());
+ assertEquals("koral:token", res.at(disjunctionOperand1+"operands/1/@type").asText());
+ assertEquals(true, res.at(disjunctionOperand1+"operands/1/key").isMissingNode());
+
+ String disjunctionOperand2 = "/query/operands/1/";
+ assertEquals("koral:token", res.at(disjunctionOperand2+"@type").asText());
+ assertEquals(true, res.at(disjunctionOperand2+"key").isMissingNode());
+
+ String disjunctionOperand3 = "/query/operands/2/";
+ assertEquals("operation:sequence", res.at(disjunctionOperand3+"operation").asText());
+ assertEquals("koral:token", res.at(disjunctionOperand3+"operands/0/@type").asText());
+ assertEquals(true, res.at(disjunctionOperand3+"operands/0/key").isMissingNode());
+ assertEquals("Mann", res.at(disjunctionOperand3+"operands/1/wrap/key").asText());
+
+ String disjunctionOperand4 = "/query/operands/3/";
+ assertEquals("operation:sequence", res.at(disjunctionOperand4+"operation").asText());
+ assertEquals("der", res.at(disjunctionOperand4+"operands/0/wrap/key").asText());
+ assertEquals("Mann", res.at(disjunctionOperand4+"operands/1/wrap/key").asText());
+ assertEquals("1", res.at(disjunctionOperand4+"distances/0/boundary/min").asText());
+ assertEquals("1", res.at(disjunctionOperand4+"distances/0/boundary/max").asText());
+ }
+
@Test
public void testRepetition () throws JsonProcessingException, IOException {
query = "der{3}";