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 */ 017package org.apache.wicket.feedback; 018 019import java.io.Serializable; 020import java.util.Collections; 021import java.util.Comparator; 022import java.util.List; 023 024import org.apache.wicket.Component; 025import org.apache.wicket.Page; 026import org.apache.wicket.Session; 027import org.apache.wicket.model.IModel; 028import org.apache.wicket.util.lang.Args; 029 030 031/** 032 * Model for extracting feedback messages. 033 * 034 * @author Eelco Hillenius 035 */ 036public class FeedbackMessagesModel implements IModel<List<FeedbackMessage>> 037{ 038 private static final long serialVersionUID = 1L; 039 040 /** Message filter */ 041 private IFeedbackMessageFilter filter; 042 043 /** Lazy loaded, temporary list. */ 044 private transient List<FeedbackMessage> messages; 045 046 /** Comparator used for sorting the messages. */ 047 private Comparator<FeedbackMessage> sortingComparator; 048 049 private final Component pageResolvingComponent; 050 051 /** 052 * Controls whether or not feedback from the {@link Session} will be collected. 053 * By default is true. 054 */ 055 private boolean includeSession = true; 056 057 /** 058 * Constructor. Creates a model for all feedback messages on the page. 059 * 060 * @param pageResolvingComponent 061 * The component where the page will be get from for which messages will be displayed 062 * usually the same page as the one feedbackpanel is attached to 063 */ 064 public FeedbackMessagesModel(Component pageResolvingComponent) 065 { 066 Args.notNull(pageResolvingComponent, "pageResolvingComponent"); 067 this.pageResolvingComponent = pageResolvingComponent; 068 } 069 070 /** 071 * Constructor. Creates a model for all feedback messages accepted by the given filter. 072 * 073 * @param filter 074 * The filter to apply 075 * @param page 076 * Page for which messages will be displayed - usually the same page as the one 077 * feedbackpanel is attached to 078 * 079 */ 080 public FeedbackMessagesModel(Page page, IFeedbackMessageFilter filter) 081 { 082 this(page); 083 setFilter(filter); 084 } 085 086 /** 087 * @return The current message filter 088 */ 089 public final IFeedbackMessageFilter getFilter() 090 { 091 return filter; 092 } 093 094 /** 095 * @return The current sorting comparator 096 */ 097 public final Comparator<FeedbackMessage> getSortingComparator() 098 { 099 return sortingComparator; 100 } 101 102 @Override 103 public final List<FeedbackMessage> getObject() 104 { 105 if (messages == null) 106 { 107 // Get filtered messages from page where component lives 108 messages = collectMessages(pageResolvingComponent, filter); 109 110 // Sort the list before returning it 111 if (sortingComparator != null) 112 { 113 Collections.sort(messages, sortingComparator); 114 } 115 116 // Let subclass do any extra processing it wants to on the messages. 117 // It may want to do something special, such as removing a given 118 // message under some special condition or perhaps eliminate 119 // duplicate messages. It could even add a message under certain 120 // conditions. 121 messages = processMessages(messages); 122 } 123 return messages; 124 } 125 126 /** 127 * Collects feedback messages 128 * 129 * @param pageResolvingComponent 130 * @param filter 131 * @return list of feedback messages 132 */ 133 protected List<FeedbackMessage> collectMessages(Component pageResolvingComponent, 134 IFeedbackMessageFilter filter) 135 { 136 return new FeedbackCollector(pageResolvingComponent.getPage(), includeSession).collect(filter); 137 } 138 139 /** 140 * @param filter 141 * Filter to apply to model 142 * @return this 143 */ 144 public final FeedbackMessagesModel setFilter(IFeedbackMessageFilter filter) 145 { 146 this.filter = filter; 147 return this; 148 } 149 150 /** 151 * Sets the comparator used for sorting the messages. 152 * 153 * @param sortingComparator 154 * comparator used for sorting the messages 155 * @return this 156 */ 157 public final FeedbackMessagesModel setSortingComparator( 158 Comparator<FeedbackMessage> sortingComparator) 159 { 160 if (!(sortingComparator instanceof Serializable)) 161 { 162 throw new IllegalArgumentException("sortingComparator must be serializable"); 163 } 164 this.sortingComparator = sortingComparator; 165 return this; 166 } 167 168 /** 169 * Override this method to post process to the FeedbackMessage list. 170 * 171 * @param messages 172 * List of sorted and filtered FeedbackMessages for further processing 173 * @return The processed FeedbackMessage list 174 */ 175 protected List<FeedbackMessage> processMessages(final List<FeedbackMessage> messages) 176 { 177 return messages; 178 } 179 180 @Override 181 public void setObject(List<FeedbackMessage> object) 182 { 183 } 184 185 @Override 186 public void detach() 187 { 188 messages = null; 189 } 190 191 /** 192 * Controls whether or not feedback from the {@link Session} will be collected. 193 * 194 * See {@link FeedbackCollector#setIncludeSession} and {@link Session#getFeedbackMessages} 195 * 196 * @param includeSession 197 * @return {@code this} for chaining 198 */ 199 public FeedbackMessagesModel setIncludeSession(boolean includeSession) 200 { 201 this.includeSession = includeSession; 202 return this; 203 } 204}