blob: 19e7e8131d7ea0d59255082ae37b2c740ade7386 [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 java.io.IOException;
import java.util.List;
import org.eclipse.persistence.jpa.jpql.parser.CompoundExpression;
import static org.eclipse.persistence.jpa.jpql.parser.AbstractExpression.*;
/**
* A compound {@link StateObject} has a left and right expressions combined by an identifier.
*
* <div><p><b>BNF:</b> <code>expression ::= left_expression &lt;identifier&gt; right_expression</code></p></div>
*
* @see CompoundExpression
*
* @version 2.4
* @since 2.4
* @author Pascal Filion
*/
@SuppressWarnings("nls")
public abstract class CompoundExpressionStateObject extends AbstractStateObject {
/**
* The {@link StateObject} representing the left expression.
*/
private StateObject leftStateObject;
/**
* The {@link StateObject} representing the right expression.
*/
private StateObject rightStateObject;
/**
* Notifies the left state object property has changed.
*/
public static final String LEFT_STATE_OBJECT_PROPERTY = "leftStateObject";
/**
* Notifies the right state object property has changed.
*/
public static final String RIGHT_STATE_OBJECT_PROPERTY = "rightStateObject";
/**
* Creates a new <code>CompoundExpressionStateObject</code>.
*
* @param parent The parent of this state object, which cannot be <code>null</code>
* @exception NullPointerException The given parent cannot be <code>null</code>
*/
protected CompoundExpressionStateObject(StateObject parent) {
super(parent);
}
/**
* Creates a new <code>ArithmeticExpressionStateObject</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 rightStateObject The {@link StateObject} representing the right expression
* @exception NullPointerException The given parent cannot be <code>null</code>
*/
protected CompoundExpressionStateObject(StateObject parent,
StateObject leftStateObject,
StateObject rightStateObject) {
super(parent);
this.leftStateObject = parent(leftStateObject);
this.rightStateObject = parent(rightStateObject);
}
/**
* Creates a new <code>ArithmeticExpressionStateObject</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 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>
*/
protected CompoundExpressionStateObject(StateObject parent,
String leftJpqlFragment,
String rightJpqlFragment) {
super(parent);
parseLeft (leftJpqlFragment);
parseRight(rightJpqlFragment);
}
@Override
protected void addChildren(List<StateObject> children) {
super.addChildren(children);
if (leftStateObject != null) {
children.add(leftStateObject);
}
if (rightStateObject != null) {
children.add(rightStateObject);
}
}
@Override
public CompoundExpression getExpression() {
return (CompoundExpression) super.getExpression();
}
/**
* Returns the identifier joining the two {@link StateObject StateObjects}.
*
* @return The JPQL identifier join two expressions
*/
public abstract String getIdentifier();
/**
* Returns the {@link StateObject} that represents the left expression.
*
* @return The {@link StateObject} representing the left expression
*/
public StateObject getLeft() {
return leftStateObject;
}
/**
* Returns the unique identifier of the BNF that will be used to parse a JPQL fragment as the
* left side of the expression.
*
* @return The query BNF ID for the left side of the expression
*/
protected abstract String getLeftQueryBNFId();
/**
* Returns the {@link StateObject} that represents the right expression.
*
* @return The {@link StateObject} representing the right expression
*/
public StateObject getRight() {
return rightStateObject;
}
/**
* Returns the unique identifier of the BNF that will be used to parse a JPQL fragment as the
* right side of the expression.
*
* @return The query BNF ID for the right side of the expression
*/
protected abstract String getRightQueryBNFId();
/**
* Determines whether there is a {@link StateObject} that represents the left expression.
*
* @return <code>true</code> if there is a left {@link StateObject}; <code>false</code> if it is
* <code>null</code>
*/
public boolean hasLeft() {
return leftStateObject != null;
}
/**
* Determines whether there is a {@link StateObject} that represents the right expression.
*
* @return <code>true</code> if there is a right {@link StateObject}; <code>false</code> if it
* is <code>null</code>
*/
public boolean hasRight() {
return rightStateObject != null;
}
@Override
public boolean isEquivalent(StateObject stateObject) {
if (super.isEquivalent(stateObject)) {
CompoundExpressionStateObject compound = (CompoundExpressionStateObject) stateObject;
return areEquivalent(leftStateObject, compound.leftStateObject) &&
areEquivalent(rightStateObject, compound.rightStateObject);
}
return false;
}
/**
* Parses the given JPQL fragment and update the left side of the compound expression.
*
* @param jpqlFragment The portion of the query to become the left side of the compound expression
*/
public void parseLeft(String jpqlFragment) {
StateObject stateObject = buildStateObject(jpqlFragment, getLeftQueryBNFId());
setLeft(stateObject);
}
/**
* Parses the given JPQL fragment and update the right side of the compound expression.
*
* @param jpqlFragment The portion of the query to become the right side of the compound expression
*/
public void parseRight(String jpqlFragment) {
StateObject stateObject = buildStateObject(jpqlFragment, getRightQueryBNFId());
setLeft(stateObject);
}
/**
* Sets the left {@link StateObject} to become the given object.
*
* @param leftStateObject The {@link StateObject} representing the left expression
*/
public void setLeft(StateObject leftStateObject) {
StateObject oldLeftStateObject = this.leftStateObject;
this.leftStateObject = parent(leftStateObject);
firePropertyChanged(LEFT_STATE_OBJECT_PROPERTY, oldLeftStateObject, leftStateObject);
}
/**
* Sets the right {@link StateObject} to become the given object.
*
* @param rightStateObject The {@link StateObject} representing the right expression
*/
public void setRight(StateObject rightStateObject) {
StateObject oldRightStateObject = this.rightStateObject;
this.rightStateObject = parent(rightStateObject);
firePropertyChanged(RIGHT_STATE_OBJECT_PROPERTY, oldRightStateObject, rightStateObject);
}
@Override
protected void toTextInternal(Appendable writer) throws IOException {
if (leftStateObject != null) {
leftStateObject.toString(writer);
}
writer.append(SPACE);
writer.append(getIdentifier());
writer.append(SPACE);
if (rightStateObject != null) {
rightStateObject.toString(writer);
}
}
}