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: * MapStringExpression.java
027: * ------------
028: * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
029: */package org.jfree.report.function.strings;
030:
031: import java.util.ArrayList;
032: import java.util.Arrays;
033:
034: import org.jfree.report.function.AbstractExpression;
035: import org.jfree.report.function.Expression;
036:
037: /**
038: * Maps a string read from a column into an other string. The possible mappings
039: * are given as (key, text) pairs. If the string from the column is null or
040: * matches none of the defined keys, a fallback value is returned.
041: *
042: * If the fallback value is undefined, the original value is returned instead.
043: *
044: * @author Thomas Morgner
045: */
046: public class MapStringExpression extends AbstractExpression {
047: /**
048: * The field from where to read the key value.
049: */
050: private String field;
051: /**
052: * The list of possible keys.
053: */
054: private ArrayList keys;
055: /**
056: * The list of mapped values.
057: */
058: private ArrayList values;
059: /**
060: * A flag defining, whether the key-lookup should be case-insensitive.
061: */
062: private boolean ignoreCase;
063: /**
064: * The fallback value is returned if none of the defined keys matches.
065: */
066: private String fallbackValue;
067: /**
068: * The null-value is returned if the key-field evaluates to <code>null</code>.
069: */
070: private String nullValue;
071:
072: /**
073: * Default Constructor.
074: */
075: public MapStringExpression() {
076: keys = new ArrayList();
077: values = new ArrayList();
078: }
079:
080: /**
081: * Returns the name of the field from where to read the key value.
082: *
083: * @return the field name.
084: */
085: public String getField() {
086: return field;
087: }
088:
089: /**
090: * Defines the name of the field from where to read the key value.
091: *
092: * @param field the field name.
093: */
094: public void setField(final String field) {
095: this .field = field;
096: }
097:
098: /**
099: * Returns the value that is returned if the key-field evaluates to <code>null</code>.
100: *
101: * @return the null-value.
102: */
103: public String getNullValue() {
104: return nullValue;
105: }
106:
107: /**
108: * Defines the value that is returned if the key-field evaluates to <code>null</code>.
109: *
110: * @param nullValue the null-value.
111: */
112: public void setNullValue(final String nullValue) {
113: this .nullValue = nullValue;
114: }
115:
116: /**
117: * Returns the value that is returned if none of the predefined keys matches the lookup-value.
118: *
119: * @return the fallback value.
120: */
121: public String getFallbackValue() {
122: return fallbackValue;
123: }
124:
125: /**
126: * Defines the value that is returned if none of the predefined keys matches the lookup-value.
127: *
128: * @param fallbackValue the fallback value.
129: */
130: public void setFallbackValue(final String fallbackValue) {
131: this .fallbackValue = fallbackValue;
132: }
133:
134: /**
135: * Defines a key value to which the lookup-field's value is compared. If the key is defined, a matching value must be
136: * defined too.
137: *
138: * @param index the index position of the key in the list.
139: * @param key the key value.
140: */
141: public void setKey(final int index, final String key) {
142: if (keys.size() == index) {
143: keys.add(key);
144: } else {
145: keys.set(index, key);
146: }
147: }
148:
149: /**
150: * Returns a key value at the given index.
151: *
152: * @param index the index position of the key in the list.
153: * @return the key value.
154: */
155: public String getKey(final int index) {
156: return (String) keys.get(index);
157: }
158:
159: /**
160: * Returns the number of keys defined in the expression.
161: *
162: * @return the number of keys.
163: */
164: public int getKeyCount() {
165: return keys.size();
166: }
167:
168: /**
169: * Returns all defined keys as string array.
170: *
171: * @return all defined keys.
172: */
173: public String[] getKey() {
174: return (String[]) keys.toArray(new String[keys.size()]);
175: }
176:
177: /**
178: * Defines all keys using the values from the string array.
179: *
180: * @param keys all defined keys.
181: */
182: public void setKey(final String[] keys) {
183: this .keys.clear();
184: this .keys.addAll(Arrays.asList(keys));
185: }
186:
187: /**
188: * Defines the mapped text for the key at the given position. This text is returned if the key matches the value
189: * read from the lookup-field column.
190: *
191: * @param index the index of the entry.
192: * @param value the text that is returned if the key is selected.
193: */
194: public void setText(final int index, final String value) {
195: if (values.size() == index) {
196: values.add(value);
197: } else {
198: values.set(index, value);
199: }
200: }
201:
202: /**
203: * Returns the mapped text for the key at the given position. This text is returned if the key matches the value
204: * read from the lookup-field column.
205: *
206: * @param index the index of the entry.
207: * @return the text that is returned if the key is selected.
208: */
209: public String getText(final int index) {
210: return (String) values.get(index);
211: }
212:
213: /**
214: * Returns the number of replacement text defined in this expression. This should match the number of keys defined.
215: * @return the number of texts defined.
216: */
217: public int getTextCount() {
218: return values.size();
219: }
220:
221: /**
222: * Returns all defined texts as string-array.
223: *
224: * @return all texts.
225: */
226: public String[] getText() {
227: return (String[]) values.toArray(new String[values.size()]);
228: }
229:
230: /**
231: * Defines all texts by using the values from the given text-array.
232: * @param texts the new text-values.
233: */
234: public void setText(final String[] texts) {
235: this .values.clear();
236: this .values.addAll(Arrays.asList(texts));
237: }
238:
239: /**
240: * Returns, whether the key-lookup should be case-insensitive.
241: *
242: * @return true, if the key comparison is case-insensitive, false otherwise.
243: */
244: public boolean isIgnoreCase() {
245: return ignoreCase;
246: }
247:
248: /**
249: * Defines, whether the key-lookup should be case-insensitive.
250: *
251: * @param ignoreCase true, if the key comparison is case-insensitive, false otherwise.
252: */
253: public void setIgnoreCase(final boolean ignoreCase) {
254: this .ignoreCase = ignoreCase;
255: }
256:
257: /**
258: * Return a completly separated copy of this function. The copy does no longer share any changeable objects with the
259: * original function.
260: *
261: * @return a copy of this function.
262: */
263: public Expression getInstance() {
264: final MapStringExpression co = (MapStringExpression) super
265: .getInstance();
266: co.values = (ArrayList) values.clone();
267: co.keys = (ArrayList) keys.clone();
268: return co;
269: }
270:
271: /**
272: * Performs the lookup by first querying the given field, and then returning the defined text for the key-position.
273: *
274: * @return the value of the function.
275: */
276: public Object getValue() {
277: final Object raw = getDataRow().get(getField());
278: if (raw == null) {
279: return getNullValue();
280: }
281: final String text = String.valueOf(raw);
282: final int length = Math.min(keys.size(), values.size());
283: for (int i = 0; i < length; i++) {
284: final String key = (String) keys.get(i);
285: if (isIgnoreCase()) {
286: if (text.equalsIgnoreCase(key)) {
287: return values.get(i);
288: }
289: } else {
290: if (text.equals(key)) {
291: return values.get(i);
292: }
293: }
294: }
295: final String fallbackValue = getFallbackValue();
296: if (fallbackValue != null) {
297: return fallbackValue;
298: }
299: return raw;
300: }
301: }
|