View Javadoc

1   package net.sf.chainedoptions.support;
2   
3   import java.util.LinkedList;
4   import java.util.List;
5   
6   import net.sf.chainedoptions.ChainedOption;
7   import net.sf.chainedoptions.ChainedOptionStrategy;
8   import net.sf.chainedoptions.LabelValueBean;
9   
10  import org.springframework.beans.BeanWrapper;
11  import org.springframework.beans.BeanWrapperImpl;
12  import org.springframework.beans.factory.InitializingBean;
13  
14  
15  /***
16   * Decorator to provide support for optional refresh on the target
17   * <code>ChainedOption</code>. The specified <code>refreshProperty</code>
18   * property on the target <code>command</code> is inspected prior to
19   * forwarding any <code>retrieveOptions</code> and <code>updateValue</code>
20   * calls to the target <code>ChainedOption</code>.
21   * 
22   * If this property is <code>false</code> an empty List will be returned by
23   * <code>retrieveOptions</code>, and <code>updateValue</code> will do
24   * nothing.
25   * <p>
26   * Such a behavior is useful for example when a click in a checkbox should
27   * change another field between a selectbox (for fixed values) and a textbox
28   * (for free text search).
29   * 
30   * @author Mattias Arthursson
31   */
32  public class OptionalRefreshChainedOption implements ChainedOption,
33          InitializingBean {
34  
35      private ChainedOption chainedOption;
36  
37      private String refreshProperty;
38  
39      /***
40       * Forward the <code>retrieveOptions</code> call to the target
41       * <code>ChainedOption</code> if the <code>refreshProperty</code> property
42       * on the target command is true.
43       * 
44       * @param command
45       *            Command object to use when extracting values that the
46       *            <code>ChainedOption</code> depends on.
47       * @param context
48       *            may contain any context that might be interesting for
49       *            retreiving valid options. E.g. a
50       *            <code>HttpServletRequest</code> object can be supplied as
51       *            context for a Strategy to perform filtering based on user
52       *            access.
53       * 
54       * @return the result of retrieveOptions on the target ChainedOption if we are
55       *         to forward, an empty <code>LinkedList</code> otherwise.
56       * 
57       * @see net.sf.chainedoptions.ChainedOption#retrieveOptions(java.lang.Object, java.lang.Object)
58       */
59      public List retrieveOptions(Object command, Object context) {
60          if (getRefreshPropertyAsBoolean(command)) {
61              return chainedOption.retrieveOptions(command, context);
62          } else {
63              return new LinkedList();
64          }
65      }
66  
67      /***
68       * Forward the <code>updateValue</code> call to the target
69       * <code>ChainedOption</code if the <code>refreshProperty</code> property on the target command is true.
70       * @param command
71       *            The command object that may be updated.
72       * @param options
73       *            A list of {@link LabelValueBean}objects to choose from.
74       * @param context
75       *            may contain any context that might be interesting for
76       *            retreiving valid options. E.g. a
77       *            <code>HttpServletRequest</code> object can be supplied as
78       *            context for a Strategy to perform filtering based on user
79       *            access.
80       * 
81       * @see net.sf.chainedoptions.ChainedOption#updateValue(java.lang.Object, java.util.List, java.lang.Object)
82       */
83      public void updateValue(Object command, List options, Object context) {
84          if (getRefreshPropertyAsBoolean(command)) {
85              chainedOption.updateValue(command, options, context);
86          }
87      }
88  
89      private boolean getRefreshPropertyAsBoolean(Object command) {
90          BeanWrapper commandWrapper = new BeanWrapperImpl(command);
91          Boolean bool = (Boolean) commandWrapper
92                  .getPropertyValue(refreshProperty);
93          return bool.booleanValue();
94      }
95  
96      /***
97       * Forward the call to the target <code>ChainedOption</code>
98       * 
99       * @return the result from the target ChainedOption.
100      */
101     public String getOptionsKey() {
102         return chainedOption.getOptionsKey();
103     }
104 
105     /***
106      * Set the <code>ChainedOption</code> that this decorator wraps.
107      * 
108      * @param chainedOption
109      *            the <code>ChainedOption</code> to forward calls to.
110      */
111     public void setChainedOption(ChainedOption chainedOption) {
112         this.chainedOption = chainedOption;
113     }
114 
115     /***
116      * Set the name of the property to inspect on the <code>command</code>
117      * object to determine whether {@link #retrieveOptions(Object, Object)}and
118      * {@link #updateValue(Object, List, Object)}should forward the call to the
119      * target <code>ChainedOption</code>.
120      * 
121      * @param refreshProperty
122      *            name of the property.
123      */
124     public void setRefreshProperty(String refreshProperty) {
125         this.refreshProperty = refreshProperty;
126     }
127 
128     /*
129      * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
130      */
131     public void afterPropertiesSet() throws Exception {
132         if (refreshProperty == null) {
133             throw new IllegalArgumentException(
134                     "Property 'refreshProperty' must be set.");
135         }
136 
137         if (chainedOption == null) {
138             throw new IllegalArgumentException(
139                     "Property 'chainedOption' must be set.");
140         }
141     }
142 
143     /***
144      * Forward the call to the target <code>ChainedOption</code>.
145      * 
146      * @param command
147      *            the <code>command</code> to operate on.
148      * @return the value returned from the target <code>ChainedOption</code>.
149      */
150     public ChainedOptionStrategy getStrategy(Object command) {
151         return chainedOption.getStrategy(command);
152     }
153 }