| /* |
| * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| |
| // Contributors: |
| // Oracle - initial API and implementation from Oracle TopLink |
| package org.eclipse.persistence.internal.jpa.parsing; |
| |
| import org.eclipse.persistence.expressions.*; |
| import org.eclipse.persistence.mappings.DatabaseMapping; |
| import org.eclipse.persistence.queries.ObjectLevelReadQuery; |
| |
| /** |
| * INTERNAL |
| * <p><b>Purpose</b>: This is the superclass for all Nodes. |
| * <p><b>Responsibilities</b>:<ul> |
| * <li> Answer default answers for all method calls |
| * <li> Delegate most responsibilities to the sub-classes |
| * </ul> |
| * @author Jon Driscoll and Joel Lucuik |
| * @since TopLink 4.0 |
| */ |
| public class Node { |
| private int line; |
| private int column; |
| protected Node left = null; |
| protected Node right = null; |
| private Object type; |
| public boolean shouldGenerateExpression; |
| protected String alias = null; |
| |
| /** |
| * Return a new Node. |
| */ |
| public Node() { |
| super(); |
| } |
| |
| /** |
| * INTERNAL |
| * Apply this node to the passed query |
| */ |
| public void applyToQuery(ObjectLevelReadQuery theQuery, GenerationContext context) { |
| } |
| |
| /** |
| * INTERNAL |
| * Add my expression semantics to the parentExpression. Each subclass will add a different expression and |
| * thus will need to override this method |
| */ |
| public Expression addToExpression(Expression parentExpression, GenerationContext context) { |
| return parentExpression; |
| } |
| |
| /** |
| * INTERNAL |
| * Get the string representation of this node. |
| * By default return toString() |
| */ |
| public String getAsString() { |
| return toString(); |
| } |
| |
| /** |
| * INTERNAL |
| * Check the child node for an unqualified field access and if so, |
| * replace it by a qualified field access. |
| */ |
| public Node qualifyAttributeAccess(ParseTreeContext context) { |
| if (left != null) { |
| left = left.qualifyAttributeAccess(context); |
| } |
| if (right != null) { |
| right = right.qualifyAttributeAccess(context); |
| } |
| return this; |
| } |
| |
| /** |
| * INTERNAL |
| * Validate node and calculate its type. |
| */ |
| public void validate(ParseTreeContext context) { |
| // Nothing to be validated here, but delegate to the child nodes. |
| if (left != null) { |
| left.validate(context); |
| } |
| if (right != null) { |
| right.validate(context); |
| } |
| } |
| |
| /** |
| * INTERNAL |
| */ |
| public void validateParameter(ParseTreeContext context, Object contextType) { |
| // nothing to be done |
| } |
| |
| /** |
| * INTERNAL |
| * Generate an expression for the node. Each subclass will generate a different expression and |
| * thus will need to override this method |
| */ |
| public Expression generateExpression(GenerationContext context) { |
| return null; |
| } |
| |
| /** |
| * INTERNAL |
| * Return the left node |
| */ |
| public Node getLeft() { |
| return left; |
| } |
| |
| /** |
| * INTERNAL |
| * Return the right node |
| */ |
| public Node getRight() { |
| return right; |
| } |
| |
| /** |
| * INTERNAL |
| * Does this node have a left |
| */ |
| public boolean hasLeft() { |
| return getLeft() != null; |
| } |
| |
| /** |
| * INTERNAL |
| * Does this node have a right |
| */ |
| public boolean hasRight() { |
| return getRight() != null; |
| } |
| |
| /** |
| * INTERNAL |
| * Is this node an Aggregate node |
| */ |
| public boolean isAggregateNode() { |
| return false; |
| } |
| |
| /** |
| * INTERNAL |
| * Is this node a Dot node |
| */ |
| public boolean isDotNode() { |
| return false; |
| } |
| |
| /** |
| * INTERNAL |
| * Is this a literal node |
| */ |
| public boolean isLiteralNode() { |
| return false; |
| } |
| |
| /** |
| * INTERNAL |
| * Is this node a Multiply node |
| */ |
| public boolean isMultiplyNode() { |
| return false; |
| } |
| |
| /** |
| * INTERNAL |
| * Is this node a Not node |
| */ |
| public boolean isNotNode() { |
| return false; |
| } |
| |
| /** |
| * INTERNAL |
| * Is this a Parameter node |
| */ |
| public boolean isParameterNode() { |
| return false; |
| } |
| |
| /** |
| * INTERNAL |
| * Is this node a Divide node |
| */ |
| public boolean isDivideNode() { |
| return false; |
| } |
| |
| /** |
| * INTERNAL |
| * Is this node a Plus node |
| */ |
| public boolean isPlusNode() { |
| return false; |
| } |
| |
| /** |
| * INTERNAL |
| * Is this node a MapKey node |
| */ |
| public boolean isMapKeyNode() { |
| return false; |
| } |
| |
| /** |
| * INTERNAL |
| * Is this node a Minus node |
| */ |
| public boolean isMinusNode() { |
| return false; |
| } |
| |
| /** |
| * INTERNAL |
| * Is this node a VariableNode |
| */ |
| public boolean isVariableNode() { |
| return false; |
| } |
| |
| /** |
| * INTERNAL |
| * Is this node an AttributeNode |
| */ |
| public boolean isAttributeNode() { |
| return false; |
| } |
| |
| /** |
| * INTERNAL |
| * Is this node a CountNode |
| */ |
| public boolean isCountNode() { |
| return false; |
| } |
| |
| /** |
| * INTERNAL |
| * Is this node a ConstructorNode |
| */ |
| public boolean isConstructorNode() { |
| return false; |
| } |
| |
| /** |
| * INTERNAL |
| * Is this node a SubqueryNode |
| */ |
| public boolean isSubqueryNode() { |
| return false; |
| } |
| |
| /** |
| * INTERNAL |
| * Is this an escape node |
| */ |
| public boolean isEscape() { |
| return false;// no it is not |
| } |
| |
| /** |
| * resolveAttribute(): Answer the name of the attribute which is represented by the receiver. |
| * Subclasses should override this. |
| */ |
| public String resolveAttribute() { |
| return ""; |
| } |
| |
| /** |
| * resolveClass: Answer the class associated with the content of this node. Default is to return null. |
| * Subclasses should override this. |
| */ |
| public Class<?> resolveClass(GenerationContext context) { |
| return null; |
| } |
| |
| /** |
| * resolveClass: Answer the class associated with the content of this node. Default is to return null. |
| * Subclasses should override this. |
| */ |
| public Class<?> resolveClass(GenerationContext context, Class<?> ownerClass) { |
| return null; |
| } |
| |
| /** |
| * resolveMapping: Answer the mapping associated with the contained nodes. |
| * Subclasses should override this. |
| */ |
| public DatabaseMapping resolveMapping(GenerationContext context) { |
| return null; |
| } |
| |
| /** |
| * resolveMapping: Answer the mapping associated with the contained nodes. Use the provided |
| * class as the context. |
| * Subclasses should override this. |
| */ |
| public DatabaseMapping resolveMapping(GenerationContext context, Class<?> ownerClass) { |
| return null; |
| } |
| |
| /** |
| * INTERNAL |
| * Set the left node to the passed value |
| */ |
| public void setLeft(Node newLeft) { |
| left = newLeft; |
| } |
| |
| /** |
| * INTERNAL |
| * Set the right for this node |
| */ |
| public void setRight(Node newRight) { |
| right = newRight; |
| } |
| |
| public int getLine() { |
| return line; |
| } |
| |
| public void setLine(int line) { |
| this.line = line; |
| } |
| |
| public int getColumn() { |
| return column; |
| } |
| |
| public void setColumn(int column) { |
| this.column = column; |
| } |
| |
| /** |
| * INTERNAL |
| * Return the type of this node. |
| */ |
| public Object getType() { |
| return type; |
| } |
| |
| /** |
| * INTERNAL |
| * Set this node's type. |
| */ |
| public void setType(Object type) { |
| this.type = type; |
| } |
| |
| /** |
| * INTERNAL |
| * Returns left.and(right) if both are defined. |
| */ |
| public Expression appendExpression(Expression left, Expression right) { |
| Expression expr = null; |
| if (left == null) { |
| expr = right; |
| } else if (right == null) { |
| expr = left; |
| } else { |
| expr = left.and(right); |
| } |
| return expr; |
| } |
| |
| @Override |
| public String toString() { |
| try { |
| return toString(1); |
| } catch (Throwable t) { |
| return t.toString(); |
| } |
| } |
| |
| public String toString(int indent) { |
| StringBuilder buffer = new StringBuilder(); |
| buffer.append(toStringDisplayName()); |
| buffer.append("\r\n"); |
| toStringIndent(indent, buffer); |
| if (hasLeft()) { |
| buffer.append("Left: ").append(getLeft().toString(indent + 1)); |
| } else { |
| buffer.append("Left: null"); |
| } |
| |
| buffer.append("\r\n"); |
| toStringIndent(indent, buffer); |
| if (hasRight()) { |
| buffer.append("Right: ").append(getRight().toString(indent + 1)); |
| } else { |
| buffer.append("Right: null"); |
| } |
| return buffer.toString(); |
| } |
| |
| public String toStringDisplayName() { |
| return getClass().toString().substring(getClass().toString().lastIndexOf('.') + 1, getClass().toString().length()); |
| } |
| |
| public void toStringIndent(int indent, StringBuilder buffer) { |
| for (int i = 0; i < indent; i++) { |
| buffer.append(" "); |
| } |
| } |
| |
| public String getAlias(){ |
| return this.alias; |
| } |
| |
| public void setAlias(String alias){ |
| this.alias = alias; |
| } |
| |
| public boolean isAliasableNode(){ |
| return false; |
| } |
| } |