001    /**
002     * Copyright 2005-2014 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.field;
017    
018    import org.apache.commons.lang.StringUtils;
019    import org.kuali.rice.core.api.uif.DataType;
020    import org.kuali.rice.core.api.util.ConcreteKeyValue;
021    import org.kuali.rice.core.api.util.KeyValue;
022    import org.kuali.rice.core.api.util.type.TypeUtils;
023    import org.kuali.rice.krad.datadictionary.AttributeDefinition;
024    import org.kuali.rice.krad.datadictionary.validation.capability.CaseConstrainable;
025    import org.kuali.rice.krad.datadictionary.validation.capability.Formatable;
026    import org.kuali.rice.krad.datadictionary.validation.capability.HierarchicallyConstrainable;
027    import org.kuali.rice.krad.datadictionary.validation.capability.LengthConstrainable;
028    import org.kuali.rice.krad.datadictionary.validation.capability.MustOccurConstrainable;
029    import org.kuali.rice.krad.datadictionary.validation.capability.PrerequisiteConstrainable;
030    import org.kuali.rice.krad.datadictionary.validation.capability.RangeConstrainable;
031    import org.kuali.rice.krad.datadictionary.validation.capability.SimpleConstrainable;
032    import org.kuali.rice.krad.datadictionary.validation.capability.ValidCharactersConstrainable;
033    import org.kuali.rice.krad.datadictionary.validation.constraint.CaseConstraint;
034    import org.kuali.rice.krad.datadictionary.validation.constraint.MustOccurConstraint;
035    import org.kuali.rice.krad.datadictionary.validation.constraint.PrerequisiteConstraint;
036    import org.kuali.rice.krad.datadictionary.validation.constraint.SimpleConstraint;
037    import org.kuali.rice.krad.datadictionary.validation.constraint.ValidCharactersConstraint;
038    import org.kuali.rice.krad.keyvalues.KeyValuesFinder;
039    import org.kuali.rice.krad.uif.UifConstants;
040    import org.kuali.rice.krad.uif.control.TextControl;
041    import org.kuali.rice.krad.uif.control.UifKeyValuesFinder;
042    import org.kuali.rice.krad.uif.view.FormView;
043    import org.kuali.rice.krad.uif.view.View;
044    import org.kuali.rice.krad.uif.control.Control;
045    import org.kuali.rice.krad.uif.control.MultiValueControlBase;
046    import org.kuali.rice.krad.uif.component.Component;
047    import org.kuali.rice.krad.uif.util.ClientValidationUtils;
048    import org.kuali.rice.krad.uif.util.ComponentUtils;
049    import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
050    import org.kuali.rice.krad.uif.view.ViewModel;
051    import org.kuali.rice.krad.uif.widget.DirectInquiry;
052    import org.kuali.rice.krad.uif.widget.QuickFinder;
053    import org.kuali.rice.krad.uif.widget.Suggest;
054    import org.kuali.rice.krad.util.ObjectUtils;
055    
056    import java.util.ArrayList;
057    import java.util.List;
058    
059    /**
060     * Field that encapsulates data input/output captured by an attribute within the
061     * application
062     *
063     * <p>
064     * R
065     * The <code>InputField</code> provides the majority of the data input/output
066     * for the screen. Through these fields the model can be displayed and updated.
067     * For data input, the field contains a {@link Control} instance will
068     * render an HTML control element(s). The input field also contains a
069     * {@link LabelField}, summary, and widgets such as a quickfinder (for
070     * looking up values) and inquiry (for getting more information on the value).
071     * <code>InputField</code> instances can have associated messages (errors)
072     * due to invalid input or business rule failures. Security can also be
073     * configured to restrict who may view the fields value.
074     * </p>
075     *
076     * @author Kuali Rice Team (rice.collab@kuali.org)
077     */
078    public class InputField extends DataField implements SimpleConstrainable, CaseConstrainable, PrerequisiteConstrainable,
079            MustOccurConstrainable, LengthConstrainable, RangeConstrainable, ValidCharactersConstrainable {
080        private static final long serialVersionUID = -3703656713706343840L;
081    
082        // constraint variables
083        private String customValidatorClass;
084        private ValidCharactersConstraint validCharactersConstraint;
085        private CaseConstraint caseConstraint;
086        private List<PrerequisiteConstraint> dependencyConstraints;
087        private List<MustOccurConstraint> mustOccurConstraints;
088        private SimpleConstraint simpleConstraint;
089        private DataType dataType;
090    
091        // display props
092        private Control control;
093        private KeyValuesFinder optionsFinder;
094        private boolean performUppercase;
095    
096        private ErrorsField errorsField;
097    
098        // messages
099        private String constraintText;
100        private String instructionalText;
101    
102        private MessageField instructionalMessageField;
103        private MessageField constraintMessageField;
104    
105        private AttributeQuery fieldAttributeQuery;
106    
107        // widgets
108        private QuickFinder fieldLookup;
109        private DirectInquiry fieldDirectInquiry;
110        private Suggest fieldSuggest;
111        private Boolean directInquiryRender = true;
112    
113        public InputField() {
114            super();
115    
116            simpleConstraint = new SimpleConstraint();
117        }
118    
119        /**
120         * The following actions are performed:
121         *
122         * <ul>
123         * <li>Set the ids for the various attribute components</li>
124         * <li>Sets up the client side validation for constraints on this field. In
125         * addition, it sets up the messages applied to this field</li>
126         * </ul>
127         *
128         * @see org.kuali.rice.krad.uif.component.ComponentBase#performFinalize(org.kuali.rice.krad.uif.view.View,
129         *      java.lang.Object, org.kuali.rice.krad.uif.component.Component)
130         */
131        @Override
132        public void performFinalize(View view, Object model, Component parent) {
133            super.performFinalize(view, model, parent);
134    
135            setupIds();
136    
137            // invoke options finder if options not configured on the control
138            List<KeyValue> fieldOptions = new ArrayList<KeyValue>();
139    
140            // use options directly configured on the control first
141            if ((control != null) && control instanceof MultiValueControlBase) {
142                MultiValueControlBase multiValueControl = (MultiValueControlBase) control;
143                if ((multiValueControl.getOptions() != null) && !multiValueControl.getOptions().isEmpty()) {
144                    fieldOptions = multiValueControl.getOptions();
145                }
146            }
147    
148            // if options not configured on the control, invoke configured options finder
149            if (fieldOptions.isEmpty() && (optionsFinder != null)) {
150                if (optionsFinder instanceof UifKeyValuesFinder) {
151                    fieldOptions = ((UifKeyValuesFinder) optionsFinder).getKeyValues((ViewModel) model);
152    
153                    // check if blank option should be added
154                    if (((UifKeyValuesFinder) optionsFinder).isAddBlankOption()) {
155                        fieldOptions.add(0, new ConcreteKeyValue("", ""));
156                    }
157                } else {
158                    fieldOptions = optionsFinder.getKeyValues();
159                }
160    
161                if ((control != null) && control instanceof MultiValueControlBase) {
162                    ((MultiValueControlBase) control).setOptions(fieldOptions);
163                }
164            }
165    
166            // if read only do key/value translation if necessary (if alternative and additional properties not set)
167            if (isReadOnly()
168                    && !fieldOptions.isEmpty()
169                    && StringUtils.isBlank(getAlternateDisplayValue())
170                    && StringUtils.isBlank(getAdditionalDisplayValue())
171                    && StringUtils.isBlank(getAlternateDisplayPropertyName())
172                    && StringUtils.isBlank(getAdditionalDisplayPropertyName())) {
173    
174                Object fieldValue = ObjectPropertyUtils.getPropertyValue(model, getBindingInfo().getBindingPath());
175    
176                // TODO: can we translate Collections? (possibly combining output with delimiter
177                if ((fieldValue != null) && (TypeUtils.isSimpleType(fieldValue.getClass()))) {
178                    for (KeyValue keyValue : fieldOptions) {
179                        if (StringUtils.equals(fieldValue.toString(), keyValue.getKey())) {
180                            setAlternateDisplayValue(keyValue.getValue());
181                            break;
182                        }
183                    }
184                }
185            }
186    
187            // if read only or the control is null no input can be given so no need to setup validation
188            if (isReadOnly() || getControl() == null) {
189                return;
190            }
191    
192            // Sets message
193            if (StringUtils.isNotBlank(instructionalText)) {
194                instructionalMessageField.setMessageText(instructionalText);
195            }
196    
197            // Sets constraints
198            if (StringUtils.isNotBlank(constraintText)) {
199                constraintMessageField.setMessageText(constraintText);
200            }
201    
202            // adjust paths on PrerequisiteConstraint property names
203            adjustPrerequisiteConstraintBinding(dependencyConstraints);
204    
205            // adjust paths on MustOccurConstraints property names
206            adjustMustOccurConstraintBinding(mustOccurConstraints);
207    
208            // adjust paths on CaseConstraint property names
209            if (caseConstraint != null) {
210                String propertyName = getBindingInfo().getPropertyAdjustedBindingPath(caseConstraint.getPropertyName());
211                caseConstraint.setPropertyName(propertyName);
212            }
213    
214            setupFieldQuery();
215    
216            ClientValidationUtils.processAndApplyConstraints(this, view);
217        }
218    
219        /**
220         * Adjust paths on the must occur constrain bindings
221         *
222         * @param mustOccurConstraints
223         */
224        protected void adjustMustOccurConstraintBinding(List<MustOccurConstraint> mustOccurConstraints) {
225            if (mustOccurConstraints != null) {
226                for (MustOccurConstraint mustOccurConstraint : mustOccurConstraints) {
227                    adjustPrerequisiteConstraintBinding(mustOccurConstraint.getPrerequisiteConstraints());
228                    adjustMustOccurConstraintBinding(mustOccurConstraint.getMustOccurConstraints());
229                }
230            }
231        }
232    
233        /**
234         * Adjust paths on the prerequisite constraint bindings
235         * @param prerequisiteConstraints
236         */
237        protected void adjustPrerequisiteConstraintBinding(List<PrerequisiteConstraint> prerequisiteConstraints) {
238            if (prerequisiteConstraints != null) {
239                for (PrerequisiteConstraint prerequisiteConstraint : prerequisiteConstraints) {
240                    String propertyName = getBindingInfo().getPropertyAdjustedBindingPath(
241                            prerequisiteConstraint.getPropertyName());
242                    prerequisiteConstraint.setPropertyName(propertyName);
243                }
244            }
245        }
246    
247        /**
248         * Performs setup of the field attribute query and informational display properties. Paths
249         * are adjusted to match the binding for the this field, and the necessary onblur script for
250         * triggering the query client side is constructed
251         */
252        protected void setupFieldQuery() {
253            if (getFieldAttributeQuery() != null) {
254                // adjust paths on query mappings
255                getFieldAttributeQuery().updateQueryFieldMapping(getBindingInfo());
256                getFieldAttributeQuery().updateReturnFieldMapping(getBindingInfo());
257                getFieldAttributeQuery().updateQueryMethodArgumentFieldList(getBindingInfo());
258    
259                // build onblur script for field query
260                String script = "executeFieldQuery('" + getControl().getId() + "',";
261                script += "'" + getId() + "'," + getFieldAttributeQuery().getQueryFieldMappingJsString() + ",";
262                script += getFieldAttributeQuery().getQueryMethodArgumentFieldsJsString() + ",";
263                script += getFieldAttributeQuery().getReturnFieldMappingJsString() + ");";
264    
265                if (StringUtils.isNotBlank(getControl().getOnBlurScript())) {
266                    script = getControl().getOnBlurScript() + script;
267                }
268                getControl().setOnBlurScript(script);
269            }
270        }
271    
272        /**
273         * Sets the ids on all components the input field uses so they will all
274         * contain this input field's id in their ids. This is useful for jQuery
275         * manipulation.
276         */
277        protected void setupIds() {
278            // update ids so they all match the attribute
279            if (getControl() != null) {
280                getControl().setId(getId());
281            }
282    
283            setNestedComponentIdAndSuffix(getErrorsField(), UifConstants.IdSuffixes.ERRORS);
284            setNestedComponentIdAndSuffix(getLabelField(), UifConstants.IdSuffixes.LABEL);
285            setNestedComponentIdAndSuffix(getInstructionalMessageField(), UifConstants.IdSuffixes.INSTRUCTIONAL);
286            setNestedComponentIdAndSuffix(getConstraintMessageField(), UifConstants.IdSuffixes.CONSTRAINT);
287            setNestedComponentIdAndSuffix(getFieldLookup(), UifConstants.IdSuffixes.QUICK_FINDER);
288            setNestedComponentIdAndSuffix(getFieldDirectInquiry(), UifConstants.IdSuffixes.DIRECT_INQUIRY);
289            setNestedComponentIdAndSuffix(getFieldSuggest(), UifConstants.IdSuffixes.SUGGEST);
290    
291            setId(getId() + UifConstants.IdSuffixes.ATTRIBUTE);
292        }
293    
294        /**
295         * Helper method for suffixing the ids of the fields nested components
296         *
297         * @param component - component to adjust id for
298         * @param suffix - suffix to append to id
299         */
300        private void setNestedComponentIdAndSuffix(Component component, String suffix) {
301            if (component != null) {
302                String fieldId = getId();
303                fieldId += suffix;
304    
305                component.setId(fieldId);
306            }
307        }
308    
309        /**
310         * Defaults the properties of the <code>InputField</code> to the
311         * corresponding properties of its <code>AttributeDefinition</code>
312         * retrieved from the dictionary (if such an entry exists). If the field
313         * already contains a value for a property, the definitions value is not
314         * used.
315         *
316         * @param view - view instance the field belongs to
317         * @param attributeDefinition - AttributeDefinition instance the property values should be
318         * copied from
319         */
320        public void copyFromAttributeDefinition(View view, AttributeDefinition attributeDefinition) {
321            super.copyFromAttributeDefinition(view, attributeDefinition);
322    
323            // max length
324            if (getMaxLength() == null) {
325                setMaxLength(attributeDefinition.getMaxLength());
326            }
327    
328            // min length
329            if (getMinLength() == null) {
330                setMinLength(attributeDefinition.getMinLength());
331            }
332    
333            // valid characters
334            if (getValidCharactersConstraint() == null) {
335                setValidCharactersConstraint(attributeDefinition.getValidCharactersConstraint());
336            }
337    
338            if (getCaseConstraint() == null) {
339                setCaseConstraint(attributeDefinition.getCaseConstraint());
340            }
341    
342            if (getDependencyConstraints() == null) {
343                setDependencyConstraints(attributeDefinition.getPrerequisiteConstraints());
344            }
345    
346            if (getMustOccurConstraints() == null) {
347                setMustOccurConstraints(attributeDefinition.getMustOccurConstraints());
348            }
349    
350            // required
351            if (getRequired() == null) {
352                setRequired(attributeDefinition.isRequired());
353    
354                //if still null, default to false
355                if (getRequired() == null) {
356                    setRequired(false);
357                }
358            }
359            
360            if (this.dataType == null) {
361                setDataType(attributeDefinition.getDataType());
362                //Assume date if dataType is still null and using a DatePicker
363                if(this.dataType == null && control instanceof TextControl && ((TextControl) control).getDatePicker() != null) {
364                    setDataType(DataType.DATE);
365                }
366            }
367    
368            // control
369            if ((getControl() == null) && (attributeDefinition.getControlField() != null)) {
370                Control control = attributeDefinition.getControlField();
371                view.assignComponentIds(control);
372    
373                setControl(ComponentUtils.copy(control));
374            }
375    
376            // constraint
377            if (StringUtils.isEmpty(getConstraintText())) {
378                setConstraintText(attributeDefinition.getConstraintText());
379                getConstraintMessageField().setMessageText(attributeDefinition.getConstraintText());
380            }
381    
382            // options
383            if (getOptionsFinder() == null) {
384                setOptionsFinder(attributeDefinition.getOptionsFinder());
385            }
386        }
387    
388        /**
389         * @see org.kuali.rice.krad.uif.component.ComponentBase#getComponentsForLifecycle()
390         */
391        @Override
392        public List<Component> getComponentsForLifecycle() {
393            List<Component> components = super.getComponentsForLifecycle();
394    
395            components.add(control);
396            components.add(errorsField);
397            components.add(fieldLookup);
398            components.add(fieldDirectInquiry);
399            components.add(fieldSuggest);
400    
401            return components;
402        }
403    
404        /**
405         * @see DataField#isInputAllowed()
406         */
407        @Override
408        public boolean isInputAllowed() {
409            return true;
410        }
411    
412        /**
413         * <code>Control</code> instance that should be used to input data for the
414         * field
415         *
416         * <p>
417         * When the field is editable, the control will be rendered so the user can
418         * input a value(s). Controls typically are part of a Form and render
419         * standard HTML control elements such as text input, select, and checkbox
420         * </p>
421         *
422         * @return Control instance
423         */
424        public Control getControl() {
425            return this.control;
426        }
427    
428        /**
429         * Setter for the field's control
430         *
431         * @param control
432         */
433        public void setControl(Control control) {
434            this.control = control;
435        }
436    
437        /**
438         * Field that contains the messages (errors) for the input field. The
439         * <code>ErrorsField</code> holds configuration on associated messages along
440         * with information on rendering the messages in the user interface
441         *
442         * @return ErrorsField instance
443         */
444        public ErrorsField getErrorsField() {
445            return this.errorsField;
446        }
447    
448        /**
449         * Setter for the input field's errors field
450         *
451         * @param errorsField
452         */
453        public void setErrorsField(ErrorsField errorsField) {
454            this.errorsField = errorsField;
455        }
456    
457        /**
458         * Instance of <code>KeyValuesFinder</code> that should be invoked to
459         * provide a List of values the field can have. Generally used to provide
460         * the options for a multi-value control or to validate the submitted field
461         * value
462         *
463         * @return KeyValuesFinder instance
464         */
465        public KeyValuesFinder getOptionsFinder() {
466            return this.optionsFinder;
467        }
468    
469        /**
470         * Setter for the field's KeyValuesFinder instance
471         *
472         * @param optionsFinder
473         */
474        public void setOptionsFinder(KeyValuesFinder optionsFinder) {
475            this.optionsFinder = optionsFinder;
476        }
477    
478        /**
479         * Setter that takes in the class name for the options finder and creates a
480         * new instance to use as the finder for the input field
481         *
482         * @param optionsFinderClass - the options finder class to set
483         */
484        public void setOptionsFinderClass(Class<? extends KeyValuesFinder> optionsFinderClass) {
485            this.optionsFinder = ObjectUtils.newInstance(optionsFinderClass);
486        }
487    
488        /**
489         * @see org.kuali.rice.krad.uif.component.ComponentBase#getSupportsOnLoad()
490         */
491        @Override
492        public boolean getSupportsOnLoad() {
493            return true;
494        }
495    
496        /**
497         * Lookup finder widget for the field
498         *
499         * <p>
500         * The quickfinder widget places a small icon next to the field that allows
501         * the user to bring up a search screen for finding valid field values. The
502         * <code>Widget</code> instance can be configured to point to a certain
503         * <code>LookupView</code>, or the framework will attempt to associate the
504         * field with a lookup based on its metadata (in particular its
505         * relationships in the model)
506         * </p>
507         *
508         * @return QuickFinder lookup widget
509         */
510        public QuickFinder getFieldLookup() {
511            return this.fieldLookup;
512        }
513    
514        /**
515         * Setter for the lookup widget
516         *
517         * @param fieldLookup - the field lookup widget to set
518         */
519        public void setFieldLookup(QuickFinder fieldLookup) {
520            this.fieldLookup = fieldLookup;
521        }
522    
523        /**
524         * Suggest box widget for the input field
525         *
526         * <p>
527         * If enabled (by render flag), as the user inputs data into the
528         * fields control a dynamic query is performed to provide the user
529         * suggestions on values which they can then select
530         * </p>
531         *
532         * <p>
533         * Note the Suggest widget is only valid when using a standard TextControl
534         * </p>
535         *
536         * @return Suggest instance
537         */
538        public Suggest getFieldSuggest() {
539            return fieldSuggest;
540        }
541    
542        /**
543         * Setter for the fields suggest widget
544         *
545         * @param fieldSuggest - the field suggest widget to  set
546         */
547        public void setFieldSuggest(Suggest fieldSuggest) {
548            this.fieldSuggest = fieldSuggest;
549        }
550    
551        /**
552         * Instructional text that display an explanation of the field usage
553         *
554         * <p>
555         * Text explaining how to use the field, including things like what values should be selected
556         * in certain cases and so on (instructions)
557         * </p>
558         *
559         * @return String instructional message
560         */
561        public String getInstructionalText() {
562            return this.instructionalText;
563        }
564    
565        /**
566         * Setter for the instructional message
567         *
568         * @param instructionalText - the instructional text to set
569         */
570        public void setInstructionalText(String instructionalText) {
571            this.instructionalText = instructionalText;
572        }
573    
574        /**
575         * Message field that displays instructional text
576         *
577         * <p>
578         * This message field can be configured to for adjusting how the instructional text will display. Generally
579         * the styleClasses property will be of most interest
580         * </p>
581         *
582         * @return MessageField instructional message field
583         */
584        public MessageField getInstructionalMessageField() {
585            return this.instructionalMessageField;
586        }
587    
588        /**
589         * Setter for the instructional text message field
590         *
591         * <p>
592         * Note this is the setter for the field that will render the instructional text. The actual text can be
593         * set on the field but can also be set using {@link #setInstructionalText(String)}
594         * </p>
595         *
596         * @param instructionalMessageField - the instructional message to set
597         */
598        public void setInstructionalMessageField(MessageField instructionalMessageField) {
599            this.instructionalMessageField = instructionalMessageField;
600        }
601    
602        /**
603         * Text that display a restriction on the value a field can hold
604         *
605         * <p>
606         * For example when the value must be a valid format (phone number, email), certain length, min/max value and
607         * so on this text can be used to indicate the constraint to the user. Generally displays with the control so
608         * it is visible when the user tabs to the field
609         * </p>
610         *
611         * @return String text to display for the constraint message
612         */
613        public String getConstraintText() {
614            return this.constraintText;
615        }
616    
617        /**
618         * Setter for the constraint message text
619         *
620         * @param constraintText - the constraint text to set
621         */
622        public void setConstraintText(String constraintText) {
623            this.constraintText = constraintText;
624        }
625    
626        /**
627         * Message field that displays constraint text
628         *
629         * <p>
630         * This message field can be configured to for adjusting how the constrain text will display. Generally
631         * the styleClasses property will be of most interest
632         * </p>
633         *
634         * @return MessageField constraint message field
635         */
636        public MessageField getConstraintMessageField() {
637            return this.constraintMessageField;
638        }
639    
640        /**
641         * Setter for the constraint text message field
642         *
643         * <p>
644         * Note this is the setter for the field that will render the constraint text. The actual text can be
645         * set on the field but can also be set using {@link #setConstraintText(String)}
646         * </p>
647         *
648         * @param constraintMessageField - the constrain message field to set
649         */
650        public void setConstraintMessageField(MessageField constraintMessageField) {
651            this.constraintMessageField = constraintMessageField;
652        }
653    
654        /**
655         * The <code>ValideCharacterConstraint</code> that applies to this <code>InputField</code>
656         *
657         * @return the valid characters constraint for this input field
658         */
659        public ValidCharactersConstraint getValidCharactersConstraint() {
660            return this.validCharactersConstraint;
661        }
662    
663        /**
664         * Setter for <code>validCharacterConstraint</code>
665         *
666         * @param validCharactersConstraint - the <code>ValidCharactersConstraint</code> to set
667         */
668        public void setValidCharactersConstraint(ValidCharactersConstraint validCharactersConstraint) {
669            this.validCharactersConstraint = validCharactersConstraint;
670        }
671    
672        /**
673         * The <code>CaseConstraint</code> that applies to this <code>InputField</code>
674         *
675         * @return the case constraint for this input field
676         */
677        public CaseConstraint getCaseConstraint() {
678            return this.caseConstraint;
679        }
680    
681        /**
682         * Setter for <code>caseConstraint</code>
683         *
684         * @param caseConstraint - the <code>CaseConstraint</code> to set
685         */
686        public void setCaseConstraint(CaseConstraint caseConstraint) {
687            this.caseConstraint = caseConstraint;
688        }
689    
690        /**
691         * List of <code>PrerequisiteConstraint</code> that apply to this <code>InputField</code>
692         *
693         * @return the dependency constraints for this input field
694         */
695        public List<PrerequisiteConstraint> getDependencyConstraints() {
696            return this.dependencyConstraints;
697        }
698    
699        /**
700         * Setter for <code>dependencyConstraints</code>
701         *
702         * @param dependencyConstraints - list of <code>PrerequisiteConstraint</code> to set
703         */
704        public void setDependencyConstraints(List<PrerequisiteConstraint> dependencyConstraints) {
705            this.dependencyConstraints = dependencyConstraints;
706        }
707    
708        /**
709         * List of <code>MustOccurConstraint</code> that apply to this <code>InputField</code>
710         *
711         * @return the must occur constraints for this input field
712         */
713        public List<MustOccurConstraint> getMustOccurConstraints() {
714            return this.mustOccurConstraints;
715        }
716    
717        /**
718         * Setter for <code>mustOccurConstraints</code>
719         *
720         * @param mustOccurConstraints - list of <code>MustOccurConstraint</code> to set
721         */
722        public void setMustOccurConstraints(List<MustOccurConstraint> mustOccurConstraints) {
723            this.mustOccurConstraints = mustOccurConstraints;
724        }
725    
726        /**
727         * Simple constraints for the input field
728         *
729         * <p>
730         * A simple constraint which store the values for constraints such as required,
731         * min/max length, and min/max value.
732         * </p>
733         *
734         * @return the simple constraint of the input field
735         */
736        public SimpleConstraint getSimpleConstraint() {
737            return this.simpleConstraint;
738        }
739    
740        /**
741         * Setter for simple constraint
742         *
743         * <p>
744         * When a simple constraint is set on this object ALL simple validation
745         * constraints set directly will be overridden - recommended to use this or
746         * the other gets/sets for defining simple constraints, not both.
747         * </p>
748         *
749         * @param simpleConstraint - the simple constraint to set
750         */
751        public void setSimpleConstraint(SimpleConstraint simpleConstraint) {
752            this.simpleConstraint = simpleConstraint;
753        }
754    
755        /**
756         * Maximum number of characters the input field value is allowed to have
757         *
758         * <p>
759         * The maximum length determines the maximum allowable length of the value
760         * for data entry editing purposes.  The maximum length is inclusive and can
761         * be smaller or longer than the actual control size.  The constraint
762         * is enforced on all data types (e.g. a numeric data type needs to meet the
763         * maximum length constraint in which digits and symbols are counted).
764         * </p>
765         *
766         * @return the maximum length of the input field
767         */
768        public Integer getMaxLength() {
769            return simpleConstraint.getMaxLength();
770        }
771    
772        /**
773         * Setter for input field max length
774         *
775         * @param maxLength - the maximum length to set
776         */
777        public void setMaxLength(Integer maxLength) {
778            simpleConstraint.setMaxLength(maxLength);
779        }
780    
781        /**
782         * Minimum number of characters the input field value needs to be
783         *
784         * <p>
785         * The minimum length determines the minimum required length of the value for
786         * data entry editing purposes.  The minimum length is inclusive. The constraint
787         * is enforced on all data types (e.g. a numeric data type needs to meet the
788         * minimum length requirement in which digits and symbols are counted).
789         * </p>
790         *
791         * @return the minimum length of the input field
792         */
793        public Integer getMinLength() {
794            return simpleConstraint.getMinLength();
795        }
796    
797        /**
798         * Setter for input field minimum length
799         *
800         * @param minLength - the minLength to set
801         */
802        public void setMinLength(Integer minLength) {
803            simpleConstraint.setMinLength(minLength);
804        }
805        
806        public Boolean getDirectInquiryRender() {
807            return this.directInquiryRender;
808        }
809        
810        public void setDirectInquiryRender(Boolean directInquiryRender) {
811            this.directInquiryRender = directInquiryRender;
812        }
813    
814        /**
815         * @see org.kuali.rice.krad.uif.component.ComponentBase#getRequired()
816         */
817        @Override
818        public Boolean getRequired() {
819            return this.simpleConstraint.getRequired();
820        }
821    
822        /**
823         * @see org.kuali.rice.krad.uif.component.ComponentBase#setRequired(java.lang.Boolean)
824         */
825        @Override
826        public void setRequired(Boolean required) {
827            this.simpleConstraint.setRequired(required);
828        }
829    
830        /**
831         * The exclusive minimum value for numeric or date field.
832         *
833         * <p>
834         * The exclusiveMin element determines the minimum allowable value for data
835         * entry editing purposes. This constrain is supported for numeric and
836         * date fields and to be used in conjunction with the appropriate
837         * {@link ValidCharactersConstraint}.
838         *
839         * For numeric constraint the value can be an integer or decimal such as -.001 or 99.
840         * </p>
841         *
842         * @return the exclusive minimum numeric value of the input field
843         */
844        public String getExclusiveMin() {
845            return simpleConstraint.getExclusiveMin();
846        }
847    
848        /**
849         * Setter for the field's exclusive minimum value
850         *
851         * @param exclusiveMin - the minimum value to set
852         */
853        public void setExclusiveMin(String exclusiveMin) {
854            simpleConstraint.setExclusiveMin(exclusiveMin);
855        }
856    
857        /**
858         * The inclusive maximum value for numeric or date field.
859         *
860         * <p>
861         * The inclusiveMax element determines the maximum allowable value for data
862         * entry editing purposes. This constrain is supported for numeric and
863         * date fields and to be used in conjunction with the appropriate
864         * {@link ValidCharactersConstraint}.
865         *
866         * For numeric constraint the value can be an integer or decimal such as -.001 or 99.
867         * </p>
868         *
869         * @return the inclusive maximum numeric value of the input field
870         */
871        public String getInclusiveMax() {
872            return simpleConstraint.getInclusiveMax();
873        }
874    
875        /**
876         * Setter for the field's inclusive maximum value
877         *
878         * @param inclusiveMax - the maximum value to set
879         */
880        public void setInclusiveMax(String inclusiveMax) {
881            simpleConstraint.setInclusiveMax(inclusiveMax);
882        }
883    
884        /**
885         * <code>DirectInquiry</code> widget for the field
886         *
887         * <p>
888         * The direct inquiry widget will render a button for the field value when
889         * that field is editable. It points to the associated inquiry view for the
890         * field. The inquiry can be configured to point to a certain
891         * <code>InquiryView</code>, or the framework will attempt to associate the
892         * field with a inquiry based on its metadata (in particular its
893         * relationships in the model)
894         * </p>
895         *
896         * @return the <code>DirectInquiry</code> field DirectInquiry
897         */
898        public DirectInquiry getFieldDirectInquiry() {
899            return fieldDirectInquiry;
900        }
901    
902        /**
903         * Setter for the field's direct inquiry widget
904         *
905         * @param fieldDirectInquiry - the <code>DirectInquiry</code> to set
906         */
907        public void setFieldDirectInquiry(DirectInquiry fieldDirectInquiry) {
908            this.fieldDirectInquiry = fieldDirectInquiry;
909        }
910    
911        /**
912         * Attribute query instance configured for this field to dynamically pull information back for
913         * updates other fields or providing messages
914         *
915         * <p>
916         * If field attribute query is not null, associated event script will be generated to trigger the
917         * query from the UI. This will invoke the <code>AttributeQueryService</code> to
918         * execute the query and return an instance of <code>AttributeQueryResult</code> that is then
919         * read by the script to update the UI. Typically used to update informational property values or
920         * other field values
921         * </p>
922         *
923         * @return AttributeQuery instance
924         */
925        public AttributeQuery getFieldAttributeQuery() {
926            return fieldAttributeQuery;
927        }
928    
929        /**
930         * Setter for this field's attribute query
931         *
932         * @param fieldAttributeQuery
933         */
934        public void setFieldAttributeQuery(AttributeQuery fieldAttributeQuery) {
935            this.fieldAttributeQuery = fieldAttributeQuery;
936        }
937    
938        /**
939         * Perform uppercase flag for this field to force input to uppercase.
940         *
941         * <p>
942         * It this flag is set to true the 'text-transform' style on the field will be set to 'uppercase'
943         * which will automatically change any text input into the field to uppercase.
944         * </p>
945         *
946         * @return performUppercase flag
947         */
948        public boolean isPerformUppercase() {
949            return performUppercase;
950        }
951    
952        /**
953         * Setter for this field's performUppercase flag
954         *
955         * @param performUppercase - boolean flag
956         */
957        public void setPerformUppercase(boolean performUppercase) {
958            this.performUppercase = performUppercase;
959        }
960    
961        /**
962         * Returns the full binding path (the path used in the name attribute of the input).
963         * This differs from propertyName in that it uses BindingInfo to determine the path.
964         * @return full binding path name
965         */
966        @Override
967        public String getName() {
968            return this.getBindingInfo().getBindingPath();
969        }
970    
971        public List<PrerequisiteConstraint> getPrerequisiteConstraints() {
972            return dependencyConstraints;
973        }
974    
975        /**
976         * This does not have to be set, represents the DataType constraint of this field.
977         * This is only checked during server side validation.
978         * @param dataType the dataType to set
979         */
980        public void setDataType(DataType dataType) {
981            this.simpleConstraint.setDataType(dataType);
982        }
983    
984        public void setDataType(String dataType) {
985            this.simpleConstraint.setDataType(DataType.valueOf(dataType));
986        }
987    
988        /**
989         * Gets the DataType of this InputField, note that DataType set to be date
990         * when this field is using a date picker with a TextControl and hasnt otherwise been
991         * explicitly set.
992         * @return
993         */
994        public DataType getDataType() {
995            return this.simpleConstraint.getDataType();
996        }
997    }