1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.uif.util;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.kuali.rice.krad.datadictionary.state.StateMapping;
20 import org.kuali.rice.krad.datadictionary.validation.constraint.BaseConstraint;
21 import org.kuali.rice.krad.datadictionary.validation.constraint.CaseConstraint;
22 import org.kuali.rice.krad.datadictionary.validation.constraint.Constraint;
23 import org.kuali.rice.krad.datadictionary.validation.constraint.MustOccurConstraint;
24 import org.kuali.rice.krad.datadictionary.validation.constraint.PrerequisiteConstraint;
25 import org.kuali.rice.krad.datadictionary.validation.constraint.SimpleConstraint;
26 import org.kuali.rice.krad.datadictionary.validation.constraint.ValidCharactersConstraint;
27 import org.kuali.rice.krad.datadictionary.validation.constraint.WhenConstraint;
28 import org.kuali.rice.krad.messages.MessageService;
29 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
30 import org.kuali.rice.krad.uif.UifConstants;
31 import org.kuali.rice.krad.uif.control.TextControl;
32 import org.kuali.rice.krad.uif.field.Field;
33 import org.kuali.rice.krad.uif.field.InputField;
34 import org.kuali.rice.krad.uif.view.FormView;
35 import org.kuali.rice.krad.uif.view.View;
36 import org.kuali.rice.krad.uif.widget.DatePicker;
37 import org.kuali.rice.krad.util.KRADUtils;
38 import org.kuali.rice.krad.web.form.UifFormBase;
39
40 import java.text.MessageFormat;
41 import java.util.ArrayList;
42 import java.util.EnumSet;
43 import java.util.HashMap;
44 import java.util.List;
45 import java.util.Map;
46
47
48
49
50
51
52
53
54
55
56 public class ClientValidationUtils {
57
58 private static int methodKey = 0;
59
60
61
62 private static List<List<String>> mustOccursPathNames;
63
64 public static final String LABEL_KEY_SPLIT_PATTERN = ",";
65
66 public static final String PREREQ_MSG_KEY = "prerequisite";
67 public static final String POSTREQ_MSG_KEY = "postrequisite";
68 public static final String MUSTOCCURS_MSG_KEY = "mustOccurs";
69 public static final String MUSTOCCURS_MSG_EQUAL_KEY = "mustOccursEqualMinMax";
70 public static final String GENERIC_FIELD_MSG_KEY = "general.genericFieldName";
71
72 public static final String ALL_MSG_KEY = "general.all";
73 public static final String ATMOST_MSG_KEY = "general.atMost";
74 public static final String AND_MSG_KEY = "general.and";
75 public static final String OR_MSG_KEY = "general.or";
76
77
78 public static enum ValidationMessageKeys {
79 REQUIRED("required"),
80 MIN_EXCLUSIVE("minExclusive"),
81 MAX_INCLUSIVE("maxInclusive"),
82 MIN_LENGTH("minLengthConditional"),
83 MAX_LENGTH("maxLengthConditional");
84
85 private ValidationMessageKeys(String name) {
86 this.name = name;
87 }
88
89 private final String name;
90
91 @Override
92 public String toString() {
93 return name;
94 }
95
96 public static boolean contains(String name) {
97 for (ValidationMessageKeys element : EnumSet.allOf(ValidationMessageKeys.class)) {
98 if (element.toString().equalsIgnoreCase(name)) {
99 return true;
100 }
101 }
102 return false;
103 }
104 }
105
106
107
108
109
110
111
112
113
114
115
116
117 public static String generateMessageText(String namespace, String componentCode, String messageKey,
118 List<String> params) {
119 String message = "NO MESSAGE";
120 if (StringUtils.isNotEmpty(messageKey)) {
121 message = KRADServiceLocatorWeb.getMessageService().getMessageText(namespace, componentCode, messageKey);
122 if (params != null && !params.isEmpty() && StringUtils.isNotEmpty(message)) {
123 message = MessageFormat.format(message, params.toArray());
124 message = MessageStructureUtils.translateStringMessage(message);
125 }
126 }
127
128 if (StringUtils.isEmpty(message)) {
129 message = messageKey;
130 }
131
132
133 message = KRADUtils.convertToHTMLAttributeSafeString(message);
134
135 return message;
136 }
137
138
139
140
141
142
143
144 public static String generateValidatorMessagesOption() {
145 MessageService messageService = KRADServiceLocatorWeb.getMessageService();
146
147 String mOption = "";
148 String keyValuePairs = "";
149 for (ValidationMessageKeys element : EnumSet.allOf(ValidationMessageKeys.class)) {
150 String key = element.toString();
151 String message = messageService.getMessageText(UifConstants.Messages.VALIDATION_MSG_KEY_PREFIX + key);
152
153 if (StringUtils.isNotEmpty(message)) {
154 message = MessageStructureUtils.translateStringMessage(message);
155 keyValuePairs = keyValuePairs + "\n" + key + ": '" + message + "',";
156 }
157 }
158
159 keyValuePairs = StringUtils.removeEnd(keyValuePairs, ",");
160 if (StringUtils.isNotEmpty(keyValuePairs)) {
161 mOption = "{" + keyValuePairs + "}";
162 }
163
164 return mOption;
165 }
166
167
168
169
170
171
172
173
174 public static String getRegexMethod(InputField field, ValidCharactersConstraint validCharactersConstraint) {
175 return getRegexMethod(field, validCharactersConstraint, true);
176 }
177
178
179
180
181
182
183
184
185
186
187 public static String getRegexMethod(InputField field, ValidCharactersConstraint validCharactersConstraint,
188 boolean escape) {
189 String message = generateMessageText(validCharactersConstraint.getMessageNamespaceCode(),
190 validCharactersConstraint.getMessageComponentCode(), validCharactersConstraint.getMessageKey(),
191 validCharactersConstraint.getValidationMessageParams());
192 String key = "validChar-" + field.getBindingInfo().getBindingPath() + methodKey;
193
194
195 String regex = validCharactersConstraint.getValue();
196 if (regex.contains("\\\\")) {
197 regex = regex.replaceAll("\\\\", "\\\\\\\\");
198 }
199 if (regex.contains("/")) {
200 regex = regex.replace("/", "\\/");
201 }
202
203 return "\njQuery.validator.addMethod(\"" + (escape ? ScriptUtils.escapeName(key) : key)
204 + "\", function(value, element) {\n "
205 + "return (this.optional(element) !== false) || /"
206 + regex
207 + "/.test(value);"
208 + "}, \""
209 + message
210 + "\");";
211 }
212
213
214
215
216
217
218
219
220
221
222 public static String getRegexMethodWithBooleanCheck(InputField field,
223 ValidCharactersConstraint validCharactersConstraint) {
224 String message = generateMessageText(validCharactersConstraint.getMessageNamespaceCode(),
225 validCharactersConstraint.getMessageComponentCode(), validCharactersConstraint.getMessageKey(),
226 validCharactersConstraint.getValidationMessageParams());
227 String key = "validChar-" + field.getBindingInfo().getBindingPath() + methodKey;
228
229
230 String regex = validCharactersConstraint.getValue();
231 if (regex.contains("\\\\")) {
232 regex = regex.replaceAll("\\\\", "\\\\\\\\");
233 }
234 if (regex.contains("/")) {
235 regex = regex.replace("/", "\\/");
236 }
237
238 return "\njQuery.validator.addMethod(\""
239 + ScriptUtils.escapeName(key)
240 + "\", function(value, element, doCheck) {\n if(doCheck === false){return true;}else{"
241 + "return (this.optional(element) !== false) || /"
242 + regex
243 + "/.test(value);}"
244 + "}, \""
245 + message
246 + "\");";
247 }
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262 public static void processCaseConstraint(InputField field, View view, CaseConstraint constraint, String andedCase,
263 String validationState, StateMapping stateMapping) {
264 if (constraint.getOperator() == null) {
265 constraint.setOperator("equals");
266 }
267
268 String operator = "==";
269 if (constraint.getOperator().equalsIgnoreCase("not_equals") || constraint.getOperator().equalsIgnoreCase(
270 "not_equal")) {
271 operator = "!=";
272 } else if (constraint.getOperator().equalsIgnoreCase("greater_than_equal")) {
273 operator = ">=";
274 } else if (constraint.getOperator().equalsIgnoreCase("less_than_equal")) {
275 operator = "<=";
276 } else if (constraint.getOperator().equalsIgnoreCase("greater_than")) {
277 operator = ">";
278 } else if (constraint.getOperator().equalsIgnoreCase("less_than")) {
279 operator = "<";
280 } else if (constraint.getOperator().equalsIgnoreCase("has_value")) {
281 operator = "";
282 }
283
284
285 field.getControl().addStyleClass("dependsOn-" + ScriptUtils.escapeName(constraint.getPropertyName()));
286
287 if (constraint.getWhenConstraint() != null && !constraint.getWhenConstraint().isEmpty()) {
288
289 String fieldPath = constraint.getPropertyName();
290 for (WhenConstraint wc : constraint.getWhenConstraint()) {
291 wc = ConstraintStateUtils.getApplicableConstraint(wc, validationState, stateMapping);
292 if (wc != null) {
293 processWhenConstraint(field, view, constraint, wc, ScriptUtils.escapeName(fieldPath), operator,
294 andedCase, validationState, stateMapping);
295 }
296 }
297 }
298 }
299
300
301
302
303
304
305
306
307
308
309
310
311
312 private static void processWhenConstraint(InputField field, View view, CaseConstraint caseConstraint,
313 WhenConstraint wc, String fieldPath, String operator, String andedCase, String validationState,
314 StateMapping stateMapping) {
315 String ruleString = "";
316
317
318 String booleanStatement = "";
319 if (wc.getValues() != null) {
320
321 String caseStr = "";
322 if (!caseConstraint.isCaseSensitive()) {
323 caseStr = ".toUpperCase()";
324 }
325 for (int i = 0; i < wc.getValues().size(); i++) {
326 if (operator.isEmpty()) {
327
328 if (wc.getValues().get(i) instanceof String && ((String) wc.getValues().get(i)).equalsIgnoreCase(
329 "false")) {
330 booleanStatement = booleanStatement + "(coerceValue('" + fieldPath + "') == '')";
331 } else {
332 booleanStatement = booleanStatement + "(coerceValue('" + fieldPath + "') != '')";
333 }
334 } else {
335
336 booleanStatement = booleanStatement
337 + "(coerceValue('"
338 + fieldPath
339 + "')"
340 + caseStr
341 + " "
342 + operator
343 + " \""
344 + wc.getValues().get(i)
345 + "\""
346 + caseStr
347 + ")";
348 }
349 if ((i + 1) != wc.getValues().size()) {
350 booleanStatement = booleanStatement + " || ";
351 }
352 }
353
354 }
355
356 if (andedCase != null) {
357 booleanStatement = "(" + booleanStatement + ") && (" + andedCase + ")";
358 }
359
360 if (wc.getConstraint() != null && StringUtils.isNotEmpty(booleanStatement)) {
361 Constraint constraint = ConstraintStateUtils.getApplicableConstraint(wc.getConstraint(), validationState,
362 stateMapping);
363 if (constraint != null) {
364 ruleString = createRule(field, constraint, booleanStatement, view, validationState, stateMapping);
365 }
366 }
367
368 if (StringUtils.isNotEmpty(ruleString)) {
369 addScriptToPage(view, field, ruleString);
370 }
371 }
372
373
374
375
376
377
378
379
380 public static void addScriptToPage(View view, InputField field, String script) {
381 String prefixScript = "";
382
383 if (field.getOnDocumentReadyScript() != null) {
384 prefixScript = field.getOnDocumentReadyScript();
385 }
386 field.setOnDocumentReadyScript(prefixScript + "\n" + "runValidationScript(function(){" + script + "});");
387 }
388
389
390
391
392
393
394
395
396 private static List<String> parseOutFields(String statement) {
397 List<String> fieldNames = new ArrayList<String>();
398 String[] splits = StringUtils.splitByWholeSeparator(statement, "coerceValue(");
399 for (String s : splits) {
400
401 if (!s.startsWith("'")) {
402 continue;
403 }
404
405 s = s.substring(1);
406 String fieldName = StringUtils.substringBefore(s, "'");
407
408 if (!fieldNames.contains(fieldName)) {
409 fieldNames.add(fieldName);
410 }
411
412 }
413 return fieldNames;
414 }
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430 @SuppressWarnings("boxing")
431 private static String createRule(InputField field, Constraint constraint, String booleanStatement, View view,
432 String validationState, StateMapping stateMapping) {
433 String rule = "";
434 int constraintCount = 0;
435 if (constraint instanceof BaseConstraint && ((BaseConstraint) constraint).getApplyClientSide()) {
436 if (constraint instanceof SimpleConstraint) {
437 if (((SimpleConstraint) constraint).getRequired() != null && ((SimpleConstraint) constraint)
438 .getRequired()) {
439 rule = rule + "required: function(element){\nreturn (" + booleanStatement + ");}";
440
441
442 String showIndicatorScript = "";
443 boolean hasConditionalReqCheck = false;
444 for (String checkedField : parseOutFields(booleanStatement)) {
445 showIndicatorScript = showIndicatorScript +
446 "setupShowReqIndicatorCheck('" + checkedField + "', '" + field.getBindingInfo()
447 .getBindingPath() + "', " + "function(){\nreturn (" + booleanStatement
448 + ");});\n";
449 hasConditionalReqCheck = true;
450 }
451
452 addScriptToPage(view, field, showIndicatorScript);
453
454 constraintCount++;
455 }
456
457 if (((SimpleConstraint) constraint).getMinLength() != null) {
458 if (constraintCount > 0) {
459 rule = rule + ",\n";
460 }
461 rule = rule
462 + "minLengthConditional: ["
463 + ((SimpleConstraint) constraint).getMinLength()
464 + ", function(){return "
465 + booleanStatement
466 + ";}]";
467 constraintCount++;
468 }
469
470 if (((SimpleConstraint) constraint).getMaxLength() != null) {
471 if (constraintCount > 0) {
472 rule = rule + ",\n";
473 }
474 rule = rule
475 + "maxLengthConditional: ["
476 + ((SimpleConstraint) constraint).getMaxLength()
477 + ", function(){return "
478 + booleanStatement
479 + ";}]";
480 constraintCount++;
481 }
482
483 if (((SimpleConstraint) constraint).getExclusiveMin() != null) {
484 if (constraintCount > 0) {
485 rule = rule + ",\n";
486 }
487 rule = rule
488 + "minExclusive: ["
489 + ((SimpleConstraint) constraint).getExclusiveMin()
490 + ", function(){return "
491 + booleanStatement
492 + ";}]";
493 constraintCount++;
494 }
495
496 if (((SimpleConstraint) constraint).getInclusiveMax() != null) {
497 if (constraintCount > 0) {
498 rule = rule + ",\n";
499 }
500 rule = rule
501 + "maxInclusive: ["
502 + ((SimpleConstraint) constraint).getInclusiveMax()
503 + ", function(){return "
504 + booleanStatement
505 + ";}]";
506 constraintCount++;
507 }
508
509 rule = "jQuery('[name=\""
510 + ScriptUtils.escapeName(field.getBindingInfo().getBindingPath())
511 + "\"]').rules(\"add\", {"
512 + rule
513 + "\n});";
514 } else if (constraint instanceof ValidCharactersConstraint) {
515 String regexMethod = "";
516 String methodName = "";
517 if (StringUtils.isNotEmpty(((ValidCharactersConstraint) constraint).getValue())) {
518 regexMethod = ClientValidationUtils.getRegexMethodWithBooleanCheck(field,
519 (ValidCharactersConstraint) constraint) + "\n";
520 methodName = "validChar-" + field.getBindingInfo().getBindingPath() + methodKey;
521 methodKey++;
522 } else {
523 if (StringUtils.isNotEmpty(((ValidCharactersConstraint) constraint).getMessageKey())) {
524 methodName = ((ValidCharactersConstraint) constraint).getMessageKey();
525 }
526 }
527
528 if (StringUtils.isNotEmpty(methodName)) {
529 rule = regexMethod
530 + "jQuery('[name=\""
531 + ScriptUtils.escapeName(field.getBindingInfo().getBindingPath())
532 + "\"]').rules(\"add\", {\n\""
533 + methodName
534 + "\" : function(element){return ("
535 + booleanStatement
536 + ");}\n});";
537 }
538 } else if (constraint instanceof PrerequisiteConstraint) {
539 processPrerequisiteConstraint(field, (PrerequisiteConstraint) constraint, view, booleanStatement);
540 } else if (constraint instanceof CaseConstraint) {
541 processCaseConstraint(field, view, (CaseConstraint) constraint, booleanStatement, validationState,
542 stateMapping);
543 } else if (constraint instanceof MustOccurConstraint) {
544 processMustOccurConstraint(field, view, (MustOccurConstraint) constraint, booleanStatement);
545 }
546 }
547
548 return rule;
549 }
550
551
552
553
554
555
556
557
558
559
560 public static void processPrerequisiteConstraint(InputField field, PrerequisiteConstraint constraint, View view) {
561 processPrerequisiteConstraint(field, constraint, view, "true");
562 }
563
564
565
566
567
568
569
570
571
572
573
574 public static void processPrerequisiteConstraint(InputField field, PrerequisiteConstraint constraint, View view,
575 String booleanStatement) {
576 if (constraint != null && constraint.getApplyClientSide().booleanValue()) {
577 String dependsClass = "dependsOn-" + ScriptUtils.escapeName(constraint.getPropertyName());
578 String addClass = "jQuery('[name=\""
579 + ScriptUtils.escapeName(field.getBindingInfo().getBindingPath())
580 + "\"]').addClass('"
581 + dependsClass
582 + "');"
583 +
584 "jQuery('[name=\""
585 + ScriptUtils.escapeName(constraint.getPropertyName())
586 + "\"]').addClass('"
587 + "dependsOn-"
588 + ScriptUtils.escapeName(field.getBindingInfo().getBindingPath())
589 + "');";
590
591 addScriptToPage(view, field, addClass
592 + getPrerequisiteStatement(field, view, constraint, booleanStatement)
593 + getPostrequisiteStatement(field, constraint, booleanStatement));
594
595
596 String showIndicatorScript = "setupShowReqIndicatorCheck('" + ScriptUtils.escapeName(
597 field.getBindingInfo().getBindingPath()) + "', '" + ScriptUtils.escapeName(
598 constraint.getPropertyName()) + "', " + "function(){\nreturn (coerceValue('" + ScriptUtils
599 .escapeName(field.getBindingInfo().getBindingPath()) + "') && " + booleanStatement + ");});\n";
600
601 addScriptToPage(view, field, showIndicatorScript);
602 }
603 }
604
605
606
607
608
609
610
611
612
613
614
615
616 private static String getPrerequisiteStatement(InputField field, View view, PrerequisiteConstraint constraint,
617 String booleanStatement) {
618 methodKey++;
619
620 MessageService messageService = KRADServiceLocatorWeb.getMessageService();
621
622 String message = "";
623 if (StringUtils.isEmpty(constraint.getMessageKey())) {
624 message = messageService.getMessageText(UifConstants.Messages.VALIDATION_MSG_KEY_PREFIX + "prerequisite");
625 message = MessageStructureUtils.translateStringMessage(message);
626 } else {
627 message = generateMessageText(constraint.getMessageNamespaceCode(),
628 constraint.getMessageComponentCode(), constraint.getMessageKey(),
629 constraint.getValidationMessageParams());
630 }
631
632 if (StringUtils.isEmpty(message)) {
633 message = "prerequisite - No message";
634 } else {
635 Field requiredField = (Field) view.getViewIndex().getDataFieldByPath(constraint.getPropertyName());
636 if (requiredField != null && StringUtils.isNotEmpty(requiredField.getLabel())) {
637 message = MessageFormat.format(message, requiredField.getLabel());
638 } else {
639 String genericFieldLabel = messageService.getMessageText(GENERIC_FIELD_MSG_KEY);
640 message = MessageFormat.format(message, genericFieldLabel);
641 }
642 }
643
644
645 String methodName = "prConstraint-"
646 + ScriptUtils.escapeName(field.getBindingInfo().getBindingPath())
647 + methodKey;
648
649 String addClass = "jQuery('[name=\""
650 + ScriptUtils.escapeName(field.getBindingInfo().getBindingPath())
651 + "\"]').addClass('"
652 + methodName
653 + "');\n";
654
655 String method = "\njQuery.validator.addMethod(\"" + methodName + "\", function(value, element) {\n" +
656 " if(" + booleanStatement + "){ return ((this.optional(element) !== false) || (coerceValue('" + ScriptUtils
657 .escapeName(constraint.getPropertyName()) + "')));}else{return true;} " +
658 "}, \"" + message + "\");";
659
660 String ifStatement = "if(occursBefore('"
661 + ScriptUtils.escapeName(constraint.getPropertyName())
662 + "','"
663 + ScriptUtils.escapeName(field.getBindingInfo().getBindingPath())
664 +
665 "')){"
666 + addClass
667 + method
668 + "}";
669
670 return ifStatement;
671 }
672
673
674
675
676
677
678
679
680
681
682
683
684 private static String getPostrequisiteStatement(InputField field, PrerequisiteConstraint constraint,
685 String booleanStatement) {
686 MessageService messageService = KRADServiceLocatorWeb.getMessageService();
687
688
689 String message = "";
690 if (StringUtils.isEmpty(constraint.getMessageKey())) {
691 message = messageService.getMessageText(UifConstants.Messages.VALIDATION_MSG_KEY_PREFIX + "postrequisite");
692 message = MessageStructureUtils.translateStringMessage(message);
693 } else {
694 message = generateMessageText(constraint.getMessageNamespaceCode(), constraint.getMessageComponentCode(),
695 constraint.getMessageKey(), constraint.getValidationMessageParams());
696 }
697
698 if (StringUtils.isEmpty(constraint.getMessageKey())) {
699 if (StringUtils.isNotEmpty(field.getLabel())) {
700 message = MessageFormat.format(message, field.getLabel());
701 } else {
702 String genericFieldLabel = messageService.getMessageText(GENERIC_FIELD_MSG_KEY);
703 message = MessageFormat.format(message, genericFieldLabel);
704 }
705 }
706
707 String function = "function(element){\n" +
708 "return (coerceValue('"
709 + ScriptUtils.escapeName(field.getBindingInfo().getBindingPath())
710 + "') && "
711 + booleanStatement
712 + ");}";
713 String postStatement = "\nelse if(occursBefore('"
714 + ScriptUtils.escapeName(field.getBindingInfo().getBindingPath())
715 + "','"
716 + ScriptUtils.escapeName(constraint.getPropertyName())
717 +
718 "')){\njQuery('[name=\""
719 + ScriptUtils.escapeName(constraint.getPropertyName())
720 +
721 "\"]').rules(\"add\", { required: \n"
722 + function
723 + ", \nmessages: {\nrequired: \""
724 + message
725 + "\"}});}\n";
726
727 return postStatement;
728
729 }
730
731
732
733
734
735
736
737
738
739
740
741
742
743 public static void processMustOccurConstraint(InputField field, View view, MustOccurConstraint mc,
744 String booleanStatement) {
745 methodKey++;
746 mustOccursPathNames = new ArrayList<List<String>>();
747
748 String methodName = "moConstraint-"
749 + ScriptUtils.escapeName(field.getBindingInfo().getBindingPath())
750 + methodKey;
751 String method = "\njQuery.validator.addMethod(\"" + methodName + "\", function(value, element) {\n" +
752 " if("
753 + booleanStatement
754 + "){return ((this.optional(element) !== false) || ("
755 + getMustOccurStatement(field, mc)
756 + "));}else{return true;}"
757 +
758 "}, \""
759 + getMustOccursMessage(view, mc)
760 + "\");";
761 String rule = method
762 + "jQuery('[name=\""
763 + ScriptUtils.escapeName(field.getBindingInfo().getBindingPath())
764 + "\"]').rules(\"add\", {\n\""
765 + methodName
766 + "\": function(element){return ("
767 + booleanStatement
768 + ");}\n});";
769 addScriptToPage(view, field, rule);
770 }
771
772
773
774
775
776
777
778
779
780
781 @SuppressWarnings("boxing")
782 private static String getMustOccurStatement(InputField field, MustOccurConstraint constraint) {
783 String statement = "";
784 List<String> attributePaths = new ArrayList<String>();
785 if (constraint != null && constraint.getApplyClientSide()) {
786 String array = "[";
787 if (constraint.getPrerequisiteConstraints() != null) {
788 for (int i = 0; i < constraint.getPrerequisiteConstraints().size(); i++) {
789 field.getControl().addStyleClass("dependsOn-" + constraint.getPrerequisiteConstraints().get(i)
790 .getPropertyName());
791 array = array + "'" + ScriptUtils.escapeName(constraint.getPrerequisiteConstraints().get(i)
792 .getPropertyName()) + "'";
793 attributePaths.add(constraint.getPrerequisiteConstraints().get(i).getPropertyName());
794
795 if (i + 1 != constraint.getPrerequisiteConstraints().size()) {
796 array = array + ",";
797 }
798 }
799 }
800 array = array + "]";
801 statement = "mustOccurTotal(" + array + ", " + constraint.getMin() + ", " + constraint.getMax() + ")";
802
803 if (constraint.getMin() != null) {
804 attributePaths.add(constraint.getMin().toString());
805 } else {
806 attributePaths.add(null);
807 }
808
809 if (constraint.getMax() != null) {
810 attributePaths.add(constraint.getMax().toString());
811 } else {
812 attributePaths.add(null);
813 }
814
815 mustOccursPathNames.add(attributePaths);
816 if (StringUtils.isEmpty(statement)) {
817 statement = "0";
818 }
819 if (constraint.getMustOccurConstraints() != null) {
820 for (MustOccurConstraint mc : constraint.getMustOccurConstraints()) {
821 statement = "mustOccurCheck(" + statement + " + " + getMustOccurStatement(field, mc) +
822 ", " + constraint.getMin() + ", " + constraint.getMax() + ")";
823 }
824 } else {
825 statement = "mustOccurCheck(" + statement +
826 ", " + constraint.getMin() + ", " + constraint.getMax() + ")";
827 }
828 }
829 return statement;
830 }
831
832
833
834
835
836
837
838
839
840
841
842 private static String getMustOccursMessage(View view, MustOccurConstraint constraint) {
843 MessageService messageService = KRADServiceLocatorWeb.getMessageService();
844
845 String message = "";
846 if (StringUtils.isNotEmpty(constraint.getMessageKey())) {
847 message = generateMessageText(constraint.getMessageNamespaceCode(), constraint.getMessageComponentCode(),
848 constraint.getMessageKey(), constraint.getValidationMessageParams());
849 } else {
850 String and = messageService.getMessageText(AND_MSG_KEY);
851 String or = messageService.getMessageText(OR_MSG_KEY);
852 String mustOccursMsgEqualMinMax = messageService.getMessageText(
853 UifConstants.Messages.VALIDATION_MSG_KEY_PREFIX + MUSTOCCURS_MSG_EQUAL_KEY);
854 String atMost = messageService.getMessageText(ATMOST_MSG_KEY);
855 String genericLabel = messageService.getMessageText(GENERIC_FIELD_MSG_KEY);
856 String mustOccursMsg = messageService.getMessageText(
857 UifConstants.Messages.VALIDATION_MSG_KEY_PREFIX + MUSTOCCURS_MSG_KEY);
858
859 String statement = "";
860 for (int i = 0; i < mustOccursPathNames.size(); i++) {
861 String andedString = "";
862
863 List<String> paths = mustOccursPathNames.get(i);
864 if (!paths.isEmpty()) {
865
866 String min = paths.get(paths.size() - 2);
867 String max = paths.get(paths.size() - 1);
868 for (int j = 0; j < paths.size() - 2; j++) {
869 InputField field = (InputField) view.getViewIndex().getDataFieldByPath(paths.get(j).trim());
870 String label = genericLabel;
871 if (field != null && StringUtils.isNotEmpty(field.getLabel())) {
872 label = field.getLabel();
873 }
874 if (min.equals(max)) {
875 if (j == 0) {
876 andedString = label;
877 } else if (j == paths.size() - 3) {
878 andedString = andedString + " " + and + " " + label;
879 } else {
880 andedString = andedString + ", " + label;
881 }
882 } else {
883 andedString = andedString + "(" + label + ")";
884 }
885 }
886 if (min.equals(max)) {
887 andedString = "(" + andedString + ")";
888 }
889
890 if (StringUtils.isNotBlank(andedString) && !andedString.equals("()")) {
891 if (StringUtils.isNotEmpty(min) && StringUtils.isNotEmpty(max) && !min.equals(max)) {
892 andedString = MessageFormat.format(mustOccursMsg, min + "-" + max) + " " + andedString;
893 } else if (StringUtils.isNotEmpty(min)
894 && StringUtils.isNotEmpty(max)
895 && min.equals(max)
896 && i == 0) {
897 andedString = mustOccursMsgEqualMinMax + " " + andedString;
898 } else if (StringUtils.isNotEmpty(min)
899 && StringUtils.isNotEmpty(max)
900 && min.equals(max)
901 && i != 0) {
902
903 } else if (StringUtils.isNotEmpty(min)) {
904 andedString = MessageFormat.format(mustOccursMsg, min) + " " + andedString;
905 } else if (StringUtils.isNotEmpty(max)) {
906 andedString = MessageFormat.format(mustOccursMsg, atMost + " " + max) + " " + andedString;
907 }
908 }
909 }
910 if (StringUtils.isNotEmpty(andedString)) {
911 if (StringUtils.isNotBlank(statement)) {
912 statement = statement + " " + or.toUpperCase() + " " + andedString;
913 } else {
914 statement = andedString;
915 }
916 }
917 }
918 if (StringUtils.isNotEmpty(statement)) {
919 message = statement;
920 message = message.replace(")(", " " + or + " ");
921 }
922 }
923
924 return message;
925 }
926
927
928
929
930
931
932
933
934
935
936
937
938 @SuppressWarnings("boxing")
939 public static void processAndApplyConstraints(InputField field, View view, Object model) {
940 methodKey = 0;
941 String validationState = ConstraintStateUtils.getClientViewValidationState(model, view);
942 StateMapping stateMapping = view.getStateMapping();
943
944 if (view instanceof FormView && ((FormView) view).isValidateClientSide()) {
945 SimpleConstraint simpleConstraint = ConstraintStateUtils.getApplicableConstraint(
946 field.getSimpleConstraint(), validationState, stateMapping);
947 if (simpleConstraint != null && simpleConstraint.getApplyClientSide()) {
948
949 if ((simpleConstraint.getRequired() != null) && (simpleConstraint.getRequired().booleanValue())) {
950 field.getControl().addStyleClass("required");
951 }
952
953 if (simpleConstraint.getExclusiveMin() != null) {
954 if (field.getControl() instanceof TextControl
955 && ((TextControl) field.getControl()).getDatePicker() != null) {
956 DatePicker datePicker = ((TextControl) field.getControl()).getDatePicker();
957 Map<String, String> dpTemplateOptions = datePicker.getTemplateOptions();
958
959 if (dpTemplateOptions == null) {
960 datePicker.setTemplateOptions(dpTemplateOptions = new HashMap<String, String>());
961 }
962
963 dpTemplateOptions.put("minDate",
964 simpleConstraint.getExclusiveMin());
965 } else {
966 String rule = "jQuery('[name=\""
967 + ScriptUtils.escapeName(field.getBindingInfo().getBindingPath())
968 + "\"]').rules(\"add\", {\n minExclusive: ["
969 + simpleConstraint.getExclusiveMin()
970 + "]});";
971 addScriptToPage(view, field, rule);
972 }
973 }
974
975 if (simpleConstraint.getInclusiveMax() != null) {
976 if (field.getControl() instanceof TextControl
977 && ((TextControl) field.getControl()).getDatePicker() != null) {
978 ((TextControl) field.getControl()).getDatePicker().getTemplateOptions().put("maxDate",
979 simpleConstraint.getInclusiveMax());
980 } else {
981 String rule = "jQuery('[name=\""
982 + ScriptUtils.escapeName(field.getBindingInfo().getBindingPath())
983 + "\"]').rules(\"add\", {\n maxInclusive: ["
984 + simpleConstraint.getInclusiveMax()
985 + "]});";
986 addScriptToPage(view, field, rule);
987 }
988 }
989 }
990
991 ValidCharactersConstraint validCharactersConstraint = ConstraintStateUtils.getApplicableConstraint(
992 field.getValidCharactersConstraint(), validationState, stateMapping);
993
994 if (validCharactersConstraint != null && validCharactersConstraint.getApplyClientSide()) {
995 if (StringUtils.isNotEmpty(validCharactersConstraint.getValue())) {
996
997 String script = ClientValidationUtils.getRegexMethod(field, validCharactersConstraint, false);
998 if (((UifFormBase) model).getRequestJsonTemplate() == UifConstants.TableToolsValues.JSON_TEMPLATE) {
999 script = script.replaceAll("\\.", "\\\\u002e");
1000 }
1001 addScriptToPage(view, field, script);
1002 field.getControl().addStyleClass(
1003 "validChar-" + field.getBindingInfo().getBindingPath() + methodKey);
1004 methodKey++;
1005 } else {
1006
1007 if (StringUtils.isNotEmpty(validCharactersConstraint.getMessageKey())) {
1008 field.getControl().addStyleClass(validCharactersConstraint.getMessageKey());
1009 }
1010 }
1011 }
1012
1013 CaseConstraint caseConstraint = ConstraintStateUtils.getApplicableConstraint(field.getCaseConstraint(),
1014 validationState, stateMapping);
1015 if (caseConstraint != null && caseConstraint.getApplyClientSide()) {
1016 processCaseConstraint(field, view, caseConstraint, null, validationState, stateMapping);
1017 }
1018
1019 if (field.getDependencyConstraints() != null) {
1020 for (PrerequisiteConstraint prc : field.getDependencyConstraints()) {
1021 prc = ConstraintStateUtils.getApplicableConstraint(prc, validationState, stateMapping);
1022 if (prc != null) {
1023 processPrerequisiteConstraint(field, prc, view);
1024 }
1025 }
1026 }
1027
1028 if (field.getMustOccurConstraints() != null) {
1029 for (MustOccurConstraint mc : field.getMustOccurConstraints()) {
1030 mc = ConstraintStateUtils.getApplicableConstraint(mc, validationState, stateMapping);
1031 if (mc != null) {
1032 processMustOccurConstraint(field, view, mc, "true");
1033 }
1034 }
1035 }
1036
1037 }
1038 }
1039
1040 }