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