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