package main.expressions; import main.parsers.XGrammarBaseVisitor; import main.parsers.XGrammarParser; import org.antlr.v4.runtime.Parser; import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.TerminalNode; import org.w3c.dom.*; import org.xml.sax.SAXException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import java.io.File; import java.io.IOException; import java.util.*; import java.util.stream.Collectors; public class ExpressionBuilder extends XGrammarBaseVisitor{ /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ private NodeContainer nodeObj; @Override public NodeContainer visitProg(XGrammarParser.ProgContext ctx) { NodeContainer nodeContainer = visit(ctx.xq(0)); nodeObj.validNodes = nodeContainer.validNodes; removeDuplicates(nodeObj); // nodeObj.printElements(); //to check results (remove print statement later) return nodeObj; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitAp_Slash(XGrammarParser.Ap_SlashContext ctx) { visit(ctx.doc()); //populates with root document node //nodeObj.slashRule = true; //indicates to rp_tag rule to check children of current nodes visit(ctx.rp()); //nodeObj.slashRule = false; return nodeObj; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitAp_Dslash(XGrammarParser.Ap_DslashContext ctx) { visit(ctx.doc()); //populates with root document element //recursively/stack iteratively add all nodes for the second rp to check on (even text nodes) nodeObj.iterativeAddAll(); return visit(ctx.rp()); //System.out.println(nodeObj.rootDoc.getDocumentElement().getChildNodes().getLength()); } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitRp_DSlash(XGrammarParser.Rp_DSlashContext ctx) { visit(ctx.rp(0)); nodeObj.iterativeAddAll(); return visit(ctx.rp(1)); } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ //base method, get all children nodes @Override public NodeContainer visitRp_Wild(XGrammarParser.Rp_WildContext ctx) { //add all child nodes of the current visiting node //gets all children nodes ArrayList toReplace = new ArrayList<>(); //add all element nodes for (Node node : nodeObj.validNodes){ NodeList tempList = node.getChildNodes(); for (int i = 0; i < tempList.getLength(); i++){ if (tempList.item(i).getNodeType() == Node.ELEMENT_NODE) { //adds only element node children toReplace.add(tempList.item(i)); } } } nodeObj.validNodes = toReplace; return nodeObj; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitRp_Per(XGrammarParser.Rp_PerContext ctx) { //remain at current node or nodes return nodeObj; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitRp_Filter(XGrammarParser.Rp_FilterContext ctx) { visit(ctx.rp()); return visit(ctx.f()); } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitRp_Concat(XGrammarParser.Rp_ConcatContext ctx) { // Check for duplicates after concatenation ArrayList og = new ArrayList<>(nodeObj.validNodes); NodeContainer rp1 = visit(ctx.rp(0)); //visit with current node object state ArrayList rp1List = rp1.validNodes; // Since nodes that were added to validNodes from the first operand shouldn't be considered for the second operand nodeObj.validNodes = og; NodeContainer rp2 = visit(ctx.rp(1)); //visit with current node object state ArrayList rp2List = rp2.validNodes; rp1List.addAll(rp2List); nodeObj.validNodes = rp1List; return removeDuplicates(nodeObj); } // @Override public NodeContainer visitRp_Concat(XGrammarParser.Rp_ConcatContext ctx) { // // NodeContainer currentState = new NodeContainer(nodeObj); // //currentState.printElements(); // NodeContainer rp1 = visit(ctx.rp(0)); //visit with current node object state // //rp1.printElements(); // nodeObj = currentState; // NodeContainer rp2 = visit(ctx.rp(1)); //visit with current node object state // //rp2.printElements(); // // nodeObj.validNodes.clear(); // nodeObj.validNodes.addAll(rp1.validNodes); // nodeObj.validNodes.addAll(rp2.validNodes); // return nodeObj; // } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ //simple method, select tag name equivalent nodes // @Override public NodeContainer visitRp_Tag(XGrammarParser.Rp_TagContext ctx) { // // ArrayList toReplace = new ArrayList<>(); // System.out.println("Rp Tag " + ctx.getText()); // //for all the children nodes check tag name against it // for (Node node : nodeObj.validNodes){ // NodeList tempList = node.getChildNodes(); // // for (int i = 0; i < tempList.getLength(); i++){ // if ((tempList.item(i).getNodeType() == Node.ELEMENT_NODE) && tempList.item(i).getNodeName().equals(ctx.TEXT().getText())){ //// System.out.println("Adding: " + tempList.item(i).getNodeName()); // toReplace.add(tempList.item(i)); // } // } // } // nodeObj.validNodes = toReplace; // System.out.println("Tag: " + toReplace); // System.out.println(ctx.getText()); // return nodeObj; // // if (nodeObj.validNodes.size() > 0){ // // nodeObj.validNodes.removeIf(n -> (n.getNodeType() == Node.ELEMENT_NODE && !(n.getNodeName().equals(ctx.TEXT().getText())))); // // } // } @Override public NodeContainer visitRp_Tag(XGrammarParser.Rp_TagContext ctx) { ArrayList toReplace = new ArrayList<>(); nodeObj.addOnlyChildren(); //if (nodeObj.slashRule == true){ //indicates the most recent / or // ancestor was a / type, add all children and check tag name against that // nodeObj.addOnlyChildren(); //} //for all current nodes, check tag name against it (must be an element node) for (Node node : nodeObj.validNodes){ if ((node.getNodeType() == Node.ELEMENT_NODE) && node.getNodeName().equals(ctx.TAGNAME().getText())) { toReplace.add(node); } } nodeObj.validNodes = toReplace; // System.out.println("In rp tag: " + nodeObj.validNodes); return nodeObj; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ //base method, get text of current node //base method, get all the text node descendants of current nodes @Override public NodeContainer visitRp_Text(XGrammarParser.Rp_TextContext ctx) { ArrayList textNodes = new ArrayList<>(); NodeList nl; for (Node node: nodeObj.validNodes) { nl = node.getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { if (nl.item(i).getNodeType() == Node.TEXT_NODE) { textNodes.add(nl.item(i)); } } } nodeObj.validNodes = textNodes; return nodeObj; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ //base method, get parent node of current visiting node @Override public NodeContainer visitRp_Dper(XGrammarParser.Rp_DperContext ctx) { /* since its possible to have more than one parent nodes in the validNodes list, but many of the nodes will have the same parent node, -> remove duplicates at end ensure that there is a valid parent node, otherwise indicate already at root; */ Set parentSet = new LinkedHashSet<>(); for (Node node : nodeObj.validNodes){ if (node == nodeObj.rootDoc){ //System.out.println("Already at the root node, unable to generate result\n"); return nodeObj; } parentSet.add(node.getParentNode()); } //nodeObj.validNodes.clear(); //nodeObj.validNodes.addAll(parentSet); nodeObj.validNodes = new ArrayList<>(parentSet); return nodeObj; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitRp_Slash(XGrammarParser.Rp_SlashContext ctx) { visit(ctx.rp(0)); //nodeObj.slashRule = true; visit(ctx.rp(1)); //nodeObj.slashRule = false; return nodeObj; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ //base method, call DOM attribute method //fix this and test @Override public NodeContainer visitRp_Attr(XGrammarParser.Rp_AttrContext ctx) { ArrayList attrNodes = new ArrayList<>(); String attr; for (int i = 0; i < nodeObj.validNodes.size(); i++) { if (nodeObj.validNodes.get(i).hasAttributes()) { if (ctx.children.size() == 2) { attr = ctx.getChild(1).getText(); } else{ continue; } NamedNodeMap attrMap = nodeObj.validNodes.get(i).getAttributes(); if (attrMap.getNamedItem(attr) != null) { attrNodes.add(attrMap.getNamedItem(attr)); } } } nodeObj.validNodes = attrNodes; return nodeObj; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ //(rp) = rp @Override public NodeContainer visitRp_Par(XGrammarParser.Rp_ParContext ctx) { return visit(ctx.rp()); //skip parenthesis tokens } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitF_Par(XGrammarParser.F_ParContext ctx) { return visit(ctx.f()); } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitF_Not(XGrammarParser.F_NotContext ctx) { ArrayList og = new ArrayList<>(nodeObj.validNodes); ArrayList nodes = visit(ctx.f()).validNodes; og.removeAll(nodes); nodeObj.validNodes = new ArrayList<>(og); return nodeObj; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitF_Or(XGrammarParser.F_OrContext ctx) { ArrayList og = new ArrayList<>(nodeObj.validNodes); ArrayList evalFilter = visit(ctx.f(0)).validNodes; nodeObj.validNodes = og; evalFilter.addAll(visit(ctx.f(1)).validNodes); evalFilter = removeDuplicates(evalFilter); nodeObj.validNodes = evalFilter; return nodeObj; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitF_Const(XGrammarParser.F_ConstContext ctx) { if (ctx.EQ().getText().equalsIgnoreCase("eq")) { throw new RuntimeException("String cannot be compared using the 'eq' operator." + "Use '=' instead"); } ArrayList og = new ArrayList<>(nodeObj.validNodes); TerminalNode stringConstant = ctx.STRINGCONST(); ArrayList returnList = new ArrayList<>(); for (Node ogNode : og) { nodeObj.validNodes = new ArrayList<>(); nodeObj.validNodes.add(ogNode); ArrayList nodes = visit(ctx.rp()).validNodes; for (Node node : nodes) { if (node.getTextContent().equals(stringConstant.getText().substring(1, stringConstant.getText().length()-1))) { returnList.add(ogNode); } //System.out.println("Node Type: " + node.getNodeType()); // System.out.println("Node Content: " + node.getTextContent()); // Potential issue --> does not differentiate between different kinds of whitespaces //ArrayList parts = new ArrayList<>( // Arrays.asList(node.getTextContent().split(" \t\r\n"))); //String sc = stringConstant.stream().map(ParseTree::getText) // .collect(Collectors.joining(" ")); // System.out.println(Node.TEXT_NODE + " " + sc.equals(String.join(" ", parts))); // if (node.getNodeType() == Node.TEXT_NODE // && String.join(" ", parts).equals(sc)) { //if (String.join(" ", parts).equals(sc)) { // Even if there's one match, move on to the next obj // returnList.add(ogNode); // break; } } nodeObj.validNodes = returnList; return nodeObj; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitF_And(XGrammarParser.F_AndContext ctx) { ArrayList og = new ArrayList<>(nodeObj.validNodes); ArrayList nodes0 = visit(ctx.f(0)).validNodes; nodeObj.validNodes = og; ArrayList nodes1 = visit(ctx.f(1)).validNodes; ArrayList result = new ArrayList<>(); for (Node node : nodes0) { if (nodes1.contains(node)) { result.add(node); } } nodeObj.validNodes = result; return nodeObj; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitF_Rp(XGrammarParser.F_RpContext ctx) { ArrayList og = new ArrayList<>(nodeObj.validNodes); ArrayList wl = visit(ctx.rp()).validNodes; if (!wl.isEmpty()) { nodeObj.validNodes = og; } else { nodeObj.validNodes = new ArrayList<>(); } return nodeObj; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitF_Eq(XGrammarParser.F_EqContext ctx) { // Need to test this method --> test cases don't have an example of this query ArrayList og = new ArrayList<>(nodeObj.validNodes); ArrayList returnList = new ArrayList<>(); for (Node ogNode : og) { nodeObj.validNodes = new ArrayList<>(); nodeObj.validNodes.add(ogNode); ArrayList op1 = visit(ctx.rp(0)).validNodes; nodeObj.validNodes = new ArrayList<>(); nodeObj.validNodes.add(ogNode); ArrayList op2 = visit(ctx.rp(1)).validNodes; for (Node node1 : op1) { for (Node node2: op2) { if (node1.isEqualNode(node2)) { returnList.add(ogNode); break; } } } } nodeObj.validNodes = returnList; return nodeObj; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitF_Is(XGrammarParser.F_IsContext ctx) { ArrayList og = new ArrayList<>(nodeObj.validNodes); ArrayList returnList = new ArrayList<>(); for (Node ogNode : og) { nodeObj.validNodes = new ArrayList<>(); nodeObj.validNodes.add(ogNode); ArrayList op1 = visit(ctx.rp(0)).validNodes; nodeObj.validNodes = new ArrayList<>(); nodeObj.validNodes.add(ogNode); ArrayList op2 = visit(ctx.rp(1)).validNodes; for (Node node1 : op1) { for (Node node2: op2) { if (node1.isSameNode(node2)) { returnList.add(ogNode); break; } } } } nodeObj.validNodes = returnList; return nodeObj; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitDoc(XGrammarParser.DocContext ctx) { //System.out.println("Visited filename and assuming its valid " + ctx.getText()); try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); String filename = " "; if (ctx.getText().contains("doc(")) { //System.out.println(ctx.getText().substring(5, (ctx.getText().length() - 2))); filename = ctx.getText().substring(5, (ctx.getText().length() - 2)); } if (ctx.getText().contains("document(")){ //System.out.println(ctx.getText().substring(10, (ctx.getText().length()-2))); filename = ctx.getText().substring(10, (ctx.getText().length() - 2)); } //System.out.println(ctx.getText().split("./" + "[\"']")[1]); //System.out.println("Reading file: " + filename); Document doc = db.parse(new File("./", filename)); doc.getDocumentElement().normalize(); if (nodeObj == null){ //nested flwr statement (don't replace var bindings) nodeObj = new NodeContainer(doc); } else{ //keep the current var bindings, but clear out the //nodeObj.validNodes.clear(); //nodeObj.validNodes.add(doc); nodeObj.validNodes = new ArrayList<>(Arrays.asList(doc)); } //System.out.println("Root Element " + doc.getFirstChild().getNodeName()); //NodeList nl = doc.getElementsByTagName("ACT"); return nodeObj; } catch (ParserConfigurationException | SAXException | IOException e) { e.printStackTrace(); } return new NodeContainer(); } public NodeContainer removeDuplicates(NodeContainer nodeContainer) { Set set = new LinkedHashSet<>(nodeContainer.validNodes); nodeContainer.validNodes = new ArrayList<>(set); //nodeContainer.validNodes.clear(); //nodeContainer.validNodes.addAll(set); return nodeContainer; } public ArrayList removeDuplicates(ArrayList nodes) { Set set = new LinkedHashSet<>(nodes); return new ArrayList<>(set); } //XQuery Evaluation Implementations /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitXq_Const(XGrammarParser.Xq_ConstContext ctx) { //edit //creates a new text node and node container object with string const as text node data and returns String varName = ctx.STRINGCONST().getText(); varName = varName.substring(1, varName.length()-1); //ignore quotes NodeContainer toReturn = new NodeContainer(); if (nodeObj == null) { DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = null; try { docBuilder = docFactory.newDocumentBuilder(); } catch (ParserConfigurationException e) { throw new RuntimeException(e); } Document doc = docBuilder.newDocument(); Node textNode = doc.createTextNode(varName); toReturn.addElement(textNode); } else{ nodeObj.rootDoc.setXmlStandalone(true); Node textNode = nodeObj.rootDoc.createTextNode(varName); toReturn.addElement(textNode); } return toReturn; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitXp_Par(XGrammarParser.Xp_ParContext ctx) { return visit(ctx.xq()); } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitXq_Dslash(XGrammarParser.Xq_DslashContext ctx) { //get any constructed nodes or return nodes (singular node values not added to nodeObj already) - examples of this are all Xqueries minus return statements where nodeObj is actually updated nodeObj.validNodes = visit(ctx.xq()).validNodes; nodeObj.iterativeAddAll(); visit(ctx.rp()); //performs functionality on nodeObj itself return removeDuplicates(nodeObj); } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitXq_Concat(XGrammarParser.Xq_ConcatContext ctx) { ArrayList og = new ArrayList<>(); if (nodeObj != null) { og = nodeObj.validNodes; } NodeContainer rp1 = visit(ctx.xq(0)); //visit with current node object state ArrayList rp1List = new ArrayList(rp1.validNodes); // Since nodes that were added to validNodes from the first operand shouldn't be considered for the second operand nodeObj.validNodes = og; NodeContainer rp2 = visit(ctx.xq(1)); //visit with current node object state ArrayList rp2List = new ArrayList(rp2.validNodes); rp1List.addAll(rp2List); nodeObj.validNodes = rp1List; return removeDuplicates(nodeObj); } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitXq_Ap(XGrammarParser.Xq_ApContext ctx) { visit(ctx.ap()); return removeDuplicates(nodeObj); } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitXq_Slash(XGrammarParser.Xq_SlashContext ctx) { nodeObj.validNodes = visit(ctx.xq()).validNodes; visit(ctx.rp()); return removeDuplicates(nodeObj); } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitXq_Var(XGrammarParser.Xq_VarContext ctx) { NodeContainer nodeContainer = new NodeContainer(); ArrayList getList = new ArrayList<>(); String varName = ctx.VAR().getText(); if (nodeObj.varBindings.containsKey(varName)) { getList = nodeObj.varBindings.get(varName); } else{ System.out.println(varName); throw new RuntimeException("Invalid Var Name"); } nodeContainer.validNodes = getList; return nodeContainer; } //DFS recursive helper public ArrayList forHelper(XGrammarParser.Xq_FLWRContext ctx, ArrayList combinedResults, int nestIndex, int nestDepth) { //base case if (nestIndex >= nestDepth){ //if the index of the current nested index is out of bounds, perform current return on current indices if (ctx.letClause() != null){ visit(ctx.letClause()); //only updates nodeObj varBindings } if (ctx.whereClause() != null){ NodeContainer whereContainer = visit(ctx.whereClause()); //filters based on where condition if (whereContainer.validNodes.size() == 0) { //skip return return combinedResults; } } combinedResults.addAll(visit(ctx.returnClause()).validNodes); return combinedResults; } String varName = ctx.forClause().VAR(nestIndex).getText(); //current variable to be moved and updated ArrayList toTraverse = new ArrayList<>(visit(ctx.forClause().xq(nestIndex)).validNodes); //evaluating xq at the position and copy the list for (Node aNode: toTraverse) { ArrayList arrayList = new ArrayList<>(); arrayList.add(aNode); nodeObj.varBindings.put(varName, arrayList); //will replace any prior set value combinedResults = forHelper(ctx, combinedResults, nestIndex + 1, nestDepth); } return combinedResults; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitXq_FLWR(XGrammarParser.Xq_FLWRContext ctx) { /* Generate a node list which: alters the binding at each nested loop iterator (for var_1 in Xq_1, for var_2 in XQ_2 ....) then let assigns more variables (this may be entire lists) evaluate where clause then evaluate the return statement where you are familiar with the previous n+k variables */ //NodeContainer iteratorLists = visit(ctx.forClause()); //get all the iterator lists // NodeContainer nodeContainer = new NodeContainer(); // HashMap> context0 = new HashMap<>(); if (nodeObj != null) { context0 = nodeObj.varBindings; //save current scope } ArrayList toAdd = new ArrayList<>(); ArrayList toReturn = new ArrayList<>(); int nestDepth = ctx.forClause().VAR().size(); //total number of nested for loops int nestIndex = 0; toReturn = forHelper(ctx, toAdd, nestIndex, nestDepth); nodeObj.validNodes = toReturn; nodeObj.varBindings = context0; //NodeContainer nodeContainer = new NodeContainer(); //nodeContainer.validNodes = toReturn; return nodeObj; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ //will every possible case of a constructed node at some point be a final node? - Double check this @Override public NodeContainer visitXq_Tag(XGrammarParser.Xq_TagContext ctx) { NodeContainer nodeContainer = visit(ctx.xq()); //first visit xq then build // nodeObj.validNodes.addAll(nodeContainer.validNodes); nodeObj.validNodes = removeDuplicates(nodeContainer).validNodes; // nodeObj.validNodes = nodeContainer.validNodes; //TODO: CHECK String tagName = ctx.TAGNAME(0).getText(); Node elementNode; if (nodeObj != null) { nodeObj.rootDoc.setXmlStandalone(true); elementNode = nodeObj.rootDoc.createElement(tagName); } else{ //elementNode = nodeObj.rootDoc.createElement(tagName); DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = null; try { docBuilder = docFactory.newDocumentBuilder(); } catch (ParserConfigurationException e) { throw new RuntimeException(e); } Document doc = docBuilder.newDocument(); elementNode = doc.createTextNode(tagName); } for (Node node: nodeObj.validNodes){ if (node != null) { elementNode.appendChild(nodeObj.rootDoc.importNode(node, true)); //append deep copy of node } } NodeContainer toReturn = new NodeContainer(); toReturn.addElement(elementNode); return toReturn; } @Override public NodeContainer visitXq_Tag2(XGrammarParser.Xq_Tag2Context ctx) { NodeContainer nodeContainer = visit(ctx.xq()); //first visit xq then build // nodeObj.validNodes.addAll(nodeContainer.validNodes); nodeObj.validNodes = removeDuplicates(nodeContainer).validNodes; // nodeObj.validNodes = nodeContainer.validNodes; //TODO: CHECK String tagName = ctx.TAGNAME(0).getText(); Node elementNode; if (nodeObj != null) { nodeObj.rootDoc.setXmlStandalone(true); elementNode = nodeObj.rootDoc.createElement(tagName); } else{ //elementNode = nodeObj.rootDoc.createElement(tagName); DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = null; try { docBuilder = docFactory.newDocumentBuilder(); } catch (ParserConfigurationException e) { throw new RuntimeException(e); } Document doc = docBuilder.newDocument(); elementNode = doc.createTextNode(tagName); } for (Node node: nodeObj.validNodes){ if (node != null) { elementNode.appendChild(nodeObj.rootDoc.importNode(node, true)); //append deep copy of node } } NodeContainer toReturn = new NodeContainer(); toReturn.addElement(elementNode); return toReturn; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitXq_Let(XGrammarParser.Xq_LetContext ctx) { HashMap> ogVarBindings = new HashMap<>(); if (nodeObj != null) { ogVarBindings = nodeObj.varBindings; } NodeContainer letContainer = visit(ctx.letClause()); nodeObj.validNodes = letContainer.validNodes; NodeContainer returned = visit(ctx.xq()); nodeObj.varBindings = ogVarBindings; return returned; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitForClause(XGrammarParser.ForClauseContext ctx) { /* NodeContainer iteratorLists = new NodeContainer(); int varCount = ctx.VAR().size(); //collects lists of all the iterators for (int i = 0; i < varCount; i++){ NodeContainer visited = visit(ctx.xq(i)); iteratorLists.varBindings.put(ctx.VAR(i).getText(), visited.validNodes); //overwrite any previous bindings } return iteratorLists; */ return visitChildren(ctx); } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitLetClause(XGrammarParser.LetClauseContext ctx) { //start with original context //then for each variable bind the result of the xquery and add to the prior context int varCount = ctx.VAR().size(); for (int i = 0; i < varCount; i++){ NodeContainer visited = visit(ctx.xq(i)); nodeObj.varBindings.put(ctx.VAR(i).getText(), visited.validNodes); //any same key name will be overwritten // if (nodeObj.varBindings.containsKey(ctx.VAR(i).getText())) // throw new RuntimeException("Duplicate variable names found, please use unique variable names"); // else } return nodeObj; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitWhereClause(XGrammarParser.WhereClauseContext ctx) { return visit(ctx.cond()); } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitReturnClause(XGrammarParser.ReturnClauseContext ctx) { // NodeContainer returned = new NodeContainer(visit(ctx.xq())); // return returned; return visit(ctx.xq()); } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitCond_And(XGrammarParser.Cond_AndContext ctx) { ArrayList og = new ArrayList<>(); if (nodeObj != null) { og = nodeObj.validNodes; } //ArrayList og = new ArrayList<>(nodeObj.validNodes); ArrayList nodes0 = visit(ctx.cond(0)).validNodes; nodeObj.validNodes = og; ArrayList nodes1 = visit(ctx.cond(1)).validNodes; ArrayList result = new ArrayList<>(); for (Node node : nodes0) { if (nodes1.contains(node)) { result.add(node); } } //nodeObj.validNodes = result; NodeContainer toReturn = new NodeContainer(); toReturn.validNodes = result; return toReturn; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitCond_Eq(XGrammarParser.Cond_EqContext ctx) { ArrayList og = new ArrayList<>(); if (nodeObj != null) { og = nodeObj.validNodes; } //ArrayList og = new ArrayList<>(nodeObj.validNodes); ArrayList returnList = new ArrayList<>(); for (Node ogNode : og) { nodeObj.validNodes = new ArrayList<>(); nodeObj.validNodes.add(ogNode); ArrayList op1 = visit(ctx.xq(0)).validNodes; nodeObj.validNodes = new ArrayList<>(); nodeObj.validNodes.add(ogNode); ArrayList op2 = visit(ctx.xq(1)).validNodes; for (Node node1 : op1) { for (Node node2 : op2) { if (node1.isEqualNode(node2)) { returnList.add(ogNode); } // The following branch if uncommented will support // equalities of the form node = "string" else if (node1.getTextContent().equals(node2.getTextContent())) { returnList.add(ogNode); } } } } NodeContainer toReturn = new NodeContainer(); toReturn.validNodes = returnList; return toReturn; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitCond_Is(XGrammarParser.Cond_IsContext ctx) { ArrayList og = new ArrayList<>(); if (nodeObj != null) { og = nodeObj.validNodes; } // ArrayList og = new ArrayList<>(nodeObj.validNodes); ArrayList returnList = new ArrayList<>(); for (Node ogNode : og) { nodeObj.validNodes = new ArrayList<>(); nodeObj.validNodes.add(ogNode); ArrayList op1 = visit(ctx.xq(0)).validNodes; nodeObj.validNodes = new ArrayList<>(); nodeObj.validNodes.add(ogNode); ArrayList op2 = visit(ctx.xq(1)).validNodes; for (Node node1 : op1) { for (Node node2: op2) { if (node1.isSameNode(node2)) { returnList.add(ogNode); break; } } } } //nodeObj.validNodes = returnList; NodeContainer toReturn = new NodeContainer(); toReturn.validNodes = returnList; return toReturn; } public ArrayList someHelper(XGrammarParser.Cond_SomeContext ctx, ArrayList combinedResults, int nestIndex, int nestDepth) { if (nestIndex >= nestDepth) { // Recurrence termination condition NodeContainer conditionResult = visit(ctx.cond()); if (conditionResult.validNodes.size() > 0) { combinedResults.addAll(conditionResult.validNodes); } return combinedResults; } String varName = ctx.VAR(nestIndex).getText(); //current variable to be moved and updated ArrayList toTraverse = new ArrayList<>(visit(ctx.xq(nestIndex)).validNodes); //evaluating xq at the position and copy the list for (Node aNode: toTraverse) { ArrayList arrayList = new ArrayList<>(); arrayList.add(aNode); nodeObj.varBindings.put(varName, arrayList); //will replace any prior set value combinedResults = someHelper(ctx, combinedResults, nestIndex + 1, nestDepth); } return combinedResults; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitCond_Some(XGrammarParser.Cond_SomeContext ctx) { HashMap> ogVarBindings = new HashMap<>(); if (nodeObj != null) { ogVarBindings = nodeObj.varBindings; } ArrayList toAdd = new ArrayList<>(); ArrayList toReturn = new ArrayList<>(); int nestDepth = ctx.VAR().size(); //total number of nested for loops int nestIndex = 0; toReturn = someHelper(ctx, toAdd, nestIndex, nestDepth); NodeContainer returnContainer = new NodeContainer(); returnContainer.validNodes = toReturn; nodeObj.varBindings = ogVarBindings; return returnContainer; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitCond_Not(XGrammarParser.Cond_NotContext ctx) { ArrayList og = new ArrayList<>(); if (nodeObj != null) { og = nodeObj.validNodes; } //ArrayList og = new ArrayList<>(nodeObj.validNodes); ArrayList nodes = visit(ctx.cond()).validNodes; og.removeAll(nodes); // nodeObj.validNodes = new ArrayList<>(og); NodeContainer toReturn = new NodeContainer(); toReturn.validNodes = og; return toReturn; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitCond_Par(XGrammarParser.Cond_ParContext ctx) { return visit(ctx.cond()); } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitCond_Empty(XGrammarParser.Cond_EmptyContext ctx) { // ToDo: Untested method --> test logic too ArrayList og = new ArrayList<>(); if (nodeObj != null) { og = nodeObj.validNodes; } //ArrayList og = new ArrayList<>(nodeObj.validNodes); ArrayList nodes = visit(ctx.xq()).validNodes; ArrayList resultNodes = new ArrayList<>(); for (Node node: og) { nodeObj.validNodes = new ArrayList<>(); nodeObj.validNodes.add(node); if (visit(ctx.xq()).validNodes.isEmpty()) resultNodes.add(node); } NodeContainer toReturn = new NodeContainer(); toReturn.validNodes = resultNodes; return toReturn; } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ @Override public NodeContainer visitCond_Or(XGrammarParser.Cond_OrContext ctx) { ArrayList og = new ArrayList<>(); if (nodeObj != null) { og = nodeObj.validNodes; } ArrayList evalFilter = visit(ctx.cond(0)).validNodes; nodeObj.validNodes = og; evalFilter.addAll(visit(ctx.cond(1)).validNodes); evalFilter = removeDuplicates(evalFilter); NodeContainer toReturn = new NodeContainer(); toReturn.validNodes = evalFilter; return toReturn; } @Override public NodeContainer visitXq_Join(XGrammarParser.Xq_JoinContext ctx) { NodeContainer returnContainer = new NodeContainer(); NodeContainer visited = visit(ctx.join()); ArrayList ogValidNodes = new ArrayList<>(nodeObj.validNodes); for (Node node: visited.validNodes) { nodeObj.validNodes = new ArrayList<>(); nodeObj.validNodes.add(node); nodeObj.varBindings.put(ctx.VAR().getText(), nodeObj.validNodes); NodeContainer interim = visit(ctx.returnClause()); returnContainer.validNodes.addAll(interim.validNodes); } nodeObj.validNodes = ogValidNodes; nodeObj.varBindings.put(ctx.VAR().getText(), returnContainer.validNodes); return returnContainer; } @Override public NodeContainer visitAttrList(XGrammarParser.AttrListContext ctx) { NodeContainer newAttrContainer = new NodeContainer(nodeObj); newAttrContainer.attrList = new ArrayList<>(); int noOfAttrs = ctx.TAGNAME().size(); for (int i = 0; i < noOfAttrs; i++) { newAttrContainer.attrList.add(ctx.TAGNAME().get(i).getText()); } return newAttrContainer; } public ArrayList xqJoinHelper(XGrammarParser.XqJoinContext ctx, ArrayList combinedResults, int nestIndex, int nestDepth) { //base case if (nestIndex >= nestDepth){ //if the index of the current nested index is out of bounds, perform current return on current indices // The grammar file specifies * wildcard but there can only be 1 where keyword // Hence defaulting to index 0 if (ctx.whereClause() != null){ NodeContainer whereContainer = visit(ctx.whereClause()); //filters based on where condition if (whereContainer.validNodes.size() == 0) { //skip return return combinedResults; } } combinedResults.addAll(visit(ctx.returnClause()).validNodes); return combinedResults; } String varName = ctx.forClause().VAR(nestIndex).getText(); //current variable to be moved and updated ArrayList toTraverse = new ArrayList<>(visit(ctx.forClause().xq(nestIndex)).validNodes); //evaluating xq at the position and copy the list for (Node aNode: toTraverse) { ArrayList arrayList = new ArrayList<>(); arrayList.add(aNode); nodeObj.varBindings.put(varName, arrayList); //will replace any prior set value combinedResults = xqJoinHelper(ctx, combinedResults, nestIndex + 1, nestDepth); } return combinedResults; } @Override public NodeContainer visitXqJoin(XGrammarParser.XqJoinContext ctx) { //System.out.println("Entered xqjoin"); // Base case HashMap> context0 = new HashMap<>(); if (nodeObj != null) { context0 = nodeObj.varBindings; //save current scope } ArrayList toAdd = new ArrayList<>(); ArrayList toReturn = new ArrayList<>(); int nestDepth = ctx.forClause().VAR().size(); //total number of nested for loops int nestIndex = 0; toReturn = xqJoinHelper(ctx, toAdd, nestIndex, nestDepth); nodeObj.validNodes = toReturn; nodeObj.varBindings = context0; //NodeContainer nodeContainer = new NodeContainer(); //nodeContainer.validNodes = toReturn; return nodeObj; } @Override public NodeContainer visitJoin(XGrammarParser.JoinContext ctx) { // System.out.println("Entering join method"); ArrayList ogValidNodes; if (nodeObj != null) { ogValidNodes = new ArrayList<>(nodeObj.validNodes); } else { ogValidNodes = new ArrayList<>(); } ArrayList joinTuples = new ArrayList<>(); ArrayList> ats = new ArrayList<>(); int atListCtr = 0; for (int i=0; i 2) throw new RuntimeException("Unhandled case: More that 2 attribute lists passed"); ArrayList leftAttrList = ats.get(0); ArrayList rightAttrList = ats.get(1); ArrayList joinResults = new ArrayList<>(); if (sizeOfLeftTable < sizeOfRightTable) { // Hash on left table attrs joinResults = performJoin(joinTuples.get(0), joinTuples.get(1), leftAttrList, rightAttrList); } else { // Hash on right table attrs, swap the order joinResults = performJoin(joinTuples.get(1), joinTuples.get(0), rightAttrList, leftAttrList); } NodeContainer resultContainer = new NodeContainer(); resultContainer.validNodes = joinResults; // return resultContainer; nodeObj.validNodes = ogValidNodes; // nodeObj.validNodes = joinResults; return resultContainer; } public ArrayList performJoin(NodeContainer leftResults, NodeContainer rightResults, ArrayList leftAttrList, ArrayList rightAttrList) { ArrayList joinResults = new ArrayList<>(); // Create hashmap on attrList for the first table HashMap> hashIndex = new HashMap<>(); for (Node node: leftResults.validNodes) { // Hash value key ArrayList indexVals = createHash(node, leftAttrList); // add to the index if (hashIndex.containsKey(indexVals.toString())) // Handle hash collisions hashIndex.get(indexVals.toString()).add(node); else { ArrayList indexArrList = new ArrayList<>(); indexArrList.add(node); hashIndex.put(indexVals.toString(), indexArrList); } } // Now perform join --> join right table with left based on hash for (Node node: rightResults.validNodes) { ArrayList indexVals = createHash(node, rightAttrList); // System.out.println(boom++ + " " + indexVals); if (hashIndex.containsKey(indexVals.toString())) { // hash match // child elements from left table --> fetch from hash map // --> this could be a list of elements for (Node matchedNode: hashIndex.get(indexVals.toString())) { Element joinedElement = nodeObj.rootDoc.createElement(node.getNodeName()); NodeList leftChildren = matchedNode.getChildNodes(); for (int i = 0; i < leftChildren.getLength(); ++i) { joinedElement.appendChild(leftChildren.item(i).cloneNode(true)); } // Now fetch elements from the right table NodeList rightChildren = node.getChildNodes(); for (int i = 0; i < rightChildren.getLength(); i++) { joinedElement.appendChild(rightChildren.item(i).cloneNode(true)); } joinResults.add(joinedElement); } } } // System.out.println(joinResults.stream().map(Node::getTextContent).collect(Collectors.toList())); return joinResults; } public ArrayList createHash(Node node, ArrayList attrList) { // analogy: columns of a tuple NodeList childNodes = node.getChildNodes(); // fetch values of columns that matches the join attr // This map will store node names and text content, so that we can // choose which columns will form the index // Needed since we need to maintain order based on leftAttrs HashMap attrMap = new HashMap<>(); for (int i = 0; i < childNodes.getLength(); i++) { if (attrList.contains(childNodes.item(i).getNodeName())) { // Nodename, value attrMap.put(childNodes.item(i).getNodeName(), childNodes.item(i).getTextContent()); } // // Nodename, value // attrMap.put(childNodes.item(i).getNodeName(), childNodes.item(i).getTextContent()); } // This entire list will form the index value for the current tuple ArrayList indexVals = new ArrayList<>(); for (String attr: attrList) { indexVals.add(attrMap.get(attr)); } return indexVals; } @Override public NodeContainer visitJoin_concat(XGrammarParser.Join_concatContext ctx) { // this is a return clause case // Copy of xq_concat ArrayList og = new ArrayList<>(); if (nodeObj != null) { og = nodeObj.validNodes; } NodeContainer rp1 = visit(ctx.returnClauseJoin(0)); //visit with current node object state ArrayList rp1List = new ArrayList(rp1.validNodes); // Since nodes that were added to validNodes from the first operand shouldn't be considered for the second operand nodeObj.validNodes = og; NodeContainer rp2 = visit(ctx.returnClauseJoin(1)); //visit with current node object state ArrayList rp2List = new ArrayList(rp2.validNodes); rp1List.addAll(rp2List); nodeObj.validNodes = rp1List; return removeDuplicates(nodeObj); } @Override public NodeContainer visitJoin_tag_no_constr(XGrammarParser.Join_tag_no_constrContext ctx) { // This is a join return clause case // copy of xq_tag NodeContainer nodeContainer = visit(ctx.returnClauseJoin()); //first visit xq then build // nodeObj.validNodes.addAll(nodeContainer.validNodes); nodeObj.validNodes = removeDuplicates(nodeContainer).validNodes; // nodeObj.validNodes = nodeContainer.validNodes; //TODO: CHECK String tagName = ctx.TAGNAME(0).getText(); Node elementNode; if (nodeObj != null) { nodeObj.rootDoc.setXmlStandalone(true); elementNode = nodeObj.rootDoc.createElement(tagName); } else{ //elementNode = nodeObj.rootDoc.createElement(tagName); DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = null; try { docBuilder = docFactory.newDocumentBuilder(); } catch (ParserConfigurationException e) { throw new RuntimeException(e); } Document doc = docBuilder.newDocument(); elementNode = doc.createTextNode(tagName); } for (Node node: nodeObj.validNodes){ if (node != null) { elementNode.appendChild(nodeObj.rootDoc.importNode(node, true)); //append deep copy of node } } NodeContainer toReturn = new NodeContainer(); toReturn.addElement(elementNode); return toReturn; } @Override public NodeContainer visitJoin_tag_constr(XGrammarParser.Join_tag_constrContext ctx) { // This is a return clause case // copy of xq_tag NodeContainer nodeContainer = visit(ctx.returnClauseJoin()); //first visit xq then build // nodeObj.validNodes.addAll(nodeContainer.validNodes); nodeObj.validNodes = removeDuplicates(nodeContainer).validNodes; // nodeObj.validNodes = nodeContainer.validNodes; //TODO: CHECK String tagName = ctx.TAGNAME(0).getText(); Node elementNode; if (nodeObj != null) { nodeObj.rootDoc.setXmlStandalone(true); elementNode = nodeObj.rootDoc.createElement(tagName); } else{ //elementNode = nodeObj.rootDoc.createElement(tagName); DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = null; try { docBuilder = docFactory.newDocumentBuilder(); } catch (ParserConfigurationException e) { throw new RuntimeException(e); } Document doc = docBuilder.newDocument(); elementNode = doc.createTextNode(tagName); } for (Node node: nodeObj.validNodes){ if (node != null) { elementNode.appendChild(nodeObj.rootDoc.importNode(node, true)); //append deep copy of node } } NodeContainer toReturn = new NodeContainer(); toReturn.addElement(elementNode); return toReturn; } @Override public NodeContainer visitJoin_ap(XGrammarParser.Join_apContext ctx) { // This is a join return clause case // copy of xq_ap visit(ctx.ap()); return removeDuplicates(nodeObj); } @Override public NodeContainer visitJoin_return(XGrammarParser.Join_returnContext ctx) { // This is a join return clause case // copy of xq_var NodeContainer nodeContainer = new NodeContainer(); ArrayList getList = new ArrayList<>(); String varName = ctx.VAR().getText(); if (nodeObj.varBindings.containsKey(varName)) { getList = nodeObj.varBindings.get(varName); } else{ System.out.println(varName); throw new RuntimeException("Invalid Var Name"); } nodeContainer.validNodes = getList; return nodeContainer; } @Override public NodeContainer visitJoin_cond_var_eq(XGrammarParser.Join_cond_var_eqContext ctx) { // copy of cond_eq ArrayList og = new ArrayList<>(); if (nodeObj != null) { og = nodeObj.validNodes; } //ArrayList og = new ArrayList<>(nodeObj.validNodes); ArrayList returnList = new ArrayList<>(); for (Node ogNode : og) { nodeObj.validNodes = new ArrayList<>(); nodeObj.validNodes.add(ogNode); // Logic from xq_var ArrayList op1 = new ArrayList<>(); String varName1 = ctx.VAR(0).getText(); if (nodeObj.varBindings.containsKey(varName1)) { op1 = nodeObj.varBindings.get(varName1); } else{ System.out.println(varName1); throw new RuntimeException("Invalid Var Name"); } nodeObj.validNodes = new ArrayList<>(); nodeObj.validNodes.add(ogNode); // Logic from xq_var ArrayList op2 = new ArrayList<>(); String varName2 = ctx.VAR(1).getText(); if (nodeObj.varBindings.containsKey(varName2)) { op2 = nodeObj.varBindings.get(varName2); } else{ System.out.println(varName2); throw new RuntimeException("Invalid Var Name"); } for (Node node1 : op1) { for (Node node2 : op2) { if (node1.isEqualNode(node2)) { returnList.add(ogNode); } } } } NodeContainer toReturn = new NodeContainer(); toReturn.validNodes = returnList; return toReturn; } @Override public NodeContainer visitJoin_cond_var_const_eq(XGrammarParser.Join_cond_var_const_eqContext ctx) { // copy of cond_eq ArrayList og = new ArrayList<>(); if (nodeObj != null) { og = nodeObj.validNodes; } //ArrayList og = new ArrayList<>(nodeObj.validNodes); ArrayList returnList = new ArrayList<>(); for (Node ogNode : og) { nodeObj.validNodes = new ArrayList<>(); nodeObj.validNodes.add(ogNode); // Logic from xq_var ArrayList op1 = new ArrayList<>(); String varName1 = ctx.VAR().getText(); if (nodeObj.varBindings.containsKey(varName1)) { op1 = nodeObj.varBindings.get(varName1); } else{ System.out.println(varName1); throw new RuntimeException("Invalid Var Name"); } nodeObj.validNodes = new ArrayList<>(); nodeObj.validNodes.add(ogNode); String varName2 = ctx.STRINGCONST().getText(); varName2 = varName2.substring(1, varName2.length()-1); //ignore quotes for (Node node1 : op1) { if (node1.getTextContent().equals(varName2)) { returnList.add(ogNode); } } } NodeContainer toReturn = new NodeContainer(); toReturn.validNodes = returnList; return toReturn; } @Override public NodeContainer visitJoin_cond_const_eq(XGrammarParser.Join_cond_const_eqContext ctx) { // copy of cond_eq ArrayList og = new ArrayList<>(); if (nodeObj != null) { og = nodeObj.validNodes; } //ArrayList og = new ArrayList<>(nodeObj.validNodes); ArrayList returnList = new ArrayList<>(); for (Node ogNode : og) { String varName1 = ctx.STRINGCONST(0).getText(); varName1 = varName1.substring(1, varName1.length()-1); //ignore quotes String varName2 = ctx.STRINGCONST(1).getText(); varName2 = varName2.substring(1, varName2.length()-1); //ignore quotes if (varName1.equals(varName2)) { returnList.add(ogNode); } } NodeContainer toReturn = new NodeContainer(); toReturn.validNodes = returnList; return toReturn; } @Override public NodeContainer visitJoin_cond_and(XGrammarParser.Join_cond_andContext ctx) { // copy of cond_and ArrayList og = new ArrayList<>(); if (nodeObj != null) { og = nodeObj.validNodes; } //ArrayList og = new ArrayList<>(nodeObj.validNodes); ArrayList nodes0 = visit(ctx.condClauseJoin(0)).validNodes; nodeObj.validNodes = og; ArrayList nodes1 = visit(ctx.condClauseJoin(1)).validNodes; ArrayList result = new ArrayList<>(); for (Node node : nodes0) { if (nodes1.contains(node)) { result.add(node); } } //nodeObj.validNodes = result; NodeContainer toReturn = new NodeContainer(); toReturn.validNodes = result; return toReturn; } }