| /* |
| * Copyright (c) 1998, 2020 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; |
| |
| /** |
| * INTERNAL |
| * <p><b>Purpose</b>: Represent the MEMBER-OF operator |
| * <p><b>Responsibilities</b>:<ul> |
| * <li> MEMBER OF is not supported. |
| * </ul> |
| * @author Jon Driscoll and Joel Lucuik |
| * @since since July 2003 |
| */ |
| import org.eclipse.persistence.expressions.*; |
| |
| public class MemberOfNode extends BinaryOperatorNode { |
| private boolean notIndicated = false; |
| |
| //If we're dealing with a NOT, we store the expression for the left. |
| //When we get to the one-to-many on the right, it will handle the noneOf using |
| //the receiver stored in the context. |
| //(i.e. secondLastRightExpression.noneOf(lastRightVariable, leftExpression) |
| private Expression leftExpression = null; |
| |
| /** |
| * Return a new MemberOfNode |
| */ |
| public MemberOfNode() { |
| super(); |
| } |
| |
| /** |
| * INTERNAL makeNodeOneToMany: |
| * Traverse to the leaf on theNode and mark as one to many |
| */ |
| public void makeNodeOneToMany(Node theNode) { |
| Node currentNode = theNode; |
| do { |
| if (!currentNode.hasRight()) { |
| ((AttributeNode)currentNode).setRequiresCollectionAttribute(true); |
| return; |
| } |
| currentNode = currentNode.getRight(); |
| } while (true); |
| } |
| |
| /** |
| * INTERNAL |
| * Validate node and calculates its type. |
| */ |
| @Override |
| public void validate(ParseTreeContext context) { |
| super.validate(context); |
| Node left = getLeft(); |
| if (left.isVariableNode() && ((VariableNode)left).isAlias(context)) { |
| context.usedVariable(((VariableNode)left).getCanonicalVariableName()); |
| } |
| left.validateParameter(context, right.getType()); |
| TypeHelper typeHelper = context.getTypeHelper(); |
| setType(typeHelper.getBooleanType()); |
| } |
| |
| @Override |
| public Expression generateExpression(GenerationContext context) { |
| // Need to make sure one of the node is marked as a one to many |
| if (getRight().isParameterNode()) { |
| makeNodeOneToMany(getLeft()); |
| } else { |
| makeNodeOneToMany(getRight()); |
| } |
| |
| //Handle NOT. Store the expression for the left, let VariableNode handle it. |
| if (notIndicated()) { |
| Expression resultFromRight = null; |
| context.setMemberOfNode(this); |
| this.setLeftExpression(getLeft().generateExpression(context)); |
| resultFromRight = getRight().generateExpression(context); |
| //clean up |
| context.setMemberOfNode(null); |
| this.setLeftExpression(null); |
| return resultFromRight; |
| } else { |
| //otherwise, handle like normal anyOf() |
| return getRight().generateExpression(context).equal(getLeft().generateExpression(context)); |
| } |
| } |
| |
| /** |
| * INTERNAL |
| * Indicate if a NOT was found in the WHERE clause. |
| * Examples: |
| * ...WHERE ... NOT MEMBER OF |
| */ |
| public void indicateNot() { |
| notIndicated = true; |
| } |
| |
| public boolean notIndicated() { |
| return notIndicated; |
| } |
| |
| //set and get the leftExpression. This is for NOT MEMBER OF. |
| public void setLeftExpression(Expression newLeftExpression) { |
| leftExpression = newLeftExpression; |
| } |
| |
| public Expression getLeftExpression() { |
| return leftExpression; |
| } |
| } |