1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.datadictionary.validation.processor;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.apache.log4j.Logger;
20 import org.kuali.rice.core.api.CoreApiServiceLocator;
21 import org.kuali.rice.core.api.search.SearchOperator;
22 import org.kuali.rice.core.api.util.ClassLoaderUtils;
23 import org.kuali.rice.core.api.util.RiceKeyConstants;
24 import org.kuali.rice.core.web.format.DateFormatter;
25 import org.kuali.rice.krad.datadictionary.exception.AttributeValidationException;
26 import org.kuali.rice.krad.datadictionary.validation.AttributeValueReader;
27 import org.kuali.rice.krad.datadictionary.validation.ValidationUtils;
28 import org.kuali.rice.krad.datadictionary.validation.capability.Constrainable;
29 import org.kuali.rice.krad.datadictionary.validation.capability.Formatable;
30 import org.kuali.rice.krad.datadictionary.validation.constraint.Constraint;
31 import org.kuali.rice.krad.datadictionary.validation.constraint.ValidCharactersConstraint;
32 import org.kuali.rice.krad.datadictionary.validation.result.ConstraintValidationResult;
33 import org.kuali.rice.krad.datadictionary.validation.result.DictionaryValidationResult;
34 import org.kuali.rice.krad.datadictionary.validation.result.ProcessorResult;
35 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
36 import org.kuali.rice.krad.util.KRADConstants;
37
38 import java.lang.reflect.Method;
39 import java.util.List;
40
41
42
43
44
45
46
47 public class ValidCharactersConstraintProcessor extends MandatoryElementConstraintProcessor<ValidCharactersConstraint> {
48
49 public static final String VALIDATE_METHOD = "validate";
50
51 private static final Logger LOG = Logger.getLogger(ValidCharactersConstraintProcessor.class);
52 private static final String[] DATE_RANGE_ERROR_PREFIXES = { KRADConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX, KRADConstants.LOOKUP_RANGE_UPPER_BOUND_PROPERTY_PREFIX };
53
54 private static final String CONSTRAINT_NAME = "valid characters constraint";
55
56
57
58
59 @Override
60 public ProcessorResult process(DictionaryValidationResult result, Object value, ValidCharactersConstraint constraint, AttributeValueReader attributeValueReader) throws AttributeValidationException {
61
62 return new ProcessorResult(processSingleValidCharacterConstraint(result, value, constraint, attributeValueReader));
63 }
64
65 @Override
66 public String getName() {
67 return CONSTRAINT_NAME;
68 }
69
70
71
72
73 @Override
74 public Class<? extends Constraint> getConstraintType() {
75 return ValidCharactersConstraint.class;
76 }
77
78
79 protected ConstraintValidationResult processSingleValidCharacterConstraint(DictionaryValidationResult result, Object value, ValidCharactersConstraint constraint, AttributeValueReader attributeValueReader) throws AttributeValidationException {
80
81 if (constraint == null)
82 return result.addNoConstraint(attributeValueReader, CONSTRAINT_NAME);
83
84 if (ValidationUtils.isNullOrEmpty(value))
85 return result.addSkipped(attributeValueReader, CONSTRAINT_NAME);
86
87
88
89 Constrainable definition = attributeValueReader.getDefinition(attributeValueReader.getAttributeName());
90 if (definition instanceof Formatable) {
91 return doProcessFormattableValidCharConstraint(result, constraint, (Formatable)definition, value, attributeValueReader);
92 }
93
94 ConstraintValidationResult constraintValidationResult = doProcessValidCharConstraint(constraint, value);
95 if (constraintValidationResult == null)
96 return result.addSuccess(attributeValueReader, CONSTRAINT_NAME);
97
98 result.addConstraintValidationResult(attributeValueReader, constraintValidationResult);
99 return constraintValidationResult;
100 }
101
102 protected ConstraintValidationResult doProcessFormattableValidCharConstraint(DictionaryValidationResult result, ValidCharactersConstraint validCharsConstraint, Formatable definition, Object value, AttributeValueReader attributeValueReader) throws AttributeValidationException {
103 String entryName = attributeValueReader.getEntryName();
104 String attributeName = attributeValueReader.getAttributeName();
105
106
107 List<String> parsedAttributeValues = attributeValueReader.getCleanSearchableValues(attributeName);
108
109 if (parsedAttributeValues != null) {
110
111 Class<?> formatterClass = null;
112 Boolean doValidateDateRangeOrder = null;
113
114
115 if (parsedAttributeValues.size() != 2)
116 doValidateDateRangeOrder = Boolean.FALSE;
117
118
119 for (int i=0;i<parsedAttributeValues.size();i++) {
120 String parsedAttributeValue = parsedAttributeValues.get(i);
121
122 ConstraintValidationResult constraintValidationResult = doProcessValidCharConstraint(validCharsConstraint, parsedAttributeValue);
123
124
125 if (constraintValidationResult != null) {
126
127 if (formatterClass == null) {
128 String formatterClassName = definition.getFormatterClass();
129 if (formatterClassName != null)
130 formatterClass = ClassLoaderUtils.getClass(formatterClassName);
131 }
132
133 if (formatterClass != null) {
134
135 if (doValidateDateRangeOrder == null) {
136
137 doValidateDateRangeOrder = Boolean.valueOf(DateFormatter.class.isAssignableFrom(formatterClass) && StringUtils.contains(ValidationUtils.getString(value), SearchOperator
138 .BETWEEN.toString()));
139 }
140
141 constraintValidationResult = processFormatterValidation(result, formatterClass, entryName, attributeName, parsedAttributeValue, DATE_RANGE_ERROR_PREFIXES[i]);
142
143 if (constraintValidationResult != null) {
144 result.addConstraintValidationResult(attributeValueReader, constraintValidationResult);
145 return constraintValidationResult;
146 }
147 } else {
148
149 result.addConstraintValidationResult(attributeValueReader, constraintValidationResult);
150 return constraintValidationResult;
151 }
152 }
153 }
154
155 if (doValidateDateRangeOrder != null && doValidateDateRangeOrder.booleanValue()) {
156 ConstraintValidationResult dateOrderValidationResult = validateDateOrder(parsedAttributeValues.get(0), parsedAttributeValues.get(1), entryName, attributeName);
157
158 if (dateOrderValidationResult != null) {
159 result.addConstraintValidationResult(attributeValueReader, dateOrderValidationResult);
160 return dateOrderValidationResult;
161 }
162 }
163
164 return result.addSuccess(attributeValueReader, CONSTRAINT_NAME);
165 }
166 return result.addSkipped(attributeValueReader, CONSTRAINT_NAME);
167 }
168
169 protected ConstraintValidationResult doProcessValidCharConstraint(ValidCharactersConstraint validCharsConstraint, Object value) {
170
171 StringBuilder fieldValue = new StringBuilder();
172 String validChars = validCharsConstraint.getValue();
173
174 fieldValue.append(ValidationUtils.getString(value));
175
176
177
178
179
180
181
182
183
184
185
186 if (!fieldValue.toString().matches(validChars)) {
187 ConstraintValidationResult constraintValidationResult = new ConstraintValidationResult(CONSTRAINT_NAME);
188 if (validCharsConstraint.getLabelKey() != null) {
189
190 constraintValidationResult.setError(RiceKeyConstants.ERROR_CUSTOM, validCharsConstraint.getLabelKey());
191 return constraintValidationResult;
192 }
193
194 constraintValidationResult.setError(RiceKeyConstants.ERROR_INVALID_FORMAT, fieldValue.toString());
195 return constraintValidationResult;
196 }
197
198
199 return null;
200 }
201
202 protected ConstraintValidationResult processFormatterValidation(DictionaryValidationResult result, Class<?> formatterClass, String entryName, String attributeName, String parsedAttributeValue, String errorKeyPrefix) {
203
204 boolean isError = false;
205
206 try {
207 Method validatorMethod = formatterClass.getDeclaredMethod(VALIDATE_METHOD, new Class<?>[] {String.class});
208 Object o = validatorMethod.invoke(formatterClass.newInstance(), parsedAttributeValue);
209 if (o instanceof Boolean) {
210 isError = !((Boolean)o).booleanValue();
211 }
212 } catch (Exception e) {
213 if ( LOG.isDebugEnabled() )
214 LOG.debug(e.getMessage(), e);
215
216 isError = true;
217 }
218
219 if (isError) {
220 String errorMessageKey = getDataDictionaryService().getAttributeValidatingErrorMessageKey(entryName, attributeName);
221 String[] errorMessageParameters = getDataDictionaryService().getAttributeValidatingErrorMessageParameters(entryName, attributeName);
222
223 ConstraintValidationResult constraintValidationResult = new ConstraintValidationResult(CONSTRAINT_NAME);
224 constraintValidationResult.setEntryName(entryName);
225 constraintValidationResult.setAttributeName(errorKeyPrefix + attributeName);
226 constraintValidationResult.setError(errorMessageKey, errorMessageParameters);
227
228 return constraintValidationResult;
229 }
230
231 return null;
232 }
233
234 protected ConstraintValidationResult validateDateOrder(String firstDateTime, String secondDateTime, String entryName, String attributeName) {
235
236 java.sql.Timestamp lVal = null;
237 java.sql.Timestamp uVal = null;
238 try {
239 lVal = CoreApiServiceLocator.getDateTimeService().convertToSqlTimestamp(firstDateTime);
240 uVal = CoreApiServiceLocator.getDateTimeService().convertToSqlTimestamp(secondDateTime);
241 } catch (Exception ex){
242
243 String errorMessageKey = KRADServiceLocatorWeb.getDataDictionaryService().getAttributeValidatingErrorMessageKey(entryName, attributeName);
244 String[] errorMessageParameters = KRADServiceLocatorWeb.getDataDictionaryService().getAttributeValidatingErrorMessageParameters(entryName, attributeName);
245 ConstraintValidationResult constraintValidationResult = new ConstraintValidationResult(CONSTRAINT_NAME);
246 constraintValidationResult.setEntryName(entryName);
247 constraintValidationResult.setAttributeName(
248 KRADConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX + attributeName);
249 constraintValidationResult.setError(errorMessageKey, errorMessageParameters);
250 return constraintValidationResult;
251 }
252
253 if (lVal != null && lVal.compareTo(uVal) > 0){
254 String errorMessageKey = KRADServiceLocatorWeb.getDataDictionaryService().getAttributeValidatingErrorMessageKey(entryName, attributeName);
255 String[] errorMessageParameters = KRADServiceLocatorWeb.getDataDictionaryService().getAttributeValidatingErrorMessageParameters(entryName, attributeName);
256 ConstraintValidationResult constraintValidationResult = new ConstraintValidationResult(CONSTRAINT_NAME);
257 constraintValidationResult.setEntryName(entryName);
258 constraintValidationResult.setAttributeName(
259 KRADConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX + attributeName);
260 constraintValidationResult.setError(errorMessageKey + ".range", errorMessageParameters);
261 return constraintValidationResult;
262 }
263
264 return null;
265 }
266
267 }