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