1
2
3
4
5
6 package pt.digitalis.dif.dem.objects.parameters.types;
7
8 import java.util.ArrayList;
9 import java.util.HashMap;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.Map.Entry;
13
14 import pt.digitalis.dif.controller.http.HTTPConstants;
15 import pt.digitalis.dif.controller.interfaces.IDIFContext;
16 import pt.digitalis.dif.controller.interfaces.IDIFSession;
17 import pt.digitalis.dif.controller.security.objects.IDIFUser;
18 import pt.digitalis.dif.dem.Entity;
19 import pt.digitalis.dif.dem.annotations.parameter.Rule;
20 import pt.digitalis.dif.dem.interfaces.IStageInstance;
21 import pt.digitalis.dif.dem.managers.IMessageManager;
22 import pt.digitalis.dif.dem.objects.messages.MessageList;
23 import pt.digitalis.dif.dem.objects.parameters.IEditableParameter;
24 import pt.digitalis.dif.dem.objects.parameters.IParameter;
25 import pt.digitalis.dif.dem.objects.parameters.ParameterScope;
26 import pt.digitalis.dif.dem.objects.parameters.constraints.IParameterConstraint;
27 import pt.digitalis.dif.dem.objects.parameters.constraints.ParameterConstraintResult;
28 import pt.digitalis.dif.dem.objects.parameters.errors.ParameterError;
29 import pt.digitalis.dif.dem.objects.parameters.errors.ParameterErrorList;
30 import pt.digitalis.dif.dem.objects.parameters.errors.ParameterErrorType;
31 import pt.digitalis.dif.dem.objects.parameters.rules.IParameterRule;
32 import pt.digitalis.dif.dem.objects.parameters.rules.ParameterRuleResult;
33 import pt.digitalis.dif.dem.objects.parameters.validators.IParameterValidator;
34 import pt.digitalis.dif.exception.objects.ParameterException;
35 import pt.digitalis.dif.ioc.DIFIoCRegistry;
36 import pt.digitalis.dif.startup.DIFGeneralConfigurationParameters;
37 import pt.digitalis.dif.utils.ObjectFormatter;
38 import pt.digitalis.dif.utils.extensions.document.DocumentRepositoryEntry;
39 import pt.digitalis.dif.utils.logging.DIFLogger;
40 import pt.digitalis.log.ILogWrapper;
41 import pt.digitalis.utils.common.StringUtils;
42
43
44
45
46
47
48
49
50
51
52
53
54 abstract public class AbstractParameter<T> implements IParameter<T>, IEditableParameter {
55
56
57 static private ILogWrapper logger = DIFLogger.getLogger();
58
59
60 static IMessageManager messageManager;
61
62
63 static private MessageList messages;
64
65
66
67
68
69
70 static private IMessageManager getMessageManager()
71 {
72 if (messageManager == null)
73 messageManager = DIFIoCRegistry.getRegistry().getImplementation(IMessageManager.class);
74
75 return messageManager;
76 }
77
78
79
80
81
82
83 public static MessageList getMessages()
84 {
85
86 if (messages == null)
87 {
88 messages = getMessageManager().collectEntityMessagesFromRepository(AbstractParameter.class);
89 }
90
91 return messages;
92 }
93
94
95 private boolean allowAnonymous = false;
96
97
98 private Map<String, IParameterConstraint> constraints = new HashMap<String, IParameterConstraint>();
99
100
101 private T defaultValue;
102
103
104
105
106
107 private Boolean firstInitialization = true;
108
109
110 private Boolean formConfigurable = false;
111
112
113 private String formLinked = null;
114
115
116 private String id;
117
118
119 private ParameterScope parameterScope;
120
121
122 private String parentID;
123
124
125 private Entity parentType;
126
127
128 private Boolean persistToRepository = false;
129
130
131 private Boolean readonly = false;
132
133
134 private Boolean referencedInARuleFromAnotherParameter = false;
135
136
137 private Boolean required = false;
138
139
140 private List<IParameterRule<T>> rules = new ArrayList<IParameterRule<T>>();
141
142
143 private Map<String, IParameterValidator> validators = new HashMap<String, IParameterValidator>();
144
145
146 private T value;
147
148
149
150
151
152
153
154 public void addRule(IParameterRule<T> rule)
155 {
156 this.rules.add(rule);
157 }
158
159
160
161
162
163
164 protected String automaticConstraints()
165 {
166 return "";
167 }
168
169
170
171
172 @Override
173 @SuppressWarnings("unchecked")
174 public IParameter<T> clone() throws CloneNotSupportedException
175 {
176 try
177 {
178 IParameter<T> parameter;
179
180 parameter = this.getClass().newInstance();
181 parameter.forceInitialize(this.allowAnonymous, this.constraints, this.defaultValue, this.formLinked,
182 this.id, this.parameterScope, this.parentID, this.parentType, this.persistToRepository,
183 this.readonly, this.referencedInARuleFromAnotherParameter, this.required, this.formConfigurable,
184 this.rules, this.validators, this.value);
185
186 return parameter;
187 }
188 catch (InstantiationException e)
189 {
190 throw new CloneNotSupportedException(e.getMessage());
191 }
192 catch (IllegalAccessException e)
193 {
194 throw new CloneNotSupportedException(e.getMessage());
195 }
196 }
197
198
199
200
201
202
203
204
205 protected String convertObjectToString(Object obj)
206 {
207 return StringUtils.toStringOrNull(obj);
208 }
209
210
211
212
213
214
215
216 public void forceInitialize(boolean allowAnonymous, Map<String, IParameterConstraint> constraints, T defaultValue,
217 String formLinked, String id, ParameterScope parameterScope, String parentID, Entity parentType,
218 boolean persistToRepository, boolean readonly, boolean referencedInARuleFromAnotherParameter,
219 boolean required, boolean formConfigurable, List<IParameterRule<T>> rules,
220 Map<String, IParameterValidator> validators, T value)
221 {
222 this.allowAnonymous = allowAnonymous;
223 this.defaultValue = defaultValue;
224 this.formLinked = formLinked;
225 this.id = id;
226 this.parameterScope = parameterScope;
227 this.parentID = parentID;
228 this.parentType = parentType;
229 this.persistToRepository = persistToRepository;
230 this.readonly = readonly;
231 this.referencedInARuleFromAnotherParameter = referencedInARuleFromAnotherParameter;
232 this.required = required;
233 this.formConfigurable = formConfigurable;
234
235 this.constraints = new HashMap<String, IParameterConstraint>();
236 this.constraints.putAll(constraints);
237
238 this.rules = new ArrayList<IParameterRule<T>>();
239 this.rules.addAll(rules);
240
241 this.validators = new HashMap<String, IParameterValidator>();
242 this.validators.putAll(validators);
243
244 this.value = value;
245 }
246
247
248
249
250 public Map<String, IParameterConstraint> getConstraints()
251 {
252 return constraints;
253 }
254
255
256
257
258
259
260 private String getDebugPrefix()
261 {
262 return "[" + getParameterScope().toString() + " parameter \"" + getId() + "\"] ";
263 }
264
265
266
267
268 public String getFormLinked()
269 {
270 return formLinked;
271 }
272
273
274
275
276 public String getId()
277 {
278 return id;
279 }
280
281
282
283
284
285
286
287
288 protected String getLanguage(IDIFContext context)
289 {
290
291 if (context != null && context.getSession() != null && context.getSession().getLanguage() != null)
292 {
293 return context.getSession().getLanguage().toLowerCase();
294 }
295 else
296 return DIFGeneralConfigurationParameters.getInstance().getDefaultLanguage();
297 }
298
299
300
301
302 public ParameterScope getParameterScope()
303 {
304 return parameterScope;
305 }
306
307
308
309
310 public String getParentID()
311 {
312 return parentID;
313 }
314
315
316
317
318 public Entity getParentType()
319 {
320 return parentType;
321 }
322
323
324
325
326 public List<IParameterRule<T>> getRules()
327 {
328 return rules;
329 }
330
331
332
333
334 public Map<String, IParameterValidator> getValidators()
335 {
336 return validators;
337 }
338
339
340
341
342 @SuppressWarnings("unchecked")
343 public T getValue(IDIFContext context) throws ParameterException
344 {
345
346 if (parameterScope == ParameterScope.SESSION)
347 {
348 if (context == null || context.getSession() == null)
349 {
350 String message;
351
352 if (context == null)
353 message = getMessages().getMessages().get("noSession");
354 else
355 message = getMessages().getMessages(context.getLanguage()).get("noSession");
356
357 throw new ParameterException(getDebugPrefix() + message, this);
358 }
359
360 return (T) context.getSession().getAttribute(getId());
361
362 }
363 else if (parameterScope == ParameterScope.USER)
364 {
365 if (context == null || context.getSession() == null || context.getSession().getUser() == null)
366 if (allowAnonymous)
367 {
368 logWarning("Can't process a USER scoped parameter without a user authenticated in session. Returning null.");
369 return null;
370 }
371 else
372 {
373 String language = (context == null ? DIFGeneralConfigurationParameters.getInstance()
374 .getDefaultLanguage() : context.getLanguage());
375
376 throw new ParameterException(getDebugPrefix() + getMessages().getMessages(language).get("noUser"),
377 this);
378 }
379
380
381 return (T) context.getSession().getUser().getParameter(getId());
382
383 }
384 else
385 return this.value;
386 }
387
388
389
390
391 public DocumentRepositoryEntry getValueAsDocument(IDIFContext context) throws ParameterException
392 {
393
394 throw new ParameterException(getMessages().getMessages(context.getLanguage()).get("invalidUsage"), this);
395 }
396
397
398
399
400 public String getValueAsString(IDIFContext context) throws ParameterException
401 {
402 T currentValue = getValue(context);
403
404 if (currentValue == null)
405 return null;
406 else
407 return currentValue.toString();
408 }
409
410
411
412
413
414
415 protected boolean hasFormBeenSubmited(IDIFContext context)
416 {
417 if (getFormLinked() == null)
418 return false;
419 else
420 {
421
422 Object submitStage = context.getRequest().getParameter(HTTPConstants.FORM_SUBMIT_STAGE);
423 Object submitForm = context.getRequest().getParameter(HTTPConstants.FORM_SUBMIT_NAME);
424
425 return (submitStage != null && submitForm != null && context.getStage().equals(submitStage) && getFormLinked()
426 .equals(submitForm.toString()));
427 }
428 }
429
430
431
432
433 protected boolean hasValue()
434 {
435 return this.value != null;
436 }
437
438
439
440
441
442
443 public void initialize(String id, Entity parentType, String parentID, boolean formConfigurable,
444 boolean persistToRepository, boolean allowAnonymousAccess, ParameterScope parameterScope,
445 String defaultValue, String constraintDefinition, Map<String, IParameterValidator> validators,
446 List<IParameterRule<T>> rules) throws ParameterException
447 {
448
449 this.id = id.toLowerCase();
450 this.parentID = parentID.toLowerCase();
451 this.parentType = parentType;
452 this.allowAnonymous = allowAnonymousAccess;
453 this.persistToRepository = persistToRepository;
454 this.parameterScope = parameterScope;
455 this.formConfigurable = formConfigurable;
456
457 if (validators == null)
458 this.validators = new HashMap<String, IParameterValidator>();
459 else
460 this.validators = validators;
461
462 if (rules == null)
463 this.rules = new ArrayList<IParameterRule<T>>();
464 else
465 this.rules = rules;
466
467 this.constraints = new HashMap<String, IParameterConstraint>();
468
469
470 if (!"".equals(automaticConstraints()))
471 {
472 if (constraintDefinition == null || "".equals(constraintDefinition))
473 constraintDefinition = automaticConstraints();
474 else
475 constraintDefinition = automaticConstraints() + "," + constraintDefinition;
476 }
477
478
479 if (constraintDefinition != null && !"".equals(constraintDefinition))
480 {
481
482 String[] constraintStrings = constraintDefinition.split(",");
483
484
485 for (String constraintString: constraintStrings)
486 {
487 String constraintID;
488 int posEqual = constraintString.indexOf("=");
489
490 constraintID = (posEqual == -1 ? constraintString : constraintString.substring(0, posEqual));
491 constraintID = constraintID.trim().toLowerCase();
492
493
494
495
496 if (constraintID.equals("readonly"))
497 this.readonly = true;
498 else if (constraintID.equals("required"))
499
500 this.required = true;
501 else
502 {
503 IParameterConstraint constraint = DIFIoCRegistry.getRegistry().getImplementation(
504 IParameterConstraint.class, constraintID);
505
506 if (constraint == null)
507 {
508
509 throw new ParameterException("Inexistant constraint \"" + constraintID + "\"", this);
510 }
511 else
512 {
513 constraint.configureConstraint(constraintString);
514 constraints.put(constraintID, constraint);
515 }
516 }
517 }
518 }
519
520 if (defaultValue != null && !"".equals(defaultValue))
521 {
522 setValueFromString(defaultValue, null);
523 this.defaultValue = value;
524 }
525
526 if (persistToRepository)
527 {
528
529 }
530 }
531
532
533
534
535 public boolean isAllowAnonymous()
536 {
537 return allowAnonymous;
538 }
539
540
541
542
543
544
545 public boolean isFirstInitialization()
546 {
547 return firstInitialization;
548 }
549
550
551
552
553 public boolean isFormConfigurable()
554 {
555 return formConfigurable && StringUtils.isNotBlank(this.getFormLinked());
556 }
557
558
559
560
561 public boolean isPersistToRepository()
562 {
563 return persistToRepository;
564 }
565
566
567
568
569 public boolean isReadonly()
570 {
571 return readonly;
572 }
573
574
575
576
577 public boolean isReferencedInARuleFromAnotherParameter()
578 {
579 return referencedInARuleFromAnotherParameter;
580 }
581
582
583
584
585 public boolean isRequired()
586 {
587 return required;
588 }
589
590
591
592
593 public boolean isStringSetterSupported()
594 {
595 return true;
596 }
597
598
599
600
601
602
603
604 protected void logWarning(String warning)
605 {
606
607 if (DIFLogger.getLogger().isDebugEnabled())
608 DIFLogger.getLogger().warn(getDebugPrefix() + warning + "\n" + this.toString());
609 else
610 DIFLogger.getLogger().warn(getDebugPrefix() + warning);
611 }
612
613
614
615
616 @SuppressWarnings("unchecked")
617 public ParameterErrorList refreshParameterValue(IStageInstance stageInstance)
618 {
619 IDIFContext context = (stageInstance == null ? null : stageInstance.getContext());
620
621 if (context == null)
622 return new ParameterErrorList(this, null);
623 else
624 {
625 String language = context.getLanguage();
626 ParameterErrorList list = new ParameterErrorList(this, null);
627
628
629 Object requestValue = context.getRequest().getParameter(getId());
630 boolean parameterExistsInRequest = context.getRequest().getParameters().containsKey(getId());
631
632
633
634
635
636
637
638
639
640
641 if (requestValue == null && !parameterExistsInRequest)
642 {
643 if (getParameterScope().equals(ParameterScope.SESSION))
644 {
645
646
647 IDIFSession session = context.getSession();
648
649 if (session == null)
650 {
651 ParameterError error = new ParameterError(getMessages().getMessages(language).get("noSession"),
652 ParameterErrorType.NO_SESSION);
653 list.addError(error);
654 }
655 else if (session.containsAttribute(getId()))
656 {
657
658 Object sessionValue = session.getAttribute(getId());
659
660
661 logger.debug(getDebugPrefix() + "Setting to \"" + sessionValue + "\" (read from Session)");
662
663 requestValue = sessionValue;
664 }
665 }
666 else if (getParameterScope().equals(ParameterScope.USER))
667 {
668
669
670
671 IDIFSession session = context.getSession();
672
673 if (session == null)
674 {
675 ParameterError error = new ParameterError(getMessages().getMessages(language).get("noSession"),
676 ParameterErrorType.NO_SESSION);
677 list.addError(error);
678 }
679 else
680 {
681
682 IDIFUser user = session.getUser();
683
684 if (user == null && !allowAnonymous)
685 {
686 ParameterError error = new ParameterError(
687 getMessages().getMessages(language).get("noUser"), ParameterErrorType.NO_USER);
688 list.addError(error);
689 }
690 else if (user != null && user.containsParameter(getId()))
691 {
692
693 requestValue = user.getParameter(getId());
694
695 logger.debug(getDebugPrefix() + "Setting to \"" + requestValue + "\" (read from User)");
696 }
697 }
698 }
699 }
700
701
702
703
704
705
706
707
708 if (requestValue == null)
709 {
710
711 if (isRequired() && !isReferencedInARuleFromAnotherParameter())
712 {
713
714
715 ParameterError error = new ParameterError(getMessages().getMessages(language).get("required"),
716 ParameterErrorType.MISSING);
717 list.addError(error);
718 list.addErrorList(setValue(null, stageInstance, true).getErrorList());
719 }
720 else
721 {
722 if (!parameterExistsInRequest
723 && (this.getParameterScope() != ParameterScope.STATIC || this.isFirstInitialization()))
724 {
725
726 logger.debug(getDebugPrefix() + "No value passed - Setting to "
727 + (defaultValue == null ? "null" : "default \"" + defaultValue.toString() + "\""));
728 list.addErrorList(setDefaultValue(stageInstance, true).getErrorList());
729 }
730
731 this.setFirstInitialization(false);
732 }
733 }
734 else
735 {
736 logger.debug(getDebugPrefix() + "Setting to \"" + requestValue + "\" (read from request)");
737
738 if (isStringSetterSupported())
739 list.addErrorList(setValueFromString(this.convertObjectToString(requestValue), stageInstance, true)
740 .getErrorList());
741 else
742 list.addErrorList(setValue((T) requestValue, stageInstance, true).getErrorList());
743 }
744
745 return list;
746 }
747 }
748
749
750
751
752 public ParameterErrorList setDefaultValue(IStageInstance stageInstance)
753 {
754 return setDefaultValue(stageInstance, false);
755 }
756
757
758
759
760
761 public ParameterErrorList setDefaultValue(IStageInstance stageInstance, boolean initializationInProgress)
762 {
763 return setValue(defaultValue, stageInstance, initializationInProgress);
764 }
765
766
767
768
769
770
771
772 public void setFirstInitialization(boolean firstInitialization)
773 {
774 this.firstInitialization = firstInitialization;
775 }
776
777
778
779
780 public void setFormConfigurable(boolean formConfigurable)
781 {
782 this.formConfigurable = formConfigurable;
783 }
784
785
786
787
788 public void setFormLinked(String formLinked)
789 {
790 this.formLinked = formLinked;
791 }
792
793
794
795
796 public void setReferencedInARuleFromAnotherParameter(boolean referencedInARuleFromAnotherParameter)
797 {
798 this.referencedInARuleFromAnotherParameter = referencedInARuleFromAnotherParameter;
799 }
800
801
802
803
804 public void setRequired(boolean required)
805 {
806 this.required = required;
807 }
808
809
810
811
812
813
814
815
816
817
818
819 public ParameterErrorList setValue(T value, IStageInstance stageInstance)
820 {
821 return setValue(value, stageInstance, false);
822 }
823
824
825
826
827
828
829
830
831
832
833
834
835
836 public ParameterErrorList setValue(T value, IStageInstance stageInstance, boolean initializationInProgress)
837 {
838
839 ParameterErrorList list = new ParameterErrorList(this, value);
840 IDIFContext context;
841
842 if (stageInstance == null)
843 context = null;
844 else
845 context = stageInstance.getContext();
846
847
848 list = validateParameterValue(value, stageInstance, initializationInProgress);
849
850 if (context == null)
851
852
853 this.value = value;
854
855 else
856 {
857 if (parameterScope == ParameterScope.SESSION)
858 {
859 if (context.getSession() == null)
860 {
861 list.addError(new ParameterError(getMessages().getMessages(context.getLanguage()).get("noSession"),
862 ParameterErrorType.NO_SESSION));
863
864 this.value = null;
865 }
866 else
867 {
868 context.getSession().addAttribute(getId(), value);
869 }
870
871 }
872 else if (parameterScope == ParameterScope.USER)
873 {
874 if (context.getSession() == null || context.getSession().getUser() == null)
875 {
876 if (!allowAnonymous)
877 list.addError(new ParameterError(
878 getMessages().getMessages(context.getLanguage()).get("noUser"),
879 ParameterErrorType.NO_USER));
880
881 this.value = null;
882 }
883 else
884 {
885
886 context.getSession().getUser().setParameter(getId(), value);
887 }
888
889 }
890 else if (parameterScope == ParameterScope.REQUEST)
891 {
892
893 this.value = value;
894
895 }
896 else if (parameterScope == ParameterScope.STATIC)
897
898 this.value = value;
899
900 if (isPersistToRepository())
901 {
902
903 }
904 }
905
906 return list;
907 }
908
909
910
911
912
913 public final ParameterErrorList setValueFromString(String value, IStageInstance stageInstance)
914 {
915
916 return this.setValueFromString(value, stageInstance, false);
917 }
918
919
920
921
922 @Override
923 public String toString()
924 {
925 ObjectFormatter formatter = new ObjectFormatter();
926 formatter.addItem("ID", this.id);
927 formatter.addItem("Value", value);
928 formatter.addItem("Value Type", this.value == null ? "n/a" : this.value.getClass().getCanonicalName());
929 formatter.addItem("Parent", "(" + this.parentType + ") " + this.parentID);
930 formatter.addItem("Scope", this.parameterScope);
931 formatter.addItem("Persist", this.persistToRepository);
932 formatter.addItem("Readonly", this.readonly);
933 formatter.addItem("Required", this.required);
934 formatter.addItem("Default Value", this.defaultValue);
935 formatter.addItem("Link to Form", this.formLinked);
936 formatter.addItem("Form Configurable", this.formConfigurable);
937 formatter.addItem("Constraints", this.constraints);
938 formatter.addItem("Validators", this.validators);
939 formatter.addItem("Rules", this.rules);
940 formatter.addItem("Referenced in a rule from another parameter", this.referencedInARuleFromAnotherParameter);
941
942 return formatter.getFormatedObject();
943 }
944
945
946
947
948
949
950
951
952
953
954
955
956 protected ParameterErrorList validateParameterValue(T value, IStageInstance stageInstance,
957 boolean initializationInProgress)
958 {
959 ParameterErrorList list = new ParameterErrorList(this, value);
960 IDIFContext context;
961
962 if (stageInstance == null)
963 context = null;
964 else
965 context = stageInstance.getContext();
966
967
968 for (Entry<String, IParameterConstraint> constraintEntry: getConstraints().entrySet())
969 {
970
971 ParameterConstraintResult constraintResult = constraintEntry.getValue().getValidationResult(value,
972 stageInstance);
973 if (!constraintResult.isValid())
974 {
975 list.addError(new ParameterError(constraintEntry.getKey(), constraintResult));
976 }
977 }
978
979
980 for (Entry<String, IParameterValidator> validatorEntry: getValidators().entrySet())
981 {
982 if (!validatorEntry.getValue().validate(value, context))
983 {
984 ParameterError error = new ParameterError(validatorEntry.getValue().validationErrorMessage(
985 getLanguage(context)), ParameterErrorType.VALIDATOR);
986 error.setValidator(validatorEntry.getKey(), validatorEntry.getValue());
987
988 list.addError(error);
989 }
990 }
991
992
993 for (IParameterRule<T> rule: getRules())
994 {
995 ParameterRuleResult result;
996 try
997 {
998 result = rule.getValidationResult(stageInstance, value, initializationInProgress, this);
999
1000 if (!result.isValid())
1001 {
1002 ParameterError error = new ParameterError(result.getErrorMessage(), ParameterErrorType.RULE);
1003 error.setRule(rule);
1004
1005 list.addError(error);
1006 }
1007 }
1008 catch (ParameterException e)
1009 {
1010 ParameterError error = new ParameterError(e.getMessage(), ParameterErrorType.RULE);
1011 error.setRule(rule);
1012
1013 list.addError(error);
1014 }
1015
1016 }
1017
1018 return list;
1019 }
1020 }