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