KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > j2ee > sun > share > configbean > ErrorMessageDB


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 /*
20  * ErrorMessageDB.java
21  *
22  * Created on March 4, 2004, 12:14 PM
23  */

24
25 package org.netbeans.modules.j2ee.sun.share.configbean;
26
27 import java.util.Collections JavaDoc;
28 import java.util.Collection JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.List JavaDoc;
31 import java.util.Map JavaDoc;
32 import java.util.Set JavaDoc;
33
34 import java.util.HashMap JavaDoc;
35 import java.util.ArrayList JavaDoc;
36
37 import java.beans.PropertyChangeEvent JavaDoc;
38 import java.beans.PropertyChangeListener JavaDoc;
39 import java.beans.PropertyChangeSupport JavaDoc;
40
41
42 /** This is an error message database for storing partitioned error messages
43  * of class ValidationError (partition, fieldId (xpath), message).
44  *
45  * @author Peter Williams
46  */

47 public final class ErrorMessageDB {
48     
49     /** The database. This is a mapping of keys to collections, where the key
50      * is a message partition (ValidationError.Partition) and the value is a
51      * collection of error objects within that partition. As validation requests
52      * are made, errors are added and removed. If a partition has no errors,
53      * it is removed from the map so that the keyset of the map always represents
54      * exactly the partitions that have errors.
55      */

56     private Map JavaDoc errorSets = new HashMap JavaDoc(19); // 19 = 2x max expected partitions
57

58     
59     /** Creates a new instance of ErrorMessageDB.
60      */

61     private ErrorMessageDB() {
62     }
63     
64
65     /** Set of partitions that currently have errors.
66      *
67      * @return Set of ValidationError.Partition
68      */

69     public Set JavaDoc getErrorPartitions() {
70         // keySet() always returns non-null so we're ok just passing this on.
71
return Collections.unmodifiableSet(errorSets.keySet());
72     }
73
74     
75     /** Retrieves the list of errors associated with a particular partition
76      *
77      * @param partition to get errors for.
78      * @return List of ValidationErrors, null if no errors.
79      */

80     public List JavaDoc getErrors(ValidationError.Partition partition) {
81         // unmodifiableList does not support a null parameter, but if there are
82
// no errors, the list will be null so we have to pass the null through.
83
List JavaDoc errorList = (List JavaDoc) errorSets.get(partition);
84         if(errorList != null) {
85             errorList = Collections.unmodifiableList(errorList);
86         }
87         return errorList;
88     }
89
90     
91     /** Adds a collection of errors to the error list. Duplicates will overwrite
92      * any matching existing error if the message is different. (This allows
93      * for a message to change as the user types, for example, from "null is
94      * invalid" to "invalid character".
95      *
96      * @param errors Collection of error messages.
97      */

98     public void addErrors(Collection JavaDoc errors) {
99         for(Iterator JavaDoc iter = errors.iterator(); iter.hasNext(); ) {
100             addErrorImpl((ValidationError) iter.next());
101         }
102     }
103     
104     
105     /** Adds an error string to the error list. Duplicates will overwrite
106      * any matching existing error if the message is different. (This allows
107      * for a message to change as the user types, for example, from "null is
108      * invalid" to "invalid character".
109      *
110      * @param error error message
111      */

112     public void addError(ValidationError error) {
113         addErrorImpl(error);
114     }
115     
116     
117     /** Remove the specified message from the database. The error passed in
118      * does not have to have a message field, only a partition and a fieldId,
119      * If this error is the last one in it's partition, that partition will also
120      * be removed.
121      *
122      * @param error Matches the error to be removed using the algorithm provided
123      * by ValidationError.equals().
124      */

125     public void removeError(ValidationError error) {
126         List JavaDoc errorList = (List JavaDoc) errorSets.get(error.getPartition());
127         if(errorList != null) {
128             int index = errorList.indexOf(error);
129             if(index != -1) {
130                 errorList.remove(index);
131                 firePartitionStateChanged(error.getPartition(), true, (errorList.size() != 0));
132             }
133
134             if(errorList.size() == 0) {
135                 errorSets.remove(error.getPartition());
136                 
137                 // If we've removed all the partitions, then the bean is now valid,
138
// (possibly temporarily, but we can batch things later if that is
139
// a problem.
140
if(errorSets.size() == 0) {
141                     fireValidationStateChanged(true);
142                 }
143             }
144         }
145     }
146     
147     
148     /** Update the message for this field. This means add or change the message
149      * if this error contains a message, or remove this message if it does not.
150      *
151      * @param error Matches the error to be removed using the algorithm provided
152      * by ValidationError.equals().
153      */

154     public void updateError(ValidationError error) {
155         if(Utils.notEmpty(error.getMessage())) {
156             addErrorImpl(error);
157         } else {
158             removeError(error);
159         }
160     }
161     
162     
163     private void addErrorImpl(ValidationError error) {
164         // Save whether or not we were valid before this addition
165
boolean oldIsValid = (errorSets.size() == 0);
166         
167         List JavaDoc errorList = getOrCreateErrorList(error.getPartition());
168         
169         // Save whether or not this partition had errors before this addition
170
boolean oldHasMessages = (errorList.size() != 0);
171         
172         if(errorList.contains(error)) {
173             errorList.remove(error);
174         }
175         
176         errorList.add(error);
177         
178         // If we were valid before, we're not now.
179
if(oldIsValid) {
180             fireValidationStateChanged(false);
181         }
182         
183         // We added or changed a message, thus the partition has changed
184
firePartitionStateChanged(error.getPartition(), oldHasMessages, true);
185     }
186     
187     
188     private List JavaDoc getOrCreateErrorList(ValidationError.Partition partition) {
189         List JavaDoc errorList = (List JavaDoc) errorSets.get(partition);
190
191         if(errorList == null) {
192             errorList = new ArrayList JavaDoc();
193             errorSets.put(partition, errorList);
194         }
195         
196         return errorList;
197     }
198     
199     
200     /** Clears out all error messages.
201      */

202     public void clearErrors() {
203         int numInvalidPartitions = errorSets.size();
204         
205         // Is there anything to do?
206
if(numInvalidPartitions > 0) {
207             Collection JavaDoc partitionList = new ArrayList JavaDoc(errorSets.keySet());
208             errorSets.clear();
209             
210             // fire events to indicate that all that was invalid before is now valid.
211
fireValidationStateChanged(true);
212             for(Iterator JavaDoc iter = partitionList.iterator(); iter.hasNext(); ) {
213                 firePartitionStateChanged((ValidationError.Partition) iter.next(), true, false);
214             }
215         }
216     }
217     
218     
219     /** Test if there are currently any errors.
220      * @return true if there are errors of any kind, false if not.
221      */

222     public boolean hasErrors() {
223         return (errorSets.size() > 0);
224     }
225     
226     
227     /** Test if there are any errors in the specified partition
228      * @return true if there are errors in the partition, false otherwise.
229      */

230     public boolean hasErrors(ValidationError.Partition partition) {
231         boolean result = false;
232         
233         List JavaDoc errorList = (List JavaDoc) errorSets.get(partition);
234         if(errorList != null && errorList.size() > 0) {
235             result = true;
236         }
237         
238         return result;
239     }
240
241     
242     /** -----------------------------------------------------------------------
243      * Property change support
244      */

245     public static final String JavaDoc VALIDATION_STATE_CHANGED = "validationStateChanged";
246     public static final String JavaDoc PARTITION_STATE_CHANGED = "partitionStateChanged";
247     
248     private PropertyChangeSupport JavaDoc propertyChangeSupport = new PropertyChangeSupport JavaDoc(this);
249     
250     public void addPropertyChangeListener(PropertyChangeListener JavaDoc pCL) {
251         propertyChangeSupport.addPropertyChangeListener(pCL);
252     }
253     
254     public void removePropertyChangeListener(PropertyChangeListener JavaDoc pCL) {
255         propertyChangeSupport.removePropertyChangeListener(pCL);
256     }
257     
258     private void fireValidationStateChanged(boolean newState) {
259         propertyChangeSupport.firePropertyChange(VALIDATION_STATE_CHANGED, !newState, newState);
260     }
261     
262     private void firePartitionStateChanged(ValidationError.Partition partition, boolean oldHasMessages, boolean newHasMessages) {
263         PartitionState oldPartitionState = new PartitionState(partition, oldHasMessages);
264         PartitionState newPartitionState = new PartitionState(partition, newHasMessages);
265         propertyChangeSupport.firePropertyChange(PARTITION_STATE_CHANGED, oldPartitionState, newPartitionState);
266     }
267     
268     public static class PartitionState {
269         private final ValidationError.Partition thePartition;
270         private final boolean hasMessages;
271         
272         private PartitionState(final ValidationError.Partition partition, final boolean hasMsgs) {
273             thePartition = partition;
274             hasMessages = hasMsgs;
275         }
276         
277         public ValidationError.Partition getPartition() {
278             return thePartition;
279         }
280         
281         public boolean hasMessages() {
282             return hasMessages;
283         }
284     };
285     
286     
287     /** -----------------------------------------------------------------------
288      * Public API to retrieve the error db for a bean. Currently the DB
289      * is a bean member, but having the API here allows us to change this
290      * later if better optimized message storage is possible.
291      */

292     public static ErrorMessageDB getMessageDB(Base bean) {
293         ErrorMessageDB messageDB = null;
294         
295         // Sometimes this method is called with a null bean because a customizer
296
// is validating but has not been initialized with a bean yet. For such
297
// cases, returning null is quite acceptable.
298
if(bean != null) {
299             messageDB = bean.getMessageDB();
300         }
301         
302         return messageDB;
303     }
304         
305     /** This is used by Base to create it's internal message DB. Should not be public.
306      */

307     static ErrorMessageDB createMessageDB() {
308         return new ErrorMessageDB();
309     }
310 }
311
Popular Tags