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