Commit 43d8e333 authored by Georg Fette's avatar Georg Fette
Browse files

...

parent f4a51c90
......@@ -8,12 +8,12 @@ import org.antlr.v4.runtime.tree.ParseTreeListener;
*/
public interface AqlListener extends ParseTreeListener {
/**
* Enter a parse tree produced by {@link AqlParser#root}.
* Enter a parse tree produced by {@link AqlParser#query}.
* @param ctx the parse tree
*/
void enterQuery(AqlParser.QueryContext ctx);
/**
* Exit a parse tree produced by {@link AqlParser#root}.
* Exit a parse tree produced by {@link AqlParser#query}.
* @param ctx the parse tree
*/
void exitQuery(AqlParser.QueryContext ctx);
......
......@@ -11,7 +11,7 @@ import org.antlr.v4.runtime.tree.ParseTreeVisitor;
*/
public interface AqlVisitor<T> extends ParseTreeVisitor<T> {
/**
* Visit a parse tree produced by {@link AqlParser#root}.
* Visit a parse tree produced by {@link AqlParser#query}.
* @param ctx the parse tree
* @return the visitor result
*/
......
......@@ -131,19 +131,25 @@ public class CQL_2_Graph_Mapper extends System_2_Graph_Mapper {
public QueryOperator parse(String aQueryString) throws IOException {
clear();
ExpressionContext e = parseWithAntlr(aQueryString);
currentOp = root;
currentOp = query;
parseExpression(e);
addLeafConceptOpsToReturn();
return root;
return query;
}
private void addLeafConceptOpsToReturn() {
if (root.getParameters().size() == 1) {
if (query.getParameters().size() == 1) {
QueryOperator returnOp = addOp(OperatorType.RETURN);
Expression firstOp = root.getParameters().get(0);
String alias = availableAliasNames.get(0);
firstOp.alias = alias;
availableAliasNames.remove(alias);
List<QueryOperator> iteratorsRecursive = query.getIteratorsRecursive();
QueryOperator firstConc = iteratorsRecursive.get(0);
String alias;
if (firstConc.alias == null) {
alias = availableAliasNames.get(0);
firstConc.alias = alias;
availableAliasNames.remove(alias);
} else {
alias = firstConc.alias;
}
QueryOperator aliasRef = addOp(OperatorType.ALIAS_REF);
aliasRef.addParameter(alias);
}
......@@ -214,7 +220,7 @@ public class CQL_2_Graph_Mapper extends System_2_Graph_Mapper {
TermExpressionContext te = (TermExpressionContext) returnClause.expression();
TermExpressionTermContext tet = (TermExpressionTermContext) te.expressionTerm();
TermContext term = tet.term();
List<Expression> formerReturns = new ArrayList<Expression>(root.getParameters());
List<Expression> formerReturns = new ArrayList<Expression>(query.getParameters());
if (term instanceof TupleSelectorTermContext) {
TupleSelectorTermContext tst = (TupleSelectorTermContext) term;
TupleSelectorContext tupleSelector = tst.tupleSelector();
......@@ -231,7 +237,7 @@ public class CQL_2_Graph_Mapper extends System_2_Graph_Mapper {
throw new RuntimeException("unexpected");
}
for (Expression anExp : formerReturns) {
root.removeParameter(anExp);
query.removeParameter(anExp);
}
}
......@@ -244,7 +250,7 @@ public class CQL_2_Graph_Mapper extends System_2_Graph_Mapper {
if (lastCreatedOp != null) {
lastCreatedOp.outputName = text;
} else if (lastPathElem != null) {
root.addParameter(lastPathElem);
query.addParameter(lastPathElem);
lastPathElem.outputName = text;
} else {
throw new RuntimeException("unexpected");
......@@ -362,7 +368,6 @@ public class CQL_2_Graph_Mapper extends System_2_Graph_Mapper {
private QueryOperator parseExpression(ExpressionContext anExp) {
String prettyPrint = prettyPrint(anExp);
boolean cacheParsingReturnRoot = parsingReturnRoot;
parsingReturnRoot = false;
QueryOperator createdOp;
if (anExp instanceof InequalityExpressionContext) {
......@@ -738,7 +743,7 @@ public class CQL_2_Graph_Mapper extends System_2_Graph_Mapper {
if (parsingRetrieveClause) {
// all parts of the returns always start with the first root concept
QueryOperator aliasRef = new QueryOperator(OperatorType.ALIAS_REF);
QueryOperator firstRootConcept = root.getFirstRootConcept();
QueryOperator firstRootConcept = query.getFirstRootConcept();
aliasRef.addParameter(firstRootConcept.alias);
lastPathElem = aliasRef;
} else {
......@@ -856,8 +861,8 @@ public class CQL_2_Graph_Mapper extends System_2_Graph_Mapper {
throw new RuntimeException("unexpected");
}
}
QueryOperator aChildConcept = new QueryOperator(currentOp, lastPathElem, text);
currentOp.removeParameter(lastPathElem);
QueryOperator aChildConcept = new QueryOperator(currentOp, lastPathElem, text);
lastPathElem = aChildConcept;
return aChildConcept;
}
......
......@@ -65,7 +65,9 @@ public class Graph_2_CQL_Mapper extends Graph_2_System_Mapper {
result = writeExpr(expression);
QueryOperator returnOp = aQuery.getParameters().get(1).asOperator();
String writeReturn = writeReturn(returnOp);
result += writeReturn;
if (!writeReturn.isEmpty()) {
result += " " + writeReturn;
}
return result.trim();
}
......@@ -100,7 +102,7 @@ public class Graph_2_CQL_Mapper extends Graph_2_System_Mapper {
QueryOperator firstReturnOp = firstReturnParam.asOperator();
if (firstReturnOp.type == OperatorType.ALIAS_REF) {
String alias = firstReturnOp.getParameters().get(0).asPrimitive().value;
if (alias.equals(root.getParameters().get(0).alias)) {
if (alias.equals(query.getIteratorsRecursive().get(0).alias)) {
return "";
}
}
......@@ -145,7 +147,7 @@ public class Graph_2_CQL_Mapper extends Graph_2_System_Mapper {
List<QueryOperator> alreadyMentionedConcepts) {
alreadyMentionedConcepts.add(aConc);
List<QueryOperator> result = new ArrayList<QueryOperator>();
List<QueryOperator> allOps = root.getOpsRecursive();
List<QueryOperator> allOps = query.getOpsRecursive();
for (QueryOperator anOp : allOps) {
Set<QueryOperator> aliasRoots = aliasRoots(anOp.getIteratorsRecursive());
if (alreadyMentionedConcepts.containsAll(aliasRoots)) {
......
......@@ -10,7 +10,7 @@ public abstract class Graph_2_System_Mapper extends Mapper {
protected void initialize(QueryOperator aQuery) {
initialize();
this.root = aQuery;
this.query = aQuery;
checkErrors();
}
......@@ -19,7 +19,7 @@ public abstract class Graph_2_System_Mapper extends Mapper {
}
protected void checkOperators() {
for (QueryOperator anOp : root.getOpsRecursive()) {
for (QueryOperator anOp : query.getOpsRecursive()) {
opMap.getOpString(anOp.type);
}
}
......
......@@ -2,7 +2,7 @@ package de.uniwue.query;
public class Mapper {
protected QueryOperator root;
protected QueryOperator query;
protected OperatorMap opMap = new OperatorMap();
......@@ -19,7 +19,7 @@ public class Mapper {
protected QueryOperator addOp(OperatorType aType) {
if (currentOp == null) {
currentOp = new QueryOperator(aType);
root.addParameter(currentOp);
query.addParameter(currentOp);
} else {
currentOp = new QueryOperator(currentOp, aType);
}
......@@ -46,7 +46,7 @@ public class Mapper {
protected void clear() {
currentOp = null;
lastPathElem = null;
root = new QueryOperator(OperatorType.QUERY);
query = new QueryOperator(OperatorType.QUERY);
}
public static void initializeStdOpMappings(OperatorMap opMap) {
......
......@@ -96,6 +96,27 @@ public class QueryOperator extends Expression {
return result;
}
public void checkConsistency() {
if ((parent != null) && !parent.getParameters().contains(this)) {
throw new RuntimeException("parent does not contain me");
}
if (type == OperatorType.ALIAS_REF) {
String alias = getParameters().get(0).asPrimitive().value;
boolean aliasExists = false;
for (QueryOperator anOp : getRoot().getOpsRecursive()) {
if ((anOp.alias != null) && anOp.alias.equals(alias)) {
aliasExists = true;
}
}
if (!aliasExists) {
throw new RuntimeException("ALIAS_REF has no matching alias");
}
}
for (QueryOperator anOp : getOperators()) {
anOp.checkConsistency();
}
}
public List<Expression> getParameters() {
return new ArrayList<Expression>(parameters);
}
......
......@@ -360,7 +360,7 @@ public class Graph_2_Cypher_Mapper extends Graph_2_System_Mapper {
String result = "";
boolean first = true;
boolean containsComparator = false;
for (QueryOperator aClause : root.getOpsRecursive()) {
for (QueryOperator aClause : query.getOpsRecursive()) {
if (compOps.contains(aClause.type)) {
containsComparator = true;
}
......@@ -368,7 +368,7 @@ public class Graph_2_Cypher_Mapper extends Graph_2_System_Mapper {
if (!containsComparator) {
return result;
}
for (Expression anExp : root.getParameters()) {
for (Expression anExp : query.getParameters()) {
if (first) {
result = result + " WHERE ";
first = false;
......@@ -413,7 +413,7 @@ public class Graph_2_Cypher_Mapper extends Graph_2_System_Mapper {
private String writeMatch() {
String result = "MATCH ";
boolean first = true;
for (QueryOperator aConc : root.getRootConcepts()) {
for (QueryOperator aConc : query.getRootConcepts()) {
if (first) {
first = false;
} else {
......@@ -449,7 +449,7 @@ public class Graph_2_Cypher_Mapper extends Graph_2_System_Mapper {
String opAlias = aliasNames[aliasIndex++];
aliases.put(anOp, opAlias);
result += " AS " + opAlias;
for (QueryOperator aConc : root.getIteratorsRecursive()) {
for (QueryOperator aConc : query.getIteratorsRecursive()) {
// if (aConc.includeInResult) {
if (aliases.containsKey(aConc) && !notToAggregateConcets.contains(aConc)) {
String returnAlias = aliases.get(aConc);
......@@ -491,7 +491,7 @@ public class Graph_2_Cypher_Mapper extends Graph_2_System_Mapper {
aliases.put(anOp, opAlias);
result += " AS " + opAlias;
for (QueryOperator aConc : root.getIteratorsRecursive()) {
for (QueryOperator aConc : query.getIteratorsRecursive()) {
if (aliases.containsKey(aConc)) {
String returnAlias = aliases.get(aConc);
result += ", " + returnAlias;
......@@ -506,7 +506,7 @@ public class Graph_2_Cypher_Mapper extends Graph_2_System_Mapper {
private String writeWith() {
String result = "";
List<QueryOperator> operatorsRecursive = root.getOpsRecursive();
List<QueryOperator> operatorsRecursive = query.getOpsRecursive();
Collections.reverse(operatorsRecursive);
for (QueryOperator anOp : operatorsRecursive) {
if (aggrOps.contains(anOp.type)) {
......
......@@ -2,8 +2,10 @@ package de.uniwue.query.i2b2;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLStreamException;
......@@ -32,6 +34,9 @@ public class Graph_2_I2B2_Mapper extends Graph_2_System_Mapper {
protected static String VALUE_CODE = "value";
private Set<String> systemCodes = new HashSet<String>(
Arrays.asList(new String[] { PATIENT_CODE, ENCOUNTER_CODE, INSTANCE_CODE, VALUE_CODE }));
private int currentPanelIndex;
private RequestedLevel globalRequestLevel = RequestedLevel.ANY;
......@@ -56,7 +61,7 @@ public class Graph_2_I2B2_Mapper extends Graph_2_System_Mapper {
}
private QueryOperator getRoot() {
return root.getRootConcepts().get(0);
return query.getRootConcepts().get(0);
}
protected void checkErrors() {
......@@ -68,7 +73,7 @@ public class Graph_2_I2B2_Mapper extends Graph_2_System_Mapper {
}
private void checkNestingOfBooleanClauses() {
for (Expression anExpr : root.getParameters()) {
for (Expression anExpr : query.getParameters()) {
QueryOperator anOp = (QueryOperator) anExpr;
if (!anOp.isBooleanOp()) {
continue;
......@@ -134,7 +139,7 @@ public class Graph_2_I2B2_Mapper extends Graph_2_System_Mapper {
protected void checkOperators() {
super.checkOperators();
for (QueryOperator anOp : root.getOpsRecursive()) {
for (QueryOperator anOp : query.getOpsRecursive()) {
if (!anOp.isBooleanOp()) {
if (anOp.type == OperatorType.BETWEEN) {
if (anOp.getParameters().size() != 3) {
......@@ -241,10 +246,9 @@ public class Graph_2_I2B2_Mapper extends Graph_2_System_Mapper {
return RequestedLevel.ANY;
}
private void addPanel(Element queryDef, List<QueryOperator> anOrClause, int panelIndex)
throws XMLStreamException {
private void addPanel(Element queryDef, List<QueryOperator> anOrClause, int panelIndex,
RequestedLevel requestLevel) throws XMLStreamException {
Element panel = addElem(queryDef, "panel");
RequestedLevel requestLevel = getRequestedLevel(anOrClause);
boolean negated = false;
// if (anOp.type == OperatorType.NOT) {
// negated = true;
......@@ -256,34 +260,50 @@ public class Graph_2_I2B2_Mapper extends Graph_2_System_Mapper {
}
}
private List<List<QueryOperator>> getOredOps(QueryOperator rootFilter) {
private List<List<QueryOperator>> getOredOps(QueryOperator filter) {
QueryOperator clause = filter.getParameters().get(1).asOperator();
List<List<QueryOperator>> oredOps = new ArrayList<List<QueryOperator>>();
if (rootFilter.type == OperatorType.AND) {
for (QueryOperator anOredClause : rootFilter.getOperators()) {
if (clause.type == OperatorType.AND) {
for (QueryOperator anOredClause : clause.getOperators()) {
List<QueryOperator> orList = new ArrayList<QueryOperator>();
orList.add(anOredClause);
oredOps.add(orList);
}
} else if (rootFilter.type == OperatorType.OR) {
oredOps.add(rootFilter.getOperators());
} else if (rootFilter.type == OperatorType.NOT) {
oredOps = getOredOps(rootFilter.getParameters().get(0).asOperator());
} else if (clause.type == OperatorType.OR) {
oredOps.add(clause.getOperators());
} else if (clause.type == OperatorType.NOT) {
oredOps = getOredOps(clause.getParameters().get(0).asOperator());
throw new RuntimeException("not yet implemented");
} else {
// an non boolean operator
List<QueryOperator> orList = new ArrayList<QueryOperator>();
orList.add(rootFilter);
oredOps.add(orList);
String code = clause.getParameters().get(0).asOperator().getIteratorSelector();
if (!systemCodes.contains(code)) {
// an non boolean operator when it is no iterator
List<QueryOperator> orList = new ArrayList<QueryOperator>();
orList.add(clause);
oredOps.add(orList);
}
}
return oredOps;
}
private void addPanels(Element queryDef) throws XMLStreamException {
QueryOperator rootFilter = root.getParameters().get(0).asOperator().getParameters().get(1)
.asOperator();
List<List<QueryOperator>> andWithOrs = getOredOps(rootFilter);
private void addPanels(Element queryDef, QueryOperator filter, RequestedLevel aLevel)
throws XMLStreamException {
List<List<QueryOperator>> andWithOrs = getOredOps(filter);
for (List<QueryOperator> anOrClause : andWithOrs) {
addPanel(queryDef, anOrClause, currentPanelIndex++);
addPanel(queryDef, anOrClause, currentPanelIndex++, aLevel);
}
}
private void addPanels(Element queryDef) throws XMLStreamException {
List<QueryOperator> patients = query.getIteratorsWithSelector(PATIENT_CODE);
addPanels(queryDef, patients.get(0).parent, RequestedLevel.ANY);
List<QueryOperator> encounters = query.getIteratorsWithSelector(ENCOUNTER_CODE);
if (encounters.size() > 0) {
addPanels(queryDef, encounters.get(0).parent, RequestedLevel.SAMEVISIT);
}
List<QueryOperator> instances = query.getIteratorsWithSelector(INSTANCE_CODE);
if (instances.size() > 0) {
addPanels(queryDef, instances.get(0).parent, RequestedLevel.SAMEINSTANCENUM);
}
}
......
......@@ -36,6 +36,7 @@ public class I2B2_2_Graph_Mapper extends Mapper {
super.clear();
patient = null;
encounter = null;
aliasIndex = 0;
}
private String prettyPrint(Element anElem) {
......@@ -43,7 +44,9 @@ public class I2B2_2_Graph_Mapper extends Mapper {
}
private void parsePanels(Element queryDef) {
String prettyPrint = prettyPrint(queryDef);
List<Element> panels = queryDef.getChildren("panel");
if (panels.size() > 1) {
addOp(OperatorType.AND);
}
......@@ -53,6 +56,7 @@ public class I2B2_2_Graph_Mapper extends Mapper {
}
private void parsePanel(Element aPanelElem) {
String prettyPrint = prettyPrint(aPanelElem);
QueryOperator lastOp = currentOp;
String panelTiming = aPanelElem.getChild("panel_timing").getText();
QueryOperator concept;
......@@ -62,7 +66,7 @@ public class I2B2_2_Graph_Mapper extends Mapper {
concept = getEncounter();
} else if (panelTiming.equals("SAMEINSTANCENUM")) {
// TODO
throw new RuntimeException("not implemented");
throw new RuntimeException("not yet implemented");
} else {
throw new RuntimeException("Unknown timing");
}
......@@ -111,6 +115,7 @@ public class I2B2_2_Graph_Mapper extends Mapper {
}
private void parseConstrainByValue(Element valueConstraint, QueryOperator constrainedConcept) {
String prettyPrint = prettyPrint(valueConstraint);
QueryOperator valueConcept = new QueryOperator(constrainedConcept.parent, constrainedConcept, "value", true);
currentOp = valueConcept;
String valueType = valueConstraint.getChildText("value_type");
......@@ -148,7 +153,11 @@ public class I2B2_2_Graph_Mapper extends Mapper {
private QueryOperator getEncounter() {
if (encounter == null) {
encounter = new QueryOperator(patient, Graph_2_I2B2_Mapper.ENCOUNTER_CODE);
currentOp = patient.parent;
QueryOperator exists = addOp(OperatorType.EXISTS);
encounter = new QueryOperator(exists, patient, Graph_2_I2B2_Mapper.ENCOUNTER_CODE, true);
String alias = aliasNames[aliasIndex++];
encounter.alias = alias;
}
return encounter;
}
......@@ -164,11 +173,11 @@ public class I2B2_2_Graph_Mapper extends Mapper {
Element rootElement = xmlDoc.getRootElement();
Element queryDef = rootElement.getChild("query_definition");
parsePanels(queryDef);
currentOp = root;
currentOp = query;
QueryOperator returnOp = addOp(OperatorType.RETURN);
QueryOperator aliasRef = addOp(OperatorType.ALIAS_REF);
aliasRef.addParameter("e");
return root;
return query;
}
}
......@@ -100,15 +100,15 @@ public class AQL_2_Graph_Mapper extends System_2_Graph_Mapper {
throw new ParseException("Errors while parsing AQL", 0);
}
String prettyPrint = prettyPrint(parseTree);
currentOp = root;
currentOp = query;
visitQueryExpr(parseTree);
moveClausesToOutmostEncapsulatingClauses();
removeUnnecessaryANDs();
return root;
return query;
}
private void moveClausesToOutmostEncapsulatingClauses() {
List<QueryOperator> exists = root.getOpsRecursiveWithType(OperatorType.EXISTS);
List<QueryOperator> exists = query.getOpsRecursiveWithType(OperatorType.EXISTS);
// move first the innermost, then proceed to the outer ones
exists = Lists.reverse(exists);
for (QueryOperator anExist : exists) {
......@@ -157,19 +157,20 @@ public class AQL_2_Graph_Mapper extends System_2_Graph_Mapper {
for (QueryOperator aChild : aFilter.getOpsRecursive()) {
usedAliases.remove(aChild.alias);
}
QueryOperator targetClause = getOutmostClauseDefiningAllAliases(usedAliases, root);
QueryOperator targetClause = getOutmostClauseDefiningAllAliases(usedAliases, query);
if (targetClause == null) {
throw new RuntimeException("there always has to be a match");
}
QueryOperator nearestFilter = getNearestFilter(aFilter);
if (nearestFilter != targetClause) {
aFilter.parent.removeParameter(aFilter);
if ((targetClause.getParameters().size() > 1)
&& (targetClause.getParameters().get(1).asOperator().type != OperatorType.AND)) {
currentOp = targetClause.getParameters().get(1).asOperator();
targetClause = insertOp(OperatorType.AND);
if (targetClause.getParameters().size() > 1) {
currentOp = targetClause.getParameters().get(1).asOperator();
if (currentOp.type != OperatorType.AND) {
targetClause = insertOp(OperatorType.AND);
}
}
targetClause.addParameter(aFilter);
currentOp.addParameter(aFilter);
}
}
......@@ -182,7 +183,7 @@ public class AQL_2_Graph_Mapper extends System_2_Graph_Mapper {
}
private void removeUnnecessaryANDs() {
for (QueryOperator anAnd : root.getOpsRecursiveWithType(OperatorType.AND)) {
for (QueryOperator anAnd : query.getOpsRecursiveWithType(OperatorType.AND)) {
if (anAnd.getParameters().size() == 1) {
anAnd.parent.addParameter(anAnd.getParameters().get(0));
anAnd.parent.removeParameter(anAnd);
......@@ -659,7 +660,7 @@ public class AQL_2_Graph_Mapper extends System_2_Graph_Mapper {
private void visitWhere(WhereContext ctx) {
String prettyPrint = prettyPrint(ctx);
currentOp = getInnermostAggregatorWithAliasedIterator(root);
currentOp = getInnermostAggregatorWithAliasedIterator(query);
IdentifiedExprContext identifiedExpr = ctx.identifiedExpr();
if (identifiedExpr != null) {
visitIdentifiedExpr(identifiedExpr);
......@@ -670,7 +671,7 @@ public class AQL_2_Graph_Mapper extends System_2_Graph_Mapper {
private void visitSelect(SelectContext ctx) {
String prettyPrint = prettyPrint(ctx);
currentOp = root;
currentOp = query;
addOp(OperatorType.RETURN);
TopExprContext topExpr = ctx.topExpr();
if (topExpr != null) {
......
......@@ -47,7 +47,7 @@ public class Graph_2_AQL_Mapper extends Graph_2_System_Mapper {
}
private void checkSortParams() {
for (Expression anExp : root.getParameters()) {
for (Expression anExp : query.getParameters()) {
QueryOperator anOp = (QueryOperator) anExp;
if (anOp.type == OperatorType.SORT) {
if (anOp.getParameters().size() > 1) {
......@@ -61,7 +61,7 @@ public class Graph_2_AQL_Mapper extends Graph_2_System_Mapper {
}
private void checkIntervalsOnlyOnDate() {
for (QueryOperator anOp : root.getOpsRecursive()) {
for (QueryOperator anOp : query.getOpsRecursive()) {
if (anOp.type == OperatorType.INTERVAL) {
for (Expression aParam : anOp.getParameters()) {
if (!aParam.isPrimitive()
......@@ -115,7 +115,7 @@ public class Graph_2_AQL_Mapper extends Graph_2_System_Mapper {
String result = "";
result += "SELECT ";
boolean first = true;
QueryOperator returnOp = root.getParameters().get(1).asOperator();
QueryOperator returnOp = query.getParameters().get(1).asOperator();
for (Expression anExp : returnOp.getParameters()) {
if (anExp.isOperator()) {
QueryOperator anOp = anExp.asOperator();
......@@ -147,7 +147,7 @@ public class Graph_2_AQL_Mapper extends Graph_2_System_Mapper {
private String getFrom() {
String result = "FROM ";
QueryOperator rootFilter = root.getParameters().get(0).asOperator();
QueryOperator rootFilter = query.getParameters().get(0).asOperator();
String nestedFrom = getFromNested(rootFilter, 1);
result += nestedFrom;
return result;
......@@ -213,8 +213,8 @@ public class Graph_2_AQL_Mapper extends Graph_2_System_Mapper {
private String getWhere() {
String result = "";
// removed nested exists because they are already handled by their containing operators
List<QueryOperator> exists = root.getOpsRecursiveWithType(OperatorType.EXISTS);
exists.addAll(root.getOpsRecursiveWithType(OperatorType.FILTER));
List<