001    /**
002     * =========================================
003     * LibFormula : a free Java formula library
004     * =========================================
005     *
006     * Project Info:  http://reporting.pentaho.org/libformula/
007     *
008     * (C) Copyright 2006-2007, by Pentaho Corporation and Contributors.
009     *
010     * This library is free software; you can redistribute it and/or modify it under the terms
011     * of the GNU Lesser General Public License as published by the Free Software Foundation;
012     * either version 2.1 of the License, or (at your option) any later version.
013     *
014     * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
015     * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016     * See the GNU Lesser General Public License for more details.
017     *
018     * You should have received a copy of the GNU Lesser General Public License along with this
019     * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
020     * Boston, MA 02111-1307, USA.
021     *
022     * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
023     * in the United States and other countries.]
024     *
025     *
026     * ------------
027     * $Id: Formula.java 3515 2007-10-16 09:22:24Z tmorgner $
028     * ------------
029     * (C) Copyright 2006-2007, by Pentaho Corporation.
030     */
031    package org.jfree.formula;
032    
033    import java.io.Serializable;
034    
035    import org.jfree.formula.lvalues.LValue;
036    import org.jfree.formula.lvalues.TypeValuePair;
037    import org.jfree.formula.parser.FormulaParser;
038    import org.jfree.formula.parser.ParseException;
039    import org.jfree.formula.parser.TokenMgrError;
040    import org.jfree.formula.typing.Type;
041    import org.jfree.formula.typing.coretypes.ErrorType;
042    import org.jfree.util.Log;
043    
044    /**
045     * Creation-Date: 31.10.2006, 14:43:05
046     *
047     * @author Thomas Morgner
048     */
049    public class Formula implements Serializable, Cloneable
050    {
051      private LValue rootReference;
052    
053      public Formula(final String formulaText) throws ParseException
054      {
055        try
056        {
057          final FormulaParser parser = new FormulaParser();
058          this.rootReference = parser.parse(formulaText);
059        }
060        catch(TokenMgrError tokenMgrError)
061        {
062          // This is ugly.
063          throw new ParseException(tokenMgrError.getMessage());
064        }
065      }
066    
067      public Formula(final LValue rootReference)
068      {
069        this.rootReference = rootReference;
070      }
071    
072      public void initialize (final FormulaContext context) throws EvaluationException
073      {
074        rootReference.initialize(context);
075      }
076    
077      /**
078       * Returns the root reference for this formula. This allows external programms
079       * to modify the formula directly.
080       *
081       * @return
082       */
083      public LValue getRootReference()
084      {
085        return rootReference;
086      }
087    
088      public TypeValuePair evaluateTyped ()
089      {
090        try
091        {
092          final TypeValuePair typeValuePair = rootReference.evaluate();
093          if (typeValuePair == null)
094          {
095            // Should no longer happen..
096            return new TypeValuePair
097                (ErrorType.TYPE, LibFormulaErrorValue.ERROR_NA_VALUE);
098          }
099          if(typeValuePair.getType().isFlagSet(Type.ERROR_TYPE))
100          {
101            Log.debug ("Error: " + typeValuePair.getValue());
102          }
103          return typeValuePair;
104        }
105        catch(EvaluationException ee)
106        {
107          return new TypeValuePair(ErrorType.TYPE, ee.getErrorValue());
108        }
109        catch (Exception e)
110        {
111          Log.warn ("Evaluation failed unexpectedly: ", e);
112          return new TypeValuePair(ErrorType.TYPE, LibFormulaErrorValue.ERROR_UNEXPECTED_VALUE);
113        }
114      }
115      
116      public Object evaluate ()
117      {
118        return evaluateTyped().getValue();
119      }
120    
121      public Object clone () throws CloneNotSupportedException
122      {
123        final Formula o = (Formula) super.clone();
124        o.rootReference = (LValue) rootReference.clone();
125        return o;
126      }
127    }