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