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     */
017    package org.apache.commons.el;
018    
019    import java.math.BigInteger;
020    
021    import javax.servlet.jsp.el.ELException;
022    
023    import org.apache.commons.logging.Log;
024    import 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    
034    public 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    }