Coverage Report - org.kuali.rice.krad.document.DocumentBase
 
Classes in this File Line Coverage Branch Coverage Complexity
DocumentBase
0%
0/196
0%
0/48
1.833
 
 1  
 /*
 2  
  * Copyright 2005-2007 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.krad.document;
 17  
 
 18  
 import java.util.ArrayList;
 19  
 import java.util.Iterator;
 20  
 import java.util.List;
 21  
 import java.util.Map;
 22  
 
 23  
 import javax.persistence.CascadeType;
 24  
 import javax.persistence.Column;
 25  
 import javax.persistence.FetchType;
 26  
 import javax.persistence.Id;
 27  
 import javax.persistence.JoinColumn;
 28  
 import javax.persistence.MappedSuperclass;
 29  
 import javax.persistence.OneToMany;
 30  
 import javax.persistence.OneToOne;
 31  
 import javax.persistence.Transient;
 32  
 
 33  
 import org.apache.commons.lang.StringUtils;
 34  
 import org.apache.log4j.Logger;
 35  
 import org.kuali.rice.kew.dto.ActionTakenEventDTO;
 36  
 import org.kuali.rice.kew.dto.DocumentRouteLevelChangeDTO;
 37  
 import org.kuali.rice.kew.dto.DocumentRouteStatusChangeDTO;
 38  
 import org.kuali.rice.kew.exception.WorkflowException;
 39  
 import org.kuali.rice.kew.util.KEWConstants;
 40  
 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
 41  
 import org.kuali.rice.kim.bo.Person;
 42  
 import org.kuali.rice.krad.bo.AdHocRoutePerson;
 43  
 import org.kuali.rice.krad.bo.AdHocRouteWorkgroup;
 44  
 import org.kuali.rice.krad.bo.DocumentHeader;
 45  
 import org.kuali.rice.krad.bo.Note;
 46  
 import org.kuali.rice.krad.bo.PersistableBusinessObject;
 47  
 import org.kuali.rice.krad.bo.PersistableBusinessObjectBase;
 48  
 import org.kuali.rice.krad.datadictionary.DocumentEntry;
 49  
 import org.kuali.rice.krad.datadictionary.WorkflowAttributes;
 50  
 import org.kuali.rice.krad.datadictionary.WorkflowProperties;
 51  
 import org.kuali.rice.krad.document.authorization.PessimisticLock;
 52  
 import org.kuali.rice.krad.exception.PessimisticLockingException;
 53  
 import org.kuali.rice.krad.exception.ValidationException;
 54  
 import org.kuali.rice.krad.rule.event.KualiDocumentEvent;
 55  
 import org.kuali.rice.krad.service.AttachmentService;
 56  
 import org.kuali.rice.krad.service.DocumentSerializerService;
 57  
 import org.kuali.rice.krad.service.KRADServiceLocator;
 58  
 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
 59  
 import org.kuali.rice.krad.service.NoteService;
 60  
 import org.kuali.rice.krad.util.ErrorMessage;
 61  
 import org.kuali.rice.krad.util.GlobalVariables;
 62  
 import org.kuali.rice.krad.util.KRADConstants;
 63  
 import org.kuali.rice.krad.util.KRADPropertyConstants;
 64  
 import org.kuali.rice.krad.util.NoteType;
 65  
 import org.kuali.rice.krad.util.ObjectUtils;
 66  
 import org.kuali.rice.krad.util.documentserializer.AlwaysFalsePropertySerializabilityEvaluator;
 67  
 import org.kuali.rice.krad.util.documentserializer.AlwaysTruePropertySerializibilityEvaluator;
 68  
 import org.kuali.rice.krad.util.documentserializer.BusinessObjectPropertySerializibilityEvaluator;
 69  
 import org.kuali.rice.krad.util.documentserializer.PropertySerializabilityEvaluator;
 70  
 import org.kuali.rice.krad.workflow.DocumentInitiator;
 71  
 import org.kuali.rice.krad.workflow.KualiDocumentXmlMaterializer;
 72  
 import org.kuali.rice.krad.workflow.KualiTransactionalDocumentInformation;
 73  
 import org.springframework.util.AutoPopulatingList;
 74  
 
 75  
 
 76  
 /**
 77  
  * @see Document
 78  
  */
 79  0
 @MappedSuperclass
 80  
 public abstract class DocumentBase extends PersistableBusinessObjectBase implements Document {
 81  0
     private static final Logger LOG = Logger.getLogger(DocumentBase.class);
 82  
     
 83  
     @Id
 84  
     @Column(name="DOC_HDR_ID")
 85  
     protected String documentNumber;
 86  
     @OneToOne(fetch=FetchType.LAZY, cascade={CascadeType.PERSIST, CascadeType.MERGE})
 87  
         @JoinColumn(name="DOC_HDR_ID", insertable=false, updatable=false)
 88  
     protected DocumentHeader documentHeader;    
 89  
 
 90  
     @OneToMany(fetch=FetchType.LAZY, cascade={CascadeType.PERSIST, CascadeType.MERGE})
 91  
         @JoinColumn(name="DOC_HDR_ID", insertable=false, updatable=false)
 92  
     private List<PessimisticLock> pessimisticLocks;
 93  
 
 94  
     @Transient
 95  
     private List<AdHocRoutePerson> adHocRoutePersons;
 96  
     @Transient
 97  
     private List<AdHocRouteWorkgroup> adHocRouteWorkgroups;
 98  
     @Transient
 99  
     private List<Note> notes;
 100  
     
 101  
     private transient NoteService noteService;
 102  
     private transient AttachmentService attachmentService;
 103  
 
 104  
     /**
 105  
      * Constructs a DocumentBase.java.
 106  
      */
 107  0
     public DocumentBase() {
 108  
         try {
 109  
             // create a new document header object
 110  0
             Class<? extends DocumentHeader> documentHeaderClass = KRADServiceLocatorWeb.getDocumentHeaderService().getDocumentHeaderBaseClass();
 111  0
             setDocumentHeader(documentHeaderClass.newInstance());
 112  0
             pessimisticLocks = new ArrayList<PessimisticLock>();
 113  0
             adHocRoutePersons = new ArrayList<AdHocRoutePerson>();
 114  0
             adHocRouteWorkgroups = new ArrayList<AdHocRouteWorkgroup>();
 115  0
             notes = new ArrayList<Note>();
 116  
         }
 117  0
         catch (IllegalAccessException e) {
 118  0
             throw new RuntimeException("Error instantiating DocumentHeader", e);
 119  
         }
 120  0
         catch (InstantiationException e) {
 121  0
             throw new RuntimeException("Error instantiating DocumentHeader", e);
 122  0
         }
 123  0
     }
 124  
 
 125  
     /**
 126  
      * @see org.kuali.rice.krad.document.Document#getAllowsCopy()
 127  
      */
 128  
     public boolean getAllowsCopy() {
 129  
         // TODO Auto-generated method stub
 130  0
         return false;
 131  
     }
 132  
 
 133  
     /**
 134  
      * This is the default document title implementation. It concatenates the document's data dictionary file label attribute and
 135  
      * the document's document header description together. This title is used to populate workflow and will show up in document
 136  
      * search results and user action lists.
 137  
      *
 138  
      * @see org.kuali.rice.krad.document.Document#getDocumentTitle()
 139  
      */
 140  
     public String getDocumentTitle() {
 141  
         try {
 142  0
             String documentTypeLabel = KRADServiceLocatorWeb.getWorkflowInfoService().getDocType(this.getDocumentHeader().getWorkflowDocument().getDocumentType()).getDocTypeLabel();
 143  0
             if (null == documentTypeLabel) {
 144  0
                 documentTypeLabel = "";
 145  
             }
 146  
     
 147  0
             String description = this.getDocumentHeader().getDocumentDescription();
 148  0
             if (null == description) {
 149  0
                 description = "";
 150  
             }
 151  
     
 152  0
             return documentTypeLabel + " - " + description;
 153  
         }
 154  0
         catch (WorkflowException e) {
 155  0
             throw new RuntimeException("Caught Exception getting the document type label", e);
 156  
         }
 157  
     }
 158  
 
 159  
     /**
 160  
      * Uses the persistence service's implementation of OJB's retrieveNonKey() fields method.
 161  
      *
 162  
      * @see org.kuali.rice.krad.bo.BusinessObject#refresh()
 163  
      */
 164  
     @Override
 165  
     public void refresh() {
 166  0
         KRADServiceLocator.getPersistenceService().retrieveNonKeyFields(this);
 167  0
     }
 168  
 
 169  
     /**
 170  
      * Checks to see if the objectId value is empty. If so, it will try to refresh the object from the DB.
 171  
      *
 172  
      * @see org.kuali.rice.krad.document.Document#refreshIfEmpty()
 173  
      */
 174  
     public void refreshIfEmpty() {
 175  0
         if (null == this.getDocumentHeader()) {
 176  0
             this.refresh();
 177  
         }
 178  0
         else if (StringUtils.isEmpty(this.getDocumentHeader().getObjectId())) {
 179  0
             this.refresh();
 180  
         }
 181  0
     }
 182  
 
 183  
     /**
 184  
      * Uses the persistence service to retrieve a reference object of a parent.
 185  
      *
 186  
      * @see org.kuali.rice.krad.document.Document#refreshReferenceObject(java.lang.String)
 187  
      */
 188  
     @Override
 189  
     public void refreshReferenceObject(String referenceObjectName) {
 190  0
         KRADServiceLocator.getPersistenceService().retrieveReferenceObject(this, referenceObjectName);
 191  0
     }
 192  
 
 193  
     /**
 194  
      * @see org.kuali.rice.krad.document.Document#prepareForSave()
 195  
      */
 196  
     public void prepareForSave() {
 197  
         // do nothing
 198  0
     }
 199  
 
 200  
     /**
 201  
      * @see org.kuali.rice.krad.document.Document#processAfterRetrieve()
 202  
      */
 203  
     public void processAfterRetrieve() {
 204  
             // do nothing
 205  0
     }
 206  
 
 207  
     /**
 208  
      * The the default implementation for RouteLevelChange does nothing, but is meant to provide a hook for documents to implement
 209  
      * for other needs.
 210  
      *
 211  
      * @see org.kuali.rice.krad.document.Document#doRouteLevelChange(org.kuali.rice.kew.dto.DocumentRouteLevelChangeDTO)
 212  
      */
 213  
     public void doRouteLevelChange(DocumentRouteLevelChangeDTO levelChangeEvent) {
 214  
         // do nothing
 215  0
     }
 216  
     
 217  
     /**
 218  
      * @see org.kuali.rice.krad.document.Document#doActionTaken(org.kuali.rice.kew.dto.ActionTakenEventDTO)
 219  
      */
 220  
     public void doActionTaken(ActionTakenEventDTO event) {
 221  0
         if ( (KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary().getDocumentEntry(this.getClass().getName()).getUseWorkflowPessimisticLocking()) && (!getNonLockingActionTakenCodes().contains(event.getActionTaken().getActionTaken())) ) {
 222  
             //DocumentAuthorizer documentAuthorizer = KRADServiceLocatorInternal.getDocumentAuthorizationService().getDocumentAuthorizer(this);
 223  
             //documentAuthorizer.establishWorkflowPessimisticLocking(this);
 224  0
                 KRADServiceLocatorWeb.getPessimisticLockService().establishWorkflowPessimisticLocking(this);
 225  
         }
 226  0
     }
 227  
     
 228  
     protected List<String> getNonLockingActionTakenCodes() {
 229  0
         List<String> actionTakenStatusCodes = new ArrayList<String>();
 230  0
         actionTakenStatusCodes.add(KEWConstants.ACTION_TAKEN_SAVED_CD);
 231  0
         actionTakenStatusCodes.add(KEWConstants.ACTION_TAKEN_ACKNOWLEDGED_CD);
 232  0
         actionTakenStatusCodes.add(KEWConstants.ACTION_TAKEN_FYI_CD);
 233  0
         actionTakenStatusCodes.add(KEWConstants.ACTION_TAKEN_DENIED_CD);
 234  0
         actionTakenStatusCodes.add(KEWConstants.ACTION_TAKEN_CANCELED_CD);
 235  0
         actionTakenStatusCodes.add(KEWConstants.ACTION_TAKEN_LOG_DOCUMENT_ACTION_CD);
 236  0
         return actionTakenStatusCodes;
 237  
     }
 238  
 
 239  
     /**
 240  
      * The the default implementation for afterWorkflowEngineProcess does nothing, but is meant to provide a hook for
 241  
      * documents to implement for other needs.
 242  
      * 
 243  
      * @see org.kuali.rice.krad.document.Document#afterWorkflowEngineProcess(boolean)
 244  
      */
 245  
     public void afterWorkflowEngineProcess(boolean successfullyProcessed) {
 246  0
         if (KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary().getDocumentEntry(this.getClass().getName()).getUseWorkflowPessimisticLocking()) {
 247  0
             if (successfullyProcessed) {
 248  
                 //DocumentAuthorizer documentAuthorizer = KRADServiceLocatorInternal.getDocumentAuthorizationService().getDocumentAuthorizer(this);
 249  
                 //documentAuthorizer.releaseWorkflowPessimisticLocking(this);
 250  0
                     KRADServiceLocatorWeb.getPessimisticLockService().releaseWorkflowPessimisticLocking(this);
 251  
             }
 252  
         }
 253  0
     }
 254  
 
 255  
     /**
 256  
      * The the default implementation for beforeWorkflowEngineProcess does nothing, but is meant to provide a hook for
 257  
      * documents to implement for other needs.
 258  
      * 
 259  
      * @see org.kuali.rice.krad.document.Document#beforeWorkflowEngineProcess()
 260  
      */
 261  
     public void beforeWorkflowEngineProcess() {
 262  
     // do nothing
 263  0
     }
 264  
     
 265  
     
 266  
 
 267  
     /**
 268  
      * The default implementation returns no additional ids for the workflow engine to lock prior to processing.
 269  
      * 
 270  
      * @see org.kuali.rice.krad.document.Document#getWorkflowEngineDocumentIdsToLock()
 271  
      */
 272  
     public List<Long> getWorkflowEngineDocumentIdsToLock() {
 273  0
                 return null;
 274  
         }
 275  
 
 276  
         /**
 277  
      * @see org.kuali.rice.krad.document.Copyable#toCopy()
 278  
      */
 279  
     public void toCopy() throws WorkflowException, IllegalStateException {
 280  0
         if (!this.getAllowsCopy()) {
 281  0
             throw new IllegalStateException(this.getClass().getName() + " does not support document-level copying");
 282  
         }
 283  0
         String sourceDocumentHeaderId = getDocumentNumber();
 284  0
         setNewDocumentHeader();
 285  
                 
 286  0
         getDocumentHeader().setDocumentTemplateNumber(sourceDocumentHeaderId);
 287  
 
 288  0
         addCopyErrorDocumentNote("copied from document " + sourceDocumentHeaderId);
 289  0
     }
 290  
 
 291  
     /**
 292  
      * Gets a new document header for this documents type and sets in the document instance.
 293  
      * 
 294  
      * @throws WorkflowException
 295  
      */
 296  
     protected void setNewDocumentHeader() throws WorkflowException {
 297  0
         TransactionalDocument newDoc = (TransactionalDocument) KRADServiceLocatorWeb.getDocumentService().getNewDocument(getDocumentHeader().getWorkflowDocument().getDocumentType());
 298  0
         newDoc.getDocumentHeader().setDocumentDescription(getDocumentHeader().getDocumentDescription());
 299  0
         newDoc.getDocumentHeader().setOrganizationDocumentNumber(getDocumentHeader().getOrganizationDocumentNumber());
 300  
 
 301  
         try {
 302  0
             ObjectUtils.setObjectPropertyDeep(this, KRADPropertyConstants.DOCUMENT_NUMBER, documentNumber.getClass(), newDoc.getDocumentNumber());
 303  
         }
 304  0
         catch (Exception e) {
 305  0
             LOG.error("Unable to set document number property in copied document " + e.getMessage(),e);
 306  0
             throw new RuntimeException("Unable to set document number property in copied document " + e.getMessage(),e);
 307  0
         }
 308  
 
 309  
         // replace current documentHeader with new documentHeader
 310  0
         setDocumentHeader(newDoc.getDocumentHeader());
 311  0
     }
 312  
 
 313  
     /**
 314  
      * Adds a note to the document indicating it was created by a copy or error correction.
 315  
      * 
 316  
      * @param noteText - text for note
 317  
      */
 318  
     protected void addCopyErrorDocumentNote(String noteText) {
 319  0
         Note note = null;
 320  
         try {
 321  0
             note = KRADServiceLocatorWeb.getDocumentService().createNoteFromDocument(this,noteText);
 322  
         }
 323  0
         catch (Exception e) {
 324  0
          logErrors();
 325  0
          throw new RuntimeException("Couldn't create note on copy or error",e);
 326  0
         }
 327  0
         addNote(note);
 328  0
     }
 329  
 
 330  
     /**
 331  
      * @see org.kuali.rice.krad.document.Document#getXmlForRouteReport()
 332  
      */
 333  
     public String getXmlForRouteReport() {
 334  0
         prepareForSave();
 335  0
         populateDocumentForRouting();
 336  0
         return getDocumentHeader().getWorkflowDocument().getApplicationContent();
 337  
     }
 338  
 
 339  
     /**
 340  
      * @see org.kuali.rice.krad.document.Document#populateDocumentForRouting()
 341  
      */
 342  
     public void populateDocumentForRouting() {
 343  0
         getDocumentHeader().getWorkflowDocument().setApplicationContent(serializeDocumentToXml());
 344  0
     }
 345  
     
 346  
     /**
 347  
      * @see org.kuali.rice.krad.document.Document#serializeDocumentToXml()
 348  
      */
 349  
     public String serializeDocumentToXml() {
 350  0
         DocumentSerializerService documentSerializerService = KRADServiceLocatorWeb.getDocumentSerializerService();
 351  0
         String xml = documentSerializerService.serializeDocumentToXmlForRouting(this);
 352  0
         return xml;
 353  
     }
 354  
 
 355  
     /**
 356  
      * Wraps a document in an instance of KualiDocumentXmlMaterializer, that provides additional metadata for serialization
 357  
      * 
 358  
      * @see org.kuali.rice.krad.document.Document#wrapDocumentWithMetadataForXmlSerialization()
 359  
      */
 360  
     public KualiDocumentXmlMaterializer wrapDocumentWithMetadataForXmlSerialization() {
 361  0
         KualiTransactionalDocumentInformation transInfo = new KualiTransactionalDocumentInformation();
 362  0
         DocumentInitiator initiator = new DocumentInitiator();
 363  0
         String initiatorPrincipalId = getDocumentHeader().getWorkflowDocument().getRouteHeader().getInitiatorPrincipalId();
 364  0
         Person initiatorUser = KimApiServiceLocator.getPersonService().getPerson(initiatorPrincipalId);
 365  0
         initiator.setPerson(initiatorUser);
 366  0
         transInfo.setDocumentInitiator(initiator);
 367  0
         KualiDocumentXmlMaterializer xmlWrapper = new KualiDocumentXmlMaterializer();
 368  0
         xmlWrapper.setDocument(this);
 369  0
         xmlWrapper.setKualiTransactionalDocumentInformation(transInfo);
 370  0
         return xmlWrapper;
 371  
     }
 372  
 
 373  
     /**
 374  
      * If workflowProperties have been defined within the data dictionary for this document, then it returns an instance of 
 375  
      * {@link BusinessObjectPropertySerializibilityEvaluator} initialized with the properties.  If none have been defined, then returns 
 376  
      * {@link AlwaysTruePropertySerializibilityEvaluator}.
 377  
      * 
 378  
      * @see org.kuali.rice.krad.document.Document#getDocumentPropertySerizabilityEvaluator()
 379  
      */
 380  
     public PropertySerializabilityEvaluator getDocumentPropertySerizabilityEvaluator() {
 381  0
         String docTypeName = getDocumentHeader().getWorkflowDocument().getDocumentType();
 382  0
         DocumentEntry documentEntry = KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary().getDocumentEntry(docTypeName);
 383  0
         WorkflowProperties workflowProperties = documentEntry.getWorkflowProperties();
 384  0
         WorkflowAttributes workflowAttributes = documentEntry.getWorkflowAttributes();
 385  0
         return createPropertySerializabilityEvaluator(workflowProperties, workflowAttributes);
 386  
     }
 387  
     
 388  
     protected PropertySerializabilityEvaluator createPropertySerializabilityEvaluator(WorkflowProperties workflowProperties, WorkflowAttributes workflowAttributes) {
 389  0
             if (workflowAttributes != null) {
 390  0
                     return new AlwaysFalsePropertySerializabilityEvaluator();
 391  
             }
 392  0
             if (workflowProperties == null) {
 393  0
                     return new AlwaysTruePropertySerializibilityEvaluator();
 394  
             }
 395  0
             PropertySerializabilityEvaluator evaluator = new BusinessObjectPropertySerializibilityEvaluator();
 396  0
             evaluator.initializeEvaluatorForDocument(this);
 397  0
             return evaluator;
 398  
     }
 399  
     
 400  
     /**
 401  
      * Returns the POJO property name of "this" document in the object returned by {@link #wrapDocumentWithMetadataForXmlSerialization()}
 402  
      * 
 403  
      * @see org.kuali.rice.krad.document.Document#getBasePathToDocumentDuringSerialization()
 404  
      */
 405  
     public String getBasePathToDocumentDuringSerialization() {
 406  0
         return "document";
 407  
     }
 408  
     
 409  
     
 410  
     /**
 411  
      * @see org.kuali.rice.krad.document.Document#getDocumentHeader()
 412  
      */
 413  
     public DocumentHeader getDocumentHeader() {
 414  0
         return this.documentHeader;
 415  
     }
 416  
 
 417  
     /**
 418  
      * @see org.kuali.rice.krad.document.Document#setDocumentHeader(org.kuali.rice.krad.document.DocumentHeader)
 419  
      */
 420  
     public void setDocumentHeader(DocumentHeader documentHeader) {
 421  0
         this.documentHeader = documentHeader;
 422  0
     }
 423  
 
 424  
     /**
 425  
      * @see org.kuali.rice.krad.document.Document#getDocumentNumber()
 426  
      */
 427  
     public String getDocumentNumber() {
 428  0
         return documentNumber;
 429  
     }
 430  
 
 431  
     /**
 432  
      * @see org.kuali.rice.krad.document.Document#setDocumentNumber(java.lang.String)
 433  
      */
 434  
     public void setDocumentNumber(String documentNumber) {
 435  0
         this.documentNumber = documentNumber;
 436  0
     }
 437  
 
 438  
     /**
 439  
      * @see org.kuali.rice.krad.document.Document#getAdHocRoutePersons()
 440  
      */
 441  
     public List<AdHocRoutePerson> getAdHocRoutePersons() {
 442  0
         return adHocRoutePersons;
 443  
     }
 444  
 
 445  
     /**
 446  
      * @see org.kuali.rice.krad.document.Document#setAdHocRoutePersons(java.util.List)
 447  
      */
 448  
     public void setAdHocRoutePersons(List<AdHocRoutePerson> adHocRoutePersons) {
 449  0
         this.adHocRoutePersons = adHocRoutePersons;
 450  0
 }
 451  
     /**
 452  
      * @see org.kuali.rice.krad.document.Document#getAdHocRouteWorkgroups()
 453  
      */
 454  
     public List<AdHocRouteWorkgroup> getAdHocRouteWorkgroups() {
 455  0
         return adHocRouteWorkgroups;
 456  
     }
 457  
 
 458  
     /**
 459  
      * @see org.kuali.rice.krad.document.Document#setAdHocRouteWorkgroups(java.util.List)
 460  
      */
 461  
     public void setAdHocRouteWorkgroups(List<AdHocRouteWorkgroup> adHocRouteWorkgroups) {
 462  0
         this.adHocRouteWorkgroups = adHocRouteWorkgroups;
 463  0
     }
 464  
 
 465  
     public void postProcessSave(KualiDocumentEvent event) {
 466  
         // TODO Auto-generated method stub
 467  
 
 468  0
         }
 469  
 
 470  
     /**
 471  
      * Override this method with implementation specific prepareForSave logic
 472  
      * 
 473  
      * @see org.kuali.rice.krad.document.Document#prepareForSave(org.kuali.rice.krad.rule.event.KualiDocumentEvent)
 474  
      */
 475  
     public void prepareForSave(KualiDocumentEvent event) {
 476  
             // do nothing by default
 477  0
     }
 478  
 
 479  
     public void validateBusinessRules(KualiDocumentEvent event) {
 480  0
         if (GlobalVariables.getMessageMap().hasErrors()) {
 481  0
             logErrors();
 482  0
             throw new ValidationException("errors occured before business rule");
 483  
         }
 484  
 
 485  
         // perform validation against rules engine
 486  0
         LOG.info("invoking rules engine on document " + getDocumentNumber());
 487  0
         boolean isValid = true;
 488  0
         isValid = KRADServiceLocatorWeb.getKualiRuleService().applyRules(event);
 489  
 
 490  
         // check to see if the br eval passed or failed
 491  0
         if (!isValid) {
 492  0
             logErrors();
 493  
             // TODO: better error handling at the lower level and a better error message are
 494  
             // needed here
 495  0
             throw new ValidationException("business rule evaluation failed");
 496  
         }
 497  0
         else if (GlobalVariables.getMessageMap().hasErrors()) {
 498  0
             logErrors();
 499  0
             throw new ValidationException("Unreported errors occured during business rule evaluation (rule developer needs to put meaningful error messages into global ErrorMap)");
 500  
         }
 501  0
         LOG.debug("validation completed");
 502  
 
 503  0
     }
 504  
 
 505  
     /**
 506  
      * This method logs errors.
 507  
      */
 508  
     protected void logErrors() {
 509  0
             if ( LOG.isInfoEnabled() ) {
 510  0
                 if (GlobalVariables.getMessageMap().hasErrors()) {
 511  
         
 512  0
                     for (Iterator<Map.Entry<String, AutoPopulatingList<ErrorMessage>>> i = GlobalVariables.getMessageMap().getAllPropertiesAndErrors().iterator(); i.hasNext();) {
 513  0
                         Map.Entry<String, AutoPopulatingList<ErrorMessage>> e = i.next();
 514  
         
 515  0
                         StringBuffer logMessage = new StringBuffer();
 516  0
                         logMessage.append("[" + e.getKey() + "] ");
 517  0
                         boolean first = true;
 518  
         
 519  0
                         AutoPopulatingList<ErrorMessage> errorList = e.getValue();
 520  0
                         for (Iterator<ErrorMessage> j = errorList.iterator(); j.hasNext();) {
 521  0
                             ErrorMessage em = j.next();
 522  
         
 523  0
                             if (first) {
 524  0
                                 first = false;
 525  
                             }
 526  
                             else {
 527  0
                                 logMessage.append(";");
 528  
                             }
 529  0
                             logMessage.append(em);
 530  0
                         }
 531  
         
 532  0
                         LOG.info(logMessage);
 533  0
                     }
 534  
                 }
 535  
             }
 536  0
     }
 537  
 
 538  
     /**
 539  
      * Hook for override
 540  
      * 
 541  
      * @see org.kuali.rice.krad.document.Document#generateSaveEvents()
 542  
      */
 543  
     public List<KualiDocumentEvent> generateSaveEvents() {
 544  0
         return new ArrayList<KualiDocumentEvent>();
 545  
     }
 546  
 
 547  
     /**
 548  
      * @see org.kuali.rice.krad.document.Document#doRouteStatusChange(org.kuali.rice.kew.dto.DocumentRouteStatusChangeDTO)
 549  
      */
 550  
     public void doRouteStatusChange(DocumentRouteStatusChangeDTO statusChangeEvent) {
 551  
         // do nothing
 552  0
     }
 553  
     
 554  
     /**
 555  
      * Returns the business object with which notes related to this document should be associated.
 556  
      * By default, the {@link DocumentHeader} of this document will be returned as the note target.
 557  
      * 
 558  
      * <p>Sub classes can override this method if they want notes to be associated with something
 559  
      * other than the document header.  If this method is overridden, the {@link #getNoteType()}
 560  
      * method should be overridden to return {@link NoteType#BUSINESS_OBJECT}
 561  
      * 
 562  
      * @return Returns the documentBusinessObject.
 563  
      */
 564  
     @Override
 565  
     public PersistableBusinessObject getNoteTarget() {
 566  0
         return getDocumentHeader();
 567  
     }
 568  
     
 569  
     /**
 570  
          * Returns the {@link NoteType} to use for notes associated with this document.
 571  
          * By default this returns {@link NoteType#DOCUMENT_HEADER} since notes are
 572  
          * associated with the {@link DocumentHeader} record by default.
 573  
          * 
 574  
          * <p>The case in which this should be overridden is if {@link #getNoteTarget()} is
 575  
          * overridden to return an object other than the DocumentHeader.
 576  
          *
 577  
          * @return the note type to use for notes associated with this document
 578  
          * 
 579  
          * @see org.kuali.rice.krad.document.Document#getNoteType()
 580  
          */
 581  
         @Override
 582  
         public NoteType getNoteType() {
 583  0
                 return NoteType.DOCUMENT_HEADER;
 584  
         }
 585  
 
 586  
         /**
 587  
          * @see org.kuali.rice.krad.document.Document#addNote(org.kuali.rice.krad.bo.Note)
 588  
          */
 589  
     @Override
 590  
         public void addNote(Note note) {
 591  0
             if (note == null) {
 592  0
                     throw new IllegalArgumentException("Note cannot be null.");
 593  
             }
 594  0
                 notes.add(note);
 595  0
         }
 596  
 
 597  
     /**
 598  
      * @see org.kuali.rice.krad.document.Document#removeNote(org.kuali.rice.krad.bo.Note)
 599  
      */
 600  
         @Override
 601  
         public boolean removeNote(Note note) {
 602  0
                 if (note == null) {
 603  0
                     throw new IllegalArgumentException("Note cannot be null.");
 604  
             }
 605  0
                 return notes.remove(note);
 606  
         }
 607  
 
 608  
         /**
 609  
          * @see org.kuali.rice.krad.document.Document#getNote(int)
 610  
          */
 611  
         @Override
 612  
         public Note getNote(int index) {
 613  0
                 return notes.get(index);
 614  
         }
 615  
 
 616  
         /**
 617  
          * @see org.kuali.rice.krad.document.Document#getNotes()
 618  
          */
 619  
         @Override
 620  
         public List<Note> getNotes() {
 621  0
                 return notes;
 622  
         }
 623  
         
 624  
         /**
 625  
          * @see org.kuali.rice.krad.document.Document#setNotes(java.util.List)
 626  
          */
 627  
         @Override
 628  
         public void setNotes(List<Note> notes) {
 629  0
                 if (notes == null) {
 630  0
                         throw new IllegalArgumentException("List of notes must be non-null.");
 631  
                 }
 632  0
                 this.notes = notes;
 633  0
         }
 634  
 
 635  
     /**
 636  
      * @see org.kuali.rice.krad.document.Document#getPessimisticLocks()
 637  
      */
 638  
     public List<PessimisticLock> getPessimisticLocks() {
 639  0
         return this.pessimisticLocks;
 640  
     }
 641  
     
 642  
     /**
 643  
      * @see org.kuali.rice.krad.document.Document#refreshPessimisticLocks()
 644  
      * @deprecated
 645  
      * This is not needed with the relationship set up with JPA annotations
 646  
      */
 647  
     @Deprecated 
 648  
     public void refreshPessimisticLocks() {
 649  0
         this.pessimisticLocks.clear();
 650  0
         this.pessimisticLocks = KRADServiceLocatorWeb.getPessimisticLockService().getPessimisticLocksForDocument(this.documentNumber);
 651  0
     }
 652  
 
 653  
     /**
 654  
      * @param pessimisticLocks the PessimisticLock objects to set
 655  
      */
 656  
     public void setPessimisticLocks(List<PessimisticLock> pessimisticLocks) {
 657  0
         this.pessimisticLocks = pessimisticLocks;
 658  0
     }
 659  
     
 660  
     /**
 661  
      * @see org.kuali.rice.krad.document.Document#addPessimisticLock(org.kuali.rice.krad.document.authorization.PessimisticLock)
 662  
      */
 663  
     public void addPessimisticLock(PessimisticLock lock) {
 664  0
         this.pessimisticLocks.add(lock);
 665  0
     }
 666  
     
 667  
     /**
 668  
      * @see org.kuali.rice.krad.document.Document#getLockClearningMethodNames()
 669  
      */
 670  
     public List<String> getLockClearningMethodNames() {
 671  0
         List<String> methodToCalls = new ArrayList<String>();
 672  0
         methodToCalls.add(KRADConstants.CLOSE_METHOD);
 673  0
         methodToCalls.add(KRADConstants.CANCEL_METHOD);
 674  
 //        methodToCalls.add(RiceConstants.BLANKET_APPROVE_METHOD);
 675  0
         methodToCalls.add(KRADConstants.ROUTE_METHOD);
 676  0
         methodToCalls.add(KRADConstants.APPROVE_METHOD);
 677  0
         methodToCalls.add(KRADConstants.DISAPPROVE_METHOD);
 678  0
         return methodToCalls;
 679  
     }
 680  
 
 681  
     /**
 682  
      * This default implementation simply returns false to indicate that custom lock descriptors are not supported by DocumentBase. If custom lock
 683  
      * descriptors are needed, the appropriate subclasses should override this method.
 684  
      * 
 685  
      * @see org.kuali.rice.krad.document.Document#useCustomLockDescriptors()
 686  
      */
 687  
     public boolean useCustomLockDescriptors() {
 688  0
             return false;
 689  
     }
 690  
 
 691  
     /**
 692  
      * This default implementation just throws a PessimisticLockingException. Subclasses of DocumentBase that need support for custom lock descriptors
 693  
      * should override this method.
 694  
      * 
 695  
      * @see org.kuali.rice.krad.document.Document#getCustomLockDescriptor(org.kuali.rice.kim.bo.Person)
 696  
      */
 697  
     public String getCustomLockDescriptor(Person user) {
 698  0
             throw new PessimisticLockingException("Document " + getDocumentNumber() +
 699  
                             " is using pessimistic locking with custom lock descriptors, but the document class has not overriden the getCustomLockDescriptor method");
 700  
     }
 701  
     
 702  
     protected AttachmentService getAttachmentService() {
 703  0
                 if ( attachmentService == null ) {
 704  0
                         attachmentService = KRADServiceLocator.getAttachmentService();
 705  
                 }
 706  0
                 return attachmentService;
 707  
         }
 708  
     
 709  
     protected NoteService getNoteService() {
 710  0
                 if ( noteService == null ) {
 711  0
                         noteService = KRADServiceLocator.getNoteService();
 712  
                 }
 713  0
                 return noteService;
 714  
         }
 715  
 }