Search in sources :

Example 1 with ParameterNode

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;
}
Also used : Symbol(org.datanucleus.query.compiler.Symbol) Node(org.datanucleus.query.compiler.Node) ParameterNode(org.datanucleus.query.compiler.ParameterNode) ArrayList(java.util.ArrayList) ParameterNode(org.datanucleus.query.compiler.ParameterNode) QueryCompilerSyntaxException(org.datanucleus.store.query.QueryCompilerSyntaxException) ArrayList(java.util.ArrayList) List(java.util.List)

Aggregations

ArrayList (java.util.ArrayList)1 List (java.util.List)1 Node (org.datanucleus.query.compiler.Node)1 ParameterNode (org.datanucleus.query.compiler.ParameterNode)1 Symbol (org.datanucleus.query.compiler.Symbol)1 QueryCompilerSyntaxException (org.datanucleus.store.query.QueryCompilerSyntaxException)1