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 }