Coverage Report - org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue
 
Classes in this File Line Coverage Branch Coverage Complexity
DocumentRouteHeaderValue
0%
0/346
0%
0/118
1.726
 
 1  
 /*
 2  
  * Copyright 2005-2007 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.routeheader;
 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.apache.log4j.Logger;
 22  
 import org.hibernate.annotations.Fetch;
 23  
 import org.hibernate.annotations.FetchMode;
 24  
 import org.kuali.rice.core.jpa.annotations.Sequence;
 25  
 import org.kuali.rice.kew.actionitem.ActionItem;
 26  
 import org.kuali.rice.kew.actionlist.CustomActionListAttribute;
 27  
 import org.kuali.rice.kew.actionlist.DefaultCustomActionListAttribute;
 28  
 import org.kuali.rice.kew.actionrequest.ActionRequestFactory;
 29  
 import org.kuali.rice.kew.actionrequest.ActionRequestValue;
 30  
 import org.kuali.rice.kew.actiontaken.ActionTakenValue;
 31  
 import org.kuali.rice.kew.bo.KewPersistableBusinessObjectBase;
 32  
 import org.kuali.rice.kew.docsearch.SearchableAttributeValue;
 33  
 import org.kuali.rice.kew.doctype.ApplicationDocumentStatus;
 34  
 import org.kuali.rice.kew.doctype.DocumentTypePolicy;
 35  
 import org.kuali.rice.kew.doctype.bo.DocumentType;
 36  
 import org.kuali.rice.kew.dto.DTOConverter;
 37  
 import org.kuali.rice.kew.dto.KeyValueDTO;
 38  
 import org.kuali.rice.kew.dto.RouteHeaderDTO;
 39  
 import org.kuali.rice.kew.engine.CompatUtils;
 40  
 import org.kuali.rice.kew.engine.node.Branch;
 41  
 import org.kuali.rice.kew.engine.node.BranchState;
 42  
 import org.kuali.rice.kew.engine.node.RouteNode;
 43  
 import org.kuali.rice.kew.engine.node.RouteNodeInstance;
 44  
 import org.kuali.rice.kew.exception.InvalidActionTakenException;
 45  
 import org.kuali.rice.kew.exception.ResourceUnavailableException;
 46  
 import org.kuali.rice.kew.exception.WorkflowException;
 47  
 import org.kuali.rice.kew.exception.WorkflowRuntimeException;
 48  
 import org.kuali.rice.kew.mail.CustomEmailAttribute;
 49  
 import org.kuali.rice.kew.mail.CustomEmailAttributeImpl;
 50  
 import org.kuali.rice.kew.notes.CustomNoteAttribute;
 51  
 import org.kuali.rice.kew.notes.CustomNoteAttributeImpl;
 52  
 import org.kuali.rice.kew.notes.Note;
 53  
 import org.kuali.rice.kew.service.KEWServiceLocator;
 54  
 import org.kuali.rice.kew.util.CodeTranslator;
 55  
 import org.kuali.rice.kew.util.KEWConstants;
 56  
 import org.kuali.rice.kew.util.Utilities;
 57  
 import org.kuali.rice.kim.bo.entity.KimPrincipal;
 58  
 
 59  
 import javax.persistence.*;
 60  
 import java.sql.Timestamp;
 61  
 import java.util.*;
 62  
 
 63  
 
 64  
 
 65  
 /**
 66  
  * A document within KEW.  A document effectively represents a process that moves through
 67  
  * the workflow engine.  It is created from a particular {@link DocumentType} and follows
 68  
  * the route path defined by that DocumentType.
 69  
  *
 70  
  * <p>During a document's lifecycle it progresses through a series of statuses, starting
 71  
  * with INITIATED and moving to one of the terminal states (such as FINAL, CANCELED, etc).
 72  
  * The list of status on a document are defined in the {@link KEWConstants} class and
 73  
  * include the constants starting with "ROUTE_HEADER_" and ending with "_CD".
 74  
  *
 75  
  * <p>Associated with the document is the document content.  The document content is XML
 76  
  * which represents the content of that document.  This XML content is typically used
 77  
  * to make routing decisions for the document.
 78  
  *
 79  
  * <p>A document has associated with it a set of {@link ActionRequestValue} object and
 80  
  * {@link ActionTakenValue} objects.  Action Requests represent requests for user
 81  
  * action (such as Approve, Acknowledge, etc).  Action Takens represent action that
 82  
  * users have performed on the document, such as approvals or cancelling of the document.
 83  
  *
 84  
  * <p>The instantiated route path of a document is defined by it's graph of
 85  
  * {@link RouteNodeInstance} objects.  The path starts at the initial node of the document
 86  
  * and progresses from there following the next nodes of each node instance.  The current
 87  
  * active nodes on the document are defined by the "active" flag on the node instance
 88  
  * where are not marked as "complete".
 89  
  *
 90  
  * @see DocumentType
 91  
  * @see ActionRequestValue
 92  
  * @see ActionItem
 93  
  * @see ActionTakenValue
 94  
  * @see RouteNodeInstance
 95  
  * @see KEWConstants
 96  
  *
 97  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 98  
  */
 99  
 @Entity
 100  
 @Table(name="KREW_DOC_HDR_T")
 101  
 @Sequence(name="KREW_DOC_HDR_S", property="routeHeaderId")
 102  
 @NamedQueries({
 103  
         @NamedQuery(name="DocumentRouteHeaderValue.FindByRouteHeaderId", query="select d from DocumentRouteHeaderValue as d where d.routeHeaderId = :routeHeaderId"),
 104  
         @NamedQuery(name="DocumentRouteHeaderValue.QuickLinks.FindWatchedDocumentsByInitiatorWorkflowId", query="SELECT NEW org.kuali.rice.kew.quicklinks.WatchedDocument(routeHeaderId, docRouteStatus, docTitle) FROM DocumentRouteHeaderValue WHERE initiatorWorkflowId = :initiatorWorkflowId AND docRouteStatus IN ('"+ KEWConstants.ROUTE_HEADER_ENROUTE_CD +"','"+ KEWConstants.ROUTE_HEADER_EXCEPTION_CD +"') ORDER BY createDate DESC"),
 105  
         @NamedQuery(name="DocumentRouteHeaderValue.GetAppDocId", query="SELECT d.appDocId from DocumentRouteHeaderValue as d where d.routeHeaderId = :routeHeaderId")
 106  
 })
 107  
 public class DocumentRouteHeaderValue extends KewPersistableBusinessObjectBase {
 108  
     private static final long serialVersionUID = -4700736340527913220L;
 109  0
     private static final Logger LOG = Logger.getLogger(DocumentRouteHeaderValue.class);
 110  
 
 111  
     public static final String CURRENT_ROUTE_NODE_NAME_DELIMITER = ", ";
 112  
 
 113  
     @Column(name="DOC_TYP_ID")
 114  
         private java.lang.Long documentTypeId;
 115  
     @Column(name="DOC_HDR_STAT_CD")
 116  
         private java.lang.String docRouteStatus;
 117  
     @Column(name="RTE_LVL")
 118  
         private java.lang.Integer docRouteLevel;
 119  
         @Column(name="STAT_MDFN_DT")
 120  
         private java.sql.Timestamp statusModDate;
 121  
         @Column(name="CRTE_DT")
 122  
         private java.sql.Timestamp createDate;
 123  
         @Column(name="APRV_DT")
 124  
         private java.sql.Timestamp approvedDate;
 125  
         @Column(name="FNL_DT")
 126  
         private java.sql.Timestamp finalizedDate;
 127  
     @Transient
 128  
     private DocumentRouteHeaderValueContent documentContent;
 129  
     @Column(name="TTL")
 130  
         private java.lang.String docTitle;
 131  
     @Column(name="APP_DOC_ID")
 132  
         private java.lang.String appDocId;
 133  0
     @Column(name="DOC_VER_NBR")
 134  
     private java.lang.Integer docVersion = new Integer(KEWConstants.DOCUMENT_VERSION_NODAL);
 135  
     @Column(name="INITR_PRNCPL_ID")
 136  
         private java.lang.String initiatorWorkflowId;
 137  
     @Column(name="RTE_PRNCPL_ID")
 138  
         private java.lang.String routedByUserWorkflowId;
 139  
         @Column(name="RTE_STAT_MDFN_DT")
 140  
         private java.sql.Timestamp routeStatusDate;
 141  
         @Column(name="RTE_LVL_MDFN_DT")
 142  
         private java.sql.Timestamp routeLevelDate;
 143  
     @Column(name="APP_DOC_STAT")
 144  
         private java.lang.String appDocStatus;
 145  
         @Column(name="APP_DOC_STAT_MDFN_DT")
 146  
         private java.sql.Timestamp appDocStatusDate;
 147  
         
 148  
     @Id
 149  
         @Column(name="DOC_HDR_ID")
 150  
         private java.lang.Long routeHeaderId;
 151  
     
 152  0
     @OneToMany(fetch=FetchType.EAGER, cascade={CascadeType.REMOVE}, mappedBy="routeHeader")
 153  
     @Fetch(value = FetchMode.SUBSELECT)
 154  
     private List<ActionRequestValue> actionRequests = new ArrayList<ActionRequestValue>();
 155  
     
 156  0
     @OneToMany(fetch=FetchType.EAGER, mappedBy="routeHeader")
 157  
     @Fetch(value = FetchMode.SUBSELECT)
 158  
     private List<ActionTakenValue> actionsTaken = new ArrayList<ActionTakenValue>();
 159  
     
 160  0
     @OneToMany(cascade={CascadeType.REMOVE}, mappedBy="routeHeader")
 161  
     private List<ActionItem> actionItems = new ArrayList<ActionItem>();
 162  
     
 163  
     /**
 164  
      * The appDocStatusHistory keeps a list of Application Document Status transitions
 165  
      * for the document.  It tracks the previous status, the new status, and a timestamp of the 
 166  
      * transition for each status transition.
 167  
      */
 168  0
     @OneToMany(fetch=FetchType.EAGER, cascade={CascadeType.PERSIST}, mappedBy="routeHeader")
 169  
     @OrderBy("statusTransitionId ASC")
 170  
     @Fetch(value = FetchMode.SUBSELECT)
 171  
     private List<DocumentStatusTransition> appDocStatusHistory = new ArrayList<DocumentStatusTransition>();
 172  
     
 173  0
     @OneToMany(cascade={CascadeType.PERSIST, CascadeType.REMOVE})
 174  
     @JoinColumn(name="DOC_HDR_ID")
 175  
     private List<Note> notes = new ArrayList<Note>();
 176  
     
 177  0
     @Transient
 178  
     private List<SearchableAttributeValue> searchableAttributeValues = new ArrayList<SearchableAttributeValue>();
 179  0
     @Transient
 180  
     private Collection queueItems = new ArrayList();
 181  0
     @Transient
 182  
     private boolean routingReport = false;
 183  
 
 184  
     private static final boolean FINAL_STATE = true;
 185  
     protected static final HashMap<String,String> legalActions;
 186  
     protected static final HashMap<String,String> stateTransitionMap;
 187  
 
 188  
     /* New Workflow 2.1 Field */
 189  0
     @ManyToMany(fetch=FetchType.EAGER, cascade = CascadeType.REMOVE)
 190  
     @JoinTable(name = "KREW_INIT_RTE_NODE_INSTN_T", joinColumns = @JoinColumn(name = "DOC_HDR_ID"), inverseJoinColumns = @JoinColumn(name = "RTE_NODE_INSTN_ID"))    
 191  
     private List<RouteNodeInstance> initialRouteNodeInstances = new ArrayList<RouteNodeInstance>();
 192  
 
 193  
     static {
 194  0
         stateTransitionMap = new HashMap<String,String>();
 195  0
         stateTransitionMap.put(KEWConstants.ROUTE_HEADER_INITIATED_CD, KEWConstants.ROUTE_HEADER_SAVED_CD + KEWConstants.ROUTE_HEADER_ENROUTE_CD + KEWConstants.ROUTE_HEADER_CANCEL_CD);
 196  
 
 197  0
         stateTransitionMap.put(KEWConstants.ROUTE_HEADER_SAVED_CD, KEWConstants.ROUTE_HEADER_SAVED_CD + KEWConstants.ROUTE_HEADER_ENROUTE_CD + KEWConstants.ROUTE_HEADER_CANCEL_CD + KEWConstants.ROUTE_HEADER_APPROVED_CD);
 198  
 
 199  0
         stateTransitionMap.put(KEWConstants.ROUTE_HEADER_ENROUTE_CD, KEWConstants.ROUTE_HEADER_DISAPPROVED_CD +
 200  
                 KEWConstants.ROUTE_HEADER_CANCEL_CD + KEWConstants.ROUTE_HEADER_APPROVED_CD + KEWConstants.ROUTE_HEADER_EXCEPTION_CD + KEWConstants.ROUTE_HEADER_SAVED_CD);
 201  0
         stateTransitionMap.put(KEWConstants.ROUTE_HEADER_DISAPPROVED_CD, "");
 202  0
         stateTransitionMap.put(KEWConstants.ROUTE_HEADER_CANCEL_CD, "");
 203  0
         stateTransitionMap.put(KEWConstants.ROUTE_HEADER_FINAL_CD, "");
 204  0
         stateTransitionMap.put(KEWConstants.ROUTE_HEADER_EXCEPTION_CD, KEWConstants.ROUTE_HEADER_EXCEPTION_CD + KEWConstants.ROUTE_HEADER_ENROUTE_CD + KEWConstants.ROUTE_HEADER_CANCEL_CD + KEWConstants.ROUTE_HEADER_APPROVED_CD + KEWConstants.ROUTE_HEADER_DISAPPROVED_CD + KEWConstants.ROUTE_HEADER_SAVED_CD);
 205  0
         stateTransitionMap.put(KEWConstants.ROUTE_HEADER_APPROVED_CD, KEWConstants.ROUTE_HEADER_APPROVED_CD + KEWConstants.ROUTE_HEADER_PROCESSED_CD + KEWConstants.ROUTE_HEADER_EXCEPTION_CD);
 206  0
         stateTransitionMap.put(KEWConstants.ROUTE_HEADER_PROCESSED_CD, KEWConstants.ROUTE_HEADER_FINAL_CD + KEWConstants.ROUTE_HEADER_PROCESSED_CD);
 207  
 
 208  0
         legalActions = new HashMap<String,String>();
 209  0
         legalActions.put(KEWConstants.ROUTE_HEADER_INITIATED_CD, KEWConstants.ACTION_TAKEN_FYI_CD + KEWConstants.ACTION_TAKEN_ACKNOWLEDGED_CD + KEWConstants.ACTION_TAKEN_SAVED_CD + KEWConstants.ACTION_TAKEN_COMPLETED_CD + KEWConstants.ACTION_TAKEN_ROUTED_CD + KEWConstants.ACTION_TAKEN_CANCELED_CD + KEWConstants.ACTION_TAKEN_ADHOC_CD + KEWConstants.ACTION_TAKEN_ADHOC_REVOKED_CD + KEWConstants.ACTION_TAKEN_BLANKET_APPROVE_CD + KEWConstants.ACTION_TAKEN_MOVE_CD);
 210  0
         legalActions.put(KEWConstants.ROUTE_HEADER_SAVED_CD, KEWConstants.ACTION_TAKEN_FYI_CD + KEWConstants.ACTION_TAKEN_ACKNOWLEDGED_CD + KEWConstants.ACTION_TAKEN_SAVED_CD + KEWConstants.ACTION_TAKEN_COMPLETED_CD + KEWConstants.ACTION_TAKEN_ROUTED_CD + KEWConstants.ACTION_TAKEN_APPROVED_CD + KEWConstants.ACTION_TAKEN_CANCELED_CD + KEWConstants.ACTION_TAKEN_ADHOC_CD + KEWConstants.ACTION_TAKEN_ADHOC_REVOKED_CD + KEWConstants.ACTION_TAKEN_BLANKET_APPROVE_CD + KEWConstants.ACTION_TAKEN_MOVE_CD);
 211  
         /* ACTION_TAKEN_ROUTED_CD not included in enroute state
 212  
          * ACTION_TAKEN_SAVED_CD removed as of version 2.4
 213  
          */
 214  0
         legalActions.put(KEWConstants.ROUTE_HEADER_ENROUTE_CD, /*KEWConstants.ACTION_TAKEN_SAVED_CD + KEWConstants.ACTION_TAKEN_ROUTED_CD + */KEWConstants.ACTION_TAKEN_APPROVED_CD + KEWConstants.ACTION_TAKEN_ACKNOWLEDGED_CD + KEWConstants.ACTION_TAKEN_FYI_CD + KEWConstants.ACTION_TAKEN_ADHOC_CD + KEWConstants.ACTION_TAKEN_ADHOC_REVOKED_CD + KEWConstants.ACTION_TAKEN_BLANKET_APPROVE_CD + KEWConstants.ACTION_TAKEN_CANCELED_CD + KEWConstants.ACTION_TAKEN_COMPLETED_CD + KEWConstants.ACTION_TAKEN_DENIED_CD + KEWConstants.ACTION_TAKEN_SU_APPROVED_CD + KEWConstants.ACTION_TAKEN_SU_CANCELED_CD + KEWConstants.ACTION_TAKEN_SU_DISAPPROVED_CD + KEWConstants.ACTION_TAKEN_SU_ROUTE_LEVEL_APPROVED_CD + KEWConstants.ACTION_TAKEN_RETURNED_TO_PREVIOUS_CD + KEWConstants.ACTION_TAKEN_SU_RETURNED_TO_PREVIOUS_CD + KEWConstants.ACTION_TAKEN_MOVE_CD);
 215  
         /* ACTION_TAKEN_ROUTED_CD not included in exception state
 216  
          * ACTION_TAKEN_SAVED_CD removed as of version 2.4.2
 217  
          */
 218  0
         legalActions.put(KEWConstants.ROUTE_HEADER_EXCEPTION_CD, /*KEWConstants.ACTION_TAKEN_SAVED_CD + */KEWConstants.ACTION_TAKEN_FYI_CD + KEWConstants.ACTION_TAKEN_ACKNOWLEDGED_CD + KEWConstants.ACTION_TAKEN_ADHOC_CD + KEWConstants.ACTION_TAKEN_ADHOC_REVOKED_CD + KEWConstants.ACTION_TAKEN_APPROVED_CD + KEWConstants.ACTION_TAKEN_BLANKET_APPROVE_CD + KEWConstants.ACTION_TAKEN_CANCELED_CD + KEWConstants.ACTION_TAKEN_COMPLETED_CD + KEWConstants.ACTION_TAKEN_DENIED_CD + KEWConstants.ACTION_TAKEN_SU_APPROVED_CD + KEWConstants.ACTION_TAKEN_SU_CANCELED_CD + KEWConstants.ACTION_TAKEN_SU_DISAPPROVED_CD + KEWConstants.ACTION_TAKEN_SU_ROUTE_LEVEL_APPROVED_CD + KEWConstants.ACTION_TAKEN_RETURNED_TO_PREVIOUS_CD + KEWConstants.ACTION_TAKEN_SU_RETURNED_TO_PREVIOUS_CD + KEWConstants.ACTION_TAKEN_MOVE_CD);
 219  0
         legalActions.put(KEWConstants.ROUTE_HEADER_FINAL_CD, KEWConstants.ACTION_TAKEN_FYI_CD + KEWConstants.ACTION_TAKEN_ACKNOWLEDGED_CD + KEWConstants.ACTION_TAKEN_ADHOC_REVOKED_CD);
 220  0
         legalActions.put(KEWConstants.ROUTE_HEADER_CANCEL_CD, KEWConstants.ACTION_TAKEN_FYI_CD + KEWConstants.ACTION_TAKEN_ACKNOWLEDGED_CD + KEWConstants.ACTION_TAKEN_ADHOC_REVOKED_CD);
 221  0
         legalActions.put(KEWConstants.ROUTE_HEADER_DISAPPROVED_CD, KEWConstants.ACTION_TAKEN_FYI_CD + KEWConstants.ACTION_TAKEN_ACKNOWLEDGED_CD + KEWConstants.ACTION_TAKEN_ADHOC_REVOKED_CD);
 222  0
         legalActions.put(KEWConstants.ROUTE_HEADER_APPROVED_CD, KEWConstants.ACTION_TAKEN_FYI_CD + KEWConstants.ACTION_TAKEN_ACKNOWLEDGED_CD + KEWConstants.ACTION_TAKEN_ADHOC_REVOKED_CD);
 223  0
         legalActions.put(KEWConstants.ROUTE_HEADER_PROCESSED_CD, KEWConstants.ACTION_TAKEN_FYI_CD + KEWConstants.ACTION_TAKEN_ACKNOWLEDGED_CD + KEWConstants.ACTION_TAKEN_ADHOC_REVOKED_CD);
 224  0
     }
 225  
 
 226  0
     public DocumentRouteHeaderValue() {
 227  0
     }
 228  
 
 229  
     public KimPrincipal getInitiatorPrincipal() {
 230  
             // if we are running a simulation, there will be no initiator
 231  0
             if (getInitiatorWorkflowId() == null) {
 232  0
                     return null;
 233  
             }
 234  0
             return KEWServiceLocator.getIdentityHelperService().getPrincipal(getInitiatorWorkflowId());
 235  
     }
 236  
     
 237  
     public KimPrincipal getRoutedByPrincipal()
 238  
     {
 239  0
             if (getRoutedByUserWorkflowId() == null) {
 240  0
                     return null;
 241  
             }
 242  0
             return KEWServiceLocator.getIdentityHelperService().getPrincipal(getRoutedByUserWorkflowId());
 243  
            }
 244  
         
 245  
     public String getInitiatorDisplayName() {
 246  0
         return KEWServiceLocator.getIdentityHelperService().getPerson(getInitiatorWorkflowId()).getName();
 247  
     }
 248  
 
 249  
     public String getRoutedByDisplayName() {
 250  0
             return KEWServiceLocator.getIdentityHelperService().getPerson(getRoutedByUserWorkflowId()).getName();
 251  
     }
 252  
         
 253  
     public String getCurrentRouteLevelName() {
 254  0
         String name = "Not Found";
 255  
         // TODO the isRouteLevelDocument junk can be ripped out
 256  0
             if(routingReport){
 257  0
                     name = "Routing Report";
 258  0
             } else if (CompatUtils.isRouteLevelDocument(this)) {
 259  0
             int routeLevelInt = getDocRouteLevel().intValue();
 260  0
             LOG.info("Getting current route level name for a Route level document: " + routeLevelInt+CURRENT_ROUTE_NODE_NAME_DELIMITER+routeHeaderId);
 261  0
             List routeLevelNodes = CompatUtils.getRouteLevelCompatibleNodeList(getDocumentType());
 262  0
             LOG.info("Route level compatible node list has " + routeLevelNodes.size() + " nodes");
 263  0
             if (routeLevelInt < routeLevelNodes.size()) {
 264  0
                 name = ((RouteNode)routeLevelNodes.get(routeLevelInt)).getRouteNodeName();
 265  
             }
 266  0
         } else {
 267  0
                 name = "";
 268  0
                 for (Iterator<String> iterator = getCurrentNodeNames().iterator(); iterator.hasNext();) {
 269  0
                         String nodeName = iterator.next();
 270  0
                         name += nodeName + (iterator.hasNext() ? CURRENT_ROUTE_NODE_NAME_DELIMITER : "");
 271  0
                 }
 272  
         }
 273  0
         return name;
 274  
     }
 275  
     
 276  
     public List<String> getCurrentNodeNames() {
 277  0
             List<String> currentNodeNames = new ArrayList<String>();
 278  0
             Collection nodeInstances = KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(getRouteHeaderId());
 279  0
         if (nodeInstances.isEmpty()) {
 280  0
             nodeInstances = KEWServiceLocator.getRouteNodeService().getTerminalNodeInstances(getRouteHeaderId());
 281  
         }
 282  0
         for (Iterator iterator = nodeInstances.iterator(); iterator.hasNext();) {
 283  0
             RouteNodeInstance nodeInstance = (RouteNodeInstance) iterator.next();
 284  0
             currentNodeNames.add(nodeInstance.getRouteNode().getRouteNodeName());
 285  0
         }
 286  0
         return currentNodeNames;
 287  
     }
 288  
 
 289  
     public String getRouteStatusLabel() {
 290  0
         return CodeTranslator.getRouteStatusLabel(getDocRouteStatus());
 291  
     }
 292  
 
 293  
     public String getDocRouteStatusLabel() {
 294  0
         return CodeTranslator.getRouteStatusLabel(getDocRouteStatus());
 295  
     }
 296  
     /**
 297  
      * 
 298  
      * This method returns the Document Status Policy for the document type associated with this Route Header.
 299  
      * The Document Status Policy denotes whether the KEW Route Status, or the Application Document Status,
 300  
      * or both are to be displayed.
 301  
      * 
 302  
      * @return
 303  
      */
 304  
     public String getDocStatusPolicy() {
 305  0
             return getDocumentType().getDocumentStatusPolicy().getPolicyStringValue();
 306  
     }
 307  
     
 308  
     public Collection getQueueItems() {
 309  0
         return queueItems;
 310  
     }
 311  
 
 312  
     public void setQueueItems(Collection queueItems) {
 313  0
         this.queueItems = queueItems;
 314  0
     }
 315  
 
 316  
     public List<ActionItem> getActionItems() {
 317  0
         return actionItems;
 318  
     }
 319  
 
 320  
     public void setActionItems(List<ActionItem> actionItems) {
 321  0
         this.actionItems = actionItems;
 322  0
     }
 323  
 
 324  
     public List<ActionTakenValue> getActionsTaken() {
 325  0
         return actionsTaken;
 326  
     }
 327  
 
 328  
     public void setActionsTaken(List<ActionTakenValue> actionsTaken) {
 329  0
         this.actionsTaken = actionsTaken;
 330  0
     }
 331  
 
 332  
     public List<ActionRequestValue> getActionRequests() {
 333  0
         return actionRequests;
 334  
     }
 335  
 
 336  
     public void setActionRequests(List<ActionRequestValue> actionRequests) {
 337  0
         this.actionRequests = actionRequests;
 338  0
     }
 339  
 
 340  
     public DocumentType getDocumentType() {
 341  0
             return KEWServiceLocator.getDocumentTypeService().findById(getDocumentTypeId());
 342  
     }
 343  
 
 344  
     public java.lang.String getAppDocId() {
 345  0
         return appDocId;
 346  
     }
 347  
 
 348  
     public void setAppDocId(java.lang.String appDocId) {
 349  0
         this.appDocId = appDocId;
 350  0
     }
 351  
 
 352  
     public java.sql.Timestamp getApprovedDate() {
 353  0
         return approvedDate;
 354  
     }
 355  
 
 356  
     public void setApprovedDate(java.sql.Timestamp approvedDate) {
 357  0
         this.approvedDate = approvedDate;
 358  0
     }
 359  
 
 360  
     public java.sql.Timestamp getCreateDate() {
 361  0
         return createDate;
 362  
     }
 363  
 
 364  
     public void setCreateDate(java.sql.Timestamp createDate) {
 365  0
         this.createDate = createDate;
 366  0
     }
 367  
 
 368  
     public java.lang.String getDocContent() {
 369  0
             return getDocumentContent().getDocumentContent();
 370  
     }
 371  
 
 372  
     public void setDocContent(java.lang.String docContent) {
 373  0
             DocumentRouteHeaderValueContent content = getDocumentContent();
 374  0
             content.setDocumentContent(docContent);
 375  0
     }
 376  
 
 377  
     public java.lang.Integer getDocRouteLevel() {
 378  0
         return docRouteLevel;
 379  
     }
 380  
 
 381  
     public void setDocRouteLevel(java.lang.Integer docRouteLevel) {
 382  0
         this.docRouteLevel = docRouteLevel;
 383  0
     }
 384  
 
 385  
     public java.lang.String getDocRouteStatus() {
 386  0
         return docRouteStatus;
 387  
     }
 388  
 
 389  
     public void setDocRouteStatus(java.lang.String docRouteStatus) {
 390  0
         this.docRouteStatus = docRouteStatus;
 391  0
     }
 392  
 
 393  
     public java.lang.String getDocTitle() {
 394  0
         return docTitle;
 395  
     }
 396  
 
 397  
     public void setDocTitle(java.lang.String docTitle) {
 398  0
         this.docTitle = docTitle;
 399  0
     }
 400  
 
 401  
     public java.lang.Long getDocumentTypeId() {
 402  0
         return documentTypeId;
 403  
     }
 404  
 
 405  
     public void setDocumentTypeId(java.lang.Long docTypeId) {
 406  0
         this.documentTypeId = docTypeId;
 407  0
     }
 408  
 
 409  
     public java.lang.Integer getDocVersion() {
 410  0
         return docVersion;
 411  
     }
 412  
 
 413  
     public void setDocVersion(java.lang.Integer docVersion) {
 414  0
         this.docVersion = docVersion;
 415  0
     }
 416  
 
 417  
     public java.sql.Timestamp getFinalizedDate() {
 418  0
         return finalizedDate;
 419  
     }
 420  
 
 421  
     public void setFinalizedDate(java.sql.Timestamp finalizedDate) {
 422  0
         this.finalizedDate = finalizedDate;
 423  0
     }
 424  
 
 425  
     public java.lang.String getInitiatorWorkflowId() {
 426  0
         return initiatorWorkflowId;
 427  
     }
 428  
 
 429  
     public void setInitiatorWorkflowId(java.lang.String initiatorWorkflowId) {
 430  0
         this.initiatorWorkflowId = initiatorWorkflowId;
 431  0
     }
 432  
 
 433  
     public java.lang.String getRoutedByUserWorkflowId() {
 434  0
         if ( (isEnroute()) && (StringUtils.isBlank(routedByUserWorkflowId)) ) {
 435  0
             return initiatorWorkflowId;
 436  
         }
 437  0
         return routedByUserWorkflowId;
 438  
     }
 439  
 
 440  
     public void setRoutedByUserWorkflowId(java.lang.String routedByUserWorkflowId) {
 441  0
         this.routedByUserWorkflowId = routedByUserWorkflowId;
 442  0
     }
 443  
 
 444  
     public java.lang.Long getRouteHeaderId() {
 445  0
         return routeHeaderId;
 446  
     }
 447  
 
 448  
     public void setRouteHeaderId(java.lang.Long routeHeaderId) {
 449  0
         this.routeHeaderId = routeHeaderId;
 450  0
     }
 451  
 
 452  
     public java.sql.Timestamp getRouteLevelDate() {
 453  0
         return routeLevelDate;
 454  
     }
 455  
 
 456  
     public void setRouteLevelDate(java.sql.Timestamp routeLevelDate) {
 457  0
         this.routeLevelDate = routeLevelDate;
 458  0
     }
 459  
 
 460  
     public java.sql.Timestamp getRouteStatusDate() {
 461  0
         return routeStatusDate;
 462  
     }
 463  
 
 464  
     public void setRouteStatusDate(java.sql.Timestamp routeStatusDate) {
 465  0
         this.routeStatusDate = routeStatusDate;
 466  0
     }
 467  
 
 468  
     public java.sql.Timestamp getStatusModDate() {
 469  0
         return statusModDate;
 470  
     }
 471  
 
 472  
     public void setStatusModDate(java.sql.Timestamp statusModDate) {
 473  0
         this.statusModDate = statusModDate;
 474  0
     }
 475  
 
 476  
     /**
 477  
      * 
 478  
      * This method returns the Application Document Status.
 479  
      * This status is an alternative to the Route Status that may be used for a document.
 480  
      * It is configurable per document type.
 481  
      * 
 482  
      * @see ApplicationDocumentStatus
 483  
      * @see DocumentTypePolicy
 484  
      * 
 485  
      * @return
 486  
      */
 487  
     public java.lang.String getAppDocStatus() {
 488  0
             if (appDocStatus == null || "".equals(appDocStatus)){
 489  0
                     return KEWConstants.UNKNOWN_STATUS;
 490  
             }
 491  0
         return appDocStatus;
 492  
     }
 493  
 
 494  
     public void setAppDocStatus(java.lang.String appDocStatus){
 495  0
         this.appDocStatus = appDocStatus;
 496  0
     }
 497  
     
 498  
     /**
 499  
      * 
 500  
      * This method returns a combination of the route status label and the app doc status.
 501  
      * 
 502  
      * @return
 503  
      */
 504  
     public String getCombinedStatus(){
 505  0
             String routeStatus = getRouteStatusLabel();
 506  0
             String appStatus = getAppDocStatus();
 507  0
             if (routeStatus != null && routeStatus.length()>0){
 508  0
                     if (appStatus.length() > 0){
 509  0
                             routeStatus += ", "+appStatus;
 510  
                     }
 511  
             } else {
 512  0
                     return appStatus;
 513  
             }
 514  0
             return routeStatus;
 515  
     }
 516  
 
 517  
     /**
 518  
      * 
 519  
      * This method sets the appDocStatus.
 520  
      * It firsts validates the new value against the defined acceptable values, if defined.
 521  
      * It also updates the AppDocStatus date, and saves the status transition information
 522  
      * 
 523  
      * @param appDocStatus
 524  
      * @throws WorkflowRuntimeException
 525  
      */
 526  
     public void updateAppDocStatus(java.lang.String appDocStatus) throws WorkflowRuntimeException{
 527  
                //validate against allowable values if defined
 528  0
             if (appDocStatus != null && appDocStatus.length() > 0 && !appDocStatus.equalsIgnoreCase(this.appDocStatus)){                    
 529  0
                     DocumentType documentType = KEWServiceLocator.getDocumentTypeService().findById(this.getDocumentTypeId());            
 530  0
                     if (documentType.getValidApplicationStatuses() != null  && documentType.getValidApplicationStatuses().size() > 0){
 531  0
                             Iterator iter = documentType.getValidApplicationStatuses().iterator();
 532  0
                             boolean statusValidated = false;
 533  0
                             while (iter.hasNext())
 534  
                             {
 535  0
                                     ApplicationDocumentStatus myAppDocStat = (ApplicationDocumentStatus) iter.next();
 536  0
                                     if (appDocStatus.compareToIgnoreCase(myAppDocStat.getStatusName()) == 0)
 537  
                                     {
 538  0
                                             statusValidated = true;
 539  0
                                             break;
 540  
                                     }
 541  0
                             }
 542  0
                             if (!statusValidated){
 543  0
                                     WorkflowRuntimeException xpee = new WorkflowRuntimeException("AppDocStatus value " +  appDocStatus + " not allowable."); 
 544  0
                                     LOG.error("Error validating nextAppDocStatus name: " +  appDocStatus + " against acceptable values.", xpee);
 545  0
                                     throw xpee; 
 546  
                             }
 547  
                     }
 548  
 
 549  
                     // set the status value
 550  0
                     String oldStatus = this.appDocStatus;
 551  0
                     this.appDocStatus = appDocStatus;
 552  
 
 553  
                     // update the timestamp
 554  0
                     setAppDocStatusDate(new Timestamp(System.currentTimeMillis()));
 555  
 
 556  
                     // save the status transition
 557  0
                     this.appDocStatusHistory.add(new DocumentStatusTransition(routeHeaderId, oldStatus, appDocStatus));
 558  
             }
 559  
 
 560  0
     }
 561  
     
 562  
     
 563  
     public java.sql.Timestamp getAppDocStatusDate() {
 564  0
         return appDocStatusDate;
 565  
     }
 566  
 
 567  
     public void setAppDocStatusDate(java.sql.Timestamp appDocStatusDate) {
 568  0
         this.appDocStatusDate = appDocStatusDate;
 569  0
     }
 570  
 
 571  
     public Object copy(boolean preserveKeys) {
 572  0
         throw new UnsupportedOperationException("The copy method is deprecated and unimplemented!");
 573  
     }
 574  
 
 575  
     /**
 576  
      * @return True if the document is in the state of Initiated
 577  
      */
 578  
     public boolean isStateInitiated() {
 579  0
         return KEWConstants.ROUTE_HEADER_INITIATED_CD.equals(docRouteStatus);
 580  
     }
 581  
 
 582  
     /**
 583  
      * @return True if the document is in the state of Saved
 584  
      */
 585  
     public boolean isStateSaved() {
 586  0
         return KEWConstants.ROUTE_HEADER_SAVED_CD.equals(docRouteStatus);
 587  
     }
 588  
 
 589  
     /**
 590  
      * @return true if the document has ever been inte enroute state
 591  
      */
 592  
     public boolean isRouted() {
 593  0
         return !(isStateInitiated() || isStateSaved());
 594  
     }
 595  
 
 596  
     public boolean isInException() {
 597  0
         return KEWConstants.ROUTE_HEADER_EXCEPTION_CD.equals(docRouteStatus);
 598  
     }
 599  
 
 600  
     public boolean isDisaproved() {
 601  0
         return KEWConstants.ROUTE_HEADER_DISAPPROVED_CD.equals(docRouteStatus);
 602  
     }
 603  
 
 604  
     public boolean isCanceled() {
 605  0
         return KEWConstants.ROUTE_HEADER_CANCEL_CD.equals(docRouteStatus);
 606  
     }
 607  
 
 608  
     public boolean isFinal() {
 609  0
         return KEWConstants.ROUTE_HEADER_FINAL_CD.equals(docRouteStatus);
 610  
     }
 611  
 
 612  
     public boolean isEnroute() {
 613  0
             return KEWConstants.ROUTE_HEADER_ENROUTE_CD.equals(docRouteStatus);
 614  
     }
 615  
 
 616  
     /**
 617  
      * @return true if the document is in the processed state
 618  
      */
 619  
     public boolean isProcessed() {
 620  0
         return KEWConstants.ROUTE_HEADER_PROCESSED_CD.equals(docRouteStatus);
 621  
     }
 622  
 
 623  
     /**
 624  
      * @return true if the document is in the approved state
 625  
      */
 626  
     public boolean isApproved() {
 627  0
         return KEWConstants.ROUTE_HEADER_APPROVED_CD.equals(docRouteStatus);
 628  
     }
 629  
 
 630  
     public boolean isRoutable() {
 631  0
         return KEWConstants.ROUTE_HEADER_ENROUTE_CD.equals(docRouteStatus) ||
 632  
                         //KEWConstants.ROUTE_HEADER_EXCEPTION_CD.equals(docRouteStatus) ||
 633  
                         KEWConstants.ROUTE_HEADER_SAVED_CD.equals(docRouteStatus) ||
 634  
                         KEWConstants.ROUTE_HEADER_APPROVED_CD.equals(docRouteStatus) ||
 635  
                         KEWConstants.ROUTE_HEADER_PROCESSED_CD.equals(docRouteStatus);
 636  
     }
 637  
 
 638  
     /**
 639  
      * Return true if the given action code is valid for this document's current state.
 640  
      *
 641  
      * @param actionCd
 642  
      *            The action code to be tested.
 643  
      * @return True if the action code is valid for the document's status.
 644  
      */
 645  
     public boolean isValidActionToTake(String actionCd) {
 646  0
         String actions = (String) legalActions.get(docRouteStatus);
 647  0
         if (!actions.contains(actionCd)) {
 648  0
             return false;
 649  
         } else {
 650  0
             return true;
 651  
         }
 652  
     }
 653  
 
 654  
     public boolean isValidStatusChange(String newStatus) {
 655  0
             return ((String) stateTransitionMap.get(getDocRouteStatus())).contains(newStatus);
 656  
     }
 657  
 
 658  
     public void setRouteStatus(String newStatus, boolean finalState) throws InvalidActionTakenException {
 659  0
         if (newStatus != getDocRouteStatus()) {
 660  
             // only modify the status mod date if the status actually changed
 661  0
             setRouteStatusDate(new Timestamp(System.currentTimeMillis()));
 662  
         }
 663  0
         if (((String) stateTransitionMap.get(getDocRouteStatus())).contains(newStatus)) {
 664  0
             LOG.debug("changing status");
 665  0
             setDocRouteStatus(newStatus);
 666  
         } else {
 667  0
             LOG.debug("unable to change status");
 668  0
             throw new InvalidActionTakenException("Document status " + CodeTranslator.getRouteStatusLabel(getDocRouteStatus()) + " cannot transition to status " + CodeTranslator.getRouteStatusLabel(newStatus));
 669  
         }
 670  0
         setStatusModDate(new Timestamp(System.currentTimeMillis()));
 671  0
         if (finalState) {
 672  0
             LOG.debug("setting final timeStamp");
 673  0
             setFinalizedDate(new Timestamp(System.currentTimeMillis()));
 674  
         }
 675  0
     }
 676  
 
 677  
     /**
 678  
      * Mark the document as being processed.
 679  
      *
 680  
      * @throws ResourceUnavailableException
 681  
      * @throws InvalidActionTakenException
 682  
      */
 683  
     public void markDocumentProcessed() throws InvalidActionTakenException {
 684  0
         LOG.debug(this + " marked processed");
 685  0
         setRouteStatus(KEWConstants.ROUTE_HEADER_PROCESSED_CD, !FINAL_STATE);
 686  0
     }
 687  
 
 688  
     /**
 689  
      * Mark document cancled.
 690  
      *
 691  
      * @throws ResourceUnavailableException
 692  
      * @throws InvalidActionTakenException
 693  
      */
 694  
     public void markDocumentCanceled() throws InvalidActionTakenException {
 695  0
         LOG.debug(this + " marked canceled");
 696  0
         setRouteStatus(KEWConstants.ROUTE_HEADER_CANCEL_CD, FINAL_STATE);
 697  0
     }
 698  
 
 699  
     /**
 700  
      * Mark document disapproved
 701  
      *
 702  
      * @throws ResourceUnavailableException
 703  
      * @throws InvalidActionTakenException
 704  
      */
 705  
     public void markDocumentDisapproved() throws InvalidActionTakenException {
 706  0
         LOG.debug(this + " marked disapproved");
 707  0
         setRouteStatus(KEWConstants.ROUTE_HEADER_DISAPPROVED_CD, FINAL_STATE);
 708  0
     }
 709  
 
 710  
     /**
 711  
      * Mark document saved
 712  
      *
 713  
      * @throws ResourceUnavailableException
 714  
      * @throws InvalidActionTakenException
 715  
      */
 716  
     public void markDocumentSaved() throws InvalidActionTakenException {
 717  0
         LOG.debug(this + " marked saved");
 718  0
         setRouteStatus(KEWConstants.ROUTE_HEADER_SAVED_CD, !FINAL_STATE);
 719  0
     }
 720  
 
 721  
     /**
 722  
      * Mark the document as being approved.
 723  
      *
 724  
      * @throws ResourceUnavailableException
 725  
      * @throws InvalidActionTakenException
 726  
      */
 727  
     public void markDocumentApproved() throws InvalidActionTakenException {
 728  0
         LOG.debug(this + " marked approved");
 729  0
         setApprovedDate(new Timestamp(System.currentTimeMillis()));
 730  0
         setRouteStatus(KEWConstants.ROUTE_HEADER_APPROVED_CD, !FINAL_STATE);
 731  0
     }
 732  
 
 733  
     /**
 734  
      * Mark the document as being in the exception state.
 735  
      *
 736  
      * @throws ResourceUnavailableException
 737  
      * @throws InvalidActionTakenException
 738  
      */
 739  
     public void markDocumentInException() throws InvalidActionTakenException {
 740  0
         LOG.debug(this + " marked in exception");
 741  0
         setRouteStatus(KEWConstants.ROUTE_HEADER_EXCEPTION_CD, !FINAL_STATE);
 742  0
     }
 743  
 
 744  
     /**
 745  
      * Mark the document as being actively routed.
 746  
      *
 747  
      * @throws ResourceUnavailableException
 748  
      * @throws InvalidActionTakenException
 749  
      */
 750  
     public void markDocumentEnroute() throws InvalidActionTakenException {
 751  0
         LOG.debug(this + " marked enroute");
 752  0
         setRouteStatus(KEWConstants.ROUTE_HEADER_ENROUTE_CD, !FINAL_STATE);
 753  0
     }
 754  
 
 755  
     /**
 756  
      * Mark document finalized.
 757  
      *
 758  
      * @throws ResourceUnavailableException
 759  
      * @throws InvalidActionTakenException
 760  
      */
 761  
     public void markDocumentFinalized() throws InvalidActionTakenException {
 762  0
         LOG.debug(this + " marked finalized");
 763  0
         setRouteStatus(KEWConstants.ROUTE_HEADER_FINAL_CD, FINAL_STATE);
 764  0
     }
 765  
 
 766  
     /**
 767  
      * This method takes data from a VO and sets it on this route header
 768  
      * @param routeHeaderVO
 769  
      * @throws WorkflowException
 770  
      */
 771  
     public void setRouteHeaderData(RouteHeaderDTO routeHeaderVO) throws WorkflowException {
 772  0
         if (!Utilities.equals(getDocTitle(), routeHeaderVO.getDocTitle())) {
 773  0
                 KEWServiceLocator.getActionListService().updateActionItemsForTitleChange(getRouteHeaderId(), routeHeaderVO.getDocTitle());
 774  
         }
 775  0
         setDocTitle(routeHeaderVO.getDocTitle());
 776  0
         setAppDocId(routeHeaderVO.getAppDocId());
 777  0
         setStatusModDate(new Timestamp(System.currentTimeMillis()));
 778  0
         updateAppDocStatus(routeHeaderVO.getAppDocStatus());
 779  
 
 780  
         /* set the variables from the routeHeaderVO */
 781  0
         List<KeyValueDTO> variables = routeHeaderVO.getVariables();
 782  0
         for (KeyValueDTO kvp : variables) {
 783  0
             setVariable(kvp.getKey(), kvp.getValue());
 784  
         }
 785  0
     }
 786  
 
 787  
     /**
 788  
      * Convenience method that returns the branch of the first (and presumably only?) initial node
 789  
      * @return the branch of the first (and presumably only?) initial node
 790  
      */
 791  
     public Branch getRootBranch() {
 792  0
         if (!this.initialRouteNodeInstances.isEmpty()) {
 793  0
             return ((RouteNodeInstance) getInitialRouteNodeInstance(0)).getBranch();
 794  
         } 
 795  0
         return null;
 796  
     }
 797  
 
 798  
     /**
 799  
      * Looks up a variable (embodied in a "BranchState" key/value pair) in the
 800  
      * branch state table.
 801  
      */
 802  
     private BranchState findVariable(String name) {
 803  0
         Branch rootBranch = getRootBranch();
 804  0
         if (rootBranch != null) {
 805  0
             List branchState = rootBranch.getBranchState();
 806  0
             Iterator it = branchState.iterator();
 807  0
             while (it.hasNext()) {
 808  0
                 BranchState state = (BranchState) it.next();
 809  0
                 if (Utilities.equals(state.getKey(), BranchState.VARIABLE_PREFIX + name)) {
 810  0
                     return state;
 811  
                 }
 812  0
             }
 813  
         }
 814  0
         return null;
 815  
     }
 816  
 
 817  
     /**
 818  
      * Gets a variable
 819  
      * @param name variable name
 820  
      * @return variable value, or null if variable is not defined
 821  
      */
 822  
     public String getVariable(String name) {
 823  0
         BranchState state = findVariable(name);
 824  0
         if (state == null) {
 825  0
             LOG.debug("Variable not found: '" + name + "'");
 826  0
             return null;
 827  
         }
 828  0
         return state.getValue();
 829  
     }
 830  
 
 831  
     public void removeVariableThatContains(String name) {
 832  0
         List<BranchState> statesToRemove = new ArrayList<BranchState>();
 833  0
         for (BranchState state : this.getRootBranchState()) {
 834  0
             if (state.getKey().contains(name)) {
 835  0
                 statesToRemove.add(state);
 836  
             }
 837  
         }
 838  0
         this.getRootBranchState().removeAll(statesToRemove);
 839  0
     }
 840  
     
 841  
     /**
 842  
      * Sets a variable
 843  
      * @param name variable name
 844  
      * @param value variable value, or null if variable should be removed
 845  
      */
 846  
     public void setVariable(String name, String value) {
 847  0
         BranchState state = findVariable(name);
 848  0
         Branch rootBranch = getRootBranch();
 849  0
         if (rootBranch != null) {
 850  0
             List branchState = rootBranch.getBranchState();
 851  0
             if (state == null) {
 852  0
                 if (value == null) {
 853  0
                     LOG.debug("set non existent variable '" + name + "' to null value");
 854  0
                     return;
 855  
                 }
 856  0
                 LOG.debug("Adding branch state: '" + name + "'='" + value + "'");
 857  0
                 state = new BranchState();
 858  0
                 state.setBranch(rootBranch);
 859  0
                 state.setKey(BranchState.VARIABLE_PREFIX + name);
 860  0
                 state.setValue(value);
 861  0
                 rootBranch.addBranchState(state);
 862  
             } else {
 863  0
                 if (value == null) {
 864  0
                     LOG.debug("Removing value: " + state.getKey() + "=" + state.getValue());
 865  0
                     branchState.remove(state);
 866  
                 } else {
 867  0
                     LOG.debug("Setting value of variable '" + name + "' to '" + value + "'");
 868  0
                     state.setValue(value);
 869  
                 }
 870  
             }
 871  
         }
 872  0
     }
 873  
     
 874  
     public List<BranchState> getRootBranchState() {
 875  0
         if (this.getRootBranch() != null) {
 876  0
             return this.getRootBranch().getBranchState();
 877  
         }
 878  0
         return null;
 879  
     }
 880  
 
 881  
     public CustomActionListAttribute getCustomActionListAttribute() throws WorkflowException {
 882  0
         CustomActionListAttribute customActionListAttribute = null;
 883  0
         if (this.getDocumentType() != null) {
 884  0
                 customActionListAttribute = this.getDocumentType().getCustomActionListAttribute();
 885  0
                 if (customActionListAttribute != null) {
 886  0
                         return customActionListAttribute;
 887  
                 }
 888  
         }
 889  0
         customActionListAttribute = new DefaultCustomActionListAttribute();
 890  0
         return customActionListAttribute;
 891  
     }
 892  
 
 893  
     public CustomEmailAttribute getCustomEmailAttribute() throws WorkflowException {
 894  0
         CustomEmailAttribute customEmailAttribute = null;
 895  
         try {
 896  0
             if (this.getDocumentType() != null) {
 897  0
                 customEmailAttribute = this.getDocumentType().getCustomEmailAttribute();
 898  0
                 if (customEmailAttribute != null) {
 899  0
                     customEmailAttribute.setRouteHeaderVO(DTOConverter.convertRouteHeader(this, null));
 900  0
                     return customEmailAttribute;
 901  
                 }
 902  
             }
 903  0
         } catch (Exception e) {
 904  0
             LOG.debug("Error in retrieving custom email attribute", e);
 905  0
         }
 906  0
         customEmailAttribute = new CustomEmailAttributeImpl();
 907  0
         customEmailAttribute.setRouteHeaderVO(DTOConverter.convertRouteHeader(this, null));
 908  0
         return customEmailAttribute;
 909  
     }
 910  
 
 911  
     public CustomNoteAttribute getCustomNoteAttribute() throws WorkflowException
 912  
     {
 913  0
         CustomNoteAttribute customNoteAttribute = null;
 914  
         try {
 915  0
             if (this.getDocumentType() != null) {
 916  0
                 customNoteAttribute = this.getDocumentType().getCustomNoteAttribute();
 917  0
                 if (customNoteAttribute != null) {
 918  0
                     customNoteAttribute.setRouteHeaderVO(DTOConverter.convertRouteHeader(this, null));
 919  0
                     return customNoteAttribute;
 920  
                 }
 921  
             }
 922  0
         } catch (Exception e) {
 923  0
             LOG.debug("Error in retrieving custom note attribute", e);
 924  0
         }
 925  0
         customNoteAttribute = new CustomNoteAttributeImpl();
 926  0
         customNoteAttribute.setRouteHeaderVO(DTOConverter.convertRouteHeader(this, null));
 927  0
         return customNoteAttribute;
 928  
     }
 929  
 
 930  
     public ActionRequestValue getDocActionRequest(int index) {
 931  0
         while (actionRequests.size() <= index) {
 932  0
                 ActionRequestValue actionRequest = new ActionRequestFactory(this).createBlankActionRequest();
 933  0
                 actionRequest.setNodeInstance(new RouteNodeInstance());
 934  0
             actionRequests.add(actionRequest);
 935  0
         }
 936  0
         return (ActionRequestValue) actionRequests.get(index);
 937  
     }
 938  
 
 939  
     public ActionTakenValue getDocActionTaken(int index) {
 940  0
         while (actionsTaken.size() <= index) {
 941  0
             actionsTaken.add(new ActionTakenValue());
 942  
         }
 943  0
         return (ActionTakenValue) actionsTaken.get(index);
 944  
     }
 945  
 
 946  
     public ActionItem getDocActionItem(int index) {
 947  0
         while (actionItems.size() <= index) {
 948  0
             actionItems.add(new ActionItem());
 949  
         }
 950  0
         return (ActionItem) actionItems.get(index);
 951  
     }
 952  
 
 953  
     private RouteNodeInstance getInitialRouteNodeInstance(int index) {
 954  0
             if (initialRouteNodeInstances.size() >= index) {
 955  0
                 return (RouteNodeInstance) initialRouteNodeInstances.get(index);
 956  
             } 
 957  0
             return null;
 958  
     }
 959  
 
 960  
 //        /**
 961  
 //         * @param searchableAttributeValues The searchableAttributeValues to set.
 962  
 //         */
 963  
 //        public void setSearchableAttributeValues(List<SearchableAttributeValue> searchableAttributeValues) {
 964  
 //                this.searchableAttributeValues = searchableAttributeValues;
 965  
 //        }
 966  
 //
 967  
 //        /**
 968  
 //         * @return Returns the searchableAttributeValues.
 969  
 //         */
 970  
 //        public List<SearchableAttributeValue> getSearchableAttributeValues() {
 971  
 //                return searchableAttributeValues;
 972  
 //        }
 973  
 
 974  
         public boolean isRoutingReport() {
 975  0
                 return routingReport;
 976  
         }
 977  
 
 978  
         public void setRoutingReport(boolean routingReport) {
 979  0
                 this.routingReport = routingReport;
 980  0
         }
 981  
 
 982  
     public List<RouteNodeInstance> getInitialRouteNodeInstances() {
 983  0
         return initialRouteNodeInstances;
 984  
     }
 985  
 
 986  
     public void setInitialRouteNodeInstances(List<RouteNodeInstance> initialRouteNodeInstances) {
 987  0
         this.initialRouteNodeInstances = initialRouteNodeInstances;
 988  0
     }
 989  
 
 990  
         public List<Note> getNotes() {
 991  0
                 return notes;
 992  
         }
 993  
 
 994  
         public void setNotes(List<Note> notes) {
 995  0
                 this.notes = notes;
 996  0
         }
 997  
 
 998  
         public DocumentRouteHeaderValueContent getDocumentContent() {
 999  0
                 if (documentContent == null) {
 1000  0
                         documentContent = KEWServiceLocator.getRouteHeaderService().getContent(getRouteHeaderId());
 1001  
                 }
 1002  0
                 return documentContent;
 1003  
         }
 1004  
 
 1005  
         public void setDocumentContent(DocumentRouteHeaderValueContent documentContent) {
 1006  0
                 this.documentContent = documentContent;
 1007  0
         }
 1008  
 
 1009  
         public List<DocumentStatusTransition> getAppDocStatusHistory() {
 1010  0
                 return this.appDocStatusHistory;
 1011  
         }
 1012  
 
 1013  
         public void setAppDocStatusHistory(
 1014  
                         List<DocumentStatusTransition> appDocStatusHistory) {
 1015  0
                 this.appDocStatusHistory = appDocStatusHistory;
 1016  0
         }
 1017  
 
 1018  
 
 1019  
         public String toString() {
 1020  0
             return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
 1021  
                 .append("routeHeaderId", routeHeaderId)
 1022  
             .append("documentTypeId", documentTypeId)
 1023  
             .append("docVersion", docVersion)
 1024  
             .append("docTitle", docTitle)
 1025  
             .append("createDate", createDate)
 1026  
             .append("initiatorWorkflowId", initiatorWorkflowId)
 1027  
             .append("routedByUserWorkflowId", routedByUserWorkflowId)
 1028  
             .append("docRouteStatus", docRouteStatus)
 1029  
             .append("routeStatusDate", routeStatusDate)
 1030  
             .append("statusModDate", statusModDate)
 1031  
             .append("docRouteLevel", docRouteLevel)
 1032  
             .append("routeLevelDate", routeLevelDate)
 1033  
             .append("approvedDate", approvedDate)
 1034  
             .append("finalizedDate", finalizedDate)
 1035  
             .append("appDocId", appDocId)
 1036  
             .toString();
 1037  
         }
 1038  
 
 1039  
         /**
 1040  
          * This overridden method ...
 1041  
          * 
 1042  
          * @see org.kuali.rice.kns.bo.BusinessObjectBase#toStringMapper()
 1043  
          */
 1044  
         @Override
 1045  
         protected LinkedHashMap toStringMapper() {
 1046  
                 // TODO chris - THIS METHOD NEEDS JAVADOCS
 1047  0
                 return null;
 1048  
         }
 1049  
 
 1050  
 }