001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.wicket.feedback;
018:
019: import java.io.Serializable;
020: import java.util.ArrayList;
021: import java.util.Collections;
022: import java.util.Iterator;
023: import java.util.List;
024:
025: import org.apache.wicket.Component;
026: import org.apache.wicket.IClusterable;
027: import org.apache.wicket.util.concurrent.CopyOnWriteArrayList;
028: import org.apache.wicket.util.string.StringList;
029: import org.slf4j.Logger;
030: import org.slf4j.LoggerFactory;
031:
032: /**
033: * Holds list of feedback messages. The list can be added to, cleared, queried
034: * and filtered.
035: * <p>
036: * WARNING: This class should typically NOT be used directly.
037: * <p>
038: *
039: * @author Eelco Hillenius
040: * @author Jonathan Locke
041: */
042: public final class FeedbackMessages implements IClusterable {
043: /** Log. */
044: private static final Logger log = LoggerFactory
045: .getLogger(FeedbackMessages.class);
046:
047: private static final long serialVersionUID = 1L;
048:
049: /**
050: * Holds a list of {@link org.apache.wicket.feedback.FeedbackMessage}s.
051: */
052: private List messages = null;
053:
054: /**
055: * Construct.
056: */
057: public FeedbackMessages() {
058: messages = new CopyOnWriteArrayList();
059: }
060:
061: /**
062: * Adds a message
063: *
064: * @param reporter
065: * @param message
066: * @param level
067: */
068: public final void add(Component reporter, String message, int level) {
069: add(new FeedbackMessage(reporter, message, level));
070: }
071:
072: /**
073: * Clears any existing messages.
074: *
075: * @return The number of messages deleted
076: */
077: public final int clear() {
078: return clear(null);
079: }
080:
081: /**
082: * Clears all messsages that are accepted by the filter.
083: *
084: * @param filter
085: * Filter for selecting messages. If null, all messages will be
086: * returned
087: * @return The number of messages deleted
088: */
089: public final int clear(final IFeedbackMessageFilter filter) {
090: if (messages.size() == 0) {
091: return 0;
092: }
093:
094: List toDelete = messages(filter);
095: int count = toDelete.size();
096: messages.removeAll(toDelete);
097:
098: trimToSize();
099: return count;
100: }
101:
102: /**
103: * Adds a new ui message with level DEBUG to the current messages.
104: *
105: * @param reporter
106: * the reporting component
107: * @param message
108: * the actual message
109: */
110: public final void debug(Component reporter, String message) {
111: add(new FeedbackMessage(reporter, message,
112: FeedbackMessage.DEBUG));
113: }
114:
115: /**
116: * Adds a new ui message with level ERROR to the current messages.
117: *
118: * @param reporter
119: * the reporting component
120: * @param message
121: * the actual message
122: */
123: public final void error(Component reporter, Serializable message) {
124: add(new FeedbackMessage(reporter, message,
125: FeedbackMessage.ERROR));
126: }
127:
128: /**
129: * Adds a new ui message with level FATAL to the current messages.
130: *
131: * @param reporter
132: * the reporting component
133: * @param message
134: * the actual message
135: */
136: public final void fatal(Component reporter, String message) {
137: add(new FeedbackMessage(reporter, message,
138: FeedbackMessage.FATAL));
139: }
140:
141: /**
142: * Convenience method that looks up whether the given component registered a
143: * message with this list with the level ERROR.
144: *
145: * @param component
146: * the component to look up whether it registered a message
147: * @return whether the given component registered a message with this list
148: * with level ERROR
149: */
150: public final boolean hasErrorMessageFor(Component component) {
151: return hasMessageFor(component, FeedbackMessage.ERROR);
152: }
153:
154: /**
155: * @param filter
156: * Filter for selecting messages
157: * @return True if one or more messages matches the filter
158: */
159: public final boolean hasMessage(final IFeedbackMessageFilter filter) {
160: return messages(filter).size() != 0;
161: }
162:
163: /**
164: * Looks up whether the given component registered a message with this list.
165: *
166: * @param component
167: * the component to look up whether it registered a message
168: * @return whether the given component registered a message with this list
169: */
170: public final boolean hasMessageFor(Component component) {
171: return messageForComponent(component) != null;
172: }
173:
174: /**
175: * Looks up whether the given component registered a message with this list
176: * with the given level.
177: *
178: * @param component
179: * The component to look up whether it registered a message
180: * @param level
181: * The level of the message
182: * @return Whether the given component registered a message with this list
183: * with the given level
184: */
185: public final boolean hasMessageFor(Component component, int level) {
186: final FeedbackMessage message = messageForComponent(component);
187: return message != null && message.isLevel(level);
188: }
189:
190: /**
191: * Adds a new ui message with level INFO to the current messages.
192: *
193: * @param reporter
194: * The reporting component
195: * @param message
196: * The actual message
197: */
198: public final void info(Component reporter, String message) {
199: add(new FeedbackMessage(reporter, message, FeedbackMessage.INFO));
200: }
201:
202: /**
203: * Gets whether there are no messages.
204: *
205: * @return True when there are no messages
206: */
207: public final boolean isEmpty() {
208: return messages.isEmpty();
209: }
210:
211: /**
212: * Gets an iterator over stored messages
213: *
214: * @return iterator over stored messages
215: */
216: public final Iterator iterator() {
217: return messages.iterator();
218: }
219:
220: /**
221: * Looks up a message for the given component.
222: *
223: * @param component
224: * the component to look up the message for
225: * @return the message that is found for the given component (first match)
226: * or null if none was found
227: */
228: public final FeedbackMessage messageForComponent(
229: final Component component) {
230: for (Iterator iterator = messages.iterator(); iterator
231: .hasNext();) {
232: FeedbackMessage message = (FeedbackMessage) iterator.next();
233: if (message.getReporter() == component) {
234: return message;
235: }
236: }
237: return null;
238: }
239:
240: /**
241: * Gets a list of messages from the page using a filter.
242: *
243: * @param filter
244: * Filter for selecting messages. If null, all messages will be
245: * returned
246: * @return The messages or an empty list if no messages are found
247: */
248: public final List messages(final IFeedbackMessageFilter filter) {
249: if (messages.size() == 0) {
250: return Collections.EMPTY_LIST;
251: }
252:
253: final List list = new ArrayList();
254: for (final Iterator iterator = messages.iterator(); iterator
255: .hasNext();) {
256: final FeedbackMessage message = (FeedbackMessage) iterator
257: .next();
258: if (filter == null || filter.accept(message)) {
259: list.add(message);
260: }
261: }
262: return list;
263: }
264:
265: /**
266: * Gets the number of messages
267: *
268: * @return the number of messages
269: */
270: public final int size() {
271: return messages.size();
272: }
273:
274: /**
275: * Gets the number of messages.
276: *
277: * @param filter
278: * Filter for counting messages. If null, the count of all
279: * messages will be returned
280: *
281: * @return the number of messages
282: */
283: public final int size(final IFeedbackMessageFilter filter) {
284: int count = 0;
285: for (final Iterator iterator = messages.iterator(); iterator
286: .hasNext();) {
287: final FeedbackMessage message = (FeedbackMessage) iterator
288: .next();
289: if (filter == null || filter.accept(message)) {
290: count++;
291: }
292: }
293: return count;
294: }
295:
296: /**
297: * @see java.lang.Object#toString()
298: */
299: public String toString() {
300: return "[feedbackMessages = " + StringList.valueOf(messages)
301: + "]";
302: }
303:
304: /**
305: * Frees any unnecessary internal storage
306: */
307: public final void trimToSize() {
308: if (messages instanceof ArrayList) {
309: ((ArrayList) messages).trimToSize();
310: }
311: }
312:
313: /**
314: * Adds a new ui message with level WARNING to the current messages.
315: *
316: * @param reporter
317: * the reporting component
318: * @param message
319: * the actual message
320: */
321: public final void warn(Component reporter, String message) {
322: add(new FeedbackMessage(reporter, message,
323: FeedbackMessage.WARNING));
324: }
325:
326: /**
327: * Adds a message.
328: *
329: * @param message
330: * the message
331: */
332: final void add(FeedbackMessage message) {
333: if (log.isDebugEnabled()) {
334: log.debug("Adding feedback message " + message);
335: }
336: messages.add(message);
337: }
338: }
|