View Javadoc
1   /**
2    * Copyright 2005-2016 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.util;
17  
18  import java.util.ArrayList;
19  import java.util.HashMap;
20  import java.util.List;
21  import java.util.Map;
22  
23  import org.apache.commons.lang.StringUtils;
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  import org.kuali.rice.core.api.uif.RemotableAbstractWidget;
27  import org.kuali.rice.core.api.uif.RemotableAttributeField;
28  import org.kuali.rice.core.api.uif.RemotableCheckbox;
29  import org.kuali.rice.core.api.uif.RemotableCheckboxGroup;
30  import org.kuali.rice.core.api.uif.RemotableControlContract;
31  import org.kuali.rice.core.api.uif.RemotableDatepicker;
32  import org.kuali.rice.core.api.uif.RemotableHiddenInput;
33  import org.kuali.rice.core.api.uif.RemotableQuickFinder;
34  import org.kuali.rice.core.api.uif.RemotableRadioButtonGroup;
35  import org.kuali.rice.core.api.uif.RemotableSelect;
36  import org.kuali.rice.core.api.uif.RemotableSelectGroup;
37  import org.kuali.rice.core.api.uif.RemotableTextExpand;
38  import org.kuali.rice.core.api.uif.RemotableTextInput;
39  import org.kuali.rice.core.api.uif.RemotableTextarea;
40  import org.kuali.rice.core.api.util.ConcreteKeyValue;
41  import org.kuali.rice.core.api.util.KeyValue;
42  import org.kuali.rice.krad.datadictionary.validation.constraint.ValidCharactersConstraint;
43  import org.kuali.rice.krad.keyvalues.KeyValuesFinder;
44  import org.kuali.rice.krad.lookup.LookupInputField;
45  import org.kuali.rice.krad.lookup.LookupView;
46  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
47  import org.kuali.rice.krad.uif.UifConstants;
48  import org.kuali.rice.krad.uif.component.Component;
49  import org.kuali.rice.krad.uif.container.CollectionGroup;
50  import org.kuali.rice.krad.uif.container.DialogGroup;
51  import org.kuali.rice.krad.uif.container.Group;
52  import org.kuali.rice.krad.uif.container.LinkGroup;
53  import org.kuali.rice.krad.uif.container.PageGroup;
54  import org.kuali.rice.krad.uif.container.TabGroup;
55  import org.kuali.rice.krad.uif.container.TabNavigationGroup;
56  import org.kuali.rice.krad.uif.container.TreeGroup;
57  import org.kuali.rice.krad.uif.control.CheckboxControl;
58  import org.kuali.rice.krad.uif.control.CheckboxGroupControl;
59  import org.kuali.rice.krad.uif.control.Control;
60  import org.kuali.rice.krad.uif.control.FileControl;
61  import org.kuali.rice.krad.uif.control.GroupControl;
62  import org.kuali.rice.krad.uif.control.HiddenControl;
63  import org.kuali.rice.krad.uif.control.MultiValueControl;
64  import org.kuali.rice.krad.uif.control.RadioGroupControl;
65  import org.kuali.rice.krad.uif.control.SelectControl;
66  import org.kuali.rice.krad.uif.control.SizedControl;
67  import org.kuali.rice.krad.uif.control.TextAreaControl;
68  import org.kuali.rice.krad.uif.control.TextControl;
69  import org.kuali.rice.krad.uif.control.UserControl;
70  import org.kuali.rice.krad.uif.element.Action;
71  import org.kuali.rice.krad.uif.element.Header;
72  import org.kuali.rice.krad.uif.element.Iframe;
73  import org.kuali.rice.krad.uif.element.Image;
74  import org.kuali.rice.krad.uif.element.Label;
75  import org.kuali.rice.krad.uif.element.Message;
76  import org.kuali.rice.krad.uif.element.ValidationMessages;
77  import org.kuali.rice.krad.uif.field.DataField;
78  import org.kuali.rice.krad.uif.field.FieldGroup;
79  import org.kuali.rice.krad.uif.field.GenericField;
80  import org.kuali.rice.krad.uif.field.ImageField;
81  import org.kuali.rice.krad.uif.field.InputField;
82  import org.kuali.rice.krad.uif.field.LinkField;
83  import org.kuali.rice.krad.uif.field.MessageField;
84  import org.kuali.rice.krad.uif.field.SpaceField;
85  import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle;
86  import org.kuali.rice.krad.uif.lifecycle.ViewPostMetadata;
87  import org.kuali.rice.krad.uif.view.InquiryView;
88  import org.kuali.rice.krad.uif.widget.Inquiry;
89  import org.kuali.rice.krad.uif.widget.LightBox;
90  import org.kuali.rice.krad.uif.widget.QuickFinder;
91  
92  /**
93   * Factory class for creating new UIF components from their base definitions in the dictionary.
94   *
95   * @author Kuali Rice Team (rice.collab@kuali.org)
96   */
97  public class ComponentFactory {
98      private static Log LOG = LogFactory.getLog(ComponentFactory.class);
99  
100     public static final String TEXT_CONTROL = "Uif-TextControl";
101     public static final String CHECKBOX_CONTROL = "Uif-CheckboxControl";
102     public static final String HIDDEN_CONTROL = "Uif-HiddenControl";
103     public static final String TEXTAREA_CONTROL = "Uif-TextAreaControl";
104     public static final String SELECT_CONTROL = "Uif-DropdownControl";
105     public static final String CHECKBOX_CONVERTED_RADIO_CONTROL = "Uif-CheckboxConvertedRadioControl";
106     public static final String CHECKBOX_GROUP_CONTROL = "Uif-VerticalCheckboxesControl";
107     public static final String CHECKBOX_GROUP_CONTROL_HORIZONTAL = "Uif-HorizontalCheckboxesControl";
108     public static final String RADIO_GROUP_CONTROL = "Uif-VerticalRadioControl";
109     public static final String RADIO_GROUP_CONTROL_HORIZONTAL = "Uif-HorizontalRadioControl";
110     public static final String FILE_CONTROL = "Uif-FileControl";
111     public static final String DATE_CONTROL = "Uif-DateControl";
112     public static final String USER_CONTROL = "Uif-KimPersonControl";
113     public static final String GROUP_CONTROL = "Uif-KimGroupControl";
114 
115     public static final String DATA_FIELD = "Uif-DataField";
116     public static final String INPUT_FIELD = "Uif-InputField";
117     public static final String LOOKUP_ACTIVE_INPUT_FIELD = "Uif-LookupActiveInputField";
118     public static final String LOOKUP_INPUT_FIELD = "Uif-LookupCriteriaInputField";
119     public static final String ERRORS_FIELD = "Uif-FieldValidationMessages";
120     public static final String ACTION = "Uif-PrimaryActionButton";
121     public static final String SECONDARY_ACTION = "Uif-SecondaryActionButton";
122     public static final String ACTION_LINK = "Uif-ActionLink";
123     public static final String LINK_FIELD = "Uif-LinkField";
124     public static final String IFRAME = "Uif-Iframe";
125     public static final String IMAGE_FIELD = "Uif-ImageField";
126     public static final String SPACE_FIELD = "Uif-SpaceField";
127     public static final String GENERIC_FIELD = "Uif-CustomTemplateField";
128     public static final String IMAGE = "Uif-Image";
129     public static final String LABEL = "Uif-Label";
130     public static final String MESSAGE = "Uif-Message";
131     public static final String MESSAGE_FIELD = "Uif-MessageField";
132     public static final String COLLECTION_GROUPING_FIELD = "Uif-ColGroupingField";
133     public static final String FIELD_GROUP = "Uif-VerticalFieldGroup";
134     public static final String HORIZONTAL_FIELD_GROUP = "Uif-HorizontalFieldGroup";
135 
136     public static final String GROUP = "Uif-GroupBase";
137     public static final String VERTICAL_BOX_GROUP = "Uif-VerticalBoxGroup";
138     public static final String HORIZONTAL_BOX_GROUP = "Uif-HorizontalBoxGroup";
139     public static final String VERTICAL_BOX_SECTION = "Uif-VerticalBoxSection";
140     public static final String HORIZONTAL_BOX_SECTION = "Uif-HorizontalBoxSection";
141     public static final String PAGE_GROUP = "Uif-Page";
142     public static final String GROUP_GRID_LAYOUT = "Uif-GridSection";
143     public static final String GROUP_WITH_DISCLOSURE_GRID_LAYOUT = "Uif-Disclosure-GridSection";
144     public static final String GROUP_BODY_ONLY = "Uif-BoxGroupBase";
145     public static final String GROUP_GRID_BODY_ONLY = "Uif-GridGroup";
146     public static final String TAB_GROUP = "Uif-TabSection";
147     public static final String NAVIGATION_GROUP = "Uif-NavigationGroupBase";
148     public static final String TREE_GROUP = "Uif-TreeSection";
149     public static final String LINK_GROUP = "Uif-LinkGroup";
150     public static final String DIALOG_GROUP = "Uif-DialogGroup";
151     public static final String COLLECTION_GROUP = "Uif-StackedCollectionSection";
152     public static final String COLLECTION_WITH_DISCLOSURE_GROUP = "Uif-Disclosure-StackedCollectionSection";
153     public static final String COLLECTION_GROUP_TABLE_LAYOUT = "Uif-TableCollectionSection";
154     public static final String COLLECTION_WITH_DISCLOSURE_GROUP_TABLE_LAYOUT = "Uif-Disclosure-TableCollectionSection";
155 
156     public static final String LIST_GROUP = "Uif-ListCollectionSection";
157 
158     public static final String HEADER = "Uif-HeaderFieldBase";
159     public static final String FOOTER = "Uif-FooterBase";
160     public static final String FOOTER_SAVECLOSECANCEL = "Uif-FormPageFooter";
161 
162     public static final String CONSTRAINT_MESSAGE = "Uif-ConstraintMessage";
163     public static final String INSTRUCTIONAL_MESSAGE = "Uif-InstructionalMessage";
164     public static final String HELP_ACTION = "Uif-HelpAction";
165     public static final String IMAGE_CAPTION_HEADER = "Uif-ImageCaptionHeader";
166     public static final String IMAGE_CUTLINE_MESSAGE = "Uif-ImageCutineMessage";
167 
168     public static final String LIGHTBOX = "Uif-LightBox";
169     public static final String QUICKFINDER = "Uif-QuickFinder";
170     public static final String INQUIRY = "Uif-Inquiry";
171 
172     public static final String ADD_BLANK_LINE_ACTION = "Uif-AddBlankLineAction";
173     public static final String ADD_WITH_DIALOG_ACTION = "Uif-AddWithDialogAction";
174     public static final String ADD_LINE_DIALOG = "Uif-AddLineDialog";
175     public static final String DIALOG_DISMISS_ACTION = "Uif-DialogDismissButton";
176     public static final String EDIT_LINE_DIALOG = "Uif-EditLineDialog";
177     public static final String EDIT_LINE_IN_DIALOG_ACTION = "Uif-EditLineInDialogAction";
178     public static final String EDIT_LINE_IN_DIALOG_SAVE_ACTION = "Uif-EditLineInDialogSaveAction";
179 
180     public static final String SESSION_TIMEOUT_WARNING_DIALOG = "Uif-SessionTimeoutWarning-DialogGroup";
181     public static final String SESSION_TIMEOUT_DIALOG = "Uif-SessionTimeout-DialogGroup";
182     public static final String YES_NO_DIALOG = "Uif-DialogGroup-YesNo";
183 
184     public static final String INQUIRY_VIEW = "Uif-InquiryView";
185     public static final String LOOKUP_VIEW = "Uif-LookupView";
186     public static final String LOOKUP_CRITERIA_FIELD = "Uif-LookupCriteriaInputField";
187     public static final String LOOKUP_CRITERIA_ACTIVE_INDICATOR_FIELD = "Uif-LookupActiveInputField";
188 
189     public static final String URL_INFO = "Uif-Url";
190 
191     private static Map<String, Component> cache = new HashMap<String, Component>();
192 
193     /**
194      * Returns a new {@link Component} instance for the given bean id from the spring factory.
195      *
196      * @param id id for the component in the view index
197      * @return Component new instance
198      */
199     public static Component getNewInstanceForRefresh(ViewPostMetadata viewPostMetadata, String id) {
200         String baseId = (String) viewPostMetadata.getComponentPostMetadata(id)
201                 .getData(UifConstants.PostMetadata.BASE_ID);
202         if (baseId == null) {
203             throw new RuntimeException(
204                     "Cannot create new instance for refresh. Base id not found for component id: " + id);
205         }
206 
207         Component component = (Component) KRADServiceLocatorWeb.getDataDictionaryService().getDictionaryBean(baseId);
208 
209         if (component != null) {
210             component = ComponentUtils.copy(component);
211         }
212 
213         return component;
214     }
215 
216     /**
217      * Returns a new {@link Component} instance for the given bean id from the spring factory.
218      *
219      * @param beanId id of the bean definition
220      * @return new component instance or null if no such component definition was found
221      */
222     public static Component getNewComponentInstance(String beanId) {
223         Component component;
224 
225         if (cache.containsKey(beanId)) {
226             component = cache.get(beanId);
227         } else {
228             component = (Component) KRADServiceLocatorWeb.getDataDictionaryService().getDictionaryBean(beanId);
229 
230             // clear id before returning so duplicates do not occur
231             component.setId(null);
232 
233             // populate property expressions from expression graph
234             ViewLifecycle.getExpressionEvaluator().populatePropertyExpressionsFromGraph(component, true);
235 
236             // TODO: preprocess?
237             // CopyUtils.preventModification(component);
238 
239             synchronized (cache) {
240                 cache.put(beanId, component);
241             }
242         }
243 
244         component = ComponentUtils.copy(component);
245 
246         return component;
247     }
248 
249     /**
250      * Retrieves a new Text control instance from Spring (initialized by the bean definition
251      * with the given id)
252      *
253      * @return TextControl
254      */
255     public static TextControl getTextControl() {
256         return (TextControl) getNewComponentInstance(TEXT_CONTROL);
257     }
258 
259     /**
260      * Retrieves a new Text area control instance from Spring (initialized by the bean definition
261      * with the given id)
262      *
263      * @return TextAreaControl
264      */
265     public static TextAreaControl getTextAreaControl() {
266         return (TextAreaControl) getNewComponentInstance(TEXTAREA_CONTROL);
267     }
268 
269     /**
270      * Retrieves a new checkbox control instance from Spring (initialized by the bean definition
271      * with the given id)
272      *
273      * @return CheckboxControl
274      */
275     public static CheckboxControl getCheckboxControl() {
276         return (CheckboxControl) getNewComponentInstance(CHECKBOX_CONTROL);
277     }
278 
279     /**
280      * Retrieves a new hidden control instance from Spring (initialized by the bean definition
281      * with the given id)
282      *
283      * @return HiddenControl
284      */
285     public static HiddenControl getHiddenControl() {
286         return (HiddenControl) getNewComponentInstance(HIDDEN_CONTROL);
287     }
288 
289     /**
290      * Retrieves a new select control instance from Spring (initialized by the bean definition
291      * with the given id)
292      *
293      * @return SelectControl
294      */
295     public static SelectControl getSelectControl() {
296         return (SelectControl) getNewComponentInstance(SELECT_CONTROL);
297     }
298 
299     /**
300      * Retrieves a new checkbox group control instance from Spring (initialized by the bean definition
301      * with the given id)
302      *
303      * <p>
304      * Return checkbox group set for vertical orientation
305      * </p>
306      *
307      * @return CheckboxGroupControl
308      */
309     public static CheckboxGroupControl getCheckboxGroupControl() {
310         return (CheckboxGroupControl) getNewComponentInstance(CHECKBOX_GROUP_CONTROL);
311     }
312 
313     /**
314      * Retrieves a new checkbox group control instance from Spring (initialized by the bean definition
315      * with the given id)
316      *
317      * <p>
318      * Return checkbox group set for horizontal orientation
319      * </p>
320      *
321      * @return CheckboxGroupControl
322      */
323     public static CheckboxGroupControl getCheckboxGroupControlHorizontal() {
324         return (CheckboxGroupControl) getNewComponentInstance(CHECKBOX_GROUP_CONTROL_HORIZONTAL);
325     }
326 
327     /**
328      * Retrieves a new radio group control instance from Spring (initialized by the bean definition
329      * with the given id)
330      *
331      * <p>
332      * Return radio group set for vertical orientation
333      * </p>
334      *
335      * @return RadioGroupControl
336      */
337     public static RadioGroupControl getRadioGroupControl() {
338         return (RadioGroupControl) getNewComponentInstance(RADIO_GROUP_CONTROL);
339     }
340 
341     /**
342      * Retrieves a new radio group control instance from Spring (initialized by the bean definition
343      * with the given id)
344      *
345      * <p>
346      * Return radio group set for horizontal orientation
347      * </p>
348      *
349      * @return RadioGroupControl
350      */
351     public static RadioGroupControl getRadioGroupControlHorizontal() {
352         return (RadioGroupControl) getNewComponentInstance(RADIO_GROUP_CONTROL_HORIZONTAL);
353     }
354 
355     /**
356      * Retrieves a new file control instance from Spring (initialized by the bean definition
357      * with the given id)
358      *
359      * @return FileControl
360      */
361     public static FileControl getFileControl() {
362         return (FileControl) getNewComponentInstance(FILE_CONTROL);
363     }
364 
365     /**
366      * Retrieves a new text control instance from Spring (initialized by the bean definition
367      * with the given id) configured for a date (enabled data picker)
368      *
369      * @return TextControl
370      */
371     public static TextControl getDateControl() {
372         return (TextControl) getNewComponentInstance(DATE_CONTROL);
373     }
374 
375     /**
376      * Retrieves a new text control instance from Spring (initialized by the bean definition
377      * with the given id) configured for KIM user input
378      *
379      * @return TextControl
380      */
381     public static UserControl getUserControl() {
382         return (UserControl) getNewComponentInstance(USER_CONTROL);
383     }
384 
385     /**
386      * Retrieves a new text control instance from Spring (initialized by the bean definition
387      * with the given id) configured for KIM group input
388      *
389      * @return TextControl
390      */
391     public static GroupControl getGroupControl() {
392         return (GroupControl) getNewComponentInstance(GROUP_CONTROL);
393     }
394 
395     /**
396      * Retrieves a new data field instance from Spring (initialized by the bean definition
397      * with the given id)
398      *
399      * @return DataField
400      */
401     public static DataField getDataField() {
402         return (DataField) getNewComponentInstance(DATA_FIELD);
403     }
404 
405     /**
406      * Retrieves a new data field instance from Spring (initialized by the bean definition
407      * with the given id) and sets the property name and label to the given parameters
408      *
409      * @param propertyName name of the property the data field should bind to
410      * @param label label for the field
411      * @return DataField
412      */
413     public static DataField getDataField(String propertyName, String label) {
414         DataField field = (DataField) getNewComponentInstance(DATA_FIELD);
415 
416         field.setPropertyName(propertyName);
417         field.setLabel(label);
418 
419         return field;
420     }
421 
422     /**
423      * Retrieves a new input field instance from Spring (initialized by the bean definition
424      * with the given id)
425      *
426      * @return InputField
427      */
428     public static InputField getInputField() {
429         return (InputField) getNewComponentInstance(INPUT_FIELD);
430     }
431 
432     /**
433      * Retrieves a new input field instance from Spring (initialized by the bean definition
434      * with the given id) and sets the property name and label to the given parameters
435      *
436      * @param propertyName name of the property the input field should bind to
437      * @param label label for the field
438      * @return InputField
439      */
440     public static InputField getInputField(String propertyName, String label) {
441         InputField field = (InputField) getNewComponentInstance(INPUT_FIELD);
442 
443         field.setPropertyName(propertyName);
444         field.setLabel(label);
445 
446         return field;
447     }
448 
449     /**
450      * Retrieves a new input field instance from Spring (initialized by the bean definition
451      * with the given id) and sets the property name, control, and label to the given parameters
452      *
453      * @param propertyName name of the property the input field should bind to
454      * @param label label for the field
455      * @param controlType enum that identifies the type of control to create for the input field
456      * @return InputField
457      */
458     public static InputField getInputField(String propertyName, String label, UifConstants.ControlType controlType) {
459         InputField field = (InputField) getNewComponentInstance(INPUT_FIELD);
460 
461         field.setPropertyName(propertyName);
462         field.setLabel(label);
463         field.setControl(getControl(controlType));
464 
465         return field;
466     }
467 
468     /**
469      * Retrieves a new input field instance from Spring (initialized by the bean definition
470      * with the given id) and sets the property name, control, defaultValue, and label to the given parameters
471      *
472      * @param propertyName name of the property the input field should bind to
473      * @param label label for the field
474      * @param controlType enum that identifies the type of control to create for the input field
475      * @param defaultValue default value for the property backing the input field
476      * @return InputField
477      */
478     public static InputField getInputField(String propertyName, String label, UifConstants.ControlType controlType,
479             String defaultValue) {
480         InputField field = (InputField) getNewComponentInstance(INPUT_FIELD);
481 
482         field.setPropertyName(propertyName);
483         field.setLabel(label);
484         field.setControl(getControl(controlType));
485         field.setDefaultValue(defaultValue);
486 
487         return field;
488     }
489 
490     /**
491      * Retrieves a new input field instance from Spring (initialized by the bean definition
492      * with the given id) and sets the property name, control, options finder, and label to the given parameters
493      *
494      * @param propertyName name of the property the input field should bind to
495      * @param label label for the field
496      * @param controlType enum that identifies the type of control to create for the input field
497      * @param optionsFinderClass class that will provide options for the control (assume control type is multi-value)
498      * @return InputField
499      */
500     public static InputField getInputField(String propertyName, String label, UifConstants.ControlType controlType,
501             Class<? extends KeyValuesFinder> optionsFinderClass) {
502         InputField field = (InputField) getNewComponentInstance(INPUT_FIELD);
503 
504         field.setPropertyName(propertyName);
505         field.setLabel(label);
506         field.setControl(getControl(controlType));
507         field.setOptionsFinderClass(optionsFinderClass);
508 
509         return field;
510     }
511 
512     /**
513      * Retrieves a new input field instance from Spring (initialized by the bean definition
514      * with the given id) and sets the property name, control, options, and label to the given parameters
515      *
516      * @param propertyName name of the property the input field should bind to
517      * @param label label for the field
518      * @param controlType enum that identifies the type of control to create for the input field
519      * @param options list of key value objects to set as the controls options
520      * @return InputField
521      */
522     public static InputField getInputField(String propertyName, String label, UifConstants.ControlType controlType,
523             List<KeyValue> options) {
524         InputField field = (InputField) getNewComponentInstance(INPUT_FIELD);
525 
526         field.setPropertyName(propertyName);
527         field.setLabel(label);
528 
529         Control control = getControl(controlType);
530         if (control instanceof MultiValueControl) {
531             ((MultiValueControl) control).setOptions(options);
532         } else {
533             throw new RuntimeException("Control is not instance of multi-value control, cannot set options");
534         }
535 
536         return field;
537     }
538 
539     /**
540      * Retrieves a new input field instance from Spring (initialized by the bean definition
541      * with the given id) and sets the property name, control, size, min and max length,
542      * and label to the given parameters
543      *
544      * @param propertyName name of the property the input field should bind to
545      * @param label label for the field
546      * @param controlType enum that identifies the type of control to create for the input field
547      * @param size size for the control
548      * @param maxLength max length for the field's value (also used for the control)
549      * @param minLength min length for the field's value (also used for the control)
550      * @return InputField
551      */
552     public static InputField getInputField(String propertyName, String label, UifConstants.ControlType controlType,
553             int size, int maxLength, int minLength) {
554         InputField field = (InputField) getNewComponentInstance(INPUT_FIELD);
555 
556         field.setPropertyName(propertyName);
557         field.setLabel(label);
558 
559         Control control = getControl(controlType);
560         if (control instanceof SizedControl) {
561             ((SizedControl) control).setSize(size);
562         } else {
563             throw new RuntimeException("Control does not support the size property");
564         }
565 
566         field.setMaxLength(maxLength);
567         field.setMinLength(minLength);
568 
569         return field;
570     }
571 
572     /**
573      * Builds a new <code>InputField</code> from the properties set on the
574      * given <code>RemotableAttributeField</code>
575      *
576      * <p>
577      * Note the returned InputField will not be initialized yet. Its state will be that of the initial
578      * object returned from the UIF dictionary with the properties set from the remotable attribute field, thus it
579      * is really just a more configuration complete field
580      * </p>
581      *
582      * @param remotableField field defined by a remove attribute
583      * 
584      * @return AttributeField instance built from remotable field
585      */
586     public static InputField translateRemotableField(RemotableAttributeField remotableField) {
587         InputField inputField = getInputField();
588 
589         inputField.setPropertyName(remotableField.getName());
590         inputField.setShortLabel(remotableField.getShortLabel());
591         inputField.setLabel(remotableField.getLongLabel());
592         inputField.setConstraintText(remotableField.getConstraintText());
593         inputField.setUppercaseValue(remotableField.isForceUpperCase());
594         inputField.setMinLength(remotableField.getMinLength());
595         inputField.setMaxLength(remotableField.getMaxLength());
596 
597         // why are exclusive min and max strings?
598         if (remotableField.getMinValue() != null) {
599             inputField.setExclusiveMin(remotableField.getMinValue().toString());
600         }
601         if (remotableField.getMaxValue() != null) {
602             inputField.setInclusiveMax(remotableField.getMaxValue().toString());
603         }
604         inputField.setRequired(remotableField.isRequired());
605 
606         if ((remotableField.getDefaultValues() != null) && !remotableField.getDefaultValues().isEmpty()) {
607             inputField.setDefaultValue(remotableField.getDefaultValues().iterator().next());
608         }
609 
610         if (StringUtils.isNotBlank(remotableField.getRegexConstraint())) {
611             ValidCharactersConstraint constraint = new ValidCharactersConstraint();
612             constraint.setValue(remotableField.getRegexConstraint());
613             inputField.setValidCharactersConstraint(constraint);
614             // TODO: how to deal with remotable field regexContraintMsg?
615         }
616 
617         RemotableDatepicker remotableDatepicker = null;
618         RemotableTextExpand remotableTextExpand = null;
619         RemotableQuickFinder remotableQuickFinder = null;
620         for (RemotableAbstractWidget remoteWidget : remotableField.getWidgets()) {
621             if (remoteWidget instanceof RemotableDatepicker) {
622                 remotableDatepicker = (RemotableDatepicker) remoteWidget;
623             } else if (remoteWidget instanceof RemotableTextExpand) {
624                 remotableTextExpand = (RemotableTextExpand) remoteWidget;
625             } else if (remoteWidget instanceof RemotableQuickFinder) {
626                 remotableQuickFinder = (RemotableQuickFinder) remoteWidget;
627             }
628         }
629 
630         if (remotableQuickFinder != null) {
631             if (inputField.getQuickfinder() == null) {
632                 inputField.setQuickfinder(ComponentFactory.getQuickFinder());
633             }
634 
635             inputField.getQuickfinder().setBaseLookupUrl(remotableQuickFinder.getBaseLookupUrl());
636             inputField.getQuickfinder().setDataObjectClassName(remotableQuickFinder.getDataObjectClass());
637             inputField.getQuickfinder().setLookupParameters(remotableQuickFinder.getLookupParameters());
638             inputField.getQuickfinder().setFieldConversions(remotableQuickFinder.getFieldConversions());
639         }
640 
641         if (remotableField.getControl() != null) {
642             Control control = null;
643 
644             RemotableControlContract remotableControl = remotableField.getControl();
645             if (remotableControl instanceof RemotableHiddenInput) {
646                 control = getHiddenControl();
647             } else if (remotableControl instanceof RemotableRadioButtonGroup) {
648                 RemotableRadioButtonGroup remotableRadioButtonGroup = (RemotableRadioButtonGroup) remotableControl;
649                 control = getRadioGroupControl();
650                 ((RadioGroupControl) control).setOptions(buildKeyValuePairs(remotableRadioButtonGroup.getKeyLabels()));
651             } else if (remotableControl instanceof RemotableSelect) {
652                 RemotableSelect remotableSelect = (RemotableSelect) remotableControl;
653                 control = getSelectControl();
654 
655                 Map<String, String> keyLabels = new HashMap<String, String>();
656                 if ((remotableSelect.getGroups() != null) && (!remotableSelect.getGroups().isEmpty())) {
657                     for (RemotableSelectGroup remotableSelectGroup : remotableSelect.getGroups()) {
658                         keyLabels.putAll(remotableSelectGroup.getKeyLabels());
659                     }
660                 } else {
661                     keyLabels = remotableSelect.getKeyLabels();
662                 }
663 
664                 ((SelectControl) control).setOptions(buildKeyValuePairs(keyLabels));
665                 if (remotableSelect.getSize() != null) {
666                     ((SelectControl) control).setSize(remotableSelect.getSize());
667                 }
668                 ((SelectControl) control).setMultiple(remotableSelect.isMultiple());
669             } else if (remotableControl instanceof RemotableCheckboxGroup) {
670                 RemotableCheckboxGroup remotableCheckboxGroup = (RemotableCheckboxGroup) remotableControl;
671                 control = getCheckboxGroupControl();
672                 ((CheckboxGroupControl) control).setOptions(buildKeyValuePairs(remotableCheckboxGroup.getKeyLabels()));
673             } else if (remotableControl instanceof RemotableCheckbox) {
674                 control = getCheckboxControl();
675             } else if (remotableControl instanceof RemotableTextarea) {
676                 RemotableTextarea remotableTextarea = (RemotableTextarea) remotableControl;
677                 control = getTextAreaControl();
678 
679                 if (remotableTextExpand != null) {
680                     ((TextAreaControl) control).setTextExpand(true);
681                 }
682                 ((TextAreaControl) control).setRows(remotableTextarea.getRows());
683                 ((TextAreaControl) control).setCols(remotableTextarea.getCols());
684                 ((TextAreaControl) control).setWatermarkText(remotableTextarea.getWatermark());
685 
686             } else if (remotableControl instanceof RemotableTextInput) {
687                 RemotableTextInput remotableTextInput = (RemotableTextInput) remotableControl;
688 
689                 if (remotableDatepicker != null) {
690                     control = getDateControl();
691                 } else {
692                     control = getTextControl();
693                 }
694 
695                 if (remotableTextExpand != null) {
696                     ((TextAreaControl) control).setTextExpand(true);
697                 }
698                 ((TextControl) control).setSize(remotableTextInput.getSize());
699                 ((TextControl) control).setWatermarkText(remotableTextInput.getWatermark());
700             }
701 
702             inputField.setControl(control);
703         }
704 
705         return inputField;
706     }
707 
708     /**
709      * For each remotable field in the given list creates a new {@link org.kuali.rice.krad.uif.field.InputField}
710      * instance and sets the
711      * corresponding properties from the remotable instance
712      *
713      * @param remotableFields list of remotable fields to translate
714      * @return List<AttributeField> list of attribute fields built from the remotable field properties
715      */
716     public static List<InputField> translateRemotableFields(List<RemotableAttributeField> remotableFields) {
717         List<InputField> inputFields = new ArrayList<InputField>();
718 
719         for (RemotableAttributeField remotableField : remotableFields) {
720             inputFields.add(translateRemotableField(remotableField));
721         }
722 
723         return inputFields;
724     }
725 
726     /**
727      * For each option in the given list, create a new {@link org.kuali.rice.core.api.util.KeyValue} instance
728      *
729      * @param optionsMap list of options
730      * @return List<KeyValue> list of key values built from the list of options
731      */
732     protected static List<KeyValue> buildKeyValuePairs(Map<String, String> optionsMap) {
733         List<KeyValue> options = new ArrayList<KeyValue>();
734 
735         for (Map.Entry<String, String> optionEntry : optionsMap.entrySet()) {
736             KeyValue keyValue = new ConcreteKeyValue(optionEntry.getKey(), optionEntry.getValue());
737             options.add(keyValue);
738         }
739 
740         return options;
741     }
742 
743     /**
744      * Gets the control
745      *
746      * @param controlType
747      * @return the control based on the control type
748      */
749     protected static Control getControl(UifConstants.ControlType controlType) {
750         Control control = null;
751         switch (controlType) {
752             case CHECKBOX:
753                 control = getCheckboxControl();
754                 break;
755             case CHECKBOXGROUP:
756                 control = getCheckboxGroupControl();
757                 break;
758             case FILE:
759                 control = getFileControl();
760                 break;
761             case GROUP:
762                 control = getGroupControl();
763                 break;
764             case HIDDEN:
765                 control = getHiddenControl();
766                 break;
767             case RADIOGROUP:
768                 control = getRadioGroupControl();
769                 break;
770             case SELECT:
771                 control = getSelectControl();
772                 break;
773             case TEXTAREA:
774                 control = getTextAreaControl();
775                 break;
776             case TEXT:
777                 control = getTextControl();
778                 break;
779             case USER:
780                 control = getUserControl();
781                 break;
782         }
783 
784         return control;
785     }
786 
787     /**
788      * Gets the errors field
789      *
790      * @return ValidationMessages errors field
791      */
792     public static ValidationMessages getErrorsField() {
793         return (ValidationMessages) getNewComponentInstance(ERRORS_FIELD);
794     }
795 
796     /**
797      * Gets the action
798      *
799      * @return action
800      */
801     public static Action getAction() {
802         return (Action) getNewComponentInstance(ACTION);
803     }
804 
805     /**
806      * Returns an instance of a secondary action component.
807      *
808      * @return action
809      */
810     public static Action getSecondaryAction() {
811         return (Action) getNewComponentInstance(SECONDARY_ACTION);
812     }
813 
814     /**
815      * Gets the action link
816      *
817      * @return action link
818      */
819     public static Action getActionLink() {
820         return (Action) getNewComponentInstance(ACTION_LINK);
821     }
822 
823     /**
824      * Gets the link field
825      *
826      * @return link field
827      */
828     public static LinkField getLinkField() {
829         return (LinkField) getNewComponentInstance(LINK_FIELD);
830     }
831 
832     /**
833      * Gets the iframe
834      *
835      * @return iframe
836      */
837     public static Iframe getIframe() {
838         return (Iframe) getNewComponentInstance(IFRAME);
839     }
840 
841     /**
842      * Gets the image field
843      *
844      * @return image field
845      */
846     public static ImageField getImageField() {
847         return (ImageField) getNewComponentInstance(IMAGE_FIELD);
848     }
849 
850     /**
851      * Gets the image component
852      *
853      * @return image field
854      */
855     public static Image getImage() {
856         return (Image) getNewComponentInstance(IMAGE);
857     }
858 
859     /**
860      * Gets the space field
861      *
862      * @return space field
863      */
864     public static SpaceField getSpaceField() {
865         return (SpaceField) getNewComponentInstance(SPACE_FIELD);
866     }
867 
868     /**
869      * Gets the generic field
870      *
871      * @return generic field
872      */
873     public static GenericField getGenericField() {
874         return (GenericField) getNewComponentInstance(GENERIC_FIELD);
875     }
876 
877     /**
878      * Gets the label
879      *
880      * @return label
881      */
882     public static Label getLabel() {
883         return (Label) getNewComponentInstance(LABEL);
884     }
885 
886     /**
887      * Gets the message
888      *
889      * @return message
890      */
891     public static Message getMessage() {
892         return (Message) getNewComponentInstance(MESSAGE);
893     }
894 
895     /**
896      * Gets the message field
897      *
898      * @return message field
899      */
900     public static MessageField getMessageField() {
901         return (MessageField) getNewComponentInstance(MESSAGE_FIELD);
902     }
903 
904     /**
905      * Gets the collection grouping field
906      *
907      * @return message field
908      */
909     public static MessageField getColGroupingField() {
910         return (MessageField) getNewComponentInstance(COLLECTION_GROUPING_FIELD);
911     }
912 
913     /**
914      * Gets the field group
915      *
916      * @return field group
917      */
918     public static FieldGroup getFieldGroup() {
919         return (FieldGroup) getNewComponentInstance(FIELD_GROUP);
920     }
921 
922     /**
923      * Gets the horizontal field group
924      *
925      * @return horizontal field group
926      */
927     public static FieldGroup getHorizontalFieldGroup() {
928         return (FieldGroup) getNewComponentInstance(HORIZONTAL_FIELD_GROUP);
929     }
930 
931     /**
932      * Gets the group
933      *
934      * @return group
935      */
936     public static Group getGroup() {
937         return (Group) getNewComponentInstance(GROUP);
938     }
939 
940     /**
941      * Gets the vertical box group
942      *
943      * @return group
944      */
945     public static Group getVerticalBoxGroup() {
946         return (Group) getNewComponentInstance(VERTICAL_BOX_GROUP);
947     }
948 
949     /**
950      * Gets the horizontal box group
951      *
952      * @return group
953      */
954     public static Group getHorizontalBoxGroup() {
955         return (Group) getNewComponentInstance(HORIZONTAL_BOX_GROUP);
956     }
957 
958     /**
959      * Gets the vertical box section
960      *
961      * @return group
962      */
963     public static Group getVerticalBoxSection() {
964         return (Group) getNewComponentInstance(VERTICAL_BOX_SECTION);
965     }
966 
967     /**
968      * Gets the horizontal box section
969      *
970      * @return group
971      */
972     public static Group getHorizontalBoxSection() {
973         return (Group) getNewComponentInstance(HORIZONTAL_BOX_SECTION);
974     }
975 
976     /**
977      * Gets the page group
978      *
979      * @return page group
980      */
981     public static PageGroup getPageGroup() {
982         return (PageGroup) getNewComponentInstance(PAGE_GROUP);
983     }
984 
985     /**
986      * Gets the group grid layout
987      *
988      * @return group grid layout
989      */
990     public static Group getGroupGridLayout() {
991         return (Group) getNewComponentInstance(GROUP_GRID_LAYOUT);
992     }
993 
994     public static Group getGroupWithDisclosureGridLayout() {
995         return (Group) getNewComponentInstance(GROUP_WITH_DISCLOSURE_GRID_LAYOUT);
996     }
997 
998     /**
999      * Gets the group body only
1000      *
1001      * @return group body only
1002      */
1003     public static Group getGroupBodyOnly() {
1004         return (Group) getNewComponentInstance(GROUP_BODY_ONLY);
1005     }
1006 
1007     /**
1008      * Gets the group grid body only
1009      *
1010      * @return group grid body only
1011      */
1012     public static Group getGroupGridBodyOnly() {
1013         return (Group) getNewComponentInstance(GROUP_GRID_BODY_ONLY);
1014     }
1015 
1016     /**
1017      * Gets the tab group
1018      *
1019      * @return tab group
1020      */
1021     public static TabGroup getTabGroup() {
1022         return (TabGroup) getNewComponentInstance(TAB_GROUP);
1023     }
1024 
1025     /**
1026      * Gets the navigation group
1027      *
1028      * @return navigation group
1029      */
1030     public static TabNavigationGroup getNavigationGroup() {
1031         return (TabNavigationGroup) getNewComponentInstance(NAVIGATION_GROUP);
1032     }
1033 
1034     /**
1035      * Gets the tree group
1036      *
1037      * @return tree group
1038      */
1039     public static TreeGroup getTreeGroup() {
1040         return (TreeGroup) getNewComponentInstance(TREE_GROUP);
1041     }
1042 
1043     /**
1044      * Gets the link group
1045      *
1046      * @return link group
1047      */
1048     public static LinkGroup getLinkGroup() {
1049         return (LinkGroup) getNewComponentInstance(LINK_GROUP);
1050     }
1051 
1052     /**
1053      * Gets the collection group
1054      *
1055      * @return collection group
1056      */
1057     public static CollectionGroup getCollectionGroup() {
1058         return (CollectionGroup) getNewComponentInstance(COLLECTION_GROUP);
1059     }
1060 
1061     /**
1062      * Gets the collection group with disclosure behavior
1063      *
1064      * @return collection group
1065      */
1066     public static CollectionGroup getCollectionWithDisclosureGroup() {
1067         return (CollectionGroup) getNewComponentInstance(COLLECTION_WITH_DISCLOSURE_GROUP);
1068     }
1069 
1070     /**
1071      * Gets the collection group table layout
1072      *
1073      * @return collection group table layout
1074      */
1075     public static CollectionGroup getCollectionGroupTableLayout() {
1076         return (CollectionGroup) getNewComponentInstance(COLLECTION_GROUP_TABLE_LAYOUT);
1077     }
1078 
1079     /**
1080      * Gets the collection group table layout with disclosure behavior
1081      *
1082      * @return collection group table layout
1083      */
1084     public static CollectionGroup getCollectionWithDisclosureGroupTableLayout() {
1085         return (CollectionGroup) getNewComponentInstance(COLLECTION_WITH_DISCLOSURE_GROUP_TABLE_LAYOUT);
1086     }
1087 
1088     /**
1089      * Gets the list group
1090      *
1091      * @return list group
1092      */
1093     public static CollectionGroup getListGroup() {
1094         return (CollectionGroup) getNewComponentInstance(LIST_GROUP);
1095     }
1096 
1097     /**
1098      * Gets the header
1099      *
1100      * @return header
1101      */
1102     public static Header getHeader() {
1103         return (Header) getNewComponentInstance(HEADER);
1104     }
1105 
1106     /**
1107      * Gets the footer
1108      *
1109      * @return footer
1110      */
1111     public static Group getFooter() {
1112         return (Group) getNewComponentInstance(FOOTER);
1113     }
1114 
1115     /**
1116      * Gets the footer save/close/cancel
1117      *
1118      * @return footer save/close/cancel
1119      */
1120     public static Group getFooterSaveCloseCancel() {
1121         return (Group) getNewComponentInstance(FOOTER_SAVECLOSECANCEL);
1122     }
1123 
1124     /**
1125      * Gets the default action component configured for help
1126      *
1127      * @return Action for help display
1128      */
1129     public static Action getHelpAction() {
1130         return (Action) getNewComponentInstance(HELP_ACTION);
1131     }
1132 
1133     /**
1134      * Gets the default constraint message configuration
1135      *
1136      * @return Message component for constraint messages
1137      */
1138     public static Message getConstraintMessage() {
1139         return (Message) getNewComponentInstance(CONSTRAINT_MESSAGE);
1140     }
1141 
1142     /**
1143      * Gets the default instructional message configuration
1144      *
1145      * @return Message component for instructional messages
1146      */
1147     public static Message getInstructionalMessage() {
1148         return (Message) getNewComponentInstance(INSTRUCTIONAL_MESSAGE);
1149     }
1150 
1151     /**
1152      * Gets the default image caption header configuration
1153      *
1154      * @return Header component for image caption headers
1155      */
1156     public static Header getImageCaptionHeader() {
1157         return (Header) getNewComponentInstance(IMAGE_CAPTION_HEADER);
1158     }
1159 
1160     /**
1161      * Gets the default image cutline message configuration
1162      *
1163      * @return Message component for image cutlines messages
1164      */
1165     public static Message getImageCutlineMessage() {
1166         return (Message) getNewComponentInstance(IMAGE_CUTLINE_MESSAGE);
1167     }
1168 
1169     /**
1170      * Gets the default lightbox configuration
1171      *
1172      * @return Lightbox component
1173      */
1174     public static LightBox getLightBox() {
1175         return (LightBox) getNewComponentInstance(LIGHTBOX);
1176     }
1177 
1178     /**
1179      * Gets the default quickfinder configuration
1180      *
1181      * @return QuickFinder component
1182      */
1183     public static QuickFinder getQuickFinder() {
1184         return (QuickFinder) getNewComponentInstance(QUICKFINDER);
1185     }
1186 
1187     /**
1188      * Gets the default inquiry configuration
1189      *
1190      * @return Inquiry component
1191      */
1192     public static Inquiry getInquiry() {
1193         return (Inquiry) getNewComponentInstance(INQUIRY);
1194     }
1195 
1196     /**
1197      * Gets an instance of the session timeout warning dialog
1198      *
1199      * @return instance of session timeout warning dialog
1200      */
1201     public static DialogGroup getSessionTimeoutWarningDialog() {
1202         return (DialogGroup) getNewComponentInstance(SESSION_TIMEOUT_WARNING_DIALOG);
1203     }
1204 
1205     /**
1206      * Gets an instance of the session timeout dialog
1207      *
1208      * @return instance of session timeout dialog
1209      */
1210     public static DialogGroup getSessionTimeoutDialog() {
1211         return (DialogGroup) getNewComponentInstance(SESSION_TIMEOUT_DIALOG);
1212     }
1213 
1214     /**
1215      * Gets an instance of the yes no dialog
1216      *
1217      * @return instance of yes no dialog
1218      */
1219     public static DialogGroup getYesNoDialog() {
1220         return (DialogGroup) getNewComponentInstance(YES_NO_DIALOG);
1221     }
1222 
1223     /**
1224      * Gets an instance of an UrlInfo
1225      *
1226      * @return instance of UrlInfo
1227      */
1228     public static UrlInfo getUrlInfo() {
1229         return (UrlInfo) getNewComponentInstance(URL_INFO);
1230     }
1231 
1232     /**
1233      * Gets an empty inquiry view configuration for population.
1234      *
1235      * @return InquiryView component
1236      */
1237     public static InquiryView getInquiryView() {
1238         return (InquiryView) getNewComponentInstance(INQUIRY_VIEW);
1239     }
1240 
1241     /**
1242      * Gets an empty lookup view configuration for population.
1243      *
1244      * @return LookupView component
1245      */
1246     public static LookupView getLookupView() {
1247         return (LookupView) getNewComponentInstance(LOOKUP_VIEW);
1248     }
1249 
1250     /**
1251      * Gets a component instance for an input field in the lookup criteria section
1252      * @return lookup input field instance
1253      */
1254     public static LookupInputField getLookupCriteriaInputField() {
1255         return (LookupInputField) getNewComponentInstance(LOOKUP_CRITERIA_FIELD);
1256     }
1257 
1258     /**
1259      * Gets a component instance for an input field for the active indicator
1260      * in the lookup criteria section
1261      * @return lookup input field instance
1262      */
1263     public static LookupInputField getLookupCriteriaActiveIndicatorInputField() {
1264         return (LookupInputField) getNewComponentInstance(LOOKUP_CRITERIA_ACTIVE_INDICATOR_FIELD);
1265     }
1266 }