View Javadoc

1   /***
2    * BaseReportFilter.java
3    *
4    * This file is part of the creme library.
5    * The creme library intends to ease the development effort of large
6    * applications by providing easy to use support classes.
7    *
8    * Copyright (C) 2002 Denis Bregeon
9    *
10   * This library is free software; you can redistribute it and/or
11   * modify it under the terms of the GNU Lesser General Public
12   * License as published by the Free Software Foundation; either
13   * version 2.1 of the License, or (at your option) any later version.
14   *
15   * This library is distributed in the hope that it will be useful,
16   * but WITHOUT ANY WARRANTY; without even the implied warranty of
17   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18   * Lesser General Public License for more details.
19   *
20   * You should have received a copy of the GNU Lesser General Public
21   * License along with this library; if not, write to the Free Software
22   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23   *
24   * contact information: dbregeon@sourceforge.net
25   */
26  package org.jcreme.filters;
27  
28  import java.io.IOException;
29  import java.io.ObjectInputStream;
30  import java.io.Serializable;
31  import java.util.HashSet;
32  
33  /***
34   * The abstract base class for every ReportFilter. Implements handling of
35   * listeners and events.
36   * 
37   * @author $Author: dbregeon $
38   * @version $Revision: 1.2 $
39   */
40  public abstract class BaseReportFilter implements ReportFilter, Serializable {
41  	static final long serialVersionUID = 6301508704547758851L;
42  
43  	/***
44  	 * A set of all FilterChangeListener attached to this ReportFilter object.
45  	 */
46  	private transient HashSet listeners = new HashSet();
47  
48  	/***
49  	 * This enables to add a listener for the changes of the filter.
50  	 * 
51  	 * @param listener
52  	 *            the object that will react to the modifications.
53  	 */
54  	public synchronized void addFilterChangeListener(
55  			final FilterChangeListener listener) {
56  		if (listener != null) {
57  			this.listeners.add(listener);
58  		}
59  	}
60  
61  	/***
62  	 * Fires the passed in FilterChangeEvent if there was an actual modification
63  	 * from oldValue to newValue.
64  	 * 
65  	 * @param evt
66  	 *            The FilterChangeEvent to be fired.
67  	 */
68  	protected synchronized void fireFilterChangeEvent(
69  			final FilterChangeEvent evt) {
70  		final Object oldValue = evt.getOldValue();
71  		final Object newValue = evt.getNewValue();
72  		boolean filterReallyChanged = ((oldValue == null) && (newValue != null))
73  				|| ((oldValue != null) && (newValue == null))
74  				|| ((oldValue instanceof Filter)
75  						&& (newValue instanceof Filter) && (!newValue
76  						.equals(oldValue)));
77  		if ((!filterReallyChanged) && (oldValue instanceof Filter[])
78  				&& (newValue instanceof Filter[])) {
79  			final Filter[] oldFilters = (Filter[]) oldValue;
80  			final Filter[] newFilters = (Filter[]) newValue;
81  			filterReallyChanged = oldFilters.length != newFilters.length;
82  			for (int i = 0; (i < oldFilters.length) && (!filterReallyChanged); i++) {
83  				filterReallyChanged = ((oldFilters[i] != null) && (!oldFilters[i]
84  						.equals(newFilters[i])))
85  						|| ((newFilters[i] != null) && (!newFilters[i]
86  								.equals(oldFilters[i])));
87  			}
88  		}
89  		if (filterReallyChanged) {
90  			final Object[] theListeners = this.listeners.toArray();
91  			for (int i = 0; i < theListeners.length; i++) {
92  				((FilterChangeListener) theListeners[i]).filterChanged(evt);
93  			}
94  		}
95  	}
96  
97  	/***
98  	 * Builds a new FilterChangeEvent from the passed in parameters.
99  	 * 
100 	 * @param propertyName
101 	 *            The property that has changed.
102 	 * @param oldValue
103 	 *            The previous value associated to the given property.
104 	 * @param newValue
105 	 *            The new value associated to the given property.
106 	 * @return The built FilterChangeEvent.
107 	 */
108 	protected FilterChangeEvent buildEvent(final String propertyName,
109 			final Object oldValue, final Object newValue) {
110 		return new FilterChangeEvent(this, propertyName, oldValue, newValue);
111 	}
112 
113 	/***
114 	 * This enables to remove a listener for the changes of the filter.
115 	 * 
116 	 * @param listener
117 	 *            the listener to remove.
118 	 */
119 	public synchronized void removeFilterChangeListener(
120 			final FilterChangeListener listener) {
121 		if (listener != null) {
122 			this.listeners.remove(listener);
123 		}
124 	}
125 
126 	/***
127 	 * This method clones this filter adds its listeners to its clone.
128 	 * 
129 	 * @return the cloned BaseReportFilter.
130 	 */
131 	public Object clone() {
132 		BaseReportFilter clonedFilter = null;
133 		try {
134 			clonedFilter = (BaseReportFilter) super.clone();
135 			clonedFilter.listeners.addAll(this.listeners);
136 		} catch (CloneNotSupportedException e) {
137 			e.printStackTrace();
138 		}
139 		return clonedFilter;
140 	}
141 
142 	private void readObject(final ObjectInputStream i) throws IOException,
143 			ClassNotFoundException {
144 		this.listeners = new HashSet();
145 		i.defaultReadObject();
146 	}
147 
148 	/***
149 	 * Convenience method that tests whether two filters are equal.
150 	 * 
151 	 * @param a
152 	 *            The first filter.
153 	 * @param b
154 	 *            The second filter.
155 	 * @return True if the filters are equal, false otherwise.
156 	 */
157 	protected boolean filtersAreEqual(final Filter a, final Filter b) {
158 		return ((a == null) && (b == null)) || ((a != null) && a.equals(b));
159 	}
160 
161 	/***
162 	 * Convenience method that tests whether two arrays of filters are equal.
163 	 * 
164 	 * @param a
165 	 *            The first array of filters.
166 	 * @param b
167 	 *            The second array of filters.
168 	 * @return True if corresponding filters of both arrays are all equal to
169 	 *         each other, false otherwise.
170 	 */
171 	protected boolean filtersAreEqual(final Filter[] a, final Filter[] b) {
172 		boolean result = (a == b);
173 		if (!result) {
174 			result = (a.length == b.length);
175 			for (int i = 0; (result) && (i < a.length); i++) {
176 				result = result && (filtersAreEqual(a[i], b[i]));
177 			}
178 		}
179 		return result;
180 	}
181 
182 }