/* * Copyright 2002-2008 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.beans.support; import java.util.Locale; import org.springframework.beans.BeanUtils; /** * RefreshablePagedListHolder is a PagedListHolder subclass with reloading capabilities. * It automatically re-requests the List from the source provider, in case of Locale or * filter changes. * * <p>Data binding works just like with PagedListHolder. The locale can be specified in * Locale's toString syntax, e.g. "locale=en_US". The filter object can be of any * custom class, preferably a bean for easy data binding from a request. An instance * will simply get passed through to <code>PagedListSourceProvider.loadList</code>. * A filter property can be specified via "filter.myFilterProperty", for example. * * <p>The scenario in the controller could be: * <code> * RefreshablePagedListHolder holder = request.getSession("mySessionAttr");<br> * if (holder == null) {<br> * holder = new RefreshablePagedListHolder();<br> * holder.setSourceProvider(new MyAnonymousOrEmbeddedSourceProvider());<br> * holder.setFilter(new MyAnonymousOrEmbeddedFilter());<br> * request.getSession().setAttribute("mySessionAttr", holder);<br> * }<br> * holder.refresh(false); * BindException ex = BindUtils.bind(request, listHolder, "myModelAttr");<br> * return ModelAndView("myViewName", ex.getModel());<br> * <br> * ...<br> * <br> * private class MyAnonymousOrEmbeddedSourceProvider implements PagedListSourceProvider {<br> * public List loadList(Locale locale, Object filter) {<br> * MyAnonymousOrEmbeddedFilter filter = (MyAnonymousOrEmbeddedFilter) filter;<br< * // an empty name mask should lead to all objects being loaded * return myBusinessService.loadMyObjectsByNameMask(filter.getName());<br> * }<br> * <br> * private class MyAnonymousOrEmbeddedFilter {<br> * private String name = "";<br> * public String getName() {<br> * return name;<br< * }<br> * public void setName(String name) {<br> * this.name = name;<br> * }<br> * }<br> * </code> * * @author Jean-Pierre Pawlak * @author Juergen Hoeller * @since 24.05.2003 * @deprecated as of Spring 2.5, to be removed in Spring 3.0 * @see org.springframework.beans.support.PagedListSourceProvider * @see org.springframework.beans.propertyeditors.LocaleEditor */ public class RefreshablePagedListHolder extends PagedListHolder { private PagedListSourceProvider sourceProvider; private Locale locale; private Locale localeUsed; private Object filter; private Object filterUsed; /** * Create a new list holder. * You'll need to set a source provider to be able to use the holder. * @see #setSourceProvider */ public RefreshablePagedListHolder() { super(); } /** * Create a new list holder with the given source provider. */ public RefreshablePagedListHolder(PagedListSourceProvider sourceProvider) { super(); this.sourceProvider = sourceProvider; } /** * Set the callback class for reloading the List when necessary. * If the list is definitely not modifiable, i.e. not locale aware * and no filtering, use PagedListHolder. * @see org.springframework.beans.support.PagedListHolder */ public void setSourceProvider(PagedListSourceProvider sourceProvider) { this.sourceProvider = sourceProvider; } /** * Return the callback class for reloading the List when necessary. */ public PagedListSourceProvider getSourceProvider() { return this.sourceProvider; } /** * Set the Locale that the source provider should use for loading the list. * This can either be populated programmatically (e.g. with the request locale), * or via binding (using Locale's toString syntax, e.g. "locale=en_US"). * @param locale the current Locale, or <code>null</code> */ public void setLocale(Locale locale) { this.locale = locale; } /** * Return the Locale that the source provider should use for loading the list. * @return the current Locale, or <code>null</code> */ public Locale getLocale() { return this.locale; } /** * Set the filter object that the source provider should use for loading the list. * This will typically be a bean, for easy data binding. * @param filter the filter object, or <code>null</code> */ public void setFilter(Object filter) { this.filter = filter; } /** * Return the filter that the source provider should use for loading the list. * @return the current filter, or <code>null</code> */ public Object getFilter() { return this.filter; } /** * Reload the underlying list from the source provider if necessary * (i.e. if the locale and/or the filter has changed), and resort it. * @param force whether a reload should be performed in any case */ public void refresh(boolean force) { if (this.sourceProvider != null && (force || (this.locale != null && !this.locale.equals(this.localeUsed)) || (this.filter != null && !this.filter.equals(this.filterUsed)))) { setSource(this.sourceProvider.loadList(this.locale, this.filter)); if (this.filter != null && !this.filter.equals(this.filterUsed)) { this.setPage(0); } this.localeUsed = this.locale; if (this.filter != null) { this.filterUsed = BeanUtils.instantiateClass(this.filter.getClass()); BeanUtils.copyProperties(this.filter, this.filterUsed); } } resort(); } }