001/** 002 * Copyright 2005-2016 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.kew.rule; 017 018import java.sql.Timestamp; 019import java.util.ArrayList; 020import java.util.Date; 021import java.util.HashMap; 022import java.util.Iterator; 023import java.util.List; 024import java.util.Map; 025 026import javax.persistence.CascadeType; 027import javax.persistence.Column; 028import javax.persistence.Convert; 029import javax.persistence.Entity; 030import javax.persistence.FetchType; 031import javax.persistence.GeneratedValue; 032import javax.persistence.Id; 033import javax.persistence.JoinColumn; 034import javax.persistence.ManyToOne; 035import javax.persistence.OneToMany; 036import javax.persistence.OneToOne; 037import javax.persistence.Table; 038import javax.persistence.Transient; 039 040import org.apache.commons.lang.StringUtils; 041import org.joda.time.DateTime; 042import org.kuali.rice.core.api.util.RiceConstants; 043import org.kuali.rice.kew.api.KewApiConstants; 044import org.kuali.rice.kew.api.rule.RuleContract; 045import org.kuali.rice.kew.api.rule.RuleExtension; 046import org.kuali.rice.kew.api.util.CodeTranslator; 047import org.kuali.rice.kew.doctype.bo.DocumentType; 048import org.kuali.rice.kew.lookupable.MyColumns; 049import org.kuali.rice.kew.routeheader.DocumentContent; 050import org.kuali.rice.kew.rule.bo.RuleAttribute; 051import org.kuali.rice.kew.rule.bo.RuleTemplateAttributeBo; 052import org.kuali.rice.kew.rule.bo.RuleTemplateBo; 053import org.kuali.rice.kew.rule.service.RuleServiceInternal; 054import org.kuali.rice.kew.rule.xmlrouting.GenericXMLRuleAttribute; 055import org.kuali.rice.kew.service.KEWServiceLocator; 056import org.kuali.rice.kim.api.services.KimApiServiceLocator; 057import org.kuali.rice.kim.impl.group.GroupBo; 058import org.kuali.rice.kim.impl.identity.PersonImpl; 059import org.kuali.rice.krad.bo.PersistableBusinessObjectBase; 060import org.kuali.rice.krad.data.jpa.PortableSequenceGenerator; 061import org.kuali.rice.krad.data.jpa.converters.Boolean01Converter; 062import org.kuali.rice.krad.data.provider.annotation.SerializationContext; 063import org.kuali.rice.krad.data.provider.annotation.Serialized; 064 065/*import org.kuali.rice.kim.api.group.Group;*/ 066 067 068/** 069 * A model bean for a Rule within the KEW rules engine. 070 * 071 * @author Kuali Rice Team (rice.collab@kuali.org) 072 */ 073@Entity 074@Table(name="KREW_RULE_T") 075public class RuleBaseValues extends PersistableBusinessObjectBase implements RuleContract { 076 077 private static final long serialVersionUID = 6137765574728530156L; 078 @Id 079 @GeneratedValue(generator = "KREW_RTE_TMPL_S") 080 @PortableSequenceGenerator(name = "KREW_RTE_TMPL_S") 081 @Column(name="RULE_ID") 082 private String id; 083 084 /** 085 * Unique Rule name 086 */ 087 @Column(name="NM") 088 private String name; 089 090 @Column(name="RULE_TMPL_ID") 091 private String ruleTemplateId; 092 093 @Column(name="PREV_VER_RULE_ID") 094 private String previousRuleId; 095 096 @Column(name="ACTV_IND") 097 @Convert(converter=Boolean01Converter.class) 098 private boolean active = true; 099 100 @Column(name="RULE_BASE_VAL_DESC") 101 private String description; 102 103 @Column(name="DOC_TYP_NM") 104 private String docTypeName; 105 106 @Column(name="DOC_HDR_ID") 107 private String documentId; 108 109 @Column(name="FRM_DT") 110 private Timestamp fromDateValue; 111 112 @Column(name="TO_DT") 113 private Timestamp toDateValue; 114 115 @Column(name="DACTVN_DT") 116 private Timestamp deactivationDate; 117 118 @Column(name="CUR_IND") 119 @Convert(converter=Boolean01Converter.class) 120 private Boolean currentInd = Boolean.TRUE; 121 122 @Column(name="RULE_VER_NBR") 123 private Integer versionNbr = 0; 124 125 @Column(name="FRC_ACTN") 126 @Convert(converter=Boolean01Converter.class) 127 private boolean forceAction; 128 129 @OneToMany(fetch=FetchType.EAGER,cascade=CascadeType.ALL, orphanRemoval = true) 130 @JoinColumn(name = "RULE_ID", referencedColumnName = "RULE_ID") 131 private List<RuleResponsibilityBo> ruleResponsibilities; 132 133 @OneToMany(fetch=FetchType.EAGER,cascade=CascadeType.ALL, orphanRemoval = true) 134 @JoinColumn(name = "RULE_ID", referencedColumnName = "RULE_ID") 135 private List<RuleExtensionBo> ruleExtensions; 136 137 @ManyToOne(fetch=FetchType.EAGER) 138 @JoinColumn(name="RULE_TMPL_ID", insertable = false, updatable = false) 139 private RuleTemplateBo ruleTemplate; 140 141 @OneToOne(fetch=FetchType.EAGER, cascade=CascadeType.ALL, orphanRemoval = true) 142 @JoinColumn(name="RULE_EXPR_ID") 143 private RuleExpressionDef ruleExpressionDef; 144 145 @Transient 146 private RuleBaseValues previousVersion; 147 148 @Column(name="ACTVN_DT") 149 private Timestamp activationDate; 150 151 @Column(name="DLGN_IND") 152 @Convert(converter=Boolean01Converter.class) 153 private Boolean delegateRule = Boolean.FALSE; 154 155 /** 156 * Indicator that signifies that this rule is a defaults/template rule which contains 157 * template-defined rule defaults for other rules which use the associated template 158 */ 159 @Column(name="TMPL_RULE_IND") 160 @Convert(converter=Boolean01Converter.class) 161 private Boolean templateRuleInd = Boolean.FALSE; 162 163 // required to be lookupable 164 @Transient 165 private String returnUrl; 166 @Transient 167 private String destinationUrl; 168 @Transient 169 private MyColumns myColumns; 170 @Transient 171 @Serialized(enabled=true,forContexts=SerializationContext.MAINTENANCE) 172 private List<PersonRuleResponsibility> personResponsibilities = new ArrayList<PersonRuleResponsibility>(); 173 @Transient 174 @Serialized(enabled=true,forContexts=SerializationContext.MAINTENANCE) 175 private List<GroupRuleResponsibility> groupResponsibilities = new ArrayList<GroupRuleResponsibility>(); 176 @Transient 177 @Serialized(enabled=true,forContexts=SerializationContext.MAINTENANCE) 178 private List<RoleRuleResponsibility> roleResponsibilities = new ArrayList<RoleRuleResponsibility>(); 179 @Transient 180 private Map<String, String> fieldValues; 181 @Transient 182 private String groupReviewerName; 183 @Transient 184 private String groupReviewerNamespace; 185 @Transient 186 private String personReviewer; 187 @Transient 188 private String personReviewerType; 189 190 public RuleBaseValues() { 191 ruleResponsibilities = new ArrayList<RuleResponsibilityBo>(); 192 ruleExtensions = new ArrayList<RuleExtensionBo>(); 193 /*personResponsibilities = new AutoPopulatingList<PersonRuleResponsibility>(PersonRuleResponsibility.class); 194 groupResponsibilities = new AutoPopulatingList<GroupRuleResponsibility>(GroupRuleResponsibility.class); 195 roleResponsibilities = new AutoPopulatingList<RoleRuleResponsibility>(RoleRuleResponsibility.class);*/ 196 fieldValues = new HashMap<String, String>(); 197 } 198 199 /** 200 * @return the rule expression definition for this rule, if defined 201 */ 202 @Override 203 public RuleExpressionDef getRuleExpressionDef() { 204 return ruleExpressionDef; 205 } 206 207 /** 208 * @param ruleExpressionDef the rule expression definition to set for this rule 209 */ 210 public void setRuleExpressionDef(RuleExpressionDef ruleExpressionDef) { 211 this.ruleExpressionDef = ruleExpressionDef; 212 } 213 214 @Override 215 public String getRuleTemplateName() { 216 if (ruleTemplate != null) { 217 return ruleTemplate.getName(); 218 } 219 return null; 220 } 221 222 public RuleBaseValues getPreviousVersion() { 223 if (previousVersion == null && previousRuleId != null) { 224 RuleServiceInternal ruleService = (RuleServiceInternal) KEWServiceLocator.getService(KEWServiceLocator.RULE_SERVICE); 225 return ruleService.findRuleBaseValuesById(previousRuleId); 226 } 227 return previousVersion; 228 } 229 230 public void setPreviousVersion(RuleBaseValues previousVersion) { 231 this.previousVersion = previousVersion; 232 } 233 234 public RuleResponsibilityBo getResponsibility(int index) { 235 while (getRuleResponsibilities().size() <= index) { 236 RuleResponsibilityBo ruleResponsibility = new RuleResponsibilityBo(); 237 ruleResponsibility.setRuleBaseValues(this); 238 getRuleResponsibilities().add(ruleResponsibility); 239 } 240 return getRuleResponsibilities().get(index); 241 } 242 243 public RuleExtensionBo getRuleExtension(int index) { 244 while (getRuleExtensions().size() <= index) { 245 getRuleExtensions().add(new RuleExtensionBo()); 246 } 247 return getRuleExtensions().get(index); 248 } 249 250 public RuleExtensionValue getRuleExtensionValue(String key) { 251 for (Iterator iter = getRuleExtensions().iterator(); iter.hasNext();) { 252 RuleExtensionBo ruleExtension = (RuleExtensionBo) iter.next(); 253 for (Iterator iterator = ruleExtension.getExtensionValues().iterator(); iterator.hasNext();) { 254 RuleExtensionValue ruleExtensionValue = (RuleExtensionValue) iterator.next(); 255 if (ruleExtensionValue.getKey().equals(key)) { 256 return ruleExtensionValue; 257 } 258 } 259 } 260 return null; 261 } 262 263 public RuleExtensionValue getRuleExtensionValue(String ruleTemplateAttributeId, String key) { 264 for (Iterator iter = getRuleExtensions().iterator(); iter.hasNext();) { 265 RuleExtensionBo ruleExtension = (RuleExtensionBo) iter.next(); 266 if (ruleExtension.getRuleTemplateAttributeId().equals(ruleTemplateAttributeId)) { 267 for (Iterator iterator = ruleExtension.getExtensionValues().iterator(); iterator.hasNext();) { 268 RuleExtensionValue ruleExtensionValue = (RuleExtensionValue) iterator.next(); 269 if (ruleExtensionValue.getKey().equals(key)) { 270 return ruleExtensionValue; 271 } 272 } 273 } 274 } 275 return null; 276 } 277 278 @Override 279 public String getPreviousRuleId() { 280 return previousRuleId; 281 } 282 283 public void setPreviousRuleId(String previousVersion) { 284 this.previousRuleId = previousVersion; 285 } 286 287 public void addRuleResponsibility(RuleResponsibilityBo ruleResponsibility) { 288 addRuleResponsibility(ruleResponsibility, new Integer(getRuleResponsibilities().size())); 289 } 290 291 public void addRuleResponsibility(RuleResponsibilityBo ruleResponsibility, Integer counter) { 292 boolean alreadyAdded = false; 293 int location = 0; 294 if (counter != null) { 295 for (RuleResponsibilityBo ruleResponsibilityRow : getRuleResponsibilities()) { 296 if (counter.intValue() == location) { 297 ruleResponsibilityRow.setPriority(ruleResponsibility.getPriority()); 298 ruleResponsibilityRow.setActionRequestedCd(ruleResponsibility.getActionRequestedCd()); 299 // CHECKME : We probably should not be overriding the version number 300 ruleResponsibilityRow.setVersionNumber(ruleResponsibility.getVersionNumber()); 301 ruleResponsibilityRow.setRuleBaseValuesId(ruleResponsibility.getRuleBaseValuesId()); 302 ruleResponsibilityRow.setRuleResponsibilityName(ruleResponsibility.getRuleResponsibilityName()); 303 ruleResponsibilityRow.setRuleResponsibilityType(ruleResponsibility.getRuleResponsibilityType()); 304 //ruleResponsibilityRow.setDelegationRules(ruleResponsibility.getDelegationRules()); 305 ruleResponsibilityRow.setApprovePolicy(ruleResponsibility.getApprovePolicy()); 306 alreadyAdded = true; 307 } 308 location++; 309 } 310 } 311 if (!alreadyAdded) { 312 getRuleResponsibilities().add(ruleResponsibility); 313 } 314 } 315 316 @Override 317 public RuleTemplateBo getRuleTemplate() { 318 return ruleTemplate; 319 } 320 321 public void setRuleTemplate(RuleTemplateBo ruleTemplate) { 322 this.ruleTemplate = ruleTemplate; 323 } 324 325 public String getRuleTemplateId() { 326 return ruleTemplateId; 327 } 328 329 public void setRuleTemplateId(String ruleTemplateId) { 330 this.ruleTemplateId = ruleTemplateId; 331 } 332 333 public DocumentType getDocumentType() { 334 return KEWServiceLocator.getDocumentTypeService().findByName(getDocTypeName()); 335 } 336 337 @Override 338 public String getDocTypeName() { 339 return docTypeName; 340 } 341 342 public void setDocTypeName(String docTypeName) { 343 this.docTypeName = docTypeName; 344 } 345 346 @Override 347 public List<RuleExtensionBo> getRuleExtensions() { 348 return ruleExtensions; 349 } 350 351 public Map<String, String> getRuleExtensionMap() { 352 Map<String, String> extensions = new HashMap<String, String>(); 353 for (RuleExtensionBo ext : this.getRuleExtensions()) { 354 for (RuleExtensionValue value : ext.getExtensionValues()) { 355 extensions.put(value.getKey(), value.getValue()); 356 } 357 } 358 return extensions; 359 } 360 361 public void setRuleExtensions(List<RuleExtensionBo> ruleExtensions) { 362 this.ruleExtensions = ruleExtensions; 363 } 364 365 @Override 366 public List<RuleResponsibilityBo> getRuleResponsibilities() { 367 return this.ruleResponsibilities; 368 } 369 370 public void setRuleResponsibilities(List<RuleResponsibilityBo> ruleResponsibilities) { 371 this.ruleResponsibilities = ruleResponsibilities; 372 } 373 374 public RuleResponsibilityBo getResponsibility(Long ruleResponsibilityKey) { 375 for (Iterator iterator = getRuleResponsibilities().iterator(); iterator.hasNext();) { 376 RuleResponsibilityBo responsibility = (RuleResponsibilityBo) iterator.next(); 377 if (responsibility.getId() != null 378 && responsibility.getId().equals(ruleResponsibilityKey)) { 379 return responsibility; 380 } 381 } 382 return null; 383 } 384 385 public void removeResponsibility(int index) { 386 getRuleResponsibilities().remove(index); 387 } 388 389 @Override 390 public boolean isActive() { 391 return active; 392 } 393 394 public void setActive(boolean active) { 395 this.active = active; 396 } 397 398 public String getActiveIndDisplay() { 399 return CodeTranslator.getActiveIndicatorLabel(isActive()); 400 } 401 402 public Boolean getCurrentInd() { 403 return currentInd; 404 } 405 406 public void setCurrentInd(Boolean currentInd) { 407 this.currentInd = currentInd; 408 } 409 410 public Timestamp getFromDateValue() { 411 return fromDateValue; 412 } 413 414 @Override 415 public DateTime getFromDate() { 416 if (this.fromDateValue == null) { 417 return null; 418 } 419 return new DateTime(this.fromDateValue.getTime()); 420 } 421 422 public void setFromDateValue(Timestamp fromDateValue) { 423 this.fromDateValue = fromDateValue; 424 } 425 426 @Override 427 public String getDescription() { 428 return description; 429 } 430 431 public void setDescription(String description) { 432 this.description = description; 433 } 434 435 @Override 436 public String getId() { 437 return id; 438 } 439 440 public void setId(String id) { 441 this.id = id; 442 } 443 444 public Timestamp getToDateValue() { 445 return toDateValue; 446 } 447 448 @Override 449 public DateTime getToDate() { 450 if (this.toDateValue == null) { 451 return null; 452 } 453 return new DateTime(this.toDateValue.getTime()); 454 } 455 456 public void setToDateValue(Timestamp toDateValue) { 457 this.toDateValue = toDateValue; 458 } 459 460 public Integer getVersionNbr() { 461 return versionNbr; 462 } 463 464 public void setVersionNbr(Integer versionNbr) { 465 this.versionNbr = versionNbr; 466 } 467 468 public String getReturnUrl() { 469 return returnUrl; 470 } 471 472 public void setReturnUrl(String returnUrl) { 473 this.returnUrl = returnUrl; 474 } 475 476 public String getFromDateString() { 477 if (this.fromDateValue != null) { 478 return RiceConstants.getDefaultDateFormat().format(this.fromDateValue); 479 } 480 return null; 481 } 482 483 public String getToDateString() { 484 if (this.toDateValue != null) { 485 return RiceConstants.getDefaultDateFormat().format(this.toDateValue); 486 } 487 return null; 488 } 489 490 @Override 491 public boolean isForceAction() { 492 return forceAction; 493 } 494 495 public void setForceAction(boolean forceAction) { 496 this.forceAction = forceAction; 497 } 498 499 public boolean isActive(Date date) { 500 boolean isAfterFromDate = getFromDateValue() == null || date.after(getFromDateValue()); 501 boolean isBeforeToDate = getToDateValue() == null || date.before(getToDateValue()); 502 return isActive() && isAfterFromDate && isBeforeToDate; 503 } 504 505 public boolean isMatch(DocumentContent docContent) { 506 for (RuleTemplateAttributeBo ruleTemplateAttribute : getRuleTemplate().getActiveRuleTemplateAttributes()) { 507 if (!ruleTemplateAttribute.isWorkflowAttribute()) { 508 continue; 509 } 510 WorkflowRuleAttribute routingAttribute = ruleTemplateAttribute.getWorkflowAttribute(); 511 512 RuleAttribute ruleAttribute = ruleTemplateAttribute.getRuleAttribute(); 513 if (ruleAttribute.getType().equals(KewApiConstants.RULE_XML_ATTRIBUTE_TYPE)) { 514 ((GenericXMLRuleAttribute) routingAttribute).setExtensionDefinition(RuleAttribute.to(ruleAttribute)); 515 } 516 String className = ruleAttribute.getResourceDescriptor(); 517 List<RuleExtension> editedRuleExtensions = new ArrayList<RuleExtension>(); 518 for (RuleExtensionBo extension : getRuleExtensions()) { 519 if (extension.getRuleTemplateAttribute().getRuleAttribute().getResourceDescriptor().equals(className)) { 520 editedRuleExtensions.add(RuleExtensionBo.to(extension)); 521 } 522 } 523 if (!routingAttribute.isMatch(docContent, editedRuleExtensions)) { 524 return false; 525 } 526 } 527 return true; 528 } 529 530 public RuleResponsibilityBo findResponsibility(String roleName) { 531 for (Iterator iter = getRuleResponsibilities().iterator(); iter.hasNext();) { 532 RuleResponsibilityBo resp = (RuleResponsibilityBo) iter.next(); 533 if (KewApiConstants.RULE_RESPONSIBILITY_ROLE_ID.equals(resp.getRuleResponsibilityType()) 534 && roleName.equals(resp.getRuleResponsibilityName())) { 535 return resp; 536 } 537 } 538 return null; 539 } 540 541 public String getDocumentId() { 542 return documentId; 543 } 544 545 public void setDocumentId(String documentId) { 546 this.documentId = documentId; 547 } 548 549 public Boolean getDelegateRule() { 550 return delegateRule; 551 } 552 553 public void setDelegateRule(Boolean isDelegateRule) { 554 this.delegateRule = isDelegateRule; 555 } 556 557 public Timestamp getActivationDate() { 558 return activationDate; 559 } 560 561 public void setActivationDate(Timestamp activationDate) { 562 this.activationDate = activationDate; 563 } 564 565 public MyColumns getMyColumns() { 566 return myColumns; 567 } 568 569 public void setMyColumns(MyColumns additionalColumns) { 570 this.myColumns = additionalColumns; 571 } 572 573 public String getDestinationUrl() { 574 return destinationUrl; 575 } 576 577 public void setDestinationUrl(String destinationUrl) { 578 this.destinationUrl = destinationUrl; 579 } 580 581 public Timestamp getDeactivationDate() { 582 return deactivationDate; 583 } 584 585 public void setDeactivationDate(Timestamp deactivationDate) { 586 this.deactivationDate = deactivationDate; 587 } 588 589 /** 590 * @return whether this is a defaults/template rule 591 */ 592 public Boolean getTemplateRuleInd() { 593 return templateRuleInd; 594 } 595 596 /** 597 * @param templateRuleInd whether this is a defaults/template rule 598 */ 599 public void setTemplateRuleInd(Boolean templateRuleInd) { 600 this.templateRuleInd = templateRuleInd; 601 } 602 603 /** 604 * Get the rule name 605 * @return the rule name 606 */ 607 @Override 608 public String getName() { 609 return name; 610 } 611 612 /** 613 * Set the rule name 614 * @param name the rule name 615 */ 616 public void setName(String name) { 617 this.name = name; 618 } 619 620 public List<PersonRuleResponsibility> getPersonResponsibilities() { 621 return this.personResponsibilities; 622 } 623 624 public void setPersonResponsibilities(List<PersonRuleResponsibility> personResponsibilities) { 625 this.personResponsibilities = personResponsibilities; 626 } 627 628 public List<GroupRuleResponsibility> getGroupResponsibilities() { 629 return this.groupResponsibilities; 630 } 631 632 public void setGroupResponsibilities(List<GroupRuleResponsibility> groupResponsibilities) { 633 this.groupResponsibilities = groupResponsibilities; 634 } 635 636 public List<RoleRuleResponsibility> getRoleResponsibilities() { 637 return this.roleResponsibilities; 638 } 639 640 public void setRoleResponsibilities(List<RoleRuleResponsibility> roleResponsibilities) { 641 this.roleResponsibilities = roleResponsibilities; 642 } 643 644 /** 645 * @return the fieldValues 646 */ 647 public Map<String, String> getFieldValues() { 648 return this.fieldValues; 649 } 650 651 /** 652 * @param fieldValues the fieldValues to set 653 */ 654 public void setFieldValues(Map<String, String> fieldValues) { 655 this.fieldValues = fieldValues; 656 } 657 658 public String getGroupReviewerName() { 659 return this.groupReviewerName; 660 } 661 662 public String getGroupReviewerNamespace() { 663 return this.groupReviewerNamespace; 664 } 665 666 public String getPersonReviewer() { 667 return this.personReviewer; 668 } 669 670 public void setGroupReviewerName(String groupReviewerName) { 671 this.groupReviewerName = groupReviewerName; 672 } 673 674 public void setGroupReviewerNamespace(String groupReviewerNamespace) { 675 this.groupReviewerNamespace = groupReviewerNamespace; 676 } 677 678 public void setPersonReviewer(String personReviewer) { 679 this.personReviewer = personReviewer; 680 } 681 682 public GroupBo getGroupBo() { 683 GroupBo groupBo = null; 684 if (StringUtils.isNotBlank(getGroupReviewerName())) { 685 if ( groupBo == null ) { 686 groupBo = GroupBo.from(KimApiServiceLocator.getGroupService().getGroupByNamespaceCodeAndName( 687 getGroupReviewerNamespace(), getGroupReviewerName())); 688 } 689 } 690 return groupBo; 691 } 692 693 public PersonImpl getPersonImpl() { 694 return new PersonImpl(); 695 } 696 697 public String getPersonReviewerType() { 698 return this.personReviewerType; 699 } 700 701 public void setPersonReviewerType(String personReviewerType) { 702 this.personReviewerType = personReviewerType; 703 } 704 705 /** 706 * Converts a mutable bo to its immutable counterpart 707 * @param bo the mutable business object 708 * @return the immutable object 709 */ 710 public static org.kuali.rice.kew.api.rule.Rule to(RuleBaseValues bo) { 711 if (bo == null) { 712 return null; 713 } 714 return org.kuali.rice.kew.api.rule.Rule.Builder.create(bo).build(); 715 } 716 717 @Override 718 public void refresh() { 719 } 720}