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 }