| /* |
| * 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.expressions; |
| |
| import java.util.List; |
| import java.util.Set; |
| |
| import org.eclipse.persistence.exceptions.*; |
| import org.eclipse.persistence.expressions.*; |
| import org.eclipse.persistence.internal.helper.DatabaseField; |
| import org.eclipse.persistence.internal.sessions.AbstractRecord; |
| import org.eclipse.persistence.internal.sessions.AbstractSession; |
| import org.eclipse.persistence.descriptors.ClassDescriptor; |
| |
| /** |
| * Used for logical AND and OR. This is not used by NOT. |
| */ |
| public class LogicalExpression extends CompoundExpression { |
| |
| public LogicalExpression() { |
| super(); |
| } |
| |
| /** |
| * INTERNAL: |
| * Used for debug printing. |
| */ |
| @Override |
| public String descriptionOfNodeType() { |
| return "Logical"; |
| } |
| |
| /** |
| * INTERNAL: |
| * Check if the object conforms to the expression in memory. |
| * This is used for in-memory querying. |
| * If the expression in not able to determine if the object conform throw a not supported exception. |
| */ |
| @Override |
| public boolean doesConform(Object object, AbstractSession session, AbstractRecord translationRow, int valueHolderPolicy, boolean objectIsUnregistered) { |
| // This should always be and or or. |
| if (this.operator.getSelector() == ExpressionOperator.And) { |
| return this.firstChild.doesConform(object, session, translationRow, valueHolderPolicy, objectIsUnregistered) && this.secondChild.doesConform(object, session, translationRow, valueHolderPolicy, objectIsUnregistered); |
| } else if (this.operator.getSelector() == ExpressionOperator.Or) { |
| return this.firstChild.doesConform(object, session, translationRow, valueHolderPolicy, objectIsUnregistered) || this.secondChild.doesConform(object, session, translationRow, valueHolderPolicy, objectIsUnregistered); |
| } |
| |
| throw QueryException.cannotConformExpression(); |
| |
| } |
| |
| /** |
| * INTERNAL: |
| * Extract the values from the expression into the row. |
| * Ensure that the query is querying the exact primary key. |
| * Return false if not on the primary key. |
| */ |
| @Override |
| public boolean extractValues(boolean primaryKeyOnly, boolean requireExactMatch, ClassDescriptor descriptor, AbstractRecord primaryKeyRow, AbstractRecord translationRow) { |
| // If this is a primary key expression then it can only have and/or relationships. |
| if (this.operator.getSelector() != ExpressionOperator.And) { |
| // If this is an exact primary key expression it can not have ors. |
| // After fixing bug 2782991 this must now work correctly. |
| if (requireExactMatch || (this.operator.getSelector() != ExpressionOperator.Or)) { |
| return false; |
| } |
| } |
| |
| // Ensure that both sides of the expression tree have a session, for correct descriptor, value resolution |
| if (this.secondChild.getSession() == null && this.firstChild.getSession() != null) { |
| this.secondChild.getBuilder().setSession(this.firstChild.getSession()); |
| } else if (this.firstChild.getSession() == null && this.secondChild.getSession() != null) { |
| this.firstChild.getBuilder().setSession(this.secondChild.getSession()); |
| } |
| |
| boolean validExpression = this.firstChild.extractValues(primaryKeyOnly, requireExactMatch, descriptor, primaryKeyRow, translationRow); |
| if (requireExactMatch && (!validExpression)) { |
| return false; |
| } |
| return this.secondChild.extractValues(primaryKeyOnly, requireExactMatch, descriptor, primaryKeyRow, translationRow); |
| } |
| |
| /** |
| * INTERNAL: |
| * Return if the expression is not a valid primary key expression and add all primary key fields to the set. |
| */ |
| @Override |
| public boolean extractFields(boolean requireExactMatch, boolean primaryKey, ClassDescriptor descriptor, List<DatabaseField> searchFields, Set<DatabaseField> foundFields) { |
| // If this is a primary key expression then it can only have and/or relationships. |
| if (this.operator.getSelector() != ExpressionOperator.And) { |
| // If this is an exact primary key expression it can not have ors. |
| // After fixing bug 2782991 this must now work correctly. |
| if (requireExactMatch || (this.operator.getSelector() != ExpressionOperator.Or)) { |
| return false; |
| } |
| } |
| |
| // Ensure that both sides of the expression tree have a session, for correct descriptor, field resolution |
| if (this.secondChild.getSession() == null && this.firstChild.getSession() != null) { |
| this.secondChild.getBuilder().setSession(this.firstChild.getSession()); |
| } else if (this.firstChild.getSession() == null && this.secondChild.getSession() != null) { |
| this.firstChild.getBuilder().setSession(this.secondChild.getSession()); |
| } |
| |
| boolean validExpression = this.firstChild.extractFields(requireExactMatch, primaryKey, descriptor, searchFields, foundFields); |
| if (requireExactMatch && (!validExpression)) { |
| return false; |
| } |
| return this.secondChild.extractFields(requireExactMatch, primaryKey, descriptor, searchFields, foundFields); |
| } |
| |
| /** |
| * INTERNAL: |
| */ |
| @Override |
| public boolean isLogicalExpression() { |
| return true; |
| } |
| } |