1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.kuali.rice.kew.rule.service.impl;
18
19 import org.apache.commons.beanutils.PropertyUtils;
20 import org.apache.commons.lang.ObjectUtils;
21 import org.apache.commons.lang.StringUtils;
22 import org.jdom.Element;
23 import org.kuali.rice.core.api.impex.ExportDataSet;
24 import org.kuali.rice.core.api.impex.xml.XmlConstants;
25 import org.kuali.rice.core.api.util.RiceConstants;
26 import org.kuali.rice.core.api.util.collect.CollectionUtils;
27 import org.kuali.rice.core.framework.services.CoreFrameworkServiceLocator;
28 import org.kuali.rice.kew.actionrequest.service.ActionRequestService;
29 import org.kuali.rice.kew.api.WorkflowDocument;
30 import org.kuali.rice.kew.api.WorkflowDocumentFactory;
31 import org.kuali.rice.kew.api.WorkflowRuntimeException;
32 import org.kuali.rice.kew.api.action.ActionRequestPolicy;
33 import org.kuali.rice.kew.api.validation.RuleValidationContext;
34 import org.kuali.rice.kew.api.validation.ValidationResults;
35 import org.kuali.rice.kew.doctype.bo.DocumentType;
36 import org.kuali.rice.kew.doctype.service.DocumentTypeService;
37 import org.kuali.rice.kew.exception.WorkflowServiceErrorException;
38 import org.kuali.rice.kew.exception.WorkflowServiceErrorImpl;
39 import org.kuali.rice.kew.responsibility.service.ResponsibilityIdService;
40 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
41 import org.kuali.rice.kew.routeheader.service.RouteHeaderService;
42 import org.kuali.rice.kew.rule.RuleBaseValues;
43 import org.kuali.rice.kew.rule.RuleDelegationBo;
44 import org.kuali.rice.kew.rule.RuleExtension;
45 import org.kuali.rice.kew.rule.RuleExtensionValue;
46 import org.kuali.rice.kew.rule.RuleResponsibilityBo;
47 import org.kuali.rice.kew.rule.RuleRoutingDefinition;
48 import org.kuali.rice.kew.rule.RuleValidationAttribute;
49 import org.kuali.rice.kew.rule.bo.RuleTemplateAttributeBo;
50 import org.kuali.rice.kew.rule.bo.RuleTemplateBo;
51 import org.kuali.rice.kew.rule.dao.RuleDAO;
52 import org.kuali.rice.kew.rule.dao.RuleResponsibilityDAO;
53 import org.kuali.rice.kew.rule.service.RuleDelegationService;
54 import org.kuali.rice.kew.rule.service.RuleServiceInternal;
55 import org.kuali.rice.kew.rule.service.RuleTemplateService;
56 import org.kuali.rice.kew.service.KEWServiceLocator;
57 import org.kuali.rice.kew.util.KEWConstants;
58 import org.kuali.rice.kew.util.PerformanceLogger;
59 import org.kuali.rice.kew.xml.RuleXmlParser;
60 import org.kuali.rice.kew.xml.export.RuleXmlExporter;
61 import org.kuali.rice.kim.api.group.Group;
62 import org.kuali.rice.kim.api.group.GroupService;
63 import org.kuali.rice.kim.api.identity.principal.PrincipalContract;
64 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
65 import org.kuali.rice.krad.UserSession;
66 import org.kuali.rice.krad.util.GlobalVariables;
67 import org.kuali.rice.krad.util.KRADConstants;
68
69 import java.io.InputStream;
70 import java.sql.Timestamp;
71 import java.text.ParseException;
72 import java.util.ArrayList;
73 import java.util.Collection;
74 import java.util.Collections;
75 import java.util.Comparator;
76 import java.util.HashMap;
77 import java.util.HashSet;
78 import java.util.Iterator;
79 import java.util.List;
80 import java.util.Map;
81 import java.util.Set;
82 import java.util.UUID;
83
84
85 public class RuleServiceInternalImpl implements RuleServiceInternal {
86
87 private static final String XML_PARSE_ERROR = "general.error.parsexml";
88
89 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(RuleServiceInternalImpl.class);
90
91 private RuleDAO ruleDAO;
92 private RuleResponsibilityDAO ruleResponsibilityDAO;
93
94 public RuleResponsibilityDAO getRuleResponsibilityDAO() {
95 return ruleResponsibilityDAO;
96 }
97
98 public RuleBaseValues getRuleByName(String name) {
99 return ruleDAO.findRuleBaseValuesByName(name);
100 }
101
102 public RuleBaseValues findDefaultRuleByRuleTemplateId(String ruleTemplateId){
103 return this.ruleDAO.findDefaultRuleByRuleTemplateId(ruleTemplateId);
104 }
105 public void setRuleResponsibilityDAO(RuleResponsibilityDAO ruleResponsibilityDAO) {
106 this.ruleResponsibilityDAO = ruleResponsibilityDAO;
107 }
108
109 public void save2(RuleBaseValues ruleBaseValues) throws Exception {
110 save2(ruleBaseValues, null, true);
111 }
112
113 public void save2(RuleBaseValues ruleBaseValues, RuleDelegationBo ruleDelegation, boolean saveDelegations) throws Exception {
114 if (ruleBaseValues.getPreviousVersionId() != null) {
115 RuleBaseValues oldRule = findRuleBaseValuesById(ruleBaseValues.getPreviousVersionId());
116 ruleBaseValues.setPreviousVersion(oldRule);
117 ruleBaseValues.setCurrentInd(Boolean.FALSE);
118 ruleBaseValues.setVersionNbr(getNextVersionNumber(oldRule));
119 }
120 if (ruleBaseValues.getVersionNbr() == null) {
121 ruleBaseValues.setVersionNbr(Integer.valueOf(0));
122 }
123 if (ruleBaseValues.getCurrentInd() == null) {
124 ruleBaseValues.setCurrentInd(Boolean.FALSE);
125 }
126
127
128 for (Object element : ruleBaseValues.getRuleResponsibilities()) {
129 RuleResponsibilityBo responsibility = (RuleResponsibilityBo) element;
130 if (responsibility.getResponsibilityId() == null) {
131 responsibility.setResponsibilityId(getResponsibilityIdService().getNewResponsibilityId());
132 }
133 if (saveDelegations) {
134 for (Object element2 : responsibility.getDelegationRules()) {
135 RuleDelegationBo localRuleDelegation = (RuleDelegationBo) element2;
136 save2(localRuleDelegation.getDelegationRule(), localRuleDelegation, true);
137 }
138 }
139 }
140 validate2(ruleBaseValues, ruleDelegation, null);
141 getRuleDAO().save(ruleBaseValues);
142 }
143
144 public void makeCurrent(String documentId) {
145 makeCurrent(findByDocumentId(documentId));
146 }
147
148 public void makeCurrent(List<RuleBaseValues> rules) {
149 PerformanceLogger performanceLogger = new PerformanceLogger();
150
151 boolean isGenerateRuleArs = true;
152 String generateRuleArs = CoreFrameworkServiceLocator.getParameterService().getParameterValueAsString(KEWConstants.KEW_NAMESPACE, KRADConstants.DetailTypes.RULE_DETAIL_TYPE, KEWConstants.RULE_GENERATE_ACTION_REQESTS_IND);
153 if (!StringUtils.isBlank(generateRuleArs)) {
154 isGenerateRuleArs = KEWConstants.YES_RULE_CHANGE_AR_GENERATION_VALUE.equalsIgnoreCase(generateRuleArs);
155 }
156 Set<String> responsibilityIds = new HashSet<String>();
157 Map<String, RuleBaseValues> rulesToSave = new HashMap<String, RuleBaseValues>();
158
159 Collections.sort(rules, new RuleDelegationSorter());
160 boolean delegateFirst = false;
161 for (RuleBaseValues rule : rules) {
162 performanceLogger.log("Preparing rule: " + rule.getDescription());
163
164 rule.setCurrentInd(Boolean.TRUE);
165 Timestamp date = new Timestamp(System.currentTimeMillis());
166 rule.setActivationDate(date);
167 try {
168 rule.setDeactivationDate(new Timestamp(RiceConstants.getDefaultDateFormat().parse("01/01/2100").getTime()));
169 } catch (Exception e) {
170 LOG.error("Parse Exception", e);
171 }
172 rulesToSave.put(rule.getId(), rule);
173 RuleBaseValues oldRule = rule.getPreviousVersion();
174 if (oldRule != null) {
175 performanceLogger.log("Setting previous rule: " + oldRule.getId() + " to non current.");
176
177 oldRule.setCurrentInd(Boolean.FALSE);
178 oldRule.setDeactivationDate(date);
179 rulesToSave.put(oldRule.getId(), oldRule);
180 if (!delegateFirst) {
181 responsibilityIds.addAll(getResponsibilityIdsFromGraph(oldRule, isGenerateRuleArs));
182 }
183
184 if (rule.getDelegateRule().booleanValue() && rule.getPreviousVersionId() != null) {
185 delegateFirst = true;
186 }
187
188 List<RuleBaseValues> oldDelegationRules = findOldDelegationRules(oldRule, rule, performanceLogger);
189 for (RuleBaseValues delegationRule : oldDelegationRules) {
190
191 performanceLogger.log("Setting previous delegation rule: " + delegationRule.getId() + "to non current.");
192
193 delegationRule.setCurrentInd(Boolean.FALSE);
194 rulesToSave.put(delegationRule.getId(), delegationRule);
195 responsibilityIds.addAll(getResponsibilityIdsFromGraph(delegationRule, isGenerateRuleArs));
196 }
197 }
198 for (Object element : rule.getRuleResponsibilities()) {
199 RuleResponsibilityBo responsibility = (RuleResponsibilityBo) element;
200 for (Object element2 : responsibility.getDelegationRules()) {
201 RuleDelegationBo delegation = (RuleDelegationBo) element2;
202
203 delegation.getDelegationRule().setCurrentInd(Boolean.TRUE);
204 RuleBaseValues delegatorRule = delegation.getDelegationRule();
205
206 performanceLogger.log("Setting delegate rule: " + delegatorRule.getDescription() + " to current.");
207 if (delegatorRule.getActivationDate() == null) {
208 delegatorRule.setActivationDate(date);
209 }
210 try {
211 delegatorRule.setDeactivationDate(new Timestamp(RiceConstants.getDefaultDateFormat().parse("01/01/2100").getTime()));
212 } catch (Exception e) {
213 LOG.error("Parse Exception", e);
214 }
215 rulesToSave.put(delegatorRule.getId(), delegatorRule);
216 }
217 }
218 }
219 for (Iterator iterator = rulesToSave.values().iterator(); iterator.hasNext();) {
220 RuleBaseValues rule = (RuleBaseValues) iterator.next();
221 getRuleDAO().save(rule);
222 performanceLogger.log("Saved rule: " + rule.getId());
223 }
224 getActionRequestService().updateActionRequestsForResponsibilityChange(responsibilityIds);
225 performanceLogger.log("Time to make current");
226 }
227
228
229
230
231
232
233
234
235
236
237
238 public void makeCurrent2(List rules) {
239 PerformanceLogger performanceLogger = new PerformanceLogger();
240
241 boolean isGenerateRuleArs = true;
242 String generateRuleArs = CoreFrameworkServiceLocator.getParameterService().getParameterValueAsString(KEWConstants.KEW_NAMESPACE, KRADConstants.DetailTypes.RULE_DETAIL_TYPE, KEWConstants.RULE_GENERATE_ACTION_REQESTS_IND);
243 if (!StringUtils.isBlank(generateRuleArs)) {
244 isGenerateRuleArs = KEWConstants.YES_RULE_CHANGE_AR_GENERATION_VALUE.equalsIgnoreCase(generateRuleArs);
245 }
246 Set<String> responsibilityIds = new HashSet<String>();
247 Map<String, RuleBaseValues> rulesToSave = new HashMap<String, RuleBaseValues>();
248
249 Collections.sort(rules, new RuleDelegationSorter());
250 for (Iterator iter = rules.iterator(); iter.hasNext();) {
251 RuleBaseValues rule = (RuleBaseValues) iter.next();
252
253 performanceLogger.log("Preparing rule: " + rule.getDescription());
254
255 rule.setCurrentInd(Boolean.TRUE);
256 Timestamp date = new Timestamp(System.currentTimeMillis());
257 rule.setActivationDate(date);
258 try {
259 rule.setDeactivationDate(new Timestamp(RiceConstants.getDefaultDateFormat().parse("01/01/2100").getTime()));
260 } catch (Exception e) {
261 LOG.error("Parse Exception", e);
262 }
263 rulesToSave.put(rule.getId(), rule);
264 RuleBaseValues oldRule = rule.getPreviousVersion();
265 if (oldRule != null) {
266 performanceLogger.log("Setting previous rule: " + oldRule.getId() + " to non current.");
267 oldRule.setCurrentInd(Boolean.FALSE);
268 oldRule.setDeactivationDate(date);
269 rulesToSave.put(oldRule.getId(), oldRule);
270 responsibilityIds.addAll(getModifiedResponsibilityIds(oldRule, rule));
271 }
272 for (Object element : rule.getRuleResponsibilities()) {
273 RuleResponsibilityBo responsibility = (RuleResponsibilityBo) element;
274 for (Object element2 : responsibility.getDelegationRules()) {
275 RuleDelegationBo delegation = (RuleDelegationBo) element2;
276 RuleBaseValues delegateRule = delegation.getDelegationRule();
277 delegateRule.setCurrentInd(Boolean.TRUE);
278 performanceLogger.log("Setting delegate rule: " + delegateRule.getDescription() + " to current.");
279 if (delegateRule.getActivationDate() == null) {
280 delegateRule.setActivationDate(date);
281 }
282 try {
283 delegateRule.setDeactivationDate(new Timestamp(RiceConstants.getDefaultDateFormat().parse("01/01/2100").getTime()));
284 } catch (Exception e) {
285 LOG.error("Parse Exception", e);
286 }
287 rulesToSave.put(delegateRule.getId(), delegateRule);
288 }
289 }
290 }
291 Map<String, String> notifyMap = new HashMap<String, String>();
292 for (RuleBaseValues rule : rulesToSave.values()) {
293 getRuleDAO().save(rule);
294 performanceLogger.log("Saved rule: " + rule.getId());
295
296 }
297 if (isGenerateRuleArs) {
298 getActionRequestService().updateActionRequestsForResponsibilityChange(responsibilityIds);
299 }
300 performanceLogger.log("Time to make current");
301 }
302
303
304
305
306
307
308 public void makeCurrent(RuleBaseValues rule, boolean isRetroactiveUpdatePermitted) {
309 makeCurrent(null, rule, isRetroactiveUpdatePermitted);
310 }
311
312 public void makeCurrent(RuleDelegationBo ruleDelegation, boolean isRetroactiveUpdatePermitted) {
313 makeCurrent(ruleDelegation, ruleDelegation.getDelegationRule(), isRetroactiveUpdatePermitted);
314 }
315
316 protected void makeCurrent(RuleDelegationBo ruleDelegation, RuleBaseValues rule, boolean isRetroactiveUpdatePermitted) {
317 PerformanceLogger performanceLogger = new PerformanceLogger();
318
319 boolean isGenerateRuleArs = false;
320 if (isRetroactiveUpdatePermitted) {
321 isGenerateRuleArs = true;
322 String generateRuleArs = CoreFrameworkServiceLocator.getParameterService().getParameterValueAsString(KEWConstants.KEW_NAMESPACE, KRADConstants.DetailTypes.RULE_DETAIL_TYPE, KEWConstants.RULE_GENERATE_ACTION_REQESTS_IND);
323 if (!StringUtils.isBlank(generateRuleArs)) {
324 isGenerateRuleArs = KEWConstants.YES_RULE_CHANGE_AR_GENERATION_VALUE.equalsIgnoreCase(generateRuleArs);
325 }
326 }
327 Set<String> responsibilityIds = new HashSet<String>();
328
329
330 performanceLogger.log("Preparing rule: " + rule.getDescription());
331
332 Map<String, RuleBaseValues> rulesToSave = new HashMap<String, RuleBaseValues>();
333 generateRuleNameIfNeeded(rule);
334 assignResponsibilityIds(rule);
335 rule.setCurrentInd(Boolean.TRUE);
336 Timestamp date = new Timestamp(System.currentTimeMillis());
337 rule.setActivationDate(date);
338 rule.setDeactivationDate(null);
339
340 rulesToSave.put(rule.getId(), rule);
341 if (rule.getPreviousVersionId() != null) {
342 RuleBaseValues oldRule = findRuleBaseValuesById(rule.getPreviousVersionId());
343 rule.setPreviousVersion(oldRule);
344 }
345 rule.setVersionNbr(0);
346 rule.setObjectId(null);
347 RuleBaseValues oldRule = rule.getPreviousVersion();
348 if (oldRule != null) {
349 performanceLogger.log("Setting previous rule: " + oldRule.getId() + " to non current.");
350 oldRule.setCurrentInd(Boolean.FALSE);
351 oldRule.setDeactivationDate(date);
352 rulesToSave.put(oldRule.getId(), oldRule);
353 responsibilityIds.addAll(getModifiedResponsibilityIds(oldRule, rule));
354 rule.setVersionNbr(getNextVersionNumber(oldRule));
355 }
356
357
358 boolean isRuleDelegation = ruleDelegation != null;
359
360 Map<String, String> notifyMap = new HashMap<String, String>();
361
362 for (RuleBaseValues ruleToSave : rulesToSave.values()) {
363 getRuleDAO().save(ruleToSave);
364 performanceLogger.log("Saved rule: " + ruleToSave.getId());
365 }
366 if (isRuleDelegation) {
367 responsibilityIds.add(ruleDelegation.getResponsibilityId());
368 ruleDelegation.setDelegateRuleId(rule.getId());
369 getRuleDelegationService().save(ruleDelegation);
370 }
371
372 if (isGenerateRuleArs) {
373 getActionRequestService().updateActionRequestsForResponsibilityChange(responsibilityIds);
374 }
375 performanceLogger.log("Time to make current");
376 }
377
378 public RuleBaseValues getParentRule(String ruleBaseValuesId) {
379 return getRuleDAO().getParentRule(ruleBaseValuesId);
380 }
381
382 private Set getResponsibilityIdsFromGraph(RuleBaseValues rule, boolean isRuleCollecting) {
383 Set responsibilityIds = new HashSet();
384 for (Object element : rule.getRuleResponsibilities()) {
385 RuleResponsibilityBo responsibility = (RuleResponsibilityBo) element;
386 if (isRuleCollecting) {
387 responsibilityIds.add(responsibility.getResponsibilityId());
388 }
389 }
390 return responsibilityIds;
391 }
392
393
394
395
396
397 private Set<String> getModifiedResponsibilityIds(RuleBaseValues oldRule, RuleBaseValues newRule) {
398 Map<String, RuleResponsibilityBo> modifiedResponsibilityMap = new HashMap<String, RuleResponsibilityBo>();
399 for (Object element : oldRule.getRuleResponsibilities()) {
400 RuleResponsibilityBo responsibility = (RuleResponsibilityBo) element;
401 modifiedResponsibilityMap.put(responsibility.getResponsibilityId(), responsibility);
402 }
403 for (Object element : newRule.getRuleResponsibilities()) {
404 RuleResponsibilityBo responsibility = (RuleResponsibilityBo) element;
405 RuleResponsibilityBo oldResponsibility = modifiedResponsibilityMap.get(responsibility.getResponsibilityId());
406 if (oldResponsibility == null) {
407
408 modifiedResponsibilityMap.put(responsibility.getResponsibilityId(), responsibility);
409 } else if (!hasResponsibilityChanged(oldResponsibility, responsibility)) {
410
411 modifiedResponsibilityMap.remove(responsibility.getResponsibilityId());
412 }
413 }
414 return modifiedResponsibilityMap.keySet();
415 }
416
417
418
419
420 private boolean hasResponsibilityChanged(RuleResponsibilityBo oldResponsibility, RuleResponsibilityBo newResponsibility) {
421 return !ObjectUtils.equals(oldResponsibility.getActionRequestedCd(), newResponsibility.getActionRequestedCd()) ||
422 !ObjectUtils.equals(oldResponsibility.getApprovePolicy(), newResponsibility.getActionRequestedCd()) ||
423 !ObjectUtils.equals(oldResponsibility.getPriority(), newResponsibility.getPriority()) ||
424 !ObjectUtils.equals(oldResponsibility.getRole(), newResponsibility.getRole()) ||
425 !ObjectUtils.equals(oldResponsibility.getRuleResponsibilityName(), newResponsibility.getRuleResponsibilityName()) ||
426 !ObjectUtils.equals(oldResponsibility.getRuleResponsibilityType(), newResponsibility.getRuleResponsibilityType());
427 }
428
429
430
431
432
433 private List<RuleBaseValues> findOldDelegationRules(RuleBaseValues oldRule, RuleBaseValues newRule, PerformanceLogger performanceLogger) {
434 performanceLogger.log("Begin to get delegation rules.");
435 List<RuleBaseValues> oldDelegations = getRuleDAO().findOldDelegations(oldRule, newRule);
436 performanceLogger.log("Located "+oldDelegations.size()+" old delegation rules.");
437 return oldDelegations;
438 }
439
440 public String routeRuleWithDelegate(String documentId, RuleBaseValues parentRule, RuleBaseValues delegateRule, PrincipalContract principal, String annotation, boolean blanketApprove) throws Exception {
441 if (parentRule == null) {
442 throw new IllegalArgumentException("Cannot route a delegate without a parent rule.");
443 }
444 if (parentRule.getDelegateRule().booleanValue()) {
445 throw new IllegalArgumentException("Parent rule cannot be a delegate.");
446 }
447 if (parentRule.getPreviousVersionId() == null && delegateRule.getPreviousVersionId() == null) {
448 throw new IllegalArgumentException("Previous rule version required.");
449 }
450
451
452
453
454
455
456
457
458
459
460
461
462
463 RuleDelegationBo ruleDelegation = getRuleDelegation(parentRule, delegateRule);
464
465 save2(delegateRule, ruleDelegation, true);
466
467
468
469
470 boolean isRoutingParent = parentRule.getId() == null;
471 if (isRoutingParent) {
472
473
474
475 save2(parentRule, null, false);
476
477 }
478
479 WorkflowDocument workflowDocument = null;
480 if (documentId != null) {
481 workflowDocument = WorkflowDocumentFactory.loadDocument(principal.getPrincipalId(), documentId);
482 } else {
483 List rules = new ArrayList();
484 rules.add(delegateRule);
485 rules.add(parentRule);
486 workflowDocument = WorkflowDocumentFactory.createDocument(principal.getPrincipalId(), getRuleDocumentTypeName(
487 rules));
488 }
489 workflowDocument.setTitle(generateTitle(parentRule, delegateRule));
490 delegateRule.setDocumentId(workflowDocument.getDocumentId());
491 workflowDocument.addAttributeDefinition(RuleRoutingDefinition.createAttributeDefinition(parentRule.getDocTypeName()));
492 getRuleDAO().save(delegateRule);
493 if (isRoutingParent) {
494 parentRule.setDocumentId(workflowDocument.getDocumentId());
495 getRuleDAO().save(parentRule);
496 }
497 if (blanketApprove) {
498 workflowDocument.blanketApprove(annotation);
499 } else {
500 workflowDocument.route(annotation);
501 }
502 return workflowDocument.getDocumentId();
503 }
504
505
506
507
508 private RuleDelegationBo getRuleDelegation(RuleBaseValues parentRule, RuleBaseValues delegateRule) throws Exception {
509 for (Object element : parentRule.getRuleResponsibilities()) {
510 RuleResponsibilityBo responsibility = (RuleResponsibilityBo) element;
511 for (Object element2 : responsibility.getDelegationRules()) {
512 RuleDelegationBo ruleDelegation = (RuleDelegationBo) element2;
513
514 if (ruleDelegation.getDelegationRule().equals(delegateRule)) {
515 return ruleDelegation;
516 }
517 }
518 }
519 return null;
520 }
521
522 private String generateTitle(RuleBaseValues parentRule, RuleBaseValues delegateRule) {
523 StringBuffer title = new StringBuffer();
524 if (delegateRule.getPreviousVersionId() != null) {
525 title.append("Editing Delegation Rule '").append(delegateRule.getDescription()).append("' on '");
526 } else {
527 title.append("Adding Delegation Rule '").append(delegateRule.getDescription()).append("' to '");
528 }
529 title.append(parentRule.getDescription()).append("'");
530 return title.toString();
531 }
532
533 public void validate(RuleBaseValues ruleBaseValues, List errors) {
534 if (errors == null) {
535 errors = new ArrayList();
536 }
537 if (getDocumentTypeService().findByName(ruleBaseValues.getDocTypeName()) == null) {
538 errors.add(new WorkflowServiceErrorImpl("Document Type Invalid", "doctype.documenttypeservice.doctypename.required"));
539 }
540 if (ruleBaseValues.getToDateValue().before(ruleBaseValues.getFromDateValue())) {
541 errors.add(new WorkflowServiceErrorImpl("From Date is later than to date", "routetemplate.ruleservice.daterange.fromafterto"));
542 }
543 if (ruleBaseValues.getDescription() == null || ruleBaseValues.getDescription().equals("")) {
544 errors.add(new WorkflowServiceErrorImpl("Description is required", "routetemplate.ruleservice.description.required"));
545 }
546 if (ruleBaseValues.getRuleResponsibilities().isEmpty()) {
547 errors.add(new WorkflowServiceErrorImpl("A responsibility is required", "routetemplate.ruleservice.responsibility.required"));
548 } else {
549 for (Object element : ruleBaseValues.getRuleResponsibilities()) {
550 RuleResponsibilityBo responsibility = (RuleResponsibilityBo) element;
551 if (responsibility.getRuleResponsibilityName() != null && KEWConstants.RULE_RESPONSIBILITY_GROUP_ID.equals(responsibility.getRuleResponsibilityType())) {
552 if (getGroupService().getGroup(responsibility.getRuleResponsibilityName()) == null) {
553 errors.add(new WorkflowServiceErrorImpl("Workgroup is invalid", "routetemplate.ruleservice.workgroup.invalid"));
554 }
555 } else if (responsibility.getPrincipal() == null && responsibility.getRole() == null) {
556 errors.add(new WorkflowServiceErrorImpl("User is invalid", "routetemplate.ruleservice.user.invalid"));
557 }
558 }
559 }
560 if (!errors.isEmpty()) {
561 throw new WorkflowServiceErrorException("RuleBaseValues validation errors", errors);
562 }
563 }
564
565 public void validate2(RuleBaseValues ruleBaseValues, RuleDelegationBo ruleDelegation, List errors) {
566 if (errors == null) {
567 errors = new ArrayList();
568 }
569 if (getDocumentTypeService().findByName(ruleBaseValues.getDocTypeName()) == null) {
570 errors.add(new WorkflowServiceErrorImpl("Document Type Invalid", "doctype.documenttypeservice.doctypename.required"));
571 LOG.error("Document Type Invalid");
572 }
573 if (ruleBaseValues.getToDateValue() == null) {
574 try {
575 ruleBaseValues.setToDateValue(new Timestamp(RiceConstants.getDefaultDateFormat().parse("01/01/2100")
576 .getTime()));
577 } catch (ParseException e) {
578 LOG.error("Error date-parsing default date");
579 throw new WorkflowServiceErrorException("Error parsing default date.", e);
580 }
581 }
582 if (ruleBaseValues.getFromDateValue() == null) {
583 ruleBaseValues.setFromDateValue(new Timestamp(System.currentTimeMillis()));
584 }
585 if (ruleBaseValues.getToDateValue().before(ruleBaseValues.getFromDateValue())) {
586 errors.add(new WorkflowServiceErrorImpl("From Date is later than to date", "routetemplate.ruleservice.daterange.fromafterto"));
587 LOG.error("From Date is later than to date");
588 }
589 if (ruleBaseValues.getDescription() == null || ruleBaseValues.getDescription().equals("")) {
590 errors.add(new WorkflowServiceErrorImpl("Description is required", "routetemplate.ruleservice.description.required"));
591 LOG.error("Description is missing");
592 }
593
594 for (Object element : ruleBaseValues.getRuleResponsibilities()) {
595 RuleResponsibilityBo responsibility = (RuleResponsibilityBo) element;
596 if (responsibility.getRuleResponsibilityName() != null && KEWConstants.RULE_RESPONSIBILITY_GROUP_ID.equals(responsibility.getRuleResponsibilityType())) {
597 if (getGroupService().getGroup(responsibility.getRuleResponsibilityName()) == null) {
598 errors.add(new WorkflowServiceErrorImpl("Workgroup is invalid", "routetemplate.ruleservice.workgroup.invalid"));
599 LOG.error("Workgroup is invalid");
600 }
601 } else if (responsibility.getPrincipal() == null && responsibility.getRole() == null) {
602 errors.add(new WorkflowServiceErrorImpl("User is invalid", "routetemplate.ruleservice.user.invalid"));
603 LOG.error("User is invalid");
604 } else if (responsibility.isUsingRole()) {
605 if (responsibility.getApprovePolicy() == null || !(responsibility.getApprovePolicy().equals(ActionRequestPolicy.ALL.getCode()) || responsibility.getApprovePolicy().equals(ActionRequestPolicy.FIRST.getCode()))) {
606 errors.add(new WorkflowServiceErrorImpl("Approve Policy is Invalid", "routetemplate.ruleservice.approve.policy.invalid"));
607 LOG.error("Approve Policy is Invalid");
608 }
609 }
610 }
611
612 if (ruleBaseValues.getRuleTemplate() != null) {
613 for (Object element : ruleBaseValues.getRuleTemplate().getActiveRuleTemplateAttributes()) {
614 RuleTemplateAttributeBo templateAttribute = (RuleTemplateAttributeBo) element;
615 if (!templateAttribute.isRuleValidationAttribute()) {
616 continue;
617 }
618 RuleValidationAttribute attribute = templateAttribute.getRuleValidationAttribute();
619 UserSession userSession = GlobalVariables.getUserSession();
620 try {
621 RuleValidationContext validationContext = RuleValidationContext.Builder.create(RuleBaseValues.to(ruleBaseValues), RuleDelegationBo
622 .to(ruleDelegation), userSession.getPrincipalId()).build();
623 ValidationResults results = attribute.validate(validationContext);
624 if (results != null && !results.getErrors().isEmpty()) {
625 errors.add(results);
626 }
627 } catch (Exception e) {
628 if (e instanceof RuntimeException) {
629 throw (RuntimeException)e;
630 }
631 throw new RuntimeException("Problem validation rule.", e);
632 }
633
634 }
635 }
636 if (ruleBaseValues.getRuleExpressionDef() != null) {
637
638 }
639
640 if (!errors.isEmpty()) {
641 throw new WorkflowServiceErrorException("RuleBaseValues validation errors", errors);
642 }
643 }
644
645 public List<RuleBaseValues> findByDocumentId(String documentId) {
646 return getRuleDAO().findByDocumentId(documentId);
647 }
648
649 public List<RuleBaseValues> search(String docTypeName, String ruleId, String ruleTemplateId, String ruleDescription, String groupId, String principalId,
650 Boolean delegateRule, Boolean activeInd, Map extensionValues, String workflowIdDirective) {
651 return getRuleDAO().search(docTypeName, ruleId, ruleTemplateId, ruleDescription, groupId, principalId, delegateRule,
652 activeInd, extensionValues, workflowIdDirective);
653 }
654
655 public List<RuleBaseValues> searchByTemplate(String docTypeName, String ruleTemplateName, String ruleDescription, String groupId, String principalId,
656 Boolean workgroupMember, Boolean delegateRule, Boolean activeInd, Map extensionValues, Collection<String> actionRequestCodes) {
657
658 if ( (StringUtils.isEmpty(docTypeName)) &&
659 (StringUtils.isEmpty(ruleTemplateName)) &&
660 (StringUtils.isEmpty(ruleDescription)) &&
661 (StringUtils.isEmpty(groupId)) &&
662 (StringUtils.isEmpty(principalId)) &&
663 (extensionValues.isEmpty()) &&
664 (actionRequestCodes.isEmpty()) ) {
665
666 throw new IllegalArgumentException("At least one criterion must be sent");
667 }
668
669 RuleTemplateBo ruleTemplate = getRuleTemplateService().findByRuleTemplateName(ruleTemplateName);
670 String ruleTemplateId = null;
671 if (ruleTemplate != null) {
672 ruleTemplateId = ruleTemplate.getId();
673 }
674
675 if ( ( (extensionValues != null) && (!extensionValues.isEmpty()) ) &&
676 (ruleTemplateId == null) ) {
677
678 throw new IllegalArgumentException("A Rule Template Name must be given if using Rule Extension values");
679 }
680
681 Collection<String> workgroupIds = new ArrayList<String>();
682 if (principalId != null) {
683 KEWServiceLocator.getIdentityHelperService().validatePrincipalId(principalId);
684 if ( (workgroupMember == null) || (workgroupMember.booleanValue()) ) {
685 workgroupIds = getGroupService().getGroupIdsByPrincipalId(principalId);
686 } else {
687
688 }
689 } else if (groupId != null) {
690 Group group = KEWServiceLocator.getIdentityHelperService().getGroup(groupId);
691 if (group == null) {
692 throw new IllegalArgumentException("Group does not exist in for given group id: " + groupId);
693 } else {
694 workgroupIds.add(group.getId());
695 }
696 }
697
698 return getRuleDAO().search(docTypeName, ruleTemplateId, ruleDescription, workgroupIds, principalId,
699 delegateRule,activeInd, extensionValues, actionRequestCodes);
700 }
701
702 public void delete(String ruleBaseValuesId) {
703 getRuleDAO().delete(ruleBaseValuesId);
704 }
705
706 public RuleBaseValues findRuleBaseValuesById(String ruleBaseValuesId) {
707 return getRuleDAO().findRuleBaseValuesById(ruleBaseValuesId);
708 }
709
710 public RuleResponsibilityBo findRuleResponsibility(String responsibilityId) {
711 return getRuleDAO().findRuleResponsibility(responsibilityId);
712 }
713
714 public List fetchAllCurrentRulesForTemplateDocCombination(String ruleTemplateName, String documentType) {
715 String ruleTemplateId = getRuleTemplateService().findByRuleTemplateName(ruleTemplateName).getId();
716 return getRuleDAO().fetchAllCurrentRulesForTemplateDocCombination(ruleTemplateId, getDocGroupAndTypeList(documentType));
717 }
718
719 public List fetchAllCurrentRulesForTemplateDocCombination(String ruleTemplateName, String documentType, Timestamp effectiveDate){
720 String ruleTemplateId = getRuleTemplateService().findByRuleTemplateName(ruleTemplateName).getId();
721 PerformanceLogger performanceLogger = new PerformanceLogger();
722 performanceLogger.log("Time to fetchRules by template " + ruleTemplateName + " not caching.");
723 return getRuleDAO().fetchAllCurrentRulesForTemplateDocCombination(ruleTemplateId, getDocGroupAndTypeList(documentType), effectiveDate);
724 }
725 public List fetchAllRules(boolean currentRules) {
726 return getRuleDAO().fetchAllRules(currentRules);
727 }
728
729 private List getDocGroupAndTypeList(String documentType) {
730 List docTypeList = new ArrayList();
731 DocumentTypeService docTypeService = (DocumentTypeService) KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE);
732 DocumentType docType = docTypeService.findByName(documentType);
733 while (docType != null) {
734 docTypeList.add(docType.getName());
735 docType = docType.getParentDocType();
736 }
737 return docTypeList;
738 }
739
740 private Integer getNextVersionNumber(RuleBaseValues currentRule) {
741 List candidates = new ArrayList();
742 candidates.add(currentRule.getVersionNbr());
743 List pendingRules = ruleDAO.findByPreviousVersionId(currentRule.getId());
744 for (Iterator iterator = pendingRules.iterator(); iterator.hasNext();) {
745 RuleBaseValues pendingRule = (RuleBaseValues) iterator.next();
746 candidates.add(pendingRule.getVersionNbr());
747 }
748 Collections.sort(candidates);
749 Integer maxVersionNumber = (Integer) candidates.get(candidates.size() - 1);
750 if (maxVersionNumber == null) {
751 return Integer.valueOf(0);
752 }
753 return Integer.valueOf(maxVersionNumber.intValue() + 1);
754 }
755
756
757
758
759
760
761
762
763 public String isLockedForRouting(String currentRuleBaseValuesId) {
764
765
766 List pendingRules = ruleDAO.findByPreviousVersionId(currentRuleBaseValuesId);
767 boolean isDead = true;
768 for (Iterator iterator = pendingRules.iterator(); iterator.hasNext();) {
769 RuleBaseValues pendingRule = (RuleBaseValues) iterator.next();
770
771 if (pendingRule.getDocumentId() != null && StringUtils.isNotBlank(pendingRule.getDocumentId())) {
772 DocumentRouteHeaderValue routeHeader = getRouteHeaderService().getRouteHeader(pendingRule.getDocumentId());
773
774 isDead = routeHeader.isDisaproved() || routeHeader.isCanceled();
775 if (!isDead) {
776 return pendingRule.getDocumentId();
777 }
778 }
779
780 for (Object element : pendingRule.getRuleResponsibilities()) {
781 RuleResponsibilityBo responsibility = (RuleResponsibilityBo) element;
782 for (Object element2 : responsibility.getDelegationRules()) {
783 RuleDelegationBo delegation = (RuleDelegationBo) element2;
784 List pendingDelegateRules = ruleDAO.findByPreviousVersionId(delegation.getDelegationRule().getId());
785 for (Iterator iterator3 = pendingDelegateRules.iterator(); iterator3.hasNext();) {
786 RuleBaseValues pendingDelegateRule = (RuleBaseValues) iterator3.next();
787 if (pendingDelegateRule.getDocumentId() != null && StringUtils.isNotBlank(pendingDelegateRule.getDocumentId())) {
788 DocumentRouteHeaderValue routeHeader = getRouteHeaderService().getRouteHeader(pendingDelegateRule.getDocumentId());
789 isDead = routeHeader.isDisaproved() || routeHeader.isCanceled();
790 if (!isDead) {
791 return pendingDelegateRule.getDocumentId();
792 }
793 }
794 }
795 }
796 }
797 }
798 return null;
799 }
800
801 public RuleBaseValues getParentRule(RuleBaseValues rule) {
802 if (rule == null || rule.getId() == null) {
803 throw new IllegalArgumentException("Rule must be non-null with non-null id: " + rule);
804 }
805 if (!Boolean.TRUE.equals(rule.getDelegateRule())) {
806 return null;
807 }
808 return getRuleDAO().getParentRule(rule.getId());
809 }
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833 public String getRuleDocumentTypeName(List rules) {
834 if (rules.size() == 0) {
835 throw new IllegalArgumentException("Cannot determine rule DocumentType for an empty list of rules.");
836 }
837 String ruleDocTypeName = null;
838 RuleRoutingConfig config = RuleRoutingConfig.parse();
839
840 RuleBaseValues firstRule = (RuleBaseValues)rules.get(0);
841 if (Boolean.TRUE.equals(firstRule.getDelegateRule())) {
842
843
844 ruleDocTypeName = config.getDocumentTypeName(firstRule);
845 } else {
846
847
848 String parentRulesDocTypeName = null;
849 for (Iterator iterator = rules.iterator(); iterator.hasNext();) {
850 RuleBaseValues rule = (RuleBaseValues) iterator.next();
851
852 if (Boolean.TRUE.equals(rule.getDelegateRule())) {
853 continue;
854 }
855 String currentDocTypeName = config.getDocumentTypeName(rule);
856 if (parentRulesDocTypeName == null) {
857 parentRulesDocTypeName = currentDocTypeName;
858 } else {
859 if (!ObjectUtils.equals(currentDocTypeName, parentRulesDocTypeName)) {
860 throw new RuntimeException("There are multiple rules being routed and they have different document type definitions! " + parentRulesDocTypeName + " and " + currentDocTypeName);
861 }
862 }
863 }
864 ruleDocTypeName = parentRulesDocTypeName;
865 }
866 if (ruleDocTypeName == null) {
867 ruleDocTypeName = KEWConstants.DEFAULT_RULE_DOCUMENT_NAME;
868 }
869 return ruleDocTypeName;
870 }
871
872 public void setRuleDAO(RuleDAO ruleDAO) {
873 this.ruleDAO = ruleDAO;
874 }
875
876 public RuleDAO getRuleDAO() {
877 return ruleDAO;
878 }
879
880 public void deleteRuleResponsibilityById(String ruleResponsibilityId) {
881 getRuleResponsibilityDAO().delete(ruleResponsibilityId);
882 }
883
884 public RuleResponsibilityBo findByRuleResponsibilityId(String ruleResponsibilityId) {
885 return getRuleResponsibilityDAO().findByRuleResponsibilityId(ruleResponsibilityId);
886 }
887
888 public List findRuleBaseValuesByResponsibilityReviewer(String reviewerName, String type) {
889 return getRuleDAO().findRuleBaseValuesByResponsibilityReviewer(reviewerName, type);
890 }
891
892 public List findRuleBaseValuesByResponsibilityReviewerTemplateDoc(String ruleTemplateName, String documentType, String reviewerName, String type) {
893 return getRuleDAO().findRuleBaseValuesByResponsibilityReviewerTemplateDoc(ruleTemplateName, documentType, reviewerName, type);
894 }
895
896 public RuleTemplateService getRuleTemplateService() {
897 return (RuleTemplateService) KEWServiceLocator.getService(KEWServiceLocator.RULE_TEMPLATE_SERVICE);
898 }
899
900 public DocumentTypeService getDocumentTypeService() {
901 return (DocumentTypeService) KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE);
902 }
903
904 public GroupService getGroupService() {
905 return KimApiServiceLocator.getGroupService();
906 }
907
908 public ActionRequestService getActionRequestService() {
909 return (ActionRequestService) KEWServiceLocator.getService(KEWServiceLocator.ACTION_REQUEST_SRV);
910 }
911
912 private ResponsibilityIdService getResponsibilityIdService() {
913 return (ResponsibilityIdService) KEWServiceLocator.getService(KEWServiceLocator.RESPONSIBILITY_ID_SERVICE);
914 }
915
916 private RuleDelegationService getRuleDelegationService() {
917 return (RuleDelegationService) KEWServiceLocator.getService(KEWServiceLocator.RULE_DELEGATION_SERVICE);
918 }
919
920 private RouteHeaderService getRouteHeaderService() {
921 return (RouteHeaderService) KEWServiceLocator.getService(KEWServiceLocator.DOC_ROUTE_HEADER_SRV);
922 }
923
924
925
926
927 public class RuleDelegationSorter implements Comparator {
928 public int compare(Object arg0, Object arg1) {
929 RuleBaseValues rule1 = (RuleBaseValues) arg0;
930 RuleBaseValues rule2 = (RuleBaseValues) arg1;
931
932 Integer rule1Value = new Integer((rule1.getDelegateRule().booleanValue() ? 0 : 1));
933 Integer rule2Value = new Integer((rule2.getDelegateRule().booleanValue() ? 0 : 1));
934 int value = rule1Value.compareTo(rule2Value);
935 return value;
936 }
937 }
938
939
940 public void loadXml(InputStream inputStream, String principalId) {
941 RuleXmlParser parser = new RuleXmlParser();
942 try {
943 parser.parseRules(inputStream);
944 } catch (Exception e) {
945 LOG.error("Error loading xml file", e);
946 WorkflowServiceErrorException wsee = new WorkflowServiceErrorException("Error loading xml file", new WorkflowServiceErrorImpl("Error loading xml file", XML_PARSE_ERROR));
947 wsee.initCause(e);
948 throw wsee;
949 }
950 }
951
952 public Element export(ExportDataSet dataSet) {
953 RuleXmlExporter exporter = new RuleXmlExporter(XmlConstants.RULE_NAMESPACE);
954 return exporter.export(dataSet);
955 }
956
957 @Override
958 public boolean supportPrettyPrint() {
959 return true;
960 }
961
962 protected List<RuleBaseValues> loadRules(List<String> ruleIds) {
963 List<RuleBaseValues> rules = new ArrayList<RuleBaseValues>();
964 for (String ruleId : ruleIds) {
965 RuleBaseValues rule = KEWServiceLocator.getRuleService().findRuleBaseValuesById(ruleId);
966 rules.add(rule);
967 }
968 return rules;
969 }
970
971
972
973
974
975 protected boolean shouldChangeRuleInvolvement(String documentId, RuleBaseValues rule) {
976 if (!rule.getCurrentInd()) {
977 LOG.warn("Rule requested for rule involvement change by document " + documentId + " is no longer current. Change will not be executed! Rule id is: " + rule.getId());
978 return false;
979 }
980 String lockingDocumentId = KEWServiceLocator.getRuleService().isLockedForRouting(rule.getId());
981 if (lockingDocumentId != null) {
982 LOG.warn("Rule requested for rule involvement change by document " + documentId + " is locked by document " + lockingDocumentId + " and cannot be modified. " +
983 "Change will not be executed! Rule id is: " + rule.getId());
984 return false;
985 }
986 return true;
987 }
988
989 protected RuleDelegationBo getRuleDelegationForDelegateRule(RuleBaseValues rule) {
990 if (Boolean.TRUE.equals(rule.getDelegateRule())) {
991 List delegations = getRuleDelegationService().findByDelegateRuleId(rule.getId());
992 for (Iterator iterator = delegations.iterator(); iterator.hasNext();) {
993 RuleDelegationBo ruleDelegation = (RuleDelegationBo) iterator.next();
994 RuleBaseValues parentRule = ruleDelegation.getRuleResponsibility().getRuleBaseValues();
995 if (Boolean.TRUE.equals(parentRule.getCurrentInd())) {
996 return ruleDelegation;
997 }
998 }
999 }
1000 return null;
1001 }
1002
1003 protected void hookUpDelegateRuleToParentRule(RuleBaseValues newParentRule, RuleBaseValues newDelegationRule, RuleDelegationBo existingRuleDelegation) {
1004
1005 boolean foundDelegation = false;
1006 outer:for (RuleResponsibilityBo responsibility : (List<RuleResponsibilityBo>)newParentRule.getRuleResponsibilities()) {
1007 for (RuleDelegationBo ruleDelegation : (List<RuleDelegationBo>)responsibility.getDelegationRules()) {
1008 if (ruleDelegation.getDelegationRule().getId().equals(existingRuleDelegation.getDelegationRule().getId())) {
1009 ruleDelegation.setDelegationRule(newDelegationRule);
1010 foundDelegation = true;
1011 break outer;
1012 }
1013 }
1014 }
1015 if (!foundDelegation) {
1016 throw new WorkflowRuntimeException("Failed to locate the existing rule delegation with id: " + existingRuleDelegation.getDelegationRule().getId());
1017 }
1018
1019 }
1020
1021 protected RuleBaseValues createNewRuleVersion(RuleBaseValues existingRule, String documentId) throws Exception {
1022 RuleBaseValues rule = new RuleBaseValues();
1023 PropertyUtils.copyProperties(rule, existingRule);
1024 rule.setPreviousVersion(existingRule);
1025 rule.setPreviousVersionId(existingRule.getId());
1026 rule.setId(null);
1027 rule.setActivationDate(null);
1028 rule.setDeactivationDate(null);
1029 rule.setVersionNumber(0L);
1030 rule.setDocumentId(documentId);
1031
1032
1033
1034 rule.setRuleResponsibilities(new ArrayList());
1035 for (RuleResponsibilityBo existingResponsibility : (List<RuleResponsibilityBo>)existingRule.getRuleResponsibilities()) {
1036 RuleResponsibilityBo responsibility = new RuleResponsibilityBo();
1037 PropertyUtils.copyProperties(responsibility, existingResponsibility);
1038 responsibility.setRuleBaseValues(rule);
1039 responsibility.setRuleBaseValuesId(null);
1040 responsibility.setId(null);
1041 responsibility.setVersionNumber(0L);
1042 rule.getRuleResponsibilities().add(responsibility);
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055 }
1056 rule.setRuleExtensions(new ArrayList());
1057 for (RuleExtension existingExtension : (List<RuleExtension>)existingRule.getRuleExtensions()) {
1058 RuleExtension extension = new RuleExtension();
1059 PropertyUtils.copyProperties(extension, existingExtension);
1060 extension.setLockVerNbr(0);
1061 extension.setRuleBaseValues(rule);
1062 extension.setRuleBaseValuesId(null);
1063 extension.setRuleExtensionId(null);
1064 rule.getRuleExtensions().add(extension);
1065 extension.setExtensionValues(new ArrayList<RuleExtensionValue>());
1066 for (RuleExtensionValue existingExtensionValue : extension.getExtensionValues()) {
1067 RuleExtensionValue extensionValue = new RuleExtensionValue();
1068 PropertyUtils.copyProperties(extensionValue, existingExtensionValue);
1069 extensionValue.setExtension(extension);
1070 extensionValue.setRuleExtensionId(null);
1071 extensionValue.setLockVerNbr(0);
1072 extensionValue.setRuleExtensionValueId(null);
1073 extension.getExtensionValues().add(extensionValue);
1074 }
1075 }
1076 return rule;
1077 }
1078
1079 private static class RuleVersion {
1080 public RuleBaseValues rule;
1081 public RuleBaseValues parent;
1082 public RuleDelegationBo delegation;
1083 }
1084
1085 private static class RuleRoutingConfig {
1086 private List configs = new ArrayList();
1087 public static RuleRoutingConfig parse() {
1088 RuleRoutingConfig config = new RuleRoutingConfig();
1089 String constant = CoreFrameworkServiceLocator.getParameterService().getParameterValueAsString(KEWConstants.KEW_NAMESPACE, KRADConstants.DetailTypes.RULE_DETAIL_TYPE, KEWConstants.RULE_CUSTOM_DOC_TYPES);
1090 if (!StringUtils.isEmpty(constant)) {
1091 String[] ruleConfigs = constant.split(",");
1092 for (String ruleConfig : ruleConfigs) {
1093 String[] configElements = ruleConfig.split(":");
1094 if (configElements.length != 4) {
1095 throw new RuntimeException("Found incorrect number of config elements within a section of the custom rule document types config. There should have been four ':' delimited sections! " + ruleConfig);
1096 }
1097 config.configs.add(configElements);
1098 }
1099 }
1100 return config;
1101 }
1102 public String getDocumentTypeName(RuleBaseValues rule) {
1103 for (Iterator iterator = configs.iterator(); iterator.hasNext();) {
1104 String[] configElements = (String[]) iterator.next();
1105 String docTypeName = configElements[0];
1106 String ruleTemplateName = configElements[1];
1107 String type = configElements[2];
1108 String ruleDocTypeName = configElements[3];
1109 if (rule.getDocTypeName().equals(docTypeName) && rule.getRuleTemplateName().equals(ruleTemplateName)) {
1110 if (type.equals("M")) {
1111 if (Boolean.FALSE.equals(rule.getDelegateRule())) {
1112 return ruleDocTypeName;
1113 }
1114 } else if (type.equals("D")) {
1115 if (Boolean.TRUE.equals(rule.getDelegateRule())) {
1116 return ruleDocTypeName;
1117 }
1118 } else {
1119 throw new RuntimeException("Bad rule type '" + type + "' in rule doc type routing config.");
1120 }
1121 }
1122 }
1123 return null;
1124 }
1125 }
1126
1127 public String getDuplicateRuleId(RuleBaseValues rule) {
1128
1129
1130
1131 List responsibilities = rule.getRuleResponsibilities();
1132 List extensions = rule.getRuleExtensions();
1133 String docTypeName = rule.getDocTypeName();
1134 String ruleTemplateName = rule.getRuleTemplateName();
1135 List rules = fetchAllCurrentRulesForTemplateDocCombination(rule.getRuleTemplateName(), rule.getDocTypeName());
1136 Iterator it = rules.iterator();
1137 while (it.hasNext()) {
1138 RuleBaseValues r = (RuleBaseValues) it.next();
1139 if (ObjectUtils.equals(rule.isActive(), r.isActive()) &&
1140 ObjectUtils.equals(docTypeName, r.getDocTypeName()) &&
1141 ObjectUtils.equals(ruleTemplateName, r.getRuleTemplateName()) &&
1142 ObjectUtils.equals(rule.getRuleExpressionDef(), r.getRuleExpressionDef()) &&
1143 CollectionUtils.collectionsEquivalent(responsibilities, r.getRuleResponsibilities()) &&
1144 CollectionUtils.collectionsEquivalent(extensions, r.getRuleExtensions())) {
1145
1146 return r.getId();
1147 }
1148 }
1149 return null;
1150 }
1151
1152 private void generateRuleNameIfNeeded(RuleBaseValues rule) {
1153 if (StringUtils.isBlank(rule.getName())) {
1154 rule.setName(UUID.randomUUID().toString());
1155 }
1156 }
1157
1158 private void assignResponsibilityIds(RuleBaseValues rule) {
1159 for (RuleResponsibilityBo responsibility : rule.getRuleResponsibilities()) {
1160 if (responsibility.getResponsibilityId() == null) {
1161 responsibility.setResponsibilityId(KEWServiceLocator.getResponsibilityIdService().getNewResponsibilityId());
1162 }
1163 }
1164 }
1165
1166 public RuleBaseValues saveRule(RuleBaseValues rule, boolean isRetroactiveUpdatePermitted) {
1167 rule.setPreviousVersionId(rule.getId());
1168 rule.setPreviousVersion(null);
1169 rule.setId(null);
1170 makeCurrent(rule, isRetroactiveUpdatePermitted);
1171 return rule;
1172 }
1173
1174 public List<RuleBaseValues> saveRules(List<RuleBaseValues> rulesToSave, boolean isRetroactiveUpdatePermitted) {
1175 List<RuleBaseValues> savedRules = new ArrayList<RuleBaseValues>();
1176 for (RuleBaseValues rule : rulesToSave) {
1177 rule = saveRule(rule, isRetroactiveUpdatePermitted);
1178 savedRules.add(rule);
1179 }
1180 return savedRules;
1181 }
1182
1183 public RuleDelegationBo saveRuleDelegation(RuleDelegationBo ruleDelegation, boolean isRetroactiveUpdatePermitted) {
1184 RuleBaseValues rule = ruleDelegation.getDelegationRule();
1185 rule.setPreviousVersionId(rule.getId());
1186 rule.setPreviousVersion(null);
1187 rule.setId(null);
1188 ruleDelegation.setRuleDelegationId(null);
1189 makeCurrent(ruleDelegation, isRetroactiveUpdatePermitted);
1190 return ruleDelegation;
1191 }
1192
1193 public List<RuleDelegationBo> saveRuleDelegations(List<RuleDelegationBo> ruleDelegationsToSave, boolean isRetroactiveUpdatePermitted) {
1194 List<RuleDelegationBo> savedRuleDelegations = new ArrayList<RuleDelegationBo>();
1195 for (RuleDelegationBo ruleDelegation : ruleDelegationsToSave) {
1196 ruleDelegation = saveRuleDelegation(ruleDelegation, isRetroactiveUpdatePermitted);
1197 savedRuleDelegations.add(ruleDelegation);
1198 }
1199 return savedRuleDelegations;
1200 }
1201
1202 public String findResponsibilityIdForRule(String ruleName, String ruleResponsibilityName, String ruleResponsibilityType) {
1203 return getRuleDAO().findResponsibilityIdForRule(ruleName, ruleResponsibilityName, ruleResponsibilityType);
1204 }
1205
1206 }