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