use of org.datanucleus.query.compiler.ParameterNode in project datanucleus-core by datanucleus.
the class ExpressionCompiler method compilePrimaryExpression.
private Expression compilePrimaryExpression(Node node) {
if (node.getNodeType() == NodeType.PRIMARY) {
Node currentNode = node.getFirstChild();
Node invokeNode = node.getNextChild();
if (invokeNode.getNodeType() != NodeType.INVOKE) {
// TODO Support more combinations
throw new QueryCompilerSyntaxException("Dont support compilation of " + node);
}
Expression currentExpr = compileExpression(currentNode);
String methodName = (String) invokeNode.getNodeValue();
List<Expression> parameterExprs = getExpressionsForPropertiesOfNode(invokeNode);
Expression invokeExpr = new InvokeExpression(currentExpr, methodName, parameterExprs);
return invokeExpr;
} else if (node.getNodeType() == NodeType.IDENTIFIER) {
Node currentNode = node;
List tupple = new ArrayList();
Expression currentExpr = null;
while (currentNode != null) {
tupple.add(currentNode.getNodeValue());
if (currentNode.getNodeType() == NodeType.INVOKE) {
if (currentExpr == null && tupple.size() > 1) {
// Check for starting with parameter/variable
String first = (String) tupple.get(0);
Symbol firstSym = symtbl.getSymbol(first);
if (firstSym != null) {
if (firstSym.getType() == Symbol.PARAMETER) {
currentExpr = new ParameterExpression(first, -1);
if (tupple.size() > 2) {
currentExpr = new PrimaryExpression(currentExpr, tupple.subList(1, tupple.size() - 1));
}
} else if (firstSym.getType() == Symbol.VARIABLE) {
currentExpr = new VariableExpression(first);
if (tupple.size() > 2) {
currentExpr = new PrimaryExpression(currentExpr, tupple.subList(1, tupple.size() - 1));
}
}
}
if (currentExpr == null) {
currentExpr = new PrimaryExpression(tupple.subList(0, tupple.size() - 1));
}
} else if (currentExpr != null && tupple.size() > 1) {
currentExpr = new PrimaryExpression(currentExpr, tupple.subList(0, tupple.size() - 1));
}
String methodName = (String) tupple.get(tupple.size() - 1);
if (currentExpr instanceof PrimaryExpression) {
// Check if this is a defined method prefix, and if so use the alias
String id = ((PrimaryExpression) currentExpr).getId();
if (aliasByPrefix != null && aliasByPrefix.containsKey(id)) {
String alias = aliasByPrefix.get(id);
methodName = alias + "." + methodName;
currentExpr = null;
}
}
List<Expression> parameterExprs = getExpressionsForPropertiesOfNode(currentNode);
currentExpr = new InvokeExpression(currentExpr, methodName, parameterExprs);
currentNode = currentNode.getFirstChild();
tupple = new ArrayList();
} else if (currentNode.getNodeType() == NodeType.CAST) {
if (currentExpr == null && tupple.size() > 1) {
// Start from PrimaryExpression and invoke on that
currentExpr = new PrimaryExpression(tupple.subList(0, tupple.size() - 1));
PrimaryExpression primExpr = (PrimaryExpression) currentExpr;
if (primExpr.tuples.size() == 1) {
Symbol sym = symtbl.getSymbol(primExpr.getId());
if (sym != null) {
if (sym.getType() == Symbol.PARAMETER) {
// Parameter symbol registered for this identifier so use ParameterExpression
currentExpr = new ParameterExpression(primExpr.getId(), -1);
} else if (sym.getType() == Symbol.VARIABLE) {
// Variable symbol registered for this identifier so use VariableExpression
currentExpr = new VariableExpression(primExpr.getId());
}
}
}
}
String className = (String) tupple.get(tupple.size() - 1);
currentExpr = new DyadicExpression(currentExpr, Expression.OP_CAST, new Literal(className));
currentNode = currentNode.getFirstChild();
tupple = new ArrayList();
} else {
// Part of identifier chain
currentNode = currentNode.getFirstChild();
}
}
if (currentExpr != null && !tupple.isEmpty()) {
// We have a trailing identifier expression e.g "((B)a).c" where we have a CastExpression and trailing "c"
currentExpr = new PrimaryExpression(currentExpr, tupple);
}
if (currentExpr == null) {
// Find type of first of tupples
String first = (String) tupple.get(0);
Symbol firstSym = symtbl.getSymbol(first);
if (firstSym != null) {
// TODO If the user has a field in the candidate the same name as a parameter and they just put the name (rather than "this.{name}") then it interprets as parameter
if (firstSym.getType() == Symbol.PARAMETER) {
ParameterExpression paramExpr = new ParameterExpression(first, -1);
if (tupple.size() > 1) {
currentExpr = new PrimaryExpression(paramExpr, tupple.subList(1, tupple.size()));
} else {
currentExpr = paramExpr;
}
} else if (firstSym.getType() == Symbol.VARIABLE) {
VariableExpression varExpr = new VariableExpression(first);
if (tupple.size() > 1) {
currentExpr = new PrimaryExpression(varExpr, tupple.subList(1, tupple.size()));
} else {
currentExpr = varExpr;
}
} else {
currentExpr = new PrimaryExpression(tupple);
}
} else {
currentExpr = new PrimaryExpression(tupple);
}
}
return currentExpr;
} else if (node.getNodeType() == NodeType.PARAMETER) {
// "{paramExpr}", "{paramExpr}.invoke(...)", "{paramExpr}.invoke(...).invoke(...)"
Object val = node.getNodeValue();
Expression currentExpr = null;
if (val instanceof Integer) {
// Positional parameter TODO Store as Integer to avoid confusion
currentExpr = new ParameterExpression("" + node.getNodeValue(), ((ParameterNode) node).getPosition());
} else {
// Named parameter
currentExpr = new ParameterExpression((String) node.getNodeValue(), ((ParameterNode) node).getPosition());
}
Node childNode = node.getFirstChild();
while (childNode != null) {
if (childNode.getNodeType() == NodeType.INVOKE) {
String methodName = (String) childNode.getNodeValue();
List<Expression> parameterExprs = getExpressionsForPropertiesOfNode(childNode);
currentExpr = new InvokeExpression(currentExpr, methodName, parameterExprs);
} else if (childNode.getNodeType() == NodeType.IDENTIFIER) {
String identifier = childNode.getNodeId();
List tuples = new ArrayList();
tuples.add(identifier);
boolean moreIdentifierNodes = true;
while (moreIdentifierNodes) {
Node currentNode = childNode;
childNode = childNode.getFirstChild();
if (childNode == null || childNode.getNodeType() != NodeType.IDENTIFIER) {
moreIdentifierNodes = false;
childNode = currentNode;
} else {
// Add as a component of the primary
tuples.add(childNode.getNodeId());
}
}
currentExpr = new PrimaryExpression(currentExpr, tuples);
} else {
throw new QueryCompilerSyntaxException("Dont support compilation of " + node);
}
childNode = childNode.getFirstChild();
}
return currentExpr;
} else if (node.getNodeType() == NodeType.INVOKE) {
Node currentNode = node;
List tupple = new ArrayList();
Expression currentExpr = null;
while (currentNode != null) {
tupple.add(currentNode.getNodeValue());
if (currentNode.getNodeType() == NodeType.INVOKE) {
String methodName = (String) tupple.get(tupple.size() - 1);
List<Expression> parameterExprs = getExpressionsForPropertiesOfNode(currentNode);
currentExpr = new InvokeExpression(currentExpr, methodName, parameterExprs);
currentNode = currentNode.getFirstChild();
if (currentNode != null) {
// Continue on along the chain
tupple = new ArrayList();
// Start from this expression
tupple.add(currentExpr);
}
} else {
// TODO What node type is this that comes after an INVOKE?
currentNode = currentNode.getFirstChild();
}
}
return currentExpr;
} else if (node.getNodeType() == NodeType.CREATOR) {
Node currentNode = node.getFirstChild();
List tupple = new ArrayList();
boolean method = false;
while (currentNode != null) {
tupple.add(currentNode.getNodeValue());
if (currentNode.getNodeType() == NodeType.INVOKE) {
method = true;
break;
}
currentNode = currentNode.getFirstChild();
}
List<Expression> parameterExprs = null;
if (method) {
parameterExprs = getExpressionsForPropertiesOfNode(currentNode);
} else {
parameterExprs = new ArrayList();
}
return new CreatorExpression(tupple, parameterExprs);
} else if (node.getNodeType() == NodeType.LITERAL) {
Node currentNode = node;
List tupple = new ArrayList();
Expression currentExpr = null;
while (currentNode != null) {
tupple.add(currentNode.getNodeValue());
if (currentNode.getNodeType() == NodeType.INVOKE) {
if (currentExpr == null && tupple.size() > 1) {
// Start from Literal and invoke on that
currentExpr = new Literal(node.getNodeValue());
}
String methodName = (String) tupple.get(tupple.size() - 1);
List<Expression> parameterExprs = getExpressionsForPropertiesOfNode(currentNode);
currentExpr = new InvokeExpression(currentExpr, methodName, parameterExprs);
currentNode = currentNode.getFirstChild();
tupple = new ArrayList();
} else {
currentNode = currentNode.getFirstChild();
}
}
if (currentExpr == null) {
currentExpr = new Literal(node.getNodeValue());
}
return currentExpr;
} else if (node.getNodeType() == NodeType.ARRAY) {
Node currentNode = node;
List<Node> arrayElements = (List<Node>) node.getNodeValue();
// Check if this is an array literal
boolean literal = true;
Class type = null;
Iterator<Node> iter = arrayElements.iterator();
while (iter.hasNext()) {
Node element = iter.next();
if (type == null) {
type = element.getNodeValue().getClass();
}
if (element.getNodeType() == NodeType.IDENTIFIER) {
literal = false;
break;
}
}
Expression currentExpr = null;
if (literal) {
Object array = Array.newInstance(type, arrayElements.size());
iter = arrayElements.iterator();
int index = 0;
while (iter.hasNext()) {
Node element = iter.next();
Array.set(array, index++, element.getNodeValue());
}
currentExpr = new Literal(array);
} else {
Expression[] arrayElementExprs = new Expression[arrayElements.size()];
for (int i = 0; i < arrayElementExprs.length; i++) {
arrayElementExprs[i] = compilePrimaryExpression(arrayElements.get(i));
}
currentExpr = new ArrayExpression(arrayElementExprs);
}
currentNode = currentNode.getFirstChild();
List tupple = new ArrayList();
while (currentNode != null) {
tupple.add(currentNode.getNodeValue());
if (currentNode.getNodeType() == NodeType.INVOKE) {
if (tupple.size() > 1) {
// Start from Literal and invoke on that
currentExpr = new Literal(node.getNodeValue());
}
String methodName = (String) tupple.get(tupple.size() - 1);
List<Expression> parameterExprs = getExpressionsForPropertiesOfNode(currentNode);
currentExpr = new InvokeExpression(currentExpr, methodName, parameterExprs);
currentNode = currentNode.getFirstChild();
tupple = new ArrayList();
} else {
currentNode = currentNode.getFirstChild();
}
}
return currentExpr;
} else if (node.getNodeType() == NodeType.SUBQUERY) {
List children = node.getChildNodes();
if (children.size() != 1) {
throw new QueryCompilerSyntaxException("Invalid number of children for SUBQUERY node : " + node);
}
Node varNode = (Node) children.get(0);
VariableExpression subqueryExpr = new VariableExpression(varNode.getNodeId());
Expression currentExpr = new SubqueryExpression((String) node.getNodeValue(), subqueryExpr);
return currentExpr;
} else if (node.getNodeType() == NodeType.CASE) {
// Node with children in the order "when", "action"[, "when", "action"], "else"
List<Node> children = node.getChildNodes();
if ((children.size() % 2) == 0) {
throw new QueryCompilerSyntaxException("Invalid number of children for CASE node (should be odd). Have you omitted the ELSE clause? : " + node);
}
Node elseNode = children.get(children.size() - 1);
Expression elseExpr = compileExpression(elseNode);
CaseExpression caseExpr = new CaseExpression();
Iterator<Node> childIter = children.iterator();
while (childIter.hasNext()) {
Node whenNode = childIter.next();
if (childIter.hasNext()) {
Node actionNode = childIter.next();
Expression whenExpr = compileExpression(whenNode);
Expression actionExpr = compileExpression(actionNode);
caseExpr.addCondition(whenExpr, actionExpr);
}
}
caseExpr.setElseExpression(elseExpr);
return caseExpr;
} else if (node.getNodeType() == NodeType.TYPE) {
List<Node> children = node.getChildNodes();
Expression containedExpr = compileExpression(children.get(0));
TypeExpression typeExpr = new TypeExpression(containedExpr);
return typeExpr;
} else {
NucleusLogger.QUERY.warn("ExpressionCompiler.compilePrimaryExpression node=" + node + " ignored by ExpressionCompiler since not of a supported type");
}
return null;
}
Aggregations