All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.cayenne.exp.parser.SimpleNode Maven / Gradle / Ivy

There is a newer version: 4.2.1
Show newest version
/* Generated By:JJTree: Do not edit this line. SimpleNode.java */

/*****************************************************************
 *   Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 ****************************************************************/

package org.apache.cayenne.exp.parser;

import java.io.PrintWriter;
import java.util.Collections;
import java.util.Map;

import org.apache.cayenne.ObjectId;
import org.apache.cayenne.Persistent;
import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.exp.ExpressionException;
import org.apache.cayenne.util.Util;

/**
 * Superclass of AST* expressions that implements Node interface defined by JavaCC
 * framework.
 * 

* Some parts of the parser are based on OGNL parser, copyright (c) 2002, Drew Davidson * and Luke Blanshard. *

* * @since 1.1 */ public abstract class SimpleNode extends Expression implements Node { protected Node parent; protected Node[] children; protected int id; /** * Utility method that encodes an object that is not an expression Node to String. */ protected static void encodeScalarAsString( PrintWriter pw, Object scalar, char quoteChar) { boolean quote = scalar instanceof String; if (quote) { pw.print(quoteChar); } // encode only ObjectId for Persistent, ensure that the order of keys is // predictable.... // TODO: should we use UUID here? if (scalar instanceof Persistent) { ObjectId id = ((Persistent) scalar).getObjectId(); Object encode = (id != null) ? id : scalar; encodeAsEscapedString(pw, String.valueOf(encode)); } else if (scalar instanceof Enum) { Enum e = (Enum) scalar; pw.print("enum:"); pw.print(e.getClass().getName() + "." + e.name()); } else { encodeAsEscapedString(pw, String.valueOf(scalar)); } if (quote) { pw.print(quoteChar); } } /** * Utility method that prints a string to the provided PrintWriter, escaping special * characters. */ protected static void encodeAsEscapedString(PrintWriter pw, String source) { int len = source.length(); for (int i = 0; i < len; i++) { char c = source.charAt(i); switch (c) { case '\n': pw.print("\\n"); continue; case '\r': pw.print("\\r"); continue; case '\t': pw.print("\\t"); continue; case '\b': pw.print("\\b"); continue; case '\f': pw.print("\\f"); continue; case '\\': pw.print("\\\\"); continue; case '\'': pw.print("\\'"); continue; case '\"': pw.print("\\\""); continue; default: pw.print(c); } } } protected SimpleNode(int i) { id = i; } /** * Always returns empty map. * * @since 3.0 */ @Override public Map getPathAliases() { return Collections.emptyMap(); } protected abstract String getExpressionOperator(int index); /** * Returns operator for ebjql statements, which can differ for Cayenne expression * operator */ protected String getEJBQLExpressionOperator(int index) { return getExpressionOperator(index); } @Override protected boolean pruneNodeForPrunedChild(Object prunedChild) { return true; } /** * Implemented for backwards compatibility with exp package. */ @Override public String expName() { return ExpressionParserTreeConstants.jjtNodeName[id]; } /** * Flattens the tree under this node by eliminating any children that are of the same * class as this node and copying their children to this node. */ @Override protected void flattenTree() { boolean shouldFlatten = false; int newSize = 0; for (Node child : children) { if (child.getClass() == getClass()) { shouldFlatten = true; newSize += child.jjtGetNumChildren(); } else { newSize++; } } if (shouldFlatten) { Node[] newChildren = new Node[newSize]; int j = 0; for (Node c : children) { if (c.getClass() == getClass()) { for (int k = 0; k < c.jjtGetNumChildren(); ++k) { newChildren[j++] = c.jjtGetChild(k); } } else { newChildren[j++] = c; } } if (j != newSize) { throw new ExpressionException("Assertion error: " + j + " != " + newSize); } this.children = newChildren; } } @Override public void encodeAsString(PrintWriter pw) { if (parent != null) { pw.print("("); } if ((children != null) && (children.length > 0)) { for (int i = 0; i < children.length; ++i) { if (i > 0) { pw.print(' '); pw.print(getExpressionOperator(i)); pw.print(' '); } if (children[i] == null) { pw.print("null"); } else { ((SimpleNode) children[i]).encodeAsString(pw); } } } if (parent != null) { pw.print(')'); } } @Override public Object getOperand(int index) { Node child = jjtGetChild(index); // unwrap ASTScalar nodes - this is likely a temporary thing to keep it compatible // with QualifierTranslator. In the future we might want to keep scalar nodes // for the purpose of expression evaluation. return unwrapChild(child); } protected Node wrapChild(Object child) { // when child is null, there's no way of telling whether this is a scalar or // not... fuzzy... maybe we should stop using this method - it is too generic return (child instanceof Node || child == null) ? (Node) child : new ASTScalar( child); } protected Object unwrapChild(Node child) { return (child instanceof ASTScalar) ? ((ASTScalar) child).getValue() : child; } @Override public int getOperandCount() { return jjtGetNumChildren(); } @Override public void setOperand(int index, Object value) { Node node = (value == null || value instanceof Node) ? (Node) value : new ASTScalar(value); jjtAddChild(node, index); // set the parent, as jjtAddChild doesn't do it... if (node != null) { node.jjtSetParent(this); } } public void jjtOpen() { } public void jjtClose() { } public void jjtSetParent(Node n) { parent = n; } public Node jjtGetParent() { return parent; } public void jjtAddChild(Node n, int i) { if (children == null) { children = new Node[i + 1]; } else if (i >= children.length) { Node c[] = new Node[i + 1]; System.arraycopy(children, 0, c, 0, children.length); children = c; } children[i] = n; } public Node jjtGetChild(int i) { return children[i]; } public final int jjtGetNumChildren() { return (children == null) ? 0 : children.length; } /** * Evaluates itself with object, pushing result on the stack. */ protected abstract Object evaluateNode(Object o) throws Exception; /** * Sets the parent to this for all children. * * @since 3.0 */ protected void connectChildren() { if (children != null) { for (Node child : children) { // although nulls are expected to be wrapped in scalar, still doing a // check here to make it more robust if (child != null) { child.jjtSetParent(this); } } } } protected Object evaluateChild(int index, Object o) throws Exception { SimpleNode node = (SimpleNode) jjtGetChild(index); return node != null ? node.evaluate(o) : null; } @Override public Expression notExp() { return new ASTNot(this); } @Override public Object evaluate(Object o) { // wrap in try/catch to provide unified exception processing try { return evaluateNode(o); } catch (Throwable th) { String string = this.toString(); throw new ExpressionException( "Error evaluating expression '" + string + "'", string, Util.unwindException(th)); } } /** * @since 3.0 */ @Override public void encodeAsEJBQL(PrintWriter pw, String rootId) { if (parent != null) { pw.print("("); } if ((children != null) && (children.length > 0)) { encodeChildrenAsEJBQL(pw, rootId); } if (parent != null) { pw.print(')'); } } /** * Encodes child of this node with specified index to EJBQL */ protected void encodeChildrenAsEJBQL(PrintWriter pw, String rootId) { for (int i = 0; i < children.length; ++i) { if (i > 0) { pw.print(' '); pw.print(getEJBQLExpressionOperator(i)); pw.print(' '); } if (children[i] == null) { pw.print("null"); } else { ((SimpleNode) children[i]).encodeAsEJBQL(pw, rootId); } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy