View Javadoc

1   /**
2    * Copyright 2005-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.uif.field;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.core.api.util.ConcreteKeyValue;
20  import org.kuali.rice.core.api.util.KeyValue;
21  import org.kuali.rice.krad.datadictionary.AttributeDefinition;
22  import org.kuali.rice.krad.datadictionary.parse.BeanTag;
23  import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute;
24  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
25  import org.kuali.rice.krad.uif.UifConstants;
26  import org.kuali.rice.krad.uif.component.Component;
27  import org.kuali.rice.krad.uif.control.CheckboxControl;
28  import org.kuali.rice.krad.uif.control.Control;
29  import org.kuali.rice.krad.uif.control.MultiValueControl;
30  import org.kuali.rice.krad.uif.control.RadioGroupControl;
31  import org.kuali.rice.krad.uif.control.TextAreaControl;
32  import org.kuali.rice.krad.uif.element.Message;
33  import org.kuali.rice.krad.uif.util.ComponentFactory;
34  import org.kuali.rice.krad.uif.util.ComponentUtils;
35  import org.kuali.rice.krad.uif.util.KeyMessage;
36  import org.kuali.rice.krad.uif.view.View;
37  import org.kuali.rice.krad.util.KRADConstants;
38  import org.kuali.rice.krad.util.KRADPropertyConstants;
39  
40  import java.util.ArrayList;
41  import java.util.List;
42  
43  /**
44   * Custom <code>InputField</code> for search fields within a lookup view
45   *
46   * @author Kuali Rice Team (rice.collab@kuali.org)
47   */
48  @BeanTag(name = "lookupCriteriaInputField-bean", parent = "Uif-LookupCriteriaInputField")
49  public class LookupInputField extends InputField {
50      private static final long serialVersionUID = -8294275596836322699L;
51  
52      private boolean disableWildcardsAndOperators;
53      private boolean addControlSelectAllOption;
54      private boolean triggerOnChange;
55      private boolean ranged;
56  
57      private RadioGroupControl radioGroupControl;
58  
59      public LookupInputField() {
60          super();
61  
62          disableWildcardsAndOperators = false;
63          addControlSelectAllOption = false;
64          setTriggerOnChange(false);
65      }
66  
67      /**
68       * Replace checkbox control with radio group control
69       *
70       * @see Component#performApplyModel(org.kuali.rice.krad.uif.view.View, Object,
71       * org.kuali.rice.krad.uif.component.Component)
72       */
73      @Override
74      public void performApplyModel(View view, Object model, Component parent) {
75          super.performApplyModel(view, model, parent);
76  
77          if (getControl() != null && getControl() instanceof CheckboxControl) {
78              setControl(getRadioGroupControl());
79          }
80      }
81  
82      /**
83       * The following actions are performed:
84       *
85       * <ul>
86       * <li>Add all option if enabled and control is multi-value</li>
87       * </ul>
88       *
89       * @see org.kuali.rice.krad.uif.component.ComponentBase#performFinalize(org.kuali.rice.krad.uif.view.View,
90       *      java.lang.Object, org.kuali.rice.krad.uif.component.Component)
91       */
92      @Override
93      public void performFinalize(View view, Object model, Component parent) {
94          super.performFinalize(view, model, parent);
95  
96          // if enabled add option to select all values
97          if (addControlSelectAllOption && (getControl() != null) && getControl() instanceof MultiValueControl) {
98              String allOptionText = KRADServiceLocatorWeb.getMessageService().getMessageText(
99                      UifConstants.MessageKeys.OPTION_ALL);
100 
101             MultiValueControl multiValueControl = (MultiValueControl) getControl();
102             if (multiValueControl.getOptions() != null) {
103                 multiValueControl.getOptions().add(0, new ConcreteKeyValue("", allOptionText));
104             }
105 
106             if (multiValueControl.getRichOptions() != null) {
107                 Message message = ComponentFactory.getMessage();
108 
109                 view.assignComponentIds(message);
110                 message.setMessageText(allOptionText);
111                 message.setGenerateSpan(false);
112 
113                 multiValueControl.getRichOptions().add(0, new KeyMessage("", allOptionText, message));
114             }
115         }
116     }
117 
118     /**
119      * Add radioGroupControl if the control is a checkbox control
120      *
121      * @see org.kuali.rice.krad.uif.component.Component#getPropertyReplacers()
122      */
123     @Override
124     public List<Component> getComponentPrototypes() {
125         List<Component> components = super.getComponentPrototypes();
126         if (getControl() != null && getControl() instanceof CheckboxControl) {
127             components.add(radioGroupControl);
128         }
129         return components;
130     }
131 
132     /**
133      * Override of InputField copy to setup properties necessary to make the field usable for inputting
134      * search criteria
135      *
136      * @param attributeDefinition - AttributeDefinition instance the property values should be copied from
137      * @see DataField#copyFromAttributeDefinition(org.kuali.rice.krad.uif.view.View,
138      * org.kuali.rice.krad.datadictionary.AttributeDefinition)
139      */
140     @Override
141     public void copyFromAttributeDefinition(View view, AttributeDefinition attributeDefinition) {
142         // label
143         if (StringUtils.isEmpty(getLabel())) {
144             setLabel(attributeDefinition.getLabel());
145         }
146 
147         // short label
148         if (StringUtils.isEmpty(getShortLabel())) {
149             setShortLabel(attributeDefinition.getShortLabel());
150         }
151 
152         // security
153         if (getDataFieldSecurity().getAttributeSecurity() == null) {
154             getDataFieldSecurity().setAttributeSecurity(attributeDefinition.getAttributeSecurity());
155         }
156 
157         // options
158         if (getOptionsFinder() == null) {
159             setOptionsFinder(attributeDefinition.getOptionsFinder());
160         }
161 
162         // TODO: what about formatter?
163 
164         // use control from dictionary if not specified and convert for searching
165         if (getControl() == null) {
166             Control control = convertControlToLookupControl(attributeDefinition);
167             view.assignComponentIds(control);
168 
169             setControl(control);
170         }
171 
172         // overwrite maxLength to allow for wildcards and ranges
173         setMaxLength(100);
174 
175         // set default value for active field to true
176         if (StringUtils.isEmpty(getDefaultValue())) {
177             if ((StringUtils.equals(getPropertyName(), KRADPropertyConstants.ACTIVE))) {
178                 setDefaultValue(KRADConstants.YES_INDICATOR_VALUE);
179             }
180         }
181 
182         /*
183            * TODO delyea: FieldUtils.createAndPopulateFieldsForLookup used to allow for a set of property names to be passed in via the URL
184            * parameters of the lookup url to set fields as 'read only'
185            */
186 
187     }
188 
189     /**
190      * If control definition is defined on the given attribute definition, converts to an appropriate control for
191      * searching (if necessary) and returns a copy for setting on the field
192      *
193      * @param attributeDefinition - attribute definition instance to retrieve control from
194      * @return Control instance or null if not found
195      */
196     protected static Control convertControlToLookupControl(AttributeDefinition attributeDefinition) {
197         if (attributeDefinition.getControlField() == null) {
198             return null;
199         }
200 
201         Control newControl = null;
202 
203         // convert checkbox to radio with yes/no/both options
204         if (CheckboxControl.class.isAssignableFrom(attributeDefinition.getControlField().getClass())) {
205             newControl = ComponentFactory.getRadioGroupControlHorizontal();
206             List<KeyValue> options = new ArrayList<KeyValue>();
207             options.add(new ConcreteKeyValue("Y", "Yes"));
208             options.add(new ConcreteKeyValue("N", "No"));
209             options.add(new ConcreteKeyValue("", "Both"));
210 
211             ((RadioGroupControl) newControl).setOptions(options);
212         }
213         // text areas get converted to simple text inputs
214         else if (TextAreaControl.class.isAssignableFrom(attributeDefinition.getControlField().getClass())) {
215             newControl = ComponentFactory.getTextControl();
216         } else {
217             newControl = ComponentUtils.copy(attributeDefinition.getControlField(), "");
218         }
219 
220         return newControl;
221     }
222 
223     /**
224      * @return the treatWildcardsAndOperatorsAsLiteral
225      */
226     @BeanTagAttribute(name="disableWildcardsAndOperators")
227     public boolean isDisableWildcardsAndOperators() {
228         return this.disableWildcardsAndOperators;
229     }
230 
231     /**
232      * @param disableWildcardsAndOperators the treatWildcardsAndOperatorsAsLiteral to set
233      */
234     public void setDisableWildcardsAndOperators(boolean disableWildcardsAndOperators) {
235         this.disableWildcardsAndOperators = disableWildcardsAndOperators;
236     }
237 
238     /**
239      * Indicates whether the option for all values (blank key, 'All' label) should be added to the lookup
240      * field, note this is only supported for {@link org.kuali.rice.krad.uif.control.MultiValueControl} instance
241      *
242      * @return boolean true if all option should be added, false if not
243      */
244     @BeanTagAttribute(name="addControlSelectAllOption")
245     public boolean isAddControlSelectAllOption() {
246         return addControlSelectAllOption;
247     }
248 
249     /**
250      * Setter for the add all option indicator
251      *
252      * @param addControlSelectAllOption
253      */
254     public void setAddControlSelectAllOption(boolean addControlSelectAllOption) {
255         this.addControlSelectAllOption = addControlSelectAllOption;
256     }
257 
258     /**
259      * Indicates that the search must execute on changing of a value in the lookup input field
260      *
261      * @return boolean
262      */
263     public boolean isTriggerOnChange() {
264         return triggerOnChange;
265     }
266 
267     /**
268      * Setter for the trigger search on change flag
269      *
270      * @param triggerOnChange
271      */
272     public void setTriggerOnChange(boolean triggerOnChange) {
273         this.triggerOnChange = triggerOnChange;
274     }
275 
276     /**
277      * The radio group control prototype that will replace the checkbox control
278      *
279      * @return RadioGroupControl
280      */
281     public RadioGroupControl getRadioGroupControl() {
282         return radioGroupControl;
283     }
284 
285     /**
286      * Setter for the radio group control
287      *
288      * @param radioGroupControl
289      */
290     public void setRadioGroupControl(RadioGroupControl radioGroupControl) {
291         this.radioGroupControl = radioGroupControl;
292     }
293 
294     /**
295      * Indicates that a field must be rendered as a from and to value
296      *
297      * @return
298      */
299     public boolean isRanged() {
300         return ranged;
301     }
302 
303     /**
304      * Setter for ranged flag to indicate this is a range field
305      *
306      * @param ranged
307      */
308     public void setRanged(boolean ranged) {
309         this.ranged = ranged;
310     }
311 }