blob: e6cacb52795e494fad30ff1d318a912f9ab9eef8 [file] [log] [blame]
/*
* Copyright (c) 2011, 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
//
package org.eclipse.persistence.jpa.jpql.tools.model.query;
import org.eclipse.persistence.jpa.jpql.Assert;
import org.eclipse.persistence.jpa.jpql.parser.ComparisonExpression;
import org.eclipse.persistence.jpa.jpql.parser.ComparisonExpressionBNF;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.*;
/**
* Only the values of like types are permitted to be compared. A type is like another type if they
* correspond to the same Java language type, or if one is a primitive Java language type and the
* other is the wrapped Java class type equivalent (e.g., int and Integer are like types in this
* sense).
* <p>
* There is one exception to this rule: it is valid to compare numeric values for which the rules of
* numeric promotion apply. Conditional expressions attempting to compare non-like type values are
* disallowed except for this numeric case.
* <p>
* Note that the arithmetic operators and comparison operators are permitted to be applied to
* state-fields and input parameters of the wrapped Java class equivalents to the primitive numeric
* Java types. Two entities of the same abstract schema type are equal if and only if they have the
* same primary key value. Only equality/inequality comparisons over enumeration constants are
* required to be supported.
* <p>
* <b>JPA 1.0 - BNF:</b>
* <pre><code>comparison_expression ::= string_expression comparison_operator {string_expression | all_or_any_expression} |
* boolean_expression {=|{@literal <>}} {boolean_expression | all_or_any_expression} |
* enum_expression {=|{@literal <>}} {enum_expression | all_or_any_expression} |
* datetime_expression comparison_operator {datetime_expression | all_or_any_expression} |
* entity_expression {=|{@literal <>}} {entity_expression | all_or_any_expression} |
* arithmetic_expression comparison_operator {arithmetic_expression | all_or_any_expression}</code></pre>
*
* <b>JPA 2.0 - BNF:</b>
* <pre><code>comparison_expression ::= string_expression comparison_operator {string_expression | all_or_any_expression} |
* boolean_expression {=|{@literal <>}} {boolean_expression | all_or_any_expression} |
* enum_expression {=|{@literal <>}} {enum_expression | all_or_any_expression} |
* datetime_expression comparison_operator {datetime_expression | all_or_any_expression} |
* entity_expression {=|{@literal <>}} {entity_expression | all_or_any_expression} |
* arithmetic_expression comparison_operator {arithmetic_expression | all_or_any_expression} |
* <b>entity_type_expression {=|{@literal <>}} entity_type_expression}</b></code></pre>
*
* @see ComparisonExpression
*
* @version 2.4
* @since 2.4
* @author Pascal Filion
*/
@SuppressWarnings("nls")
public class ComparisonExpressionStateObject extends CompoundExpressionStateObject {
/**
* The comparison identifier, which is either {@literal <, <=, =, >=, <>}.
*/
private String identifier;
/**
* Notifies the identifier property has changed.
*/
public static final String IDENTIFIER_PROPERTY = "identifier";
/**
* Creates a new <code>ComparisonExpressionStateObject</code>.
*
* @param parent The parent of this state object, which cannot be <code>null</code>
* @param leftStateObject The {@link StateObject} representing the left expression
* @param identifier The comparison identifier, either {@literal <, <=, =, >=, <>}
* @param rightStateObject The {@link StateObject} representing the right expression
* @exception NullPointerException The given parent cannot be <code>null</code>
*/
public ComparisonExpressionStateObject(StateObject parent,
StateObject leftStateObject,
String identifier,
StateObject rightStateObject) {
super(parent, leftStateObject, rightStateObject);
validateIdentifier(identifier);
this.identifier = identifier;
}
/**
* Creates a new <code>ComparisonExpressionStateObject</code>.
*
* @param parent The parent of this state object, which cannot be <code>null</code>
* @param identifier The comparison identifier, either {@literal <, <=, =, >=, <>}
* @exception NullPointerException The given parent cannot be <code>null</code>
*/
public ComparisonExpressionStateObject(StateObject parent, String identifier) {
super(parent);
validateIdentifier(identifier);
this.identifier = identifier;
}
/**
* Creates a new <code>ComparisonExpressionStateObject</code>.
*
* @param parent The parent of this state object, which cannot be <code>null</code>
* @param leftJpqlFragment The string representation of the left expression to parse and to
* convert into a {@link StateObject}
* @param identifier The comparison identifier, either {@literal <, <=, =, >=, <>}
* @param rightJpqlFragment The string representation of the right expression to parse and to
* convert into a {@link StateObject}
* @exception NullPointerException The given parent cannot be <code>null</code>
*/
public ComparisonExpressionStateObject(StateObject parent,
String leftJpqlFragment,
String identifier,
String rightJpqlFragment) {
super(parent, leftJpqlFragment, rightJpqlFragment);
validateIdentifier(identifier);
this.identifier = identifier;
}
@Override
public void accept(StateObjectVisitor visitor) {
visitor.visit(this);
}
@Override
public ComparisonExpression getExpression() {
return (ComparisonExpression) super.getExpression();
}
@Override
public String getIdentifier() {
return identifier;
}
@Override
protected String getLeftQueryBNFId() {
return ComparisonExpressionBNF.ID;
}
@Override
protected String getRightQueryBNFId() {
return ComparisonExpressionBNF.ID;
}
@Override
public boolean isEquivalent(StateObject stateObject) {
if (super.isEquivalent(stateObject)) {
ComparisonExpressionStateObject comparison = (ComparisonExpressionStateObject) stateObject;
return identifier == comparison.identifier;
}
return false;
}
/**
* Keeps a reference of the {@link ComparisonExpression parsed object} object, which should only
* be done when this object is instantiated during the conversion of a parsed JPQL query into
* {@link StateObject StateObjects}.
*
* @param expression The {@link ComparisonExpression parsed object} representing a comparison
* expression
*/
public void setExpression(ComparisonExpression expression) {
super.setExpression(expression);
}
/**
* Sets the comparison identifier to one of the following: {@literal <, <=, =, >=, <>}.
*
* @param identifier The new comparison identifier, either {@literal <, <=, =, >=, <>}
*/
public void setIdentifier(String identifier) {
validateIdentifier(identifier);
String oldIdentifier = this.identifier;
this.identifier = identifier;
firePropertyChanged(IDENTIFIER_PROPERTY, oldIdentifier, identifier);
}
protected void validateIdentifier(String identifier) {
Assert.isValid(
identifier,
"The comparison identifier must be either <, <=, =, >=, <>.",
LOWER_THAN, LOWER_THAN_OR_EQUAL, EQUAL, GREATER_THAN, GREATER_THAN_OR_EQUAL, DIFFERENT
);
}
}