/******************************************************************************* * Copyright (c) 2006 Oracle Corporation. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Cameron Bateman/Oracle - initial API and implementation * ********************************************************************************/ package org.eclipse.jst.jsf.validation.internal.el.operators; import org.eclipse.emf.common.util.Diagnostic; import org.eclipse.jst.jsf.common.internal.types.BooleanLiteralType; import org.eclipse.jst.jsf.common.internal.types.IAssignable; import org.eclipse.jst.jsf.common.internal.types.LiteralType; import org.eclipse.jst.jsf.common.internal.types.TypeCoercer; import org.eclipse.jst.jsf.common.internal.types.TypeCoercionException; import org.eclipse.jst.jsf.common.internal.types.TypeConstants; import org.eclipse.jst.jsf.common.internal.types.TypeTransformer; import org.eclipse.jst.jsf.common.internal.types.ValueType; import org.eclipse.jst.jsf.core.IJSFCoreConstants; import org.eclipse.jst.jsf.validation.internal.el.diagnostics.DiagnosticFactory; /** * Super-class of all relational binary ops - "==", "!=", "<", ">", "<=", ">=" * @author cbateman * */ /*package*/ abstract class RelationalBinaryOperator extends BinaryOperator { private final String _jsfVersion; RelationalBinaryOperator(final DiagnosticFactory diagnosticFactory, final String jsfVersion) { super(diagnosticFactory); _jsfVersion = jsfVersion; } /** * @param firstArg * @param secondArg * @return the result of the operation */ protected abstract boolean doRealOperation(Number firstArg, Number secondArg); /** * @param firstArg * @param secondArg * @return the result of the operation */ protected abstract boolean doRealOperation(String firstArg, String secondArg); /** * @return the operation's user readable name */ protected abstract String getOperationName(); /** * Performs a the operation, casting both args to BigDecimal first * * @param firstArg * @param secondArg * @param numberType * @return the result of the comparison or null if indeterminate */ protected ValueType handleNumericComparison(ValueType firstArg, ValueType secondArg, Class numberType) { try { TypeCoercer.coerceToNumber(TypeTransformer.transformBoxPrimitives(firstArg.getSignature())); TypeCoercer.coerceToNumber(TypeTransformer.transformBoxPrimitives(secondArg.getSignature())); Number firstValue = null; if (firstArg instanceof LiteralType) { firstValue = ((LiteralType)firstArg).coerceToNumber(numberType); } Number secondValue = null; if (secondArg instanceof LiteralType) { secondValue = ((LiteralType)secondArg).coerceToNumber(numberType); } if (firstValue != null && secondValue != null) { boolean result = doRealOperation(firstValue, secondValue); return result ? BooleanLiteralType.TRUE : BooleanLiteralType.FALSE; } // if we get to here, we only know that both can be up cast to BigDecimal // and compared. This will yield a boolean result // this value cannot be lhs return new ValueType(TypeConstants.TYPE_BOOLEAN, IAssignable.ASSIGNMENT_TYPE_RHS); } catch (TypeCoercionException tce) { // no valid coercion, so return null return null; } } /** * @param firstType * @param secondType * @param numberType * @return a diagnostic validating the relational comparison of firstType to secondType */ protected Diagnostic validateNumericComparison(ValueType firstType, ValueType secondType, Class numberType) { try { TypeCoercer.coerceToNumber(TypeTransformer.transformBoxPrimitives(firstType.getSignature())); TypeCoercer.coerceToNumber(TypeTransformer.transformBoxPrimitives(secondType.getSignature())); Number firstValue = null; if (firstType instanceof LiteralType) { firstValue = ((LiteralType)firstType).coerceToNumber(numberType); } Number secondValue = null; if (secondType instanceof LiteralType) { secondValue = ((LiteralType)secondType).coerceToNumber(numberType); } if (firstValue != null && secondValue != null) { boolean result = doRealOperation(firstValue, secondValue); return _diagnosticFactory. create_BINARY_OP_CONSTANT_EXPRESSION_ALWAYS_EVAL_SAME (getOperationName(), Boolean.toString(result)); } // if we get to here, we only know that both can be up cast to BigDecimal // and compared. This condition is okay return Diagnostic.OK_INSTANCE; } catch (TypeCoercionException tce) { // could not make numeric coercion for valid comparison return _diagnosticFactory.create_BINARY_OP_COULD_NOT_MAKE_NUMERIC_COERCION(getOperationName()); } } /** * @param firstType * @param secondType * @return the result of the operation */ protected ValueType handleStringComparison(ValueType firstType, ValueType secondType) { String firstValue = null; if (firstType instanceof LiteralType) { firstValue = ((LiteralType)firstType).getLiteralValue(); } String secondValue = null; if (secondType instanceof LiteralType) { secondValue = ((LiteralType)secondType).getLiteralValue(); } if (firstValue != null && secondValue != null) { boolean newValue = doRealOperation(firstValue, secondValue); return newValue ? BooleanLiteralType.TRUE : BooleanLiteralType.FALSE; } // if don't have all literals, just return boolean type return new ValueType(TypeConstants.TYPE_BOOLEAN, IAssignable.ASSIGNMENT_TYPE_RHS); } /** * @param firstType * @param secondType * @return a diagnostic validating the string comparison of firstType to secondType */ protected Diagnostic validateStringComparison(ValueType firstType, ValueType secondType) { String firstValue = null; if (firstType instanceof LiteralType) { firstValue = ((LiteralType)firstType).getLiteralValue(); } String secondValue = null; if (secondType instanceof LiteralType) { secondValue = ((LiteralType)secondType).getLiteralValue(); } if (firstValue != null && secondValue != null) { boolean newValue = doRealOperation(firstValue, secondValue); return _diagnosticFactory. create_BINARY_OP_CONSTANT_EXPRESSION_ALWAYS_EVAL_SAME (getOperationName(), Boolean.toString(newValue)); } // if don't have all literals, just return boolean type return Diagnostic.OK_INSTANCE; } /** * @return the current JSF version string */ protected final String getJsfVersion() { return _jsfVersion; } /** * @return true if the JSF version for this operator is JSF 1.1 or 1.0 */ protected final boolean isPreJSF12() { return IJSFCoreConstants.JSF_VERSION_1_1.equals(_jsfVersion) || IJSFCoreConstants.JSF_VERSION_1_0.equals(_jsfVersion); } /** * @return true if the JSF version for this operator is JSF 1.2 or later */ protected final boolean isJSF12OrLater() { return !isPreJSF12(); } }