View Javadoc

1   /*
2    * Copyright 2005-2007 The Kuali Foundation
3    *
4    *
5    * Licensed under the Educational Community License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    * http://www.opensource.org/licenses/ecl2.php
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.kuali.rice.kew.service;
18  
19  import java.util.Arrays;
20  import java.util.List;
21  
22  import org.apache.commons.lang.ObjectUtils;
23  import org.kuali.rice.core.resourceloader.GlobalResourceLoader;
24  import org.kuali.rice.kew.dto.ActionItemDTO;
25  import org.kuali.rice.kew.dto.ActionRequestDTO;
26  import org.kuali.rice.kew.dto.ActionTakenDTO;
27  import org.kuali.rice.kew.dto.DocumentContentDTO;
28  import org.kuali.rice.kew.dto.DocumentDetailDTO;
29  import org.kuali.rice.kew.dto.DocumentSearchCriteriaDTO;
30  import org.kuali.rice.kew.dto.DocumentSearchResultDTO;
31  import org.kuali.rice.kew.dto.DocumentStatusTransitionDTO;
32  import org.kuali.rice.kew.dto.DocumentTypeDTO;
33  import org.kuali.rice.kew.dto.ReportCriteriaDTO;
34  import org.kuali.rice.kew.dto.RouteHeaderDTO;
35  import org.kuali.rice.kew.dto.RouteNodeInstanceDTO;
36  import org.kuali.rice.kew.dto.RuleDTO;
37  import org.kuali.rice.kew.dto.RuleReportCriteriaDTO;
38  import org.kuali.rice.kew.dto.WorkflowAttributeDefinitionDTO;
39  import org.kuali.rice.kew.dto.WorkflowAttributeValidationErrorDTO;
40  import org.kuali.rice.kew.exception.WorkflowException;
41  import org.kuali.rice.kew.util.KEWConstants;
42  import org.kuali.rice.kim.bo.types.dto.AttributeSet;
43  
44  /**
45   * Convenience class for client applications to query workflow.  This class is one of two
46   * (Java) client interfaces to the KEW system (the other being {@link WorkflowDocument} class).
47   *
48   * <p>The first time an instance of this class is created, it will read the client configuration to
49   * determine how to connect to KEW.  To use this API, simply create a new instance using the
50   * empty constructor.
51   *
52   * @author Kuali Rice Team (rice.collab@kuali.org)
53   */
54  public class WorkflowInfo implements java.io.Serializable {
55  
56  	private static final long serialVersionUID = 3231835171780770399L;
57  
58  	/**
59       * Retrieves the WorkflowUtility proxy from the locator.  The locator will cache this for us.
60       */
61  	private WorkflowUtility getWorkflowUtility() throws WorkflowException {
62          WorkflowUtility workflowUtility = 
63          	(WorkflowUtility)GlobalResourceLoader.getService(KEWConstants.WORKFLOW_UTILITY_SERVICE);
64      	if (workflowUtility == null) {
65      		throw new WorkflowException("Could not locate the WorkflowUtility service.  Please ensure that KEW client is configured properly!");
66      	}
67      	return workflowUtility;
68  
69      }
70  
71      /**
72       * Returns the RouteHeaderVO of the specified document for the specified user
73       * @param principalId principalId as whom to obtain the route header VO
74       * @param routeHeaderId the id of the document whose route header VO to obtain
75       * @return the RouteHeaderVO of the specified document for the specified user
76       * @throws WorkflowException if an error occurs obtaining the route header VO
77       * @see WorkflowUtility#getRouteHeaderWithUser(String, Long)
78       */
79      public RouteHeaderDTO getRouteHeader(String principalId, Long routeHeaderId) throws WorkflowException {
80      	return getWorkflowUtility().getRouteHeaderWithPrincipal(principalId, routeHeaderId);
81      }
82      
83      public AttributeSet getActionsRequested(String principalId, Long documentId) throws WorkflowException {
84      	return getWorkflowUtility().getActionsRequested(principalId, documentId);
85      }
86  
87      /**
88       * Returns the RouteHeaderVO of the specified document
89       * @param routeHeaderId the id of the document whose route header VO to obtain
90       * @return the RouteHeaderVO of the specified document
91       * @throws WorkflowException if an error occurs obtaining the route header VO
92       * @see WorkflowUtility#getRouteHeader(Long)
93       */
94      public RouteHeaderDTO getRouteHeader(Long documentId) throws WorkflowException {
95      	return getWorkflowUtility().getRouteHeader(documentId);
96      }
97  
98      /**
99       * Returns the status of the document with the given ID.
100      *
101      * @since 0.9.1
102      * @throws WorkflowException if document cannot be found for the given ID or
103      * if the given document ID is null.
104      */
105     public String getDocumentStatus(Long documentId) throws WorkflowException {
106    		return getWorkflowUtility().getDocumentStatus(documentId);
107     }
108 
109     /**
110      * Returns the status of the document with the given ID.
111      *
112      * @since 0.9.1
113      * @throws WorkflowException if document cannot be found for the given ID or
114      * if the given document ID is null.
115      */
116     public DocumentStatusTransitionDTO[] getDocumentStatusTransitionHistory(Long documentId) throws WorkflowException {
117    		return getWorkflowUtility().getDocumentStatusTransitionHistory(documentId);
118     }
119 
120     /**
121      * Returns the DocumentType of the document with the specified id
122      * @param documentTypeId the id of the document whose document type we should return
123      * @return the DocumentTypeVO of the document with the specified id
124      * @throws WorkflowException if an error occurs obtaining the document type
125      * @see WorkflowUtility#getDocumentType(Long)
126      */
127     public DocumentTypeDTO getDocType(Long documentTypeId) throws WorkflowException {
128     	return getWorkflowUtility().getDocumentType(documentTypeId);
129     }
130 
131     /**
132      * Returns the DocumentType of the document type with the specified name
133      * @param documentTypeName the name of the document type whose DocumentType we should return
134      * @return the DocumentTypeVO of the document type with the specified name
135      * @throws WorkflowException if an error occurs obtaining the document type
136      * @see WorkflowUtility#getDocumentTypeByName(String)
137      */
138     public DocumentTypeDTO getDocType(String documentTypeName) throws WorkflowException {
139     	return getWorkflowUtility().getDocumentTypeByName(documentTypeName);
140     }
141 
142     /**
143      * Returns a new unique id to be used as a responsibility id
144      * @return a new unique id to be used as a responsibility id
145      * @throws WorkflowException if an error occurs obtaining a new responsibility id
146      * @see WorkflowUtility#getNewResponsibilityId()
147      */
148     public Long getNewResponsibilityId() throws WorkflowException {
149     	return getWorkflowUtility().getNewResponsibilityId();
150     }
151 
152     public Integer getUserActionItemCount(String principalId) throws WorkflowException {
153     	return getWorkflowUtility().getUserActionItemCount(principalId);
154     }
155     
156     public ActionItemDTO[] getActionItems(Long routeHeaderId) throws WorkflowException {
157     	return getWorkflowUtility().getAllActionItems(routeHeaderId);
158     }
159 
160     public ActionItemDTO[] getActionItems(Long routeHeaderId, String[] actionRequestedCodes) throws WorkflowException {
161     	return getWorkflowUtility().getActionItems(routeHeaderId, actionRequestedCodes);
162     }
163 
164     /**
165      * Returns the pending action requests of the document of the specified id
166      * @param routeHeaderId the id of the document whose action requests will be retrieved
167      * @return the pending action requests of the document of the specified id
168      * @throws WorkflowException if an error occurs obtaining the documents action requests
169      * @see WorkflowUtility#getActionRequests(Long)
170      */
171     public ActionRequestDTO[] getActionRequests(Long routeHeaderId) throws WorkflowException {
172     	return getWorkflowUtility().getAllActionRequests(routeHeaderId);
173     }
174 
175    /**
176     * Returns the pending action requests of the document of the specified id for the specified
177     * user and/or the specified node name.  If both user and node name are empty then will
178     * return all pending action requests.
179     * @param routeHeaderId the id of the document whose action requests will be retrieved
180     * @param nodeName the node name of the requests to be retrieved
181     * @param userId the user that the requests would be satisfied by
182     * @return the pending action requests of the document of the specified id
183     * @throws WorkflowException if an error occurs obtaining the documents action requests
184     * @see WorkflowUtility#getActionRequests(Long)
185     */
186    public ActionRequestDTO[] getActionRequests(Long routeHeaderId, String nodeName, String principalId) throws WorkflowException {
187 	   return getWorkflowUtility().getActionRequests(routeHeaderId, nodeName, principalId);
188    }
189 
190    /**
191 
192 
193     /**
194      * Returns the actions taken on the document of the specified id
195      * @param routeHeaderId the id of the document whose actions taken will be retrieved
196      * @return the actions taken on the document of the specified id
197      * @throws WorkflowException if an error occurs obtaining the actions taken
198      * @see WorkflowUtility#getActionsTaken(Long)
199      */
200     public ActionTakenDTO[] getActionsTaken(Long routeHeaderId) throws WorkflowException {
201     	return getWorkflowUtility().getActionsTaken(routeHeaderId);
202     }
203 
204     /**
205      * Returns whether the user is in the document's route log (whether an action request has been, or may be,
206      * generated for the user)
207      * @param routeHeaderId the id of the document to analyze
208      * @param userId the id of the user to check
209      * @param lookFuture whether to evaluate potential future requests
210      * @return whether the user is in the document's route log
211      * @throws WorkflowException if an error occurs determining whether the user is in the document's route log
212      * @see WorkflowUtility#isUserInRouteLog(Long, String, boolean)
213      */
214     public boolean isUserAuthenticatedByRouteLog(Long routeHeaderId, String principalId, boolean lookFuture) throws WorkflowException {
215     	return getWorkflowUtility().isUserInRouteLog(routeHeaderId, principalId, lookFuture);
216     }
217     
218     /**
219      * Returns whether the user is in the document's route log (whether an action request has been, or may be,
220      * generated for the user).  The flattenNodes boolean instructs the underlying Simulation Engine to perform
221      * a "flattened" evaluation or not and only takes effect if lookFuture is true.  When doing a "flattened"
222      * evaluation, all branches will be followed regardless of split and join logic built into the document type.
223      * 
224      * @param routeHeaderId the id of the document to analyze
225      * @param userId the id of the user to check
226      * @param lookFuture whether to evaluate potential future requests
227      * @return whether the user is in the document's route log
228      * @throws WorkflowException if an error occurs determining whether the user is in the document's route log
229      * @see WorkflowUtility#isUserInRouteLog(Long, String, boolean)
230      */
231     public boolean isUserAuthenticatedByRouteLog(Long routeHeaderId, String principalId, boolean lookFuture, boolean flattenNodes) throws WorkflowException {
232     	return getWorkflowUtility().isUserInRouteLogWithOptionalFlattening(routeHeaderId, principalId, lookFuture, flattenNodes);
233     }
234 
235     /**
236      * Returns whether the specified user is the final approver for the document
237      * @param routeHeaderId the id of document to check
238      * @param userId the id of the user to check
239      * @return whether the specified user is the final approver for the document
240      * @throws WorkflowException if an error occurs determining whether the user is the final approver on the document
241      * @see WorkflowUtility#isFinalApprover(Long, String)
242      */
243     public boolean isFinalApprover(Long routeHeaderId, String principalId) throws WorkflowException {
244     	return getWorkflowUtility().isFinalApprover(routeHeaderId, principalId);
245     }
246 
247     /**
248      * Validate the WorkflowAttributeDefinition against it's attribute on the server.  This will validate
249      * the inputs that will eventually become xml.
250      *
251      * Only applies to attributes implementing WorkflowAttributeXmlValidator.
252      *
253      * @param attributeDefinition the attribute definition to validate
254      * @return WorkflowAttributeValidationErrorVO[] of error from the attribute
255      * @throws WorkflowException when attribute doesn't implement WorkflowAttributeXmlValidator
256      * @see WorkflowUtility#validateWorkflowAttributeDefinitionVO(WorkflowAttributeDefinitionDTO)
257      */
258     public WorkflowAttributeValidationErrorDTO[] validAttributeDefinition(WorkflowAttributeDefinitionDTO attributeDefinition) throws WorkflowException {
259     	return getWorkflowUtility().validateWorkflowAttributeDefinitionVO(attributeDefinition);
260     }
261 
262     // WORKFLOW 2.3: new methods
263 
264     /**
265      * Runs a "rule report" give a rule report criteria.
266      * @param ruleReportCriteria the criteria for the rule report
267      * @return an array of RuleVO representing rules that will fire under the specified criteria
268      * @see WorkflowUtility#ruleReport(RuleReportCriteriaDTO)
269      */
270     public RuleDTO[] ruleReport(RuleReportCriteriaDTO ruleReportCriteria) throws WorkflowException {
271     	return getWorkflowUtility().ruleReport(ruleReportCriteria);
272     }
273 
274     // WORKFLOW 2.1: new methods
275 
276     /**
277      * Returns a document detail VO representing the route header along with action requests, actions taken,
278      * and route node instances.
279      * @param documentId id of the document whose details should be returned
280      * @return Returns a document detail VO representing the route header along with action requests, actions taken, and route node instances.
281      * @throws WorkflowException
282      * @see WorkflowUtility#getDocumentDetail(Long)
283      */
284     public DocumentDetailDTO getDocumentDetail(Long documentId) throws WorkflowException {
285     	return getWorkflowUtility().getDocumentDetail(documentId);
286     }
287 
288     /**
289      * Returns a node instance of the specified note instance id
290      * @param nodeInstanceId the id of the node instance to return
291      * @return a node instance of the specified note instance id
292      * @throws WorkflowException if an error occurs obtaining the node instance
293      * @see WorkflowUtility#getNodeInstance(Long)
294      */
295     public RouteNodeInstanceDTO getNodeInstance(Long nodeInstanceId) throws WorkflowException {
296     	return getWorkflowUtility().getNodeInstance(nodeInstanceId);
297     }
298 
299     /**
300      * Returns the route node instances that have been created so far during the life of the specified document.  This includes
301      * all previous instances which have already been processed and are no longer active.
302      * @param routeHeaderId the id of the document whose route node instances should be returned
303      * @return the route node instances that have been created so far during the life of this document
304      * @throws WorkflowException if there is an error getting the route node instances for the document
305      * @see WorkflowUtility#getDocumentRouteNodeInstances(Long)
306      */
307     public RouteNodeInstanceDTO[] getDocumentRouteNodeInstances(Long routeHeaderId) throws WorkflowException {
308     	return getWorkflowUtility().getDocumentRouteNodeInstances(routeHeaderId);
309     }
310 
311     /**
312      * Returns all active node instances on the document.
313      * @param routeHeaderId id of the document whose active node instances should be returned
314      * @return all active node instances on the document
315      * @throws WorkflowException if there is an error obtaining the currently active nodes on the document
316      * @see WorkflowUtility#getActiveNodeInstances(Long)
317      */
318     public RouteNodeInstanceDTO[] getActiveNodeInstances(Long routeHeaderId) throws WorkflowException {
319     	return getWorkflowUtility().getActiveNodeInstances(routeHeaderId);
320     }
321 
322     /**
323      * Returns all node instances on the document which have no successor.
324      * @param routeHeaderId id of the document whose terminal node instances should be returned
325      * @return all terminal node instances of the document
326      * @throws WorkflowException if there is an error obtaining the terminal node instances on the document
327      * @see WorkflowUtility#getTerminalNodeInstances(Long)
328      */
329     public RouteNodeInstanceDTO[] getTerminalNodeInstances(Long routeHeaderId) throws WorkflowException {
330     	return getWorkflowUtility().getTerminalNodeInstances(routeHeaderId);
331     }
332     
333     /**
334      * Returns the current node instances on the document.  If the document has active nodes, those will
335      * be returned.  Otherwise, all terminal nodes will be returned.
336      * @param routeHeaderId id of the document whose current node instances should be returned
337      * @return all current node instances of the document
338      * @throws WorkflowException if there is an error obtaining the current node instances on the document
339      * @see WorkflowUtility#getCurrentNodeInstances(Long)
340      */
341     public RouteNodeInstanceDTO[] getCurrentNodeInstances(Long routeHeaderId) throws WorkflowException {
342     	return getWorkflowUtility().getCurrentNodeInstances(routeHeaderId);
343     }
344     
345     /**
346      * Returns names of all current nodes the document is currently at.  If the document has active nodes, those
347      * will be returned.  Otherwise, the document's terminal nodes will be returned.
348      *
349      * @return names of all current nodes the document is currently at.
350      * @throws WorkflowException if there is an error obtaining the current nodes on the document
351      * @see WorkflowUtility#getCurrentNodeInstances(Long)
352      */
353     public String[] getCurrentNodeNames(Long documentId) throws WorkflowException {
354     	RouteNodeInstanceDTO[] currentNodeInstances = getWorkflowUtility().getCurrentNodeInstances(documentId);
355     	String[] nodeNames = new String[(currentNodeInstances == null ? 0 : currentNodeInstances.length)];
356     	for (int index = 0; index < currentNodeInstances.length; index++) {
357     		nodeNames[index] = currentNodeInstances[index].getName();
358     	}
359     	return nodeNames;
360     }
361 
362     /**
363      * Re-resolves the specified role on the document, and refreshes any pending action requests.
364      * @param documentTypeName the type of the document for which to re-resolve roles
365      * @param roleName the role name to re-resolve
366      * @param qualifiedRoleNameLabel the qualified role name label
367      * @throws WorkflowException if an error occurs re-resolving the role
368      * @see WorkflowUtility#reResolveRole(String, String, String)
369      */
370     public void reResolveRole(String documentTypeName, String roleName, String qualifiedRoleNameLabel) throws WorkflowException {
371     	getWorkflowUtility().reResolveRole(documentTypeName, roleName, qualifiedRoleNameLabel);
372     }
373 
374     /**
375      * Re-resolves the specified role on the document, and refreshes any pending action requests.
376      * @param documentId the id of the document for which to re-resolve roles
377      * @param roleName the role name to re-resolve
378      * @param qualifiedRoleNameLabel the qualified role name label
379      * @throws WorkflowException if an error occurs re-resolving the role
380      * @see WorkflowUtility#reResolveRoleByDocumentId(Long, String, String)
381      */
382     public void reResolveRole(Long documentId, String roleName, String qualifiedRoleNameLabel) throws WorkflowException {
383     	getWorkflowUtility().reResolveRoleByDocumentId(documentId, roleName, qualifiedRoleNameLabel);
384     }
385 
386     /**
387      * Runs a "routing report"
388      * @param reportCriteria routing report criteria
389      * @return DocumentDetailVO detailing the actionrequests that would be generated under the specified criteria
390      * @see WorkflowUtility#routingReport(ReportCriteriaDTO)
391      */
392     public DocumentDetailDTO routingReport(ReportCriteriaDTO reportCriteria) throws WorkflowException {
393     	return getWorkflowUtility().routingReport(reportCriteria);
394     }
395     
396     /**
397      * Returns the application document id for the document with the given id.
398      *
399      * @param documentId the document id of the document for which to fetch the application document id
400      * @return the application document of the document with the given id or null if the document does not have an application document id
401      */
402     public String getAppDocId(Long documentId)  throws WorkflowException {
403     	return getWorkflowUtility().getAppDocId(documentId);
404     }
405 
406     /**
407      * Returns whether the specified user is the last approver at the specified node name
408      * @param routeHeaderId the id of document to check
409      * @param userId the id of the user to check
410      * @param nodeName name of node to check
411      * @return whether the specified user is the last approver at the specified node name
412      * @throws WorkflowException if an error occurs determining whether the user is the last approver at the specified node
413      * @see WorkflowUtility#isLastApproverAtNode(Long, String, String)
414      */
415     public boolean isLastApproverAtNode(Long routeHeaderId, String principalId, String nodeName) throws WorkflowException {
416     	return getWorkflowUtility().isLastApproverAtNode(routeHeaderId, principalId, nodeName);
417     }
418 
419     /**
420      * Returns whether the specified node on the specified document type would produce approve or complete requests
421      * @param docType the type of the document to check
422      * @param docContent the content to use
423      * @param nodeName the node to check
424      * @return whether the specified node on the specified document type would produce approve or complete requests
425      * @throws WorkflowException if an error occurs
426      * @see WorkflowUtility#routeNodeHasApproverActionRequest(String, String, String)
427      */
428     public boolean routeNodeHasApproverActionRequest(String docType, String docContent, String nodeName) throws WorkflowException {
429     	return getWorkflowUtility().routeNodeHasApproverActionRequest(docType, docContent, nodeName);
430     }
431 
432     /**
433      * This method allows a document search to be executed just as would occur from the User Interface using the given user as
434      * the searching user
435      * 
436      * @param userId - user to use when executing the search (for security filtering purposes)
437      * @param criteriaVO - criteria to use for the search
438      * @return a {@link DocumentSearchResultDTO} object containing a list of search result columns and data rows
439      * @throws WorkflowException
440      */
441     public DocumentSearchResultDTO performDocumentSearch(String principalId, DocumentSearchCriteriaDTO criteriaVO) throws WorkflowException {
442     	return getWorkflowUtility().performDocumentSearchWithPrincipal(principalId, criteriaVO);
443     }
444 
445     /**
446      * This method allows a document search to be executed just as would occur from the User Interface
447      * 
448      * @param criteriaVO - criteria to use for the search
449      * @return a {@link DocumentSearchResultDTO} object containing a list of search result columns and data rows
450      * @throws WorkflowException
451      */
452     public DocumentSearchResultDTO performDocumentSearch(DocumentSearchCriteriaDTO criteriaVO) throws WorkflowException {
453     	return getWorkflowUtility().performDocumentSearch(criteriaVO);
454     }
455 
456     /**
457      * Returns the document content VO of the specified document
458      * @param routeHeaderId the id of the document whose content should be returned
459      * @return the document content VO of the specified document
460      * @throws WorkflowException if an error occurs obtaining the document content
461      * @see WorkflowUtility#getDocumentContent(Long)
462      */
463     public DocumentContentDTO getDocumentContent(Long routeHeaderId) throws WorkflowException {
464     	return getWorkflowUtility().getDocumentContent(routeHeaderId);
465     }
466 
467     /**
468      * Returns names of nodes already traversed
469      * @param documentId id of the document to check
470      * @return names of nodes already traversed
471      * @throws WorkflowException if an error occurs
472      * @see WorkflowUtility#getPreviousRouteNodeNames(Long)
473      */
474     public String[] getPreviousRouteNodeNames(Long documentId) throws WorkflowException {
475     	return getWorkflowUtility().getPreviousRouteNodeNames(documentId);
476     }
477 
478     /**
479      * Checks whether a document would product at least one action request under the specified criteria
480      * @param reportCriteriaDTO criteria under which to perform the check
481      * @param actionRequestedCodes the types of action requests to check for
482      * @param ignoreCurrentActionRequests determines if method should look only at simulation generated requests 
483      *        or both simulation generated requests and requests that are currently active on the document
484      * @return whether a document would product at least one action request under the specified criteria
485      * @throws WorkflowException if an error occurs
486      * @see WorkflowUtility#documentWillHaveAtLeastOneActionRequest(ReportCriteriaDTO, String[], boolean)
487      */
488     public boolean documentWillHaveAtLeastOneActionRequest(ReportCriteriaDTO reportCriteriaDTO, String[] actionRequestedCodes, boolean ignoreCurrentActionRequests) throws WorkflowException {
489     	return getWorkflowUtility().documentWillHaveAtLeastOneActionRequest(reportCriteriaDTO, actionRequestedCodes, ignoreCurrentActionRequests);
490     }
491 
492     /**
493      * @deprecated use {@link #documentWillHaveAtLeastOneActionRequest(ReportCriteriaDTO, String[], boolean)} instead
494      * 
495      * This method assumes both existing and generated requests should be taken into account
496      */
497     public boolean documentWillHaveAtLeastOneActionRequest(ReportCriteriaDTO reportCriteriaDTO, String[] actionRequestedCodes) throws WorkflowException {
498     	return getWorkflowUtility().documentWillHaveAtLeastOneActionRequest(reportCriteriaDTO, actionRequestedCodes, false);
499     }
500 
501     // DEPRECATED: as of Workflow 2.1
502 
503     /**
504      * @deprecated use {@link #isLastApproverAtNode(Long, String, String) instead
505      */
506     protected boolean isLastApproverInRouteLevel(Long routeHeaderId, String principalId, Integer routeLevel) throws WorkflowException {
507     	return getWorkflowUtility().isLastApproverInRouteLevel(routeHeaderId, principalId, routeLevel);
508     }
509 
510     /**
511      * @deprecated use {@link #routeNodeHasApproverActionRequest(String, String, String)}
512      */
513     protected boolean routeLevelHasApproverActionRequest(String docType, String docContent, Integer routeLevel) throws WorkflowException {
514     	return getWorkflowUtility().routeLevelHasApproverActionRequest(docType, docContent, routeLevel);
515     }
516     
517     /**
518      * 
519      * This method gets a list of ids of all principals who have a pending action request for a document.
520      * 
521      * @param actionRequestedCd
522      * @param routeHeaderId
523      * @return
524      * @throws WorkflowException
525      */
526 	public List<String> getPrincipalIdsWithPendingActionRequestByActionRequestedAndDocId(String actionRequestedCd, Long routeHeaderId) throws WorkflowException {
527 		String[] results = getWorkflowUtility().getPrincipalIdsWithPendingActionRequestByActionRequestedAndDocId(actionRequestedCd, routeHeaderId);
528 		if (ObjectUtils.equals(null, results)) {
529 			return null;
530 		}
531 		return (List<String>) Arrays.asList(results);
532     }
533 
534     /**
535      * This method gets a list of ids of all principals in the route log - 
536      * - initiators, 
537      * - people who have taken action, 
538      * - people with a pending action request, 
539 	 * - people who will receive an action request for the document in question
540 	 * 
541      * @param routeHeaderId
542      * @param lookFuture
543      * @return
544      * @throws WorkflowException
545      */
546 	public List<String> getPrincipalIdsInRouteLog(Long routeHeaderId, boolean lookFuture) throws WorkflowException {
547 		String[] results = getWorkflowUtility().getPrincipalIdsInRouteLog(routeHeaderId, lookFuture);
548 		if (ObjectUtils.equals(null, results)) {
549 			return null;
550 		}
551 		return (List<String>) Arrays.asList(results);
552     }
553     
554     public String getDocumentInitiatorPrincipalId( Long routeHeaderId ) throws WorkflowException {
555     	return getWorkflowUtility().getDocumentInitiatorPrincipalId(routeHeaderId);
556     }
557     public String getDocumentRoutedByPrincipalId( Long routeHeaderId ) throws WorkflowException {
558     	return getWorkflowUtility().getDocumentRoutedByPrincipalId(routeHeaderId);
559     }
560     
561     public boolean hasRouteNode(String documentTypeName, String routeNodeName) throws WorkflowException {
562     	return getWorkflowUtility().hasRouteNode(documentTypeName, routeNodeName);
563     }
564     
565     public boolean isCurrentActiveDocumentType(String documentTypeName) throws WorkflowException {
566     	return getWorkflowUtility().isCurrentActiveDocumentType(documentTypeName);
567     }
568     
569 }