1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kew.rule.web;
17
18 import org.apache.commons.beanutils.PropertyUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.apache.struts.action.ActionErrors;
21 import org.apache.struts.action.ActionMessage;
22 import org.kuali.rice.core.api.util.RiceConstants;
23 import org.kuali.rice.core.framework.persistence.jdbc.sql.SQLUtils;
24 import org.kuali.rice.kew.api.rule.RoleName;
25 import org.kuali.rice.kew.api.util.CodeTranslator;
26 import org.kuali.rice.kew.exception.WorkflowServiceError;
27 import org.kuali.rice.kew.rule.KeyValueId;
28 import org.kuali.rice.kew.rule.RoleAttribute;
29 import org.kuali.rice.kew.rule.RuleBaseValues;
30 import org.kuali.rice.kew.rule.RuleDelegationBo;
31 import org.kuali.rice.kew.rule.RuleExtensionBo;
32 import org.kuali.rice.kew.rule.RuleExtensionValue;
33 import org.kuali.rice.kew.rule.RuleResponsibilityBo;
34 import org.kuali.rice.kew.rule.WorkflowRuleAttribute;
35 import org.kuali.rice.kew.rule.bo.RuleAttribute;
36 import org.kuali.rice.kew.rule.bo.RuleTemplateAttributeBo;
37 import org.kuali.rice.kew.rule.bo.RuleTemplateBo;
38 import org.kuali.rice.kew.rule.service.RuleDelegationService;
39 import org.kuali.rice.kew.rule.service.RuleTemplateService;
40 import org.kuali.rice.kew.rule.xmlrouting.GenericXMLRuleAttribute;
41 import org.kuali.rice.kew.service.KEWServiceLocator;
42 import org.kuali.rice.kew.api.KewApiConstants;
43 import org.kuali.rice.kns.web.ui.Field;
44 import org.kuali.rice.kns.web.ui.Row;
45
46 import java.sql.Timestamp;
47 import java.text.ParseException;
48 import java.text.SimpleDateFormat;
49 import java.util.ArrayList;
50 import java.util.Calendar;
51 import java.util.Collection;
52 import java.util.Collections;
53 import java.util.Date;
54 import java.util.HashMap;
55 import java.util.Iterator;
56 import java.util.List;
57 import java.util.Map;
58
59
60
61
62
63
64
65
66
67 public class WebRuleBaseValues extends RuleBaseValues {
68
69 private static final long serialVersionUID = 5938997470219200474L;
70 private static final int TO_DATE_UPPER_LIMIT = 2100;
71 private List rows = new ArrayList();
72 private List fields = new ArrayList();
73 private List roles = new ArrayList();
74 private String fromDateString;
75 private String toDateString;
76 private String ruleTemplateName;
77 private boolean hasExtensionValueErrors = false;
78
79 public WebRuleBaseValues() {
80 }
81
82 public WebRuleBaseValues(RuleBaseValues rule) throws Exception {
83 edit(rule);
84 }
85
86 private void loadFields() {
87 fields.clear();
88 if (getRuleTemplateId() != null) {
89 RuleTemplateBo ruleTemplate = getRuleTemplateService().findByRuleTemplateId(getRuleTemplateId());
90 if (ruleTemplate != null) {
91 List ruleTemplateAttributes = ruleTemplate.getActiveRuleTemplateAttributes();
92 Collections.sort(ruleTemplateAttributes);
93 for (Iterator iter = ruleTemplateAttributes.iterator(); iter.hasNext();) {
94 RuleTemplateAttributeBo ruleTemplateAttribute = (RuleTemplateAttributeBo) iter.next();
95 if (!ruleTemplateAttribute.isWorkflowAttribute()) {
96 continue;
97 }
98 WorkflowRuleAttribute workflowAttribute = ruleTemplateAttribute.getWorkflowAttribute();
99 RuleAttribute ruleAttribute = ruleTemplateAttribute.getRuleAttribute();
100 if (ruleAttribute.getType().equals(KewApiConstants.RULE_XML_ATTRIBUTE_TYPE)) {
101 ((GenericXMLRuleAttribute) workflowAttribute).setExtensionDefinition(RuleAttribute.to(ruleAttribute));
102 }
103 for (Object element : workflowAttribute.getRuleRows()) {
104 Row row = (Row) element;
105 for (Object element2 : row.getFields()) {
106 Field field = (Field) element2;
107 String fieldValue = "";
108 RuleExtensionValue extensionValue = getRuleExtensionValue(ruleTemplateAttribute.getId(), field.getPropertyName());
109
110 fieldValue = (extensionValue != null) ? extensionValue.getValue() : field.getPropertyValue();
111 fields.add(new KeyValueId(field.getPropertyName(), fieldValue, ruleTemplateAttribute.getId()));
112 }
113 }
114 }
115 }
116 }
117 }
118
119 public void loadFieldsWithDefaultValues() {
120 fields.clear();
121 if (getRuleTemplateId() != null) {
122 RuleTemplateBo ruleTemplate = getRuleTemplateService().findByRuleTemplateId(getRuleTemplateId());
123 if (ruleTemplate != null) {
124 List ruleTemplateAttributes = ruleTemplate.getActiveRuleTemplateAttributes();
125 Collections.sort(ruleTemplateAttributes);
126 for (Iterator iter = ruleTemplateAttributes.iterator(); iter.hasNext();) {
127 RuleTemplateAttributeBo ruleTemplateAttribute = (RuleTemplateAttributeBo) iter.next();
128 if (!ruleTemplateAttribute.isWorkflowAttribute()) {
129 continue;
130 }
131 WorkflowRuleAttribute workflowAttribute = ruleTemplateAttribute.getWorkflowAttribute();
132 RuleAttribute ruleAttribute = ruleTemplateAttribute.getRuleAttribute();
133 if (ruleAttribute.getType().equals(KewApiConstants.RULE_XML_ATTRIBUTE_TYPE)) {
134 ((GenericXMLRuleAttribute) workflowAttribute).setExtensionDefinition(RuleAttribute.to(ruleAttribute));
135 }
136 for (Object element : workflowAttribute.getRuleRows()) {
137 Row row = (Row) element;
138 for (Object element2 : row.getFields()) {
139 Field field = (Field) element2;
140 fields.add(new KeyValueId(field.getPropertyName(), field.getPropertyValue(), ruleTemplateAttribute.getId() + ""));
141 }
142 }
143 }
144 }
145 }
146 }
147
148 private void loadWebValues() {
149 loadRows();
150 loadDates();
151 loadRuleTemplateName();
152 }
153
154 private void loadRows() {
155 getRoles().clear();
156 if (getRuleTemplateId() != null) {
157 RuleTemplateBo ruleTemplate = getRuleTemplateService().findByRuleTemplateId(getRuleTemplateId());
158 if (ruleTemplate != null) {
159 setRuleTemplateName(ruleTemplate.getName());
160 List<RuleTemplateAttributeBo> ruleTemplateAttributes = ruleTemplate.getActiveRuleTemplateAttributes();
161 Collections.sort(ruleTemplateAttributes);
162 List<Row> rows = new ArrayList<Row>();
163 for (RuleTemplateAttributeBo ruleTemplateAttribute : ruleTemplateAttributes) {
164 if (!ruleTemplateAttribute.isWorkflowAttribute()) {
165 continue;
166 }
167 WorkflowRuleAttribute workflowAttribute = ruleTemplateAttribute.getWorkflowAttribute();
168
169 RuleAttribute ruleAttribute = ruleTemplateAttribute.getRuleAttribute();
170 if (ruleAttribute.getType().equals(KewApiConstants.RULE_XML_ATTRIBUTE_TYPE)) {
171 ((GenericXMLRuleAttribute) workflowAttribute).setExtensionDefinition(RuleAttribute.to(ruleAttribute));
172 }
173 workflowAttribute.validateRuleData(getFieldMap(ruleTemplateAttribute.getId()+""));
174 rows.addAll(workflowAttribute.getRuleRows());
175 if (workflowAttribute instanceof RoleAttribute) {
176 RoleAttribute roleAttribute = (RoleAttribute) workflowAttribute;
177 getRoles().addAll(roleAttribute.getRoleNames());
178 }
179 }
180 setRows(rows);
181 }
182 }
183 }
184
185 private void loadDates() {
186 if (getFromDateString() != null) {
187 setFromDateString(RiceConstants.getDefaultDateFormat().format(getFromDateValue()));
188 }
189 if (getToDateString() != null) {
190 setToDateString(RiceConstants.getDefaultDateFormat().format(getToDateValue()));
191 }
192 }
193
194 private void loadRuleTemplateName() {
195 if (org.apache.commons.lang.StringUtils.isEmpty(getRuleTemplateName()) && getRuleTemplateId() != null) {
196 RuleTemplateBo ruleTemplate = getRuleTemplateService().findByRuleTemplateId(getRuleTemplateId());
197 if (ruleTemplate != null) {
198 setRuleTemplateName(ruleTemplate.getName());
199 }
200 }
201 }
202
203 public List getFields() {
204 return fields;
205 }
206
207 public void setFields(List fields) {
208 this.fields = fields;
209 }
210
211 public KeyValueId getField(int index) {
212 while (getFields().size() <= index) {
213 KeyValueId field = new KeyValueId();
214 getFields().add(field);
215 }
216 return (KeyValueId) getFields().get(index);
217 }
218
219 public String getFromDateString() {
220 return fromDateString;
221 }
222
223 public void setFromDateString(String fromDateString) {
224 this.fromDateString = fromDateString;
225 }
226
227 public List<RoleName> getRoles() {
228 return roles;
229 }
230
231 public void setRoles(List<RoleName> roles) {
232 this.roles = roles;
233 }
234
235 public List<RoleName> getRows() {
236 return rows;
237 }
238
239 public void setRows(List ruleTemplateAttributes) {
240 this.rows = ruleTemplateAttributes;
241 }
242
243 @Override
244 public String getToDateString() {
245 return this.toDateString;
246 }
247
248 public void setToDateString(String toDateString) {
249 this.toDateString = toDateString;
250 }
251
252 @Override
253 public String getRuleTemplateName() {
254 return ruleTemplateName;
255 }
256
257 public void setRuleTemplateName(String ruleTemplateName) {
258 this.ruleTemplateName = ruleTemplateName;
259 }
260
261 public boolean isHasExtensionValueErrors() {
262 return hasExtensionValueErrors;
263 }
264
265 public void setHasExtensionValueErrors(boolean hasRuleExtensionValueErrors) {
266 this.hasExtensionValueErrors = hasRuleExtensionValueErrors;
267 }
268
269
270
271
272
273
274 public void edit(RuleBaseValues rule) throws Exception {
275 load(rule);
276 initialize();
277 }
278
279
280
281
282 public void load(RuleBaseValues rule) throws Exception {
283 PropertyUtils.copyProperties(this, rule);
284 injectWebMembers();
285 }
286
287 public void initialize() throws Exception {
288 loadFields();
289
290 for (Object element : getRuleResponsibilities()) {
291 WebRuleResponsibility responsibility = (WebRuleResponsibility) element;
292 responsibility.initialize();
293 }
294 establishRequiredState();
295 }
296
297 private void injectWebMembers() throws Exception {
298 List currentResponsibilities = getRuleResponsibilities();
299 setRuleResponsibilities(new ArrayList());
300 for (Iterator iterator = currentResponsibilities.iterator(); iterator.hasNext();) {
301 RuleResponsibilityBo responsibility = (RuleResponsibilityBo) iterator.next();
302 WebRuleResponsibility webResponsibility = createNewRuleResponsibility();
303 webResponsibility.load(responsibility);
304 }
305 }
306
307
308
309
310 public void establishRequiredState() throws Exception {
311 loadWebValues();
312 if (getRuleResponsibilities().isEmpty()) {
313 createNewRuleResponsibility();
314 }
315 for (Object element : getRuleResponsibilities()) {
316 WebRuleResponsibility responsibility = (WebRuleResponsibility) element;
317 responsibility.establishRequiredState();
318 }
319 }
320
321 @Override
322 public RuleResponsibilityBo getResponsibility(int index) {
323 while (getRuleResponsibilities().size() <= index) {
324 createNewRuleResponsibility();
325 }
326 return getRuleResponsibilities().get(index);
327 }
328
329 public int getResponsibilitiesSize() {
330 return getRuleResponsibilities().size();
331 }
332
333 public WebRuleResponsibility createNewRuleResponsibility() {
334 WebRuleResponsibility responsibility = new WebRuleResponsibility();
335 responsibility.setRuleBaseValues(this);
336 addRuleResponsibility(responsibility);
337 return responsibility;
338 }
339
340 public Map getFieldMap(String ruleTemplateAttributeId) {
341 Map fieldMap = new HashMap();
342 for (Iterator iterator = getFields().iterator(); iterator.hasNext();) {
343 KeyValueId field = (KeyValueId) iterator.next();
344 if (ruleTemplateAttributeId.equals(field.getId())) {
345 fieldMap.put(field.getKey(), field.getValue());
346 }
347 }
348 return fieldMap;
349 }
350
351 public void populatePreviousRuleIds() {
352 if (getPreviousRuleId() == null) {
353 setPreviousRuleId(getId());
354 }
355 for (Object element : getRuleResponsibilities()) {
356 WebRuleResponsibility responsibility = (WebRuleResponsibility) element;
357 responsibility.populatePreviousRuleIds();
358 }
359 }
360
361
362
363
364 public void materialize() {
365 if (getRuleTemplate() == null && getRuleTemplateId() != null) {
366 setRuleTemplate(getRuleTemplateService().findByRuleTemplateId(getRuleTemplateId()));
367 }
368 }
369
370 public void validateRule(String keyPrefix, ActionErrors errors) {
371
372 if (getRuleTemplateId() == null) {
373 errors.add(keyPrefix + "ruleTemplateId", new ActionMessage("routetemplate.required.html", "rule template"));
374 } else {
375 List errorList = new ArrayList();
376 populateRuleExtensionValues(errorList);
377 saveServiceErrors(keyPrefix + "ruleExtensionValues", errorList, errors);
378 if (!errorList.isEmpty()) {
379 setHasExtensionValueErrors(true);
380 }
381 }
382
383
384
385 boolean dateParseProblem = false;
386 try {
387 setToDateValue(decodeTimestamp(getToDateString()));
388 } catch (ParseException e) {
389 errors.add(keyPrefix + "toDateValue", new ActionMessage("routetemplate.required.html", "to date (MM/DD/YYYY)"));
390 dateParseProblem = true;
391 }
392 try {
393 setFromDateValue(decodeTimestamp(getFromDateString()));
394 } catch (ParseException e) {
395 errors.add(keyPrefix + "fromDateValue", new ActionMessage("routetemplate.required.html", "from date (MM/DD/YYYY)"));
396 dateParseProblem = true;
397 }
398 throttleDates();
399 if (getFromDateValue() == null) {
400 setFromDateValue(new Timestamp(new Date().getTime()));
401 }
402 if (getToDateValue() == null) {
403 try {
404 setToDateValue(new Timestamp(new SimpleDateFormat("MM/dd/yyyy").parse("01/01/2100").getTime()));
405 } catch (ParseException e) {
406 errors.add(keyPrefix + "toDateValue", new ActionMessage("routetemplate.required.html", "to date"));
407 dateParseProblem = true;
408 }
409 }
410 if (!dateParseProblem && getToDateValue().before(getFromDateValue())) {
411 errors.add(keyPrefix + "toDateValue", new ActionMessage("routetemplate.ruleservice.daterange.fromafterto"));
412 }
413
414 if (org.apache.commons.lang.StringUtils.isEmpty(getDescription())) {
415 errors.add(keyPrefix + "description", new ActionMessage("routetemplate.ruleservice.description.required"));
416 }
417
418 if (getRuleResponsibilities().isEmpty()) {
419 errors.add(keyPrefix + "responsibilities", new ActionMessage("routetemplate.ruleservice.responsibility.required"));
420 }
421
422 int respIndex = 0;
423 for (Object element : getRuleResponsibilities()) {
424 WebRuleResponsibility responsibility = (WebRuleResponsibility) element;
425 String respPrefix = keyPrefix + "responsibility[" + respIndex + "].";
426 responsibility.validateResponsibility(respPrefix, errors);
427 respIndex++;
428 }
429 }
430
431
432
433
434
435 private void throttleDates() {
436 if (getToDateValue() != null) {
437 Calendar calendar = Calendar.getInstance();
438 calendar.setTime(getToDateValue());
439 if (calendar.get(Calendar.YEAR) > TO_DATE_UPPER_LIMIT) {
440 calendar.set(Calendar.YEAR, TO_DATE_UPPER_LIMIT);
441 setToDateValue(new Timestamp(calendar.getTimeInMillis()));
442 setToDateString(new SimpleDateFormat("MM/dd/yyyy").format(getToDateValue()));
443 }
444 }
445 }
446
447 private void saveServiceErrors(String errorKey, Collection srvErrors, ActionErrors errors) {
448 for (Iterator iterator = srvErrors.iterator(); iterator.hasNext();) {
449 WorkflowServiceError error = (WorkflowServiceError) iterator.next();
450 if (error.getArg1() == null && error.getArg2() == null) {
451 errors.add(errorKey, new ActionMessage(error.getKey()));
452 } else if (error.getArg1() != null && error.getArg2() == null) {
453 errors.add(errorKey, new ActionMessage(error.getKey(), error.getArg1()));
454 } else {
455 errors.add(errorKey, new ActionMessage(error.getKey(), error.getArg1(), error.getArg2()));
456 }
457 }
458 }
459
460 private Timestamp decodeTimestamp(String dateValue) throws ParseException {
461 if (org.apache.commons.lang.StringUtils.isEmpty(dateValue)) {
462 return null;
463 }
464
465
466
467 String convertedDate = SQLUtils.getEntryFormattedDate(dateValue);
468 if (convertedDate == null) {
469 throw new ParseException("Date entered as '" + dateValue + "' is in invalid format", 0);
470 }
471 Date date = RiceConstants.getDefaultDateFormat().parse(convertedDate);
472 return new Timestamp(date.getTime());
473 }
474
475 private void populateRuleExtensionValues(List errorList) {
476 RuleTemplateBo ruleTemplate = getRuleTemplateService().findByRuleTemplateId(getRuleTemplateId());
477 setRuleTemplate(ruleTemplate);
478
479
480 List extensions = new ArrayList();
481 for (Object element : ruleTemplate.getActiveRuleTemplateAttributes()) {
482 RuleTemplateAttributeBo ruleTemplateAttribute = (RuleTemplateAttributeBo) element;
483 if (!ruleTemplateAttribute.isWorkflowAttribute()) {
484 continue;
485 }
486 WorkflowRuleAttribute workflowAttribute = ruleTemplateAttribute.getWorkflowAttribute();
487
488 RuleAttribute ruleAttribute = ruleTemplateAttribute.getRuleAttribute();
489 if (ruleAttribute.getType().equals(KewApiConstants.RULE_XML_ATTRIBUTE_TYPE)) {
490 ((GenericXMLRuleAttribute) workflowAttribute).setExtensionDefinition(RuleAttribute.to(ruleAttribute));
491 }
492
493 List attValidationErrors = workflowAttribute.validateRuleData(getFieldMap(ruleTemplateAttribute.getId()+""));
494 if (attValidationErrors != null && !attValidationErrors.isEmpty()) {
495 errorList.addAll(attValidationErrors);
496 } else {
497 List ruleExtensionValues = workflowAttribute.getRuleExtensionValues();
498 if (ruleExtensionValues != null && !ruleExtensionValues.isEmpty()) {
499 RuleExtensionBo ruleExtension = new RuleExtensionBo();
500 ruleExtension.setRuleTemplateAttributeId(ruleTemplateAttribute.getId());
501
502 ruleExtension.setExtensionValues(ruleExtensionValues);
503 extensions.add(ruleExtension);
504 }
505 }
506 }
507 setRuleExtensions(extensions);
508 setRuleTemplate(ruleTemplate);
509
510 for (Object element : getRuleExtensions()) {
511 RuleExtensionBo ruleExtension = (RuleExtensionBo) element;
512 ruleExtension.setRuleBaseValues(this);
513
514 for (Object element2 : ruleTemplate.getActiveRuleTemplateAttributes()) {
515 RuleTemplateAttributeBo ruleTemplateAttribute = (RuleTemplateAttributeBo) element2;
516 if (StringUtils.equals(ruleTemplateAttribute.getId(), ruleExtension.getRuleTemplateAttributeId())) {
517 ruleExtension.setRuleTemplateAttribute(ruleTemplateAttribute);
518 break;
519 }
520 }
521
522 for (Object element2 : ruleExtension.getExtensionValues()) {
523 RuleExtensionValue ruleExtensionValue = (RuleExtensionValue) element2;
524 ruleExtensionValue.setExtension(ruleExtension);
525 }
526 }
527
528 }
529
530 private RuleTemplateService getRuleTemplateService() {
531 return (RuleTemplateService) KEWServiceLocator.getService(KEWServiceLocator.RULE_TEMPLATE_SERVICE);
532 }
533
534
535
536
537 public Map getActionRequestCodes() {
538 Map actionRequestCodes = new HashMap();
539 actionRequestCodes.putAll(CodeTranslator.arLabels);
540 if (getRuleTemplateId() != null) {
541 RuleTemplateBo ruleTemplate = getRuleTemplateService().findByRuleTemplateId(getRuleTemplateId());
542 if (ruleTemplate != null) {
543 if (ruleTemplate.getAcknowledge() != null && "false".equals(ruleTemplate.getAcknowledge().getValue())) {
544 actionRequestCodes.remove(KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ);
545 }
546 if (ruleTemplate.getComplete() != null && "false".equals(ruleTemplate.getComplete().getValue())) {
547 actionRequestCodes.remove(KewApiConstants.ACTION_REQUEST_COMPLETE_REQ);
548 }
549 if (ruleTemplate.getApprove() != null && "false".equals(ruleTemplate.getApprove().getValue())) {
550 actionRequestCodes.remove(KewApiConstants.ACTION_REQUEST_APPROVE_REQ);
551 }
552 if (ruleTemplate.getFyi() != null && "false".equals(ruleTemplate.getFyi().getValue())) {
553 actionRequestCodes.remove(KewApiConstants.ACTION_REQUEST_FYI_REQ);
554 }
555 }
556 }
557 return actionRequestCodes;
558 }
559
560 public RuleDelegationBo getRuleDelegation() {
561 if (getDelegateRule().booleanValue()) {
562 List ruleDelegations = getRuleDelegationService().findByDelegateRuleId(getId());
563 RuleDelegationBo currentRuleDelegation = (RuleDelegationBo) ruleDelegations.get(0);
564 RuleBaseValues mostRecentRule = currentRuleDelegation.getRuleResponsibility().getRuleBaseValues();
565
566 for (Iterator iter = ruleDelegations.iterator(); iter.hasNext();) {
567 RuleDelegationBo ruleDelegation = (RuleDelegationBo) iter.next();
568 RuleBaseValues parentRule = ruleDelegation.getRuleResponsibility().getRuleBaseValues();
569
570 if (parentRule.getActivationDate().after(mostRecentRule.getActivationDate())) {
571 mostRecentRule = ruleDelegation.getRuleResponsibility().getRuleBaseValues();
572 currentRuleDelegation = ruleDelegation;
573 }
574 }
575 return currentRuleDelegation;
576 }
577 return null;
578 }
579
580 public String getParentRuleId() {
581 if (getDelegateRule().booleanValue()) {
582 List ruleDelegations = getRuleDelegationService().findByDelegateRuleId(getId());
583 RuleDelegationBo currentRuleDelegation = (RuleDelegationBo) ruleDelegations.get(0);
584 RuleBaseValues mostRecentRule = currentRuleDelegation.getRuleResponsibility().getRuleBaseValues();
585
586 for (Iterator iter = ruleDelegations.iterator(); iter.hasNext();) {
587 RuleDelegationBo ruleDelegation = (RuleDelegationBo) iter.next();
588 RuleBaseValues parentRule = ruleDelegation.getRuleResponsibility().getRuleBaseValues();
589
590 if (parentRule.getActivationDate().after(mostRecentRule.getActivationDate())) {
591 mostRecentRule = ruleDelegation.getRuleResponsibility().getRuleBaseValues();
592 }
593 }
594 return mostRecentRule.getId();
595 }
596 return null;
597 }
598
599 private RuleDelegationService getRuleDelegationService() {
600 return (RuleDelegationService) KEWServiceLocator.getService(KEWServiceLocator.RULE_DELEGATION_SERVICE);
601 }
602 }