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 java.io.InputStream;
20 import java.sql.Timestamp;
21 import java.text.ParseException;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.Comparator;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Set;
32
33 import javax.xml.namespace.QName;
34 import org.apache.commons.beanutils.PropertyUtils;
35 import org.apache.commons.collections.ComparatorUtils;
36 import org.apache.commons.lang.ObjectUtils;
37 import org.apache.commons.lang.StringUtils;
38 import org.jdom.Element;
39 import org.kuali.rice.core.util.RiceConstants;
40 import org.kuali.rice.kew.actionrequest.service.ActionRequestService;
41 import org.kuali.rice.kew.doctype.bo.DocumentType;
42 import org.kuali.rice.kew.doctype.service.DocumentTypeService;
43 import org.kuali.rice.kew.dto.WorkflowIdDTO;
44 import org.kuali.rice.kew.exception.WorkflowException;
45 import org.kuali.rice.kew.exception.WorkflowRuntimeException;
46 import org.kuali.rice.kew.exception.WorkflowServiceErrorException;
47 import org.kuali.rice.kew.exception.WorkflowServiceErrorImpl;
48 import org.kuali.rice.kew.export.ExportDataSet;
49 import org.kuali.rice.kew.identity.Id;
50 import org.kuali.rice.kew.messaging.MessageServiceNames;
51 import org.kuali.rice.kew.responsibility.service.ResponsibilityIdService;
52 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
53 import org.kuali.rice.kew.routeheader.service.RouteHeaderService;
54 import org.kuali.rice.kew.rule.MyRules2;
55 import org.kuali.rice.kew.rule.RuleBaseValues;
56 import org.kuali.rice.kew.rule.RuleDelegation;
57 import org.kuali.rice.kew.rule.RuleExtension;
58 import org.kuali.rice.kew.rule.RuleExtensionValue;
59 import org.kuali.rice.kew.rule.RuleResponsibility;
60 import org.kuali.rice.kew.rule.RuleRoutingDefinition;
61 import org.kuali.rice.kew.rule.RuleValidationAttribute;
62 import org.kuali.rice.kew.rule.bo.RuleTemplate;
63 import org.kuali.rice.kew.rule.bo.RuleTemplateAttribute;
64 import org.kuali.rice.kew.rule.dao.RuleDAO;
65 import org.kuali.rice.kew.rule.dao.RuleResponsibilityDAO;
66 import org.kuali.rice.kew.rule.service.RuleCacheProcessor;
67 import org.kuali.rice.kew.rule.service.RuleDelegationCacheProcessor;
68 import org.kuali.rice.kew.rule.service.RuleDelegationService;
69 import org.kuali.rice.kew.rule.service.RuleService;
70 import org.kuali.rice.kew.rule.service.RuleTemplateService;
71 import org.kuali.rice.kew.service.KEWServiceLocator;
72 import org.kuali.rice.kew.service.WorkflowDocument;
73 import org.kuali.rice.kew.user.UserId;
74 import org.kuali.rice.kew.util.KEWConstants;
75 import org.kuali.rice.kew.util.PerformanceLogger;
76 import org.kuali.rice.kew.util.Utilities;
77 import org.kuali.rice.kew.validation.RuleValidationContext;
78 import org.kuali.rice.kew.validation.ValidationResults;
79 import org.kuali.rice.kew.web.session.UserSession;
80 import org.kuali.rice.kew.workgroup.GroupId;
81 import org.kuali.rice.kew.xml.RuleXmlParser;
82 import org.kuali.rice.kew.xml.XmlConstants;
83 import org.kuali.rice.kew.xml.export.RuleXmlExporter;
84 import org.kuali.rice.kim.bo.Group;
85 import org.kuali.rice.kim.bo.entity.KimPrincipal;
86 import org.kuali.rice.kim.service.IdentityManagementService;
87 import org.kuali.rice.kim.service.KIMServiceLocator;
88 import org.kuali.rice.kns.util.Guid;
89 import org.kuali.rice.kns.util.KNSConstants;
90 import org.kuali.rice.ksb.service.KSBServiceLocator;
91
92
93 public class RuleServiceImpl implements RuleService {
94
95 private static final String USING_RULE_CACHE_IND = "CACHING_IND";
96 private static final String XML_PARSE_ERROR = "general.error.parsexml";
97 private static final String RULE_GROUP_CACHE = "org.kuali.workflow.rules.RuleCache";
98
99 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(RuleServiceImpl.class);
100
101 private RuleDAO ruleDAO;
102 private RuleResponsibilityDAO ruleResponsibilityDAO;
103
104 public RuleResponsibilityDAO getRuleResponsibilityDAO() {
105 return ruleResponsibilityDAO;
106 }
107
108 public RuleBaseValues getRuleByName(String name) {
109 return ruleDAO.findRuleBaseValuesByName(name);
110 }
111
112 public RuleBaseValues findDefaultRuleByRuleTemplateId(Long ruleTemplateId){
113 return this.ruleDAO.findDefaultRuleByRuleTemplateId(ruleTemplateId);
114 }
115 public void setRuleResponsibilityDAO(RuleResponsibilityDAO ruleResponsibilityDAO) {
116 this.ruleResponsibilityDAO = ruleResponsibilityDAO;
117 }
118
119 public void save2(RuleBaseValues ruleBaseValues) throws Exception {
120 save2(ruleBaseValues, null, true);
121 }
122
123 public void save2(RuleBaseValues ruleBaseValues, RuleDelegation ruleDelegation, boolean saveDelegations) throws Exception {
124 if (ruleBaseValues.getPreviousVersionId() != null) {
125 RuleBaseValues oldRule = findRuleBaseValuesById(ruleBaseValues.getPreviousVersionId());
126 ruleBaseValues.setPreviousVersion(oldRule);
127 ruleBaseValues.setCurrentInd(Boolean.FALSE);
128 ruleBaseValues.setVersionNbr(getNextVersionNumber(oldRule));
129 }
130 if (ruleBaseValues.getVersionNbr() == null) {
131 ruleBaseValues.setVersionNbr(Integer.valueOf(0));
132 }
133 if (ruleBaseValues.getCurrentInd() == null) {
134 ruleBaseValues.setCurrentInd(Boolean.FALSE);
135 }
136
137
138 for (Iterator iterator = ruleBaseValues.getResponsibilities().iterator(); iterator.hasNext();) {
139 RuleResponsibility responsibility = (RuleResponsibility) iterator.next();
140 if (responsibility.getResponsibilityId() == null) {
141 responsibility.setResponsibilityId(getResponsibilityIdService().getNewResponsibilityId());
142 }
143 if (saveDelegations) {
144 for (Iterator iter = responsibility.getDelegationRules().iterator(); iter.hasNext();) {
145 RuleDelegation localRuleDelegation = (RuleDelegation) iter.next();
146 save2(localRuleDelegation.getDelegationRuleBaseValues(), localRuleDelegation, true);
147 }
148 }
149 }
150 validate2(ruleBaseValues, ruleDelegation, null);
151 getRuleDAO().save(ruleBaseValues);
152 }
153
154 public void makeCurrent(Long routeHeaderId) {
155 makeCurrent(findByRouteHeaderId(routeHeaderId));
156 }
157
158 public void makeCurrent(List rules) {
159 PerformanceLogger performanceLogger = new PerformanceLogger();
160
161 boolean isGenerateRuleArs = true;
162 String generateRuleArs = Utilities.getKNSParameterValue(KEWConstants.KEW_NAMESPACE, KNSConstants.DetailTypes.RULE_DETAIL_TYPE, KEWConstants.RULE_GENERATE_ACTION_REQESTS_IND);
163 if (!StringUtils.isBlank(generateRuleArs)) {
164 isGenerateRuleArs = KEWConstants.YES_RULE_CHANGE_AR_GENERATION_VALUE.equalsIgnoreCase(generateRuleArs);
165 }
166 Set responsibilityIds = new HashSet();
167 HashMap rulesToSave = new HashMap();
168
169 Collections.sort(rules, new RuleDelegationSorter());
170 boolean delegateFirst = false;
171 for (Iterator iter = rules.iterator(); iter.hasNext();) {
172 RuleBaseValues rule = (RuleBaseValues) iter.next();
173
174 performanceLogger.log("Preparing rule: " + rule.getDescription());
175
176 rule.setCurrentInd(Boolean.TRUE);
177 Timestamp date = new Timestamp(System.currentTimeMillis());
178 rule.setActivationDate(date);
179 try {
180 rule.setDeactivationDate(new Timestamp(RiceConstants.getDefaultDateFormat().parse("01/01/2100").getTime()));
181 } catch (Exception e) {
182 LOG.error("Parse Exception", e);
183 }
184 rulesToSave.put(rule.getRuleBaseValuesId(), rule);
185 RuleBaseValues oldRule = rule.getPreviousVersion();
186 if (oldRule != null) {
187 performanceLogger.log("Setting previous rule: " + oldRule.getRuleBaseValuesId() + " to non current.");
188
189 oldRule.setCurrentInd(Boolean.FALSE);
190 oldRule.setDeactivationDate(date);
191 rulesToSave.put(oldRule.getRuleBaseValuesId(), oldRule);
192 if (!delegateFirst) {
193 responsibilityIds.addAll(getResponsibilityIdsFromGraph(oldRule, isGenerateRuleArs));
194 }
195
196 if (rule.getDelegateRule().booleanValue() && rule.getPreviousVersionId() != null) {
197 delegateFirst = true;
198 }
199
200 List oldDelegationRules = findOldDelegationRules(oldRule, rule, performanceLogger);
201 for (Iterator iterator = oldDelegationRules.iterator(); iterator.hasNext();) {
202 RuleBaseValues delegationRule = (RuleBaseValues) iterator.next();
203
204 performanceLogger.log("Setting previous delegation rule: " + delegationRule.getRuleBaseValuesId() + "to non current.");
205
206 delegationRule.setCurrentInd(Boolean.FALSE);
207 rulesToSave.put(delegationRule.getRuleBaseValuesId(), delegationRule);
208 responsibilityIds.addAll(getResponsibilityIdsFromGraph(delegationRule, isGenerateRuleArs));
209 }
210 }
211 for (Iterator iterator = rule.getResponsibilities().iterator(); iterator.hasNext();) {
212 RuleResponsibility responsibility = (RuleResponsibility) iterator.next();
213 for (Iterator delIterator = responsibility.getDelegationRules().iterator(); delIterator.hasNext();) {
214 RuleDelegation delegation = (RuleDelegation) delIterator.next();
215
216 delegation.getDelegationRuleBaseValues().setCurrentInd(Boolean.TRUE);
217 RuleBaseValues delegatorRule = delegation.getDelegationRuleBaseValues();
218
219 performanceLogger.log("Setting delegate rule: " + delegatorRule.getDescription() + " to current.");
220 if (delegatorRule.getActivationDate() == null) {
221 delegatorRule.setActivationDate(date);
222 }
223 try {
224 delegatorRule.setDeactivationDate(new Timestamp(RiceConstants.getDefaultDateFormat().parse("01/01/2100").getTime()));
225 } catch (Exception e) {
226 LOG.error("Parse Exception", e);
227 }
228 rulesToSave.put(delegatorRule.getRuleBaseValuesId(), delegatorRule);
229 }
230 }
231 }
232 Map<String, Long> notifyMap = new HashMap<String, Long>();
233 for (Iterator iterator = rulesToSave.values().iterator(); iterator.hasNext();) {
234 RuleBaseValues rule = (RuleBaseValues) iterator.next();
235 getRuleDAO().save(rule);
236 performanceLogger.log("Saved rule: " + rule.getRuleBaseValuesId());
237 installNotification(rule, notifyMap);
238 }
239 LOG.info("Notifying rule cache of "+notifyMap.size()+" cache changes.");
240 for (Iterator iterator = notifyMap.values().iterator(); iterator.hasNext();) {
241 queueRuleCache((Long)iterator.next());
242 }
243
244 getActionRequestService().updateActionRequestsForResponsibilityChange(responsibilityIds);
245 performanceLogger.log("Time to make current");
246 }
247
248
249
250
251
252
253
254
255
256
257
258 public void makeCurrent2(List rules) {
259 PerformanceLogger performanceLogger = new PerformanceLogger();
260
261 boolean isGenerateRuleArs = true;
262 String generateRuleArs = Utilities.getKNSParameterValue(KEWConstants.KEW_NAMESPACE, KNSConstants.DetailTypes.RULE_DETAIL_TYPE, KEWConstants.RULE_GENERATE_ACTION_REQESTS_IND);
263 if (!StringUtils.isBlank(generateRuleArs)) {
264 isGenerateRuleArs = KEWConstants.YES_RULE_CHANGE_AR_GENERATION_VALUE.equalsIgnoreCase(generateRuleArs);
265 }
266 Set<Long> responsibilityIds = new HashSet<Long>();
267 Map<Long, RuleBaseValues> rulesToSave = new HashMap<Long, RuleBaseValues>();
268
269 Collections.sort(rules, new RuleDelegationSorter());
270 for (Iterator iter = rules.iterator(); iter.hasNext();) {
271 RuleBaseValues rule = (RuleBaseValues) iter.next();
272
273 performanceLogger.log("Preparing rule: " + rule.getDescription());
274
275 rule.setCurrentInd(Boolean.TRUE);
276 Timestamp date = new Timestamp(System.currentTimeMillis());
277 rule.setActivationDate(date);
278 try {
279 rule.setDeactivationDate(new Timestamp(RiceConstants.getDefaultDateFormat().parse("01/01/2100").getTime()));
280 } catch (Exception e) {
281 LOG.error("Parse Exception", e);
282 }
283 rulesToSave.put(rule.getRuleBaseValuesId(), rule);
284 RuleBaseValues oldRule = rule.getPreviousVersion();
285 if (oldRule != null) {
286 performanceLogger.log("Setting previous rule: " + oldRule.getRuleBaseValuesId() + " to non current.");
287 oldRule.setCurrentInd(Boolean.FALSE);
288 oldRule.setDeactivationDate(date);
289 rulesToSave.put(oldRule.getRuleBaseValuesId(), oldRule);
290 responsibilityIds.addAll(getModifiedResponsibilityIds(oldRule, rule));
291 }
292 for (Iterator iterator = rule.getResponsibilities().iterator(); iterator.hasNext();) {
293 RuleResponsibility responsibility = (RuleResponsibility) iterator.next();
294 for (Iterator delIterator = responsibility.getDelegationRules().iterator(); delIterator.hasNext();) {
295 RuleDelegation delegation = (RuleDelegation) delIterator.next();
296 RuleBaseValues delegateRule = delegation.getDelegationRuleBaseValues();
297 delegateRule.setCurrentInd(Boolean.TRUE);
298 performanceLogger.log("Setting delegate rule: " + delegateRule.getDescription() + " to current.");
299 if (delegateRule.getActivationDate() == null) {
300 delegateRule.setActivationDate(date);
301 }
302 try {
303 delegateRule.setDeactivationDate(new Timestamp(RiceConstants.getDefaultDateFormat().parse("01/01/2100").getTime()));
304 } catch (Exception e) {
305 LOG.error("Parse Exception", e);
306 }
307 rulesToSave.put(delegateRule.getRuleBaseValuesId(), delegateRule);
308 }
309 }
310 }
311 Map<String, Long> notifyMap = new HashMap<String, Long>();
312 for (RuleBaseValues rule : rulesToSave.values()) {
313 getRuleDAO().save(rule);
314 performanceLogger.log("Saved rule: " + rule.getRuleBaseValuesId());
315 installNotification(rule, notifyMap);
316 }
317 LOG.info("Notifying rule cache of "+notifyMap.size()+" cache changes.");
318 for (Iterator iterator = notifyMap.values().iterator(); iterator.hasNext();) {
319 queueRuleCache((Long)iterator.next());
320 }
321 if (isGenerateRuleArs) {
322 getActionRequestService().updateActionRequestsForResponsibilityChange(responsibilityIds);
323 }
324 performanceLogger.log("Time to make current");
325 }
326
327
328
329
330
331
332 public void makeCurrent(RuleBaseValues rule, boolean isRetroactiveUpdatePermitted) {
333 makeCurrent(null, rule, isRetroactiveUpdatePermitted);
334 }
335
336 public void makeCurrent(RuleDelegation ruleDelegation, boolean isRetroactiveUpdatePermitted) {
337 makeCurrent(ruleDelegation, ruleDelegation.getDelegationRuleBaseValues(), isRetroactiveUpdatePermitted);
338 }
339
340 protected void makeCurrent(RuleDelegation ruleDelegation, RuleBaseValues rule, boolean isRetroactiveUpdatePermitted) {
341 PerformanceLogger performanceLogger = new PerformanceLogger();
342
343 boolean isGenerateRuleArs = false;
344 if (isRetroactiveUpdatePermitted) {
345 isGenerateRuleArs = true;
346 String generateRuleArs = Utilities.getKNSParameterValue(KEWConstants.KEW_NAMESPACE, KNSConstants.DetailTypes.RULE_DETAIL_TYPE, KEWConstants.RULE_GENERATE_ACTION_REQESTS_IND);
347 if (!StringUtils.isBlank(generateRuleArs)) {
348 isGenerateRuleArs = KEWConstants.YES_RULE_CHANGE_AR_GENERATION_VALUE.equalsIgnoreCase(generateRuleArs);
349 }
350 }
351 Set<Long> responsibilityIds = new HashSet<Long>();
352
353
354 performanceLogger.log("Preparing rule: " + rule.getDescription());
355
356 Map<Long, RuleBaseValues> rulesToSave = new HashMap<Long, RuleBaseValues>();
357 generateRuleNameIfNeeded(rule);
358 assignResponsibilityIds(rule);
359 rule.setCurrentInd(Boolean.TRUE);
360 Timestamp date = new Timestamp(System.currentTimeMillis());
361 rule.setActivationDate(date);
362 rule.setDeactivationDate(null);
363
364 rulesToSave.put(rule.getRuleBaseValuesId(), rule);
365 if (rule.getPreviousVersionId() != null) {
366 RuleBaseValues oldRule = findRuleBaseValuesById(rule.getPreviousVersionId());
367 rule.setPreviousVersion(oldRule);
368 }
369 rule.setVersionNbr(0);
370 RuleBaseValues oldRule = rule.getPreviousVersion();
371 if (oldRule != null) {
372 performanceLogger.log("Setting previous rule: " + oldRule.getRuleBaseValuesId() + " to non current.");
373 oldRule.setCurrentInd(Boolean.FALSE);
374 oldRule.setDeactivationDate(date);
375 rulesToSave.put(oldRule.getRuleBaseValuesId(), oldRule);
376 responsibilityIds.addAll(getModifiedResponsibilityIds(oldRule, rule));
377 rule.setVersionNbr(getNextVersionNumber(oldRule));
378 }
379
380
381 boolean isRuleDelegation = ruleDelegation != null;
382
383 Map<String, Long> notifyMap = new HashMap<String, Long>();
384
385 for (RuleBaseValues ruleToSave : rulesToSave.values()) {
386 getRuleDAO().save(ruleToSave);
387 performanceLogger.log("Saved rule: " + ruleToSave.getRuleBaseValuesId());
388 if (!isRuleDelegation) {
389 installNotification(ruleToSave, notifyMap);
390 }
391 }
392 if (isRuleDelegation) {
393 responsibilityIds.add(ruleDelegation.getResponsibilityId());
394 ruleDelegation.setDelegateRuleId(rule.getRuleBaseValuesId());
395 getRuleDelegationService().save(ruleDelegation);
396 installDelegationNotification(ruleDelegation.getResponsibilityId(), notifyMap);
397 }
398 LOG.info("Notifying rule cache of "+notifyMap.size()+" cache changes.");
399 for (Iterator iterator = notifyMap.values().iterator(); iterator.hasNext();) {
400 if (isRuleDelegation) {
401 queueDelegationRuleCache((Long)iterator.next());
402 } else {
403 queueRuleCache((Long)iterator.next());
404 }
405 }
406
407
408
409 if (isGenerateRuleArs) {
410 getActionRequestService().updateActionRequestsForResponsibilityChange(responsibilityIds);
411 }
412 performanceLogger.log("Time to make current");
413 }
414
415
416 private void queueRuleCache(Long ruleId){
417
418
419
420
421
422
423
424
425
426
427 RuleCacheProcessor ruleCacheProcessor = MessageServiceNames.getRuleCacheProcessor();
428 ruleCacheProcessor.clearRuleFromCache(ruleId);
429
430 }
431
432
433
434
435
436
437
438
439 private void installNotification(RuleBaseValues rule, Map<String, Long> notifyMap) {
440
441 if (!rule.getTemplateRuleInd()) {
442 String key = getRuleCacheKey(rule.getRuleTemplateName(), rule.getDocTypeName());
443 if (!notifyMap.containsKey(key)) {
444 notifyMap.put(key, rule.getRuleBaseValuesId());
445 }
446 }
447 }
448
449 private void queueDelegationRuleCache(Long responsibilityId) {
450 RuleDelegationCacheProcessor ruleDelegationCacheProcessor = (RuleDelegationCacheProcessor)KSBServiceLocator.getMessageHelper().getServiceAsynchronously(new QName("RuleDelegationCacheProcessorService"), null, null, null, null);
451 ruleDelegationCacheProcessor.clearRuleDelegationFromCache(responsibilityId);
452 }
453
454 private void installDelegationNotification(Long responsibilityId, Map<String, Long> notifyMap) {
455
456 String key = getRuleDlgnCacheKey(responsibilityId);
457 if (!notifyMap.containsKey(key)) {
458 notifyMap.put(key, responsibilityId);
459 }
460 }
461
462 protected String getRuleDlgnCacheKey(Long responsibilityId) {
463 return "RuleDlgnCache:" + responsibilityId;
464 }
465
466 public RuleBaseValues getParentRule(Long ruleBaseValuesId) {
467 return getRuleDAO().getParentRule(ruleBaseValuesId);
468 }
469
470 public void notifyCacheOfDocumentTypeChange(DocumentType documentType) {
471 DocumentType rootDocumentType = KEWServiceLocator.getDocumentTypeService().findRootDocumentType(documentType);
472 notifyCacheOfDocumentTypeChangeFromRoot(rootDocumentType, documentType);
473 notifyCacheOfDocumentTypeChangeFromParent(documentType);
474 }
475
476
477
478
479
480 protected void notifyCacheOfDocumentTypeChangeFromParent(DocumentType documentType) {
481 flushDocumentTypeFromCache(documentType.getName());
482 for (Iterator iter = documentType.getChildrenDocTypes().iterator(); iter.hasNext();) {
483 notifyCacheOfDocumentTypeChangeFromParent((DocumentType) iter.next());
484 }
485 }
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502 protected void notifyCacheOfDocumentTypeChangeFromRoot(DocumentType rootDocumentType, DocumentType documentType) {
503 if (rootDocumentType.getName().equals(documentType.getName())) {
504 return;
505 }
506 flushDocumentTypeFromCache(rootDocumentType.getName());
507 for (Iterator iter = rootDocumentType.getChildrenDocTypes().iterator(); iter.hasNext();) {
508 notifyCacheOfDocumentTypeChangeFromRoot((DocumentType) iter.next(), documentType);
509 }
510 }
511
512 public void notifyCacheOfRuleChange(RuleBaseValues rule, DocumentType documentType) {
513 Boolean cachingRules = Boolean.valueOf(Utilities.getKNSParameterBooleanValue(KEWConstants.KEW_NAMESPACE, KNSConstants.DetailTypes.RULE_DETAIL_TYPE, USING_RULE_CACHE_IND));
514
515 LOG.info("Entering notifyCacheOfRuleChange. CachingRules: " + cachingRules + " ; ruleID: " + rule.getRuleBaseValuesId());
516 if (!cachingRules.booleanValue()) {
517 return;
518 }
519
520
521 String ruleTemplateName = null;
522 if (rule.getRuleTemplate() == null) {
523 if (rule.getPreviousVersion() != null) {
524 RuleBaseValues prev = rule.getPreviousVersion();
525 if (prev.getRuleTemplate() != null) {
526 ruleTemplateName = prev.getRuleTemplate().getName();
527 }
528 }
529 } else {
530 ruleTemplateName = rule.getRuleTemplate().getName();
531 }
532
533 if (documentType == null) {
534 documentType = getDocumentTypeService().findByName(rule.getDocTypeName());
535
536 if (Boolean.TRUE.equals(rule.getDelegateRule())) {
537 List delegations = getRuleDelegationService().findByDelegateRuleId(rule.getRuleBaseValuesId());
538 for (Iterator iterator = delegations.iterator(); iterator.hasNext();) {
539 RuleDelegation ruleDelegation = (RuleDelegation) iterator.next();
540 RuleBaseValues parentRule = ruleDelegation.getRuleResponsibility().getRuleBaseValues();
541 if (Boolean.TRUE.equals(parentRule.getCurrentInd())) {
542 ruleTemplateName = parentRule.getRuleTemplate().getName();
543 break;
544 }
545 }
546 }
547 }
548 flushListFromCache(ruleTemplateName, documentType.getName());
549
550
551
552
553
554
555
556
557 for (Iterator iter = documentType.getChildrenDocTypes().iterator(); iter.hasNext();) {
558 DocumentType childDocumentType = (DocumentType) iter.next();
559
560
561
562
563 notifyCacheOfRuleChange(rule, childDocumentType);
564 }
565 LOG.info("Leaving notifyCacheOfRuleChange. CachingRules: " + cachingRules + " ; ruleID: " + rule.getRuleBaseValuesId() + " ; documentType: " + documentType.getDocumentTypeId());
566
567
568
569 }
570
571
572
573
574 protected String getRuleCacheKey(String ruleTemplateName, String docTypeName) {
575 return "RuleCache:" + ruleTemplateName + "_" + docTypeName;
576 }
577
578
579
580
581 protected String getDocumentTypeRuleCacheGroupName(String documentTypeName) {
582 return "DocumentTypeRuleCache:"+documentTypeName;
583 }
584
585 protected List<RuleBaseValues> getListFromCache(String ruleTemplateName, String documentTypeName) {
586 LOG.debug("Retrieving List of Rules from cache for ruleTemplate='" + ruleTemplateName + "' and documentType='" + documentTypeName + "'");
587 return (List) KEWServiceLocator.getCacheAdministrator().getFromCache(getRuleCacheKey(ruleTemplateName, documentTypeName));
588
589 }
590
591 protected void putListInCache(String ruleTemplateName, String documentTypeName, List<RuleBaseValues> rules) {
592 assert(ruleTemplateName != null) : "putListInCache was called with a null ruleTemplateName";
593 LOG.info("Caching " + rules.size() + " rules for ruleTemplate='" + ruleTemplateName + "' and documentType='" + documentTypeName + "'");
594 String groups[] = new String[] { getDocumentTypeRuleCacheGroupName(documentTypeName), RULE_GROUP_CACHE };
595 KEWServiceLocator.getCacheAdministrator().putInCache(getRuleCacheKey(ruleTemplateName, documentTypeName), rules, groups);
596 }
597
598 protected void flushDocumentTypeFromCache(String documentTypeName) {
599 LOG.info("Flushing DocumentType from Cache for the given name: " + documentTypeName);
600 KEWServiceLocator.getCacheAdministrator().flushGroup(getDocumentTypeRuleCacheGroupName(documentTypeName));
601 }
602
603 protected void flushListFromCache(String ruleTemplateName, String documentTypeName) {
604 LOG.info("Flushing rules from Cache for ruleTemplate='" + ruleTemplateName + "' and documentType='" + documentTypeName + "'");
605 KEWServiceLocator.getCacheAdministrator().flushEntry(getRuleCacheKey(ruleTemplateName, documentTypeName));
606 }
607
608 public void flushRuleCache() {
609 LOG.info("Flushing entire Rule Cache.");
610 KEWServiceLocator.getCacheAdministrator().flushGroup(RULE_GROUP_CACHE);
611 }
612
613 private Set getResponsibilityIdsFromGraph(RuleBaseValues rule, boolean isRuleCollecting) {
614 Set responsibilityIds = new HashSet();
615 for (Iterator iterator = rule.getResponsibilities().iterator(); iterator.hasNext();) {
616 RuleResponsibility responsibility = (RuleResponsibility) iterator.next();
617 if (isRuleCollecting) {
618 responsibilityIds.add(responsibility.getResponsibilityId());
619 }
620 }
621 return responsibilityIds;
622 }
623
624
625
626
627
628 private Set<Long> getModifiedResponsibilityIds(RuleBaseValues oldRule, RuleBaseValues newRule) {
629 Map<Long, RuleResponsibility> modifiedResponsibilityMap = new HashMap<Long, RuleResponsibility>();
630 for (Iterator iterator = oldRule.getResponsibilities().iterator(); iterator.hasNext();) {
631 RuleResponsibility responsibility = (RuleResponsibility) iterator.next();
632 modifiedResponsibilityMap.put(responsibility.getResponsibilityId(), responsibility);
633 }
634 for (Iterator iterator = newRule.getResponsibilities().iterator(); iterator.hasNext();) {
635 RuleResponsibility responsibility = (RuleResponsibility) iterator.next();
636 RuleResponsibility oldResponsibility = modifiedResponsibilityMap.get(responsibility.getResponsibilityId());
637 if (oldResponsibility == null) {
638
639 modifiedResponsibilityMap.put(responsibility.getResponsibilityId(), responsibility);
640 } else if (!hasResponsibilityChanged(oldResponsibility, responsibility)) {
641
642 modifiedResponsibilityMap.remove(responsibility.getResponsibilityId());
643 }
644 }
645 return modifiedResponsibilityMap.keySet();
646 }
647
648
649
650
651 private boolean hasResponsibilityChanged(RuleResponsibility oldResponsibility, RuleResponsibility newResponsibility) {
652 return !ObjectUtils.equals(oldResponsibility.getActionRequestedCd(), newResponsibility.getActionRequestedCd()) ||
653 !ObjectUtils.equals(oldResponsibility.getApprovePolicy(), newResponsibility.getActionRequestedCd()) ||
654 !ObjectUtils.equals(oldResponsibility.getPriority(), newResponsibility.getPriority()) ||
655 !ObjectUtils.equals(oldResponsibility.getRole(), newResponsibility.getRole()) ||
656 !ObjectUtils.equals(oldResponsibility.getRuleResponsibilityName(), newResponsibility.getRuleResponsibilityName()) ||
657 !ObjectUtils.equals(oldResponsibility.getRuleResponsibilityType(), newResponsibility.getRuleResponsibilityType());
658 }
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689 private List findOldDelegationRules(RuleBaseValues oldRule, RuleBaseValues newRule, PerformanceLogger performanceLogger) {
690 performanceLogger.log("Begin to get delegation rules.");
691 List oldDelegations = getRuleDAO().findOldDelegations(oldRule, newRule);
692 performanceLogger.log("Located "+oldDelegations.size()+" old delegation rules.");
693 return oldDelegations;
694 }
695
696 public Long route2(Long routeHeaderId, MyRules2 myRules, KimPrincipal principal, String annotation, boolean blanketApprove) throws Exception {
697 List errors = new ArrayList();
698 if (myRules.getRules().isEmpty()) {
699 errors.add(new WorkflowServiceErrorImpl("Rule required", "rule.required"));
700 }
701 if (!errors.isEmpty()) {
702 throw new WorkflowServiceErrorException("RuleBaseValues validation errors", errors);
703 }
704 WorkflowDocument workflowDocument = null;
705 if (routeHeaderId == null) {
706 workflowDocument = new WorkflowDocument(new WorkflowIdDTO(principal.getPrincipalId()), getRuleDocmentTypeName(myRules.getRules()));
707 } else {
708 workflowDocument = new WorkflowDocument(new WorkflowIdDTO(principal.getPrincipalId()), routeHeaderId);
709 }
710
711 for (Iterator iter = myRules.getRules().iterator(); iter.hasNext();) {
712 RuleBaseValues rule = (RuleBaseValues) iter.next();
713 rule.setRouteHeaderId(workflowDocument.getRouteHeaderId());
714
715 workflowDocument.addAttributeDefinition(new RuleRoutingDefinition(rule.getDocTypeName()));
716 getRuleDAO().retrieveAllReferences(rule);
717 save2(rule);
718 }
719
720 workflowDocument.setTitle(generateTitle(myRules));
721 if (blanketApprove) {
722 workflowDocument.blanketApprove(annotation);
723 } else {
724 workflowDocument.routeDocument(annotation);
725 }
726 return workflowDocument.getRouteHeaderId();
727 }
728
729 public Long routeRuleWithDelegate(Long routeHeaderId, RuleBaseValues parentRule, RuleBaseValues delegateRule, KimPrincipal principal, String annotation, boolean blanketApprove) throws Exception {
730 if (parentRule == null) {
731 throw new IllegalArgumentException("Cannot route a delegate without a parent rule.");
732 }
733 if (parentRule.getDelegateRule().booleanValue()) {
734 throw new IllegalArgumentException("Parent rule cannot be a delegate.");
735 }
736 if (parentRule.getPreviousVersionId() == null && delegateRule.getPreviousVersionId() == null) {
737 throw new IllegalArgumentException("Previous rule version required.");
738 }
739
740
741
742
743
744
745
746
747
748
749
750
751
752 RuleDelegation ruleDelegation = getRuleDelegation(parentRule, delegateRule);
753
754 save2(delegateRule, ruleDelegation, true);
755
756
757
758
759 boolean isRoutingParent = parentRule.getRuleBaseValuesId() == null;
760 if (isRoutingParent) {
761
762
763
764 save2(parentRule, null, false);
765
766 }
767
768 WorkflowDocument workflowDocument = null;
769 if (routeHeaderId != null) {
770 workflowDocument = new WorkflowDocument(new WorkflowIdDTO(principal.getPrincipalId()), routeHeaderId);
771 } else {
772 List rules = new ArrayList();
773 rules.add(delegateRule);
774 rules.add(parentRule);
775 workflowDocument = new WorkflowDocument(new WorkflowIdDTO(principal.getPrincipalId()), getRuleDocmentTypeName(rules));
776 }
777 workflowDocument.setTitle(generateTitle(parentRule, delegateRule));
778 delegateRule.setRouteHeaderId(workflowDocument.getRouteHeaderId());
779 workflowDocument.addAttributeDefinition(new RuleRoutingDefinition(parentRule.getDocTypeName()));
780 getRuleDAO().save(delegateRule);
781 if (isRoutingParent) {
782 parentRule.setRouteHeaderId(workflowDocument.getRouteHeaderId());
783 getRuleDAO().save(parentRule);
784 }
785 if (blanketApprove) {
786 workflowDocument.blanketApprove(annotation);
787 } else {
788 workflowDocument.routeDocument(annotation);
789 }
790 return workflowDocument.getRouteHeaderId();
791 }
792
793
794
795
796 private RuleDelegation getRuleDelegation(RuleBaseValues parentRule, RuleBaseValues delegateRule) throws Exception {
797 for (Iterator iterator = parentRule.getResponsibilities().iterator(); iterator.hasNext(); ) {
798 RuleResponsibility responsibility = (RuleResponsibility) iterator.next();
799 for (Iterator respIt = responsibility.getDelegationRules().iterator(); respIt.hasNext(); ) {
800 RuleDelegation ruleDelegation = (RuleDelegation) respIt.next();
801
802 if (ruleDelegation.getDelegationRuleBaseValues().equals(delegateRule)) {
803 return ruleDelegation;
804 }
805 }
806 }
807 return null;
808 }
809
810 private String generateTitle(RuleBaseValues parentRule, RuleBaseValues delegateRule) {
811 StringBuffer title = new StringBuffer();
812 if (delegateRule.getPreviousVersionId() != null) {
813 title.append("Editing Delegation Rule '").append(delegateRule.getDescription()).append("' on '");
814 } else {
815 title.append("Adding Delegation Rule '").append(delegateRule.getDescription()).append("' to '");
816 }
817 title.append(parentRule.getDescription()).append("'");
818 return title.toString();
819 }
820
821 private String generateTitle(MyRules2 myRules) {
822 StringBuffer title = new StringBuffer();
823 RuleBaseValues firstRule = myRules.getRule(0);
824 if (myRules.getRules().size() > 1) {
825 title.append("Routing ").append(myRules.getSize()).append(" Rules, '");
826 title.append(firstRule.getDescription()).append("',...");
827 } else if (firstRule.getPreviousVersionId() != null) {
828 title.append("Editing Rule '").append(firstRule.getDescription()).append("'");
829 } else {
830 title.append("Adding Rule '").append(firstRule.getDescription()).append("'");
831 }
832 return title.toString();
833 }
834
835 public void validate(RuleBaseValues ruleBaseValues, List errors) {
836 if (errors == null) {
837 errors = new ArrayList();
838 }
839 if (getDocumentTypeService().findByName(ruleBaseValues.getDocTypeName()) == null) {
840 errors.add(new WorkflowServiceErrorImpl("Document Type Invalid", "doctype.documenttypeservice.doctypename.required"));
841 }
842 if (ruleBaseValues.getToDate().before(ruleBaseValues.getFromDate())) {
843 errors.add(new WorkflowServiceErrorImpl("From Date is later than to date", "routetemplate.ruleservice.daterange.fromafterto"));
844 }
845 if (ruleBaseValues.getActiveInd() == null) {
846 errors.add(new WorkflowServiceErrorImpl("Active Indicator is required", "routetemplate.ruleservice.activeind.required"));
847 }
848 if (ruleBaseValues.getDescription() == null || ruleBaseValues.getDescription().equals("")) {
849 errors.add(new WorkflowServiceErrorImpl("Description is required", "routetemplate.ruleservice.description.required"));
850 }
851 if (ruleBaseValues.getForceAction() == null) {
852 errors.add(new WorkflowServiceErrorImpl("Force Action is required", "routetemplate.ruleservice.forceAction.required"));
853 }
854 if (ruleBaseValues.getResponsibilities().isEmpty()) {
855 errors.add(new WorkflowServiceErrorImpl("A responsibility is required", "routetemplate.ruleservice.responsibility.required"));
856 } else {
857 for (Iterator iter = ruleBaseValues.getResponsibilities().iterator(); iter.hasNext();) {
858 RuleResponsibility responsibility = (RuleResponsibility) iter.next();
859 if (responsibility.getRuleResponsibilityName() != null && KEWConstants.RULE_RESPONSIBILITY_GROUP_ID.equals(responsibility.getRuleResponsibilityType())) {
860 if (getIdentityManagementService().getGroup(responsibility.getRuleResponsibilityName()) == null) {
861 errors.add(new WorkflowServiceErrorImpl("Workgroup is invalid", "routetemplate.ruleservice.workgroup.invalid"));
862 }
863 } else if (responsibility.getPrincipal() == null && responsibility.getRole() == null) {
864 errors.add(new WorkflowServiceErrorImpl("User is invalid", "routetemplate.ruleservice.user.invalid"));
865 }
866 }
867 }
868 if (!errors.isEmpty()) {
869 throw new WorkflowServiceErrorException("RuleBaseValues validation errors", errors);
870 }
871 }
872
873 public void validate2(RuleBaseValues ruleBaseValues, RuleDelegation ruleDelegation, List errors) {
874 if (errors == null) {
875 errors = new ArrayList();
876 }
877 if (getDocumentTypeService().findByName(ruleBaseValues.getDocTypeName()) == null) {
878 errors.add(new WorkflowServiceErrorImpl("Document Type Invalid", "doctype.documenttypeservice.doctypename.required"));
879 LOG.error("Document Type Invalid");
880 }
881 if (ruleBaseValues.getToDate() == null) {
882 try {
883 ruleBaseValues.setToDate(new Timestamp(RiceConstants.getDefaultDateFormat().parse("01/01/2100").getTime()));
884 } catch (ParseException e) {
885 LOG.error("Error date-parsing default date");
886 throw new WorkflowServiceErrorException("Error parsing default date.", e);
887 }
888 }
889 if (ruleBaseValues.getFromDate() == null) {
890 ruleBaseValues.setFromDate(new Timestamp(System.currentTimeMillis()));
891 }
892 if (ruleBaseValues.getToDate().before(ruleBaseValues.getFromDate())) {
893 errors.add(new WorkflowServiceErrorImpl("From Date is later than to date", "routetemplate.ruleservice.daterange.fromafterto"));
894 LOG.error("From Date is later than to date");
895 }
896 if (ruleBaseValues.getActiveInd() == null) {
897 errors.add(new WorkflowServiceErrorImpl("Active Indicator is required", "routetemplate.ruleservice.activeind.required"));
898 LOG.error("Active Indicator is missing");
899 }
900 if (ruleBaseValues.getDescription() == null || ruleBaseValues.getDescription().equals("")) {
901 errors.add(new WorkflowServiceErrorImpl("Description is required", "routetemplate.ruleservice.description.required"));
902 LOG.error("Description is missing");
903 }
904 if (ruleBaseValues.getForceAction() == null) {
905 errors.add(new WorkflowServiceErrorImpl("Force Action is required", "routetemplate.ruleservice.forceAction.required"));
906 LOG.error("Force Action is missing");
907 }
908
909 for (Iterator iter = ruleBaseValues.getResponsibilities().iterator(); iter.hasNext();) {
910 RuleResponsibility responsibility = (RuleResponsibility) iter.next();
911 if (responsibility.getRuleResponsibilityName() != null && KEWConstants.RULE_RESPONSIBILITY_GROUP_ID.equals(responsibility.getRuleResponsibilityType())) {
912 if (getIdentityManagementService().getGroup(responsibility.getRuleResponsibilityName()) == null) {
913 errors.add(new WorkflowServiceErrorImpl("Workgroup is invalid", "routetemplate.ruleservice.workgroup.invalid"));
914 LOG.error("Workgroup is invalid");
915 }
916 } else if (responsibility.getPrincipal() == null && responsibility.getRole() == null) {
917 errors.add(new WorkflowServiceErrorImpl("User is invalid", "routetemplate.ruleservice.user.invalid"));
918 LOG.error("User is invalid");
919 } else if (responsibility.isUsingRole()) {
920 if (responsibility.getApprovePolicy() == null || !(responsibility.getApprovePolicy().equals(KEWConstants.APPROVE_POLICY_ALL_APPROVE) || responsibility.getApprovePolicy().equals(KEWConstants.APPROVE_POLICY_FIRST_APPROVE))) {
921 errors.add(new WorkflowServiceErrorImpl("Approve Policy is Invalid", "routetemplate.ruleservice.approve.policy.invalid"));
922 LOG.error("Approve Policy is Invalid");
923 }
924 }
925 }
926
927 if (ruleBaseValues.getRuleTemplate() != null) {
928 for (Iterator iter = ruleBaseValues.getRuleTemplate().getActiveRuleTemplateAttributes().iterator(); iter.hasNext();) {
929 RuleTemplateAttribute templateAttribute = (RuleTemplateAttribute) iter.next();
930 if (!templateAttribute.isRuleValidationAttribute()) {
931 continue;
932 }
933 RuleValidationAttribute attribute = templateAttribute.getRuleValidationAttribute();
934 UserSession userSession = UserSession.getAuthenticatedUser();
935 try {
936 RuleValidationContext validationContext = new RuleValidationContext(ruleBaseValues, ruleDelegation, userSession);
937 ValidationResults results = attribute.validate(validationContext);
938 if (results != null && !results.getValidationResults().isEmpty()) {
939 errors.add(results);
940 }
941 } catch (Exception e) {
942 if (e instanceof RuntimeException) {
943 throw (RuntimeException)e;
944 }
945 throw new RuntimeException("Problem validation rule.", e);
946 }
947
948 }
949 }
950 if (ruleBaseValues.getRuleExpressionDef() != null) {
951
952 }
953
954 if (!errors.isEmpty()) {
955 throw new WorkflowServiceErrorException("RuleBaseValues validation errors", errors);
956 }
957 }
958
959 public List findByRouteHeaderId(Long routeHeaderId) {
960 return getRuleDAO().findByRouteHeaderId(routeHeaderId);
961 }
962
963 public List search(String docTypeName, Long ruleId, Long ruleTemplateId, String ruleDescription, String groupId, String principalId,
964 Boolean delegateRule, Boolean activeInd, Map extensionValues, String workflowIdDirective) {
965 return getRuleDAO().search(docTypeName, ruleId, ruleTemplateId, ruleDescription, groupId, principalId, delegateRule,
966 activeInd, extensionValues, workflowIdDirective);
967 }
968
969 public List search(String docTypeName, String ruleTemplateName, String ruleDescription, String groupId, String principalId,
970 Boolean workgroupMember, Boolean delegateRule, Boolean activeInd, Map extensionValues, Collection<String> actionRequestCodes) {
971
972 if ( (StringUtils.isEmpty(docTypeName)) &&
973 (StringUtils.isEmpty(ruleTemplateName)) &&
974 (StringUtils.isEmpty(ruleDescription)) &&
975 (StringUtils.isEmpty(groupId)) &&
976 (StringUtils.isEmpty(principalId)) &&
977 (extensionValues.isEmpty()) &&
978 (actionRequestCodes.isEmpty()) ) {
979
980 throw new IllegalArgumentException("At least one criterion must be sent");
981 }
982
983 RuleTemplate ruleTemplate = getRuleTemplateService().findByRuleTemplateName(ruleTemplateName);
984 Long ruleTemplateId = null;
985 if (ruleTemplate != null) {
986 ruleTemplateId = ruleTemplate.getRuleTemplateId();
987 }
988
989 if ( ( (extensionValues != null) && (!extensionValues.isEmpty()) ) &&
990 (ruleTemplateId == null) ) {
991
992 throw new IllegalArgumentException("A Rule Template Name must be given if using Rule Extension values");
993 }
994
995 Collection<String> workgroupIds = new ArrayList<String>();
996 if (principalId != null) {
997 KEWServiceLocator.getIdentityHelperService().validatePrincipalId(principalId);
998 if ( (workgroupMember == null) || (workgroupMember.booleanValue()) ) {
999 workgroupIds = getIdentityManagementService().getGroupIdsForPrincipal(principalId);
1000 } else {
1001
1002 }
1003 } else if (groupId != null) {
1004 Group group = KEWServiceLocator.getIdentityHelperService().getGroup(groupId);
1005 if (group == null) {
1006 throw new IllegalArgumentException("Group does not exist in for given group id: " + groupId);
1007 } else {
1008 workgroupIds.add(group.getGroupId());
1009 }
1010 }
1011
1012 return getRuleDAO().search(docTypeName, ruleTemplateId, ruleDescription, workgroupIds, principalId,
1013 delegateRule,activeInd, extensionValues, actionRequestCodes);
1014 }
1015
1016 public void delete(Long ruleBaseValuesId) {
1017 getRuleDAO().delete(ruleBaseValuesId);
1018 }
1019
1020 public RuleBaseValues findRuleBaseValuesById(Long ruleBaseValuesId) {
1021 return getRuleDAO().findRuleBaseValuesById(ruleBaseValuesId);
1022 }
1023
1024 public RuleResponsibility findRuleResponsibility(Long responsibilityId) {
1025 return getRuleDAO().findRuleResponsibility(responsibilityId);
1026 }
1027
1028 public List fetchAllCurrentRulesForTemplateDocCombination(String ruleTemplateName, String documentType, boolean ignoreCache) {
1029 PerformanceLogger performanceLogger = new PerformanceLogger();
1030 Boolean cachingRules = Boolean.valueOf(Utilities.getKNSParameterBooleanValue(KEWConstants.KEW_NAMESPACE, KNSConstants.DetailTypes.RULE_DETAIL_TYPE, USING_RULE_CACHE_IND));
1031 if (cachingRules.booleanValue()) {
1032
1033 List<RuleBaseValues> rules = getListFromCache(ruleTemplateName, documentType);
1034 if (rules != null && !ignoreCache) {
1035 performanceLogger.log("Time to fetchRules by template " + ruleTemplateName + " cached.");
1036 return rules;
1037 }
1038 RuleTemplate ruleTemplate = getRuleTemplateService().findByRuleTemplateName(ruleTemplateName);
1039 if (ruleTemplate == null) {
1040 return Collections.EMPTY_LIST;
1041 }
1042 Long ruleTemplateId = ruleTemplate.getRuleTemplateId();
1043
1044
1045 rules = getRuleDAO().fetchAllCurrentRulesForTemplateDocCombination(ruleTemplateId, getDocGroupAndTypeList(documentType));
1046
1047 putListInCache(ruleTemplateName, documentType, rules);
1048
1049 performanceLogger.log("Time to fetchRules by template " + ruleTemplateName + " cache refreshed.");
1050 return rules;
1051 } else {
1052 Long ruleTemplateId = getRuleTemplateService().findByRuleTemplateName(ruleTemplateName).getRuleTemplateId();
1053 performanceLogger.log("Time to fetchRules by template " + ruleTemplateName + " not caching.");
1054 return getRuleDAO().fetchAllCurrentRulesForTemplateDocCombination(ruleTemplateId, getDocGroupAndTypeList(documentType));
1055 }
1056 }
1057
1058 public List fetchAllCurrentRulesForTemplateDocCombination(String ruleTemplateName, String documentType) {
1059 return fetchAllCurrentRulesForTemplateDocCombination(ruleTemplateName, documentType, false);
1060 }
1061
1062 public List fetchAllCurrentRulesForTemplateDocCombination(String ruleTemplateName, String documentType, Timestamp effectiveDate){
1063 Long ruleTemplateId = getRuleTemplateService().findByRuleTemplateName(ruleTemplateName).getRuleTemplateId();
1064 PerformanceLogger performanceLogger = new PerformanceLogger();
1065 performanceLogger.log("Time to fetchRules by template " + ruleTemplateName + " not caching.");
1066 return getRuleDAO().fetchAllCurrentRulesForTemplateDocCombination(ruleTemplateId, getDocGroupAndTypeList(documentType), effectiveDate);
1067 }
1068 public List fetchAllRules(boolean currentRules) {
1069 return getRuleDAO().fetchAllRules(currentRules);
1070 }
1071
1072 private List getDocGroupAndTypeList(String documentType) {
1073 List docTypeList = new ArrayList();
1074 DocumentTypeService docTypeService = (DocumentTypeService) KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE);
1075 DocumentType docType = docTypeService.findByName(documentType);
1076 while (docType != null) {
1077 docTypeList.add(docType.getName());
1078 docType = docType.getParentDocType();
1079 }
1080 return docTypeList;
1081 }
1082
1083 private Integer getNextVersionNumber(RuleBaseValues currentRule) {
1084 List candidates = new ArrayList();
1085 candidates.add(currentRule.getVersionNbr());
1086 List pendingRules = ruleDAO.findByPreviousVersionId(currentRule.getRuleBaseValuesId());
1087 for (Iterator iterator = pendingRules.iterator(); iterator.hasNext();) {
1088 RuleBaseValues pendingRule = (RuleBaseValues) iterator.next();
1089 candidates.add(pendingRule.getVersionNbr());
1090 }
1091 Collections.sort(candidates);
1092 Integer maxVersionNumber = (Integer) candidates.get(candidates.size() - 1);
1093 if (maxVersionNumber == null) {
1094 return Integer.valueOf(0);
1095 }
1096 return Integer.valueOf(maxVersionNumber.intValue() + 1);
1097 }
1098
1099
1100
1101
1102
1103
1104
1105
1106 public Long isLockedForRouting(Long currentRuleBaseValuesId) {
1107
1108
1109 List pendingRules = ruleDAO.findByPreviousVersionId(currentRuleBaseValuesId);
1110 boolean isDead = true;
1111 for (Iterator iterator = pendingRules.iterator(); iterator.hasNext();) {
1112 RuleBaseValues pendingRule = (RuleBaseValues) iterator.next();
1113
1114 if (pendingRule.getRouteHeaderId() != null && pendingRule.getRouteHeaderId().longValue() != 0) {
1115 DocumentRouteHeaderValue routeHeader = getRouteHeaderService().getRouteHeader(pendingRule.getRouteHeaderId());
1116
1117 isDead = routeHeader.isDisaproved() || routeHeader.isCanceled();
1118 if (!isDead) {
1119 return pendingRule.getRouteHeaderId();
1120 }
1121 }
1122 for (Iterator iter = pendingRule.getResponsibilities().iterator(); iter.hasNext();) {
1123 RuleResponsibility responsibility = (RuleResponsibility) iter.next();
1124 for (Iterator iterator2 = responsibility.getDelegationRules().iterator(); iterator2.hasNext();) {
1125 RuleDelegation delegation = (RuleDelegation) iterator2.next();
1126 List pendingDelegateRules = ruleDAO.findByPreviousVersionId(delegation.getDelegationRuleBaseValues().getRuleBaseValuesId());
1127 for (Iterator iterator3 = pendingDelegateRules.iterator(); iterator3.hasNext();) {
1128 RuleBaseValues pendingDelegateRule = (RuleBaseValues) iterator3.next();
1129 if (pendingDelegateRule.getRouteHeaderId() != null && pendingDelegateRule.getRouteHeaderId().longValue() != 0) {
1130 DocumentRouteHeaderValue routeHeader = getRouteHeaderService().getRouteHeader(pendingDelegateRule.getRouteHeaderId());
1131 isDead = routeHeader.isDisaproved() || routeHeader.isCanceled();
1132 if (!isDead) {
1133 return pendingDelegateRule.getRouteHeaderId();
1134 }
1135 }
1136 }
1137 }
1138 }
1139 }
1140 return null;
1141 }
1142
1143 public RuleBaseValues getParentRule(RuleBaseValues rule) {
1144 if (rule == null || rule.getRuleBaseValuesId() == null) {
1145 throw new IllegalArgumentException("Rule must be non-null with non-null id: " + rule);
1146 }
1147 if (!Boolean.TRUE.equals(rule.getDelegateRule())) {
1148 return null;
1149 }
1150 return getRuleDAO().getParentRule(rule.getRuleBaseValuesId());
1151 }
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175 public String getRuleDocmentTypeName(List rules) {
1176 if (rules.size() == 0) {
1177 throw new IllegalArgumentException("Cannot determine rule DocumentType for an empty list of rules.");
1178 }
1179 String ruleDocTypeName = null;
1180 RuleRoutingConfig config = RuleRoutingConfig.parse();
1181
1182 RuleBaseValues firstRule = (RuleBaseValues)rules.get(0);
1183 if (Boolean.TRUE.equals(firstRule.getDelegateRule())) {
1184
1185
1186 ruleDocTypeName = config.getDocumentTypeName(firstRule);
1187 } else {
1188
1189
1190 String parentRulesDocTypeName = null;
1191 for (Iterator iterator = rules.iterator(); iterator.hasNext();) {
1192 RuleBaseValues rule = (RuleBaseValues) iterator.next();
1193
1194 if (Boolean.TRUE.equals(rule.getDelegateRule())) {
1195 continue;
1196 }
1197 String currentDocTypeName = config.getDocumentTypeName(rule);
1198 if (parentRulesDocTypeName == null) {
1199 parentRulesDocTypeName = currentDocTypeName;
1200 } else {
1201 if (!Utilities.equals(currentDocTypeName, parentRulesDocTypeName)) {
1202 throw new RuntimeException("There are multiple rules being routed and they have different document type definitions! " + parentRulesDocTypeName + " and " + currentDocTypeName);
1203 }
1204 }
1205 }
1206 ruleDocTypeName = parentRulesDocTypeName;
1207 }
1208 if (ruleDocTypeName == null) {
1209 ruleDocTypeName = KEWConstants.DEFAULT_RULE_DOCUMENT_NAME;
1210 }
1211 return ruleDocTypeName;
1212 }
1213
1214 public void setRuleDAO(RuleDAO ruleDAO) {
1215 this.ruleDAO = ruleDAO;
1216 }
1217
1218 public RuleDAO getRuleDAO() {
1219 return ruleDAO;
1220 }
1221
1222 public void deleteRuleResponsibilityById(Long ruleResponsibilityId) {
1223 getRuleResponsibilityDAO().delete(ruleResponsibilityId);
1224 }
1225
1226 public RuleResponsibility findByRuleResponsibilityId(Long ruleResponsibilityId) {
1227 return getRuleResponsibilityDAO().findByRuleResponsibilityId(ruleResponsibilityId);
1228 }
1229
1230 public List findRuleBaseValuesByResponsibilityReviewer(String reviewerName, String type) {
1231 return getRuleDAO().findRuleBaseValuesByResponsibilityReviewer(reviewerName, type);
1232 }
1233
1234 public List findRuleBaseValuesByResponsibilityReviewerTemplateDoc(String ruleTemplateName, String documentType, String reviewerName, String type) {
1235 return getRuleDAO().findRuleBaseValuesByResponsibilityReviewerTemplateDoc(ruleTemplateName, documentType, reviewerName, type);
1236 }
1237
1238 public RuleTemplateService getRuleTemplateService() {
1239 return (RuleTemplateService) KEWServiceLocator.getService(KEWServiceLocator.RULE_TEMPLATE_SERVICE);
1240 }
1241
1242 public DocumentTypeService getDocumentTypeService() {
1243 return (DocumentTypeService) KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE);
1244 }
1245
1246 public IdentityManagementService getIdentityManagementService() {
1247 return (IdentityManagementService) KIMServiceLocator.getService(KIMServiceLocator.KIM_IDENTITY_MANAGEMENT_SERVICE);
1248 }
1249
1250 public ActionRequestService getActionRequestService() {
1251 return (ActionRequestService) KEWServiceLocator.getService(KEWServiceLocator.ACTION_REQUEST_SRV);
1252 }
1253
1254 private ResponsibilityIdService getResponsibilityIdService() {
1255 return (ResponsibilityIdService) KEWServiceLocator.getService(KEWServiceLocator.RESPONSIBILITY_ID_SERVICE);
1256 }
1257
1258 private RuleDelegationService getRuleDelegationService() {
1259 return (RuleDelegationService) KEWServiceLocator.getService(KEWServiceLocator.RULE_DELEGATION_SERVICE);
1260 }
1261
1262 private RouteHeaderService getRouteHeaderService() {
1263 return (RouteHeaderService) KEWServiceLocator.getService(KEWServiceLocator.DOC_ROUTE_HEADER_SRV);
1264 }
1265
1266
1267
1268
1269 public class RuleDelegationSorter implements Comparator {
1270 public int compare(Object arg0, Object arg1) {
1271 RuleBaseValues rule1 = (RuleBaseValues) arg0;
1272 RuleBaseValues rule2 = (RuleBaseValues) arg1;
1273
1274 Integer rule1Value = new Integer((rule1.getDelegateRule().booleanValue() ? 0 : 1));
1275 Integer rule2Value = new Integer((rule2.getDelegateRule().booleanValue() ? 0 : 1));
1276 int value = rule1Value.compareTo(rule2Value);
1277 return value;
1278 }
1279 }
1280
1281
1282 public void loadXml(InputStream inputStream, String principalId) {
1283 RuleXmlParser parser = new RuleXmlParser();
1284 try {
1285 parser.parseRules(inputStream);
1286 } catch (Exception e) {
1287 LOG.error("Error loading xml file", e);
1288 WorkflowServiceErrorException wsee = new WorkflowServiceErrorException("Error loading xml file", new WorkflowServiceErrorImpl("Error loading xml file", XML_PARSE_ERROR));
1289 wsee.initCause(e);
1290 throw wsee;
1291 }
1292 }
1293
1294 public Element export(ExportDataSet dataSet) {
1295 RuleXmlExporter exporter = new RuleXmlExporter(XmlConstants.RULE_NAMESPACE);
1296 return exporter.export(dataSet);
1297 }
1298
1299 public void removeRuleInvolvement(Id entityToBeRemoved, List<Long> ruleIds, Long documentId) throws WorkflowException {
1300 KimPrincipal principal = null;
1301 Group workgroupToRemove = null;
1302 if (entityToBeRemoved instanceof UserId) {
1303 principal = KEWServiceLocator.getIdentityHelperService().getPrincipal(((UserId) entityToBeRemoved));
1304 } else if (entityToBeRemoved instanceof GroupId) {
1305 workgroupToRemove = KEWServiceLocator.getIdentityHelperService().getGroup((GroupId)entityToBeRemoved);
1306 } else {
1307 throw new WorkflowRuntimeException("Invalid ID for entity to be replaced was passed, type was: " + entityToBeRemoved);
1308 }
1309 List<RuleBaseValues> existingRules = loadRules(ruleIds);
1310
1311 Collections.sort(existingRules, ComparatorUtils.reversedComparator(new RuleDelegationSorter()));
1312
1313 Map<Long, RuleBaseValues> oldIdNewRuleMapping = new HashMap<Long, RuleBaseValues>();
1314 Map<Long, RuleBaseValues> rulesToVersion = new HashMap<Long, RuleBaseValues>();
1315 for (RuleBaseValues existingRule : existingRules) {
1316 if (!shouldChangeRuleInvolvement(documentId, existingRule)) {
1317 continue;
1318 }
1319 List<RuleResponsibility> finalResponsibilities = new ArrayList<RuleResponsibility>();
1320 RuleVersion ruleVersion = createNewRemoveReplaceVersion(existingRule, oldIdNewRuleMapping, documentId);
1321 boolean modified = false;
1322 for (RuleResponsibility responsibility : (List<RuleResponsibility>)ruleVersion.rule.getResponsibilities()) {
1323 if (responsibility.isUsingWorkflowUser()) {
1324 if (principal != null && responsibility.getRuleResponsibilityName().equals(principal.getPrincipalName())) {
1325 modified = true;
1326 continue;
1327 }
1328 } else if (responsibility.isUsingGroup()) {
1329 if (workgroupToRemove != null && responsibility.getRuleResponsibilityName().equals(workgroupToRemove.getGroupId())) {
1330 modified = true;
1331 continue;
1332 }
1333 }
1334 finalResponsibilities.add(responsibility);
1335 }
1336 if (modified) {
1337
1338 if (ruleVersion.parent != null && ruleVersion.delegation != null) {
1339 hookUpDelegateRuleToParentRule(ruleVersion.parent, ruleVersion.rule, ruleVersion.delegation);
1340 }
1341 if (finalResponsibilities.isEmpty()) {
1342
1343 ruleVersion.rule.setActiveInd(false);
1344 } else {
1345 ruleVersion.rule.setResponsibilities(finalResponsibilities);
1346 }
1347 try {
1348 save2(ruleVersion.rule, ruleVersion.delegation, false);
1349 if (ruleVersion.delegation != null) {
1350 KEWServiceLocator.getRuleDelegationService().save(ruleVersion.delegation);
1351 }
1352 rulesToVersion.put(ruleVersion.rule.getRuleBaseValuesId(), ruleVersion.rule);
1353 if (ruleVersion.parent != null) {
1354 save2(ruleVersion.parent, null, false);
1355 rulesToVersion.put(ruleVersion.parent.getRuleBaseValuesId(), ruleVersion.parent);
1356 }
1357 } catch (Exception e) {
1358 throw new WorkflowRuntimeException(e);
1359 }
1360 }
1361 }
1362 makeCurrent2(new ArrayList<RuleBaseValues>(rulesToVersion.values()));
1363 }
1364
1365 protected List<RuleBaseValues> loadRules(List<Long> ruleIds) {
1366 List<RuleBaseValues> rules = new ArrayList<RuleBaseValues>();
1367 for (Long ruleId : ruleIds) {
1368 RuleBaseValues rule = KEWServiceLocator.getRuleService().findRuleBaseValuesById(ruleId);
1369 rules.add(rule);
1370 }
1371 return rules;
1372 }
1373
1374 public void replaceRuleInvolvement(Id entityToBeReplaced, Id newEntity, List<Long> ruleIds, Long documentId) throws WorkflowException {
1375 KimPrincipal principalToBeReplaced = null;
1376 Group workgroupToReplace = null;
1377 if (entityToBeReplaced instanceof UserId) {
1378 principalToBeReplaced = KEWServiceLocator.getIdentityHelperService().getPrincipal(((UserId) entityToBeReplaced));
1379 } else if (entityToBeReplaced instanceof GroupId) {
1380 workgroupToReplace = KEWServiceLocator.getIdentityHelperService().getGroup((GroupId)entityToBeReplaced);
1381 } else {
1382 throw new WorkflowRuntimeException("Invalid ID for entity to be replaced was passed, type was: " + entityToBeReplaced);
1383 }
1384 KimPrincipal newPrincipal = null;
1385 Group newWorkgroup = null;
1386 if (newEntity instanceof UserId) {
1387 newPrincipal = KEWServiceLocator.getIdentityHelperService().getPrincipal((UserId) newEntity);
1388 } else if (newEntity instanceof GroupId) {
1389 newWorkgroup = KEWServiceLocator.getIdentityHelperService().getGroup((GroupId)newEntity);
1390 }
1391 List<RuleBaseValues> existingRules = loadRules(ruleIds);
1392
1393 Collections.sort(existingRules, ComparatorUtils.reversedComparator(new RuleDelegationSorter()));
1394
1395 Map<Long, RuleBaseValues> oldIdNewRuleMapping = new HashMap<Long, RuleBaseValues>();
1396 Map<Long, RuleBaseValues> rulesToVersion = new HashMap<Long, RuleBaseValues>();
1397 for (RuleBaseValues existingRule : existingRules) {
1398 if (!shouldChangeRuleInvolvement(documentId, existingRule)) {
1399 continue;
1400 }
1401 RuleVersion ruleVersion = createNewRemoveReplaceVersion(existingRule, oldIdNewRuleMapping, documentId);
1402 RuleBaseValues rule = ruleVersion.rule;
1403 boolean modified = false;
1404 for (RuleResponsibility responsibility : (List<RuleResponsibility>)rule.getResponsibilities()) {
1405 if (responsibility.isUsingWorkflowUser()) {
1406 if (principalToBeReplaced != null && responsibility.getRuleResponsibilityName().equals(principalToBeReplaced.getPrincipalId())) {
1407 if (newPrincipal != null) {
1408 responsibility.setRuleResponsibilityType(KEWConstants.RULE_RESPONSIBILITY_WORKFLOW_ID);
1409 responsibility.setRuleResponsibilityName(newPrincipal.getPrincipalId());
1410 modified = true;
1411 } else if (newWorkgroup != null) {
1412 responsibility.setRuleResponsibilityType(KEWConstants.RULE_RESPONSIBILITY_GROUP_ID);
1413 responsibility.setRuleResponsibilityName(newWorkgroup.getGroupId());
1414 modified = true;
1415 }
1416 }
1417 } else if (responsibility.isUsingGroup()) {
1418 if (workgroupToReplace != null && responsibility.getRuleResponsibilityName().equals(workgroupToReplace.getGroupId())) {
1419 if (newPrincipal != null) {
1420 responsibility.setRuleResponsibilityType(KEWConstants.RULE_RESPONSIBILITY_WORKFLOW_ID);
1421 responsibility.setRuleResponsibilityName(newPrincipal.getPrincipalId());
1422 modified = true;
1423 } else if (newWorkgroup != null) {
1424 responsibility.setRuleResponsibilityType(KEWConstants.RULE_RESPONSIBILITY_GROUP_ID);
1425 responsibility.setRuleResponsibilityName(newWorkgroup.getGroupId().toString());
1426 modified = true;
1427 }
1428 }
1429 }
1430 }
1431 if (modified) {
1432 try {
1433
1434 if (ruleVersion.parent != null && ruleVersion.delegation != null) {
1435 hookUpDelegateRuleToParentRule(ruleVersion.parent, ruleVersion.rule, ruleVersion.delegation);
1436 }
1437 save2(ruleVersion.rule, ruleVersion.delegation, false);
1438 if (ruleVersion.delegation != null) {
1439 KEWServiceLocator.getRuleDelegationService().save(ruleVersion.delegation);
1440 }
1441 rulesToVersion.put(ruleVersion.rule.getRuleBaseValuesId(), ruleVersion.rule);
1442 if (ruleVersion.parent != null) {
1443 save2(ruleVersion.parent, null, false);
1444 rulesToVersion.put(ruleVersion.parent.getRuleBaseValuesId(), ruleVersion.parent);
1445 }
1446 } catch (Exception e) {
1447 throw new WorkflowRuntimeException(e);
1448 }
1449 }
1450 }
1451
1452 makeCurrent2(new ArrayList<RuleBaseValues>(rulesToVersion.values()));
1453
1454 }
1455
1456
1457
1458
1459
1460 protected boolean shouldChangeRuleInvolvement(Long documentId, RuleBaseValues rule) {
1461 if (!rule.getCurrentInd()) {
1462 LOG.warn("Rule requested for rule involvement change by document " + documentId + " is no longer current. Change will not be executed! Rule id is: " + rule.getRuleBaseValuesId());
1463 return false;
1464 }
1465 Long lockingDocumentId = KEWServiceLocator.getRuleService().isLockedForRouting(rule.getRuleBaseValuesId());
1466 if (lockingDocumentId != null) {
1467 LOG.warn("Rule requested for rule involvement change by document " + documentId + " is locked by document " + lockingDocumentId + " and cannot be modified. " +
1468 "Change will not be executed! Rule id is: " + rule.getRuleBaseValuesId());
1469 return false;
1470 }
1471 return true;
1472 }
1473
1474 protected RuleDelegation getRuleDelegationForDelegateRule(RuleBaseValues rule) {
1475 if (Boolean.TRUE.equals(rule.getDelegateRule())) {
1476 List delegations = getRuleDelegationService().findByDelegateRuleId(rule.getRuleBaseValuesId());
1477 for (Iterator iterator = delegations.iterator(); iterator.hasNext();) {
1478 RuleDelegation ruleDelegation = (RuleDelegation) iterator.next();
1479 RuleBaseValues parentRule = ruleDelegation.getRuleResponsibility().getRuleBaseValues();
1480 if (Boolean.TRUE.equals(parentRule.getCurrentInd())) {
1481 return ruleDelegation;
1482 }
1483 }
1484 }
1485 return null;
1486 }
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497 protected RuleVersion createNewRemoveReplaceVersion(RuleBaseValues existingRule, Map<Long, RuleBaseValues> originalIdNewRuleMapping, Long documentId) {
1498 try {
1499
1500 RuleBaseValues rule = null;
1501 if (originalIdNewRuleMapping.containsKey(existingRule.getRuleBaseValuesId())) {
1502 rule = originalIdNewRuleMapping.get(existingRule.getRuleBaseValuesId());
1503 } else {
1504 rule = createNewRuleVersion(existingRule, documentId);
1505 }
1506
1507 RuleVersion ruleVersion = new RuleVersion();
1508 RuleBaseValues existingParentRule = null;
1509 RuleBaseValues newParentRule = null;
1510
1511 if (rule.getDelegateRule()) {
1512 RuleDelegation existingBaseDelegation = getRuleDelegationForDelegateRule(existingRule);
1513 ruleVersion.delegation = existingBaseDelegation;
1514 existingParentRule = existingBaseDelegation.getRuleResponsibility().getRuleBaseValues();
1515 if (originalIdNewRuleMapping.containsKey(existingParentRule.getRuleBaseValuesId())) {
1516 newParentRule = originalIdNewRuleMapping.get(existingParentRule.getRuleBaseValuesId());
1517 } else {
1518
1519 newParentRule = createNewRuleVersion(existingParentRule, documentId);
1520 }
1521 }
1522
1523
1524 originalIdNewRuleMapping.put(existingRule.getRuleBaseValuesId(), rule);
1525 if (existingParentRule != null && !originalIdNewRuleMapping.containsKey(existingParentRule.getRuleBaseValuesId())) {
1526 originalIdNewRuleMapping.put(existingParentRule.getRuleBaseValuesId(), newParentRule);
1527 }
1528
1529 ruleVersion.rule = rule;
1530 ruleVersion.parent = newParentRule;
1531 return ruleVersion;
1532 } catch (Exception e) {
1533 if (e instanceof RuntimeException) {
1534 throw (RuntimeException)e;
1535 }
1536 throw new WorkflowRuntimeException(e);
1537 }
1538 }
1539
1540 protected void hookUpDelegateRuleToParentRule(RuleBaseValues newParentRule, RuleBaseValues newDelegationRule, RuleDelegation existingRuleDelegation) {
1541
1542 boolean foundDelegation = false;
1543 outer:for (RuleResponsibility responsibility : (List<RuleResponsibility>)newParentRule.getResponsibilities()) {
1544 for (RuleDelegation ruleDelegation : (List<RuleDelegation>)responsibility.getDelegationRules()) {
1545 if (ruleDelegation.getDelegationRuleBaseValues().getRuleBaseValuesId().equals(existingRuleDelegation.getDelegationRuleBaseValues().getRuleBaseValuesId())) {
1546 ruleDelegation.setDelegationRuleBaseValues(newDelegationRule);
1547 foundDelegation = true;
1548 break outer;
1549 }
1550 }
1551 }
1552 if (!foundDelegation) {
1553 throw new WorkflowRuntimeException("Failed to locate the existing rule delegation with id: " + existingRuleDelegation.getDelegationRuleBaseValues().getRuleBaseValuesId());
1554 }
1555
1556 }
1557
1558 protected RuleBaseValues createNewRuleVersion(RuleBaseValues existingRule, Long documentId) throws Exception {
1559 RuleBaseValues rule = new RuleBaseValues();
1560 PropertyUtils.copyProperties(rule, existingRule);
1561 rule.setPreviousVersion(existingRule);
1562 rule.setPreviousVersionId(existingRule.getRuleBaseValuesId());
1563 rule.setRuleBaseValuesId(null);
1564 rule.setActivationDate(null);
1565 rule.setDeactivationDate(null);
1566 rule.setVersionNumber(0L);
1567 rule.setRouteHeaderId(documentId);
1568
1569
1570
1571 rule.setResponsibilities(new ArrayList());
1572 for (RuleResponsibility existingResponsibility : (List<RuleResponsibility>)existingRule.getResponsibilities()) {
1573 RuleResponsibility responsibility = new RuleResponsibility();
1574 PropertyUtils.copyProperties(responsibility, existingResponsibility);
1575 responsibility.setRuleBaseValues(rule);
1576 responsibility.setRuleBaseValuesId(null);
1577 responsibility.setRuleResponsibilityKey(null);
1578 responsibility.setVersionNumber(0L);
1579 rule.getResponsibilities().add(responsibility);
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592 }
1593 rule.setRuleExtensions(new ArrayList());
1594 for (RuleExtension existingExtension : (List<RuleExtension>)existingRule.getRuleExtensions()) {
1595 RuleExtension extension = new RuleExtension();
1596 PropertyUtils.copyProperties(extension, existingExtension);
1597 extension.setLockVerNbr(0);
1598 extension.setRuleBaseValues(rule);
1599 extension.setRuleBaseValuesId(null);
1600 extension.setRuleExtensionId(null);
1601 rule.getRuleExtensions().add(extension);
1602 extension.setExtensionValues(new ArrayList<RuleExtensionValue>());
1603 for (RuleExtensionValue existingExtensionValue : extension.getExtensionValues()) {
1604 RuleExtensionValue extensionValue = new RuleExtensionValue();
1605 PropertyUtils.copyProperties(extensionValue, existingExtensionValue);
1606 extensionValue.setExtension(extension);
1607 extensionValue.setRuleExtensionId(null);
1608 extensionValue.setLockVerNbr(0);
1609 extensionValue.setRuleExtensionValueId(null);
1610 extension.getExtensionValues().add(extensionValue);
1611 }
1612 }
1613 return rule;
1614 }
1615
1616 private static class RuleVersion {
1617 public RuleBaseValues rule;
1618 public RuleBaseValues parent;
1619 public RuleDelegation delegation;
1620 }
1621
1622 private static class RuleRoutingConfig {
1623 private List configs = new ArrayList();
1624 public static RuleRoutingConfig parse() {
1625 RuleRoutingConfig config = new RuleRoutingConfig();
1626 String constant = Utilities.getKNSParameterValue(KEWConstants.KEW_NAMESPACE, KNSConstants.DetailTypes.RULE_DETAIL_TYPE, KEWConstants.RULE_CUSTOM_DOC_TYPES);
1627 if (!StringUtils.isEmpty(constant)) {
1628 String[] ruleConfigs = constant.split(",");
1629 for (int index = 0; index < ruleConfigs.length; index++) {
1630 String[] configElements = ruleConfigs[index].split(":");
1631 if (configElements.length != 4) {
1632 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! " + ruleConfigs[index]);
1633 }
1634 config.configs.add(configElements);
1635 }
1636 }
1637 return config;
1638 }
1639 public String getDocumentTypeName(RuleBaseValues rule) {
1640 for (Iterator iterator = configs.iterator(); iterator.hasNext();) {
1641 String[] configElements = (String[]) iterator.next();
1642 String docTypeName = configElements[0];
1643 String ruleTemplateName = configElements[1];
1644 String type = configElements[2];
1645 String ruleDocTypeName = configElements[3];
1646 if (rule.getDocTypeName().equals(docTypeName) && rule.getRuleTemplateName().equals(ruleTemplateName)) {
1647 if (type.equals("M")) {
1648 if (Boolean.FALSE.equals(rule.getDelegateRule())) {
1649 return ruleDocTypeName;
1650 }
1651 } else if (type.equals("D")) {
1652 if (Boolean.TRUE.equals(rule.getDelegateRule())) {
1653 return ruleDocTypeName;
1654 }
1655 } else {
1656 throw new RuntimeException("Bad rule type '" + type + "' in rule doc type routing config.");
1657 }
1658 }
1659 }
1660 return null;
1661 }
1662 }
1663
1664 public Long getDuplicateRuleId(RuleBaseValues rule) {
1665
1666
1667
1668 List responsibilities = rule.getResponsibilities();
1669 List extensions = rule.getRuleExtensions();
1670 String docTypeName = rule.getDocTypeName();
1671 String ruleTemplateName = rule.getRuleTemplateName();
1672 List rules = fetchAllCurrentRulesForTemplateDocCombination(rule.getRuleTemplateName(), rule.getDocTypeName(), false);
1673 Iterator it = rules.iterator();
1674 while (it.hasNext()) {
1675 RuleBaseValues r = (RuleBaseValues) it.next();
1676 if (Utilities.equals(rule.getActiveInd(), r.getActiveInd()) &&
1677 Utilities.equals(docTypeName, r.getDocTypeName()) &&
1678 Utilities.equals(ruleTemplateName, r.getRuleTemplateName()) &&
1679 Utilities.equals(rule.getRuleExpressionDef(), r.getRuleExpressionDef()) &&
1680 Utilities.collectionsEquivalent(responsibilities, r.getResponsibilities()) &&
1681 Utilities.collectionsEquivalent(extensions, r.getRuleExtensions())) {
1682
1683 return r.getRuleBaseValuesId();
1684 }
1685 }
1686 return null;
1687 }
1688
1689 private void generateRuleNameIfNeeded(RuleBaseValues rule) {
1690 if (StringUtils.isBlank(rule.getName())) {
1691 rule.setName(new Guid().toString());
1692 }
1693 }
1694
1695 private void assignResponsibilityIds(RuleBaseValues rule) {
1696 for (RuleResponsibility responsibility : rule.getResponsibilities()) {
1697 if (responsibility.getResponsibilityId() == null) {
1698 responsibility.setResponsibilityId(KEWServiceLocator.getResponsibilityIdService().getNewResponsibilityId());
1699 }
1700 }
1701 }
1702
1703 public RuleBaseValues saveRule(RuleBaseValues rule, boolean isRetroactiveUpdatePermitted) {
1704 rule.setPreviousVersionId(rule.getRuleBaseValuesId());
1705 rule.setPreviousVersion(null);
1706 rule.setRuleBaseValuesId(null);
1707 makeCurrent(rule, isRetroactiveUpdatePermitted);
1708 return rule;
1709 }
1710
1711 public List<RuleBaseValues> saveRules(List<RuleBaseValues> rulesToSave, boolean isRetroactiveUpdatePermitted) {
1712 List<RuleBaseValues> savedRules = new ArrayList<RuleBaseValues>();
1713 for (RuleBaseValues rule : rulesToSave) {
1714 rule = saveRule(rule, isRetroactiveUpdatePermitted);
1715 savedRules.add(rule);
1716 }
1717 return savedRules;
1718 }
1719
1720 public RuleDelegation saveRuleDelegation(RuleDelegation ruleDelegation, boolean isRetroactiveUpdatePermitted) {
1721 RuleBaseValues rule = ruleDelegation.getDelegationRuleBaseValues();
1722 rule.setPreviousVersionId(rule.getRuleBaseValuesId());
1723 rule.setPreviousVersion(null);
1724 rule.setRuleBaseValuesId(null);
1725 ruleDelegation.setRuleDelegationId(null);
1726 makeCurrent(ruleDelegation, isRetroactiveUpdatePermitted);
1727 return ruleDelegation;
1728 }
1729
1730 public List<RuleDelegation> saveRuleDelegations(List<RuleDelegation> ruleDelegationsToSave, boolean isRetroactiveUpdatePermitted) {
1731 List<RuleDelegation> savedRuleDelegations = new ArrayList<RuleDelegation>();
1732 for (RuleDelegation ruleDelegation : ruleDelegationsToSave) {
1733 ruleDelegation = saveRuleDelegation(ruleDelegation, isRetroactiveUpdatePermitted);
1734 savedRuleDelegations.add(ruleDelegation);
1735 }
1736 return savedRuleDelegations;
1737 }
1738
1739 public Long findResponsibilityIdForRule(String ruleName, String ruleResponsibilityName, String ruleResponsibilityType) {
1740 return getRuleDAO().findResponsibilityIdForRule(ruleName, ruleResponsibilityName, ruleResponsibilityType);
1741 }
1742
1743 }