1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kew.impl.document;
17
18 import java.io.Serializable;
19 import java.util.Arrays;
20 import java.util.Collections;
21 import java.util.Date;
22 import java.util.HashSet;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Set;
26
27 import org.apache.commons.lang.StringUtils;
28 import org.joda.time.DateTime;
29 import org.kuali.rice.core.api.uif.RemotableAttributeErrorContract;
30 import org.kuali.rice.kew.api.KewApiConstants;
31 import org.kuali.rice.kew.api.KewApiServiceLocator;
32 import org.kuali.rice.kew.api.action.ActionRequest;
33 import org.kuali.rice.kew.api.action.ActionRequestType;
34 import org.kuali.rice.kew.api.action.ActionTaken;
35 import org.kuali.rice.kew.api.action.ActionType;
36 import org.kuali.rice.kew.api.action.AdHocRevoke;
37 import org.kuali.rice.kew.api.action.AdHocToGroup;
38 import org.kuali.rice.kew.api.action.AdHocToPrincipal;
39 import org.kuali.rice.kew.api.action.DocumentActionParameters;
40 import org.kuali.rice.kew.api.action.DocumentActionResult;
41 import org.kuali.rice.kew.api.action.MovePoint;
42 import org.kuali.rice.kew.api.action.RequestedActions;
43 import org.kuali.rice.kew.api.action.ReturnPoint;
44 import org.kuali.rice.kew.api.action.ValidActions;
45 import org.kuali.rice.kew.api.action.WorkflowDocumentActionsService;
46 import org.kuali.rice.kew.api.document.Document;
47 import org.kuali.rice.kew.api.document.DocumentContent;
48 import org.kuali.rice.kew.api.document.DocumentContentUpdate;
49 import org.kuali.rice.kew.api.document.DocumentDetail;
50 import org.kuali.rice.kew.api.document.DocumentStatus;
51 import org.kuali.rice.kew.api.document.DocumentUpdate;
52 import org.kuali.rice.kew.api.document.attribute.WorkflowAttributeDefinition;
53 import org.kuali.rice.kew.api.document.node.RouteNodeInstance;
54 import org.kuali.rice.kew.api.document.WorkflowDocumentService;
55
56
57
58
59
60
61
62
63 public class WorkflowDocumentImpl implements Serializable, WorkflowDocumentPrototype {
64
65 private static final long serialVersionUID = -3672966990721719088L;
66
67
68
69
70 private String principalId;
71
72
73
74 private ModifiableDocument modifiableDocument;
75
76
77
78 private ModifiableDocumentContent modifiableDocumentContent;
79
80
81
82
83 private ValidActions validActions;
84
85
86
87
88 private RequestedActions requestedActions;
89
90
91
92 private boolean documentDeleted = false;
93
94 private transient WorkflowDocumentActionsService workflowDocumentActionsService;
95 private transient WorkflowDocumentService workflowDocumentService;
96
97 public void init(String principalId, Document document) {
98 if (StringUtils.isBlank("principalId")) {
99 throw new IllegalArgumentException("principalId was null or blank");
100 }
101 if (document == null) {
102 throw new IllegalArgumentException("document was null");
103 }
104 this.principalId = principalId;
105 this.modifiableDocument = new ModifiableDocument(document);
106 this.modifiableDocumentContent = null;
107 this.validActions = null;
108 this.requestedActions = null;
109 }
110
111 public WorkflowDocumentActionsService getWorkflowDocumentActionsService() {
112 if (workflowDocumentActionsService == null) {
113 workflowDocumentActionsService = KewApiServiceLocator.getWorkflowDocumentActionsService();
114 }
115 return workflowDocumentActionsService;
116 }
117
118 public void setWorkflowDocumentActionsService(WorkflowDocumentActionsService workflowDocumentActionsService) {
119 this.workflowDocumentActionsService = workflowDocumentActionsService;
120 }
121
122 public WorkflowDocumentService getWorkflowDocumentService() {
123 if (workflowDocumentService == null) {
124 workflowDocumentService = KewApiServiceLocator.getWorkflowDocumentService();
125 }
126 return workflowDocumentService;
127 }
128
129 public void setWorkflowDocumentService(WorkflowDocumentService workflowDocumentService) {
130 this.workflowDocumentService = workflowDocumentService;
131 }
132
133 protected ModifiableDocument getModifiableDocument() {
134 return modifiableDocument;
135 }
136
137 protected ModifiableDocumentContent getModifiableDocumentContent() {
138 if (this.modifiableDocumentContent == null) {
139 DocumentContent documentContent = getWorkflowDocumentService().getDocumentContent(getDocumentId());
140 if (documentContent == null) {
141 throw new IllegalStateException("Failed to load document content for documentId: " + getDocumentId());
142 }
143 this.modifiableDocumentContent = new ModifiableDocumentContent(documentContent);
144 }
145 return this.modifiableDocumentContent;
146 }
147
148 @Override
149 public String getDocumentId() {
150 if (documentDeleted) {
151 throw new IllegalStateException("Document has been deleted.");
152 }
153 return getModifiableDocument().getDocumentId();
154 }
155
156 @Override
157 public Document getDocument() {
158 return getModifiableDocument().getDocument();
159 }
160
161 @Override
162 public DocumentContent getDocumentContent() {
163 return getModifiableDocumentContent().getDocumentContent();
164 }
165
166 @Override
167 public String getApplicationContent() {
168 return getDocumentContent().getApplicationContent();
169 }
170
171 @Override
172 public void setApplicationContent(String applicationContent) {
173 getModifiableDocumentContent().setApplicationContent(applicationContent);
174 }
175
176 @Override
177 public void setAttributeContent(String attributeContent) {
178 getModifiableDocumentContent().setAttributeContent(attributeContent);
179 }
180
181 @Override
182 public void clearAttributeContent() {
183 getModifiableDocumentContent().setAttributeContent("");
184 }
185
186 @Override
187 public String getAttributeContent() {
188 return getDocumentContent().getAttributeContent();
189 }
190
191 @Override
192 public void addAttributeDefinition(WorkflowAttributeDefinition attributeDefinition) {
193 getModifiableDocumentContent().addAttributeDefinition(attributeDefinition);
194 }
195
196 @Override
197 public void removeAttributeDefinition(WorkflowAttributeDefinition attributeDefinition) {
198 getModifiableDocumentContent().removeAttributeDefinition(attributeDefinition);
199 }
200
201 @Override
202 public void clearAttributeDefinitions() {
203 getAttributeDefinitions().clear();
204 }
205
206 @Override
207 public List<WorkflowAttributeDefinition> getAttributeDefinitions() {
208 return getModifiableDocumentContent().getAttributeDefinitions();
209 }
210
211 @Override
212 public void setSearchableContent(String searchableContent) {
213 getModifiableDocumentContent().setSearchableContent(searchableContent);
214 }
215
216 @Override
217 public void addSearchableDefinition(WorkflowAttributeDefinition searchableDefinition) {
218 getModifiableDocumentContent().addSearchableDefinition(searchableDefinition);
219 }
220
221 @Override
222 public void removeSearchableDefinition(WorkflowAttributeDefinition searchableDefinition) {
223 getModifiableDocumentContent().removeSearchableDefinition(searchableDefinition);
224 }
225
226 @Override
227 public void clearSearchableDefinitions() {
228 getSearchableDefinitions().clear();
229 }
230
231 @Override
232 public void clearSearchableContent() {
233 getModifiableDocumentContent().setSearchableContent("");
234 }
235
236 @Override
237 public List<WorkflowAttributeDefinition> getSearchableDefinitions() {
238 return getModifiableDocumentContent().getSearchableDefinitions();
239 }
240
241 @Override
242 public List<? extends RemotableAttributeErrorContract> validateAttributeDefinition(
243 WorkflowAttributeDefinition attributeDefinition) {
244 return getWorkflowDocumentActionsService().validateWorkflowAttributeDefinition(attributeDefinition);
245 }
246
247 @Override
248 public List<ActionRequest> getRootActionRequests() {
249 return getWorkflowDocumentService().getRootActionRequests(getDocumentId());
250 }
251
252 @Override
253 public List<ActionTaken> getActionsTaken() {
254 return getWorkflowDocumentService().getActionsTaken(getDocumentId());
255 }
256
257 @Override
258 public void setApplicationDocumentId(String applicationDocumentId) {
259 getModifiableDocument().setApplicationDocumentId(applicationDocumentId);
260 }
261
262 @Override
263 public String getApplicationDocumentId() {
264 return getModifiableDocument().getApplicationDocumentId();
265 }
266
267 @Override
268 public DateTime getDateCreated() {
269 return getModifiableDocument().getDateCreated();
270 }
271
272 @Override
273 public String getTitle() {
274 return getModifiableDocument().getTitle();
275 }
276
277 @Override
278 public ValidActions getValidActions() {
279 if (validActions == null) {
280 validActions = getWorkflowDocumentActionsService().determineValidActions(getDocumentId(), getPrincipalId());
281 }
282 return validActions;
283 }
284
285 @Override
286 public RequestedActions getRequestedActions() {
287 if (requestedActions == null) {
288 requestedActions = getWorkflowDocumentActionsService().determineRequestedActions(getDocumentId(),
289 getPrincipalId());
290 }
291 return requestedActions;
292 }
293
294 protected DocumentUpdate getDocumentUpdateIfDirty() {
295 if (getModifiableDocument().isDirty()) {
296 return getModifiableDocument().build();
297 }
298 return null;
299 }
300
301 protected DocumentContentUpdate getDocumentContentUpdateIfDirty() {
302 if (getModifiableDocumentContent().isDirty()) {
303 return getModifiableDocumentContent().build();
304 }
305 return null;
306 }
307
308 protected void resetStateAfterAction(DocumentActionResult response) {
309 this.modifiableDocument = new ModifiableDocument(response.getDocument());
310 this.validActions = null;
311 if (response.getValidActions() != null) {
312 this.validActions = response.getValidActions();
313 }
314 this.requestedActions = null;
315 if (response.getRequestedActions() != null) {
316 this.requestedActions = response.getRequestedActions();
317 }
318
319 this.modifiableDocumentContent = null;
320 }
321
322 @Override
323 public void saveDocument(String annotation) {
324 DocumentActionResult result = getWorkflowDocumentActionsService().save(
325 constructDocumentActionParameters(annotation));
326 resetStateAfterAction(result);
327 }
328
329 @Override
330 public void route(String annotation) {
331 DocumentActionResult result = getWorkflowDocumentActionsService().route(
332 constructDocumentActionParameters(annotation));
333 resetStateAfterAction(result);
334 }
335
336 @Override
337 public void disapprove(String annotation) {
338 DocumentActionResult result = getWorkflowDocumentActionsService().disapprove(
339 constructDocumentActionParameters(annotation));
340 resetStateAfterAction(result);
341 }
342
343 @Override
344 public void approve(String annotation) {
345 DocumentActionResult result = getWorkflowDocumentActionsService().approve(
346 constructDocumentActionParameters(annotation));
347 resetStateAfterAction(result);
348 }
349
350 @Override
351 public void cancel(String annotation) {
352 DocumentActionResult result = getWorkflowDocumentActionsService().cancel(
353 constructDocumentActionParameters(annotation));
354 resetStateAfterAction(result);
355 }
356
357 @Override
358 public void recall(String annotation, boolean cancel) {
359 DocumentActionResult result = getWorkflowDocumentActionsService().recall(
360 constructDocumentActionParameters(annotation), cancel);
361 resetStateAfterAction(result);
362 }
363
364 @Override
365 public void blanketApprove(String annotation) {
366 DocumentActionResult result = getWorkflowDocumentActionsService().blanketApprove(
367 constructDocumentActionParameters(annotation));
368 resetStateAfterAction(result);
369 }
370
371 @Override
372 public void blanketApprove(String annotation, String... nodeNames) {
373 if (nodeNames == null) {
374 throw new IllegalArgumentException("nodeNames was null");
375 }
376 Set<String> nodeNamesSet = new HashSet<String>(Arrays.asList(nodeNames));
377 DocumentActionResult result = getWorkflowDocumentActionsService().blanketApproveToNodes(
378 constructDocumentActionParameters(annotation), nodeNamesSet);
379 resetStateAfterAction(result);
380 }
381
382 @Override
383 public void saveDocumentData() {
384 DocumentActionResult result = getWorkflowDocumentActionsService().saveDocumentData(
385 constructDocumentActionParameters(null));
386 resetStateAfterAction(result);
387 }
388
389 @Override
390 public void setApplicationDocumentStatus(String applicationDocumentStatus) {
391 getModifiableDocument().setApplicationDocumentStatus(applicationDocumentStatus);
392 }
393
394 @Override
395 public void acknowledge(String annotation) {
396 DocumentActionResult result = getWorkflowDocumentActionsService().acknowledge(
397 constructDocumentActionParameters(annotation));
398 resetStateAfterAction(result);
399 }
400
401 @Override
402 public void fyi(String annotation) {
403 DocumentActionResult result = getWorkflowDocumentActionsService().clearFyi(
404 constructDocumentActionParameters(annotation));
405 resetStateAfterAction(result);
406 }
407
408 @Override
409 public void fyi() {
410 fyi("");
411 }
412
413 @Override
414 public void delete() {
415 getWorkflowDocumentActionsService().delete(getDocumentId(), principalId);
416 documentDeleted = true;
417 }
418
419 @Override
420 public void refresh() {
421 Document document = getWorkflowDocumentService().getDocument(getDocumentId());
422 this.modifiableDocument = new ModifiableDocument(document);
423 this.validActions = null;
424 this.requestedActions = null;
425 this.modifiableDocumentContent = null;
426 }
427
428 @Override
429 public void adHocToPrincipal(ActionRequestType actionRequested, String annotation, String targetPrincipalId,
430 String responsibilityDescription, boolean forceAction) {
431 adHocToPrincipal(actionRequested, null, annotation, targetPrincipalId, responsibilityDescription, forceAction);
432 }
433
434 @Override
435 public void adHocToPrincipal(ActionRequestType actionRequested, String nodeName, String annotation,
436 String targetPrincipalId, String responsibilityDescription, boolean forceAction) {
437 adHocToPrincipal(actionRequested, nodeName, annotation, targetPrincipalId, responsibilityDescription,
438 forceAction, null);
439 }
440
441 @Override
442 public void adHocToPrincipal(ActionRequestType actionRequested, String nodeName, String annotation,
443 String targetPrincipalId, String responsibilityDescription, boolean forceAction, String requestLabel) {
444 AdHocToPrincipal.Builder builder = AdHocToPrincipal.Builder
445 .create(actionRequested, nodeName, targetPrincipalId);
446 builder.setResponsibilityDescription(responsibilityDescription);
447 builder.setForceAction(forceAction);
448 builder.setRequestLabel(requestLabel);
449 DocumentActionResult result = getWorkflowDocumentActionsService().adHocToPrincipal(
450 constructDocumentActionParameters(annotation), builder.build());
451 resetStateAfterAction(result);
452 }
453
454 @Override
455 public void adHocToPrincipal(AdHocToPrincipal adHocToPrincipal, String annotation) {
456 DocumentActionResult result = getWorkflowDocumentActionsService().adHocToPrincipal(
457 constructDocumentActionParameters(annotation), adHocToPrincipal);
458 resetStateAfterAction(result);
459 }
460
461 @Override
462 public void adHocToGroup(ActionRequestType actionRequested, String annotation, String targetGroupId,
463 String responsibilityDescription, boolean forceAction) {
464 adHocToGroup(actionRequested, null, annotation, targetGroupId, responsibilityDescription, forceAction);
465 }
466
467 @Override
468 public void adHocToGroup(ActionRequestType actionRequested, String nodeName, String annotation,
469 String targetGroupId, String responsibilityDescription, boolean forceAction) {
470 adHocToGroup(actionRequested, nodeName, annotation, targetGroupId, responsibilityDescription, forceAction, null);
471 }
472
473 @Override
474 public void adHocToGroup(ActionRequestType actionRequested, String nodeName, String annotation,
475 String targetGroupId, String responsibilityDescription, boolean forceAction, String requestLabel) {
476 AdHocToGroup.Builder builder = AdHocToGroup.Builder.create(actionRequested, nodeName, targetGroupId);
477 builder.setResponsibilityDescription(responsibilityDescription);
478 builder.setForceAction(forceAction);
479 builder.setRequestLabel(requestLabel);
480 DocumentActionResult result = getWorkflowDocumentActionsService().adHocToGroup(
481 constructDocumentActionParameters(annotation), builder.build());
482 resetStateAfterAction(result);
483 }
484
485 @Override
486 public void adHocToGroup(AdHocToGroup adHocToGroup, String annotation) {
487 DocumentActionResult result = getWorkflowDocumentActionsService().adHocToGroup(
488 constructDocumentActionParameters(annotation), adHocToGroup);
489 resetStateAfterAction(result);
490 }
491
492 @Override
493 public void revokeAdHocRequestById(String actionRequestId, String annotation) {
494 if (StringUtils.isBlank(actionRequestId)) {
495 throw new IllegalArgumentException("actionRequestId was null or blank");
496 }
497 DocumentActionResult result = getWorkflowDocumentActionsService().revokeAdHocRequestById(
498 constructDocumentActionParameters(annotation), actionRequestId);
499 resetStateAfterAction(result);
500 }
501
502 @Override
503 public void revokeAdHocRequests(AdHocRevoke revoke, String annotation) {
504 if (revoke == null) {
505 throw new IllegalArgumentException("revokeFromPrincipal was null");
506 }
507 DocumentActionResult result = getWorkflowDocumentActionsService().revokeAdHocRequests(
508 constructDocumentActionParameters(annotation), revoke);
509 resetStateAfterAction(result);
510 }
511
512 @Override
513 public void revokeAllAdHocRequests(String annotation) {
514 DocumentActionResult result = getWorkflowDocumentActionsService().revokeAllAdHocRequests(
515 constructDocumentActionParameters(annotation));
516 resetStateAfterAction(result);
517 }
518
519 @Override
520 public void setTitle(String title) {
521 getModifiableDocument().setTitle(title);
522 }
523
524 @Override
525 public String getDocumentTypeName() {
526 return getDocument().getDocumentTypeName();
527 }
528
529 @Override
530 public boolean isCompletionRequested() {
531 return getRequestedActions().isCompleteRequested();
532 }
533
534 @Override
535 public boolean isApprovalRequested() {
536 return getRequestedActions().isApproveRequested();
537 }
538
539 @Override
540 public boolean isAcknowledgeRequested() {
541 return getRequestedActions().isAcknowledgeRequested();
542 }
543
544 @Override
545 public boolean isFYIRequested() {
546 return getRequestedActions().isFyiRequested();
547 }
548
549 @Override
550 public boolean isBlanketApproveCapable() {
551 return isValidAction(ActionType.BLANKET_APPROVE)
552 && (isCompletionRequested() || isApprovalRequested() || isInitiated());
553 }
554
555 @Override
556 public boolean isRouteCapable() {
557 return isValidAction(ActionType.ROUTE);
558 }
559
560 @Override
561 public boolean isValidAction(ActionType actionType) {
562 if (actionType == null) {
563 throw new IllegalArgumentException("actionType was null");
564 }
565
566 return getWorkflowDocumentActionsService().isValidAction(actionType.getCode(), getDocumentId(),
567 getPrincipalId());
568 }
569
570 @Override
571 public void superUserBlanketApprove(String annotation) {
572 DocumentActionResult result = getWorkflowDocumentActionsService().superUserBlanketApprove(
573 constructDocumentActionParameters(annotation), true);
574 resetStateAfterAction(result);
575 }
576
577 @Override
578 public void superUserNodeApprove(String nodeName, String annotation) {
579 DocumentActionResult result = getWorkflowDocumentActionsService().superUserNodeApprove(
580 constructDocumentActionParameters(annotation), true, nodeName);
581 resetStateAfterAction(result);
582 }
583
584 @Override
585 public void superUserTakeRequestedAction(String actionRequestId, String annotation) {
586 DocumentActionResult result = getWorkflowDocumentActionsService().superUserTakeRequestedAction(
587 constructDocumentActionParameters(annotation), true, actionRequestId);
588 resetStateAfterAction(result);
589 }
590
591 @Override
592 public void superUserDisapprove(String annotation) {
593 DocumentActionResult result = getWorkflowDocumentActionsService().superUserDisapprove(
594 constructDocumentActionParameters(annotation), true);
595 resetStateAfterAction(result);
596 }
597
598 @Override
599 public void superUserCancel(String annotation) {
600 DocumentActionResult result = getWorkflowDocumentActionsService().superUserCancel(
601 constructDocumentActionParameters(annotation), true);
602 resetStateAfterAction(result);
603 }
604
605 @Override
606 public void superUserReturnToPreviousNode(ReturnPoint returnPoint, String annotation) {
607 DocumentActionResult result = getWorkflowDocumentActionsService().superUserReturnToPreviousNode(
608 constructDocumentActionParameters(annotation), true, returnPoint);
609 resetStateAfterAction(result);
610 }
611
612 @Override
613 public void complete(String annotation) {
614 DocumentActionResult result = getWorkflowDocumentActionsService().complete(
615 constructDocumentActionParameters(annotation));
616 resetStateAfterAction(result);
617 }
618
619 @Override
620 public void logAnnotation(String annotation) {
621 getWorkflowDocumentActionsService().logAnnotation(getDocumentId(), principalId, annotation);
622 }
623
624 @Override
625 public DocumentStatus getStatus() {
626 return getDocument().getStatus();
627 }
628
629 @Override
630 public boolean checkStatus(DocumentStatus status) {
631 if (status == null) {
632 throw new IllegalArgumentException("status was null");
633 }
634 return status == getStatus();
635 }
636
637
638
639
640
641
642 @Override
643 public boolean isInitiated() {
644 return checkStatus(DocumentStatus.INITIATED);
645 }
646
647
648
649
650
651
652 @Override
653 public boolean isSaved() {
654 return checkStatus(DocumentStatus.SAVED);
655 }
656
657
658
659
660
661
662 @Override
663 public boolean isEnroute() {
664 return checkStatus(DocumentStatus.ENROUTE);
665 }
666
667
668
669
670
671
672 @Override
673 public boolean isException() {
674 return checkStatus(DocumentStatus.EXCEPTION);
675 }
676
677
678
679
680
681
682 @Override
683 public boolean isCanceled() {
684 return checkStatus(DocumentStatus.CANCELED);
685 }
686
687
688
689
690
691
692 @Override
693 public boolean isRecalled() {
694 return checkStatus(DocumentStatus.RECALLED);
695 }
696
697
698
699
700
701
702 @Override
703 public boolean isDisapproved() {
704 return checkStatus(DocumentStatus.DISAPPROVED);
705 }
706
707
708
709
710
711
712 @Override
713 public boolean isApproved() {
714 return isProcessed() || isFinal();
715 }
716
717
718
719
720
721
722 @Override
723 public boolean isProcessed() {
724 return checkStatus(DocumentStatus.PROCESSED);
725 }
726
727
728
729
730
731
732 @Override
733 public boolean isFinal() {
734 return checkStatus(DocumentStatus.FINAL);
735 }
736
737
738
739
740
741
742 @Override
743 public String getPrincipalId() {
744 return principalId;
745 }
746
747 @Override
748 public void switchPrincipal(String principalId) {
749 if (StringUtils.isBlank(this.principalId)) {
750 throw new IllegalArgumentException("principalId was null or blank");
751 }
752 this.principalId = principalId;
753 this.validActions = null;
754 this.requestedActions = null;
755 }
756
757 @Override
758 public void takeGroupAuthority(String annotation, String groupId) {
759 DocumentActionResult result = getWorkflowDocumentActionsService().takeGroupAuthority(
760 constructDocumentActionParameters(annotation), groupId);
761 resetStateAfterAction(result);
762 }
763
764 @Override
765 public void releaseGroupAuthority(String annotation, String groupId) {
766 DocumentActionResult result = getWorkflowDocumentActionsService().releaseGroupAuthority(
767 constructDocumentActionParameters(annotation), groupId);
768 resetStateAfterAction(result);
769 }
770
771 @Override
772 public Set<String> getNodeNames() {
773 final List<String> names = getWorkflowDocumentService().getActiveRouteNodeNames(getDocumentId());
774 return Collections.unmodifiableSet(new HashSet<String>(names));
775 }
776
777 public Set<String> getCurrentNodeNames() {
778 final List<String> names = getWorkflowDocumentService().getCurrentRouteNodeNames(getDocumentId());
779 return Collections.unmodifiableSet(new HashSet<String>(names));
780 }
781
782 @Override
783 public void returnToPreviousNode(String annotation, String nodeName) {
784 if (nodeName == null) {
785 throw new IllegalArgumentException("nodeName was null");
786 }
787 returnToPreviousNode(annotation, ReturnPoint.create(nodeName));
788 }
789
790 @Override
791 public void returnToPreviousNode(String annotation, ReturnPoint returnPoint) {
792 if (returnPoint == null) {
793 throw new IllegalArgumentException("returnPoint was null");
794 }
795 DocumentActionResult result = getWorkflowDocumentActionsService().returnToPreviousNode(
796 constructDocumentActionParameters(annotation), returnPoint);
797 resetStateAfterAction(result);
798 }
799
800 @Override
801 public void move(MovePoint movePoint, String annotation) {
802 if (movePoint == null) {
803 throw new IllegalArgumentException("movePoint was null");
804 }
805 DocumentActionResult result = getWorkflowDocumentActionsService().move(
806 constructDocumentActionParameters(annotation), movePoint);
807 resetStateAfterAction(result);
808 }
809
810 @Override
811 public List<RouteNodeInstance> getActiveRouteNodeInstances() {
812 return getWorkflowDocumentService().getActiveRouteNodeInstances(getDocumentId());
813 }
814
815 @Override
816 public List<RouteNodeInstance> getCurrentRouteNodeInstances() {
817 return getWorkflowDocumentService().getCurrentRouteNodeInstances(getDocumentId());
818 }
819
820 @Override
821 public List<RouteNodeInstance> getRouteNodeInstances() {
822 return getWorkflowDocumentService().getRouteNodeInstances(getDocumentId());
823 }
824
825 @Override
826 public List<String> getPreviousNodeNames() {
827 return getWorkflowDocumentService().getPreviousRouteNodeNames(getDocumentId());
828 }
829
830 @Override
831 public DocumentDetail getDocumentDetail() {
832 return getWorkflowDocumentService().getDocumentDetail(getDocumentId());
833 }
834
835 @Override
836 public void updateDocumentContent(DocumentContentUpdate documentContentUpdate) {
837 if (documentContentUpdate == null) {
838 throw new IllegalArgumentException("documentContentUpdate was null.");
839 }
840 getModifiableDocumentContent().setDocumentContentUpdate(documentContentUpdate);
841 }
842
843 @Override
844 public void placeInExceptionRouting(String annotation) {
845 DocumentActionResult result = getWorkflowDocumentActionsService().placeInExceptionRouting(
846 constructDocumentActionParameters(annotation));
847 resetStateAfterAction(result);
848 }
849
850 @Override
851 public void setVariable(String name, String value) {
852 getModifiableDocument().setVariable(name, value);
853 }
854
855 @Override
856 public String getVariableValue(String name) {
857 return getModifiableDocument().getVariableValue(name);
858 }
859
860 @Override
861 public void setReceiveFutureRequests() {
862 setVariable(getFutureRequestsKey(principalId), getReceiveFutureRequestsValue());
863 }
864
865 @Override
866 public void setDoNotReceiveFutureRequests() {
867 this.setVariable(getFutureRequestsKey(principalId), getDoNotReceiveFutureRequestsValue());
868 }
869
870 @Override
871 public void setClearFutureRequests() {
872 this.setVariable(getFutureRequestsKey(principalId), getClearFutureRequestsValue());
873 }
874
875 protected String getFutureRequestsKey(String principalId) {
876 return KewApiConstants.RECEIVE_FUTURE_REQUESTS_BRANCH_STATE_KEY + "," + principalId + ","
877 + new Date().toString() + ", " + Math.random();
878 }
879
880 @Override
881 public String getReceiveFutureRequestsValue() {
882 return KewApiConstants.RECEIVE_FUTURE_REQUESTS_BRANCH_STATE_VALUE;
883 }
884
885 @Override
886 public String getDoNotReceiveFutureRequestsValue() {
887 return KewApiConstants.DONT_RECEIVE_FUTURE_REQUESTS_BRANCH_STATE_VALUE;
888 }
889
890 @Override
891 public String getClearFutureRequestsValue() {
892 return KewApiConstants.CLEAR_FUTURE_REQUESTS_BRANCH_STATE_VALUE;
893 }
894
895 protected DocumentActionParameters constructDocumentActionParameters(String annotation) {
896 DocumentActionParameters.Builder builder = DocumentActionParameters.Builder.create(getDocumentId(),
897 getPrincipalId());
898 builder.setAnnotation(annotation);
899 builder.setDocumentUpdate(getDocumentUpdateIfDirty());
900 builder.setDocumentContentUpdate(getDocumentContentUpdateIfDirty());
901 return builder.build();
902 }
903
904 @Override
905 public DateTime getDateLastModified() {
906 return getDocument().getDateLastModified();
907 }
908
909 @Override
910 public DateTime getDateApproved() {
911 return getDocument().getDateApproved();
912 }
913
914 @Override
915 public DateTime getDateFinalized() {
916 return getDocument().getDateFinalized();
917 }
918
919 @Override
920 public String getInitiatorPrincipalId() {
921 return getDocument().getInitiatorPrincipalId();
922 }
923
924 @Override
925 public String getRoutedByPrincipalId() {
926 return getDocument().getRoutedByPrincipalId();
927 }
928
929 @Override
930 public String getDocumentTypeId() {
931 return getDocument().getDocumentTypeId();
932 }
933
934 @Override
935 public String getDocumentHandlerUrl() {
936 return getDocument().getDocumentHandlerUrl();
937 }
938
939 @Override
940 public String getApplicationDocumentStatus() {
941 return getDocument().getApplicationDocumentStatus();
942 }
943
944 @Override
945 public DateTime getApplicationDocumentStatusDate() {
946 return getDocument().getApplicationDocumentStatusDate();
947 }
948
949 @Override
950 public Map<String, String> getVariables() {
951 return getDocument().getVariables();
952 }
953
954
955
956
957
958 protected static class ModifiableDocumentContent implements Serializable {
959
960 private static final long serialVersionUID = -4458431160327214042L;
961
962 private boolean dirty;
963 private DocumentContent originalDocumentContent;
964 private DocumentContentUpdate.Builder builder;
965
966 protected ModifiableDocumentContent(DocumentContent documentContent) {
967 this.dirty = false;
968 this.originalDocumentContent = documentContent;
969 this.builder = DocumentContentUpdate.Builder.create(documentContent);
970 }
971
972 protected DocumentContent getDocumentContent() {
973 if (!dirty) {
974 return originalDocumentContent;
975 }
976 DocumentContent.Builder documentContentBuilder = DocumentContent.Builder.create(originalDocumentContent);
977 documentContentBuilder.setApplicationContent(builder.getApplicationContent());
978 documentContentBuilder.setAttributeContent(builder.getAttributeContent());
979 documentContentBuilder.setSearchableContent(builder.getSearchableContent());
980 return documentContentBuilder.build();
981 }
982
983 protected DocumentContentUpdate build() {
984 return builder.build();
985 }
986
987 protected void setDocumentContentUpdate(DocumentContentUpdate update) {
988 this.builder = DocumentContentUpdate.Builder.create(update);
989 this.dirty = true;
990 }
991
992 protected void addAttributeDefinition(WorkflowAttributeDefinition definition) {
993 builder.getAttributeDefinitions().add(definition);
994 dirty = true;
995 }
996
997 protected void removeAttributeDefinition(WorkflowAttributeDefinition definition) {
998 builder.getAttributeDefinitions().remove(definition);
999 dirty = true;
1000 }
1001
1002 protected List<WorkflowAttributeDefinition> getAttributeDefinitions() {
1003 return builder.getAttributeDefinitions();
1004 }
1005
1006 protected void addSearchableDefinition(WorkflowAttributeDefinition definition) {
1007 builder.getSearchableDefinitions().add(definition);
1008 dirty = true;
1009 }
1010
1011 protected void removeSearchableDefinition(WorkflowAttributeDefinition definition) {
1012 builder.getSearchableDefinitions().remove(definition);
1013 dirty = true;
1014 }
1015
1016 protected List<WorkflowAttributeDefinition> getSearchableDefinitions() {
1017 return builder.getAttributeDefinitions();
1018 }
1019
1020 protected void setApplicationContent(String applicationContent) {
1021 if ( !StringUtils.equals(applicationContent, builder.getApplicationContent() ) ) {
1022 builder.setApplicationContent(applicationContent);
1023 dirty = true;
1024 }
1025 }
1026
1027 protected void setAttributeContent(String attributeContent) {
1028 if ( !StringUtils.equals(attributeContent, builder.getAttributeContent() ) ) {
1029 builder.setAttributeContent(attributeContent);
1030 dirty = true;
1031 }
1032 }
1033
1034 public void setAttributeDefinitions(List<WorkflowAttributeDefinition> attributeDefinitions) {
1035 builder.setAttributeDefinitions(attributeDefinitions);
1036 dirty = true;
1037 }
1038
1039 public void setSearchableContent(String searchableContent) {
1040 if ( !StringUtils.equals(searchableContent, builder.getSearchableContent() ) ) {
1041 builder.setSearchableContent(searchableContent);
1042 dirty = true;
1043 }
1044 }
1045
1046 public void setSearchableDefinitions(List<WorkflowAttributeDefinition> searchableDefinitions) {
1047 builder.setSearchableDefinitions(searchableDefinitions);
1048 dirty = true;
1049 }
1050
1051 boolean isDirty() {
1052 return dirty;
1053 }
1054
1055 }
1056
1057
1058
1059
1060
1061 protected static class ModifiableDocument implements Serializable {
1062
1063 private static final long serialVersionUID = -3234793238863410378L;
1064
1065 private boolean dirty;
1066 private Document originalDocument;
1067 private DocumentUpdate.Builder builder;
1068
1069 protected ModifiableDocument(Document document) {
1070 this.dirty = false;
1071 this.originalDocument = document;
1072 this.builder = DocumentUpdate.Builder.create(document);
1073 }
1074
1075 protected Document getDocument() {
1076 if (!dirty) {
1077 return originalDocument;
1078 }
1079 Document.Builder documentBuilder = Document.Builder.create(originalDocument);
1080 documentBuilder.setApplicationDocumentId(builder.getApplicationDocumentId());
1081 documentBuilder.setTitle(builder.getTitle());
1082 documentBuilder.setApplicationDocumentStatus(builder.getApplicationDocumentStatus());
1083 documentBuilder.setVariables(builder.getVariables());
1084 return documentBuilder.build();
1085 }
1086
1087 protected DocumentUpdate build() {
1088 return builder.build();
1089 }
1090
1091
1092
1093
1094 protected String getDocumentId() {
1095 return originalDocument.getDocumentId();
1096 }
1097
1098
1099
1100
1101 protected DateTime getDateCreated() {
1102 return originalDocument.getDateCreated();
1103 }
1104
1105 protected String getApplicationDocumentId() {
1106 return builder.getApplicationDocumentId();
1107 }
1108
1109 protected void setApplicationDocumentId(String applicationDocumentId) {
1110 if ( !StringUtils.equals(applicationDocumentId, builder.getApplicationDocumentId() ) ) {
1111 builder.setApplicationDocumentId(applicationDocumentId);
1112 dirty = true;
1113 addDirtyField("applicationDocumentId");
1114 }
1115 }
1116
1117 protected String getTitle() {
1118 return builder.getTitle();
1119 }
1120
1121 protected void setTitle(String title) {
1122 if ( !StringUtils.equals(title, builder.getTitle() ) ) {
1123 builder.setTitle(title);
1124 dirty = true;
1125 addDirtyField("title");
1126 }
1127 }
1128
1129 protected String getApplicationDocumentStatus() {
1130 return builder.getApplicationDocumentStatus();
1131 }
1132
1133 protected void setApplicationDocumentStatus(String applicationDocumentStatus) {
1134 if ( !StringUtils.equals(applicationDocumentStatus, builder.getApplicationDocumentStatus() ) ) {
1135 builder.setApplicationDocumentStatus(applicationDocumentStatus);
1136 dirty = true;
1137 addDirtyField("applicationDocumentStatus");
1138 }
1139 }
1140
1141 protected void setVariable(String name, String value) {
1142 if ( !StringUtils.equals(value, builder.getVariableValue(name) ) ) {
1143 builder.setVariable(name, value);
1144 dirty = true;
1145 addDirtyField("var[" + name + "]");
1146 }
1147 }
1148
1149 protected String getVariableValue(String name) {
1150 return builder.getVariableValue(name);
1151 }
1152
1153 boolean isDirty() {
1154 return dirty;
1155 }
1156
1157 void addDirtyField(String field) {
1158 builder.addDirtyField(field);
1159 }
1160
1161 }
1162
1163 }