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 }