001/**
002 * Copyright 2005-2016 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 */
016package org.kuali.rice.krad.uif.field;
017
018import org.apache.commons.lang.StringUtils;
019import org.kuali.rice.core.api.uif.DataType;
020import org.kuali.rice.core.api.util.ConcreteKeyValue;
021import org.kuali.rice.core.api.util.KeyValue;
022import org.kuali.rice.core.api.util.type.TypeUtils;
023import org.kuali.rice.krad.datadictionary.AttributeDefinition;
024import org.kuali.rice.krad.datadictionary.validation.capability.CaseConstrainable;
025import org.kuali.rice.krad.datadictionary.validation.capability.Formatable;
026import org.kuali.rice.krad.datadictionary.validation.capability.HierarchicallyConstrainable;
027import org.kuali.rice.krad.datadictionary.validation.capability.LengthConstrainable;
028import org.kuali.rice.krad.datadictionary.validation.capability.MustOccurConstrainable;
029import org.kuali.rice.krad.datadictionary.validation.capability.PrerequisiteConstrainable;
030import org.kuali.rice.krad.datadictionary.validation.capability.RangeConstrainable;
031import org.kuali.rice.krad.datadictionary.validation.capability.SimpleConstrainable;
032import org.kuali.rice.krad.datadictionary.validation.capability.ValidCharactersConstrainable;
033import org.kuali.rice.krad.datadictionary.validation.constraint.CaseConstraint;
034import org.kuali.rice.krad.datadictionary.validation.constraint.MustOccurConstraint;
035import org.kuali.rice.krad.datadictionary.validation.constraint.PrerequisiteConstraint;
036import org.kuali.rice.krad.datadictionary.validation.constraint.SimpleConstraint;
037import org.kuali.rice.krad.datadictionary.validation.constraint.ValidCharactersConstraint;
038import org.kuali.rice.krad.keyvalues.KeyValuesFinder;
039import org.kuali.rice.krad.uif.UifConstants;
040import org.kuali.rice.krad.uif.control.TextControl;
041import org.kuali.rice.krad.uif.control.UifKeyValuesFinder;
042import org.kuali.rice.krad.uif.view.FormView;
043import org.kuali.rice.krad.uif.view.View;
044import org.kuali.rice.krad.uif.control.Control;
045import org.kuali.rice.krad.uif.control.MultiValueControlBase;
046import org.kuali.rice.krad.uif.component.Component;
047import org.kuali.rice.krad.uif.util.ClientValidationUtils;
048import org.kuali.rice.krad.uif.util.ComponentUtils;
049import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
050import org.kuali.rice.krad.uif.view.ViewModel;
051import org.kuali.rice.krad.uif.widget.DirectInquiry;
052import org.kuali.rice.krad.uif.widget.QuickFinder;
053import org.kuali.rice.krad.uif.widget.Suggest;
054import org.kuali.rice.krad.util.ObjectUtils;
055
056import java.util.ArrayList;
057import 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 */
078public 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}