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 java.math.BigInteger;
020
021import javax.servlet.jsp.el.ELException;
022
023import org.apache.commons.logging.Log;
024import org.apache.commons.logging.LogFactory;
025
026/**
027 *
028 * <p>The implementation of the modulus operator
029 * 
030 * @author Nathan Abramson - Art Technology Group
031 * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: bayard $
032 **/
033
034public class ModulusOperator
035  extends BinaryOperator
036{
037    
038    //-------------------------------------
039    // Constants
040    //-------------------------------------
041    private static Log log = LogFactory.getLog(ModulusOperator.class);
042    
043  //-------------------------------------
044  // Singleton
045  //-------------------------------------
046
047  public static final ModulusOperator SINGLETON =
048    new ModulusOperator ();
049
050  //-------------------------------------
051  /**
052   *
053   * Constructor
054   **/
055  public ModulusOperator ()
056  {
057  }
058
059  //-------------------------------------
060  // Expression methods
061  //-------------------------------------
062  /**
063   *
064   * Returns the symbol representing the operator
065   **/
066  public String getOperatorSymbol ()
067  {
068    return "%";
069  }
070
071  //-------------------------------------
072  /**
073   *
074   * Applies the operator to the given value
075   **/
076  public Object apply (Object pLeft, Object pRight)
077    throws ELException
078  {
079    if (pLeft == null &&
080        pRight == null) {
081        if (log.isWarnEnabled()) {
082            log.warn(
083                MessageUtil.getMessageWithArgs(
084                    Constants.ARITH_OP_NULL, getOperatorSymbol()));
085        }     
086      return PrimitiveObjects.getInteger (0);
087    }
088
089    if ((pLeft != null &&
090         (Coercions.isFloatingPointType (pLeft) ||
091          Coercions.isFloatingPointString (pLeft))) ||
092      Coercions.isBigDecimal(pLeft) ||
093        (pRight != null &&
094         (Coercions.isFloatingPointType (pRight) ||
095          Coercions.isFloatingPointString (pRight) ||
096      Coercions.isBigDecimal(pRight)))) {
097      double left =
098        Coercions.coerceToPrimitiveNumber (pLeft, Double.class).
099        doubleValue ();
100      double right =
101        Coercions.coerceToPrimitiveNumber (pRight, Double.class).
102        doubleValue ();
103
104      try {
105        return PrimitiveObjects.getDouble (left % right);
106      }
107      catch (Exception exc) {
108          if (log.isErrorEnabled()) {
109              String message = MessageUtil.getMessageWithArgs(
110                  Constants.ARITH_ERROR,
111                  getOperatorSymbol(),
112                  "" + left,
113                  "" + right);
114              log.error(message);
115              throw new ELException(message);
116          }     
117        return PrimitiveObjects.getInteger (0);
118      }
119    }
120    else if (Coercions.isBigInteger(pLeft) || Coercions.isBigInteger(pRight)) {
121        BigInteger left = (BigInteger)
122             Coercions.coerceToPrimitiveNumber(pLeft, BigInteger.class);
123        BigInteger right = (BigInteger)
124            Coercions.coerceToPrimitiveNumber(pRight, BigInteger.class);
125
126        try {
127            return left.remainder(right);
128        } catch (Exception exc) {
129            if (log.isErrorEnabled()) {
130                String message = MessageUtil.getMessageWithArgs(
131                    Constants.ARITH_ERROR,
132                    getOperatorSymbol(),
133                    "" + left,
134                    "" + right);
135                log.error(message);
136                throw new ELException(message);
137            }              
138            return PrimitiveObjects.getInteger(0);
139        }
140    }
141    else {
142      long left =
143        Coercions.coerceToPrimitiveNumber (pLeft, Long.class).
144        longValue ();
145      long right =
146        Coercions.coerceToPrimitiveNumber (pRight, Long.class).
147        longValue ();
148
149      try {
150        return PrimitiveObjects.getLong (left % right);
151      }
152      catch (Exception exc) {
153          if (log.isErrorEnabled()) {
154              String message = MessageUtil.getMessageWithArgs(
155                  Constants.ARITH_ERROR,
156                  getOperatorSymbol(),
157                  "" + left,
158                  "" + right);
159              log.error(message);
160              throw new ELException(message);
161          }             
162        return PrimitiveObjects.getInteger (0);
163      }
164    }
165  }
166
167  //-------------------------------------
168}