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 }