001: /**
002: * ===========================================
003: * JFreeReport : a free Java reporting library
004: * ===========================================
005: *
006: * Project Info: http://reporting.pentaho.org/
007: *
008: * (C) Copyright 2001-2007, by Object Refinery Ltd, 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: * AbstractExpression.java
027: * ------------
028: * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
029: */package org.jfree.report.function;
030:
031: import java.io.Serializable;
032:
033: import org.jfree.report.DataRow;
034: import org.jfree.report.ResourceBundleFactory;
035: import org.jfree.util.Configuration;
036:
037: /**
038: * An abstract base class for implementing new report expressions.
039: * <p/>
040: * Expressions are stateless functions which have access to the report's {@link DataRow}. All expressions are named and
041: * the defined names have to be unique within the report's expressions, functions and fields of the datasource.
042: * Expressions are configured using properties.
043: * <p/>
044: *
045: * @author Thomas Morgner
046: */
047: public abstract class AbstractExpression implements Expression,
048: Serializable {
049: /**
050: * The expression name.
051: */
052: private String name;
053:
054: /**
055: * The dependency level.
056: */
057: private int dependency;
058:
059: /**
060: * The data row.
061: */
062: private transient ExpressionRuntime runtime;
063:
064: /**
065: * A flag indicating whether the expression's result should be preserved in the datarow even when the expression
066: * itself goes out of scope.
067: */
068: private boolean preserve;
069:
070: /**
071: * Creates an unnamed expression. Make sure the name of the expression is set using {@link #setName} before the
072: * expression is added to the report's expression collection.
073: */
074: protected AbstractExpression() {
075: name = super .toString();
076: }
077:
078: /**
079: * Returns the name of the expression.
080: *
081: * @return the name.
082: */
083: public String getName() {
084: return name;
085: }
086:
087: /**
088: * Sets the name of the expression. <P> The name should be unique among: <ul> <li>the functions and expressions for
089: * the report; <li>the columns in the report's <code>TableModel</code>; </ul> This allows the expression to be
090: * referenced by name from any report element.
091: * <p/>
092: * You should not change the name of an expression once it has been added to the report's expression collection.
093: *
094: * @param name the name (<code>null</code> not permitted).
095: */
096: public void setName(final String name) {
097: if (name == null) {
098: throw new NullPointerException(
099: "AbstractExpression.setName(...) : name is null.");
100: }
101: this .name = name;
102: }
103:
104: /**
105: * Returns <code>true</code> if this expression contains "auto-active" content and should be called by the system
106: * regardless of whether this expression is referenced in the {@link DataRow}.
107: *
108: * @return true as all expressions are always evaluated now.
109: * @deprecated The Active-Flag is no longer evaluated. We always assume it to be true.
110: */
111: public final boolean isActive() {
112: return true;
113: }
114:
115: /**
116: * Defines, whether the expression is an active expression. This method has no effect anymore.
117: *
118: * @param active a flag.
119: * @deprecated All expressions are always active. This method has no effect anymore.
120: */
121: public final void setActive(final boolean active) {
122: }
123:
124: /**
125: * Returns the dependency level for the expression (controls evaluation order for expressions and functions).
126: *
127: * @return the level.
128: */
129: public int getDependencyLevel() {
130: return dependency;
131: }
132:
133: /**
134: * Sets the dependency level for the expression.
135: * <p/>
136: * The dependency level controls the order of evaluation for expressions and functions. Higher level expressions are
137: * evaluated before lower level expressions. Any level in the range 0 to Integer.MAX_VALUE is allowed. Negative
138: * values are reserved for system functions (printing and layouting).
139: *
140: * @param level the level (must be greater than or equal to 0).
141: */
142: public void setDependencyLevel(final int level) {
143: if (level < 0) {
144: throw new IllegalArgumentException(
145: "AbstractExpression.setDependencyLevel(...) : negative "
146: + "dependency not allowed for user-defined expressions.");
147: }
148: this .dependency = level;
149: }
150:
151: /**
152: * Returns the current {@link DataRow}.
153: *
154: * @return the data row.
155: */
156: public DataRow getDataRow() {
157: if (runtime == null) {
158: throw new IllegalStateException("Runtime is null");
159: }
160: return runtime.getDataRow();
161: }
162:
163: /**
164: * Clones the expression. The expression should be reinitialized after the cloning. <P> Expressions maintain no
165: * state, cloning is done at the beginning of the report processing to disconnect the expression from any other object
166: * space.
167: *
168: * @return a clone of this expression.
169: * @throws CloneNotSupportedException this should never happen.
170: */
171: public Object clone() throws CloneNotSupportedException {
172: return super .clone();
173: }
174:
175: /**
176: * Return a completly separated copy of this function. The copy does no longer share any changeable objects with the
177: * original function.
178: *
179: * @return a copy of this function.
180: */
181: public Expression getInstance() {
182: try {
183: final AbstractExpression abstractExpression = (AbstractExpression) clone();
184: abstractExpression.setRuntime(null);
185: return abstractExpression;
186: } catch (CloneNotSupportedException cne) {
187: throw new IllegalStateException(
188: "Clone must always be supported.");
189: }
190: }
191:
192: public ResourceBundleFactory getResourceBundleFactory() {
193: if (runtime == null) {
194: throw new IllegalStateException("Runtime is null");
195: }
196: return runtime.getResourceBundleFactory();
197: }
198:
199: public Configuration getReportConfiguration() {
200: if (runtime == null) {
201: throw new IllegalStateException("Runtime is null");
202: }
203: return runtime.getConfiguration();
204: }
205:
206: /**
207: * Defines the ExpressionRune used in this expression. The ExpressionRuntime is set before the expression
208: * receives events or gets evaluated and is unset afterwards. Do not hold references on the runtime or you
209: * will create memory-leaks.
210: *
211: * @param runtime the runtime information for the expression
212: */
213: public void setRuntime(final ExpressionRuntime runtime) {
214: this .runtime = runtime;
215: }
216:
217: /**
218: * Returns the ExpressionRune used in this expression. The ExpressionRuntime is set before the expression
219: * receives events or gets evaluated and is unset afterwards. Do not hold references on the runtime or you
220: * will create memory-leaks.
221: *
222: * @return the runtime information for the expression
223: */
224: public ExpressionRuntime getRuntime() {
225: return runtime;
226: }
227:
228: /**
229: * Checks, whether this expression is a deep-traversing expression. Deep-traversing expressions receive
230: * events from all sub-reports. This returns false by default, as ordinary expressions have no need to be
231: * deep-traversing.
232: *
233: * @return false.
234: */
235: public boolean isDeepTraversing() {
236: return false;
237: }
238:
239: /**
240: * Checks, whether this expression's last value is preserved after the expression goes out of scope.
241: *
242: * @return true, if the expression's last value is preserved, false otherwise.
243: */
244: public boolean isPreserve() {
245: return preserve;
246: }
247:
248: /**
249: * Defines, whether this expression's last value is preserved after the expression goes out of scope.
250: *
251: * @param preserve true, if the expression's last value is preserved, false otherwise.
252: */
253: public void setPreserve(final boolean preserve) {
254: this.preserve = preserve;
255: }
256: }
|