blob: 6e8f9dfc13ef28bc1773c741177378659c93d325 [file] [log] [blame]
/*******************************************************************************
* 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.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.TypeTransformer;
import org.eclipse.jst.jsf.common.internal.types.ValueType;
import org.eclipse.jst.jsf.validation.internal.el.diagnostics.DiagnosticFactory;
/**
* Represents the ternary choice op in EL: a ? b :c
* Based on JSP.2.3.8
*
* @author cbateman
*
*/
public class TernaryChoiceOperator
{
/**
* @param choiceArg
* @param whenTrueArg
* @param whenFalseArg
* @return the result of the choice arguments or null if indeterminant
*/
public ValueType perform(ValueType choiceArg, ValueType whenTrueArg, ValueType whenFalseArg)
{
final boolean isChoiceBoolean =
TypeCoercer.canCoerceToBoolean(TypeTransformer.transformBoxPrimitives(choiceArg.getSignature()));
if (isChoiceBoolean)
{
if (choiceArg instanceof LiteralType)
{
try
{
Boolean result = ((LiteralType)choiceArg).coerceToBoolean();
if (result != null)
{
return result.booleanValue() ? whenTrueArg : whenFalseArg;
}
}
catch (TypeCoercionException tce)
{
return null;
}
}
final String boxedWhenTrueArg =
TypeTransformer.transformBoxPrimitives(whenTrueArg.getSignature());
final String boxedWhenFalseArg =
TypeTransformer.transformBoxPrimitives(whenFalseArg.getSignature());
// check if the two results are the same type
// TODO: could increase accuracy by appoximating type:i.e. if both
// are numeric etc.
if (boxedWhenTrueArg.equals(boxedWhenFalseArg))
{
return new ValueType(whenTrueArg, IAssignable.ASSIGNMENT_TYPE_RHS);
}
// otherwise, we have no idea what the resulting type is
return null;
}
// if choice is not boolean, then can't resolve
return null;
}
/**
* @param choiceArg
* @param whenTrueArg
* @param whenFalseArg
* @return a diagnostic validating the choice expr with these arguments
*/
public Diagnostic validate(ValueType choiceArg)
{
final boolean isChoiceBoolean =
TypeCoercer.canCoerceToBoolean(TypeTransformer.transformBoxPrimitives(choiceArg.getSignature()));
if (isChoiceBoolean)
{
if (choiceArg instanceof LiteralType)
{
try
{
Boolean result = ((LiteralType)choiceArg).coerceToBoolean();
if (result != null)
{
String whichSelected = result.booleanValue() ? "first" : "second";
return DiagnosticFactory.
create_TERNARY_OP_CHOICE_IS_ALWAYS_SAME
(result.booleanValue(), whichSelected);
}
}
catch (TypeCoercionException tce)
{
return DiagnosticFactory.
create_TERNARY_OP_CANNOT_COERCE_CHOICE_TO_BOOLEAN();
}
}
// in both the case where the two arguments are the same and when
// they are different types, the best we can say is "OK", since
// we really don't know
return Diagnostic.OK_INSTANCE;
}
// if choice is not boolean, then can't resolve
return DiagnosticFactory.
create_TERNARY_OP_CANNOT_COERCE_CHOICE_TO_BOOLEAN();
}
}