001    /**
002     * ========================================
003     * JFreeReport : a free Java report library
004     * ========================================
005     *
006     * Project Info:  http://reporting.pentaho.org/
007     *
008     * (C) Copyright 2000-2007, by Object Refinery Limited, 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     * $Id: FormulaExpression.java 3048 2007-07-28 18:02:42Z tmorgner $
027     * ------------
028     * (C) Copyright 2000-2005, by Object Refinery Limited.
029     * (C) Copyright 2005-2007, by Pentaho Corporation.
030     */
031    
032    package org.jfree.report.expressions;
033    
034    import org.jfree.formula.Formula;
035    import org.jfree.formula.FormulaContext;
036    import org.jfree.formula.parser.ParseException;
037    import org.jfree.report.DataSourceException;
038    import org.jfree.report.flow.ReportContext;
039    import org.jfree.util.Log;
040    
041    /**
042     * Creation-Date: 04.11.2006, 19:24:04
043     *
044     * @author Thomas Morgner
045     */
046    public class FormulaExpression extends AbstractExpression
047    {
048      private transient Formula compiledFormula;
049      private String formulaNamespace;
050      private String formulaExpression;
051      private String formula;
052    
053      public FormulaExpression()
054      {
055      }
056    
057      private synchronized FormulaContext getFormulaContext()
058      {
059        final ReportContext globalContext = getRuntime().getReportContext();
060        return globalContext.getFormulaContext();
061      }
062    
063      public String getFormula()
064      {
065        return formula;
066      }
067    
068      public String getFormulaNamespace()
069      {
070        return formulaNamespace;
071      }
072    
073      public String getFormulaExpression()
074      {
075        return formulaExpression;
076      }
077    
078      public void setFormula(final String formula)
079      {
080        this.formula = formula;
081        if (formula == null)
082        {
083          formulaNamespace = null;
084          formulaExpression = null;
085        }
086        else
087        {
088          final int separator = formula.indexOf(':');
089          if (separator <= 0 || ((separator + 1) == formula.length()))
090          {
091            if (formula.startsWith("="))
092            {
093              formulaNamespace = "report";
094              formulaExpression = formula.substring(1);
095            }
096            else
097            {
098              // error: invalid formula.
099              formulaNamespace = null;
100              formulaExpression = null;
101            }
102          }
103          else
104          {
105            formulaNamespace = formula.substring(0, separator);
106            formulaExpression = formula.substring(separator + 1);
107          }
108        }
109        this.compiledFormula = null;
110      }
111    
112      private Object computeRegularValue()
113      {
114        try
115        {
116          if (compiledFormula == null)
117          {
118            compiledFormula = new Formula(formulaExpression);
119          }
120    
121          final ReportFormulaContext context =
122              new ReportFormulaContext(getFormulaContext(), getDataRow());
123          try
124          {
125            compiledFormula.initialize(context);
126            return compiledFormula.evaluate();
127          }
128          finally
129          {
130            context.setDataRow(null);
131          }
132        }
133        catch (Exception e)
134        {
135          Log.debug("Failed to compute the regular value.", e);
136          return null;
137        }
138      }
139    
140      /**
141       * Returns the compiled formula. The formula is not connected to a formula
142       * context.
143       *
144       * @return the formula.
145       * @throws ParseException if the formula contains syntax errors.
146       */
147      public Formula getCompiledFormula()
148          throws ParseException
149      {
150        if (compiledFormula == null)
151        {
152          compiledFormula = new Formula(formulaExpression);
153        }
154        return compiledFormula;
155      }
156    
157      /**
158       * Return the current expression value. <P> The value depends (obviously) on
159       * the expression implementation.
160       *
161       * @return the value of the function.
162       */
163      public Object computeValue() throws DataSourceException
164      {
165        try
166        {
167          return computeRegularValue();
168        }
169        catch (Exception e)
170        {
171          return null;
172        }
173      }
174    
175      /**
176       * Clones the expression, expression should be reinitialized after the
177       * cloning. <P> Expression maintain no state, cloning is done at the beginning
178       * of the report processing to disconnect the used expression from any other
179       * object space.
180       *
181       * @return A clone of this expression.
182       * @throws CloneNotSupportedException this should never happen.
183       */
184      public Object clone() throws CloneNotSupportedException
185      {
186        final FormulaExpression o = (FormulaExpression) super.clone();
187        if (compiledFormula != null)
188        {
189          o.compiledFormula = (Formula) compiledFormula.clone();
190        }
191        return o;
192      }
193    }