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