View Javadoc

1   /**
2    * Copyright 2005-2012 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.uif.field;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.core.api.uif.DataType;
20  import org.kuali.rice.core.api.util.ConcreteKeyValue;
21  import org.kuali.rice.core.api.util.KeyValue;
22  import org.kuali.rice.core.api.util.type.TypeUtils;
23  import org.kuali.rice.krad.datadictionary.AttributeDefinition;
24  import org.kuali.rice.krad.datadictionary.validation.capability.CaseConstrainable;
25  import org.kuali.rice.krad.datadictionary.validation.capability.Formatable;
26  import org.kuali.rice.krad.datadictionary.validation.capability.HierarchicallyConstrainable;
27  import org.kuali.rice.krad.datadictionary.validation.capability.LengthConstrainable;
28  import org.kuali.rice.krad.datadictionary.validation.capability.MustOccurConstrainable;
29  import org.kuali.rice.krad.datadictionary.validation.capability.PrerequisiteConstrainable;
30  import org.kuali.rice.krad.datadictionary.validation.capability.RangeConstrainable;
31  import org.kuali.rice.krad.datadictionary.validation.capability.SimpleConstrainable;
32  import org.kuali.rice.krad.datadictionary.validation.capability.ValidCharactersConstrainable;
33  import org.kuali.rice.krad.datadictionary.validation.constraint.CaseConstraint;
34  import org.kuali.rice.krad.datadictionary.validation.constraint.MustOccurConstraint;
35  import org.kuali.rice.krad.datadictionary.validation.constraint.PrerequisiteConstraint;
36  import org.kuali.rice.krad.datadictionary.validation.constraint.SimpleConstraint;
37  import org.kuali.rice.krad.datadictionary.validation.constraint.ValidCharactersConstraint;
38  import org.kuali.rice.krad.keyvalues.KeyValuesFinder;
39  import org.kuali.rice.krad.uif.UifConstants;
40  import org.kuali.rice.krad.uif.control.TextControl;
41  import org.kuali.rice.krad.uif.control.UifKeyValuesFinder;
42  import org.kuali.rice.krad.uif.view.FormView;
43  import org.kuali.rice.krad.uif.view.View;
44  import org.kuali.rice.krad.uif.control.Control;
45  import org.kuali.rice.krad.uif.control.MultiValueControlBase;
46  import org.kuali.rice.krad.uif.component.Component;
47  import org.kuali.rice.krad.uif.util.ClientValidationUtils;
48  import org.kuali.rice.krad.uif.util.ComponentUtils;
49  import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
50  import org.kuali.rice.krad.uif.view.ViewModel;
51  import org.kuali.rice.krad.uif.widget.DirectInquiry;
52  import org.kuali.rice.krad.uif.widget.QuickFinder;
53  import org.kuali.rice.krad.uif.widget.Suggest;
54  import org.kuali.rice.krad.util.ObjectUtils;
55  
56  import java.util.ArrayList;
57  import java.util.List;
58  
59  /**
60   * Field that encapsulates data input/output captured by an attribute within the
61   * application
62   *
63   * <p>
64   * R
65   * The <code>InputField</code> provides the majority of the data input/output
66   * for the screen. Through these fields the model can be displayed and updated.
67   * For data input, the field contains a {@link Control} instance will
68   * render an HTML control element(s). The input field also contains a
69   * {@link LabelField}, summary, and widgets such as a quickfinder (for
70   * looking up values) and inquiry (for getting more information on the value).
71   * <code>InputField</code> instances can have associated messages (errors)
72   * due to invalid input or business rule failures. Security can also be
73   * configured to restrict who may view the fields value.
74   * </p>
75   *
76   * @author Kuali Rice Team (rice.collab@kuali.org)
77   */
78  public class InputField extends DataField implements SimpleConstrainable, CaseConstrainable, PrerequisiteConstrainable,
79          MustOccurConstrainable, LengthConstrainable, RangeConstrainable, ValidCharactersConstrainable {
80      private static final long serialVersionUID = -3703656713706343840L;
81  
82      // constraint variables
83      private String customValidatorClass;
84      private ValidCharactersConstraint validCharactersConstraint;
85      private CaseConstraint caseConstraint;
86      private List<PrerequisiteConstraint> dependencyConstraints;
87      private List<MustOccurConstraint> mustOccurConstraints;
88      private SimpleConstraint simpleConstraint;
89      private DataType dataType;
90  
91      // display props
92      private Control control;
93      private KeyValuesFinder optionsFinder;
94      private boolean performUppercase;
95  
96      private ErrorsField errorsField;
97  
98      // messages
99      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((String) fieldValue, 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 }