001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.el;
018
019import javax.servlet.jsp.el.ELException;
020import javax.servlet.jsp.el.FunctionMapper;
021import javax.servlet.jsp.el.VariableResolver;
022
023/**
024 *
025 * <p>Represents a conditional expression.  I've decided not to produce an
026 * abstract base "TernaryOperatorExpression" class since (a) future ternary
027 * operators are unlikely and (b) it's not clear that there would be a
028 * meaningful way to abstract them.  (For instance, would they all be right-
029 * associative?  Would they all have two fixed operator symbols?)
030 * 
031 * @author Shawn Bayern
032 **/
033
034public class ConditionalExpression
035  extends Expression
036{
037  //-------------------------------------
038  // Properties
039  //-------------------------------------
040  // property condition
041
042  Expression mCondition;
043  public Expression getCondition ()
044  { return mCondition; }
045  public void setCondition (Expression pCondition)
046  { mCondition = pCondition; }
047
048  //-------------------------------------
049  // property trueBranch
050
051  Expression mTrueBranch;
052  public Expression getTrueBranch ()
053  { return mTrueBranch; }
054  public void setTrueBranch (Expression pTrueBranch)
055  { mTrueBranch = pTrueBranch; }
056
057  //-------------------------------------
058  // property falseBranch
059
060  Expression mFalseBranch;
061  public Expression getFalseBranch ()
062  { return mFalseBranch; }
063  public void setFalseBranch (Expression pFalseBranch)
064  { mFalseBranch = pFalseBranch; }
065
066  //-------------------------------------
067  /**
068   *
069   * Constructor
070   **/
071  public ConditionalExpression (Expression pCondition,
072                                Expression pTrueBranch,
073                                Expression pFalseBranch)
074  {
075    mCondition = pCondition;
076    mTrueBranch = pTrueBranch;
077    mFalseBranch = pFalseBranch;
078  }
079
080  //-------------------------------------
081  // Expression methods
082  //-------------------------------------
083  /**
084   *
085   * Returns the expression in the expression language syntax
086   **/
087  public String getExpressionString ()
088  {
089    return
090      "( " + mCondition.getExpressionString() + " ? " + 
091      mTrueBranch.getExpressionString() + " : " +
092      mFalseBranch.getExpressionString() + " )";
093  }
094
095  //-------------------------------------
096  /**
097   *
098   * Evaluates the conditional expression and returns the literal result
099   **/
100  public Object evaluate (VariableResolver vr,
101                          FunctionMapper f)
102    throws ELException
103  {
104    // first, evaluate the condition (and coerce the result to a boolean value)
105    boolean condition =
106      Coercions.coerceToBoolean(
107        mCondition.evaluate(vr, f)).booleanValue();
108
109    // then, use this boolean to branch appropriately
110    if (condition)
111      return mTrueBranch.evaluate(vr, f);
112    else
113      return mFalseBranch.evaluate(vr, f);
114  }
115
116  public Expression bindFunctions(final FunctionMapper functions) throws ELException {
117       return new ConditionalExpression(
118               mCondition.bindFunctions(functions),
119               mTrueBranch.bindFunctions(functions),
120               mFalseBranch.bindFunctions(functions));
121  }
122
123  //-------------------------------------
124}