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