11/*
2- * Copyright 2002-2011 the original author or authors.
2+ * Copyright 2002-2012 the original author or authors.
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
2525import org .springframework .web .bind .support .SimpleSessionStatus ;
2626
2727/**
28- * Records model and view related decisions made by
29- * {@link HandlerMethodArgumentResolver}s and
30- * {@link HandlerMethodReturnValueHandler}s during the course of invocation of
28+ * Records model and view related decisions made by
29+ * {@link HandlerMethodArgumentResolver}s and
30+ * {@link HandlerMethodReturnValueHandler}s during the course of invocation of
3131 * a controller method.
32- *
32+ *
3333 * <p>The {@link #setRequestHandled} flag can be used to indicate the request
3434 * has been handled directly and view resolution is not required.
35- *
36- * <p>A default {@link Model} is automatically created at instantiation.
37- * An alternate model instance may be provided via {@link #setRedirectModel}
38- * for use in a redirect scenario. When {@link #setRedirectModelScenario} is set
39- * to {@code true} signalling a redirect scenario, the {@link #getModel()}
35+ *
36+ * <p>A default {@link Model} is automatically created at instantiation.
37+ * An alternate model instance may be provided via {@link #setRedirectModel}
38+ * for use in a redirect scenario. When {@link #setRedirectModelScenario} is set
39+ * to {@code true} signalling a redirect scenario, the {@link #getModel()}
4040 * returns the redirect model instead of the default model.
41- *
41+ *
4242 * @author Rossen Stoyanchev
4343 * @since 3.1
4444 */
4545public class ModelAndViewContainer {
4646
4747 private Object view ;
48-
48+
4949 private boolean requestHandled = false ;
50-
50+
5151 private final ModelMap defaultModel = new BindingAwareModelMap ();
5252
5353 private ModelMap redirectModel ;
@@ -57,31 +57,31 @@ public class ModelAndViewContainer {
5757 private boolean ignoreDefaultModelOnRedirect = false ;
5858
5959 private final SessionStatus sessionStatus = new SimpleSessionStatus ();
60-
60+
6161 /**
6262 * Create a new instance.
6363 */
6464 public ModelAndViewContainer () {
6565 }
6666
6767 /**
68- * Set a view name to be resolved by the DispatcherServlet via a ViewResolver.
68+ * Set a view name to be resolved by the DispatcherServlet via a ViewResolver.
6969 * Will override any pre-existing view name or View.
7070 */
7171 public void setViewName (String viewName ) {
7272 this .view = viewName ;
7373 }
7474
7575 /**
76- * Return the view name to be resolved by the DispatcherServlet via a
76+ * Return the view name to be resolved by the DispatcherServlet via a
7777 * ViewResolver, or {@code null} if a View object is set.
7878 */
7979 public String getViewName () {
8080 return (this .view instanceof String ? (String ) this .view : null );
8181 }
82-
82+
8383 /**
84- * Set a View object to be used by the DispatcherServlet.
84+ * Set a View object to be used by the DispatcherServlet.
8585 * Will override any pre-existing view name or View.
8686 */
8787 public void setView (Object view ) {
@@ -97,28 +97,28 @@ public Object getView() {
9797 }
9898
9999 /**
100- * Whether the view is a view reference specified via a name to be
100+ * Whether the view is a view reference specified via a name to be
101101 * resolved by the DispatcherServlet via a ViewResolver.
102102 */
103103 public boolean isViewReference () {
104104 return (this .view instanceof String );
105105 }
106-
106+
107107 /**
108- * Signal a scenario where the request is handled directly.
109- * <p>A {@link HandlerMethodReturnValueHandler} may use this flag to
110- * indicate the response has been fully handled and view resolution
108+ * Signal a scenario where the request is handled directly.
109+ * <p>A {@link HandlerMethodReturnValueHandler} may use this flag to
110+ * indicate the response has been fully handled and view resolution
111111 * is not required (e.g. {@code @ResponseBody}).
112112 * <p>A {@link HandlerMethodArgumentResolver} may also use this flag
113- * to indicate the presence of an argument (e.g.
114- * {@code ServletResponse} or {@code OutputStream}) that may lead to
113+ * to indicate the presence of an argument (e.g.
114+ * {@code ServletResponse} or {@code OutputStream}) that may lead to
115115 * a complete response depending on the method return value.
116116 * <p>The default value is {@code true}.
117117 */
118118 public void setRequestHandled (boolean requestHandled ) {
119119 this .requestHandled = requestHandled ;
120120 }
121-
121+
122122 /**
123123 * Whether the request is handled directly.
124124 */
@@ -129,7 +129,7 @@ public boolean isRequestHandled() {
129129 /**
130130 * Return the model to use: the "default" or the "redirect" model.
131131 * <p>The default model is used if {@code "redirectModelScenario=false"} or
132- * if the redirect model is {@code null} (i.e. it wasn't declared as a
132+ * if the redirect model is {@code null} (i.e. it wasn't declared as a
133133 * method argument) and {@code ignoreDefaultModelOnRedirect=false}.
134134 */
135135 public ModelMap getModel () {
@@ -140,17 +140,17 @@ public ModelMap getModel() {
140140 return (this .redirectModel != null ) ? this .redirectModel : new ModelMap ();
141141 }
142142 }
143-
143+
144144 /**
145145 * Whether to use the default model or the redirect model.
146146 */
147147 private boolean useDefaultModel () {
148148 return !this .redirectModelScenario || ((this .redirectModel == null ) && !this .ignoreDefaultModelOnRedirect );
149149 }
150-
150+
151151 /**
152- * Provide a separate model instance to use in a redirect scenario.
153- * The provided additional model however is not used used unless
152+ * Provide a separate model instance to use in a redirect scenario.
153+ * The provided additional model however is not used used unless
154154 * {@link #setRedirectModelScenario(boolean)} gets set to {@code true} to signal
155155 * a redirect scenario.
156156 */
@@ -168,7 +168,7 @@ public void setRedirectModelScenario(boolean redirectModelScenario) {
168168
169169 /**
170170 * When set to {@code true} the default model is never used in a redirect
171- * scenario. So if a redirect model is not available, an empty model is
171+ * scenario. So if a redirect model is not available, an empty model is
172172 * used instead.
173173 * <p>When set to {@code false} the default model can be used in a redirect
174174 * scenario if a redirect model is not available.
@@ -179,7 +179,7 @@ public void setIgnoreDefaultModelOnRedirect(boolean ignoreDefaultModelOnRedirect
179179 }
180180
181181 /**
182- * Return the {@link SessionStatus} instance to use that can be used to
182+ * Return the {@link SessionStatus} instance to use that can be used to
183183 * signal that session processing is complete.
184184 */
185185 public SessionStatus getSessionStatus () {
@@ -188,16 +188,16 @@ public SessionStatus getSessionStatus() {
188188
189189 /**
190190 * Add the supplied attribute to the underlying model.
191- * @see ModelMap# addAttribute(String, Object)
191+ * A shortcut for {@code getModel(). addAttribute(String, Object)}.
192192 */
193193 public ModelAndViewContainer addAttribute (String name , Object value ) {
194194 getModel ().addAttribute (name , value );
195195 return this ;
196196 }
197-
197+
198198 /**
199199 * Add the supplied attribute to the underlying model.
200- * @see Model# addAttribute(Object)
200+ * A shortcut for {@code getModel(). addAttribute(Object)}.
201201 */
202202 public ModelAndViewContainer addAttribute (Object value ) {
203203 getModel ().addAttribute (value );
@@ -206,26 +206,38 @@ public ModelAndViewContainer addAttribute(Object value) {
206206
207207 /**
208208 * Copy all attributes to the underlying model.
209- * @see ModelMap# addAllAttributes(Map)
209+ * A shortcut for {@code getModel(). addAllAttributes(Map)}.
210210 */
211211 public ModelAndViewContainer addAllAttributes (Map <String , ?> attributes ) {
212212 getModel ().addAllAttributes (attributes );
213213 return this ;
214214 }
215215
216216 /**
217- * Copy attributes in the supplied <code>Map</code> with existing objects of
217+ * Copy attributes in the supplied <code>Map</code> with existing objects of
218218 * the same name taking precedence (i.e. not getting replaced).
219- * @see ModelMap# mergeAttributes(Map)
219+ * A shortcut for {@code getModel(). mergeAttributes(Map<String, ?>)}.
220220 */
221221 public ModelAndViewContainer mergeAttributes (Map <String , ?> attributes ) {
222222 getModel ().mergeAttributes (attributes );
223223 return this ;
224224 }
225225
226+ /**
227+ * Remove the given attributes from the model.
228+ */
229+ public ModelAndViewContainer removeAttributes (Map <String , ?> attributes ) {
230+ if (attributes != null ) {
231+ for (String key : attributes .keySet ()) {
232+ getModel ().remove (key );
233+ }
234+ }
235+ return this ;
236+ }
237+
226238 /**
227239 * Whether the underlying model contains the given attribute name.
228- * @see ModelMap# containsAttribute(String)
240+ * A shortcut for {@code getModel(). containsAttribute(String)}.
229241 */
230242 public boolean containsAttribute (String name ) {
231243 return getModel ().containsAttribute (name );
@@ -257,5 +269,5 @@ public String toString() {
257269 }
258270 return sb .toString ();
259271 }
260-
272+
261273}
0 commit comments