View Javadoc
1   /**
2    * Copyright 2005-2016 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kew.impl.document;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.apache.log4j.Logger;
20  import org.joda.time.DateTime;
21  import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
22  import org.kuali.rice.core.api.exception.RiceIllegalStateException;
23  import org.kuali.rice.kew.actionrequest.ActionRequestValue;
24  import org.kuali.rice.kew.actiontaken.ActionTakenValue;
25  import org.kuali.rice.kew.api.action.ActionRequest;
26  import org.kuali.rice.kew.api.action.ActionTaken;
27  import org.kuali.rice.kew.api.document.Document;
28  import org.kuali.rice.kew.api.document.DocumentContent;
29  import org.kuali.rice.kew.api.document.DocumentDetail;
30  import org.kuali.rice.kew.api.document.DocumentLink;
31  import org.kuali.rice.kew.api.document.DocumentStatus;
32  import org.kuali.rice.kew.api.document.WorkflowDocumentService;
33  import org.kuali.rice.kew.api.document.node.RouteNodeInstance;
34  import org.kuali.rice.kew.api.document.search.DocumentSearchCriteria;
35  import org.kuali.rice.kew.api.document.search.DocumentSearchResults;
36  import org.kuali.rice.kew.doctype.bo.DocumentType;
37  import org.kuali.rice.kew.dto.DTOConverter;
38  import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
39  import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValueContent;
40  import org.kuali.rice.kew.routeheader.DocumentStatusTransition;
41  import org.kuali.rice.kew.service.KEWServiceLocator;
42  
43  import javax.jws.WebParam;
44  import java.math.BigDecimal;
45  import java.sql.Timestamp;
46  import java.util.ArrayList;
47  import java.util.Collection;
48  import java.util.Collections;
49  import java.util.List;
50  
51  /**
52   * 
53   * @author Kuali Rice Team (rice.collab@kuali.org)
54   *
55   */
56  public class WorkflowDocumentServiceImpl implements WorkflowDocumentService {
57  
58  	private static final Logger LOG = Logger.getLogger(WorkflowDocumentServiceImpl.class);
59  	
60  	@Override
61  	public Document getDocument(String documentId) {
62  		if (StringUtils.isBlank(documentId)) {
63  			throw new RiceIllegalArgumentException("documentId was blank or null");
64  		}
65  		DocumentRouteHeaderValue documentBo = KEWServiceLocator.getRouteHeaderService().getRouteHeader(documentId);
66  		return DocumentRouteHeaderValue.to(documentBo);
67  	}
68  
69  	@Override
70  	public boolean doesDocumentExist(String documentId) {
71  	    if (StringUtils.isBlank(documentId)) {
72              throw new RiceIllegalArgumentException("documentId was blank or null");
73          }
74  	    DocumentRouteHeaderValue documentBo = KEWServiceLocator.getRouteHeaderService().getRouteHeader(documentId);
75  	    return documentBo != null;
76  	}
77  
78      @Override
79      public String getDocumentTypeName(String documentId) {
80          if (StringUtils.isBlank(documentId)) {
81              throw new RiceIllegalArgumentException("documentId was blank or null");
82          }
83          DocumentType documentType = KEWServiceLocator.getDocumentTypeService().findByDocumentId(documentId);
84          if (documentType == null) {
85              throw new RiceIllegalArgumentException("Failed to determine document type name for document with id "
86                      + documentId
87                      + ". Perhaps document does not exist?");
88          }
89          return documentType.getName();
90      }
91  
92  
93      @Override
94      public DocumentDetail getDocumentDetailByAppId(String documentTypeName, String appId) {
95          if (StringUtils.isEmpty(documentTypeName)) {
96              throw new RiceIllegalArgumentException("documentTypeName was blank or null");
97          }
98          if (StringUtils.isEmpty(appId)) {
99              throw new RiceIllegalArgumentException("appId was blank or null");
100         }
101 
102         Collection documentIds = KEWServiceLocator.getRouteHeaderService().findByDocTypeAndAppId(documentTypeName, appId);
103         if(documentIds==null||documentIds.isEmpty()){
104             throw new RiceIllegalStateException("No RouteHeader Ids found for documentTypName: " + documentTypeName + ", appId: " + appId);
105         }
106         if(documentIds.size()>1){
107             throw new RiceIllegalStateException("Multiple RouteHeader Ids found for documentTypName: " + documentTypeName + ", appId: " + appId);
108 		}
109 
110         return getDocumentDetail((String)documentIds.iterator().next());
111 	}
112 
113     public RouteNodeInstance getRouteNodeInstance(String nodeInstanceId)  {
114         if (StringUtils.isEmpty(nodeInstanceId)) {
115             throw new RiceIllegalArgumentException("nodeInstanceId was blank or null");
116         }
117         if ( LOG.isDebugEnabled() ) {
118         	LOG.debug("Fetching RouteNodeInstanceVO [id="+nodeInstanceId+"]");
119         }
120         org.kuali.rice.kew.engine.node.RouteNodeInstance nodeInstance = KEWServiceLocator.getRouteNodeService().findRouteNodeInstanceById(nodeInstanceId);
121         return org.kuali.rice.kew.engine.node.RouteNodeInstance.to(nodeInstance);
122     }
123 
124     @Override
125     public DocumentStatus getDocumentStatus(String documentId) {
126         if (StringUtils.isEmpty(documentId)) {
127             throw new RiceIllegalArgumentException("documentId was blank or null");
128         }
129         String documentStatus = KEWServiceLocator.getRouteHeaderService().getDocumentStatus(documentId);
130         if (StringUtils.isEmpty(documentStatus)) {
131             throw new RiceIllegalStateException("DocumentStatus not found for documentId: " + documentId);
132         }
133         return DocumentStatus.fromCode(documentStatus);
134     }
135 
136     @Override
137     public String getApplicationDocumentId(String documentId) {
138         if (StringUtils.isEmpty(documentId)) {
139             throw new RiceIllegalArgumentException("documentId was blank or null");
140         }
141  	 	return KEWServiceLocator.getRouteHeaderService().getAppDocId(documentId);
142  	}
143 
144     @Override
145     public String getApplicationDocumentStatus(String documentId)
146             throws RiceIllegalArgumentException {
147         if (StringUtils.isEmpty(documentId)) {
148             throw new RiceIllegalArgumentException("documentId was blank or null");
149         }
150         return KEWServiceLocator.getRouteHeaderService().getAppDocStatus(documentId);
151     }
152 
153     @Override
154     public DocumentSearchResults documentSearch(String principalId, DocumentSearchCriteria criteria) {
155         if (criteria == null) {
156             throw new RiceIllegalArgumentException("criteria was null");
157         }
158         return KEWServiceLocator.getDocumentSearchService().lookupDocuments(principalId, criteria);
159     }
160 
161     @Override
162     public DocumentSearchResults documentSearchSaveable(String principalId, DocumentSearchCriteria criteria, boolean saveSearch) {
163         if (criteria == null) {
164             throw new RiceIllegalArgumentException("criteria was null");
165         }
166         return KEWServiceLocator.getDocumentSearchService().lookupDocuments(principalId, criteria, saveSearch);
167     }
168 
169     @Override
170     public List<String> getSearchableAttributeStringValuesByKey(String documentId, String key) {
171         if (StringUtils.isEmpty(documentId)) {
172             throw new RiceIllegalArgumentException("documentId was blank or null");
173         }
174         if (StringUtils.isEmpty(key)) {
175             throw new RiceIllegalArgumentException("key was blank or null");
176         }
177 		return KEWServiceLocator.getRouteHeaderService().getSearchableAttributeStringValuesByKey(documentId, key);
178 	}
179 
180     @Override
181 	public List<DateTime> getSearchableAttributeDateTimeValuesByKey(String documentId, String key) {
182 		if (StringUtils.isEmpty(documentId)) {
183             throw new RiceIllegalArgumentException("documentId was blank or null");
184         }
185         if (StringUtils.isEmpty(key)) {
186             throw new RiceIllegalArgumentException("key was blank or null");
187         }
188 
189         List<Timestamp> results = KEWServiceLocator.getRouteHeaderService().getSearchableAttributeDateTimeValuesByKey(documentId, key);
190         if (results == null) {
191             return null;
192         }
193         List<DateTime> dateTimes = new ArrayList<DateTime>();
194 
195 		for(Timestamp time : results) {
196             dateTimes.add(new DateTime(time.getTime()));
197         }
198         return dateTimes;
199 	}
200 
201     @Override
202 	public List<BigDecimal> getSearchableAttributeFloatValuesByKey(String documentId, String key) {
203         if (StringUtils.isEmpty(documentId)) {
204             throw new RiceIllegalArgumentException("documentId was blank or null");
205         }
206         if (StringUtils.isEmpty(key)) {
207             throw new RiceIllegalArgumentException("key was blank or null");
208         }
209 		return KEWServiceLocator.getRouteHeaderService().getSearchableAttributeFloatValuesByKey(documentId, key);
210 	}
211 
212     @Override
213     public List<Long> getSearchableAttributeLongValuesByKey(String documentId, String key) {
214         if (StringUtils.isEmpty(documentId)) {
215             throw new RiceIllegalArgumentException("documentId was blank or null");
216         }
217         if (StringUtils.isEmpty(key)) {
218             throw new RiceIllegalArgumentException("key was blank or null");
219         }
220 		return KEWServiceLocator.getRouteHeaderService().getSearchableAttributeLongValuesByKey(documentId, key);
221 	}
222 	
223 	@Override
224 	public DocumentContent getDocumentContent(String documentId) {
225 		if (StringUtils.isBlank(documentId)) {
226 			throw new RiceIllegalArgumentException("documentId was blank or null");
227 		}
228 		DocumentRouteHeaderValueContent content = KEWServiceLocator.getRouteHeaderService().getContent(documentId);
229 		return DocumentRouteHeaderValueContent.to(content);
230 	}
231 
232 	@Override
233 	public List<ActionRequest> getRootActionRequests(String documentId) {
234         if (StringUtils.isBlank(documentId)) {
235 			throw new RiceIllegalArgumentException("documentId was blank or null");
236 		}
237 		List<ActionRequest> actionRequests = new ArrayList<ActionRequest>();
238 		List<ActionRequestValue> actionRequestBos = KEWServiceLocator.getActionRequestService().findAllRootActionRequestsByDocumentId(documentId);
239 		for (ActionRequestValue actionRequestBo : actionRequestBos) {
240 			actionRequests.add(ActionRequestValue.to(actionRequestBo));
241 		}
242 		return Collections.unmodifiableList(actionRequests);
243 	}
244 	
245 	@Override
246 	public List<ActionRequest> getPendingActionRequests(String documentId) {
247 		if (StringUtils.isBlank(documentId)) {
248 			throw new RiceIllegalArgumentException("documentId was blank or null");
249 		}
250 		List<ActionRequest> actionRequests = new ArrayList<ActionRequest>();
251 		List<ActionRequestValue> actionRequestBos = KEWServiceLocator.getActionRequestService().findAllPendingRequests(documentId);
252 		for (ActionRequestValue actionRequestBo : actionRequestBos) {
253 			actionRequests.add(ActionRequestValue.to(actionRequestBo));
254 		}
255 		return Collections.unmodifiableList(actionRequests);
256 	}
257 	
258 	@Override
259 	public List<ActionRequest> getActionRequestsForPrincipalAtNode(String documentId, String nodeName,
260             String principalId) {
261         if (StringUtils.isBlank(documentId)) {
262         	throw new RiceIllegalArgumentException("documentId was null or blank");
263         }
264         if ( LOG.isDebugEnabled() ) {
265         	LOG.debug("Fetching ActionRequests [docId="+documentId+", nodeName="+nodeName+", principalId="+principalId+"]");
266         }
267         List<ActionRequestValue> actionRequestBos = KEWServiceLocator.getActionRequestService().findAllActionRequestsByDocumentId(documentId);
268         List<ActionRequestValue> matchingActionRequests = new ArrayList<ActionRequestValue>();
269         for (ActionRequestValue actionRequestValue : actionRequestBos) {
270             if (actionRequestMatches(actionRequestValue, nodeName, principalId)) {
271                 matchingActionRequests.add(actionRequestValue);
272             }
273         }
274         List<ActionRequest> actionRequests = new ArrayList<ActionRequest>(matchingActionRequests.size());
275         for (ActionRequestValue matchingActionRequest : matchingActionRequests) {
276         	actionRequests.add(ActionRequestValue.to(matchingActionRequest));
277         }
278         return actionRequests;
279     }
280 	
281     protected boolean actionRequestMatches(ActionRequestValue actionRequest, String nodeName, String principalId) {
282         boolean matchesUserId = true;  // assume a match in case user is empty
283         boolean matchesNodeName = true;  // assume a match in case node name is empty
284         if (StringUtils.isNotBlank(nodeName)) {
285             matchesNodeName = nodeName.equals(actionRequest.getPotentialNodeName());
286         }
287         if (principalId != null) {
288             matchesUserId = actionRequest.isRecipientRoutedRequest(principalId);
289         }
290         return matchesNodeName && matchesUserId;
291     }
292 
293 
294 	@Override
295 	public List<ActionTaken> getActionsTaken(String documentId) {
296         if (StringUtils.isEmpty(documentId)) {
297             throw new RiceIllegalArgumentException("documentId is null or empty.");
298         }
299 		List<ActionTaken> actionTakens = new ArrayList<ActionTaken>();
300 		Collection<ActionTakenValue> actionTakenBos = KEWServiceLocator.getActionTakenService().findByDocumentId(documentId);
301 		for (ActionTakenValue actionTakenBo : actionTakenBos) {
302 			actionTakens.add(ActionTakenValue.to(actionTakenBo));
303 		}
304 		return actionTakens;
305 	}
306 
307     @Override
308     public List<ActionTaken> _getActionsTaken(String documentId) {
309         return getActionsTaken(documentId);
310     }
311 
312     @Override
313     public List<ActionTaken> getAllActionsTaken(String documentId){
314         if(StringUtils.isEmpty(documentId)){
315             throw new RiceIllegalArgumentException("documentId is null or empty.");
316         }
317 
318 		List<ActionTaken> actionsTaken = new ArrayList<ActionTaken>();
319         Collection<ActionTakenValue> actionTakenBos = KEWServiceLocator.getActionTakenService().findByDocumentIdIgnoreCurrentInd(documentId);
320 		for (ActionTakenValue actionTakenBo : actionTakenBos) {
321 			actionsTaken.add(ActionTakenValue.to(actionTakenBo));
322 		}
323        return actionsTaken;
324     }
325 	
326 	@Override
327 	public DocumentDetail getDocumentDetail(@WebParam(name = "documentId") String documentId) {
328 		if (StringUtils.isBlank(documentId)) {
329             throw new RiceIllegalArgumentException("documentId was null or blank");
330         }
331         if ( LOG.isDebugEnabled() ) {
332         	LOG.debug("Fetching DocumentDetail [id="+documentId+"]");
333         }
334         DocumentRouteHeaderValue document = KEWServiceLocator.getRouteHeaderService().getRouteHeader(documentId);
335         if (document == null) {
336         	return null;
337         }
338         DocumentDetail documentDetailVO = DTOConverter.convertDocumentDetailNew(document);
339         if ( LOG.isDebugEnabled() ) {
340         	LOG.debug("Returning DocumentDetailVO [id=" + documentId + "]");
341         }
342         return documentDetailVO;
343 	}
344 
345     @Override
346     public List<org.kuali.rice.kew.api.document.DocumentStatusTransition> getDocumentStatusTransitionHistory(String documentId) {
347 		if (StringUtils.isBlank(documentId)) {
348             throw new RiceIllegalArgumentException("documentId was null or blank");
349         }
350         if ( LOG.isDebugEnabled() ) {
351             LOG.debug("Fetching document status transition history [id="+documentId+"]");
352         }
353         DocumentRouteHeaderValue document = KEWServiceLocator.getRouteHeaderService().getRouteHeader(documentId);;
354 
355         List<DocumentStatusTransition> list = document.getAppDocStatusHistory();
356 
357         List<org.kuali.rice.kew.api.document.DocumentStatusTransition> transitionHistory = new ArrayList<org.kuali.rice.kew.api.document.DocumentStatusTransition>(list.size());
358 
359         for (DocumentStatusTransition transition : list) {
360             transitionHistory.add(DocumentStatusTransition.to(transition));
361         }
362         return transitionHistory;
363     }
364 	
365 	@Override
366 	public List<RouteNodeInstance> getRouteNodeInstances(String documentId) {
367     	if (StringUtils.isBlank(documentId)) {
368             throw new RiceIllegalArgumentException("documentId was null or blank");
369         }
370 
371         if ( LOG.isDebugEnabled() ) {
372     		LOG.debug("Fetching RouteNodeInstances [documentId=" + documentId + "]");
373     	}
374     	DocumentRouteHeaderValue documentBo = KEWServiceLocator.getRouteHeaderService().getRouteHeader(documentId);
375     	if (documentBo == null) {
376     		return Collections.emptyList();
377     	}
378     	return convertRouteNodeInstances(KEWServiceLocator.getRouteNodeService().getFlattenedNodeInstances(documentBo, true));
379     }	
380 	
381 	@Override
382 	public List<RouteNodeInstance> getActiveRouteNodeInstances(String documentId) {
383 		if (StringUtils.isBlank(documentId)) {
384             throw new RiceIllegalArgumentException("documentId was null or blank");
385         }
386 
387         if ( LOG.isDebugEnabled() ) {
388     		LOG.debug("Fetching active RouteNodeInstances [documentId=" + documentId + "]");
389     	}
390         return convertRouteNodeInstances(KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(documentId));
391 	}
392 
393     @Override
394     public List<RouteNodeInstance> getTerminalRouteNodeInstances(String documentId) {
395     	if (StringUtils.isBlank(documentId)) {
396             throw new RiceIllegalArgumentException("documentId was null or blank");
397         }
398 
399         if ( LOG.isDebugEnabled() ) {
400     		LOG.debug("Fetching terminal RouteNodeInstanceVOs [docId=" + documentId + "]");
401     	}
402         return convertRouteNodeInstances(KEWServiceLocator.getRouteNodeService().getTerminalNodeInstances(documentId));
403     }
404 
405     public List<RouteNodeInstance> getCurrentRouteNodeInstances(String documentId) {
406     	if (StringUtils.isBlank(documentId)) {
407             throw new RiceIllegalArgumentException("documentId was null or blank");
408         }
409 
410         if ( LOG.isDebugEnabled() ) {
411     		LOG.debug("Fetching current RouteNodeInstanceVOs [docId=" + documentId + "]");
412     	}
413     	return convertRouteNodeInstances(KEWServiceLocator.getRouteNodeService().getCurrentNodeInstances(documentId));
414     }
415     
416     public List<String> getActiveRouteNodeNames(String documentId) {
417     	if (StringUtils.isBlank(documentId)) {
418             throw new RiceIllegalArgumentException("documentId was null or blank");
419         }
420     	
421     	final List<String> nodes = KEWServiceLocator.getRouteNodeService().getActiveRouteNodeNames(documentId);
422     	return nodes != null ? Collections.unmodifiableList(nodes) : Collections.<String>emptyList();
423     }
424     
425     public List<String> getTerminalRouteNodeNames(String documentId) {
426     	if (StringUtils.isBlank(documentId)) {
427             throw new RiceIllegalArgumentException("documentId was null or blank");
428         }
429     	
430     	final List<String> nodes = KEWServiceLocator.getRouteNodeService().getTerminalRouteNodeNames(documentId);
431     	return nodes != null ? Collections.unmodifiableList(nodes) : Collections.<String>emptyList();
432     }
433 
434     public List<String> getCurrentRouteNodeNames(String documentId) {
435     	if (StringUtils.isBlank(documentId)) {
436             throw new RiceIllegalArgumentException("documentId was null or blank");
437         }
438     	
439     	final List<String> nodes = KEWServiceLocator.getRouteNodeService().getCurrentRouteNodeNames(documentId);
440     	return nodes != null ? Collections.unmodifiableList(nodes) : Collections.<String>emptyList();
441     }
442 
443 	private List<RouteNodeInstance> convertRouteNodeInstances(List<org.kuali.rice.kew.engine.node.RouteNodeInstance> routeNodeInstanceBos) {
444 		List<RouteNodeInstance> routeNodeInstances = new ArrayList<RouteNodeInstance>();
445         for (org.kuali.rice.kew.engine.node.RouteNodeInstance routeNodeInstanceBo : routeNodeInstanceBos) {
446         	routeNodeInstances.add(org.kuali.rice.kew.engine.node.RouteNodeInstance.to(routeNodeInstanceBo));
447         }
448         return Collections.unmodifiableList(routeNodeInstances);
449 	}
450 	
451 	@Override
452 	public List<String> getPreviousRouteNodeNames(String documentId) {
453 
454 		if (StringUtils.isBlank(documentId)) {
455             throw new RiceIllegalArgumentException("documentId was null or blank");
456         }
457         if ( LOG.isDebugEnabled() ) {
458 			LOG.debug("Fetching previous node names [documentId=" + documentId + "]");
459 		}
460         return new ArrayList<String>(KEWServiceLocator.getRouteNodeService().findPreviousNodeNames(documentId));
461 	}
462 
463     @Override
464     public List<String> getPrincipalIdsWithPendingActionRequestByActionRequestedAndDocId(String actionRequestedCd, String documentId){
465     	if (StringUtils.isEmpty(actionRequestedCd)) {
466             throw new RiceIllegalArgumentException("actionRequestCd was blank or null");
467         }
468         if (StringUtils.isEmpty(documentId)) {
469             throw new RiceIllegalArgumentException("documentId was blank or null");
470         }
471         return KEWServiceLocator.getActionRequestService().
472     				getPrincipalIdsWithPendingActionRequestByActionRequestedAndDocId(actionRequestedCd, documentId);
473     }
474 
475     @Override
476     public String getDocumentInitiatorPrincipalId(String documentId) {
477         if (StringUtils.isEmpty(documentId)) {
478             throw new RiceIllegalArgumentException("documentId was blank or null");
479         }
480 
481         DocumentRouteHeaderValue header = KEWServiceLocator.getRouteHeaderService().getRouteHeader(documentId, false);
482         if ( header == null) {
483         	return null;
484         }
485     	return header.getInitiatorWorkflowId();
486     }
487 
488     @Override
489     public String getRoutedByPrincipalIdByDocumentId(String documentId) {
490         if (StringUtils.isEmpty(documentId)) {
491             throw new RiceIllegalArgumentException("documentId was blank or null");
492         }
493 
494         DocumentRouteHeaderValue header = KEWServiceLocator.getRouteHeaderService().getRouteHeader(documentId, false);
495         if ( header == null) {
496         	return null;
497         }
498     	return header.getRoutedByUserWorkflowId();
499     }
500 
501 	@Override
502 	public DocumentLink addDocumentLink(DocumentLink documentLink) throws RiceIllegalArgumentException {
503 		if (documentLink == null) {
504 			throw new RiceIllegalArgumentException("documentLink was null");
505 		}
506 		if (documentLink.getId() != null) {
507 			throw new RiceIllegalArgumentException("the given documentLink already has an id, cannot add a document link with an existing id");
508 		}
509 		org.kuali.rice.kew.documentlink.DocumentLink documentLinkBo = org.kuali.rice.kew.documentlink.DocumentLink.from(documentLink);
510 		documentLinkBo = KEWServiceLocator.getDocumentLinkService().saveDocumentLink(documentLinkBo);
511 		return org.kuali.rice.kew.documentlink.DocumentLink.to(documentLinkBo);
512 	}
513 
514 	@Override
515 	public DocumentLink deleteDocumentLink(String documentLinkId) throws RiceIllegalArgumentException {
516 		if (StringUtils.isBlank(documentLinkId)) {
517 			throw new RiceIllegalArgumentException("documentLinkId was null or blank");
518 		}
519 		org.kuali.rice.kew.documentlink.DocumentLink documentLinkBo = KEWServiceLocator.getDocumentLinkService().getDocumentLink(documentLinkId);
520 		if (documentLinkBo == null) {
521 			throw new RiceIllegalStateException("Failed to locate document link with the given documentLinkId: " + documentLinkId);
522 		}
523 		KEWServiceLocator.getDocumentLinkService().deleteDocumentLink(documentLinkBo);
524 		return org.kuali.rice.kew.documentlink.DocumentLink.to(documentLinkBo);
525 	}
526 	    
527 	@Override
528 	public List<DocumentLink> deleteDocumentLinksByDocumentId(String originatingDocumentId) throws RiceIllegalArgumentException {
529 		if (StringUtils.isBlank(originatingDocumentId)) {
530 			throw new RiceIllegalArgumentException("originatingDocumentId was null or blank");
531 		}
532 		List<org.kuali.rice.kew.documentlink.DocumentLink> documentLinkBos = KEWServiceLocator.getDocumentLinkService().getLinkedDocumentsByDocId(originatingDocumentId);
533 		if (documentLinkBos == null || documentLinkBos.isEmpty()) {
534 			return Collections.emptyList();
535 		}
536 		List<DocumentLink> deletedDocumentLinks = new ArrayList<DocumentLink>();
537 		for (org.kuali.rice.kew.documentlink.DocumentLink documentLinkBo : documentLinkBos) {
538 			deletedDocumentLinks.add(org.kuali.rice.kew.documentlink.DocumentLink.to(documentLinkBo));
539 			KEWServiceLocator.getDocumentLinkService().deleteDocumentLink(documentLinkBo);
540 		}
541 		return Collections.unmodifiableList(deletedDocumentLinks);
542     }
543 	    
544 	@Override
545 	public List<DocumentLink> getOutgoingDocumentLinks(String originatingDocumentId) throws RiceIllegalArgumentException {
546 		if (StringUtils.isBlank(originatingDocumentId)) {
547 			throw new RiceIllegalArgumentException("originatingDocumentId was null or blank");
548 		}
549 		List<org.kuali.rice.kew.documentlink.DocumentLink> outgoingDocumentLinkBos = KEWServiceLocator.getDocumentLinkService().getLinkedDocumentsByDocId(originatingDocumentId);
550 		List<DocumentLink> outgoingDocumentLinks = new ArrayList<DocumentLink>();
551 		for (org.kuali.rice.kew.documentlink.DocumentLink outgoingDocumentLinkBo : outgoingDocumentLinkBos) {
552 			outgoingDocumentLinks.add(org.kuali.rice.kew.documentlink.DocumentLink.to(outgoingDocumentLinkBo));
553 		}
554 		return Collections.unmodifiableList(outgoingDocumentLinks);
555     }
556 	
557 	@Override
558 	public List<DocumentLink> getIncomingDocumentLinks(String destinationDocumentId) throws RiceIllegalArgumentException {
559 		if (StringUtils.isBlank(destinationDocumentId)) {
560 			throw new RiceIllegalArgumentException("destinationDocumentId was null or blank");
561 		}
562 		List<org.kuali.rice.kew.documentlink.DocumentLink> incomingDocumentLinkBos = KEWServiceLocator.getDocumentLinkService().getOutgoingLinkedDocumentsByDocId(destinationDocumentId);
563 		List<DocumentLink> incomingDocumentLinks = new ArrayList<DocumentLink>();
564 		for (org.kuali.rice.kew.documentlink.DocumentLink incomingDocumentLinkBo : incomingDocumentLinkBos) {
565 			incomingDocumentLinks.add(org.kuali.rice.kew.documentlink.DocumentLink.to(incomingDocumentLinkBo));
566 		}
567 		return Collections.unmodifiableList(incomingDocumentLinks);
568     }
569 	    
570 	@Override
571 	public DocumentLink getDocumentLink(String documentLinkId) throws RiceIllegalArgumentException {
572 		if (StringUtils.isBlank(documentLinkId)) {
573 			throw new RiceIllegalArgumentException("documentLinkId was null or blank");
574 		}
575 		org.kuali.rice.kew.documentlink.DocumentLink documentLinkBo = KEWServiceLocator.getDocumentLinkService().getDocumentLink(documentLinkId);
576 		return org.kuali.rice.kew.documentlink.DocumentLink.to(documentLinkBo);
577     }
578 	
579 }