blob: 66036c561826a726a7e03964340b890eef65eb4d [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.ArithmeticFactor;
import org.eclipse.persistence.jpa.jpql.parser.ArithmeticFactorBNF;
import static org.eclipse.persistence.jpa.jpql.parser.AbstractExpression.*;
/**
* This state object simply adds a plus or minus sign to the arithmetic primary expression.
*
* <div><p><b>BNF:</b> <code>arithmetic_factor ::= [{+|-}] arithmetic_primary</code></p></div>
*
* @see ArithmeticFactor
*
* @version 2.4
* @since 2.4
* @author Pascal Filion
*/
@SuppressWarnings({"nls", "unused"}) // unused used for the import statement: see bug 330740
public class ArithmeticFactorStateObject extends AbstractStateObject {
/**
* <code>true</code> if the arithmetic sign is the plus sign; <code>false</code> otherwise.
*/
private boolean plusSign;
/**
* The {@link StateObject} that represents the arithmetic primary expression.
*/
private StateObject stateObject;
/**
* Notifies the arithmetic sign property has changed.
*/
public static final String ARITHMETIC_SIGN_PROPERTY = "arithmeticSign";
/**
* Notifies the state object property has changed.
*/
public static final String STATE_OBJECT_PROPERTY = "stateObject";
/**
* Creates a new <code>ArithmeticFactorStateObject</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>
*/
public ArithmeticFactorStateObject(StateObject parent) {
super(parent);
}
/**
* Creates a new <code>ArithmeticFactorStateObject</code>.
*
* @param parent The parent of this state object, which cannot be <code>null</code>
* @param stateObject The {@link StateObject} that represents the arithmetic primary expression
* @exception NullPointerException The given parent cannot be <code>null</code>
*/
public ArithmeticFactorStateObject(StateObject parent, boolean plusSign, StateObject stateObject) {
super(parent);
this.plusSign = plusSign;
this.stateObject = parent(stateObject);
}
@Override
public void accept(StateObjectVisitor visitor) {
visitor.visit(this);
}
@Override
protected void addChildren(List<StateObject> children) {
super.addChildren(children);
if (stateObject != null) {
children.add(stateObject);
}
}
/**
* Makes sure the <code><b>-</b></code> sign is used.
*/
public void addMinus() {
if (plusSign) {
setArithmeticSign(false);
}
}
/**
* Makes sure the <code><b>+</b></code> sign is used.
*/
public void addPlus() {
if (!plusSign) {
setArithmeticSign(true);
}
}
/**
* Returns the arithmetic sign this expression is actually representing.
*
* @return The single character value of the arithmetic sign: '+' or '-'
*/
public String getArithmeticSign() {
return plusSign ? PLUS : MINUS;
}
@Override
public ArithmeticFactor getExpression() {
return (ArithmeticFactor) super.getExpression();
}
/**
* Returns the {@link StateObject} that represents the arithmetic primary expression.
*
* @return The {@link StateObject} that represents the arithmetic primary expression or
* <code>null</code> if none was specified
*/
public StateObject getStateObject() {
return stateObject;
}
/**
* Determines whether the arithmetic sign is the minus sign.
*
* @return <code>true</code> if the arithmetic sign is the minus sign; <code>false</code> if it
* is the plus sign
*/
public boolean hasMinusSign() {
return !plusSign;
}
/**
* Determines whether the arithmetic sign is the plus sign.
*
* @return <code>true</code> if the arithmetic sign is the plus sign; <code>false</code> if it
* is the minus sign
*/
public boolean hasPlusSign() {
return plusSign;
}
/**
* Determines whether an {@link StateObject} representing the arithmetic primary expression
* exists.
*
* @return <code>true</code> if there is the arithmetic primary expression exists; <code>false</code>
* otherwise
*/
public boolean hasStateObject() {
return stateObject != null;
}
@Override
public boolean isEquivalent(StateObject stateObject) {
if (super.isEquivalent(stateObject)) {
ArithmeticFactorStateObject arithmeticFactor = (ArithmeticFactorStateObject) stateObject;
return plusSign == arithmeticFactor.plusSign &&
areEquivalent(stateObject, arithmeticFactor.stateObject);
}
return false;
}
/**
* Parses the given JPQL fragment to become the new arithmetic primary.
*
* @param jpqlFragment A portion of a query that will be parsed and the {@link StateObject} that
* was created will become the new arithmetic primary of this {@link ArithmeticFactorStateObject}
*/
public void parse(String jpqlFragment) {
StateObject stateObject = buildStateObject(jpqlFragment, ArithmeticFactorBNF.ID);
setStateObject(stateObject);
}
/**
* Sets the arithmetic sign this expression is actually representing.
*
* @param plusSign The single character value of the arithmetic sign: '+' (<code>true</code>) or
* '-' (<code>false</code>)
*/
public void setArithmeticSign(boolean plusSign) {
boolean oldPlusSign = plusSign;
this.plusSign = !oldPlusSign;
firePropertyChanged(ARITHMETIC_SIGN_PROPERTY, oldPlusSign, plusSign);
}
/**
* Keeps a reference of the {@link ArithmeticFactor 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 ArithmeticFactor parsed object} representing an arithmetic
* factor expression
*/
public void setExpression(ArithmeticFactor expression) {
super.setExpression(expression);
}
/**
* Returns the {@link StateObject} that represents the arithmetic primary expression.
*
* @param stateObject The {@link StateObject} that represents the arithmetic primary expression
* or <code>null</code> if none was specified
*/
public void setStateObject(StateObject stateObject) {
StateObject oldStateObject = this.stateObject;
this.stateObject = parent(stateObject);
firePropertyChanged(STATE_OBJECT_PROPERTY, oldStateObject, stateObject);
}
/**
* Toggles the arithmetic sign, plus becomes minus and vice versa.
*/
public void toggleArithmeticSign() {
setArithmeticSign(!plusSign);
}
@Override
protected void toTextInternal(Appendable writer) throws IOException {
writer.append(getArithmeticSign());
if (stateObject != null) {
writer.append(SPACE);
stateObject.toString(writer);
}
}
}