stacking bug fix
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusTree.java b/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusTree.java
index 42b5b07..6e50e62 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusTree.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusTree.java
@@ -79,6 +79,19 @@
* Marks the object to which following occurrence information is to be added.
*/
LinkedHashMap<String,Object> curOccGroup = new LinkedHashMap<String,Object>();
+ /**
+ * Keeps track of how many objects there are to pop after every recursion of {@link #processNode(ParseTree)}
+ */
+ LinkedList<Integer> objectsToPop = new LinkedList<Integer>();
+ /**
+ * Keeps track of how many objects there are to pop after every recursion of {@link #processNode(ParseTree)}
+ */
+ LinkedList<Integer> tokensToPop = new LinkedList<Integer>();
+ /**
+ * Keeps track of how many objects there are to pop after every recursion of {@link #processNode(ParseTree)}
+ */
+ LinkedList<Integer> fieldsToPop = new LinkedList<Integer>();
+
/**
* Most centrally, this class maintains a set of nested maps and lists which represent the JSON tree, which is built by the JSON serialiser
@@ -152,6 +165,10 @@
String nodeCat = getNodeCat(node);
openNodeCats.push(nodeCat);
+ Integer stackedObjects = 0;
+ Integer stackedTokens= 0;
+ Integer stackedFields = 0;
+
// System.err.println(objectStack);
// System.out.println(openNodeCats);
// System.out.println(" "+requestMap.get("query")+"");
@@ -176,6 +193,7 @@
if (!ignoreCq_segment) {
LinkedHashMap<String,Object> sequence = new LinkedHashMap<String,Object>();
objectStack.push(sequence);
+ stackedObjects++;
// Step 0: cq_segments has 'occ' child -> introduce group as super group to the sequence/token/group
// this requires creating a group and inserting it at a suitable place
if (getNodeCat(node.getChild(node.getChildCount()-1)).equals("occ")) {
@@ -186,19 +204,29 @@
occGroup.put("operands", groupOperands);
curOccGroup = occGroup;
objectStack.push(occGroup);
+ stackedObjects++;
if (openNodeCats.get(1).equals("query")) {
// top query node
if (node.getParent().getChildCount() == 1) {
+ // only child
requestMap.put("query", occGroup);
} else {
- // create containing sequence and embed there
- LinkedHashMap<String,Object> superSequence = new LinkedHashMap<String,Object>();
- superSequence.put("@type", "korap:sequence");
- ArrayList<Object> operands = new ArrayList<Object>();
- operands.add(occGroup);
- superSequence.put("operands", operands);
- requestMap.put("query", superSequence);
- objectStack.add(1, superSequence); // add at 2nd position to keep current cq_segment accessible
+ // not an only child, need to create containing sequence
+ if (node.getParent().getChild(0).equals(node)) {
+ // if first child, create containing sequence and embed there
+ LinkedHashMap<String,Object> superSequence = new LinkedHashMap<String,Object>();
+ superSequence.put("@type", "korap:sequence");
+ ArrayList<Object> operands = new ArrayList<Object>();
+ operands.add(occGroup);
+ superSequence.put("operands", operands);
+ requestMap.put("query", superSequence);
+ objectStack.add(1, superSequence); // add at 2nd position to keep current cq_segment accessible
+ stackedObjects--;
+ } else {
+ // if not first child, add to previously created parent sequence
+ ArrayList<Object> topSequenceOperands = (ArrayList<Object>) objectStack.get(1).get("operands");
+ topSequenceOperands.add(occGroup);
+ }
}
} else if (!objectStack.isEmpty()){
// embed in super sequence
@@ -217,6 +245,7 @@
// if only child, make the sequence a mere korap:token
sequence.put("@type", "korap:token");
tokenStack.push(sequence);
+ stackedTokens++;
}
// Step II: decide where to put this element
// check if this is an argument for a containing occurrence group (see step 0)
@@ -226,7 +255,7 @@
// ...if not modified by occurrence, put into suitable super structure
} else {
if (openNodeCats.get(1).equals("query")) {
- // top query node
+ // cq_segment is top query node
if (node.getParent().getChildCount()==1) {
// only child
requestMap.put("query", sequence);
@@ -238,8 +267,10 @@
superSequence.put("@type", "korap:sequence");
ArrayList<Object> operands = new ArrayList<Object>();
superSequence.put("operands", operands);
+ operands.add(sequence);
requestMap.put("query", superSequence);
objectStack.add(1, superSequence); // add at 2nd position to keep current cq_segment accessible
+ stackedObjects--;
} else {
// if not first child, add to previously created parent sequence
ArrayList<Object> topSequenceOperands = (ArrayList<Object>) objectStack.get(1).get("operands");
@@ -262,12 +293,14 @@
if (tokenStack.isEmpty()) {
token = new LinkedHashMap<String, Object>();
tokenStack.push(token);
+ stackedTokens++;
} else {
// in case cq_segments has already added the token
token = tokenStack.getFirst();
}
curToken = token;
objectStack.push(token);
+ stackedObjects++;
// Step II: start filling object and add to containing sequence
token.put("@type", "korap:token");
// add token to sequence only if it is not an only child (in that case, cq_segments has already added the info and is just waiting for the values from "field")
@@ -283,11 +316,11 @@
if (nodeCat.equals("cq_disj_segments")) {
LinkedHashMap<String,Object> disjunction = new LinkedHashMap<String,Object>();
objectStack.push(disjunction);
+ stackedObjects++;
ArrayList<Object> disjOperands = new ArrayList<Object>();
disjunction.put("@type", "korap:group");
disjunction.put("relation", "or");
disjunction.put("operands", disjOperands);
- objectStack.push(disjunction);
// decide where to put the disjunction
if (openNodeCats.get(1).equals("query")) {
requestMap.put("query", disjunction);
@@ -337,6 +370,7 @@
group.put("@type", "korap:group");
group.put("operands", groupOperands);
fieldStack.push(groupOperands);
+ stackedFields++;
// Step I: get operator (& or |)
ParseTree operatorNode = node.getChild(1).getChild(0);
String operator = getNodeCat(operatorNode);
@@ -364,12 +398,14 @@
if (tokenStack.isEmpty()) {
token = new LinkedHashMap<String, Object>();
tokenStack.push(token);
+ stackedTokens++;
} else {
// in case sq_segments has already added the token
token = tokenStack.getFirst();
}
curToken = token;
objectStack.push(token);
+ stackedObjects++;
// Step II: fill object (token values) and put into containing sequence
token.put("@type", "korap:token");
String word = node.getChild(0).toStringTree(poliqarpParser);
@@ -395,6 +431,7 @@
}
curToken = elem;
objectStack.push(elem);
+ stackedObjects++;
// Step II: fill object (token values) and put into containing sequence
elem.put("@type", "korap:element");
String value = node.getChild(1).toStringTree(poliqarpParser);
@@ -409,6 +446,7 @@
if (nodeCat.equals("spanclass")) {
LinkedHashMap<String,Object> span = new LinkedHashMap<String,Object>();
objectStack.push(span);
+ stackedObjects++;
ArrayList<Object> spanOperands = new ArrayList<Object>();
String id = "0";
// Step I: get info
@@ -436,12 +474,12 @@
topSequenceOperands.add(span);
}
- objectStack.push(span);
}
if (nodeCat.equals("position")) {
LinkedHashMap<String,Object> positionGroup = new LinkedHashMap<String,Object>();
objectStack.push(positionGroup);
+ stackedObjects++;
ArrayList<Object> posOperands = new ArrayList<Object>();
// Step I: get info
String relation = getNodeCat(node.getChild(0));
@@ -464,6 +502,7 @@
if (nodeCat.equals("shrink")) {
LinkedHashMap<String,Object> shrinkGroup = new LinkedHashMap<String,Object>();
objectStack.push(shrinkGroup);
+ stackedObjects++;
ArrayList<Object> shrinkOperands = new ArrayList<Object>();
// Step I: get info
String operandClass = "0";
@@ -490,6 +529,7 @@
subSequence.put("operands", subSequenceOperands);
shrinkOperands.add(subSequence);
objectStack.push(subSequence);
+ stackedObjects++;
}
// Step II: decide where to put the group
// add group to sequence only if it is not an only child (in that case, sq_segments has already added the info and is just waiting for the relevant info)
@@ -528,8 +568,6 @@
metaFilter.put("@type", "korap:meta");
}
-
-
if (nodeCat.equals("within")) {
ParseTree domainNode = node.getChild(2);
String domain = getNodeCat(domainNode);
@@ -540,6 +578,10 @@
visited.add(domainNode);
}
+ objectsToPop.push(stackedObjects);
+ tokensToPop.push(stackedTokens);
+ fieldsToPop.push(stackedFields);
+
/*
****************************************************************
****************************************************************
@@ -552,34 +594,48 @@
processNode(child);
}
- // Stuff that happens when leaving a node (taking it off the stack)
- if (nodeCat.equals("cq_segments") || nodeCat.equals("sq_segments")) {
- // exclude whitespaces analysed as empty cq_segments
- if (!ignoreCq_segment && !objectStack.isEmpty()) {
- objectStack.pop();
- }
- }
-
- if (nodeCat.equals("cq_disj_segments")) {
+ // Stuff that happens when leaving a node (taking items off the stacks)
+ for (int i=0; i<objectsToPop.get(0); i++) {
objectStack.pop();
}
-
- if (nodeCat.equals("cq_segment") || nodeCat.equals("sq_segment")){
+ objectsToPop.pop();
+ for (int i=0; i<tokensToPop.get(0); i++) {
tokenStack.pop();
- objectStack.pop();
}
-
- if (nodeCat.equals("conj_field")) {
+ tokensToPop.pop();
+ for (int i=0; i<fieldsToPop.get(0); i++) {
fieldStack.pop();
}
+ fieldsToPop.pop();
- if (nodeCat.equals("position") || nodeCat.equals("spanclass")) {
- objectStack.pop();
- }
-
- if (nodeCat.equals("shrink")) {
- objectStack.pop();
- }
+// // Stuff that happens when leaving a node (taking it off the stack)
+// if (nodeCat.equals("cq_segments") || nodeCat.equals("sq_segments")) {
+// // exclude whitespaces analysed as empty cq_segments
+// if (!ignoreCq_segment && !objectStack.isEmpty()) {
+// objectStack.pop();
+// }
+// }
+//
+// if (nodeCat.equals("cq_disj_segments")) {
+// objectStack.pop();
+// }
+//
+// if (nodeCat.equals("cq_segment") || nodeCat.equals("sq_segment")){
+// tokenStack.pop();
+// objectStack.pop();
+// }
+//
+// if (nodeCat.equals("conj_field")) {
+// fieldStack.pop();
+// }
+//
+// if (nodeCat.equals("position") || nodeCat.equals("spanclass")) {
+// objectStack.pop();
+// }
+//
+// if (nodeCat.equals("shrink")) {
+// objectStack.pop();
+// }
openNodeCats.pop();
}