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