001: /*
002: * ============================================================================
003: * GNU Lesser General Public License
004: * ============================================================================
005: *
006: * JasperReports - Free Java report-generating library.
007: * Copyright (C) 2001-2006 JasperSoft Corporation http://www.jaspersoft.com
008: *
009: * This library is free software; you can redistribute it and/or
010: * modify it under the terms of the GNU Lesser General Public
011: * License as published by the Free Software Foundation; either
012: * 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,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: * Lesser General Public License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
022: *
023: * JasperSoft Corporation
024: * 303 Second Street, Suite 450 North
025: * San Francisco, CA 94107
026: * http://www.jaspersoft.com
027: */
028: package net.sf.jasperreports.crosstabs.fill.calculation;
029:
030: import java.util.Comparator;
031:
032: import net.sf.jasperreports.engine.JRException;
033:
034: import org.apache.commons.collections.comparators.ReverseComparator;
035:
036: /**
037: * Bucket definition.
038: *
039: * @author Lucian Chirita (lucianc@users.sourceforge.net)
040: * @version $Id: BucketDefinition.java 1229 2006-04-19 10:27:35Z teodord $
041: */
042: public class BucketDefinition {
043: /**
044: * Ascending order constant.
045: */
046: public static final byte ORDER_ASCENDING = 1;
047:
048: /**
049: * Descending order constant.
050: */
051: public static final byte ORDER_DESCENDING = 2;
052:
053: /**
054: * Constant indicating that total are not required for this bucket.
055: */
056: public static final byte TOTAL_POSITION_NONE = 0;
057:
058: /**
059: * Constants indicating that totals are to be positioned before the other buckets.
060: */
061: public static final byte TOTAL_POSITION_START = 1;
062:
063: /**
064: * Constants indicating that totals are to be positioned at the end of the other buckets.
065: */
066: public static final byte TOTAL_POSITION_END = 2;
067:
068: /**
069: * Value type used for non-null values.
070: */
071: protected static final byte VALUE_TYPE_VALUE = 0;
072:
073: /**
074: * Value type used for null bucket values.
075: */
076: protected static final byte VALUE_TYPE_NULL = 1;
077:
078: /**
079: * Value type used for total buckets.
080: */
081: protected static final byte VALUE_TYPE_TOTAL = 2;
082:
083: /**
084: * The total value for this bucket.
085: */
086: protected final Bucket VALUE_TOTAL = new Bucket(VALUE_TYPE_TOTAL);
087:
088: /**
089: * The null bucket.
090: */
091: protected final Bucket VALUE_NULL = new Bucket(VALUE_TYPE_NULL);
092:
093: protected final Comparator comparator;
094: private final byte totalPosition;
095:
096: private boolean computeTotal;
097:
098: /**
099: * Creates a bucket.
100: *
101: * @param valueClass the class of the bucket values
102: * @param comparator the comparator to use for bucket sorting
103: * @param order the order type, {@link #ORDER_ASCENDING ORDER_ASCENDING} or {@link #ORDER_DESCENDING ORDER_DESCENDING} descending
104: * @param totalPosition the position of the total bucket
105: * @throws JRException
106: */
107: public BucketDefinition(Class valueClass, Comparator comparator,
108: byte order, byte totalPosition) throws JRException {
109: if (comparator == null
110: && !Comparable.class.isAssignableFrom(valueClass)) {
111: throw new JRException(
112: "The bucket expression values are not comparable and no comparator specified.");
113: }
114:
115: switch (order) {
116: case ORDER_DESCENDING: {
117: if (comparator == null) {
118: this .comparator = new ReverseComparator();
119: } else {
120: this .comparator = new ReverseComparator(comparator);
121: }
122: break;
123: }
124: case ORDER_ASCENDING:
125: default: {
126: this .comparator = comparator;
127: break;
128: }
129: }
130:
131: this .totalPosition = totalPosition;
132: computeTotal = totalPosition != TOTAL_POSITION_NONE;
133: }
134:
135: /**
136: * Whether this bucket needs total calculation.
137: *
138: * @return this bucket needs total calculation
139: */
140: public boolean computeTotal() {
141: return computeTotal;
142: }
143:
144: /**
145: * Instructs that the bucket will need total bucket calculation.
146: *
147: * @see #computeTotal()
148: */
149: public void setComputeTotal() {
150: computeTotal = true;
151: }
152:
153: /**
154: * Returns the total bucket position.
155: *
156: * @return the total bucket position
157: */
158: public byte getTotalPosition() {
159: return totalPosition;
160: }
161:
162: /**
163: * Returns the comparator used for bucket ordering.
164: *
165: * @return the comparator used for bucket ordering
166: */
167: public Comparator getComparator() {
168: return comparator;
169: }
170:
171: /**
172: * Creates a {@link Bucket BucketValue} object for a given value.
173: *
174: * @param value the value
175: * @return the corresponding {@link Bucket BucketValue} object
176: */
177: public Bucket create(Object value) {
178: if (value == null) {
179: return VALUE_NULL;
180: }
181:
182: return new Bucket(value);
183: }
184:
185: /**
186: * Bucket value class.
187: *
188: * @author Lucian Chirita (lucianc@users.sourceforge.net)
189: */
190: public class Bucket implements Comparable {
191: private final Object value;
192: private final byte type;
193:
194: /**
195: * Creates a bucket for a value type.
196: *
197: * @param type the value type
198: */
199: protected Bucket(byte type) {
200: this .value = null;
201: this .type = type;
202: }
203:
204: /**
205: * Creates a bucket for a value.
206: *
207: * @param value the value
208: */
209: protected Bucket(Object value) {
210: this .value = value;
211: this .type = VALUE_TYPE_VALUE;
212: }
213:
214: /**
215: * Returns the bucket value.
216: *
217: * @return the bucket value
218: */
219: public Object getValue() {
220: return value;
221: }
222:
223: public boolean equals(Object o) {
224: if (o == null || !(o instanceof Bucket)) {
225: return false;
226: }
227:
228: if (o == this ) {
229: return true;
230: }
231:
232: Bucket v = (Bucket) o;
233:
234: if (type != VALUE_TYPE_VALUE) {
235: return type == v.type;
236: }
237:
238: return v.type == VALUE_TYPE_VALUE && value.equals(v.value);
239: }
240:
241: public int hashCode() {
242: int hash = type;
243:
244: if (type == VALUE_TYPE_VALUE) {
245: hash = 37 * hash + value.hashCode();
246: }
247:
248: return hash;
249: }
250:
251: public String toString() {
252: switch (type) {
253: case VALUE_TYPE_NULL:
254: return "NULL";
255: case VALUE_TYPE_TOTAL:
256: return "TOTAL";
257: case VALUE_TYPE_VALUE:
258: default:
259: return String.valueOf(value);
260: }
261: }
262:
263: public int compareTo(Object o) {
264: Bucket val = (Bucket) o;
265: if (type != val.type) {
266: return type - val.type;
267: }
268:
269: if (type != VALUE_TYPE_VALUE) {
270: return 0;
271: }
272:
273: if (comparator != null) {
274: return comparator.compare(value, val.value);
275: }
276:
277: return ((Comparable) value).compareTo(val.value);
278: }
279:
280: /**
281: * Decides whether this is a total bucket.
282: *
283: * @return whether this is a total bucket
284: */
285: public boolean isTotal() {
286: return type == VALUE_TYPE_TOTAL;
287: }
288: }
289: }
|