View Javadoc

1   /*
2    * Copyright 2005-2007 The Kuali Foundation
3    *
4    *
5    * Licensed under the Educational Community License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    * http://www.opensource.org/licenses/ecl2.php
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.kuali.rice.kew.actionrequest;
18  
19  import org.apache.commons.lang.StringUtils;
20  import org.apache.commons.lang.builder.ToStringBuilder;
21  import org.apache.commons.lang.builder.ToStringStyle;
22  import org.hibernate.annotations.Fetch;
23  import org.hibernate.annotations.FetchMode;
24  import org.hibernate.annotations.GenericGenerator;
25  import org.hibernate.annotations.Parameter;
26  import org.joda.time.DateTime;
27  import org.kuali.rice.core.api.util.RiceConstants;
28  import org.kuali.rice.core.framework.persistence.jpa.OrmUtils;
29  import org.kuali.rice.kew.actionitem.ActionItem;
30  import org.kuali.rice.kew.actiontaken.ActionTakenValue;
31  import org.kuali.rice.kew.api.action.ActionRequest;
32  import org.kuali.rice.kew.api.action.ActionRequestPolicy;
33  import org.kuali.rice.kew.api.action.ActionRequestStatus;
34  import org.kuali.rice.kew.api.action.ActionRequestType;
35  import org.kuali.rice.kew.api.action.ActionTaken;
36  import org.kuali.rice.kew.api.action.DelegationType;
37  import org.kuali.rice.kew.api.action.RecipientType;
38  import org.kuali.rice.kew.dto.DTOConverter.RouteNodeInstanceLoader;
39  import org.kuali.rice.kew.engine.CompatUtils;
40  import org.kuali.rice.kew.engine.node.RouteNode;
41  import org.kuali.rice.kew.engine.node.RouteNodeInstance;
42  import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
43  import org.kuali.rice.kew.rule.RuleBaseValues;
44  import org.kuali.rice.kew.rule.service.RuleService;
45  import org.kuali.rice.kew.service.KEWServiceLocator;
46  import org.kuali.rice.kew.user.RoleRecipient;
47  import org.kuali.rice.kew.util.CodeTranslator;
48  import org.kuali.rice.kew.util.KEWConstants;
49  import org.kuali.rice.kim.api.group.Group;
50  import org.kuali.rice.kim.api.identity.Person;
51  import org.kuali.rice.kim.api.identity.principal.Principal;
52  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
53  
54  import javax.persistence.CascadeType;
55  import javax.persistence.Column;
56  import javax.persistence.Entity;
57  import javax.persistence.FetchType;
58  import javax.persistence.GeneratedValue;
59  import javax.persistence.Id;
60  import javax.persistence.JoinColumn;
61  import javax.persistence.ManyToOne;
62  import javax.persistence.NamedQueries;
63  import javax.persistence.NamedQuery;
64  import javax.persistence.OneToMany;
65  import javax.persistence.Table;
66  import javax.persistence.Transient;
67  import java.io.Serializable;
68  import java.sql.Timestamp;
69  import java.util.ArrayList;
70  import java.util.Iterator;
71  import java.util.List;
72  /**
73   * Bean mapped to DB. Represents ActionRequest to a workgroup, user or role.  Contains
74   * references to children/parent if a member of a graph
75   *
76   * @author Kuali Rice Team (rice.collab@kuali.org)
77   */
78  @Entity
79  @Table(name="KREW_ACTN_RQST_T")
80  //@Sequence(name="KREW_ACTN_RQST_S", property="actionRequestId")
81  @NamedQueries({
82    @NamedQuery(name="ActionRequestValue.FindByDocumentId", query="select arv from ActionRequestValue arv where arv.documentId = :documentId"),
83    @NamedQuery(name="ActionRequestValue.GetUserRequestCount", query="select count(arv) from ActionRequestValue arv where arv.documentId = :documentId and arv.recipientTypeCd = :recipientTypeCd and arv.principalId = :principalId and arv.currentIndicator = :currentIndicator"),
84    @NamedQuery(name="ActionRequestValue.FindActivatedByGroup", query="select count(arv) from ActionRequestValue arv where arv.groupId = :groupId and arv.currentIndicator = :currentIndicator and arv.status = :status"),
85    @NamedQuery(name="ActionRequestValue.FindAllByDocId", query="select arv from ActionRequestValue arv where arv.documentId = :documentId and arv.currentIndicator = :currentIndicator"),
86    @NamedQuery(name="ActionRequestValue.FindAllPendingByDocId", query="select arv from ActionRequestValue arv where arv.documentId = :documentId and arv.currentIndicator = :currentIndicator and (arv.status = :actionRequestStatus1 or arv.status = :actionRequestStatus2)"),
87    @NamedQuery(name="ActionRequestValue.FindAllRootByDocId", query="select arv from ActionRequestValue arv where arv.documentId = :documentId and arv.currentIndicator = :currentIndicator and arv.parentActionRequest is null"),
88    @NamedQuery(name="ActionRequestValue.FindByStatusAndDocId", query="select arv from ActionRequestValue arv where arv.documentId = :documentId and arv.currentIndicator = :currentIndicator and arv.status = :status"),
89    @NamedQuery(name="ActionRequestValue.FindPendingByActionRequestedAndDocId", query="select arv from ActionRequestValue arv where arv.documentId = :documentId and arv.currentIndicator = :currentIndicator and arv.actionRequested = :actionRequested and (arv.status = :actionRequestStatus1 or arv.status = :actionRequestStatus2)"),
90    @NamedQuery(name="ActionRequestValue.FindPendingByDocIdAtOrBelowRouteLevel", query="select arv from ActionRequestValue arv where arv.documentId = :documentId and arv.currentIndicator = :currentIndicator and arv.status <> :status and arv.routeLevel <= :routeLevel"),
91    @NamedQuery(name="ActionRequestValue.FindPendingRootRequestsByDocIdAtOrBelowRouteLevel", query="select arv from ActionRequestValue arv where arv.documentId = :documentId and arv.currentIndicator = :currentIndicator and arv.parentActionRequest is null and arv.status <> :status and routeLevel <= :routeLevel"),
92    @NamedQuery(name="ActionRequestValue.FindPendingRootRequestsByDocIdAtRouteLevel", query="select arv from ActionRequestValue arv where arv.documentId = :documentId and arv.currentIndicator = :currentIndicator and arv.parentActionRequest is null and arv.status <> :status and routeLevel = :routeLevel"),
93    @NamedQuery(name="ActionRequestValue.FindPendingRootRequestsByDocIdAtRouteNode", query="select arv from ActionRequestValue arv where arv.documentId = :documentId and arv.currentIndicator = :currentIndicator and arv.parentActionRequest is null and arv.nodeInstance.routeNodeInstanceId = :routeNodeInstanceId and (arv.status = :actionRequestStatus1 or arv.status = :actionRequestStatus2)"),
94    @NamedQuery(name="ActionRequestValue.FindPendingRootRequestsByDocumentType", query="select arv from ActionRequestValue arv where arv.documentId in (select drhv.documentId from DocumentRouteHeaderValue drhv where drhv.documentTypeId = :documentTypeId) and arv.currentIndicator = :currentIndicator and arv.parentActionRequest is null and (arv.status = :actionRequestStatus1 or arv.status = :actionRequestStatus2)"),
95    @NamedQuery(name="ActionRequestValue.FindRootRequestsByDocIdAtRouteNode", query="select arv from ActionRequestValue arv where arv.documentId = :documentId and arv.currentIndicator = :currentIndicator and arv.parentActionRequest is null and arv.nodeInstance.routeNodeInstanceId = :routeNodeInstanceId"),
96    @NamedQuery(name="ActionRequestValue.GetRequestGroupIds", query="select arv.groupId from ActionRequestValue arv where arv.documentId = :documentId and arv.currentIndicator = :currentIndicator and arv.recipientTypeCd = :recipientTypeCd"),
97    @NamedQuery(name="ActionRequestValue.FindByStatusAndGroupId", query="select arv from ActionRequestValue arv where arv.groupId = :groupId and arv.currentIndicator = :currentIndicator and arv.status = :status")
98  })
99  public class ActionRequestValue implements Serializable {
100 
101 	private static final long serialVersionUID = 8781414791855848385L;
102 
103 	private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(ActionRequestValue.class);
104 
105     private static final String ACTION_CODE_RANK = "FKACB";//B is a hack for allowing blanket approves to count for approve and complete requests in findPreviousAction in ActionTakenService this is a hack and accounts for the -3 on compareActionCode
106     private static final String RECIPIENT_TYPE_RANK = "RWU";
107     private static final String DELEGATION_TYPE_RANK = "SPN";
108 
109     @Id
110     @GeneratedValue(generator="KREW_ACTN_RQST_S")
111 	@GenericGenerator(name="KREW_ACTN_RQST_S",strategy="org.hibernate.id.enhanced.SequenceStyleGenerator",parameters={
112 			@Parameter(name="sequence_name",value="KREW_ACTN_RQST_S"),
113 			@Parameter(name="value_column",value="id")
114 	})
115 	@Column(name="ACTN_RQST_ID")
116 	private String actionRequestId;
117     @Column(name="ACTN_RQST_CD")
118 	private String actionRequested;
119     @Column(name="DOC_HDR_ID")
120 	private String documentId;
121     @Column(name="STAT_CD")
122 	private String status;
123     @Column(name="RSP_ID")
124 	private String responsibilityId;
125     @Column(name="GRP_ID")
126 	private String groupId;
127     @Column(name="RECIP_TYP_CD")
128 	private String recipientTypeCd;
129     @Column(name="PRIO_NBR")
130 	private Integer priority;
131     @Column(name="RTE_LVL_NBR")
132 	private Integer routeLevel;
133     @Column(name="ACTN_TKN_ID", insertable=false, updatable=false)
134 	private String actionTakenId;
135     @Column(name="DOC_VER_NBR")
136     private Integer docVersion = 1;
137 	@Column(name="CRTE_DT")
138 	private java.sql.Timestamp createDate;
139     @Column(name="RSP_DESC_TXT")
140 	private String responsibilityDesc;
141     @Column(name="ACTN_RQST_ANNOTN_TXT")
142 	private String annotation;
143     @Column(name="VER_NBR")
144 	private Integer jrfVerNbr;
145     @Column(name="PRNCPL_ID")
146 	private String principalId;
147     @Column(name="FRC_ACTN")
148 	private Boolean forceAction;
149     @Column(name="PARNT_ID", insertable=false, updatable=false)
150 	private String parentActionRequestId;
151     @Column(name="QUAL_ROLE_NM")
152 	private String qualifiedRoleName;
153     @Column(name="ROLE_NM")
154 	private String roleName;
155     @Column(name="QUAL_ROLE_NM_LBL_TXT")
156 	private String qualifiedRoleNameLabel;
157     @Transient
158     private String displayStatus;
159     @Column(name="RULE_ID")
160 	private String ruleBaseValuesId;
161 
162     @Column(name="DLGN_TYP")
163     private String delegationType;
164     @Column(name="APPR_PLCY")
165 	private String approvePolicy;
166 
167     @ManyToOne(fetch=FetchType.EAGER)
168 	@JoinColumn(name="PARNT_ID")
169 	private ActionRequestValue parentActionRequest;
170     @Fetch(value = FetchMode.SELECT)
171     @OneToMany(mappedBy="parentActionRequest",cascade={CascadeType.PERSIST, CascadeType.MERGE},fetch=FetchType.EAGER)
172     private List<ActionRequestValue> childrenRequests = new ArrayList<ActionRequestValue>();
173     @ManyToOne(fetch=FetchType.EAGER)
174 	@JoinColumn(name="ACTN_TKN_ID")
175 	private ActionTakenValue actionTaken;
176     //@OneToMany(fetch=FetchType.LAZY,mappedBy="actionRequestId")
177     //private List<ActionItem> actionItems = new ArrayList<ActionItem>();
178     @Column(name="CUR_IND")
179     private Boolean currentIndicator = true;
180     @Transient
181     private String createDateString;
182 
183     /* New Workflow 2.1 Field */
184     // The node instance at which this request was generated
185     @ManyToOne(fetch=FetchType.EAGER)
186 	@JoinColumn(name="RTE_NODE_INSTN_ID")
187 	private RouteNodeInstance nodeInstance;
188 
189     @Column(name="RQST_LBL")
190     private String requestLabel;
191     
192     @Transient
193     private boolean resolveResponsibility = true;
194     @Transient
195     private DocumentRouteHeaderValue routeHeader;
196     @Transient
197     private List<ActionItem> simulatedActionItems;
198     
199     public ActionRequestValue() {
200         createDate = new Timestamp(System.currentTimeMillis());
201     }
202     
203     //@PrePersist
204     public void beforeInsert(){
205     	OrmUtils.populateAutoIncValue(this, KEWServiceLocator.getEntityManagerFactory().createEntityManager());
206     }
207    
208     public Group getGroup() {
209         if (getGroupId() == null) {
210             LOG.error("Attempting to get a group with a blank group id");
211             return null;
212         }
213         return KimApiServiceLocator.getGroupService().getGroup(getGroupId());
214     }
215 
216     public String getRouteLevelName() {
217         // this is for backward compatibility of requests which have not been converted
218         if (CompatUtils.isRouteLevelRequest(this)) {
219             int routeLevelInt = getRouteLevel();
220             if (routeLevelInt == KEWConstants.EXCEPTION_ROUTE_LEVEL) {
221                 return "Exception";
222             }
223 
224             List<RouteNode> routeLevelNodes = CompatUtils.getRouteLevelCompatibleNodeList(KEWServiceLocator.getRouteHeaderService().getRouteHeader(documentId).getDocumentType());
225             if (!(routeLevelInt < routeLevelNodes.size())) {
226                 return "Not Found";
227             }
228             return ((RouteNode)routeLevelNodes.get(routeLevelInt)).getRouteNodeName();
229         } else {
230             return (nodeInstance == null ? "Exception" : nodeInstance.getName());
231         }
232     }
233 
234     public boolean isUserRequest() {
235         return principalId != null;
236     }
237 
238     public Principal getPrincipal() {
239     	if (getPrincipalId() == null) {
240     		return null;
241     	}
242     	return KEWServiceLocator.getIdentityHelperService().getPrincipal(getPrincipalId());
243     }
244     
245     public Person getPerson() {
246     	if (getPrincipalId() == null) {
247     		return null;
248     	}
249     	return KimApiServiceLocator.getPersonService().getPerson(getPrincipalId());
250     }
251 
252     public String getDisplayName() {
253     	if (isUserRequest()) {
254     	    return getPerson().getName();
255     	} else if (isGroupRequest()) {
256     		return getGroup().getName();
257     	} else if (isRoleRequest()) {
258     		return getRoleName();
259     	}
260     	return "";
261     }
262 
263     public Recipient getRecipient() {
264         if (getPrincipalId() != null) {
265             return new KimPrincipalRecipient(getPrincipal());
266         } else if (getGroupId() != null){
267             return new KimGroupRecipient(getGroup());
268         } else {
269         	return new RoleRecipient(this.getRoleName());
270         }
271     }
272 
273     public boolean isPending() {
274         return ActionRequestStatus.INITIALIZED.getCode().equals(getStatus()) || ActionRequestStatus.ACTIVATED.getCode().equals(getStatus());
275     }
276 
277     public String getStatusLabel() {
278         return CodeTranslator.getActionRequestStatusLabel(getStatus());
279     }
280 
281     public String getActionRequestedLabel() {
282     	if (StringUtils.isNotBlank(getRequestLabel())) {
283     		return getRequestLabel();
284     	}
285     	return CodeTranslator.getActionRequestLabel(getActionRequested());
286     }
287 
288     /**
289      * @return Returns the actionTaken.
290      */
291     public ActionTakenValue getActionTaken() {
292         return actionTaken;
293     }
294 
295     /**
296      * @param actionTaken
297      *            The actionTaken to set.
298      */
299     public void setActionTaken(ActionTakenValue actionTaken) {
300         this.actionTaken = actionTaken;
301     }
302 
303     /**
304      * @return Returns the actionRequested.
305      */
306     public String getActionRequested() {
307         return actionRequested;
308     }
309 
310     /**
311      * @param actionRequested
312      *            The actionRequested to set.
313      */
314     public void setActionRequested(String actionRequested) {
315         this.actionRequested = actionRequested;
316     }
317 
318     /**
319      * @return Returns the actionRequestId.
320      */
321     public String getActionRequestId() {
322         return actionRequestId;
323     }
324 
325     /**
326      * @param actionRequestId
327      *            The actionRequestId to set.
328      */
329     public void setActionRequestId(String actionRequestId) {
330         this.actionRequestId = actionRequestId;
331     }
332 
333     /**
334      * @return Returns the actionTakenId.
335      */
336     public String getActionTakenId() {
337         return actionTakenId;
338     }
339 
340     /**
341      * @param actionTakenId
342      *            The actionTakenId to set.
343      */
344     public void setActionTakenId(String actionTakenId) {
345         this.actionTakenId = actionTakenId;
346     }
347 
348     /**
349      * @return Returns the annotation.
350      */
351     public String getAnnotation() {
352         return annotation;
353     }
354 
355     /**
356      * @param annotation
357      *            The annotation to set.
358      */
359     public void setAnnotation(String annotation) {
360         this.annotation = annotation;
361     }
362 
363     /**
364      * @return Returns the createDate.
365      */
366     public java.sql.Timestamp getCreateDate() {
367         return createDate;
368     }
369 
370     /**
371      * @param createDate
372      *            The createDate to set.
373      */
374     public void setCreateDate(java.sql.Timestamp createDate) {
375         this.createDate = createDate;
376     }
377 
378     /**
379      * @return Returns the docVersion.
380      */
381     public Integer getDocVersion() {
382         return docVersion;
383     }
384 
385     /**
386      * @param docVersion
387      *            The docVersion to set.
388      */
389     public void setDocVersion(Integer docVersion) {
390         this.docVersion = docVersion;
391     }
392 
393     public String getPrincipalId() {
394         return principalId;
395     }
396 
397     public void setPrincipalId(String principalId) {
398         this.principalId = principalId;
399     }
400     
401     /**
402      * @return Returns the forceAction.
403      */
404     public Boolean getForceAction() {
405         return forceAction;
406     }
407 
408     /**
409      * @param forceAction
410      *            The forceAction to set.
411      */
412     public void setForceAction(Boolean forceAction) {
413         this.forceAction = forceAction;
414     }
415 
416     /**
417      * @return Returns the jrfVerNbr.
418      */
419     public Integer getJrfVerNbr() {
420         return jrfVerNbr;
421     }
422 
423     /**
424      * @param jrfVerNbr
425      *            The jrfVerNbr to set.
426      */
427     public void setJrfVerNbr(Integer jrfVerNbr) {
428         this.jrfVerNbr = jrfVerNbr;
429     }
430 
431     /**
432      * @return Returns the priority.
433      */
434     public Integer getPriority() {
435         return priority;
436     }
437 
438     /**
439      * @param priority
440      *            The priority to set.
441      */
442     public void setPriority(Integer priority) {
443         this.priority = priority;
444     }
445 
446     /**
447      * @return Returns the recipientTypeCd.
448      */
449     public String getRecipientTypeCd() {
450         return recipientTypeCd;
451     }
452 
453     /**
454      * @param recipientTypeCd
455      *            The recipientTypeCd to set.
456      */
457     public void setRecipientTypeCd(String recipientTypeCd) {
458         this.recipientTypeCd = recipientTypeCd;
459     }
460 
461     /**
462      * @return Returns the responsibilityDesc.
463      */
464     public String getResponsibilityDesc() {
465         return responsibilityDesc;
466     }
467 
468     /**
469      * @param responsibilityDesc
470      *            The responsibilityDesc to set.
471      */
472     public void setResponsibilityDesc(String responsibilityDesc) {
473         this.responsibilityDesc = responsibilityDesc;
474     }
475 
476     /**
477      * @return Returns the responsibilityId.
478      */
479     public String getResponsibilityId() {
480         return responsibilityId;
481     }
482 
483     /**
484      * @param responsibilityId
485      *            The responsibilityId to set.
486      */
487     public void setResponsibilityId(String responsibilityId) {
488         this.responsibilityId = responsibilityId;
489     }
490 
491     /**
492      * @return Returns the documentId.
493      */
494     public String getDocumentId() {
495         return documentId;
496     }
497 
498     public void setDocumentId(String documentId) {
499         this.documentId = documentId;
500     }
501 
502     public Integer getRouteLevel() {
503         return routeLevel;
504     }
505 
506     public void setRouteLevel(Integer routeLevel) {
507         this.routeLevel = routeLevel;
508     }
509 
510     public String getStatus() {
511         return status;
512     }
513 
514     public void setStatus(String status) {
515         this.status = status;
516     }
517 
518     public String getGroupId() {
519         return groupId;
520     }
521 
522     public void setGroupId(String groupId) {
523         this.groupId = groupId;
524     }
525 
526     public boolean isInitialized() {
527         return ActionRequestStatus.INITIALIZED.getCode().equals(getStatus());
528     }
529 
530     public boolean isActive() {
531         return ActionRequestStatus.ACTIVATED.getCode().equals(getStatus());
532     }
533 
534     public boolean isApproveOrCompleteRequest() {
535         return KEWConstants.ACTION_REQUEST_APPROVE_REQ.equals(getActionRequested()) || KEWConstants.ACTION_REQUEST_COMPLETE_REQ.equals(getActionRequested());
536     }
537 
538     public boolean isDone() {
539         return ActionRequestStatus.DONE.getCode().equals(getStatus());
540     }
541 
542     public boolean isReviewerUser() {
543         return RecipientType.PRINCIPAL.getCode().equals(getRecipientTypeCd());
544     }
545 
546     public boolean isRecipientRoutedRequest(String principalId) {
547     	//before altering this method it is used in checkRouteLogAuthentication
548     	//don't break that method
549     	if (principalId == null || "".equals(principalId)) {
550     		return false;
551     	}
552 
553     	boolean isRecipientInGraph = false;
554     	if (isReviewerUser()) {
555     			isRecipientInGraph = getPrincipalId().equals(principalId);
556     	} else if (isGroupRequest()) {
557     		Group group = getGroup();
558 			if (group == null){
559 				LOG.error("Was unable to retrieve workgroup " + getGroupId());
560 			}
561     		isRecipientInGraph = KimApiServiceLocator.getGroupService().isMemberOfGroup(principalId, group.getId());
562     	}
563 
564 
565         for (ActionRequestValue childRequest : getChildrenRequests())
566         {
567             isRecipientInGraph = isRecipientInGraph || childRequest.isRecipientRoutedRequest(principalId);
568         }
569 
570     	return isRecipientInGraph;
571     }
572 
573     public boolean isRecipientRoutedRequest(Recipient recipient) {
574     	//before altering this method it is used in checkRouteLogAuthentication
575     	//don't break that method
576     	if (recipient == null) {
577     		return false;
578     	}
579 
580     	boolean isRecipientInGraph = false;
581     	if (isReviewerUser()) {
582     		if (recipient instanceof KimPrincipalRecipient) {
583     			isRecipientInGraph = getPrincipalId().equals(((KimPrincipalRecipient) recipient).getPrincipalId());
584     		} else if (recipient instanceof KimGroupRecipient){
585     			isRecipientInGraph = KimApiServiceLocator.getGroupService().isMemberOfGroup(getPrincipalId(), ((KimGroupRecipient)recipient).getGroup().getId());
586     		}
587 
588     	} else if (isGroupRequest()) {
589     		Group group = getGroup();
590 			if (group == null){
591 				LOG.error("Was unable to retrieve workgroup " + getGroupId());
592 			}
593     		if (recipient instanceof KimPrincipalRecipient) {
594     			KimPrincipalRecipient principalRecipient = (KimPrincipalRecipient)recipient;
595     			isRecipientInGraph = KimApiServiceLocator.getGroupService().isMemberOfGroup(principalRecipient.getPrincipalId(), group.getId());
596     		} else if (recipient instanceof KimGroupRecipient) {
597     			isRecipientInGraph = ((KimGroupRecipient) recipient).getGroup().getId().equals(group.getId());
598     		}
599     	}
600 
601 
602         for (ActionRequestValue childRequest : getChildrenRequests())
603         {
604             isRecipientInGraph = isRecipientInGraph || childRequest.isRecipientRoutedRequest(recipient);
605         }
606 
607     	return isRecipientInGraph;
608     }
609 
610     public boolean isGroupRequest(){
611     	return RecipientType.GROUP.getCode().equals(getRecipientTypeCd());
612     }
613 
614     public boolean isRoleRequest() {
615         return RecipientType.ROLE.getCode().equals(getRecipientTypeCd());
616     }
617 
618     public boolean isAcknowledgeRequest() {
619         return KEWConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ.equals(getActionRequested());
620     }
621 
622     public boolean isApproveRequest() {
623         return KEWConstants.ACTION_REQUEST_APPROVE_REQ.equals(getActionRequested());
624     }
625 
626     public boolean isCompleteRequst() {
627         return KEWConstants.ACTION_REQUEST_COMPLETE_REQ.equals(getActionRequested());
628     }
629 
630     public boolean isFYIRequest() {
631         return KEWConstants.ACTION_REQUEST_FYI_REQ.equals(getActionRequested());
632     }
633 
634     /**
635      * Allows comparison of action requests to see which is greater responsibility. -1 : indicates code 1 is lesser responsibility than code 2 0 : indicates the same responsibility 1 : indicates code1 is greater responsibility than code 2 The priority of action requests is as follows: fyi < acknowledge < (approve == complete)
636      *
637      * @param code1
638      * @param code2
639      * @param completeAndApproveTheSame
640      * @return -1 if less than, 0 if equal, 1 if greater than
641      */
642     public static int compareActionCode(String code1, String code2, boolean completeAndApproveTheSame) {
643     	int cutoff = Integer.MAX_VALUE;
644     	if (completeAndApproveTheSame) {
645     		// hacked so that APPROVE and COMPLETE are equal
646     		cutoff = ACTION_CODE_RANK.length() - 3;
647     	}
648         Integer code1Index = Math.min(ACTION_CODE_RANK.indexOf(code1), cutoff);
649         Integer code2Index = Math.min(ACTION_CODE_RANK.indexOf(code2), cutoff);
650         return code1Index.compareTo(code2Index);
651     }
652 
653     /**
654      * Allows comparison of action requests to see which is greater responsibility. -1 : indicates type 1 is lesser responsibility than type 2 0 : indicates the same responsibility 1 : indicates type1 is greater responsibility than type 2
655      *
656      * @param type1
657      * @param type2
658      * @return -1 if less than, 0 if equal, 1 if greater than
659      */
660     public static int compareRecipientType(String type1, String type2) {
661         Integer type1Index = RECIPIENT_TYPE_RANK.indexOf(type1);
662         Integer type2Index = RECIPIENT_TYPE_RANK.indexOf(type2);
663         return type1Index.compareTo(type2Index);
664     }
665 
666     public static int compareDelegationType(String type1, String type2) {
667     	if (StringUtils.isEmpty(type1)) {
668     		type1 = "N";
669     	}
670     	if (StringUtils.isEmpty(type2)) {
671     		type2 = "N";
672     	}
673     	Integer type1Index = DELEGATION_TYPE_RANK.indexOf(type1);
674         Integer type2Index = DELEGATION_TYPE_RANK.indexOf(type2);
675         return type1Index.compareTo(type2Index);
676     }
677 
678     public List<ActionItem> getActionItems() {
679     	if (this.simulatedActionItems == null || this.simulatedActionItems.isEmpty()) {
680     		return (List<ActionItem>) KEWServiceLocator.getActionListService().findByActionRequestId(actionRequestId);
681     	} else {
682     		return this.simulatedActionItems;
683     	}
684     }
685 
686     public List<ActionItem> getSimulatedActionItems() {
687     	if (this.simulatedActionItems == null) {
688     		this.simulatedActionItems = new ArrayList<ActionItem>();
689     	}
690 		return this.simulatedActionItems;
691 	}
692 
693 	public void setSimulatedActionItems(List<ActionItem> simulatedActionItems) {
694 		this.simulatedActionItems = simulatedActionItems;
695 	}
696 
697 	public Boolean getCurrentIndicator() {
698         return currentIndicator;
699     }
700 
701     public void setCurrentIndicator(Boolean currentIndicator) {
702         this.currentIndicator = currentIndicator;
703     }
704 
705     public String getParentActionRequestId() {
706         return parentActionRequestId;
707     }
708 
709     public void setParentActionRequestId(String parentActionRequestId) {
710         this.parentActionRequestId = parentActionRequestId;
711     }
712 
713     public ActionRequestValue getParentActionRequest() {
714         return parentActionRequest;
715     }
716 
717     public void setParentActionRequest(ActionRequestValue parentActionRequest) {
718         this.parentActionRequest = parentActionRequest;
719     }
720 
721     public List<ActionRequestValue> getChildrenRequests() {
722         return childrenRequests;
723     }
724 
725     public void setChildrenRequests(List<ActionRequestValue> childrenRequests) {
726         this.childrenRequests = childrenRequests;
727     }
728 
729     public String getQualifiedRoleName() {
730         return qualifiedRoleName;
731     }
732 
733     public void setQualifiedRoleName(String roleName) {
734         this.qualifiedRoleName = roleName;
735     }
736 
737     public String getDelegationType() {
738         return delegationType;
739     }
740 
741     public void setDelegationType(String delegatePolicy) {
742         this.delegationType = delegatePolicy;
743     }
744 
745     public String getRoleName() {
746         return roleName;
747     }
748 
749     public void setRoleName(String roleName) {
750         this.roleName = roleName;
751     }
752 
753     public String getApprovePolicy() {
754         return approvePolicy;
755     }
756 
757     public void setApprovePolicy(String requestType) {
758         this.approvePolicy = requestType;
759     }
760 
761     public boolean getHasApprovePolicy() {
762         return getApprovePolicy() != null;
763     }
764 
765     public boolean isDeactivated() {
766         return ActionRequestStatus.DONE.getCode().equals(getStatus());
767     }
768 
769     public boolean hasParent() {
770         return getParentActionRequest() != null;
771     }
772 
773     public boolean hasChild(ActionRequestValue actionRequest) {
774         if (actionRequest == null)
775             return false;
776         String actionRequestId = actionRequest.getActionRequestId();
777         for (Iterator<ActionRequestValue> iter = getChildrenRequests().iterator(); iter.hasNext();) {
778             ActionRequestValue childRequest = iter.next();
779             if (childRequest.equals(actionRequest) || (actionRequestId != null && actionRequestId.equals(childRequest.getActionRequestId()))) {
780                 return true;
781             }
782         }
783         return false;
784     }
785 
786     public String getDisplayStatus() {
787         return displayStatus;
788     }
789 
790     public void setDisplayStatus(String displayStatus) {
791         this.displayStatus = displayStatus;
792     }
793 
794     public String getQualifiedRoleNameLabel() {
795         return qualifiedRoleNameLabel;
796     }
797 
798     public void setQualifiedRoleNameLabel(String qualifiedRoleNameLabel) {
799         this.qualifiedRoleNameLabel = qualifiedRoleNameLabel;
800     }
801 
802     public String getCreateDateString() {
803         if (createDateString == null || createDateString.trim().equals("")) {
804             return RiceConstants.getDefaultDateFormat().format(getCreateDate());
805         } else {
806             return createDateString;
807         }
808     }
809 
810     public void setCreateDateString(String createDateString) {
811         this.createDateString = createDateString;
812     }
813 
814     public RouteNodeInstance getNodeInstance() {
815 		return nodeInstance;
816 	}
817 
818     public String getPotentialNodeName() {
819         return (getNodeInstance() == null ? "" : getNodeInstance().getName());
820     }
821 
822 	public void setNodeInstance(RouteNodeInstance nodeInstance) {
823 		this.nodeInstance = nodeInstance;
824 	}
825 
826 	public String getRecipientTypeLabel() {
827 		return RecipientType.fromCode(getRecipientTypeCd()).getLabel();
828     }
829 
830     public RuleBaseValues getRuleBaseValues(){
831         if(ruleBaseValuesId != null){
832             return getRuleService().findRuleBaseValuesById(ruleBaseValuesId);
833         }
834         return null;
835     }
836     public String getRuleBaseValuesId() {
837         return ruleBaseValuesId;
838     }
839 
840     public void setRuleBaseValuesId(String ruleBaseValuesId) {
841         this.ruleBaseValuesId = ruleBaseValuesId;
842     }
843     
844 	private RuleService getRuleService() {
845         return (RuleService) KEWServiceLocator.getService(KEWServiceLocator.RULE_SERVICE);
846     }
847 
848     public boolean isPrimaryDelegator() {
849         boolean primaryDelegator = false;
850         for (Iterator<ActionRequestValue> iter = childrenRequests.iterator(); iter.hasNext();) {
851             ActionRequestValue childRequest = iter.next();
852             primaryDelegator = DelegationType.PRIMARY.getCode().equals(childRequest.getDelegationType()) || primaryDelegator;
853         }
854         return primaryDelegator;
855     }
856 
857     /**
858      * Used to get primary delegate names on route log in the 'Requested Of' section so primary delegate requests
859      * list the delegate and not the delegator as having the request 'IN ACTION LIST'.  This method doesn't recurse
860      * and therefore assume an AR structure.
861      *
862      * @return primary delgate requests
863      */
864     public List<ActionRequestValue> getPrimaryDelegateRequests() {
865         List<ActionRequestValue> primaryDelegateRequests = new ArrayList<ActionRequestValue>();
866         for (ActionRequestValue childRequest : childrenRequests)
867         {
868             if (DelegationType.PRIMARY.getCode().equals(childRequest.getDelegationType()))
869             {
870                 if (childRequest.isRoleRequest())
871                 {
872                     for (ActionRequestValue actionRequestValue : childRequest.getChildrenRequests())
873                     {
874                         primaryDelegateRequests.add(actionRequestValue);
875                     }
876                 } else
877                 {
878                 	primaryDelegateRequests.add(childRequest);
879                 }
880             }
881         }
882         return primaryDelegateRequests;
883     }
884 
885     public boolean isAdHocRequest() {                                          
886     	return KEWConstants.ADHOC_REQUEST_RESPONSIBILITY_ID.equals(getResponsibilityId());
887     }
888 
889     public boolean isGeneratedRequest() {
890     	return KEWConstants.MACHINE_GENERATED_RESPONSIBILITY_ID.equals(getResponsibilityId());
891     }
892 
893     public boolean isExceptionRequest() {
894     	return KEWConstants.EXCEPTION_REQUEST_RESPONSIBILITY_ID.equals(getResponsibilityId());
895     }
896 
897     public boolean isRouteModuleRequest() {
898     	// FIXME: KULRICE-5201 switched rsp_id to a varchar, so the comparison below is no longer valid
899 //    	return getResponsibilityId() > 0;
900     	// TODO: KULRICE-5329 Verify that this code below makes sense 
901     	return getResponsibilityId() != null && !KEWConstants.SPECIAL_RESPONSIBILITY_ID_SET.contains(getResponsibilityId());
902     }
903 
904     public String toString() {
905         return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
906             .append("actionRequestId", actionRequestId)
907             .append("actionRequested", actionRequested)
908             .append("documentId", documentId)
909             .append("status", status)
910             .append("responsibilityId", responsibilityId)
911             .append("groupId", groupId)
912             .append("recipientTypeCd", recipientTypeCd)
913             .append("priority", priority)
914             .append("routeLevel", routeLevel)
915             .append("actionTakenId", actionTakenId)
916             .append("docVersion", docVersion)
917             .append("createDate", createDate)
918             .append("responsibilityDesc", responsibilityDesc)
919             .append("annotation", annotation)
920             .append("jrfVerNbr", jrfVerNbr)
921             .append("principalId", principalId)
922             .append("forceAction", forceAction)
923             .append("parentActionRequestId", parentActionRequestId)
924             .append("qualifiedRoleName", qualifiedRoleName)
925             .append("roleName", roleName)
926             .append("qualifiedRoleNameLabel", qualifiedRoleNameLabel)
927             .append("displayStatus", displayStatus)
928             .append("ruleBaseValuesId", ruleBaseValuesId)
929             .append("delegationType", delegationType)
930             .append("approvePolicy", approvePolicy)
931             .append("childrenRequests", childrenRequests == null ? null : childrenRequests.size())
932             .append("actionTaken", actionTaken)
933             .append("currentIndicator", currentIndicator)
934             .append("createDateString", createDateString)
935             .append("nodeInstance", nodeInstance).toString();
936     }
937 
938 	public String getRequestLabel() {
939 		return this.requestLabel;
940 	}
941 
942 	public void setRequestLabel(String requestLabel) {
943 		this.requestLabel = requestLabel;
944 	}
945 
946     public String getGroupName() {
947         return KimApiServiceLocator.getGroupService().getGroup(this.groupId).getName();
948     }
949 
950 	/**
951 	 * @return the resolveResponsibility
952 	 */
953 	public boolean getResolveResponsibility() {
954 		return this.resolveResponsibility;
955 	}
956 
957 	/**
958 	 * @param resolveResponsibility the resolveResponsibility to set
959 	 */
960 	public void setResolveResponsibility(boolean resolveResponsibility) {
961 		this.resolveResponsibility = resolveResponsibility;
962 	}
963 
964 	public DocumentRouteHeaderValue getRouteHeader() {
965 		if (this.routeHeader == null && this.documentId != null) {
966 			this.routeHeader = KEWServiceLocator.getRouteHeaderService().getRouteHeader(this.documentId);
967 		}
968 		return this.routeHeader;
969 	}
970 
971 	public void setRouteHeader(DocumentRouteHeaderValue routeHeader) {
972 		this.routeHeader = routeHeader;
973 	}
974 	
975 	public static ActionRequest to(ActionRequestValue actionRequestBo) {
976 		if (actionRequestBo == null) {
977 			return null;
978 		}
979 		return createActionRequestBuilder(actionRequestBo).build();
980 	}
981 	
982 	private static ActionRequest.Builder createActionRequestBuilder(ActionRequestValue actionRequestBo) {
983 		ActionRequest.Builder builder = ActionRequest.Builder.create(actionRequestBo.getActionRequestId(),
984 				ActionRequestType.fromCode(actionRequestBo.getActionRequested()),
985 				ActionRequestStatus.fromCode(actionRequestBo.getStatus()),
986 				actionRequestBo.getResponsibilityId(),
987 				actionRequestBo.getDocumentId(),
988 				RecipientType.fromCode(actionRequestBo.getRecipientTypeCd()));
989 		if (actionRequestBo.getActionTaken() != null) {
990 			builder.setActionTaken(ActionTaken.Builder.create(ActionTakenValue.to(actionRequestBo.getActionTaken())));
991 		}
992 		builder.setAnnotation(actionRequestBo.getAnnotation());
993 		builder.setCurrent(actionRequestBo.getCurrentIndicator().booleanValue());
994 		builder.setDateCreated(new DateTime(actionRequestBo.getCreateDate().getTime()));
995 		if (!StringUtils.isBlank(actionRequestBo.getDelegationType())) {
996 			builder.setDelegationType(DelegationType.fromCode(actionRequestBo.getDelegationType()));
997 		}
998 		builder.setForceAction(actionRequestBo.getForceAction().booleanValue());
999 		builder.setGroupId(actionRequestBo.getGroupId());
1000 		builder.setNodeName(actionRequestBo.getPotentialNodeName());
1001 		if (actionRequestBo.getParentActionRequestId() != null) {
1002 			builder.setParentActionRequestId(actionRequestBo.getParentActionRequestId());
1003 		}
1004 		builder.setPrincipalId(actionRequestBo.getPrincipalId());
1005 		if (actionRequestBo.getPriority() == null) {
1006 			builder.setPriority(KEWConstants.ACTION_REQUEST_DEFAULT_PRIORITY);
1007 		} else {
1008             builder.setPriority(actionRequestBo.getPriority().intValue());
1009         }
1010         if (actionRequestBo.getRouteLevel() == null ) {
1011             builder.setRouteLevel(0);
1012         } else {
1013             builder.setRouteLevel(actionRequestBo.getRouteLevel().intValue());
1014         }
1015 		builder.setQualifiedRoleName(actionRequestBo.getQualifiedRoleName());
1016 		builder.setQualifiedRoleNameLabel(actionRequestBo.getQualifiedRoleNameLabel());
1017 		builder.setRequestLabel(actionRequestBo.getRequestLabel());
1018 		if (!StringUtils.isBlank(actionRequestBo.getApprovePolicy())) {
1019 			builder.setRequestPolicy(ActionRequestPolicy.fromCode(actionRequestBo.getApprovePolicy()));
1020 		}
1021 		builder.setResponsibilityDescription(actionRequestBo.getResponsibilityDesc());
1022 		builder.setRoleName(actionRequestBo.getRoleName());
1023 		if (actionRequestBo.getNodeInstance() != null) {
1024 			builder.setRouteNodeInstanceId(actionRequestBo.getNodeInstance().getRouteNodeInstanceId());
1025 		}
1026 		
1027 		List<ActionRequest.Builder> childRequests = new ArrayList<ActionRequest.Builder>();
1028 		if (actionRequestBo.getChildrenRequests() != null) {
1029 			for (ActionRequestValue childActionRequestBo : actionRequestBo.getChildrenRequests()) {
1030 				childRequests.add(createActionRequestBuilder(childActionRequestBo));
1031 			}
1032 		}
1033 		builder.setChildRequests(childRequests);
1034 		return builder;
1035 	}
1036 	
1037     /**
1038      * TODO - this javadoc copied from DTOConverter, needs to be updated!
1039      * 
1040      * Converts an ActionRequestVO to an ActionRequest. The ActionRequestDTO passed in must be the root action request in the
1041      * graph, otherwise an IllegalArgumentException is thrown. This is to avoid potentially sticky issues with circular
1042      * references in the conversion. NOTE: This method's primary purpose is to convert ActionRequestVOs returned from a
1043      * RouteModule. Incidentally, the DTO's returned from the route module will be lacking some information (like the node
1044      * instance) so no attempts are made to convert this data since further initialization is handled by a higher level
1045      * component (namely ActionRequestService.initializeActionRequestGraph).
1046      */
1047     public static ActionRequestValue from(ActionRequest actionRequest) {
1048         return ActionRequestValue.from(actionRequest, null);
1049     }
1050     
1051     /**
1052      * Converts an ActionRequestVO to an ActionRequest. The ActionRequestDTO passed in must be the root action request in the
1053      * graph, otherwise an IllegalArgumentException is thrown. This is to avoid potentially sticky issues with circular
1054      * references in the conversion. 
1055      * @param routeNodeInstanceLoader a service that will provide routeNodeInstanceS based on their IDs.
1056      */
1057     public static ActionRequestValue from(ActionRequest actionRequest, 
1058             RouteNodeInstanceLoader routeNodeInstanceLoader) {
1059         return convertActionRequest(actionRequest, null, routeNodeInstanceLoader);
1060     }
1061 
1062     private static ActionRequestValue convertActionRequest(ActionRequest actionRequest, ActionRequestValue parentActionRequestBo,
1063             RouteNodeInstanceLoader routeNodeInstanceLoader) {
1064         if (actionRequest == null) {
1065             return null;
1066         }
1067         ActionRequestValue actionRequestBo = new ActionRequestFactory().createBlankActionRequest();
1068         populateActionRequest(actionRequestBo, actionRequest, routeNodeInstanceLoader);
1069         if (parentActionRequestBo != null) {
1070             actionRequestBo.setParentActionRequest(parentActionRequestBo);
1071             actionRequestBo.setParentActionRequestId(parentActionRequestBo.getActionRequestId());
1072         }
1073         if (actionRequest.getChildRequests() != null) {
1074             for (ActionRequest childRequest : actionRequest.getChildRequests()) {
1075                 actionRequestBo.getChildrenRequests().add(ActionRequestValue.convertActionRequest(childRequest, actionRequestBo, routeNodeInstanceLoader));
1076             }
1077         }
1078         return actionRequestBo;
1079     }
1080 
1081     /**
1082      * This method converts everything except for the parent and child requests
1083      */
1084     private static void populateActionRequest(ActionRequestValue actionRequestBo, ActionRequest actionRequest, 
1085             RouteNodeInstanceLoader routeNodeInstanceLoader) {
1086 
1087         actionRequestBo.setActionRequested(actionRequest.getActionRequested().getCode());
1088         if (!StringUtils.isBlank(actionRequest.getId())) {
1089             actionRequestBo.setActionRequestId(actionRequest.getId());
1090         }
1091         
1092         if (actionRequest.getActionTaken() != null) {
1093             // actionRequestBo.setActionTaken(ActionTakenValue.from(actionRequest.getActionTaken()));
1094             if (!StringUtils.isBlank(actionRequest.getActionTaken().getId())) {
1095                 actionRequestBo.setActionTakenId(actionRequest.getActionTaken().getId());
1096             }
1097         }
1098         actionRequestBo.setAnnotation(actionRequest.getAnnotation());
1099         if (actionRequest.getRequestPolicy() != null) {
1100             actionRequestBo.setApprovePolicy(actionRequest.getRequestPolicy().getCode());
1101         }
1102         actionRequestBo.setCreateDate(new Timestamp(actionRequest.getDateCreated().getMillis()));
1103         actionRequestBo.setCurrentIndicator(actionRequest.isCurrent());
1104         if (actionRequest.getDelegationType() != null) {
1105             actionRequestBo.setDelegationType(actionRequest.getDelegationType().getCode());
1106         }
1107         //actionRequestBo.setDocVersion(actionRequest.?);
1108         actionRequestBo.setForceAction(actionRequest.isForceAction());
1109         actionRequestBo.setPriority(actionRequest.getPriority());
1110         actionRequestBo.setRouteLevel(actionRequest.getRouteLevel());
1111         actionRequestBo.setQualifiedRoleName(actionRequest.getQualifiedRoleName());
1112         actionRequestBo.setQualifiedRoleNameLabel(actionRequest.getQualifiedRoleNameLabel());
1113         actionRequestBo.setRecipientTypeCd(actionRequest.getRecipientType().getCode());
1114         actionRequestBo.setResponsibilityDesc(actionRequest.getResponsibilityDescription());
1115         if (!StringUtils.isBlank(actionRequest.getResponsibilityId())) {
1116             actionRequestBo.setResponsibilityId(actionRequest.getResponsibilityId());
1117         }
1118         actionRequestBo.setRoleName(actionRequest.getRoleName());
1119         String documentId = actionRequest.getDocumentId();
1120         if (documentId != null) {
1121             actionRequestBo.setDocumentId(documentId);
1122             actionRequestBo.setRouteHeader(KEWServiceLocator.getRouteHeaderService().getRouteHeader(documentId));
1123         }
1124 
1125         actionRequestBo.setStatus(actionRequest.getStatus().getCode());
1126         actionRequestBo.setPrincipalId(actionRequest.getPrincipalId());
1127         actionRequestBo.setGroupId(actionRequest.getGroupId());
1128         
1129         if (routeNodeInstanceLoader != null && !StringUtils.isBlank(actionRequest.getRouteNodeInstanceId())) {
1130             actionRequestBo.setNodeInstance(routeNodeInstanceLoader.load(actionRequest.getRouteNodeInstanceId()));
1131         }
1132     }
1133     
1134 }