001/**
002 * Copyright 2005-2016 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.kew.actionrequest;
017
018import org.apache.commons.lang.StringUtils;
019import org.apache.commons.lang.builder.ToStringBuilder;
020import org.apache.commons.lang.builder.ToStringStyle;
021import org.hibernate.annotations.Fetch;
022import org.hibernate.annotations.FetchMode;
023import org.hibernate.annotations.GenericGenerator;
024import org.hibernate.annotations.Parameter;
025import org.joda.time.DateTime;
026import org.kuali.rice.core.api.delegation.DelegationType;
027import org.kuali.rice.core.api.util.RiceConstants;
028import org.kuali.rice.core.framework.persistence.jpa.OrmUtils;
029import org.kuali.rice.kew.actionitem.ActionItem;
030import org.kuali.rice.kew.actiontaken.ActionTakenValue;
031import org.kuali.rice.kew.api.action.ActionRequest;
032import org.kuali.rice.kew.api.action.ActionRequestPolicy;
033import org.kuali.rice.kew.api.action.ActionRequestStatus;
034import org.kuali.rice.kew.api.action.ActionRequestType;
035import org.kuali.rice.kew.api.action.ActionTaken;
036import org.kuali.rice.kew.api.action.RecipientType;
037import org.kuali.rice.kew.api.util.CodeTranslator;
038import org.kuali.rice.kew.dto.DTOConverter.RouteNodeInstanceLoader;
039import org.kuali.rice.kew.engine.CompatUtils;
040import org.kuali.rice.kew.engine.node.RouteNode;
041import org.kuali.rice.kew.engine.node.RouteNodeInstance;
042import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
043import org.kuali.rice.kew.rule.RuleBaseValues;
044import org.kuali.rice.kew.rule.service.RuleServiceInternal;
045import org.kuali.rice.kew.service.KEWServiceLocator;
046import org.kuali.rice.kew.user.RoleRecipient;
047import org.kuali.rice.kew.api.KewApiConstants;
048import org.kuali.rice.kim.api.group.Group;
049import org.kuali.rice.kim.api.identity.Person;
050import org.kuali.rice.kim.api.identity.principal.Principal;
051import org.kuali.rice.kim.api.services.KimApiServiceLocator;
052
053import javax.persistence.CascadeType;
054import javax.persistence.Column;
055import javax.persistence.Entity;
056import javax.persistence.FetchType;
057import javax.persistence.GeneratedValue;
058import javax.persistence.Id;
059import javax.persistence.JoinColumn;
060import javax.persistence.ManyToOne;
061import javax.persistence.NamedQueries;
062import javax.persistence.NamedQuery;
063import javax.persistence.OneToMany;
064import javax.persistence.Table;
065import javax.persistence.Transient;
066import java.io.Serializable;
067import java.sql.Timestamp;
068import java.util.ArrayList;
069import java.util.Arrays;
070import java.util.Iterator;
071import java.util.List;
072/**
073 * Bean mapped to DB. Represents ActionRequest to a workgroup, user or role.  Contains
074 * references to children/parent if a member of a graph
075 *
076 * @author Kuali Rice Team (rice.collab@kuali.org)
077 */
078@Entity
079@Table(name="KREW_ACTN_RQST_T")
080//@Sequence(name="KREW_ACTN_RQST_S", property="actionRequestId")
081@NamedQueries({
082  @NamedQuery(name="ActionRequestValue.FindByDocumentId", query="select arv from ActionRequestValue arv where arv.documentId = :documentId"),
083  @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"),
084  @NamedQuery(name="ActionRequestValue.FindActivatedByGroup", query="select count(arv) from ActionRequestValue arv where arv.groupId = :groupId and arv.currentIndicator = :currentIndicator and arv.status = :status"),
085  @NamedQuery(name="ActionRequestValue.FindAllByDocId", query="select arv from ActionRequestValue arv where arv.documentId = :documentId and arv.currentIndicator = :currentIndicator"),
086  @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)"),
087  @NamedQuery(name="ActionRequestValue.FindAllRootByDocId", query="select arv from ActionRequestValue arv where arv.documentId = :documentId and arv.currentIndicator = :currentIndicator and arv.parentActionRequest is null"),
088  @NamedQuery(name="ActionRequestValue.FindByStatusAndDocId", query="select arv from ActionRequestValue arv where arv.documentId = :documentId and arv.currentIndicator = :currentIndicator and arv.status = :status"),
089  @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)"),
090  @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"),
091  @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"),
092  @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"),
093  @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)"),
094  @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)"),
095  @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"),
096  @NamedQuery(name="ActionRequestValue.GetRequestGroupIds", query="select arv.groupId from ActionRequestValue arv where arv.documentId = :documentId and arv.currentIndicator = :currentIndicator and arv.recipientTypeCd = :recipientTypeCd"),
097  @NamedQuery(name="ActionRequestValue.FindByStatusAndGroupId", query="select arv from ActionRequestValue arv where arv.groupId = :groupId and arv.currentIndicator = :currentIndicator and arv.status = :status")
098})
099public 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 List DELEGATION_TYPE_RANK = Arrays.asList(new Object[]{DelegationType.SECONDARY, DelegationType.PRIMARY, null});
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 delegationTypeCode;
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 == KewApiConstants.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            Person person = getPerson();
255            if ( person != null ) {
256                return person.getName();
257            }
258        } else if (isGroupRequest()) {
259            Group group = getGroup();
260            if ( group != null ) {
261                    return group.getName();
262            } else {
263                return getGroupId();
264            }
265        } else if (isRoleRequest()) {
266                return getRoleName();
267        }
268        return "";
269    }
270
271    public Recipient getRecipient() {
272        if (getPrincipalId() != null) {
273            return new KimPrincipalRecipient(getPrincipal());
274        } else if (getGroupId() != null){
275            return new KimGroupRecipient(getGroup());
276        } else {
277                return new RoleRecipient(this.getRoleName());
278        }
279    }
280
281    public boolean isPending() {
282        return ActionRequestStatus.INITIALIZED.getCode().equals(getStatus()) || ActionRequestStatus.ACTIVATED.getCode().equals(getStatus());
283    }
284
285    public String getStatusLabel() {
286        return CodeTranslator.getActionRequestStatusLabel(getStatus());
287    }
288
289    public String getActionRequestedLabel() {
290        if (StringUtils.isNotBlank(getRequestLabel())) {
291                return getRequestLabel();
292        }
293        return CodeTranslator.getActionRequestLabel(getActionRequested());
294    }
295
296    /**
297     * @return Returns the actionTaken.
298     */
299    public ActionTakenValue getActionTaken() {
300        return actionTaken;
301    }
302
303    /**
304     * @param actionTaken
305     *            The actionTaken to set.
306     */
307    public void setActionTaken(ActionTakenValue actionTaken) {
308        this.actionTaken = actionTaken;
309    }
310
311    /**
312     * @return Returns the actionRequested.
313     */
314    public String getActionRequested() {
315        return actionRequested;
316    }
317
318    /**
319     * @param actionRequested
320     *            The actionRequested to set.
321     */
322    public void setActionRequested(String actionRequested) {
323        this.actionRequested = actionRequested;
324    }
325
326    /**
327     * @return Returns the actionRequestId.
328     */
329    public String getActionRequestId() {
330        return actionRequestId;
331    }
332
333    /**
334     * @param actionRequestId
335     *            The actionRequestId to set.
336     */
337    public void setActionRequestId(String actionRequestId) {
338        this.actionRequestId = actionRequestId;
339    }
340
341    /**
342     * @return Returns the actionTakenId.
343     */
344    public String getActionTakenId() {
345        return actionTakenId;
346    }
347
348    /**
349     * @param actionTakenId
350     *            The actionTakenId to set.
351     */
352    public void setActionTakenId(String actionTakenId) {
353        this.actionTakenId = actionTakenId;
354    }
355
356    /**
357     * @return Returns the annotation.
358     */
359    public String getAnnotation() {
360        return annotation;
361    }
362
363    /**
364     * @param annotation
365     *            The annotation to set.
366     */
367    public void setAnnotation(String annotation) {
368        this.annotation = annotation;
369    }
370
371    /**
372     * @return Returns the createDate.
373     */
374    public java.sql.Timestamp getCreateDate() {
375        return createDate;
376    }
377
378    /**
379     * @param createDate
380     *            The createDate to set.
381     */
382    public void setCreateDate(java.sql.Timestamp createDate) {
383        this.createDate = createDate;
384    }
385
386    /**
387     * @return Returns the docVersion.
388     */
389    public Integer getDocVersion() {
390        return docVersion;
391    }
392
393    /**
394     * @param docVersion
395     *            The docVersion to set.
396     */
397    public void setDocVersion(Integer docVersion) {
398        this.docVersion = docVersion;
399    }
400
401    public String getPrincipalId() {
402        return principalId;
403    }
404
405    public void setPrincipalId(String principalId) {
406        this.principalId = principalId;
407    }
408    
409    /**
410     * @return Returns the forceAction.
411     */
412    public Boolean getForceAction() {
413        return forceAction;
414    }
415
416    /**
417     * @param forceAction
418     *            The forceAction to set.
419     */
420    public void setForceAction(Boolean forceAction) {
421        this.forceAction = forceAction;
422    }
423
424    /**
425     * @return Returns the jrfVerNbr.
426     */
427    public Integer getJrfVerNbr() {
428        return jrfVerNbr;
429    }
430
431    /**
432     * @param jrfVerNbr
433     *            The jrfVerNbr to set.
434     */
435    public void setJrfVerNbr(Integer jrfVerNbr) {
436        this.jrfVerNbr = jrfVerNbr;
437    }
438
439    /**
440     * @return Returns the priority.
441     */
442    public Integer getPriority() {
443        return priority;
444    }
445
446    /**
447     * @param priority
448     *            The priority to set.
449     */
450    public void setPriority(Integer priority) {
451        this.priority = priority;
452    }
453
454    /**
455     * @return Returns the recipientTypeCd.
456     */
457    public String getRecipientTypeCd() {
458        return recipientTypeCd;
459    }
460
461    /**
462     * @param recipientTypeCd
463     *            The recipientTypeCd to set.
464     */
465    public void setRecipientTypeCd(String recipientTypeCd) {
466        this.recipientTypeCd = recipientTypeCd;
467    }
468
469    /**
470     * @return Returns the responsibilityDesc.
471     */
472    public String getResponsibilityDesc() {
473        return responsibilityDesc;
474    }
475
476    /**
477     * @param responsibilityDesc
478     *            The responsibilityDesc to set.
479     */
480    public void setResponsibilityDesc(String responsibilityDesc) {
481        this.responsibilityDesc = responsibilityDesc;
482    }
483
484    /**
485     * @return Returns the responsibilityId.
486     */
487    public String getResponsibilityId() {
488        return responsibilityId;
489    }
490
491    /**
492     * @param responsibilityId
493     *            The responsibilityId to set.
494     */
495    public void setResponsibilityId(String responsibilityId) {
496        this.responsibilityId = responsibilityId;
497    }
498
499    /**
500     * @return Returns the documentId.
501     */
502    public String getDocumentId() {
503        return documentId;
504    }
505
506    public void setDocumentId(String documentId) {
507        this.documentId = documentId;
508    }
509
510    public Integer getRouteLevel() {
511        return routeLevel;
512    }
513
514    public void setRouteLevel(Integer routeLevel) {
515        this.routeLevel = routeLevel;
516    }
517
518    public String getStatus() {
519        return status;
520    }
521
522    public void setStatus(String status) {
523        this.status = status;
524    }
525
526    public String getGroupId() {
527        return groupId;
528    }
529
530    public void setGroupId(String groupId) {
531        this.groupId = groupId;
532    }
533
534    public boolean isInitialized() {
535        return ActionRequestStatus.INITIALIZED.getCode().equals(getStatus());
536    }
537
538    public boolean isActive() {
539        return ActionRequestStatus.ACTIVATED.getCode().equals(getStatus());
540    }
541
542    public boolean isApproveOrCompleteRequest() {
543        return KewApiConstants.ACTION_REQUEST_APPROVE_REQ.equals(getActionRequested()) || KewApiConstants.ACTION_REQUEST_COMPLETE_REQ.equals(getActionRequested());
544    }
545
546    public boolean isDone() {
547        return ActionRequestStatus.DONE.getCode().equals(getStatus());
548    }
549
550    public boolean isReviewerUser() {
551        return RecipientType.PRINCIPAL.getCode().equals(getRecipientTypeCd());
552    }
553
554    /**
555     * Determines whether the specified principalId is in the recipient graph of this action request
556     * @param principalId the principal id to check
557     * @return whether the specified principalId is in the recipient graph of this action request
558     */
559    public boolean isRecipientRoutedRequest(String principalId) {
560        //before altering this method it is used in checkRouteLogAuthentication
561        //don't break that method
562        if (principalId == null || "".equals(principalId)) {
563                return false;
564        }
565
566        boolean isRecipientInGraph = false;
567        if (isReviewerUser()) {
568                        isRecipientInGraph = getPrincipalId().equals(principalId);
569        } else if (isGroupRequest()) {
570                Group group = getGroup();
571                        if (group == null){
572                                LOG.error("Was unable to retrieve workgroup " + getGroupId());
573                        }
574                isRecipientInGraph = KimApiServiceLocator.getGroupService().isMemberOfGroup(principalId, group.getId());
575        }
576
577
578        for (ActionRequestValue childRequest : getChildrenRequests())
579        {
580            isRecipientInGraph = isRecipientInGraph || childRequest.isRecipientRoutedRequest(principalId);
581        }
582
583        return isRecipientInGraph;
584    }
585
586    public boolean isRecipientRoutedRequest(Recipient recipient) {
587        //before altering this method it is used in checkRouteLogAuthentication
588        //don't break that method
589        if (recipient == null) {
590                return false;
591        }
592
593        boolean isRecipientInGraph = false;
594        if (isReviewerUser()) {
595                if (recipient instanceof KimPrincipalRecipient) {
596                        isRecipientInGraph = getPrincipalId().equals(((KimPrincipalRecipient) recipient).getPrincipalId());
597                } else if (recipient instanceof KimGroupRecipient){
598                        isRecipientInGraph = KimApiServiceLocator.getGroupService().isMemberOfGroup(getPrincipalId(), ((KimGroupRecipient)recipient).getGroup().getId());
599                }
600
601        } else if (isGroupRequest()) {
602                Group group = getGroup();
603                        if (group == null){
604                                LOG.error("Was unable to retrieve workgroup " + getGroupId());
605                        }
606                if (recipient instanceof KimPrincipalRecipient) {
607                        KimPrincipalRecipient principalRecipient = (KimPrincipalRecipient)recipient;
608                        isRecipientInGraph = KimApiServiceLocator.getGroupService().isMemberOfGroup(principalRecipient.getPrincipalId(), group.getId());
609                } else if (recipient instanceof KimGroupRecipient) {
610                        isRecipientInGraph = ((KimGroupRecipient) recipient).getGroup().getId().equals(group.getId());
611                }
612        }
613
614
615        for (ActionRequestValue childRequest : getChildrenRequests())
616        {
617            isRecipientInGraph = isRecipientInGraph || childRequest.isRecipientRoutedRequest(recipient);
618        }
619
620        return isRecipientInGraph;
621    }
622
623    public boolean isGroupRequest(){
624        return RecipientType.GROUP.getCode().equals(getRecipientTypeCd());
625    }
626
627    public boolean isRoleRequest() {
628        return RecipientType.ROLE.getCode().equals(getRecipientTypeCd());
629    }
630
631    public boolean isAcknowledgeRequest() {
632        return KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ.equals(getActionRequested());
633    }
634
635    public boolean isApproveRequest() {
636        return KewApiConstants.ACTION_REQUEST_APPROVE_REQ.equals(getActionRequested());
637    }
638
639    public boolean isCompleteRequst() {
640        return KewApiConstants.ACTION_REQUEST_COMPLETE_REQ.equals(getActionRequested());
641    }
642
643    public boolean isFYIRequest() {
644        return KewApiConstants.ACTION_REQUEST_FYI_REQ.equals(getActionRequested());
645    }
646
647    /**
648     * 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)
649     *
650     * @param code1
651     * @param code2
652     * @param completeAndApproveTheSame
653     * @return -1 if less than, 0 if equal, 1 if greater than
654     */
655    public static int compareActionCode(String code1, String code2, boolean completeAndApproveTheSame) {
656        int cutoff = Integer.MAX_VALUE;
657        if (completeAndApproveTheSame) {
658                // hacked so that APPROVE and COMPLETE are equal
659                cutoff = ACTION_CODE_RANK.length() - 3;
660        }
661        Integer code1Index = Math.min(ACTION_CODE_RANK.indexOf(code1), cutoff);
662        Integer code2Index = Math.min(ACTION_CODE_RANK.indexOf(code2), cutoff);
663        return code1Index.compareTo(code2Index);
664    }
665
666    /**
667     * 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
668     *
669     * @param type1
670     * @param type2
671     * @return -1 if less than, 0 if equal, 1 if greater than
672     */
673    public static int compareRecipientType(String type1, String type2) {
674        Integer type1Index = RECIPIENT_TYPE_RANK.indexOf(type1);
675        Integer type2Index = RECIPIENT_TYPE_RANK.indexOf(type2);
676        return type1Index.compareTo(type2Index);
677    }
678
679    public static int compareDelegationType(DelegationType type1, DelegationType type2) {
680        Integer type1Index = DELEGATION_TYPE_RANK.indexOf(type1);
681        Integer type2Index = DELEGATION_TYPE_RANK.indexOf(type2);
682        return type1Index.compareTo(type2Index);
683    }
684
685    public List<ActionItem> getActionItems() {
686        if (this.simulatedActionItems == null || this.simulatedActionItems.isEmpty()) {
687                return (List<ActionItem>) KEWServiceLocator.getActionListService().findByActionRequestId(actionRequestId);
688        } else {
689                return this.simulatedActionItems;
690        }
691    }
692
693    public List<ActionItem> getSimulatedActionItems() {
694        if (this.simulatedActionItems == null) {
695                this.simulatedActionItems = new ArrayList<ActionItem>();
696        }
697                return this.simulatedActionItems;
698        }
699
700        public void setSimulatedActionItems(List<ActionItem> simulatedActionItems) {
701                this.simulatedActionItems = simulatedActionItems;
702        }
703
704        public Boolean getCurrentIndicator() {
705        return currentIndicator;
706    }
707
708    public void setCurrentIndicator(Boolean currentIndicator) {
709        this.currentIndicator = currentIndicator;
710    }
711
712    public String getParentActionRequestId() {
713        return parentActionRequestId;
714    }
715
716    public void setParentActionRequestId(String parentActionRequestId) {
717        this.parentActionRequestId = parentActionRequestId;
718    }
719
720    public ActionRequestValue getParentActionRequest() {
721        return parentActionRequest;
722    }
723
724    public void setParentActionRequest(ActionRequestValue parentActionRequest) {
725        this.parentActionRequest = parentActionRequest;
726    }
727
728    public List<ActionRequestValue> getChildrenRequests() {
729        return childrenRequests;
730    }
731
732    public void setChildrenRequests(List<ActionRequestValue> childrenRequests) {
733        this.childrenRequests = childrenRequests;
734    }
735
736    public String getQualifiedRoleName() {
737        return qualifiedRoleName;
738    }
739
740    public void setQualifiedRoleName(String roleName) {
741        this.qualifiedRoleName = roleName;
742    }
743
744    public DelegationType getDelegationType() {
745        return DelegationType.fromCode(delegationTypeCode);
746    }
747
748    public void setDelegationType(DelegationType delegationPolicy) {
749        this.delegationTypeCode = delegationPolicy == null ? null : delegationPolicy.getCode();
750    }
751
752
753    public String getDelegationTypeCode() {
754        return delegationTypeCode;
755    }
756
757    public void setDelegationTypeCode(String delegationTypeCode) {
758        this.delegationTypeCode = delegationTypeCode;
759    }
760
761    public String getRoleName() {
762        return roleName;
763    }
764
765    public void setRoleName(String roleName) {
766        this.roleName = roleName;
767    }
768
769    public String getApprovePolicy() {
770        return approvePolicy;
771    }
772
773    public void setApprovePolicy(String requestType) {
774        this.approvePolicy = requestType;
775    }
776
777    public boolean getHasApprovePolicy() {
778        return getApprovePolicy() != null;
779    }
780
781    public boolean isDeactivated() {
782        return ActionRequestStatus.DONE.getCode().equals(getStatus());
783    }
784
785    public boolean hasParent() {
786        return getParentActionRequest() != null;
787    }
788
789    public boolean hasChild(ActionRequestValue actionRequest) {
790        if (actionRequest == null)
791            return false;
792        String actionRequestId = actionRequest.getActionRequestId();
793        for (Iterator<ActionRequestValue> iter = getChildrenRequests().iterator(); iter.hasNext();) {
794            ActionRequestValue childRequest = iter.next();
795            if (childRequest.equals(actionRequest) || (actionRequestId != null && actionRequestId.equals(childRequest.getActionRequestId()))) {
796                return true;
797            }
798        }
799        return false;
800    }
801
802    public String getDisplayStatus() {
803        return displayStatus;
804    }
805
806    public void setDisplayStatus(String displayStatus) {
807        this.displayStatus = displayStatus;
808    }
809
810    public String getQualifiedRoleNameLabel() {
811        return qualifiedRoleNameLabel;
812    }
813
814    public void setQualifiedRoleNameLabel(String qualifiedRoleNameLabel) {
815        this.qualifiedRoleNameLabel = qualifiedRoleNameLabel;
816    }
817
818    public String getCreateDateString() {
819        if (createDateString == null || createDateString.trim().equals("")) {
820            return RiceConstants.getDefaultDateFormat().format(getCreateDate());
821        } else {
822            return createDateString;
823        }
824    }
825
826    public void setCreateDateString(String createDateString) {
827        this.createDateString = createDateString;
828    }
829
830    public RouteNodeInstance getNodeInstance() {
831                return nodeInstance;
832        }
833
834    public String getPotentialNodeName() {
835        return (getNodeInstance() == null ? "" : getNodeInstance().getName());
836    }
837
838        public void setNodeInstance(RouteNodeInstance nodeInstance) {
839                this.nodeInstance = nodeInstance;
840        }
841
842        public String getRecipientTypeLabel() {
843                return RecipientType.fromCode(getRecipientTypeCd()).getLabel();
844    }
845
846    public RuleBaseValues getRuleBaseValues(){
847        if(ruleBaseValuesId != null){
848            return getRuleService().findRuleBaseValuesById(ruleBaseValuesId);
849        }
850        return null;
851    }
852    public String getRuleBaseValuesId() {
853        return ruleBaseValuesId;
854    }
855
856    public void setRuleBaseValuesId(String ruleBaseValuesId) {
857        this.ruleBaseValuesId = ruleBaseValuesId;
858    }
859    
860        private RuleServiceInternal getRuleService() {
861        return (RuleServiceInternal) KEWServiceLocator.getService(KEWServiceLocator.RULE_SERVICE);
862    }
863
864    public boolean isPrimaryDelegator() {
865        boolean primaryDelegator = false;
866        for (Iterator<ActionRequestValue> iter = childrenRequests.iterator(); iter.hasNext();) {
867            ActionRequestValue childRequest = iter.next();
868            primaryDelegator = DelegationType.PRIMARY.equals(childRequest.getDelegationType()) || primaryDelegator;
869        }
870        return primaryDelegator;
871    }
872
873    /**
874     * Used to get primary delegate names on route log in the 'Requested Of' section so primary delegate requests
875     * list the delegate and not the delegator as having the request 'IN ACTION LIST'.  This method doesn't recurse
876     * and therefore assume an AR structure.
877     *
878     * @return primary delgate requests
879     */
880    public List<ActionRequestValue> getPrimaryDelegateRequests() {
881        List<ActionRequestValue> primaryDelegateRequests = new ArrayList<ActionRequestValue>();
882        for (ActionRequestValue childRequest : childrenRequests)
883        {
884            if (DelegationType.PRIMARY.equals(childRequest.getDelegationType()))
885            {
886                if (childRequest.isRoleRequest())
887                {
888                    for (ActionRequestValue actionRequestValue : childRequest.getChildrenRequests())
889                    {
890                        primaryDelegateRequests.add(actionRequestValue);
891                    }
892                } else
893                {
894                        primaryDelegateRequests.add(childRequest);
895                }
896            }
897        }
898        return primaryDelegateRequests;
899    }
900
901    public boolean isAdHocRequest() {                                          
902        return KewApiConstants.ADHOC_REQUEST_RESPONSIBILITY_ID.equals(getResponsibilityId());
903    }
904
905    public boolean isGeneratedRequest() {
906        return KewApiConstants.MACHINE_GENERATED_RESPONSIBILITY_ID.equals(getResponsibilityId());
907    }
908
909    public boolean isExceptionRequest() {
910        return KewApiConstants.EXCEPTION_REQUEST_RESPONSIBILITY_ID.equals(getResponsibilityId());
911    }
912
913    public boolean isRouteModuleRequest() {
914        // FIXME: KULRICE-5201 switched rsp_id to a varchar, so the comparison below is no longer valid
915//      return getResponsibilityId() > 0;
916        // TODO: KULRICE-5329 Verify that this code below makes sense 
917        return getResponsibilityId() != null && !KewApiConstants.SPECIAL_RESPONSIBILITY_ID_SET.contains(getResponsibilityId());
918    }
919
920    public String toString() {
921        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
922            .append("actionRequestId", actionRequestId)
923            .append("actionRequested", actionRequested)
924            .append("documentId", documentId)
925            .append("status", status)
926            .append("responsibilityId", responsibilityId)
927            .append("groupId", groupId)
928            .append("recipientTypeCd", recipientTypeCd)
929            .append("priority", priority)
930            .append("routeLevel", routeLevel)
931            .append("actionTakenId", actionTakenId)
932            .append("docVersion", docVersion)
933            .append("createDate", createDate)
934            .append("responsibilityDesc", responsibilityDesc)
935            .append("annotation", annotation)
936            .append("jrfVerNbr", jrfVerNbr)
937            .append("principalId", principalId)
938            .append("forceAction", forceAction)
939            .append("parentActionRequestId", parentActionRequestId)
940            .append("qualifiedRoleName", qualifiedRoleName)
941            .append("roleName", roleName)
942            .append("qualifiedRoleNameLabel", qualifiedRoleNameLabel)
943            .append("displayStatus", displayStatus)
944            .append("ruleBaseValuesId", ruleBaseValuesId)
945            .append("delegationType", delegationTypeCode)
946            .append("approvePolicy", approvePolicy)
947            .append("actionTaken", actionTaken)
948            .append("currentIndicator", currentIndicator)
949            .append("createDateString", createDateString)
950            .append("nodeInstance", nodeInstance).toString();
951    }
952
953        public String getRequestLabel() {
954                return this.requestLabel;
955        }
956
957        public void setRequestLabel(String requestLabel) {
958                this.requestLabel = requestLabel;
959        }
960
961    public String getGroupName() {
962        return KimApiServiceLocator.getGroupService().getGroup(this.groupId).getName();
963    }
964
965        /**
966         * @return the resolveResponsibility
967         */
968        public boolean getResolveResponsibility() {
969                return this.resolveResponsibility;
970        }
971
972        /**
973         * @param resolveResponsibility the resolveResponsibility to set
974         */
975        public void setResolveResponsibility(boolean resolveResponsibility) {
976                this.resolveResponsibility = resolveResponsibility;
977        }
978
979        public DocumentRouteHeaderValue getRouteHeader() {
980                if (this.routeHeader == null && this.documentId != null) {
981                        this.routeHeader = KEWServiceLocator.getRouteHeaderService().getRouteHeader(this.documentId);
982                }
983                return this.routeHeader;
984        }
985
986        public void setRouteHeader(DocumentRouteHeaderValue routeHeader) {
987                this.routeHeader = routeHeader;
988        }
989        
990        public static ActionRequest to(ActionRequestValue actionRequestBo) {
991                if (actionRequestBo == null) {
992                        return null;
993                }
994                return createActionRequestBuilder(actionRequestBo).build();
995        }
996        
997        private static ActionRequest.Builder createActionRequestBuilder(ActionRequestValue actionRequestBo) {
998                ActionRequest.Builder builder = ActionRequest.Builder.create(actionRequestBo.getActionRequestId(),
999                                ActionRequestType.fromCode(actionRequestBo.getActionRequested()),
1000                                ActionRequestStatus.fromCode(actionRequestBo.getStatus()),
1001                                actionRequestBo.getResponsibilityId(),
1002                                actionRequestBo.getDocumentId(),
1003                                RecipientType.fromCode(actionRequestBo.getRecipientTypeCd()));
1004                if (actionRequestBo.getActionTaken() != null) {
1005                        builder.setActionTaken(ActionTaken.Builder.create(ActionTakenValue.to(actionRequestBo.getActionTaken())));
1006                }
1007                builder.setAnnotation(actionRequestBo.getAnnotation());
1008                builder.setCurrent(actionRequestBo.getCurrentIndicator().booleanValue());
1009                builder.setDateCreated(new DateTime(actionRequestBo.getCreateDate().getTime()));
1010                if (actionRequestBo.getDelegationType() != null) {
1011                        builder.setDelegationType(actionRequestBo.getDelegationType());
1012                }
1013                builder.setForceAction(actionRequestBo.getForceAction().booleanValue());
1014                builder.setGroupId(actionRequestBo.getGroupId());
1015                builder.setNodeName(actionRequestBo.getPotentialNodeName());
1016                if (actionRequestBo.getParentActionRequestId() != null) {
1017                        builder.setParentActionRequestId(actionRequestBo.getParentActionRequestId());
1018                }
1019                builder.setPrincipalId(actionRequestBo.getPrincipalId());
1020                if (actionRequestBo.getPriority() == null) {
1021                        builder.setPriority(KewApiConstants.ACTION_REQUEST_DEFAULT_PRIORITY);
1022                } else {
1023            builder.setPriority(actionRequestBo.getPriority().intValue());
1024        }
1025        if (actionRequestBo.getRouteLevel() == null ) {
1026            builder.setRouteLevel(0);
1027        } else {
1028            builder.setRouteLevel(actionRequestBo.getRouteLevel().intValue());
1029        }
1030                builder.setQualifiedRoleName(actionRequestBo.getQualifiedRoleName());
1031                builder.setQualifiedRoleNameLabel(actionRequestBo.getQualifiedRoleNameLabel());
1032                builder.setRequestLabel(actionRequestBo.getRequestLabel());
1033                if (!StringUtils.isBlank(actionRequestBo.getApprovePolicy())) {
1034                        builder.setRequestPolicy(ActionRequestPolicy.fromCode(actionRequestBo.getApprovePolicy()));
1035                }
1036                builder.setResponsibilityDescription(actionRequestBo.getResponsibilityDesc());
1037                builder.setRoleName(actionRequestBo.getRoleName());
1038                if (actionRequestBo.getNodeInstance() != null) {
1039                        builder.setRouteNodeInstanceId(actionRequestBo.getNodeInstance().getRouteNodeInstanceId());
1040                }
1041                
1042                List<ActionRequest.Builder> childRequests = new ArrayList<ActionRequest.Builder>();
1043                if (actionRequestBo.getChildrenRequests() != null) {
1044                        for (ActionRequestValue childActionRequestBo : actionRequestBo.getChildrenRequests()) {
1045                                childRequests.add(createActionRequestBuilder(childActionRequestBo));
1046                        }
1047                }
1048                builder.setChildRequests(childRequests);
1049                return builder;
1050        }
1051        
1052    /**
1053     * TODO - this javadoc copied from DTOConverter, needs to be updated!
1054     * 
1055     * Converts an ActionRequestVO to an ActionRequest. The ActionRequestDTO passed in must be the root action request in the
1056     * graph, otherwise an IllegalArgumentException is thrown. This is to avoid potentially sticky issues with circular
1057     * references in the conversion. NOTE: This method's primary purpose is to convert ActionRequestVOs returned from a
1058     * RouteModule. Incidentally, the DTO's returned from the route module will be lacking some information (like the node
1059     * instance) so no attempts are made to convert this data since further initialization is handled by a higher level
1060     * component (namely ActionRequestService.initializeActionRequestGraph).
1061     */
1062    public static ActionRequestValue from(ActionRequest actionRequest) {
1063        return ActionRequestValue.from(actionRequest, null);
1064    }
1065    
1066    /**
1067     * Converts an ActionRequestVO to an ActionRequest. The ActionRequestDTO passed in must be the root action request in the
1068     * graph, otherwise an IllegalArgumentException is thrown. This is to avoid potentially sticky issues with circular
1069     * references in the conversion. 
1070     * @param routeNodeInstanceLoader a service that will provide routeNodeInstanceS based on their IDs.
1071     */
1072    public static ActionRequestValue from(ActionRequest actionRequest, 
1073            RouteNodeInstanceLoader routeNodeInstanceLoader) {
1074        return convertActionRequest(actionRequest, null, routeNodeInstanceLoader);
1075    }
1076
1077    private static ActionRequestValue convertActionRequest(ActionRequest actionRequest, ActionRequestValue parentActionRequestBo,
1078            RouteNodeInstanceLoader routeNodeInstanceLoader) {
1079        if (actionRequest == null) {
1080            return null;
1081        }
1082        ActionRequestValue actionRequestBo = new ActionRequestFactory().createBlankActionRequest();
1083        populateActionRequest(actionRequestBo, actionRequest, routeNodeInstanceLoader);
1084        if (parentActionRequestBo != null) {
1085            actionRequestBo.setParentActionRequest(parentActionRequestBo);
1086            actionRequestBo.setParentActionRequestId(parentActionRequestBo.getActionRequestId());
1087        }
1088        if (actionRequest.getChildRequests() != null) {
1089            for (ActionRequest childRequest : actionRequest.getChildRequests()) {
1090                actionRequestBo.getChildrenRequests().add(ActionRequestValue.convertActionRequest(childRequest, actionRequestBo, routeNodeInstanceLoader));
1091            }
1092        }
1093        return actionRequestBo;
1094    }
1095
1096    /**
1097     * This method converts everything except for the parent and child requests
1098     */
1099    private static void populateActionRequest(ActionRequestValue actionRequestBo, ActionRequest actionRequest, 
1100            RouteNodeInstanceLoader routeNodeInstanceLoader) {
1101
1102        actionRequestBo.setActionRequested(actionRequest.getActionRequested().getCode());
1103        if (!StringUtils.isBlank(actionRequest.getId())) {
1104            actionRequestBo.setActionRequestId(actionRequest.getId());
1105        }
1106        
1107        if (actionRequest.getActionTaken() != null) {
1108            // actionRequestBo.setActionTaken(ActionTakenValue.from(actionRequest.getActionTaken()));
1109            if (!StringUtils.isBlank(actionRequest.getActionTaken().getId())) {
1110                actionRequestBo.setActionTakenId(actionRequest.getActionTaken().getId());
1111            }
1112        }
1113        actionRequestBo.setAnnotation(actionRequest.getAnnotation());
1114        if (actionRequest.getRequestPolicy() != null) {
1115            actionRequestBo.setApprovePolicy(actionRequest.getRequestPolicy().getCode());
1116        }
1117        actionRequestBo.setCreateDate(new Timestamp(actionRequest.getDateCreated().getMillis()));
1118        actionRequestBo.setCurrentIndicator(actionRequest.isCurrent());
1119        if (actionRequest.getDelegationType() != null) {
1120            actionRequestBo.setDelegationType(actionRequest.getDelegationType());
1121        }
1122        //actionRequestBo.setDocVersion(actionRequest.?);
1123        actionRequestBo.setForceAction(actionRequest.isForceAction());
1124        actionRequestBo.setPriority(actionRequest.getPriority());
1125        actionRequestBo.setRouteLevel(actionRequest.getRouteLevel());
1126        actionRequestBo.setQualifiedRoleName(actionRequest.getQualifiedRoleName());
1127        actionRequestBo.setQualifiedRoleNameLabel(actionRequest.getQualifiedRoleNameLabel());
1128        actionRequestBo.setRecipientTypeCd(actionRequest.getRecipientType().getCode());
1129        actionRequestBo.setResponsibilityDesc(actionRequest.getResponsibilityDescription());
1130        if (!StringUtils.isBlank(actionRequest.getResponsibilityId())) {
1131            actionRequestBo.setResponsibilityId(actionRequest.getResponsibilityId());
1132        }
1133        actionRequestBo.setRoleName(actionRequest.getRoleName());
1134        String documentId = actionRequest.getDocumentId();
1135        if (documentId != null) {
1136            actionRequestBo.setDocumentId(documentId);
1137            actionRequestBo.setRouteHeader(KEWServiceLocator.getRouteHeaderService().getRouteHeader(documentId));
1138        }
1139
1140        actionRequestBo.setStatus(actionRequest.getStatus().getCode());
1141        actionRequestBo.setPrincipalId(actionRequest.getPrincipalId());
1142        actionRequestBo.setGroupId(actionRequest.getGroupId());
1143        
1144        if (routeNodeInstanceLoader != null && !StringUtils.isBlank(actionRequest.getRouteNodeInstanceId())) {
1145            actionRequestBo.setNodeInstance(routeNodeInstanceLoader.load(actionRequest.getRouteNodeInstanceId()));
1146        }
1147    }
1148    
1149}