1 /**
2 * Copyright 2005-2015 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(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 }