View Javadoc

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