Coverage Report - org.kuali.rice.kew.service.impl.WorkflowUtilityWebServiceImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
WorkflowUtilityWebServiceImpl
0%
0/639
0%
0/372
4.696
 
 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.impl;
 18  
 
 19  
 import java.math.BigDecimal;
 20  
 import java.sql.Timestamp;
 21  
 import java.util.ArrayList;
 22  
 import java.util.Arrays;
 23  
 import java.util.Collection;
 24  
 import java.util.Collections;
 25  
 import java.util.Date;
 26  
 import java.util.HashMap;
 27  
 import java.util.HashSet;
 28  
 import java.util.Iterator;
 29  
 import java.util.List;
 30  
 import java.util.Map;
 31  
 import java.util.Set;
 32  
 
 33  
 import javax.jws.WebService;
 34  
 
 35  
 import org.apache.commons.lang.StringUtils;
 36  
 import org.apache.log4j.Logger;
 37  
 import org.kuali.rice.core.exception.RiceRuntimeException;
 38  
 import org.kuali.rice.core.resourceloader.GlobalResourceLoader;
 39  
 import org.kuali.rice.kew.actionitem.ActionItem;
 40  
 import org.kuali.rice.kew.actionrequest.ActionRequestValue;
 41  
 import org.kuali.rice.kew.actionrequest.KimPrincipalRecipient;
 42  
 import org.kuali.rice.kew.actionrequest.Recipient;
 43  
 import org.kuali.rice.kew.actiontaken.ActionTakenValue;
 44  
 import org.kuali.rice.kew.definition.AttributeDefinition;
 45  
 import org.kuali.rice.kew.docsearch.DocSearchCriteriaDTO;
 46  
 import org.kuali.rice.kew.docsearch.DocumentSearchResultComponents;
 47  
 import org.kuali.rice.kew.doctype.bo.DocumentType;
 48  
 import org.kuali.rice.kew.documentlink.DocumentLink;
 49  
 import org.kuali.rice.kew.dto.ActionItemDTO;
 50  
 import org.kuali.rice.kew.dto.ActionRequestDTO;
 51  
 import org.kuali.rice.kew.dto.ActionTakenDTO;
 52  
 import org.kuali.rice.kew.dto.DTOConverter;
 53  
 import org.kuali.rice.kew.dto.DocumentContentDTO;
 54  
 import org.kuali.rice.kew.dto.DocumentDetailDTO;
 55  
 import org.kuali.rice.kew.dto.DocumentLinkDTO;
 56  
 import org.kuali.rice.kew.dto.DocumentSearchCriteriaDTO;
 57  
 import org.kuali.rice.kew.dto.DocumentSearchResultDTO;
 58  
 import org.kuali.rice.kew.dto.DocumentStatusTransitionDTO;
 59  
 import org.kuali.rice.kew.dto.DocumentTypeDTO;
 60  
 import org.kuali.rice.kew.dto.PropertyDefinitionDTO;
 61  
 import org.kuali.rice.kew.dto.ReportCriteriaDTO;
 62  
 import org.kuali.rice.kew.dto.RouteHeaderDTO;
 63  
 import org.kuali.rice.kew.dto.RouteNodeInstanceDTO;
 64  
 import org.kuali.rice.kew.dto.RuleDTO;
 65  
 import org.kuali.rice.kew.dto.RuleExtensionDTO;
 66  
 import org.kuali.rice.kew.dto.RuleReportCriteriaDTO;
 67  
 import org.kuali.rice.kew.dto.WorkflowAttributeDefinitionDTO;
 68  
 import org.kuali.rice.kew.dto.WorkflowAttributeValidationErrorDTO;
 69  
 import org.kuali.rice.kew.engine.ActivationContext;
 70  
 import org.kuali.rice.kew.engine.CompatUtils;
 71  
 import org.kuali.rice.kew.engine.RouteContext;
 72  
 import org.kuali.rice.kew.engine.node.KeyValuePair;
 73  
 import org.kuali.rice.kew.engine.node.RouteNode;
 74  
 import org.kuali.rice.kew.engine.node.RouteNodeInstance;
 75  
 import org.kuali.rice.kew.engine.simulation.SimulationCriteria;
 76  
 import org.kuali.rice.kew.engine.simulation.SimulationEngine;
 77  
 import org.kuali.rice.kew.engine.simulation.SimulationResults;
 78  
 import org.kuali.rice.kew.exception.WorkflowException;
 79  
 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
 80  
 import org.kuali.rice.kew.routeheader.DocumentStatusTransition;
 81  
 import org.kuali.rice.kew.rule.FlexRM;
 82  
 import org.kuali.rice.kew.rule.RuleBaseValues;
 83  
 import org.kuali.rice.kew.rule.WorkflowAttribute;
 84  
 import org.kuali.rice.kew.rule.WorkflowAttributeValidationError;
 85  
 import org.kuali.rice.kew.rule.WorkflowAttributeXmlValidator;
 86  
 import org.kuali.rice.kew.rule.xmlrouting.GenericXMLRuleAttribute;
 87  
 import org.kuali.rice.kew.service.KEWServiceLocator;
 88  
 import org.kuali.rice.kew.service.WorkflowUtility;
 89  
 import org.kuali.rice.kew.util.KEWConstants;
 90  
 import org.kuali.rice.kew.util.KEWWebServiceConstants;
 91  
 import org.kuali.rice.kew.util.Utilities;
 92  
 import org.kuali.rice.kew.web.session.UserSession;
 93  
 import org.kuali.rice.kim.bo.entity.KimPrincipal;
 94  
 import org.kuali.rice.kim.bo.types.dto.AttributeSet;
 95  
 import org.kuali.rice.kim.service.KIMServiceLocator;
 96  
 import org.kuali.rice.kns.util.KNSConstants;
 97  
 import org.kuali.rice.kns.util.ObjectUtils;
 98  
 
 99  
 @SuppressWarnings({"unchecked"})
 100  
 @WebService(endpointInterface = KEWWebServiceConstants.WorkflowUtility.INTERFACE_CLASS,
 101  
         serviceName = KEWWebServiceConstants.WorkflowUtility.WEB_SERVICE_NAME,
 102  
         portName = KEWWebServiceConstants.WorkflowUtility.WEB_SERVICE_PORT,
 103  
         targetNamespace = KEWWebServiceConstants.MODULE_TARGET_NAMESPACE)
 104  0
 public class WorkflowUtilityWebServiceImpl implements WorkflowUtility {
 105  
 
 106  0
     private static final Logger LOG = Logger.getLogger(WorkflowUtilityWebServiceImpl.class);
 107  
 
 108  
     public RouteHeaderDTO getRouteHeaderWithPrincipal(String principalId, Long documentId) throws WorkflowException {
 109  0
         if (documentId == null) {
 110  0
             LOG.error("null routeHeaderId passed in.  Throwing RuntimeExcpetion");
 111  0
             throw new RuntimeException("Null documentId passed in.");
 112  
         }
 113  0
         if (principalId == null) {
 114  0
             LOG.error("null principalId passed in.");
 115  0
             throw new RuntimeException("null principalId passed in");
 116  
         }
 117  0
         if ( LOG.isDebugEnabled() ) {
 118  0
             LOG.debug("Fetching RouteHeaderVO [id="+documentId+", user="+principalId+"]");
 119  
         }
 120  0
         DocumentRouteHeaderValue document = loadDocument(documentId);
 121  0
         RouteHeaderDTO routeHeaderVO = DTOConverter.convertRouteHeader(document, principalId);
 122  0
         if (routeHeaderVO == null) {
 123  0
                 LOG.error("Returning null RouteHeaderVO [id=" + documentId + ", user=" + principalId + "]");
 124  
         }
 125  0
         if ( LOG.isDebugEnabled() ) {
 126  0
             LOG.debug("Returning RouteHeaderVO [id=" + documentId + ", user=" + principalId + "]");
 127  
         }
 128  0
         return routeHeaderVO;
 129  
     }
 130  
 
 131  
     public AttributeSet getActionsRequested(String principalId, Long documentId) {
 132  0
         if (documentId == null) {
 133  0
             LOG.error("null routeHeaderId passed in.  Throwing RuntimeExcpetion");
 134  0
             throw new RuntimeException("Null documentId passed in.");
 135  
         }
 136  0
         if (principalId == null) {
 137  0
             LOG.error("null principalId passed in.");
 138  0
             throw new RuntimeException("null principalId passed in");
 139  
         }
 140  0
         if ( LOG.isDebugEnabled() ) {
 141  0
             LOG.debug("Fetching DocumentRouteHeaderValue [id="+documentId+", user="+principalId+"]");
 142  
         }
 143  0
         DocumentRouteHeaderValue document = loadDocument(documentId);
 144  0
         return KEWServiceLocator.getActionRequestService().getActionsRequested(document, principalId, true);
 145  
     }
 146  
 
 147  
     public RouteHeaderDTO getRouteHeader(Long documentId) throws WorkflowException {
 148  0
         if (documentId == null) {
 149  0
             LOG.error("null routeHeaderId passed in.");
 150  0
             throw new RuntimeException("null routeHeaderId passed in");
 151  
         }
 152  0
         if ( LOG.isDebugEnabled() ) {
 153  0
             LOG.debug("Fetching RouteHeaderVO [id="+documentId+"]");
 154  
         }
 155  0
         DocumentRouteHeaderValue document = loadDocument(documentId);
 156  
         
 157  0
         UserSession userSession = UserSession.getAuthenticatedUser();
 158  0
         String principalId = null;
 159  0
         if (userSession != null) { // get the principalId if we can
 160  0
                 principalId = userSession.getPrincipalId();
 161  
         }
 162  
         
 163  0
         RouteHeaderDTO routeHeaderVO = DTOConverter.convertRouteHeader(document, principalId);
 164  0
         if (routeHeaderVO == null) {
 165  0
                 LOG.error("Returning null RouteHeaderVO [id=" + documentId + "]");
 166  
         }
 167  0
         if ( LOG.isDebugEnabled() ) {
 168  0
             LOG.debug("Returning RouteHeaderVO [id=" + documentId + "]");
 169  
         }
 170  0
         return routeHeaderVO;
 171  
     }
 172  
 
 173  
     public String getDocumentStatus(Long documentId) throws WorkflowException {
 174  0
         if (documentId == null) {
 175  0
             LOG.error("null documentId passed in.");
 176  0
             throw new IllegalArgumentException("null documentId passed in");
 177  
         }
 178  0
         String documentStatus = KEWServiceLocator.getRouteHeaderService().getDocumentStatus(documentId);
 179  0
         if (StringUtils.isEmpty(documentStatus)) {
 180  0
             throw new WorkflowException("Could not locate a document with the ID " + documentId);
 181  
         }
 182  0
         return documentStatus;
 183  
     }
 184  
 
 185  
     public DocumentDetailDTO getDocumentDetail(Long documentId) throws WorkflowException {
 186  0
         if (documentId == null) {
 187  0
             LOG.error("null documentId passed in.");
 188  0
             throw new RuntimeException("null documentId passed in");
 189  
         }
 190  0
         if ( LOG.isDebugEnabled() ) {
 191  0
                 LOG.debug("Fetching DocumentDetailVO [id="+documentId+"]");
 192  
         }
 193  0
         DocumentRouteHeaderValue document = loadDocument(documentId);
 194  0
         DocumentDetailDTO documentDetailVO = DTOConverter.convertDocumentDetail(document);
 195  0
         if (documentDetailVO == null) {
 196  0
                 LOG.error("Returning null DocumentDetailVO [id=" + documentId + "]");
 197  
         }
 198  0
         if ( LOG.isDebugEnabled() ) {
 199  0
                 LOG.debug("Returning DocumentDetailVO [id=" + documentId + "]");
 200  
         }
 201  0
         return documentDetailVO;
 202  
     }
 203  
 
 204  
     public RouteNodeInstanceDTO getNodeInstance(Long nodeInstanceId) throws WorkflowException {
 205  0
         if (nodeInstanceId == null) {
 206  0
             LOG.error("null nodeInstanceId passed in.");
 207  0
             throw new RuntimeException("null nodeInstanceId passed in");
 208  
         }
 209  0
         if ( LOG.isDebugEnabled() ) {
 210  0
                 LOG.debug("Fetching RouteNodeInstanceVO [id="+nodeInstanceId+"]");
 211  
         }
 212  0
         RouteNodeInstance nodeInstance = KEWServiceLocator.getRouteNodeService().findRouteNodeInstanceById(nodeInstanceId);
 213  0
         return DTOConverter.convertRouteNodeInstance(nodeInstance);
 214  
     }
 215  
 
 216  
     public DocumentTypeDTO getDocumentType(Long documentTypeId) throws WorkflowException {
 217  0
         if (documentTypeId == null) {
 218  0
             LOG.error("null documentTypeId passed in.");
 219  0
             throw new RuntimeException("null documentTypeId passed in.");
 220  
         }
 221  0
         if ( LOG.isDebugEnabled() ) {
 222  0
                 LOG.debug("Fetching DocumentTypeVO [documentTypeId="+documentTypeId+"]");
 223  
         }
 224  0
         return KEWServiceLocator.getDocumentTypeService().getDocumentTypeVO(documentTypeId);
 225  
     }
 226  
 
 227  
     public DocumentTypeDTO getDocumentTypeByName(String documentTypeName) throws WorkflowException {
 228  0
         if (documentTypeName == null) {
 229  0
             LOG.error("null documentTypeName passed in.");
 230  0
             throw new RuntimeException("null documentTypeName passed in");
 231  
         }
 232  0
         if ( LOG.isDebugEnabled() ) {
 233  0
                 LOG.debug("Fetching DocumentTypeVO [documentTypeName="+documentTypeName+"]");
 234  
         }
 235  0
         DocumentTypeDTO documentType = KEWServiceLocator.getDocumentTypeService().getDocumentTypeVO(documentTypeName);
 236  0
         return documentType;
 237  
     }
 238  
 
 239  
     public Long getNewResponsibilityId() {
 240  0
             LOG.debug("Getting new responsibility id.");
 241  0
         Long rid = KEWServiceLocator.getResponsibilityIdService().getNewResponsibilityId();
 242  0
         if ( LOG.isDebugEnabled() ) {
 243  0
                 LOG.debug("returning responsibility Id " + rid);
 244  
         }
 245  0
         return rid;
 246  
     }
 247  
 
 248  
     public Integer getUserActionItemCount(String principalId) throws WorkflowException {
 249  0
         return Integer.valueOf(KEWServiceLocator.getActionListService().getCount(principalId));
 250  
     }
 251  
 
 252  
         public ActionItemDTO[] getActionItemsForPrincipal(String principalId) throws WorkflowException {
 253  
         //added by Derek
 254  0
         Collection actionItems = KEWServiceLocator.getActionListService().getActionList(principalId, null);
 255  0
         ActionItemDTO[] actionItemVOs = new ActionItemDTO[actionItems.size()];
 256  0
         int i = 0;
 257  0
         for (Iterator iterator = actionItems.iterator(); iterator.hasNext(); i++) {
 258  0
             ActionItem actionItem = (ActionItem) iterator.next();
 259  0
             actionItemVOs[i] = DTOConverter.convertActionItem(actionItem);
 260  
         }
 261  0
         return actionItemVOs;
 262  
     }
 263  
 
 264  
     public ActionItemDTO[] getAllActionItems(Long routeHeaderId) throws WorkflowException {
 265  0
         Collection actionItems = KEWServiceLocator.getActionListService().getActionListForSingleDocument(routeHeaderId);
 266  0
         ActionItemDTO[] actionItemVOs = new ActionItemDTO[actionItems.size()];
 267  0
         int i = 0;
 268  0
         for (Iterator iterator = actionItems.iterator(); iterator.hasNext(); i++) {
 269  0
             ActionItem actionItem = (ActionItem) iterator.next();
 270  0
             actionItemVOs[i] = DTOConverter.convertActionItem(actionItem);
 271  
         }
 272  0
         return actionItemVOs;
 273  
     }
 274  
 
 275  
     public ActionItemDTO[] getActionItems(Long routeHeaderId, String[] actionRequestedCodes) throws WorkflowException {
 276  0
         List<String> actionRequestedCds = Arrays.asList(actionRequestedCodes);
 277  0
         ActionItemDTO[] actionItems = getAllActionItems(routeHeaderId);
 278  0
         List<ActionItemDTO> matchingActionitems = new ArrayList<ActionItemDTO>();
 279  0
         for (int i = 0; i < actionItems.length; i++) {
 280  0
             ActionItemDTO actionItemVO = actionItems[i];
 281  0
             if (actionRequestedCds.contains(actionItemVO.getActionRequestCd())) {
 282  0
                 matchingActionitems.add(actionItemVO);
 283  
             }
 284  
         }
 285  0
         ActionItemDTO[] returnActionItems = new ActionItemDTO[matchingActionitems.size()];
 286  0
         int j = 0;
 287  0
         for (ActionItemDTO actionItemVO : matchingActionitems) {
 288  0
             returnActionItems[j] = actionItemVO;
 289  0
             j++;
 290  
         }
 291  0
         return returnActionItems;
 292  
     }
 293  
 
 294  
     public ActionRequestDTO[] getAllActionRequests(Long routeHeaderId) throws WorkflowException {
 295  0
         return getActionRequests(routeHeaderId, null, null);
 296  
     }
 297  
 
 298  
     /**
 299  
      * Returns a flattened list of ActionRequests which match the given criteria.
 300  
      * Because the list is flattened, that means that all children requests from
 301  
      * all graphs are returned in the top-level list.
 302  
      */
 303  
     public ActionRequestDTO[] getActionRequests(Long routeHeaderId, String nodeName, String principalId) throws WorkflowException {
 304  0
         if (routeHeaderId == null) {
 305  0
             LOG.error("null routeHeaderId passed in.");
 306  0
             throw new RuntimeException("null routeHeaderId passed in.");
 307  
         }
 308  0
         if ( LOG.isDebugEnabled() ) {
 309  0
                 LOG.debug("Fetching ActionRequestVOs [docId="+routeHeaderId+"]");
 310  
         }
 311  0
         List actionRequests = KEWServiceLocator.getActionRequestService().findAllActionRequestsByRouteHeaderId(routeHeaderId);
 312  0
         List matchingActionRequests = new ArrayList();
 313  0
         for (Iterator iterator = actionRequests.iterator(); iterator.hasNext();) {
 314  0
             ActionRequestValue actionRequestValue = (ActionRequestValue) iterator.next();
 315  0
             if (actionRequestMatches(actionRequestValue, nodeName, principalId)) {
 316  0
                 matchingActionRequests.add(actionRequestValue);
 317  
             }
 318  0
         }
 319  0
         ActionRequestDTO[] actionRequestVOs = new ActionRequestDTO[matchingActionRequests.size()];
 320  0
         int i = 0;
 321  0
         for (Iterator iter = matchingActionRequests.iterator(); iter.hasNext(); i++) {
 322  0
             ActionRequestValue actionRequest = (ActionRequestValue) iter.next();
 323  0
             actionRequestVOs[i] = DTOConverter.convertActionRequest(actionRequest);
 324  
         }
 325  0
         return actionRequestVOs;
 326  
     }
 327  
 
 328  
     private boolean actionRequestMatches(ActionRequestValue actionRequest, String nodeName, String principalId) throws WorkflowException {
 329  0
         boolean matchesUserId = true;  // assume a match in case user is empty
 330  0
         boolean matchesNodeName = true;  // assume a match in case node name is empty
 331  0
         if (StringUtils.isNotBlank(nodeName)) {
 332  0
             matchesNodeName = nodeName.equals(actionRequest.getPotentialNodeName());
 333  
         }
 334  0
         if (principalId != null) {
 335  0
             matchesUserId = actionRequest.isRecipientRoutedRequest(principalId);
 336  
         }
 337  0
         return matchesNodeName && matchesUserId;
 338  
     }
 339  
 
 340  
     public ActionTakenDTO[] getActionsTaken(Long routeHeaderId) throws WorkflowException {
 341  0
         if (routeHeaderId == null) {
 342  0
             LOG.error("null routeHeaderId passed in.");
 343  0
             throw new RuntimeException("null routeHeaderId passed in.");
 344  
         }
 345  0
         if ( LOG.isDebugEnabled() ) {
 346  0
                 LOG.debug("Fetching ActionTakenVOs [docId="+routeHeaderId+"]");
 347  
         }
 348  0
         Collection actionsTaken = KEWServiceLocator.getActionTakenService().findByRouteHeaderId(routeHeaderId);
 349  0
         ActionTakenDTO[] actionTakenVOs = new ActionTakenDTO[actionsTaken.size()];
 350  0
         int i = 0;
 351  0
         for (Iterator iter = actionsTaken.iterator(); iter.hasNext(); i++) {
 352  0
             ActionTakenValue actionTaken = (ActionTakenValue) iter.next();
 353  0
             actionTakenVOs[i] = DTOConverter.convertActionTakenWithActionRequests(actionTaken);
 354  
         }
 355  0
         return actionTakenVOs;
 356  
     }
 357  
 
 358  
     /**
 359  
      * This work is also being done in the bowels of convertDocumentContentVO in DTOConverter so some code
 360  
      * could be reduced.
 361  
      *
 362  
      * @param definition
 363  
      * @return WorkflowAttributeValidationErrorVO[] errors from client input into attribute
 364  
      */
 365  
     public WorkflowAttributeValidationErrorDTO[] validateWorkflowAttributeDefinitionVO(WorkflowAttributeDefinitionDTO definition) throws WorkflowException {
 366  0
         if (definition == null) {
 367  0
             LOG.error("null definition passed in.");
 368  0
             throw new RuntimeException("null definition passed in.");
 369  
         }
 370  0
         if ( LOG.isDebugEnabled() ) {
 371  0
                 LOG.debug("Validating WorkflowAttributeDefinitionVO [attributeName="+definition.getAttributeName()+"]");
 372  
         }
 373  0
         AttributeDefinition attributeDefinition = DTOConverter.convertWorkflowAttributeDefinitionVO(definition, null);
 374  0
         WorkflowAttribute attribute = null;
 375  0
         if (attributeDefinition != null) {
 376  0
                 attribute = (WorkflowAttribute) GlobalResourceLoader.getObject(attributeDefinition.getObjectDefinition());
 377  
         }
 378  0
         if (attribute instanceof GenericXMLRuleAttribute) {
 379  0
             Map<String, String> attributePropMap = new HashMap<String, String>();
 380  0
             GenericXMLRuleAttribute xmlAttribute = (GenericXMLRuleAttribute)attribute;
 381  0
             xmlAttribute.setRuleAttribute(attributeDefinition.getRuleAttribute());
 382  0
             for (int i = 0; i < definition.getProperties().length; i++) {
 383  0
                 PropertyDefinitionDTO property = definition.getProperties()[i];
 384  0
                 attributePropMap.put(property.getName(), property.getValue());
 385  
             }
 386  0
             xmlAttribute.setParamMap(attributePropMap);
 387  
         }
 388  
         //validate inputs from client application if the attribute is capable
 389  0
         if (attribute instanceof WorkflowAttributeXmlValidator) {
 390  0
             List errors = ((WorkflowAttributeXmlValidator)attribute).validateClientRoutingData();
 391  0
             WorkflowAttributeValidationErrorDTO[] errorVOs = new WorkflowAttributeValidationErrorDTO[errors.size()];
 392  0
             for (int i = 0; i < errorVOs.length; i++) {
 393  0
                 errorVOs[i] = DTOConverter.convertWorkflowAttributeValidationError((WorkflowAttributeValidationError)errors.get(i));
 394  
             }
 395  0
             return errorVOs;
 396  
         } else {
 397  
             // WORKAROUND: if it is not validatable, then just quietly succeed
 398  0
             return new WorkflowAttributeValidationErrorDTO[0];
 399  
         }
 400  
     }
 401  
 
 402  
     public RouteNodeInstanceDTO[] getDocumentRouteNodeInstances(Long documentId) throws WorkflowException {
 403  0
             if ( LOG.isDebugEnabled() ) {
 404  0
                     LOG.debug("Fetching RouteNodeInstanceVOs [docId=" + documentId + "]");
 405  
             }
 406  0
             return convertRouteNodeInstances(KEWServiceLocator.getRouteNodeService().getFlattenedNodeInstances(loadDocument(documentId), true));
 407  
     }
 408  
 
 409  
     public RouteNodeInstanceDTO[] getActiveNodeInstances(Long documentId) throws WorkflowException {
 410  0
             if ( LOG.isDebugEnabled() ) {
 411  0
                     LOG.debug("Fetching active RouteNodeInstanceVOs [docId=" + documentId + "]");
 412  
             }
 413  0
         loadDocument(documentId);
 414  0
         return convertRouteNodeInstances(KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(documentId));
 415  
     }
 416  
 
 417  
     public RouteNodeInstanceDTO[] getTerminalNodeInstances(Long documentId) throws WorkflowException {
 418  0
             if ( LOG.isDebugEnabled() ) {
 419  0
                     LOG.debug("Fetching terminal RouteNodeInstanceVOs [docId=" + documentId + "]");
 420  
             }
 421  0
             loadDocument(documentId);
 422  0
         return convertRouteNodeInstances(KEWServiceLocator.getRouteNodeService().getTerminalNodeInstances(documentId));
 423  
     }
 424  
 
 425  
     public RouteNodeInstanceDTO[] getCurrentNodeInstances(Long documentId) throws WorkflowException {
 426  0
             if ( LOG.isDebugEnabled() ) {
 427  0
                     LOG.debug("Fetching current RouteNodeInstanceVOs [docId=" + documentId + "]");
 428  
             }
 429  0
             loadDocument(documentId);
 430  0
             return convertRouteNodeInstances(KEWServiceLocator.getRouteNodeService().getCurrentNodeInstances(documentId));
 431  
     }
 432  
 
 433  
     private RouteNodeInstanceDTO[] convertRouteNodeInstances(List nodeInstances) throws WorkflowException {
 434  0
         RouteNodeInstanceDTO[] nodeInstanceVOs = new RouteNodeInstanceDTO[nodeInstances.size()];
 435  0
         int i = 0;
 436  0
         for (Iterator iter = nodeInstances.iterator(); iter.hasNext(); ) {
 437  0
             nodeInstanceVOs[i++] = DTOConverter.convertRouteNodeInstance((RouteNodeInstance) iter.next());
 438  
         }
 439  0
         return nodeInstanceVOs;
 440  
     }
 441  
 
 442  
     public boolean isUserInRouteLog(Long routeHeaderId, String principalId, boolean lookFuture) throws WorkflowException {
 443  0
             return isUserInRouteLogWithOptionalFlattening(routeHeaderId, principalId, lookFuture, false);
 444  
     }
 445  
     
 446  
     public boolean isUserInRouteLogWithOptionalFlattening(Long routeHeaderId, String principalId, boolean lookFuture, boolean flattenNodes) throws WorkflowException {
 447  0
         if (routeHeaderId == null) {
 448  0
             LOG.error("null routeHeaderId passed in.");
 449  0
             throw new RuntimeException("null routeHeaderId passed in.");
 450  
         }
 451  0
         if (principalId == null ){
 452  0
             LOG.error("null principalId passed in.");
 453  0
             throw new RiceRuntimeException("null principalId passed in.");
 454  
         }
 455  0
         boolean authorized = false;
 456  0
         if ( LOG.isDebugEnabled() ) {
 457  0
                 LOG.debug("Evaluating isUserInRouteLog [docId=" + routeHeaderId + ", principalId=" + principalId + ", lookFuture=" + lookFuture + "]");
 458  
         }
 459  0
         DocumentRouteHeaderValue routeHeader = loadDocument(routeHeaderId);
 460  0
         KimPrincipal principal = KEWServiceLocator.getIdentityHelperService().getPrincipal(principalId);
 461  0
         List actionsTaken = KEWServiceLocator.getActionTakenService().findByRouteHeaderIdWorkflowId(routeHeaderId, principal.getPrincipalId());
 462  
 
 463  0
         if(routeHeader.getInitiatorWorkflowId().equals(principal.getPrincipalId())){
 464  0
                 return true;
 465  
         }
 466  
 
 467  0
         if (actionsTaken.size() > 0) {
 468  0
                 LOG.debug("found action taken by user");
 469  0
                 authorized = true;
 470  
         }
 471  
 
 472  0
         List actionRequests = KEWServiceLocator.getActionRequestService().findAllActionRequestsByRouteHeaderId(routeHeaderId);
 473  0
         if (actionRequestListHasPrincipal(principal, actionRequests)) {
 474  0
                 authorized = true;
 475  
         }
 476  
 
 477  0
         if (!lookFuture) {
 478  0
                 return authorized;
 479  
         }
 480  
 
 481  
 
 482  0
         SimulationEngine simulationEngine = new SimulationEngine();
 483  0
         SimulationCriteria criteria = new SimulationCriteria(routeHeaderId);
 484  0
         criteria.setDestinationNodeName(null); // process entire document to conclusion
 485  0
         criteria.getDestinationRecipients().add(new KimPrincipalRecipient(principal));
 486  0
         criteria.setFlattenNodes(flattenNodes);
 487  
 
 488  
         try {
 489  0
                 SimulationResults results = simulationEngine.runSimulation(criteria);
 490  0
                 if (actionRequestListHasPrincipal(principal, results.getSimulatedActionRequests())) {
 491  0
                         authorized = true;
 492  
                 }
 493  0
         } catch (Exception e) {
 494  0
                 throw new RiceRuntimeException(e);
 495  0
         }
 496  
 
 497  0
         return authorized;
 498  
     }
 499  
 
 500  
     /**
 501  
      * @see org.kuali.rice.kew.service.WorkflowUtility#getPrincipalIdsInRouteLog(java.lang.Long, boolean)
 502  
      */
 503  
     public String[] getPrincipalIdsInRouteLog(Long routeHeaderId, boolean lookFuture) throws WorkflowException {
 504  0
         if (routeHeaderId == null) {
 505  0
             LOG.error("null routeHeaderId passed in.");
 506  0
             throw new RuntimeException("null routeHeaderId passed in.");
 507  
         }
 508  0
             Set<String> principalIds = new HashSet<String>();
 509  
         try {
 510  0
                 if ( LOG.isDebugEnabled() ) {
 511  0
                         LOG.debug("Evaluating isUserInRouteLog [docId=" + routeHeaderId + ", lookFuture=" + lookFuture + "]");
 512  
                 }
 513  0
             DocumentRouteHeaderValue routeHeader = loadDocument(routeHeaderId);
 514  0
             List<ActionTakenValue> actionsTakens =
 515  
                     (List<ActionTakenValue>)KEWServiceLocator.getActionTakenService().findByRouteHeaderId(routeHeaderId);
 516  
             //TODO: confirm that the initiator is not already there in the actionstaken
 517  0
             principalIds.add(routeHeader.getInitiatorWorkflowId());
 518  0
             for(ActionTakenValue actionTaken: actionsTakens){
 519  0
                     principalIds.add(actionTaken.getPrincipalId());
 520  
             }
 521  0
             List<ActionRequestValue> actionRequests =
 522  
                     KEWServiceLocator.getActionRequestService().findAllActionRequestsByRouteHeaderId(routeHeaderId);
 523  0
             for(ActionRequestValue actionRequest: actionRequests){
 524  0
                     principalIds.addAll(getPrincipalIdsForActionRequest(actionRequest));
 525  
             }
 526  0
             if (!lookFuture) {
 527  0
                     return principalIds.toArray(new String[]{});
 528  
             }
 529  0
             SimulationEngine simulationEngine = new SimulationEngine();
 530  0
             SimulationCriteria criteria = new SimulationCriteria(routeHeaderId);
 531  0
             criteria.setDestinationNodeName(null); // process entire document to conclusion
 532  0
             SimulationResults results = simulationEngine.runSimulation(criteria);
 533  0
             actionRequests = (List<ActionRequestValue>)results.getSimulatedActionRequests();
 534  0
             for(ActionRequestValue actionRequest: actionRequests){
 535  0
                     principalIds.addAll(getPrincipalIdsForActionRequest(actionRequest));
 536  
             }
 537  0
         } catch (Exception ex) {
 538  0
             LOG.warn("Problems getting principalIds in Route Log for routeHeaderId: "+routeHeaderId+". Exception:"+ex.getMessage(),ex);
 539  0
         }
 540  0
             return principalIds.toArray(new String[]{});
 541  
     }
 542  
 
 543  
         /**
 544  
          * This method gets all of the principalIds for the given ActionRequestValue.  It drills down into
 545  
          * groups if need be.
 546  
          * 
 547  
          * @param actionRequest
 548  
          */
 549  
         private List<String> getPrincipalIdsForActionRequest(ActionRequestValue actionRequest) {
 550  0
                 List<String> results = Collections.emptyList();
 551  0
                 if (actionRequest.getPrincipalId() != null) {
 552  0
                         results = Collections.singletonList(actionRequest.getPrincipalId());
 553  0
                 } else if (actionRequest.getGroupId() != null) {
 554  0
                         List<String> principalIdsForGroup = 
 555  
                                 KIMServiceLocator.getGroupService().getMemberPrincipalIds(actionRequest.getGroupId());
 556  0
                         if (principalIdsForGroup != null) {
 557  0
                                 results = principalIdsForGroup;
 558  
                         }
 559  
                 }
 560  0
                 return results;
 561  
         }
 562  
 
 563  
     /***
 564  
      * @see org.kuali.rice.kew.service.WorkflowUtility#getPrincipalIdsWithPendingActionRequestByActionRequestedAndDocId(java.lang.String, java.lang.Long)
 565  
      */
 566  
     public String[] getPrincipalIdsWithPendingActionRequestByActionRequestedAndDocId(String actionRequestedCd, Long routeHeaderId){
 567  0
             List<String> results = KEWServiceLocator.getActionRequestService().
 568  
                                     getPrincipalIdsWithPendingActionRequestByActionRequestedAndDocId(actionRequestedCd, routeHeaderId);
 569  0
             if (ObjectUtils.isNull(results)) {
 570  0
                     return null;
 571  
             }
 572  0
             return results.toArray(new String[]{});
 573  
     }
 574  
 
 575  
     private boolean actionRequestListHasPrincipal(KimPrincipal principal, List actionRequests) throws WorkflowException {
 576  0
         for (Iterator iter = actionRequests.iterator(); iter.hasNext();) {
 577  0
             ActionRequestValue actionRequest = (ActionRequestValue) iter.next();
 578  0
             if (actionRequest.isRecipientRoutedRequest(new KimPrincipalRecipient(principal))) {
 579  0
                 return true;
 580  
             }
 581  0
         }
 582  0
         return false;
 583  
     }
 584  
 
 585  
     private boolean isRecipientRoutedRequest(ActionRequestValue actionRequest, List<Recipient> recipients) throws WorkflowException {
 586  0
         for (Recipient recipient : recipients) {
 587  0
             if (actionRequest.isRecipientRoutedRequest(recipient)) {
 588  0
                 return true;
 589  
             }
 590  
         }
 591  0
         return false;
 592  
     }
 593  
 
 594  
     /**
 595  
      * @see org.kuali.rice.kew.service.WorkflowUtility#documentWillHaveAtLeastOneActionRequest(org.kuali.rice.kew.dto.ReportCriteriaDTO, java.lang.String[], boolean)
 596  
      */
 597  
     public boolean documentWillHaveAtLeastOneActionRequest(ReportCriteriaDTO reportCriteriaDTO, String[] actionRequestedCodes, boolean ignoreCurrentActionRequests) {
 598  
         try {
 599  0
                 SimulationEngine simulationEngine = new SimulationEngine();
 600  0
                 SimulationCriteria criteria = DTOConverter.convertReportCriteriaDTO(reportCriteriaDTO);
 601  
                 // set activate requests to true by default so force action works correctly
 602  0
                 criteria.setActivateRequests(Boolean.TRUE);
 603  0
                 SimulationResults results = simulationEngine.runSimulation(criteria);
 604  0
             List actionRequestsToProcess = results.getSimulatedActionRequests();
 605  0
             if (!ignoreCurrentActionRequests) {
 606  0
                 actionRequestsToProcess.addAll(results.getDocument().getActionRequests());
 607  
             }
 608  0
             for (Iterator iter = actionRequestsToProcess.iterator(); iter.hasNext();) {
 609  0
                                 ActionRequestValue actionRequest = (ActionRequestValue) iter.next();
 610  0
                 if (actionRequest.isDone()) {
 611  
                     // an action taken has eliminated this request from being active
 612  0
                     continue;
 613  
                 }
 614  
                                 // if no action request codes are passed in.... assume any request found is
 615  0
                             if ( (actionRequestedCodes == null) || (actionRequestedCodes.length == 0) ) {
 616  
                                     // we found an action request
 617  0
                                     return true;
 618  
                             }
 619  
                             // check the action requested codes passed in
 620  0
                             for (int i = 0; i < actionRequestedCodes.length; i++) {
 621  0
                                         String requestedActionRequestCode = actionRequestedCodes[i];
 622  0
                                         if (requestedActionRequestCode.equals(actionRequest.getActionRequested())) {
 623  0
                                             boolean satisfiesDestinationUserCriteria = (criteria.getDestinationRecipients().isEmpty()) || (isRecipientRoutedRequest(actionRequest,criteria.getDestinationRecipients()));
 624  0
                                             if (satisfiesDestinationUserCriteria) {
 625  0
                                                 if (StringUtils.isBlank(criteria.getDestinationNodeName())) {
 626  0
                                                     return true;
 627  0
                                                 } else if (StringUtils.equals(criteria.getDestinationNodeName(),actionRequest.getNodeInstance().getName())) {
 628  0
                                                     return true;
 629  
                                                 }
 630  
                                             }
 631  
                                         }
 632  
                                 }
 633  0
                         }
 634  0
                 return false;
 635  0
         } catch (Exception ex) {
 636  0
                 String error = "Problems evaluating documentWillHaveAtLeastOneActionRequest: " + ex.getMessage();
 637  0
             LOG.error(error,ex);
 638  0
             if (ex instanceof RuntimeException) {
 639  0
                     throw (RuntimeException)ex;
 640  
             }
 641  0
             throw new RuntimeException(error, ex);
 642  
         }
 643  
     }
 644  
 
 645  
     public boolean isLastApproverInRouteLevel(Long routeHeaderId, String principalId, Integer routeLevel) throws WorkflowException {
 646  0
         if (routeLevel == null) {
 647  0
             LOG.error("null routeLevel passed in.");
 648  0
             throw new RuntimeException("null routeLevel passed in.");
 649  
         }
 650  0
         if ( LOG.isDebugEnabled() ) {
 651  0
                 LOG.debug("Evaluating isLastApproverInRouteLevel [docId=" + routeHeaderId + ", principalId=" + principalId + ", routeLevel=" + routeLevel + "]");
 652  
         }
 653  0
         DocumentRouteHeaderValue document = loadDocument(routeHeaderId);
 654  0
         RouteNode node = CompatUtils.getNodeForLevel(document.getDocumentType(), routeLevel);
 655  0
         if (node == null) {
 656  0
             throw new RuntimeException("Cannot resolve given route level to an approriate node name: " + routeLevel);
 657  
         }
 658  0
         return isLastApproverAtNode(routeHeaderId, principalId, node.getRouteNodeName());
 659  
     }
 660  
 
 661  
     public boolean isLastApproverAtNode(Long routeHeaderId, String principalId, String nodeName) throws WorkflowException {
 662  0
         if (routeHeaderId == null) {
 663  0
             LOG.error("null routeHeaderId passed in.");
 664  0
             throw new RuntimeException("null routeHeaderId passed in.");
 665  
         }
 666  0
         if (principalId == null ){
 667  0
             LOG.error("null principalId passed in.");
 668  0
             throw new RuntimeException("null principalId passed in.");
 669  
         }
 670  0
         if ( LOG.isDebugEnabled() ) {
 671  0
                 LOG.debug("Evaluating isLastApproverAtNode [docId=" + routeHeaderId + ", principalId=" + principalId + ", nodeName=" + nodeName + "]");
 672  
         }
 673  0
         loadDocument(routeHeaderId);
 674  
         // If this app constant is set to true, then we will attempt to simulate activation of non-active requests before
 675  
         // attempting to deactivate them, this is in order to address the force action issue reported by EPIC in issue
 676  
         // http://fms.dfa.cornell.edu:8080/browse/KULWF-366
 677  0
         boolean activateFirst = Utilities.getKNSParameterBooleanValue(KEWConstants.KEW_NAMESPACE, KNSConstants.DetailTypes.FEATURE_DETAIL_TYPE, KEWConstants.IS_LAST_APPROVER_ACTIVATE_FIRST_IND, false);
 678  
 
 679  0
         List requests = KEWServiceLocator.getActionRequestService().findPendingByDocRequestCdNodeName(routeHeaderId, KEWConstants.ACTION_REQUEST_APPROVE_REQ, nodeName);
 680  0
         if (requests == null || requests.isEmpty()) {
 681  0
             return false;
 682  
         }
 683  0
         ActivationContext activationContext = new ActivationContext(ActivationContext.CONTEXT_IS_SIMULATION);
 684  0
         for (Iterator iterator = requests.iterator(); iterator.hasNext();) {
 685  0
             ActionRequestValue request = (ActionRequestValue) iterator.next();
 686  0
             if (activateFirst && !request.isActive()) {
 687  0
                 KEWServiceLocator.getActionRequestService().activateRequest(request, activationContext);
 688  
             }
 689  0
             if (request.isUserRequest() && request.getPrincipalId().equals(principalId)) {
 690  0
                 KEWServiceLocator.getActionRequestService().deactivateRequest(null, request, activationContext);
 691  0
             } else if (request.isGroupRequest() && KIMServiceLocator.getIdentityManagementService().isMemberOfGroup(principalId, request.getGroup().getGroupId())) {
 692  0
                 KEWServiceLocator.getActionRequestService().deactivateRequest(null, request, activationContext);
 693  
             }
 694  0
         }
 695  0
         boolean allDeactivated = true;
 696  0
         for (Iterator iter = requests.iterator(); iter.hasNext();) {
 697  0
             ActionRequestValue actionRequest = (ActionRequestValue) iter.next();
 698  0
             allDeactivated = allDeactivated && actionRequest.isDeactivated();
 699  0
         }
 700  0
         return allDeactivated;
 701  
     }
 702  
 
 703  
     /**
 704  
      * Used to determine if a given route level will produce Approve Action Requests.
 705  
      *
 706  
      * @deprecated use routeNodeHasApproverActionRequest instead
 707  
      */
 708  
     public boolean routeLevelHasApproverActionRequest(String documentTypeName, String docContent, Integer routeLevel) throws WorkflowException {
 709  0
         if (documentTypeName == null) {
 710  0
             LOG.error("null document type name passed in.");
 711  0
             throw new RuntimeException("null document type passed in.");
 712  
         }
 713  0
         if (routeLevel == null) {
 714  0
             LOG.error("null routeLevel passed in.");
 715  0
             throw new RuntimeException("null routeLevel passed in.");
 716  
         }
 717  0
         if ( LOG.isDebugEnabled() ) {
 718  0
                 LOG.debug("Evaluating routeLevelHasApproverActionRequest [docTypeName=" + documentTypeName + ", routeLevel=" + routeLevel + "]");
 719  
         }
 720  0
         DocumentType documentType = KEWServiceLocator.getDocumentTypeService().findByName(documentTypeName);
 721  0
         if (!CompatUtils.isRouteLevelCompatible(documentType)) {
 722  0
             throw new WorkflowException("The given document type is not route level compatible: " + documentTypeName);
 723  
         }
 724  0
         RouteNode routeNode = CompatUtils.getNodeForLevel(documentType, routeLevel);
 725  0
         return routeNodeHasApproverActionRequest(documentType, docContent, routeNode, routeLevel);
 726  
     }
 727  
 
 728  
     public boolean routeNodeHasApproverActionRequest(String documentTypeName, String docContent, String nodeName) throws WorkflowException {
 729  0
         if (documentTypeName == null) {
 730  0
             LOG.error("null docType passed in.");
 731  0
             throw new RuntimeException("null docType passed in.");
 732  
         }
 733  0
         if (nodeName == null) {
 734  0
             LOG.error("null nodeName passed in.");
 735  0
             throw new RuntimeException("null nodeName passed in.");
 736  
         }
 737  0
         if ( LOG.isDebugEnabled() ) {
 738  0
                 LOG.debug("Evaluating routeNodeHasApproverActionRequest [docTypeName=" + documentTypeName + ", nodeName=" + nodeName + "]");
 739  
         }
 740  0
         DocumentType documentType = KEWServiceLocator.getDocumentTypeService().findByName(documentTypeName);
 741  0
         RouteNode routeNode = KEWServiceLocator.getRouteNodeService().findRouteNodeByName(documentType.getDocumentTypeId(), nodeName);
 742  0
         return routeNodeHasApproverActionRequest(documentType, docContent, routeNode, new Integer(KEWConstants.INVALID_ROUTE_LEVEL));
 743  
     }
 744  
 
 745  
     /**
 746  
      * Really this method needs to be implemented using the routingReport functionality (the SimulationEngine).
 747  
      * This would get rid of the needs for us to call to FlexRM directly.
 748  
      */
 749  
     private boolean routeNodeHasApproverActionRequest(DocumentType documentType, String docContent, RouteNode node, Integer routeLevel) throws WorkflowException {
 750  0
         if (documentType == null) {
 751  0
             LOG.error("could not locate document type.");
 752  0
             throw new RuntimeException("could not locate document type.");
 753  
         }
 754  0
         if (docContent == null) {
 755  0
             LOG.error("null docContent passed in.");
 756  0
             throw new RuntimeException("null docContent passed in.");
 757  
         }
 758  0
         if (node == null) {
 759  0
             LOG.error("could not locate route node.");
 760  0
             throw new RuntimeException("could not locate route node.");
 761  
         }
 762  
 
 763  0
         DocumentRouteHeaderValue routeHeader = new DocumentRouteHeaderValue();
 764  0
         routeHeader.setRouteHeaderId(new Long(0));
 765  0
         routeHeader.setDocumentTypeId(documentType.getDocumentTypeId());
 766  0
         routeHeader.setDocRouteLevel(routeLevel);
 767  0
         routeHeader.setDocVersion(new Integer(KEWConstants.CURRENT_DOCUMENT_VERSION));
 768  
 
 769  0
         if (node.getRuleTemplate() != null && node.isFlexRM()) {
 770  0
             String ruleTemplateName = node.getRuleTemplate().getName();
 771  0
             routeHeader.setDocContent(docContent);
 772  0
             routeHeader.setDocRouteStatus(KEWConstants.ROUTE_HEADER_INITIATED_CD);
 773  0
             FlexRM flexRM = new FlexRM();
 774  0
                     RouteContext context = RouteContext.getCurrentRouteContext();
 775  0
                     context.setDocument(routeHeader);
 776  
                     try {
 777  0
                             List actionRequests = flexRM.getActionRequests(routeHeader, node, null, ruleTemplateName);
 778  0
                             for (Iterator iter = actionRequests.iterator(); iter.hasNext();) {
 779  0
                                     ActionRequestValue actionRequest = (ActionRequestValue) iter.next();
 780  0
                                     if (actionRequest.isApproveOrCompleteRequest()) {
 781  0
                                             return true;
 782  
                                     }
 783  0
                             }
 784  0
                     } finally {
 785  0
                             RouteContext.clearCurrentRouteContext();
 786  0
                     }
 787  
         }
 788  0
         return false;
 789  
     }
 790  
 
 791  
     private void incomingParamCheck(Object object, String name) {
 792  0
         if (object == null) {
 793  0
             LOG.error("null " + name + " passed in.");
 794  0
             throw new RuntimeException("null " + name + " passed in.");
 795  
         }
 796  0
     }
 797  
 
 798  
     public void reResolveRole(String documentTypeName, String roleName, String qualifiedRoleNameLabel) throws WorkflowException {
 799  0
         incomingParamCheck(documentTypeName, "documentTypeName");
 800  0
         incomingParamCheck(roleName, "roleName");
 801  0
         incomingParamCheck(qualifiedRoleNameLabel, "qualifiedRoleNameLabel");
 802  0
         if ( LOG.isDebugEnabled() ) {
 803  0
                 LOG.debug("Re-resolving Role [docTypeName=" + documentTypeName + ", roleName=" + roleName + ", qualifiedRoleNameLabel=" + qualifiedRoleNameLabel + "]");
 804  
         }
 805  0
             DocumentType documentType = KEWServiceLocator.getDocumentTypeService().findByName(documentTypeName);
 806  0
             if (Utilities.isEmpty(qualifiedRoleNameLabel)) {
 807  0
                     KEWServiceLocator.getRoleService().reResolveRole(documentType, roleName);
 808  
             } else {
 809  0
                     KEWServiceLocator.getRoleService().reResolveQualifiedRole(documentType, roleName, qualifiedRoleNameLabel);
 810  
             }
 811  0
     }
 812  
 
 813  
     public void reResolveRoleByDocumentId(Long documentId, String roleName, String qualifiedRoleNameLabel) throws WorkflowException {
 814  0
         incomingParamCheck(documentId, "documentId");
 815  0
         incomingParamCheck(roleName, "roleName");
 816  0
         incomingParamCheck(qualifiedRoleNameLabel, "qualifiedRoleNameLabel");
 817  0
         if ( LOG.isDebugEnabled() ) {
 818  0
                 LOG.debug("Re-resolving Role [documentId=" + documentId + ", roleName=" + roleName + ", qualifiedRoleNameLabel=" + qualifiedRoleNameLabel + "]");
 819  
         }
 820  0
         DocumentRouteHeaderValue routeHeader = loadDocument(documentId);
 821  0
             if (Utilities.isEmpty(qualifiedRoleNameLabel)) {
 822  0
                     KEWServiceLocator.getRoleService().reResolveRole(routeHeader, roleName);
 823  
             } else {
 824  0
                     KEWServiceLocator.getRoleService().reResolveQualifiedRole(routeHeader, roleName, qualifiedRoleNameLabel);
 825  
             }
 826  0
     }
 827  
 
 828  
     public DocumentDetailDTO routingReport(ReportCriteriaDTO reportCriteria) throws WorkflowException {
 829  0
         incomingParamCheck(reportCriteria, "reportCriteria");
 830  0
         if ( LOG.isDebugEnabled() ) {
 831  0
                 LOG.debug("Executing routing report [docId=" + reportCriteria.getRouteHeaderId() + ", docTypeName=" + reportCriteria.getDocumentTypeName() + "]");
 832  
         }
 833  0
         SimulationCriteria criteria = DTOConverter.convertReportCriteriaDTO(reportCriteria);
 834  0
         return DTOConverter.convertDocumentDetail(KEWServiceLocator.getRoutingReportService().report(criteria));
 835  
     }
 836  
 
 837  
     public boolean isFinalApprover(Long routeHeaderId, String principalId) throws WorkflowException {
 838  0
         incomingParamCheck(routeHeaderId, "routeHeaderId");
 839  0
         incomingParamCheck(principalId, "principalId");
 840  0
         if ( LOG.isDebugEnabled() ) {
 841  0
                 LOG.debug("Evaluating isFinalApprover [docId=" + routeHeaderId + ", principalId=" + principalId + "]");
 842  
         }
 843  0
         DocumentRouteHeaderValue routeHeader = loadDocument(routeHeaderId);
 844  0
         List requests = KEWServiceLocator.getActionRequestService().findPendingByDoc(routeHeaderId);
 845  0
         List finalApproverNodes = KEWServiceLocator.getRouteNodeService().findFinalApprovalRouteNodes(routeHeader.getDocumentType().getDocumentTypeId());
 846  0
         if (finalApproverNodes.isEmpty()) {
 847  0
                 if ( LOG.isDebugEnabled() ) {
 848  0
                         LOG.debug("Could not locate final approval nodes for document " + routeHeaderId);
 849  
                 }
 850  0
             return false;
 851  
         }
 852  0
         Set finalApproverNodeNames = new HashSet();
 853  0
         for (Iterator iterator = finalApproverNodes.iterator(); iterator.hasNext();) {
 854  0
             RouteNode node = (RouteNode) iterator.next();
 855  0
             finalApproverNodeNames.add(node.getRouteNodeName());
 856  0
         }
 857  
 
 858  0
         int approveRequest = 0;
 859  0
         for (Iterator iter = requests.iterator(); iter.hasNext();) {
 860  0
             ActionRequestValue request = (ActionRequestValue) iter.next();
 861  0
             RouteNodeInstance nodeInstance = request.getNodeInstance();
 862  0
             if (nodeInstance == null) {
 863  0
                     if ( LOG.isDebugEnabled() ) {
 864  0
                             LOG.debug("Found an action request on the document with a null node instance, indicating EXCEPTION routing.");
 865  
                     }
 866  0
                 return false;
 867  
             }
 868  0
             if (finalApproverNodeNames.contains(nodeInstance.getRouteNode().getRouteNodeName())) {
 869  0
                 if (request.isApproveOrCompleteRequest()) {
 870  0
                     approveRequest++;
 871  0
                     if ( LOG.isDebugEnabled() ) {
 872  0
                             LOG.debug("Found request is approver " + request.getActionRequestId());
 873  
                     }
 874  0
                     if (! request.isRecipientRoutedRequest(principalId)) {
 875  0
                             if ( LOG.isDebugEnabled() ) {
 876  0
                                     LOG.debug("Action Request not for user " + principalId);
 877  
                             }
 878  0
                         return false;
 879  
                     }
 880  
                 }
 881  
             }
 882  0
         }
 883  
 
 884  0
         if (approveRequest == 0) {
 885  0
             return false;
 886  
         }
 887  0
         if ( LOG.isDebugEnabled() ) {
 888  0
                 LOG.debug("Principal "+principalId+" is final approver for document " + routeHeaderId);
 889  
         }
 890  0
         return true;
 891  
     }
 892  
 
 893  
     public boolean isSuperUserForDocumentType(String principalId, Long documentTypeId) throws WorkflowException {
 894  0
             if ( LOG.isDebugEnabled() ) {
 895  0
                     LOG.debug("Determining super user status [principalId=" + principalId + ", documentTypeId=" + documentTypeId + "]");
 896  
             }
 897  0
             DocumentType documentType = KEWServiceLocator.getDocumentTypeService().findById(documentTypeId);
 898  0
             boolean isSuperUser = KEWServiceLocator.getDocumentTypePermissionService().canAdministerRouting(principalId, documentType);
 899  0
             if ( LOG.isDebugEnabled() ) {
 900  0
                     LOG.debug("Super user status is " + isSuperUser + ".");
 901  
             }
 902  0
             return isSuperUser;
 903  
     }
 904  
 
 905  
     private DocumentRouteHeaderValue loadDocument(Long documentId) {
 906  0
         return KEWServiceLocator.getRouteHeaderService().getRouteHeader(documentId);
 907  
     }
 908  
 
 909  
     public DocumentContentDTO getDocumentContent(Long routeHeaderId) throws WorkflowException {
 910  0
             if ( LOG.isDebugEnabled() ) {
 911  0
                     LOG.debug("Fetching document content [docId=" + routeHeaderId + "]");
 912  
             }
 913  0
             DocumentRouteHeaderValue document = KEWServiceLocator.getRouteHeaderService().getRouteHeader(routeHeaderId);
 914  0
             return DTOConverter.convertDocumentContent(document.getDocContent(), routeHeaderId);
 915  
     }
 916  
 
 917  
         public String[] getPreviousRouteNodeNames(Long documentId) throws WorkflowException {
 918  0
                 if ( LOG.isDebugEnabled() ) {
 919  0
                         LOG.debug("Fetching previous node names [docId=" + documentId + "]");
 920  
                 }
 921  0
                 DocumentRouteHeaderValue document = KEWServiceLocator.getRouteHeaderService().getRouteHeader(documentId);
 922  
                 //going conservative for now.  if the doc isn't enroute or exception nothing will be returned.
 923  0
                 if (document.isEnroute() || document.isInException()) {
 924  
 
 925  0
                         List activeNodeInstances = KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(document);
 926  0
                         long largetActivatedNodeId = 0;
 927  0
                         for (Iterator iter = activeNodeInstances.iterator(); iter.hasNext();) {
 928  0
                                 RouteNodeInstance routeNodeInstance = (RouteNodeInstance) iter.next();
 929  0
                                 if (routeNodeInstance.getRouteNode().getRouteNodeId().longValue() > largetActivatedNodeId) {
 930  0
                                         largetActivatedNodeId = routeNodeInstance.getRouteNode().getRouteNodeId().longValue();
 931  
                                 }
 932  0
                         }
 933  
 
 934  0
                         List routeNodes = KEWServiceLocator.getRouteNodeService().getFlattenedNodeInstances(document, false);
 935  0
                         List nodeNames = new ArrayList();
 936  
 
 937  0
                         for (Iterator iter = routeNodes.iterator(); iter.hasNext();) {
 938  0
                                 RouteNodeInstance routeNode = (RouteNodeInstance) iter.next();
 939  0
                                 if (routeNode.isComplete() && !nodeNames.contains(routeNode.getName())) {
 940  
                                         //if the prototype of the nodeInstance we're analyzing is less than the largest id of all our active prototypes
 941  
                                         //then add it to the list.  This is an attempt to account for return to previous hitting a single node multiple times
 942  0
                                         if (routeNode.getRouteNode().getRouteNodeId().longValue() < largetActivatedNodeId) {
 943  0
                                                 nodeNames.add(routeNode.getName());
 944  
                                         }
 945  
                                 }
 946  0
                         }
 947  0
                         return (String[]) nodeNames.toArray(new String[nodeNames.size()]);
 948  
                 } else {
 949  0
                         return new String[0];
 950  
                 }
 951  
         }
 952  
 
 953  
     public RuleDTO[] ruleReport(RuleReportCriteriaDTO ruleReportCriteria) throws WorkflowException {
 954  0
         incomingParamCheck(ruleReportCriteria, "ruleReportCriteria");
 955  0
         if (ruleReportCriteria == null) {
 956  0
             throw new IllegalArgumentException("At least one criterion must be sent in a RuleReportCriteriaDTO object");
 957  
         }
 958  0
         if ( LOG.isDebugEnabled() ) {
 959  0
                 LOG.debug("Executing rule report [responsibleUser=" + ruleReportCriteria.getResponsiblePrincipalId() + ", responsibleWorkgroup=" +
 960  
                     ruleReportCriteria.getResponsibleGroupId() + "]");
 961  
         }
 962  0
         Map extensionValues = new HashMap();
 963  0
         if (ruleReportCriteria.getRuleExtensionVOs() != null) {
 964  0
             for (int i = 0; i < ruleReportCriteria.getRuleExtensionVOs().length; i++) {
 965  0
                 RuleExtensionDTO ruleExtensionVO = ruleReportCriteria.getRuleExtensionVOs()[i];
 966  0
                 KeyValuePair ruleExtension = DTOConverter.convertRuleExtensionVO(ruleExtensionVO);
 967  0
                 extensionValues.put(ruleExtension.getKey(), ruleExtension.getValue());
 968  
             }
 969  
         }
 970  0
         Collection<String> actionRequestCodes = new ArrayList<String>();
 971  0
         if ( (ruleReportCriteria.getActionRequestCodes() != null) && (ruleReportCriteria.getActionRequestCodes().length != 0) ) {
 972  0
             actionRequestCodes = Arrays.asList(ruleReportCriteria.getActionRequestCodes());
 973  
         }
 974  0
         Collection rulesFound = KEWServiceLocator.getRuleService().search(ruleReportCriteria.getDocumentTypeName(),ruleReportCriteria.getRuleTemplateName(),
 975  
                 ruleReportCriteria.getRuleDescription(), ruleReportCriteria.getResponsibleGroupId(),
 976  
                 ruleReportCriteria.getResponsiblePrincipalId(),
 977  
                 ruleReportCriteria.isConsiderWorkgroupMembership(),ruleReportCriteria.isIncludeDelegations(),
 978  
                 ruleReportCriteria.isActiveIndicator(),extensionValues,actionRequestCodes);
 979  0
         RuleDTO[] returnableRules = new RuleDTO[rulesFound.size()];
 980  0
         int i = 0;
 981  0
         for (Iterator iter = rulesFound.iterator(); iter.hasNext();) {
 982  0
             RuleBaseValues rule = (RuleBaseValues) iter.next();
 983  0
             returnableRules[i] = DTOConverter.convertRule(rule);
 984  0
             i++;
 985  0
         }
 986  0
         return returnableRules;
 987  
     }
 988  
 
 989  
     public DocumentSearchResultDTO performDocumentSearch(DocumentSearchCriteriaDTO criteriaVO) throws WorkflowException {
 990  0
         return performDocumentSearchWithPrincipal(null, criteriaVO);
 991  
     }
 992  
 
 993  
     public DocumentSearchResultDTO performDocumentSearchWithPrincipal(String principalId, DocumentSearchCriteriaDTO criteriaVO) throws WorkflowException {
 994  0
         DocSearchCriteriaDTO criteria = DTOConverter.convertDocumentSearchCriteriaDTO(criteriaVO);
 995  0
         criteria.setOverridingUserSession(true);
 996  0
         if (principalId != null) {
 997  0
                 KEWServiceLocator.getIdentityHelperService().validatePrincipalId(principalId);
 998  
         } else {
 999  
                 // if the principal is null then we need to use the system "kr" user for execution of the search
 1000  0
                 principalId = KEWServiceLocator.getIdentityHelperService().getSystemPrincipal().getPrincipalId();
 1001  
         }
 1002  0
         DocumentSearchResultComponents components = KEWServiceLocator.getDocumentSearchService().getListRestrictedByCriteria(principalId, criteria);
 1003  0
         DocumentSearchResultDTO resultVO = DTOConverter.convertDocumentSearchResultComponents(components);
 1004  0
         resultVO.setOverThreshold(criteria.isOverThreshold());
 1005  0
         resultVO.setSecurityFilteredRows(Integer.valueOf(criteria.getSecurityFilteredRows()));
 1006  0
         return resultVO;
 1007  
     }
 1008  
 
 1009  
     /**
 1010  
      * @see org.kuali.rice.kew.service.WorkflowUtility#getDocumentInitiatorPrincipalId(java.lang.Long)
 1011  
      */
 1012  
     public String getDocumentInitiatorPrincipalId(Long routeHeaderId)
 1013  
                     throws WorkflowException {
 1014  0
         if (routeHeaderId == null) {
 1015  0
             LOG.error("null routeHeaderId passed in.");
 1016  0
             throw new RuntimeException("null routeHeaderId passed in.");
 1017  
         }
 1018  
 
 1019  0
         DocumentRouteHeaderValue header = KEWServiceLocator.getRouteHeaderService().getRouteHeader(routeHeaderId, false);
 1020  0
         if ( header == null) {
 1021  0
                 return null;
 1022  
         }
 1023  0
             return header.getInitiatorWorkflowId();
 1024  
     }
 1025  
     /**
 1026  
      * @see org.kuali.rice.kew.service.WorkflowUtility#getDocumentRoutedByPrincipalId(java.lang.Long)
 1027  
      */
 1028  
     public String getDocumentRoutedByPrincipalId(Long routeHeaderId)
 1029  
                     throws WorkflowException {
 1030  0
         if (routeHeaderId == null) {
 1031  0
             LOG.error("null routeHeaderId passed in.");
 1032  0
             throw new RuntimeException("null routeHeaderId passed in.");
 1033  
         }
 1034  
 
 1035  0
         DocumentRouteHeaderValue header = KEWServiceLocator.getRouteHeaderService().getRouteHeader(routeHeaderId, false);
 1036  0
         if ( header == null) {
 1037  0
                 return null;
 1038  
         }
 1039  0
             return header.getRoutedByUserWorkflowId();
 1040  
     }
 1041  
 
 1042  
     /**
 1043  
          *
 1044  
          * @see org.kuali.rice.kew.service.WorkflowUtility#getSearchableAttributeDateTimeValuesByKey(java.lang.Long, java.lang.String)
 1045  
          */
 1046  
         public Timestamp[] getSearchableAttributeDateTimeValuesByKey(
 1047  
                         Long documentId, String key) {
 1048  0
                 List<Timestamp> results = KEWServiceLocator.getRouteHeaderService().getSearchableAttributeDateTimeValuesByKey(documentId, key);
 1049  0
                 if (ObjectUtils.isNull(results)) {
 1050  0
                         return null;
 1051  
                 }
 1052  0
                 return results.toArray(new Timestamp[]{});
 1053  
         }
 1054  
 
 1055  
         /**
 1056  
          *
 1057  
          * @see org.kuali.rice.kew.service.WorkflowUtility#getSearchableAttributeFloatValuesByKey(java.lang.Long, java.lang.String)
 1058  
          */
 1059  
         public BigDecimal[] getSearchableAttributeFloatValuesByKey(Long documentId, String key) {
 1060  0
                 List<BigDecimal> results = KEWServiceLocator.getRouteHeaderService().getSearchableAttributeFloatValuesByKey(documentId, key);
 1061  0
                 if (ObjectUtils.isNull(results)) {
 1062  0
                         return null;
 1063  
                 }
 1064  0
                 return results.toArray(new BigDecimal[]{});
 1065  
         }
 1066  
 
 1067  
         /**
 1068  
          *
 1069  
          * @see org.kuali.rice.kew.service.WorkflowUtility#getSearchableAttributeLongValuesByKey(java.lang.Long, java.lang.String)
 1070  
          */
 1071  
         public Long[] getSearchableAttributeLongValuesByKey(Long documentId, String key) {
 1072  0
                 List<Long> results = KEWServiceLocator.getRouteHeaderService().getSearchableAttributeLongValuesByKey(documentId, key);
 1073  0
                 if (ObjectUtils.isNull(results)) {
 1074  0
                         return null;
 1075  
                 }
 1076  0
                 return results.toArray(new Long[]{});
 1077  
         }
 1078  
 
 1079  
         /**
 1080  
          *
 1081  
          * @see org.kuali.rice.kew.service.WorkflowUtility#getSearchableAttributeStringValuesByKey(java.lang.Long, java.lang.String)
 1082  
          */
 1083  
         public String[] getSearchableAttributeStringValuesByKey(Long documentId, String key) {
 1084  0
                 List<String> results = KEWServiceLocator.getRouteHeaderService().getSearchableAttributeStringValuesByKey(documentId, key);
 1085  0
                 if (ObjectUtils.isNull(results)) {
 1086  0
                         return null;
 1087  
                 }
 1088  0
                 return results.toArray(new String[]{});
 1089  
         }
 1090  
 
 1091  
     public String getFutureRequestsKey(String principalId) {
 1092  0
         return KEWConstants.RECEIVE_FUTURE_REQUESTS_BRANCH_STATE_KEY + "," + principalId + "," + new Date().toString() + ", " + Math.random();
 1093  
     }
 1094  
 
 1095  
     public String getReceiveFutureRequestsValue() {
 1096  0
         return KEWConstants.RECEIVE_FUTURE_REQUESTS_BRANCH_STATE_VALUE;
 1097  
     }
 1098  
 
 1099  
     public String getDoNotReceiveFutureRequestsValue() {
 1100  0
         return KEWConstants.DONT_RECEIVE_FUTURE_REQUESTS_BRANCH_STATE_VALUE;
 1101  
     }
 1102  
 
 1103  
     public String getClearFutureRequestsValue() {
 1104  0
         return KEWConstants.CLEAR_FUTURE_REQUESTS_BRANCH_STATE_VALUE;
 1105  
     }
 1106  
     
 1107  
     public boolean hasRouteNode(String documentTypeName, String routeNodeName) throws WorkflowException {
 1108  0
         if (documentTypeName == null) {
 1109  0
             LOG.error("null documentTypeName passed in.");
 1110  0
             throw new RuntimeException("null documentTypeName passed in");
 1111  
         }
 1112  0
         if (routeNodeName == null) {
 1113  0
             LOG.error("null routeNodeName passed in.");
 1114  0
             throw new RuntimeException("null routeNodeName passed in");
 1115  
         }
 1116  0
             DocumentTypeDTO docType = getDocumentTypeByName(documentTypeName);
 1117  0
             if(docType==null){
 1118  0
             LOG.error("docType null for the documentTypeName passed in "+documentTypeName);
 1119  0
             throw new RuntimeException("docType null for the documentTypeName passed in "+documentTypeName);
 1120  
         }
 1121  0
             RouteNode routeNode = KEWServiceLocator.getRouteNodeService().findRouteNodeByName(docType.getDocTypeId(), routeNodeName);
 1122  
             
 1123  0
             if(routeNode==null){
 1124  0
                     if(docType.getDocTypeParentName() == null)
 1125  0
                             return false;
 1126  
                     else
 1127  0
                             return hasRouteNode(docType.getDocTypeParentName(), routeNodeName);        
 1128  
             }
 1129  
             else
 1130  0
                     return true;
 1131  
             
 1132  
     }
 1133  
 
 1134  
     public boolean isCurrentActiveDocumentType(String documentTypeName) throws WorkflowException {
 1135  0
             DocumentType docType = KEWServiceLocator.getDocumentTypeService().findByName(documentTypeName);
 1136  0
             return docType != null && docType.isActive();
 1137  
     }
 1138  
     
 1139  
         public DocumentDetailDTO getDocumentDetailFromAppId(
 1140  
                         String documentTypeName, String appId) throws WorkflowException {
 1141  0
         if (documentTypeName == null) {
 1142  0
             LOG.error("null documentTypeName passed in.");
 1143  0
             throw new RuntimeException("null documentTypeName passed in");
 1144  
         }
 1145  0
         if (appId == null) {
 1146  0
             LOG.error("null appId passed in.");
 1147  0
             throw new RuntimeException("null appId passed in");
 1148  
         }
 1149  
         
 1150  0
         Collection routeHeaderIds = KEWServiceLocator.getRouteHeaderService().findByDocTypeAndAppId(documentTypeName, appId);
 1151  
         
 1152  0
         if(routeHeaderIds==null||routeHeaderIds.isEmpty()){
 1153  0
             LOG.error("No RouteHeader Ids found for criteria");
 1154  0
                     throw new WorkflowException("No RouteHeader Ids found for criteria");
 1155  
         }
 1156  0
         if(routeHeaderIds.size()>1){
 1157  0
             LOG.error("More than one RouteHeader Id found for criteria");
 1158  0
                     throw new WorkflowException("More than one RouteHeader Id found for criteria");
 1159  
                 }
 1160  
         
 1161  0
         return getDocumentDetail((Long)routeHeaderIds.iterator().next());
 1162  
         }
 1163  
         
 1164  
         public String getAppDocId(Long documentId) {
 1165  0
                   return KEWServiceLocator.getRouteHeaderService().getAppDocId(documentId);
 1166  
          }
 1167  
     
 1168  
     public DocumentStatusTransitionDTO[] getDocumentStatusTransitionHistory(Long documentId) throws WorkflowException {
 1169  0
         if (documentId == null) {
 1170  0
             LOG.error("null routeHeaderId passed in.");
 1171  0
             throw new RuntimeException("null routeHeaderId passed in");
 1172  
         }
 1173  0
         if ( LOG.isDebugEnabled() ) {
 1174  0
             LOG.debug("Fetching document status transition history [id="+documentId+"]");
 1175  
         }
 1176  0
         DocumentRouteHeaderValue document = loadDocument(documentId);
 1177  
         
 1178  0
         UserSession userSession = UserSession.getAuthenticatedUser();
 1179  0
         String principalId = null;
 1180  0
         if (userSession != null) { // get the principalId if we can
 1181  0
                 principalId = userSession.getPrincipalId();
 1182  
         }
 1183  0
         List<DocumentStatusTransition> list = document.getAppDocStatusHistory();
 1184  
 
 1185  0
         DocumentStatusTransitionDTO[] transitionHistory = new DocumentStatusTransitionDTO[list.size()];        
 1186  0
         int i = 0;
 1187  0
         for (Iterator iter = list.iterator(); iter.hasNext();) {
 1188  0
                 DocumentStatusTransition transition = (DocumentStatusTransition) iter.next();
 1189  0
             transitionHistory[i] = DTOConverter.convertDocumentStatusTransition(transition);
 1190  0
             i++;
 1191  0
         }
 1192  0
         return transitionHistory;
 1193  
     }
 1194  
 
 1195  
         //for document link
 1196  
 
 1197  
         public void deleteDocumentLink(DocumentLinkDTO docLink) throws WorkflowException {
 1198  0
                 KEWServiceLocator.getDocumentLinkService().deleteDocumentLink(initDocLink(docLink));
 1199  0
         }
 1200  
 
 1201  
         /**
 1202  
          * This overridden method ...
 1203  
          * 
 1204  
          * @see org.kuali.rice.kew.routeheader.service.WorkflowDocumentService#addDocumentLink(org.kuali.rice.kew.documentlink.DocumentLink)
 1205  
          */
 1206  
         public void addDocumentLink(DocumentLinkDTO docLinkVO) throws WorkflowException {
 1207  0
                 KEWServiceLocator.getDocumentLinkService().saveDocumentLink(initDocLink(docLinkVO));
 1208  0
         }
 1209  
 
 1210  
         /**
 1211  
          * This overridden method ...
 1212  
          * 
 1213  
          * @see org.kuali.rice.kew.routeheader.service.WorkflowDocumentService#getgetLinkedDocumentsByDocId(java.lang.Long)
 1214  
          */
 1215  
         public List<DocumentLinkDTO> getLinkedDocumentsByDocId(Long id) throws WorkflowException {
 1216  0
                 return DTOConverter.convertDocumentLinkToArrayList(KEWServiceLocator.getDocumentLinkService().getLinkedDocumentsByDocId(id));
 1217  
         }
 1218  
 
 1219  
         /**
 1220  
          * This overridden method ...
 1221  
          * 
 1222  
          * @see org.kuali.rice.kew.routeheader.service.WorkflowDocumentService#getDocumentLink(org.kuali.rice.kew.documentlink.DocumentLink)
 1223  
          */
 1224  
         public DocumentLinkDTO getLinkedDocument(DocumentLinkDTO docLinkVO) throws WorkflowException{
 1225  0
                 return DTOConverter.convertDocumentLink(KEWServiceLocator.getDocumentLinkService().getLinkedDocument(initDocLink(docLinkVO)));
 1226  
         }
 1227  
 
 1228  
         /**
 1229  
          * This overridden method ...
 1230  
          * 
 1231  
          * @see org.kuali.rice.kew.routeheader.service.WorkflowDocumentService#deleteDocumentLinkByDocId(java.lang.Long)
 1232  
          */
 1233  
         public void deleteDocumentLinksByDocId(Long id) throws WorkflowException{
 1234  0
                 KEWServiceLocator.getDocumentLinkService().deleteDocumentLinksByDocId(id);
 1235  0
         }
 1236  
 
 1237  
         private DocumentLink initDocLink(DocumentLinkDTO docLinkVO){
 1238  0
                 DocumentLink docLink = new DocumentLink();
 1239  0
                 docLink.setDocLinkId(docLinkVO.getLinbkId());
 1240  0
                 docLink.setOrgnDocId(docLinkVO.getOrgnDocId());
 1241  0
                 docLink.setDestDocId(docLinkVO.getDestDocId());
 1242  
 
 1243  0
                 return docLink;
 1244  
         }
 1245  
 }