001    /**
002     * Copyright 2005-2012 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.rice.krad.uif.util;
017    
018    import org.apache.commons.lang.StringUtils;
019    import org.apache.commons.logging.Log;
020    import org.apache.commons.logging.LogFactory;
021    import org.kuali.rice.core.api.uif.RemotableAbstractWidget;
022    import org.kuali.rice.core.api.uif.RemotableAttributeField;
023    import org.kuali.rice.core.api.uif.RemotableCheckbox;
024    import org.kuali.rice.core.api.uif.RemotableCheckboxGroup;
025    import org.kuali.rice.core.api.uif.RemotableControlContract;
026    import org.kuali.rice.core.api.uif.RemotableDatepicker;
027    import org.kuali.rice.core.api.uif.RemotableHiddenInput;
028    import org.kuali.rice.core.api.uif.RemotableQuickFinder;
029    import org.kuali.rice.core.api.uif.RemotableRadioButtonGroup;
030    import org.kuali.rice.core.api.uif.RemotableSelect;
031    import org.kuali.rice.core.api.uif.RemotableSelectGroup;
032    import org.kuali.rice.core.api.uif.RemotableTextExpand;
033    import org.kuali.rice.core.api.uif.RemotableTextInput;
034    import org.kuali.rice.core.api.uif.RemotableTextarea;
035    import org.kuali.rice.core.api.util.ConcreteKeyValue;
036    import org.kuali.rice.core.api.util.KeyValue;
037    import org.kuali.rice.krad.datadictionary.validation.constraint.ValidCharactersConstraint;
038    import org.kuali.rice.krad.keyvalues.KeyValuesFinder;
039    import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
040    import org.kuali.rice.krad.uif.UifConstants;
041    import org.kuali.rice.krad.uif.container.CollectionGroup;
042    import org.kuali.rice.krad.uif.container.Group;
043    import org.kuali.rice.krad.uif.container.LinkGroup;
044    import org.kuali.rice.krad.uif.container.NavigationGroup;
045    import org.kuali.rice.krad.uif.container.PageGroup;
046    import org.kuali.rice.krad.uif.container.TabGroup;
047    import org.kuali.rice.krad.uif.container.TreeGroup;
048    import org.kuali.rice.krad.uif.control.CheckboxControl;
049    import org.kuali.rice.krad.uif.control.CheckboxGroupControl;
050    import org.kuali.rice.krad.uif.control.Control;
051    import org.kuali.rice.krad.uif.control.FileControl;
052    import org.kuali.rice.krad.uif.control.HiddenControl;
053    import org.kuali.rice.krad.uif.control.MultiValueControl;
054    import org.kuali.rice.krad.uif.control.RadioGroupControl;
055    import org.kuali.rice.krad.uif.control.SelectControl;
056    import org.kuali.rice.krad.uif.control.SizedControl;
057    import org.kuali.rice.krad.uif.control.TextAreaControl;
058    import org.kuali.rice.krad.uif.control.TextControl;
059    import org.kuali.rice.krad.uif.component.Component;
060    import org.kuali.rice.krad.uif.element.Action;
061    import org.kuali.rice.krad.uif.element.Header;
062    import org.kuali.rice.krad.uif.element.Iframe;
063    import org.kuali.rice.krad.uif.element.Image;
064    import org.kuali.rice.krad.uif.element.Label;
065    import org.kuali.rice.krad.uif.element.Message;
066    import org.kuali.rice.krad.uif.element.ValidationMessages;
067    import org.kuali.rice.krad.uif.field.DataField;
068    import org.kuali.rice.krad.uif.field.InputField;
069    import org.kuali.rice.krad.uif.field.MessageField;
070    import org.kuali.rice.krad.uif.field.SpaceField;
071    import org.kuali.rice.krad.uif.field.FieldGroup;
072    import org.kuali.rice.krad.uif.field.GenericField;
073    import org.kuali.rice.krad.uif.field.ImageField;
074    import org.kuali.rice.krad.uif.field.LinkField;
075    import org.kuali.rice.krad.uif.view.View;
076    
077    import java.util.ArrayList;
078    import java.util.HashMap;
079    import java.util.List;
080    import java.util.Map;
081    
082    /**
083     * Factory class for creating new UIF components from their base definitions
084     * in the dictionary
085     *
086     * @author Kuali Rice Team (rice.collab@kuali.org)
087     */
088    public class ComponentFactory {
089        
090        private static Log LOG = LogFactory.getLog(ComponentFactory.class);
091    
092        protected static final String TEXT_CONTROL = "Uif-TextControl";
093        protected static final String CHECKBOX_CONTROL = "Uif-CheckboxControl";
094        protected static final String HIDDEN_CONTROL = "Uif-HiddenControl";
095        protected static final String TEXTAREA_CONTROL = "Uif-TextAreaControl";
096        protected static final String SELECT_CONTROL = "Uif-DropdownControl";
097        protected static final String CHECKBOX_GROUP_CONTROL = "Uif-VerticalCheckboxesControl";
098        protected static final String CHECKBOX_GROUP_CONTROL_HORIZONTAL = "Uif-HorizontalCheckboxesControl";
099        protected static final String RADIO_GROUP_CONTROL = "Uif-VerticalRadioControl";
100        protected static final String RADIO_GROUP_CONTROL_HORIZONTAL = "Uif-HorizontalRadioControl";
101        protected static final String FILE_CONTROL = "Uif-FileControl";
102        protected static final String DATE_CONTROL = "Uif-DateControl";
103        protected static final String USER_CONTROL = "Uif-KimPersonControl";
104        protected static final String GROUP_CONTROL = "Uif-KimGroupControl";
105    
106        protected static final String DATA_FIELD = "Uif-DataField";
107        protected static final String INPUT_FIELD = "Uif-InputField";
108        protected static final String ERRORS_FIELD = "Uif-FieldValidationMessages";
109        protected static final String ACTION = "Uif-PrimaryActionButton";
110        protected static final String ACTION_LINK = "Uif-ActionLink";
111        protected static final String LINK_FIELD = "Uif-LinkField";
112        protected static final String IFRAME = "Uif-Iframe";
113        protected static final String IMAGE_FIELD = "Uif-ImageField";
114        protected static final String SPACE_FIELD = "Uif-SpaceField";
115        protected static final String GENERIC_FIELD = "Uif-CustomTemplateField";
116        protected static final String IMAGE = "Uif-Image";
117        protected static final String LABEL = "Uif-Label";
118        protected static final String MESSAGE = "Uif-Message";
119        protected static final String MESSAGE_FIELD = "Uif-MessageField";
120        protected static final String FIELD_GROUP = "Uif-VerticalFieldGroup";
121        protected static final String HORIZONTAL_FIELD_GROUP = "Uif-HorizontalFieldGroup";
122    
123        protected static final String GROUP = "Uif-BoxSection";
124        protected static final String PAGE_GROUP = "Uif-Page";
125        protected static final String GROUP_GRID_LAYOUT = "Uif-GridSection";
126        protected static final String GROUP_BODY_ONLY = "Uif-BoxGroup";
127        protected static final String GROUP_GRID_BODY_ONLY = "Uif-GridGroup";
128        protected static final String TAB_GROUP = "Uif-TabSection";
129        protected static final String NAVIGATION_GROUP = "Uif-NavigationGroupBase";
130        protected static final String TREE_GROUP = "Uif-TreeSection";
131        protected static final String LINK_GROUP = "Uif-LinkGroup";
132        protected static final String COLLECTION_GROUP = "Uif-StackedCollectionSection";
133        protected static final String COLLECTION_GROUP_TABLE_LAYOUT = "Uif-TableCollectionSection";
134        protected static final String LIST_GROUP = "Uif-ListCollectionSection";
135    
136        protected static final String HEADER = "Uif-HeaderFieldBase";
137        protected static final String FOOTER = "Uif-FooterBase";
138        protected static final String FOOTER_SAVECLOSECANCEL = "Uif-FormPageFooter";
139    
140        protected static final String CONSTRAINT_MESSAGE = "Uif-ConstraintMessage";
141        protected static final String INSTRUCTIONAL_MESSAGE = "Uif-InstructionalMessage";
142        protected static final String HELP_ACTION = "Uif-HelpAction";
143        protected static final String IMAGE_CAPTION_HEADER = "Uif-ImageCaptionHeader";
144        protected static final String IMAGE_CUTLINE_MESSAGE = "Uif-ImageCutineMessage";
145    
146        private static Map<String, Component> cache = new HashMap<String, Component>();
147    
148        /**
149         * Gets a fresh copy of the component by the id passed in which used to look up the component in
150         * the view index, then retrieve a new instance with initial state configured using the factory id
151         *
152         * @param id - id for the component in the view index
153         * @return Component new instance
154         */
155        public static Component getNewInstanceForRefresh(View view, String id) {
156            Component component = null;
157            Component origComponent = view.getViewIndex().getComponentById(id);
158    
159            if (origComponent == null) {
160                throw new RuntimeException(id + " not found in view index try setting p:forceSessionPersistence=\"true\" in xml");
161            }
162    
163            if (view.getViewIndex().getInitialComponentStates().containsKey(origComponent.getBaseId())) {
164                component = view.getViewIndex().getInitialComponentStates().get(origComponent.getBaseId());
165                LOG.debug("getNewInstanceForRefresh: id '" + id + "' was found in initialStates");
166            } else {
167                component = (Component) KRADServiceLocatorWeb.getDataDictionaryService().getDictionaryObject(
168                        origComponent.getBaseId());
169                LOG.debug("getNewInstanceForRefresh: id '"
170                        + id
171                        + "' was NOT found in initialStates. New one fetched from DD");
172            }
173    
174            if (component != null) {
175                component = ComponentUtils.copyObject(component);
176                component.setId(origComponent.getBaseId());
177            }
178    
179            return component;
180        }
181    
182        /**
183         * Returns a new <code>Component</code> instance for the given bean id from the spring factory
184         *
185         * @param beanId - id of the bean definition
186         * @return new component instance or null if no such component definition was found
187         */
188        public static Component getNewComponentInstance(String beanId) {
189            Component component = null;
190            if (cache.containsKey(beanId)) {
191                component = ComponentUtils.copy(cache.get(beanId));
192            } else {
193                component = (Component) KRADServiceLocatorWeb.getDataDictionaryService().getDictionaryObject(beanId);
194    
195                // clear id before returning so duplicates do not occur
196                component.setId(null);
197                component.setBaseId(null);
198    
199                // populate property expressions from expression graph
200                ExpressionUtils.populatePropertyExpressionsFromGraph(component, true);
201    
202                // add to cache
203                cache.put(beanId, ComponentUtils.copy(component));
204            }
205    
206            return component;
207        }
208    
209        /**
210         * Retrieves a new Text control instance from Spring (initialized by the bean definition
211         * with the given id)
212         *
213         * @return TextControl
214         */
215        public static TextControl getTextControl() {
216            return (TextControl) getNewComponentInstance(TEXT_CONTROL);
217        }
218    
219        /**
220         * Retrieves a new Text area control instance from Spring (initialized by the bean definition
221         * with the given id)
222         *
223         * @return TextAreaControl
224         */
225        public static TextAreaControl getTextAreaControl() {
226            return (TextAreaControl) getNewComponentInstance(TEXTAREA_CONTROL);
227        }
228    
229        /**
230         * Retrieves a new checkbox control instance from Spring (initialized by the bean definition
231         * with the given id)
232         *
233         * @return CheckboxControl
234         */
235        public static CheckboxControl getCheckboxControl() {
236            return (CheckboxControl) getNewComponentInstance(CHECKBOX_CONTROL);
237        }
238    
239        /**
240         * Retrieves a new hidden control instance from Spring (initialized by the bean definition
241         * with the given id)
242         *
243         * @return HiddenControl
244         */
245        public static HiddenControl getHiddenControl() {
246            return (HiddenControl) getNewComponentInstance(HIDDEN_CONTROL);
247        }
248    
249        /**
250         * Retrieves a new select control instance from Spring (initialized by the bean definition
251         * with the given id)
252         *
253         * @return SelectControl
254         */
255        public static SelectControl getSelectControl() {
256            return (SelectControl) getNewComponentInstance(SELECT_CONTROL);
257        }
258    
259        /**
260         * Retrieves a new checkbox group control instance from Spring (initialized by the bean definition
261         * with the given id)
262         *
263         * <p>
264         * Return checkbox group set for vertical orientation
265         * </p>
266         *
267         * @return CheckboxGroupControl
268         */
269        public static CheckboxGroupControl getCheckboxGroupControl() {
270            return (CheckboxGroupControl) getNewComponentInstance(CHECKBOX_GROUP_CONTROL);
271        }
272    
273        /**
274         * Retrieves a new checkbox group control instance from Spring (initialized by the bean definition
275         * with the given id)
276         *
277         * <p>
278         * Return checkbox group set for horizontal orientation
279         * </p>
280         *
281         * @return CheckboxGroupControl
282         */
283        public static CheckboxGroupControl getCheckboxGroupControlHorizontal() {
284            return (CheckboxGroupControl) getNewComponentInstance(CHECKBOX_GROUP_CONTROL_HORIZONTAL);
285        }
286    
287        /**
288         * Retrieves a new radio group control instance from Spring (initialized by the bean definition
289         * with the given id)
290         *
291         * <p>
292         * Return radio group set for vertical orientation
293         * </p>
294         *
295         * @return RadioGroupControl
296         */
297        public static RadioGroupControl getRadioGroupControl() {
298            return (RadioGroupControl) getNewComponentInstance(RADIO_GROUP_CONTROL);
299        }
300    
301        /**
302         * Retrieves a new radio group control instance from Spring (initialized by the bean definition
303         * with the given id)
304         *
305         * <p>
306         * Return radio group set for horizontal orientation
307         * </p>
308         *
309         * @return RadioGroupControl
310         */
311        public static RadioGroupControl getRadioGroupControlHorizontal() {
312            return (RadioGroupControl) getNewComponentInstance(RADIO_GROUP_CONTROL_HORIZONTAL);
313        }
314    
315        /**
316         * Retrieves a new file control instance from Spring (initialized by the bean definition
317         * with the given id)
318         *
319         * @return FileControl
320         */
321        public static FileControl getFileControl() {
322            return (FileControl) getNewComponentInstance(FILE_CONTROL);
323        }
324    
325        /**
326         * Retrieves a new text control instance from Spring (initialized by the bean definition
327         * with the given id) configured for a date (enabled data picker)
328         *
329         * @return TextControl
330         */
331        public static TextControl getDateControl() {
332            return (TextControl) getNewComponentInstance(DATE_CONTROL);
333        }
334    
335        /**
336         * Retrieves a new text control instance from Spring (initialized by the bean definition
337         * with the given id) configured for KIM user input
338         *
339         * @return TextControl
340         */
341        public static TextControl getUserControl() {
342            return (TextControl) getNewComponentInstance(USER_CONTROL);
343        }
344    
345        /**
346         * Retrieves a new text control instance from Spring (initialized by the bean definition
347         * with the given id) configured for KIM group input
348         *
349         * @return TextControl
350         */
351        public static TextControl getGroupControl() {
352            return (TextControl) getNewComponentInstance(GROUP_CONTROL);
353        }
354    
355        /**
356         * Retrieves a new data field instance from Spring (initialized by the bean definition
357         * with the given id)
358         *
359         * @return DataField
360         */
361        public static DataField getDataField() {
362            return (DataField) getNewComponentInstance(DATA_FIELD);
363        }
364    
365        /**
366         * Retrieves a new data field instance from Spring (initialized by the bean definition
367         * with the given id) and sets the property name and label to the given parameters
368         *
369         * @param propertyName - name of the property the data field should bind to
370         * @param label - label for the field
371         * @return DataField
372         */
373        public static DataField getDataField(String propertyName, String label) {
374            DataField field = (DataField) getNewComponentInstance(DATA_FIELD);
375    
376            field.setPropertyName(propertyName);
377            field.setLabel(label);
378    
379            return field;
380        }
381    
382        /**
383         * Retrieves a new input field instance from Spring (initialized by the bean definition
384         * with the given id)
385         *
386         * @return InputField
387         */
388        public static InputField getInputField() {
389            return (InputField) getNewComponentInstance(INPUT_FIELD);
390        }
391    
392        /**
393         * Retrieves a new input 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 input field should bind to
397         * @param label - label for the field
398         * @return InputField
399         */
400        public static InputField getInputField(String propertyName, String label) {
401            InputField field = (InputField) getNewComponentInstance(INPUT_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) and sets the property name, control, and label to the given parameters
412         *
413         * @param propertyName - name of the property the input field should bind to
414         * @param label - label for the field
415         * @param controlType - enum that identifies the type of control to create for the input field
416         * @return InputField
417         */
418        public static InputField getInputField(String propertyName, String label, UifConstants.ControlType controlType) {
419            InputField field = (InputField) getNewComponentInstance(INPUT_FIELD);
420    
421            field.setPropertyName(propertyName);
422            field.setLabel(label);
423            field.setControl(getControl(controlType));
424    
425            return field;
426        }
427    
428        /**
429         * Retrieves a new input field instance from Spring (initialized by the bean definition
430         * with the given id) and sets the property name, control, defaultValue, and label to the given parameters
431         *
432         * @param propertyName - name of the property the input field should bind to
433         * @param label - label for the field
434         * @param controlType - enum that identifies the type of control to create for the input field
435         * @param defaultValue - default value for the property backing the input field
436         * @return InputField
437         */
438        public static InputField getInputField(String propertyName, String label, UifConstants.ControlType controlType,
439                String defaultValue) {
440            InputField field = (InputField) getNewComponentInstance(INPUT_FIELD);
441    
442            field.setPropertyName(propertyName);
443            field.setLabel(label);
444            field.setControl(getControl(controlType));
445            field.setDefaultValue(defaultValue);
446    
447            return field;
448        }
449    
450        /**
451         * Retrieves a new input field instance from Spring (initialized by the bean definition
452         * with the given id) and sets the property name, control, options finder, and label to the given parameters
453         *
454         * @param propertyName - name of the property the input field should bind to
455         * @param label - label for the field
456         * @param controlType - enum that identifies the type of control to create for the input field
457         * @param optionsFinderClass - class that will provide options for the control (assume control type is multi-value)
458         * @return InputField
459         */
460        public static InputField getInputField(String propertyName, String label, UifConstants.ControlType controlType,
461                Class<? extends KeyValuesFinder> optionsFinderClass) {
462            InputField field = (InputField) getNewComponentInstance(INPUT_FIELD);
463    
464            field.setPropertyName(propertyName);
465            field.setLabel(label);
466            field.setControl(getControl(controlType));
467            field.setOptionsFinderClass(optionsFinderClass);
468    
469            return field;
470        }
471    
472        /**
473         * Retrieves a new input field instance from Spring (initialized by the bean definition
474         * with the given id) and sets the property name, control, options, and label to the given parameters
475         *
476         * @param propertyName - name of the property the input field should bind to
477         * @param label - label for the field
478         * @param controlType - enum that identifies the type of control to create for the input field
479         * @param options - list of key value objects to set as the controls options
480         * @return InputField
481         */
482        public static InputField getInputField(String propertyName, String label, UifConstants.ControlType controlType,
483                List<KeyValue> options) {
484            InputField field = (InputField) getNewComponentInstance(INPUT_FIELD);
485    
486            field.setPropertyName(propertyName);
487            field.setLabel(label);
488    
489            Control control = getControl(controlType);
490            if (control instanceof MultiValueControl) {
491                ((MultiValueControl) control).setOptions(options);
492            } else {
493                throw new RuntimeException("Control is not instance of multi-value control, cannot set options");
494            }
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, size, min and max length,
502         * and label to the given parameters
503         *
504         * @param propertyName - name of the property the input field should bind to
505         * @param label - label for the field
506         * @param controlType - enum that identifies the type of control to create for the input field
507         * @param size - size for the control
508         * @param maxLength - max length for the field's value (also used for the control)
509         * @param minLength - min length for the field's value (also used for the control)
510         * @return InputField
511         */
512        public static InputField getInputField(String propertyName, String label, UifConstants.ControlType controlType,
513                int size, int maxLength, int minLength) {
514            InputField field = (InputField) getNewComponentInstance(INPUT_FIELD);
515    
516            field.setPropertyName(propertyName);
517            field.setLabel(label);
518    
519            Control control = getControl(controlType);
520            if (control instanceof SizedControl) {
521                ((SizedControl) control).setSize(size);
522            } else {
523                throw new RuntimeException("Control does not support the size property");
524            }
525    
526            field.setMaxLength(maxLength);
527            field.setMinLength(minLength);
528    
529            return field;
530        }
531    
532        /**
533         * Builds a new <code>InputField</code> from the properties set on the
534         * given <code>RemotableAttributeField</code>
535         *
536         * <p>
537         * Note the returned InputField will not be initialized yet. Its state will be that of the initial
538         * object returned from the UIF dictionary with the properties set from the remotable attribute field, thus it
539         * is really just a more configuration complete field
540         * </p>
541         *
542         * @return AttributeField instance built from remotable field
543         */
544        public static InputField translateRemotableField(RemotableAttributeField remotableField) {
545            InputField inputField = getInputField();
546    
547            inputField.setPropertyName(remotableField.getName());
548            inputField.setShortLabel(remotableField.getShortLabel());
549            inputField.setLabel(remotableField.getLongLabel());
550            inputField.setConstraintText(remotableField.getConstraintText());
551            inputField.setUppercaseValue(remotableField.isForceUpperCase());
552            inputField.setMinLength(remotableField.getMinLength());
553            inputField.setMaxLength(remotableField.getMaxLength());
554    
555            // why are exclusive min and max strings?
556            if (remotableField.getMinValue() != null) {
557                inputField.setExclusiveMin(remotableField.getMinValue().toString());
558            }
559            if (remotableField.getMaxValue() != null) {
560                inputField.setInclusiveMax(remotableField.getMaxValue().toString());
561            }
562            inputField.setRequired(remotableField.isRequired());
563    
564            if ((remotableField.getDefaultValues() != null) && !remotableField.getDefaultValues().isEmpty()) {
565                inputField.setDefaultValue(remotableField.getDefaultValues().iterator().next());
566            }
567    
568            if (StringUtils.isNotBlank(remotableField.getRegexConstraint())) {
569                ValidCharactersConstraint constraint = new ValidCharactersConstraint();
570                constraint.setValue(remotableField.getRegexConstraint());
571                inputField.setValidCharactersConstraint(constraint);
572                // TODO: how to deal with remotable field regexContraintMsg?
573            }
574    
575            RemotableDatepicker remotableDatepicker = null;
576            RemotableTextExpand remotableTextExpand = null;
577            RemotableQuickFinder remotableQuickFinder = null;
578            for (RemotableAbstractWidget remoteWidget : remotableField.getWidgets()) {
579                if (remoteWidget instanceof RemotableDatepicker) {
580                    remotableDatepicker = (RemotableDatepicker) remoteWidget;
581                } else if (remoteWidget instanceof RemotableTextExpand) {
582                    remotableTextExpand = (RemotableTextExpand) remoteWidget;
583                } else if (remoteWidget instanceof RemotableQuickFinder) {
584                    remotableQuickFinder = (RemotableQuickFinder) remoteWidget;
585                }
586            }
587    
588            if (remotableQuickFinder != null) {
589                inputField.getQuickfinder().setBaseLookupUrl(remotableQuickFinder.getBaseLookupUrl());
590                inputField.getQuickfinder().setDataObjectClassName(remotableQuickFinder.getDataObjectClass());
591                inputField.getQuickfinder().setLookupParameters(remotableQuickFinder.getLookupParameters());
592                inputField.getQuickfinder().setFieldConversions(remotableQuickFinder.getFieldConversions());
593            }
594    
595            if (remotableField.getControl() != null) {
596                Control control = null;
597    
598                RemotableControlContract remotableControl = remotableField.getControl();
599                if (remotableControl instanceof RemotableHiddenInput) {
600                    control = getHiddenControl();
601                } else if (remotableControl instanceof RemotableRadioButtonGroup) {
602                    RemotableRadioButtonGroup remotableRadioButtonGroup = (RemotableRadioButtonGroup) remotableControl;
603                    control = getRadioGroupControl();
604                    ((RadioGroupControl) control).setOptions(buildKeyValuePairs(remotableRadioButtonGroup.getKeyLabels()));
605                } else if (remotableControl instanceof RemotableSelect) {
606                    RemotableSelect remotableSelect = (RemotableSelect) remotableControl;
607                    control = getSelectControl();
608    
609                    Map<String, String> keyLabels = new HashMap<String, String>();
610                    if ((remotableSelect.getGroups() != null) && (!remotableSelect.getGroups().isEmpty())) {
611                        for (RemotableSelectGroup remotableSelectGroup : remotableSelect.getGroups()) {
612                            keyLabels.putAll(remotableSelectGroup.getKeyLabels());
613                        }
614                    } else {
615                        keyLabels = remotableSelect.getKeyLabels();
616                    }
617    
618                    ((SelectControl) control).setOptions(buildKeyValuePairs(keyLabels));
619                    if (remotableSelect.getSize() != null) {
620                        ((SelectControl) control).setSize(remotableSelect.getSize());
621                    }
622                    ((SelectControl) control).setMultiple(remotableSelect.isMultiple());
623                } else if (remotableControl instanceof RemotableCheckboxGroup) {
624                    RemotableCheckboxGroup remotableCheckboxGroup = (RemotableCheckboxGroup) remotableControl;
625                    control = getCheckboxGroupControl();
626                    ((CheckboxGroupControl) control).setOptions(buildKeyValuePairs(remotableCheckboxGroup.getKeyLabels()));
627                } else if (remotableControl instanceof RemotableCheckbox) {
628                    control = getCheckboxControl();
629                } else if (remotableControl instanceof RemotableTextarea) {
630                    RemotableTextarea remotableTextarea = (RemotableTextarea) remotableControl;
631                    control = getTextAreaControl();
632    
633                    if (remotableTextExpand != null) {
634                        ((TextAreaControl) control).setTextExpand(true);
635                    }
636                    ((TextAreaControl) control).setRows(remotableTextarea.getRows());
637                    ((TextAreaControl) control).setCols(remotableTextarea.getCols());
638                    ((TextAreaControl) control).setWatermarkText(remotableTextarea.getWatermark());
639    
640                } else if (remotableControl instanceof RemotableTextInput) {
641                    RemotableTextInput remotableTextInput = (RemotableTextInput) remotableControl;
642    
643                    if (remotableDatepicker != null) {
644                        control = getDateControl();
645                    } else {
646                        control = getTextControl();
647                    }
648    
649                    if (remotableTextExpand != null) {
650                        ((TextAreaControl) control).setTextExpand(true);
651                    }
652                    ((TextControl) control).setSize(remotableTextInput.getSize());
653                    ((TextControl) control).setWatermarkText(remotableTextInput.getWatermark());
654                }
655    
656                inputField.setControl(control);
657            }
658    
659            return inputField;
660        }
661    
662        /**
663         * For each remotable field in the given list creates a new {@link org.kuali.rice.krad.uif.field.InputField}
664         * instance and sets the
665         * corresponding properties from the remotable instance
666         *
667         * @param remotableFields - list of remotable fields to translate
668         * @return List<AttributeField> list of attribute fields built from the remotable field properties
669         */
670        public static List<InputField> translateRemotableFields(List<RemotableAttributeField> remotableFields) {
671            List<InputField> inputFields = new ArrayList<InputField>();
672    
673            for (RemotableAttributeField remotableField : remotableFields) {
674                inputFields.add(translateRemotableField(remotableField));
675            }
676    
677            return inputFields;
678        }
679    
680        /**
681         * For each option in the given list, create a new {@link org.kuali.rice.core.api.util.KeyValue} instance
682         *
683         * @param optionsMap - list of options
684         * @return List<KeyValue> list of key values built from the list of options
685         */
686        protected static List<KeyValue> buildKeyValuePairs(Map<String, String> optionsMap) {
687            List<KeyValue> options = new ArrayList<KeyValue>();
688    
689            for (Map.Entry<String, String> optionEntry : optionsMap.entrySet()) {
690                KeyValue keyValue = new ConcreteKeyValue(optionEntry.getKey(), optionEntry.getValue());
691                options.add(keyValue);
692            }
693    
694            return options;
695        }
696    
697        /**
698         * Gets the control
699         *
700         * @param controlType
701         * @return Control the control based on the control type
702         */
703        protected static Control getControl(UifConstants.ControlType controlType) {
704            Control control = null;
705            switch (controlType) {
706                case CHECKBOX:
707                    control = getCheckboxControl();
708                case CHECKBOXGROUP:
709                    control = getCheckboxGroupControl();
710                case FILE:
711                    control = getFileControl();
712                case GROUP:
713                    control = getGroupControl();
714                case HIDDEN:
715                    control = getHiddenControl();
716                case RADIOGROUP:
717                    control = getRadioGroupControl();
718                case SELECT:
719                    control = getSelectControl();
720                case TEXTAREA:
721                    control = getTextAreaControl();
722                case TEXT:
723                    control = getTextControl();
724                case USER:
725                    control = getUserControl();
726            }
727    
728            return control;
729        }
730    
731        /**
732         * Gets the errors field
733         *
734         * @return ValidationMessages errors field
735         */
736        public static ValidationMessages getErrorsField() {
737            return (ValidationMessages) getNewComponentInstance(ERRORS_FIELD);
738        }
739    
740        /**
741         * Gets the action
742         *
743         * @return Action action
744         */
745        public static Action getAction() {
746            return (Action) getNewComponentInstance(ACTION);
747        }
748    
749        /**
750         * Gets the action link
751         *
752         * @return Action action link
753         */
754        public static Action getActionLink() {
755            return (Action) getNewComponentInstance(ACTION_LINK);
756        }
757    
758        /**
759         * Gets the link field
760         *
761         * @return LinkField link field
762         */
763        public static LinkField getLinkField() {
764            return (LinkField) getNewComponentInstance(LINK_FIELD);
765        }
766    
767        /**
768         * Gets the iframe
769         *
770         * @return Iframe iframe
771         */
772        public static Iframe getIframe() {
773            return (Iframe) getNewComponentInstance(IFRAME);
774        }
775    
776        /**
777         * Gets the image field
778         *
779         * @return ImageField image field
780         */
781        public static ImageField getImageField() {
782            return (ImageField) getNewComponentInstance(IMAGE_FIELD);
783        }
784    
785        /**
786         * Gets the image component
787         *
788         * @return ImageField image field
789         */
790        public static Image getImage() {
791            return (Image) getNewComponentInstance(IMAGE);
792        }
793    
794        /**
795         * Gets the space field
796         *
797         * @return SpaceField space field
798         */
799        public static SpaceField getSpaceField() {
800            return (SpaceField) getNewComponentInstance(SPACE_FIELD);
801        }
802    
803        /**
804         * Gets the generic field
805         *
806         * @return GenericField generic field
807         */
808        public static GenericField getGenericField() {
809            return (GenericField) getNewComponentInstance(GENERIC_FIELD);
810        }
811    
812        /**
813         * Gets the label
814         *
815         * @return Label label
816         */
817        public static Label getLabel() {
818            return (Label) getNewComponentInstance(LABEL);
819        }
820    
821        /**
822         * Gets the message
823         *
824         * @return Message message
825         */
826        public static Message getMessage() {
827            return (Message) getNewComponentInstance(MESSAGE);
828        }
829    
830        /**
831         * Gets the message field
832         *
833         * @return MessageField message field
834         */
835        public static MessageField getMessageField() {
836            return (MessageField) getNewComponentInstance(MESSAGE_FIELD);
837        }
838    
839        /**
840         * Gets the field group
841         *
842         * @return FieldGroup field group
843         */
844        public static FieldGroup getFieldGroup() {
845            return (FieldGroup) getNewComponentInstance(FIELD_GROUP);
846        }
847    
848        /**
849         * Gets the horizontal field group
850         *
851         * @return FieldGroup horizontal field group
852         */
853        public static FieldGroup getHorizontalFieldGroup() {
854            return (FieldGroup) getNewComponentInstance(HORIZONTAL_FIELD_GROUP);
855        }
856    
857        /**
858         * Gets the group
859         *
860         * @return Group group
861         */
862        public static Group getGroup() {
863            return (Group) getNewComponentInstance(GROUP);
864        }
865    
866        /**
867         * Gets the page group
868         *
869         * @return PageGroup page group
870         */
871        public static PageGroup getPageGroup() {
872            return (PageGroup) getNewComponentInstance(PAGE_GROUP);
873        }
874    
875        /**
876         * Gets the group grid layout
877         *
878         * @return Group group grid layout
879         */
880        public static Group getGroupGridLayout() {
881            return (Group) getNewComponentInstance(GROUP_GRID_LAYOUT);
882        }
883    
884        /**
885         * Gets the group body only
886         *
887         * @return Group group body only
888         */
889        public static Group getGroupBodyOnly() {
890            return (Group) getNewComponentInstance(GROUP_BODY_ONLY);
891        }
892    
893        /**
894         * Gets the group grid body only
895         *
896         * @return Group group grid body only
897         */
898        public static Group getGroupGridBodyOnly() {
899            return (Group) getNewComponentInstance(GROUP_GRID_BODY_ONLY);
900        }
901    
902        /**
903         * Gets the tab group
904         *
905         * @return TabGroup tab group
906         */
907        public static TabGroup getTabGroup() {
908            return (TabGroup) getNewComponentInstance(TAB_GROUP);
909        }
910    
911        /**
912         * Gets the navigation group
913         *
914         * @return NavigationGroup navigation group
915         */
916        public static NavigationGroup getNavigationGroup() {
917            return (NavigationGroup) getNewComponentInstance(NAVIGATION_GROUP);
918        }
919    
920        /**
921         * Gets the tree group
922         *
923         * @return TreeGroup tree group
924         */
925        public static TreeGroup getTreeGroup() {
926            return (TreeGroup) getNewComponentInstance(TREE_GROUP);
927        }
928    
929        /**
930         * Gets the link group
931         *
932         * @return LinkGroup link group
933         */
934        public static LinkGroup getLinkGroup() {
935            return (LinkGroup) getNewComponentInstance(LINK_GROUP);
936        }
937    
938        /**
939         * Gets the collection group
940         *
941         * @return CollectionGroup collection group
942         */
943        public static CollectionGroup getCollectionGroup() {
944            return (CollectionGroup) getNewComponentInstance(COLLECTION_GROUP);
945        }
946    
947        /**
948         * Gets the collection group table layout
949         *
950         * @return CollectionGroup collection group table layout
951         */
952        public static CollectionGroup getCollectionGroupTableLayout() {
953            return (CollectionGroup) getNewComponentInstance(COLLECTION_GROUP_TABLE_LAYOUT);
954        }
955    
956        /**
957         * Gets the list group
958         *
959         * @return CollectionGroup list group
960         */
961        public static CollectionGroup getListGroup() {
962            return (CollectionGroup) getNewComponentInstance(LIST_GROUP);
963        }
964    
965        /**
966         * Gets the header
967         *
968         * @return Header header
969         */
970        public static Header getHeader() {
971            return (Header) getNewComponentInstance(HEADER);
972        }
973    
974        /**
975         * Gets the footer
976         *
977         * @return Group footer
978         */
979        public static Group getFooter() {
980            return (Group) getNewComponentInstance(FOOTER);
981        }
982    
983        /**
984         * Gets the footer save/close/cancel
985         *
986         * @return Group footer save/close/cancel
987         */
988        public static Group getFooterSaveCloseCancel() {
989            return (Group) getNewComponentInstance(FOOTER_SAVECLOSECANCEL);
990        }
991    
992        /**
993         * Gets the default action component configured for help
994         *
995         * @return Action for help display
996         */
997        public static Action getHelpAction() {
998            return (Action) getNewComponentInstance(HELP_ACTION);
999        }
1000    
1001        /**
1002         * Gets the default constraint message configuration
1003         *
1004         * @return Message component for constraint messages
1005         */
1006        public static Message getConstraintMessage() {
1007            return (Message) getNewComponentInstance(CONSTRAINT_MESSAGE);
1008        }
1009    
1010        /**
1011         * Gets the default instructional message configuration
1012         *
1013         * @return Message component for instructional messages
1014         */
1015        public static Message getInstructionalMessage() {
1016            return (Message) getNewComponentInstance(INSTRUCTIONAL_MESSAGE);
1017        }
1018    
1019        /**
1020         * Gets the default image caption header configuration
1021         *
1022         * @return Header component for image caption headers
1023         */
1024        public static Header getImageCaptionHeader() {
1025            return (Header) getNewComponentInstance(IMAGE_CAPTION_HEADER);
1026        }
1027    
1028        /**
1029         * Gets the default image cutline message configuration
1030         *
1031         * @return Message component for image cutlines messages
1032         */
1033        public static Message getImageCutlineMessage() {
1034            return (Message) getNewComponentInstance(IMAGE_CUTLINE_MESSAGE);
1035        }
1036    }