Coverage Report - org.kuali.rice.krad.document.MaintenanceDocumentBase
 
Classes in this File Line Coverage Branch Coverage Complexity
MaintenanceDocumentBase
0%
0/353
0%
0/152
2.806
 
 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.io.FileNotFoundException;
 19  
 import java.io.IOException;
 20  
 import java.io.StringReader;
 21  
 import java.util.ArrayList;
 22  
 import java.util.Collections;
 23  
 import java.util.List;
 24  
 
 25  
 import javax.persistence.CascadeType;
 26  
 import javax.persistence.Column;
 27  
 import javax.persistence.Entity;
 28  
 import javax.persistence.FetchType;
 29  
 import javax.persistence.JoinColumn;
 30  
 import javax.persistence.ManyToOne;
 31  
 import javax.persistence.Table;
 32  
 import javax.persistence.Transient;
 33  
 import javax.xml.parsers.DocumentBuilder;
 34  
 import javax.xml.parsers.DocumentBuilderFactory;
 35  
 import javax.xml.parsers.ParserConfigurationException;
 36  
 
 37  
 import org.apache.commons.lang.StringUtils;
 38  
 import org.apache.ojb.broker.core.proxy.ProxyHelper;
 39  
 import org.apache.struts.upload.FormFile;
 40  
 import org.kuali.rice.core.util.RiceKeyConstants;
 41  
 import org.kuali.rice.kew.dto.DocumentRouteStatusChangeDTO;
 42  
 import org.kuali.rice.kim.bo.Person;
 43  
 import org.kuali.rice.krad.bo.BusinessObject;
 44  
 import org.kuali.rice.krad.bo.DocumentAttachment;
 45  
 import org.kuali.rice.krad.bo.DocumentHeader;
 46  
 import org.kuali.rice.krad.bo.GlobalBusinessObject;
 47  
 import org.kuali.rice.krad.bo.Note;
 48  
 import org.kuali.rice.krad.bo.PersistableAttachment;
 49  
 import org.kuali.rice.krad.bo.PersistableBusinessObject;
 50  
 import org.kuali.rice.krad.datadictionary.DocumentEntry;
 51  
 import org.kuali.rice.krad.datadictionary.WorkflowAttributes;
 52  
 import org.kuali.rice.krad.datadictionary.WorkflowProperties;
 53  
 import org.kuali.rice.krad.exception.PessimisticLockingException;
 54  
 import org.kuali.rice.krad.exception.ValidationException;
 55  
 import org.kuali.rice.krad.maintenance.Maintainable;
 56  
 import org.kuali.rice.krad.rule.event.KualiDocumentEvent;
 57  
 import org.kuali.rice.krad.rule.event.SaveDocumentEvent;
 58  
 import org.kuali.rice.krad.service.*;
 59  
 import org.kuali.rice.krad.util.GlobalVariables;
 60  
 import org.kuali.rice.krad.util.KRADConstants;
 61  
 import org.kuali.rice.krad.util.MaintenanceUtils;
 62  
 import org.kuali.rice.krad.util.NoteType;
 63  
 import org.kuali.rice.krad.util.ObjectUtils;
 64  
 import org.kuali.rice.krad.util.documentserializer.PropertySerializabilityEvaluator;
 65  
 import org.kuali.rice.krad.workflow.service.KualiWorkflowDocument;
 66  
 import org.w3c.dom.Document;
 67  
 import org.w3c.dom.Node;
 68  
 import org.w3c.dom.NodeList;
 69  
 import org.xml.sax.InputSource;
 70  
 import org.xml.sax.SAXException;
 71  
 
 72  
 
 73  
 /**
 74  
  * The maintenance xml structure will be: <maintainableDocumentContents maintainableImplClass="className">
 75  
  * <oldMaintainableObject>... </oldMaintainableObject> <newMaintainableObject>... </newMaintainableObject>
 76  
  * </maintainableDocumentContents> Maintenance Document
 77  
  */
 78  
 @Entity
 79  
 @Table(name = "KRNS_MAINT_DOC_T")
 80  
 public class MaintenanceDocumentBase extends DocumentBase implements MaintenanceDocument, SessionDocument {
 81  
     private static final long serialVersionUID = -505085142412593305L;
 82  0
     private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(MaintenanceDocumentBase.class);
 83  
     public static final String MAINTAINABLE_IMPL_CLASS = "maintainableImplClass";
 84  
     public static final String OLD_MAINTAINABLE_TAG_NAME = "oldMaintainableObject";
 85  
     public static final String NEW_MAINTAINABLE_TAG_NAME = "newMaintainableObject";
 86  
     public static final String MAINTENANCE_ACTION_TAG_NAME = "maintenanceAction";
 87  
     public static final String NOTES_TAG_NAME = "notes";
 88  
 
 89  
     @Transient
 90  
     transient private static MaintenanceDocumentDictionaryService maintenanceDocumentDictionaryService;
 91  
     @Transient
 92  
     transient private static MaintenanceDocumentService maintenanceDocumentService;
 93  
     @Transient
 94  
     transient private static DocumentHeaderService documentHeaderService;
 95  
     @Transient
 96  
     transient private static DocumentService documentService;
 97  
 
 98  
     @Transient
 99  
     protected Maintainable oldMaintainableObject;
 100  
     @Transient
 101  
     protected Maintainable newMaintainableObject;
 102  
 
 103  
     @Column(name = "DOC_CNTNT", length = 4096)
 104  
     protected String xmlDocumentContents;
 105  
     @Transient
 106  
     protected boolean fieldsClearedOnCopy;
 107  0
     @Transient
 108  
     protected boolean displayTopicFieldInNotes = false;
 109  
 
 110  
     @Transient
 111  
     protected transient FormFile fileAttachment;
 112  
     @Transient
 113  
     protected String attachmentPropertyName;
 114  
 
 115  
     @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE})
 116  
     @JoinColumn(name = "DOC_HDR_ID", insertable = false, updatable = false)
 117  
     protected DocumentAttachment attachment;
 118  
 
 119  
     public FormFile getFileAttachment() {
 120  0
         return this.fileAttachment;
 121  
     }
 122  
 
 123  
     public void setFileAttachment(FormFile fileAttachment) {
 124  0
         this.fileAttachment = fileAttachment;
 125  0
     }
 126  
 
 127  
     public String getAttachmentPropertyName() {
 128  0
         return this.attachmentPropertyName;
 129  
     }
 130  
 
 131  
     public void setAttachmentPropertyName(String attachmentPropertyName) {
 132  0
         this.attachmentPropertyName = attachmentPropertyName;
 133  0
     }
 134  
 
 135  
     public MaintenanceDocumentBase() {
 136  0
         super();
 137  0
         fieldsClearedOnCopy = false;
 138  0
     }
 139  
 
 140  
     /**
 141  
      * Initializies the maintainables.
 142  
      */
 143  
     public MaintenanceDocumentBase(String documentTypeName) {
 144  0
         this();
 145  0
         Class clazz = getMaintenanceDocumentDictionaryService().getMaintainableClass(documentTypeName);
 146  
         try {
 147  0
             oldMaintainableObject = (Maintainable) clazz.newInstance();
 148  0
             newMaintainableObject = (Maintainable) clazz.newInstance();
 149  
 
 150  
             // initialize maintainable with a data object
 151  0
             Class<?> boClazz = getMaintenanceDocumentDictionaryService().getBusinessObjectClass(documentTypeName);
 152  0
             oldMaintainableObject.setDataObject(boClazz.newInstance());
 153  0
             oldMaintainableObject.setBoClass(boClazz);
 154  0
             newMaintainableObject.setDataObject(boClazz.newInstance());
 155  0
             newMaintainableObject.setBoClass(boClazz);
 156  
             
 157  0
         } catch (InstantiationException e) {
 158  0
             LOG.error("Unable to initialize maintainables of type " + clazz.getName());
 159  0
             throw new RuntimeException("Unable to initialize maintainables of type " + clazz.getName());
 160  0
         } catch (IllegalAccessException e) {
 161  0
             LOG.error("Unable to initialize maintainables of type " + clazz.getName());
 162  0
             throw new RuntimeException("Unable to initialize maintainables of type " + clazz.getName());
 163  0
         }
 164  0
     }
 165  
 
 166  
     /**
 167  
      * Builds out the document title for maintenance documents - this will get loaded into the flex doc and passed into workflow. It
 168  
      * will be searchable.
 169  
      */
 170  
     @Override
 171  
     public String getDocumentTitle() {
 172  0
         String documentTitle = "";
 173  
 
 174  0
         documentTitle = newMaintainableObject.getDocumentTitle(this);
 175  0
         if (StringUtils.isNotBlank(documentTitle)) {
 176  
             // if doc title has been overridden by maintainable, use it
 177  0
             return documentTitle;
 178  
         }
 179  
 
 180  
         // TODO - build out with bo label once we get the data dictionary stuff in place
 181  
         // build out the right classname
 182  0
         String className = newMaintainableObject.getDataObject().getClass().getName();
 183  0
         String truncatedClassName = className.substring(className.lastIndexOf('.') + 1);
 184  0
         if (isOldBusinessObjectInDocument()) {
 185  0
             documentTitle = "Edit ";
 186  
         } else {
 187  0
             documentTitle = "New ";
 188  
         }
 189  0
         documentTitle += truncatedClassName + " - ";
 190  0
         documentTitle += this.getDocumentHeader().getDocumentDescription() + " ";
 191  0
         return documentTitle;
 192  
     }
 193  
 
 194  
     /**
 195  
      * @param xmlDocument
 196  
      * @return
 197  
      */
 198  
     protected boolean isOldMaintainableInDocument(Document xmlDocument) {
 199  0
         boolean isOldMaintainableInExistence = false;
 200  0
         if (xmlDocument.getElementsByTagName(OLD_MAINTAINABLE_TAG_NAME).getLength() > 0) {
 201  0
             isOldMaintainableInExistence = true;
 202  
         }
 203  0
         return isOldMaintainableInExistence;
 204  
     }
 205  
 
 206  
 
 207  
     /**
 208  
      * Checks old maintainable bo has key values
 209  
      */
 210  
     public boolean isOldBusinessObjectInDocument() {
 211  0
         boolean isOldBusinessObjectInExistence = false;
 212  0
         if (oldMaintainableObject == null || oldMaintainableObject.getBusinessObject() == null) {
 213  0
             isOldBusinessObjectInExistence = false;
 214  
         } else {
 215  0
             isOldBusinessObjectInExistence = oldMaintainableObject.isOldBusinessObjectInDocument();
 216  
         }
 217  0
         return isOldBusinessObjectInExistence;
 218  
     }
 219  
 
 220  
     /**
 221  
      * This method is a simplified-naming wrapper around isOldBusinessObjectInDocument(), so that the method name matches the
 222  
      * functionality.
 223  
      */
 224  
     public boolean isNew() {
 225  0
         return MaintenanceUtils.isMaintenanceDocumentCreatingNewRecord(newMaintainableObject.getMaintenanceAction());
 226  
     }
 227  
 
 228  
     /**
 229  
      * This method is a simplified-naming wrapper around isOldBusinessObjectInDocument(), so that the method name matches the
 230  
      * functionality.
 231  
      */
 232  
     public boolean isEdit() {
 233  0
         if (KRADConstants.MAINTENANCE_EDIT_ACTION.equalsIgnoreCase(newMaintainableObject.getMaintenanceAction())) {
 234  0
             return true;
 235  
         } else {
 236  0
             return false;
 237  
         }
 238  
         // return isOldBusinessObjectInDocument();
 239  
     }
 240  
 
 241  
     public boolean isNewWithExisting() {
 242  0
         if (KRADConstants.MAINTENANCE_NEWWITHEXISTING_ACTION.equalsIgnoreCase(newMaintainableObject.getMaintenanceAction())) {
 243  0
             return true;
 244  
         } else {
 245  0
             return false;
 246  
         }
 247  
     }
 248  
 
 249  
     public void populateMaintainablesFromXmlDocumentContents() {
 250  
         // get a hold of the parsed xml document, then read the classname,
 251  
         // then instantiate one to two instances depending on content
 252  
         // then populate those instances
 253  0
         if (!StringUtils.isEmpty(xmlDocumentContents)) {
 254  0
             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 255  
             try {
 256  0
                 DocumentBuilder builder = factory.newDocumentBuilder();
 257  0
                 Document xmlDocument = builder.parse(new InputSource(new StringReader(xmlDocumentContents)));
 258  0
                 String clazz = xmlDocument.getDocumentElement().getAttribute(MAINTAINABLE_IMPL_CLASS);
 259  0
                 if (isOldMaintainableInDocument(xmlDocument)) {
 260  0
                     oldMaintainableObject = (Maintainable) Class.forName(clazz).newInstance();
 261  0
                     Object bo = getBusinessObjectFromXML(OLD_MAINTAINABLE_TAG_NAME);
 262  
 
 263  0
                     String oldMaintenanceAction = getMaintenanceAction(xmlDocument, OLD_MAINTAINABLE_TAG_NAME);
 264  0
                     oldMaintainableObject.setMaintenanceAction(oldMaintenanceAction);
 265  
 
 266  0
                     oldMaintainableObject.setDataObject(bo);
 267  0
                     oldMaintainableObject.setBoClass(bo.getClass());
 268  
                 }
 269  0
                 newMaintainableObject = (Maintainable) Class.forName(clazz).newInstance();
 270  0
                 Object bo = getBusinessObjectFromXML(NEW_MAINTAINABLE_TAG_NAME);
 271  0
                 newMaintainableObject.setDataObject(bo);
 272  0
                 newMaintainableObject.setBoClass(bo.getClass());
 273  
 
 274  0
                 String newMaintenanceAction = getMaintenanceAction(xmlDocument, NEW_MAINTAINABLE_TAG_NAME);
 275  0
                 newMaintainableObject.setMaintenanceAction(newMaintenanceAction);
 276  
 
 277  0
                 if (newMaintainableObject.isBoNotesEnabled()) {
 278  0
                     List<Note> notes = getNotesFromXml(NOTES_TAG_NAME);
 279  0
                     setNotes(notes);
 280  
                 }
 281  
 
 282  0
             } catch (ParserConfigurationException e) {
 283  0
                 LOG.error("Error while parsing document contents", e);
 284  0
                 throw new RuntimeException("Could not load document contents from xml", e);
 285  0
             } catch (SAXException e) {
 286  0
                 LOG.error("Error while parsing document contents", e);
 287  0
                 throw new RuntimeException("Could not load document contents from xml", e);
 288  0
             } catch (IOException e) {
 289  0
                 LOG.error("Error while parsing document contents", e);
 290  0
                 throw new RuntimeException("Could not load document contents from xml", e);
 291  0
             } catch (InstantiationException e) {
 292  0
                 LOG.error("Error while parsing document contents", e);
 293  0
                 throw new RuntimeException("Could not load document contents from xml", e);
 294  0
             } catch (IllegalAccessException e) {
 295  0
                 LOG.error("Error while parsing document contents", e);
 296  0
                 throw new RuntimeException("Could not load document contents from xml", e);
 297  0
             } catch (ClassNotFoundException e) {
 298  0
                 LOG.error("Error while parsing document contents", e);
 299  0
                 throw new RuntimeException("Could not load document contents from xml", e);
 300  0
             }
 301  
 
 302  
         }
 303  0
     }
 304  
 
 305  
     /**
 306  
      * This method is a lame containment of ugly DOM walking code. This is ONLY necessary because of the version conflicts between
 307  
      * Xalan.jar in 2.6.x and 2.7. As soon as we can upgrade to 2.7, this will be switched to using XPath, which is faster and much
 308  
      * easier on the eyes.
 309  
      *
 310  
      * @param xmlDocument
 311  
      * @param oldOrNewElementName - String oldMaintainableObject or newMaintainableObject
 312  
      * @return the value of the element, or null if none was there
 313  
      */
 314  
     protected String getMaintenanceAction(Document xmlDocument, String oldOrNewElementName) {
 315  
 
 316  0
         if (StringUtils.isBlank(oldOrNewElementName)) {
 317  0
             throw new IllegalArgumentException("oldOrNewElementName may not be blank, null, or empty-string.");
 318  
         }
 319  
 
 320  0
         String maintenanceAction = null;
 321  0
         NodeList rootChildren = xmlDocument.getDocumentElement().getChildNodes();
 322  0
         for (int i = 0; i < rootChildren.getLength(); i++) {
 323  0
             Node rootChild = rootChildren.item(i);
 324  0
             if (oldOrNewElementName.equalsIgnoreCase(rootChild.getNodeName())) {
 325  0
                 NodeList maintChildren = rootChild.getChildNodes();
 326  0
                 for (int j = 0; j < maintChildren.getLength(); j++) {
 327  0
                     Node maintChild = maintChildren.item(j);
 328  0
                     if (MAINTENANCE_ACTION_TAG_NAME.equalsIgnoreCase(maintChild.getNodeName())) {
 329  0
                         maintenanceAction = maintChild.getChildNodes().item(0).getNodeValue();
 330  
                     }
 331  
                 }
 332  
             }
 333  
         }
 334  0
         return maintenanceAction;
 335  
     }
 336  
 
 337  
     private List<Note> getNotesFromXml(String notesTagName) {
 338  0
         String notesXml = StringUtils.substringBetween(xmlDocumentContents, "<" + notesTagName + ">", "</" + notesTagName + ">");
 339  0
         if (StringUtils.isBlank(notesXml)) {
 340  0
             return Collections.emptyList();
 341  
         }
 342  0
         List<Note> notes = (List<Note>) KRADServiceLocator.getXmlObjectSerializerService().fromXml(notesXml);
 343  0
         if (notes == null) {
 344  0
             return Collections.emptyList();
 345  
         }
 346  0
         return notes;
 347  
     }
 348  
 
 349  
     /**
 350  
      * Retrieves substring of document contents from maintainable tag name. Then use xml service to translate xml into a business
 351  
      * object.
 352  
      */
 353  
     protected Object getBusinessObjectFromXML(String maintainableTagName) {
 354  0
         String maintXml = StringUtils.substringBetween(xmlDocumentContents, "<" + maintainableTagName + ">", "</" + maintainableTagName + ">");
 355  0
         Object businessObject = KRADServiceLocator.getXmlObjectSerializerService().fromXml(maintXml);
 356  0
         return businessObject;
 357  
     }
 358  
 
 359  
     /**
 360  
      * Populates the xml document contents from the maintainables.
 361  
      *
 362  
      * @see org.kuali.rice.krad.document.MaintenanceDocument#populateXmlDocumentContentsFromMaintainables()
 363  
      */
 364  
     public void populateXmlDocumentContentsFromMaintainables() {
 365  0
         StringBuilder docContentBuffer = new StringBuilder();
 366  0
         docContentBuffer.append("<maintainableDocumentContents maintainableImplClass=\"").append(newMaintainableObject.getClass().getName()).append("\">");
 367  
 
 368  
         // if business objects notes are enabled then we need to persist notes to the XML
 369  0
         if (getNewMaintainableObject().isBoNotesEnabled()) {
 370  0
             docContentBuffer.append("<" + NOTES_TAG_NAME + ">");
 371  
             // copy notes to a non-ojb Proxied ArrayList to get rid of the usage of those proxies
 372  
             // note: XmlObjectSerializerServiceImpl should be doing this for us but it does not
 373  
             // appear to be working (at least in this case) and the xml comes through
 374  
             // with the fully qualified ListProxyDefault class name from OJB embedded inside it.
 375  0
             List<Note> noteList = new ArrayList<Note>();
 376  0
             for (Note note : getNotes()) {
 377  0
                 noteList.add(note);
 378  
             }
 379  0
             docContentBuffer.append(KRADServiceLocator.getXmlObjectSerializerService().toXml(noteList));
 380  0
             docContentBuffer.append("</" + NOTES_TAG_NAME + ">");
 381  
         }
 382  0
         if (oldMaintainableObject != null && oldMaintainableObject.getDataObject() != null) {
 383  
             // TODO: refactor this out into a method
 384  0
             docContentBuffer.append("<" + OLD_MAINTAINABLE_TAG_NAME + ">");
 385  
 
 386  0
             Object oldBo = oldMaintainableObject.getDataObject();
 387  
             
 388  
             // hack to resolve XStream not dealing well with Proxies
 389  0
             if(oldBo instanceof PersistableBusinessObject) {
 390  0
                 ObjectUtils.materializeAllSubObjects((PersistableBusinessObject)oldBo);
 391  
             }
 392  
             
 393  0
             docContentBuffer.append(KRADServiceLocator.getBusinessObjectSerializerService().serializeBusinessObjectToXml(oldBo));
 394  
 
 395  
             // add the maintainable's maintenanceAction
 396  0
             docContentBuffer.append("<" + MAINTENANCE_ACTION_TAG_NAME + ">");
 397  0
             docContentBuffer.append(oldMaintainableObject.getMaintenanceAction());
 398  0
             docContentBuffer.append("</" + MAINTENANCE_ACTION_TAG_NAME + ">\n");
 399  
 
 400  0
             docContentBuffer.append("</" + OLD_MAINTAINABLE_TAG_NAME + ">");
 401  
         }
 402  0
         docContentBuffer.append("<" + NEW_MAINTAINABLE_TAG_NAME + ">");
 403  
 
 404  0
         Object newBo = newMaintainableObject.getDataObject();
 405  
         
 406  0
         if(newBo instanceof PersistableBusinessObject) {
 407  
             // hack to resolve XStream not dealing well with Proxies
 408  0
             ObjectUtils.materializeAllSubObjects((PersistableBusinessObject)newBo);
 409  
         }
 410  
         
 411  0
         docContentBuffer.append(KRADServiceLocator.getBusinessObjectSerializerService().serializeBusinessObjectToXml(newBo));
 412  
 
 413  
         // add the maintainable's maintenanceAction
 414  0
         docContentBuffer.append("<" + MAINTENANCE_ACTION_TAG_NAME + ">");
 415  0
         docContentBuffer.append(newMaintainableObject.getMaintenanceAction());
 416  0
         docContentBuffer.append("</" + MAINTENANCE_ACTION_TAG_NAME + ">\n");
 417  
 
 418  0
         docContentBuffer.append("</" + NEW_MAINTAINABLE_TAG_NAME + ">");
 419  0
         docContentBuffer.append("</maintainableDocumentContents>");
 420  0
         xmlDocumentContents = docContentBuffer.toString();
 421  0
     }
 422  
 
 423  
     /**
 424  
      * @see org.kuali.rice.krad.document.DocumentBase#doRouteStatusChange(org.kuali.rice.kew.dto.DocumentRouteStatusChangeDTO)
 425  
      */
 426  
     @Override
 427  
     public void doRouteStatusChange(DocumentRouteStatusChangeDTO statusChangeEvent) {
 428  0
         super.doRouteStatusChange(statusChangeEvent);
 429  
 
 430  0
         KualiWorkflowDocument workflowDocument = getDocumentHeader().getWorkflowDocument();
 431  0
         getNewMaintainableObject().doRouteStatusChange(getDocumentHeader());
 432  
         // commit the changes to the Maintainable BusinessObject when it goes to Processed (ie, fully approved),
 433  
         // and also unlock it
 434  0
         if (workflowDocument.stateIsProcessed()) {
 435  0
             String documentNumber = getDocumentHeader().getDocumentNumber();
 436  0
             newMaintainableObject.setDocumentNumber(documentNumber);
 437  
 
 438  
             //Populate Attachment Property
 439  0
             if (newMaintainableObject.getBusinessObject() instanceof PersistableAttachment) {
 440  0
                 populateAttachmentForBO();
 441  
             }
 442  
 
 443  0
             newMaintainableObject.saveBusinessObject();
 444  
 
 445  0
             if (!getDocumentService().saveDocumentNotes(this)) {
 446  0
                 throw new IllegalStateException("Failed to save document notes, this means that the note target was not ready for notes to be attached when it should have been.");
 447  
             }
 448  
 
 449  
             //Attachment should be deleted from Maintenance Document attachment table
 450  0
             deleteDocumentAttachment();
 451  
 
 452  0
             getMaintenanceDocumentService().deleteLocks(documentNumber);
 453  
 
 454  
             //for issue 3070, check if delete record
 455  0
             if (this.checkAllowsRecordDeletion() && this.checkMaintenanceAction() &&
 456  
                     this.checkDeletePermission(newMaintainableObject.getBusinessObject()))
 457  0
                 newMaintainableObject.deleteBusinessObject();
 458  
         }
 459  
 
 460  
         // unlock the document when its canceled or disapproved
 461  0
         if (workflowDocument.stateIsCanceled() || workflowDocument.stateIsDisapproved()) {
 462  
             //Attachment should be deleted from Maintenance Document attachment table
 463  0
             deleteDocumentAttachment();
 464  
 
 465  0
             String documentNumber = getDocumentHeader().getDocumentNumber();
 466  0
             getMaintenanceDocumentService().deleteLocks(documentNumber);
 467  
         }
 468  0
     }
 469  
 
 470  
     @Override
 471  
     /**
 472  
      * @see org.kuali.rice.krad.document.DocumentBase#getWorkflowEngineDocumentIdsToLock()
 473  
      */
 474  
     public List<Long> getWorkflowEngineDocumentIdsToLock() {
 475  0
         if (newMaintainableObject != null) {
 476  0
             return newMaintainableObject.getWorkflowEngineDocumentIdsToLock();
 477  
         }
 478  0
         return Collections.emptyList();
 479  
     }
 480  
 
 481  
     /**
 482  
      * Pre-Save hook.
 483  
      *
 484  
      * @see org.kuali.rice.krad.document.Document#prepareForSave()
 485  
      */
 486  
     @Override
 487  
     public void prepareForSave() {
 488  0
         if (newMaintainableObject != null) {
 489  0
             newMaintainableObject.prepareForSave();
 490  
         }
 491  0
     }
 492  
 
 493  
     /**
 494  
      * @see org.kuali.rice.krad.document.DocumentBase#processAfterRetrieve()
 495  
      */
 496  
     @Override
 497  
     public void processAfterRetrieve() {
 498  
 
 499  0
         super.processAfterRetrieve();
 500  
             
 501  0
         populateMaintainablesFromXmlDocumentContents();
 502  0
         if (oldMaintainableObject != null) {
 503  0
             oldMaintainableObject.setDocumentNumber(documentNumber);
 504  
         }
 505  0
         if (newMaintainableObject != null) {
 506  0
             newMaintainableObject.setDocumentNumber(documentNumber);
 507  0
             newMaintainableObject.processAfterRetrieve();
 508  
             // If a maintenance lock exists, warn the user.
 509  0
             checkForLockingDocument(false);
 510  
         }
 511  
 
 512  
        
 513  
 
 514  0
     }
 515  
 
 516  
     /**
 517  
      * @return Returns the newMaintainableObject.
 518  
      */
 519  
     public Maintainable getNewMaintainableObject() {
 520  0
         return newMaintainableObject;
 521  
     }
 522  
 
 523  
     /**
 524  
      * @param newMaintainableObject The newMaintainableObject to set.
 525  
      */
 526  
     public void setNewMaintainableObject(Maintainable newMaintainableObject) {
 527  0
         this.newMaintainableObject = newMaintainableObject;
 528  0
     }
 529  
 
 530  
     /**
 531  
      * @return Returns the oldMaintainableObject.
 532  
      */
 533  
     public Maintainable getOldMaintainableObject() {
 534  0
         return oldMaintainableObject;
 535  
     }
 536  
 
 537  
     /**
 538  
      * @param oldMaintainableObject The oldMaintainableObject to set.
 539  
      */
 540  
     public void setOldMaintainableObject(Maintainable oldMaintainableObject) {
 541  0
         this.oldMaintainableObject = oldMaintainableObject;
 542  0
     }
 543  
 
 544  
     @Override
 545  
     public void setDocumentNumber(String documentNumber) {
 546  0
         super.setDocumentNumber(documentNumber);
 547  
 
 548  
         // set the finDocNumber on the Maintainable
 549  0
         oldMaintainableObject.setDocumentNumber(documentNumber);
 550  0
         newMaintainableObject.setDocumentNumber(documentNumber);
 551  
 
 552  0
     }
 553  
 
 554  
     /**
 555  
      * Gets the fieldsClearedOnCopy attribute.
 556  
      *
 557  
      * @return Returns the fieldsClearedOnCopy.
 558  
      */
 559  
     public final boolean isFieldsClearedOnCopy() {
 560  0
         return fieldsClearedOnCopy;
 561  
     }
 562  
 
 563  
     /**
 564  
      * Sets the fieldsClearedOnCopy attribute value.
 565  
      *
 566  
      * @param fieldsClearedOnCopy The fieldsClearedOnCopy to set.
 567  
      */
 568  
     public final void setFieldsClearedOnCopy(boolean fieldsClearedOnCopy) {
 569  0
         this.fieldsClearedOnCopy = fieldsClearedOnCopy;
 570  0
     }
 571  
 
 572  
     /**
 573  
      * Gets the xmlDocumentContents attribute.
 574  
      *
 575  
      * @return Returns the xmlDocumentContents.
 576  
      */
 577  
     public String getXmlDocumentContents() {
 578  0
         return xmlDocumentContents;
 579  
     }
 580  
 
 581  
     /**
 582  
      * Sets the xmlDocumentContents attribute value.
 583  
      *
 584  
      * @param xmlDocumentContents The xmlDocumentContents to set.
 585  
      */
 586  
     public void setXmlDocumentContents(String xmlDocumentContents) {
 587  0
         this.xmlDocumentContents = xmlDocumentContents;
 588  0
     }
 589  
 
 590  
     /**
 591  
      * @see org.kuali.rice.krad.document.Document#getAllowsCopy()
 592  
      */
 593  
     public boolean getAllowsCopy() {
 594  0
         return getMaintenanceDocumentDictionaryService().getAllowsCopy(this);
 595  
     }
 596  
 
 597  
     /**
 598  
      * @see org.kuali.rice.krad.document.MaintenanceDocument#getDisplayTopicFieldInNotes()
 599  
      */
 600  
     public boolean getDisplayTopicFieldInNotes() {
 601  0
         return displayTopicFieldInNotes;
 602  
     }
 603  
 
 604  
     /**
 605  
      * @see org.kuali.rice.krad.document.MaintenanceDocument#setDisplayTopicFieldInNotes(boolean)
 606  
      */
 607  
     public void setDisplayTopicFieldInNotes(boolean displayTopicFieldInNotes) {
 608  0
         this.displayTopicFieldInNotes = displayTopicFieldInNotes;
 609  0
     }
 610  
 
 611  
     @Override
 612  
     /**
 613  
      * Overridden to avoid serializing the xml twice, because of the xmlDocumentContents property of this object
 614  
      */
 615  
     public String serializeDocumentToXml() {
 616  0
         String tempXmlDocumentContents = xmlDocumentContents;
 617  0
         xmlDocumentContents = null;
 618  0
         String xmlForWorkflow = super.serializeDocumentToXml();
 619  0
         xmlDocumentContents = tempXmlDocumentContents;
 620  0
         return xmlForWorkflow;
 621  
     }
 622  
 
 623  
     @Override
 624  
     public void prepareForSave(KualiDocumentEvent event) {
 625  0
         super.prepareForSave(event);
 626  
 
 627  0
         populateDocumentAttachment();
 628  0
         populateXmlDocumentContentsFromMaintainables();
 629  0
     }
 630  
 
 631  
     /**
 632  
      * The attachment BO is proxied in OJB.  For some reason when an attachment does not yet
 633  
      * exist, refreshReferenceObject is not returning null and the proxy cannot be materialized.
 634  
      * So, this method exists to properly handle the proxied attachment BO.  This is a hack
 635  
      * and should be removed post JPA migration.
 636  
      */
 637  
     protected void refreshAttachment() {
 638  0
         if (ObjectUtils.isNull(attachment)) {
 639  0
             this.refreshReferenceObject("attachment");
 640  0
             final boolean isProxy = attachment != null && ProxyHelper.isProxy(attachment);
 641  0
             if (isProxy && ProxyHelper.getRealObject(attachment) == null) {
 642  0
                 attachment = null;
 643  
             }
 644  
         }
 645  0
     }
 646  
 
 647  
     protected void populateAttachmentForBO() {
 648  0
         refreshAttachment();
 649  
 
 650  0
         PersistableAttachment boAttachment = (PersistableAttachment) newMaintainableObject.getBusinessObject();
 651  
 
 652  0
         if (attachment != null) {
 653  
             byte[] fileContents;
 654  0
             fileContents = attachment.getAttachmentContent();
 655  0
             if (fileContents.length > 0) {
 656  0
                 boAttachment.setAttachmentContent(fileContents);
 657  0
                 boAttachment.setFileName(attachment.getFileName());
 658  0
                 boAttachment.setContentType(attachment.getContentType());
 659  
             }
 660  
         }
 661  
 
 662  0
     }
 663  
 
 664  
     public void populateDocumentAttachment() {
 665  0
         refreshAttachment();
 666  
 
 667  0
         if (fileAttachment != null && StringUtils.isNotEmpty(fileAttachment.getFileName())) {
 668  
             //Populate DocumentAttachment BO
 669  0
             if (attachment == null) {
 670  0
                 attachment = new DocumentAttachment();
 671  
             }
 672  
 
 673  
             byte[] fileContents;
 674  
             try {
 675  0
                 fileContents = fileAttachment.getFileData();
 676  0
                 if (fileContents.length > 0) {
 677  0
                     attachment.setFileName(fileAttachment.getFileName());
 678  0
                     attachment.setContentType(fileAttachment.getContentType());
 679  0
                     attachment.setAttachmentContent(fileAttachment.getFileData());
 680  0
                     attachment.setDocumentNumber(getDocumentNumber());
 681  
                 }
 682  0
             } catch (FileNotFoundException e) {
 683  0
                 LOG.error("Error while populating the Document Attachment", e);
 684  0
                 throw new RuntimeException("Could not populate DocumentAttachment object", e);
 685  0
             } catch (IOException e) {
 686  0
                 LOG.error("Error while populating the Document Attachment", e);
 687  0
                 throw new RuntimeException("Could not populate DocumentAttachment object", e);
 688  0
             }
 689  
 
 690  
         }
 691  
 //        else if(attachment != null) {
 692  
 //            //Attachment has been deleted - Need to delete the Attachment Reference Object
 693  
 //            deleteAttachment();
 694  
 //        }
 695  0
     }
 696  
 
 697  
     public void deleteDocumentAttachment() {
 698  0
         KRADServiceLocator.getBusinessObjectService().delete(attachment);
 699  0
         attachment = null;
 700  0
     }
 701  
 
 702  
     /**
 703  
      * Explicitly NOT calling super here.  This is a complete override of the validation
 704  
      * rules behavior.
 705  
      *
 706  
      * @see org.kuali.rice.krad.document.DocumentBase#validateBusinessRules(org.kuali.rice.krad.rule.event.KualiDocumentEvent)
 707  
      */
 708  
     public void validateBusinessRules(KualiDocumentEvent event) {
 709  0
         if (GlobalVariables.getMessageMap().hasErrors()) {
 710  0
             logErrors();
 711  0
             throw new ValidationException("errors occured before business rule");
 712  
         }
 713  
 
 714  
         // check for locking documents for MaintenanceDocuments
 715  0
         if (this instanceof MaintenanceDocument) {
 716  0
             checkForLockingDocument(true);
 717  
         }
 718  
 
 719  
         // Make sure the business object's version number matches that of the database's copy.
 720  0
         if (newMaintainableObject != null) {
 721  0
                 if ( KRADServiceLocator.getPersistenceStructureService().isPersistable( newMaintainableObject.getDataObject().getClass() ) ) {
 722  0
                 PersistableBusinessObject pbObject = KRADServiceLocator.getBusinessObjectService().retrieve(newMaintainableObject.getBusinessObject());
 723  0
                 Long pbObjectVerNbr = ObjectUtils.isNull(pbObject) ? null : pbObject.getVersionNumber();
 724  0
                 Long newObjectVerNbr = newMaintainableObject.getBusinessObject().getVersionNumber();
 725  0
                 if (pbObjectVerNbr != null && !(pbObjectVerNbr.equals(newObjectVerNbr))) {
 726  0
                     GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_ERRORS, RiceKeyConstants.ERROR_VERSION_MISMATCH);
 727  0
                     throw new ValidationException("Version mismatch between the local business object and the database business object");
 728  
                 }
 729  
             }
 730  
         }
 731  
 
 732  
         // perform validation against rules engine
 733  0
         if (LOG.isInfoEnabled()) {
 734  0
             LOG.info("invoking rules engine on document " + getDocumentNumber());
 735  
         }
 736  0
         boolean isValid = true;
 737  0
         isValid = KRADServiceLocatorWeb.getKualiRuleService().applyRules(event);
 738  
 
 739  
         // check to see if the br eval passed or failed
 740  0
         if (!isValid) {
 741  0
             logErrors();
 742  
             // TODO: better error handling at the lower level and a better error message are
 743  
             // needed here
 744  0
             throw new ValidationException("business rule evaluation failed");
 745  0
         } else if (GlobalVariables.getMessageMap().hasErrors()) {
 746  0
             logErrors();
 747  0
             if (event instanceof SaveDocumentEvent) {
 748  
                 // for maintenance documents, we want to always actually do a save if the
 749  
                 // user requests a save, even if there are validation or business rules
 750  
                 // failures. this empty if does this, and allows the document to be saved,
 751  
                 // even if there are failures.
 752  
                 // BR or validation failures on a ROUTE even should always stop the route,
 753  
                 // that has not changed
 754  
             } else {
 755  0
                 throw new ValidationException("Unreported errors occured during business rule evaluation (rule developer needs to put meaningful error messages into global ErrorMap)");
 756  
             }
 757  
         }
 758  0
         LOG.debug("validation completed");
 759  
 
 760  0
     }
 761  
 
 762  
 
 763  
     protected void checkForLockingDocument(boolean throwExceptionIfLocked) {
 764  0
         MaintenanceUtils.checkForLockingDocument(this, throwExceptionIfLocked);
 765  0
     }
 766  
 
 767  
     /**
 768  
      * this needs to happen after the document itself is saved, to preserve consistency of the ver_nbr and in the case of initial
 769  
      * save, because this can't be saved until the document is saved initially
 770  
      *
 771  
      * @see org.kuali.rice.krad.document.DocumentBase#postProcessSave(org.kuali.rice.krad.rule.event.KualiDocumentEvent)
 772  
      */
 773  
     @Override
 774  
     public void postProcessSave(KualiDocumentEvent event) {
 775  0
         PersistableBusinessObject bo = getNewMaintainableObject().getBusinessObject();
 776  0
         if (bo instanceof GlobalBusinessObject) {
 777  0
             KRADServiceLocator.getBusinessObjectService().save(bo);
 778  
         }
 779  
         //currently only global documents could change the list of what they're affecting during routing,
 780  
         //so could restrict this to only happening with them, but who knows if that will change, so safest
 781  
         //to always do the delete and re-add...seems a bit inefficient though if nothing has changed, which is
 782  
         //most of the time...could also try to only add/update/delete what's changed, but this is easier
 783  0
         if (!(event instanceof SaveDocumentEvent)) { //don't lock until they route
 784  0
             getMaintenanceDocumentService().deleteLocks(this.getDocumentNumber());
 785  0
             getMaintenanceDocumentService().storeLocks(this.getNewMaintainableObject().generateMaintenanceLocks());
 786  
         }
 787  0
     }
 788  
 
 789  
     /**
 790  
      * @see org.kuali.rice.krad.document.DocumentBase#getDocumentBusinessObject()
 791  
      */
 792  
     @Override
 793  
     public PersistableBusinessObject getDocumentBusinessObject() {
 794  0
         return getNewMaintainableObject().getBusinessObject();
 795  
     }
 796  
 
 797  
     /**
 798  
      * <p>The Note target for maintenance documents is determined by whether or not the underlying
 799  
      * {@link Maintainable} supports business object notes or not.  This is determined via a call to
 800  
      * {@link Maintainable#isBoNotesEnabled()}.  The note target is then derived as follows:
 801  
      * <p/>
 802  
      * <ul>
 803  
      * <li>If the {@link Maintainable} supports business object notes, delegate to {@link #getDocumentBusinessObject()}.
 804  
      * <li>Otherwise, delegate to the default implementation of getNoteTarget on the superclass which will
 805  
      * effectively return a reference to the {@link DocumentHeader}.
 806  
      * </ul>
 807  
      *
 808  
      * @see org.kuali.rice.krad.document.Document#getNoteTarget()
 809  
      */
 810  
     @Override
 811  
     public PersistableBusinessObject getNoteTarget() {
 812  0
         if (getNewMaintainableObject() == null) {
 813  0
             throw new IllegalStateException("Failed to acquire the note target.  The new maintainable object on this document is null.");
 814  
         }
 815  0
         if (getNewMaintainableObject().isBoNotesEnabled()) {
 816  0
             return getDocumentBusinessObject();
 817  
         }
 818  0
         return super.getNoteTarget();
 819  
     }
 820  
 
 821  
     /**
 822  
      * The {@link NoteType} for maintenance documents is determined by whether or not the underlying
 823  
      * {@link Maintainable} supports business object notes or not.  This is determined via a call to
 824  
      * {@link Maintainable#isBoNotesEnabled()}.  The {@link NoteType} is then derived as follows:
 825  
      * <p/>
 826  
      * <ul>
 827  
      * <li>If the {@link Maintainable} supports business object notes, return {@link NoteType#BUSINESS_OBJECT}.
 828  
      * <li>Otherwise, delegate to {@link DocumentBase#getNoteType()}
 829  
      * </ul>
 830  
      *
 831  
      * @see org.kuali.rice.krad.document.Document#getNoteType()
 832  
      * @see org.kuali.rice.krad.document.Document#getNoteTarget()
 833  
      */
 834  
     @Override
 835  
     public NoteType getNoteType() {
 836  0
         if (getNewMaintainableObject().isBoNotesEnabled()) {
 837  0
             return NoteType.BUSINESS_OBJECT;
 838  
         }
 839  0
         return super.getNoteType();
 840  
     }
 841  
 
 842  
     @Override
 843  
     public PropertySerializabilityEvaluator getDocumentPropertySerizabilityEvaluator() {
 844  0
         String docTypeName = "";
 845  0
         if (newMaintainableObject != null) {
 846  0
             docTypeName = getMaintenanceDocumentDictionaryService().getDocumentTypeName(this.newMaintainableObject.getBoClass());
 847  
         } else { // I don't know why we aren't just using the header in the first place
 848  
             // but, in the case where we can't get it in the way above, attempt to get
 849  
             // it off the workflow document header
 850  0
             if (getDocumentHeader() != null && getDocumentHeader().getWorkflowDocument() != null) {
 851  0
                 docTypeName = getDocumentHeader().getWorkflowDocument().getDocumentType();
 852  
             }
 853  
         }
 854  0
         if (!StringUtils.isBlank(docTypeName)) {
 855  0
             DocumentEntry documentEntry = getMaintenanceDocumentDictionaryService().getMaintenanceDocumentEntry(docTypeName);
 856  0
             if (documentEntry != null) {
 857  0
                 WorkflowProperties workflowProperties = documentEntry.getWorkflowProperties();
 858  0
                 WorkflowAttributes workflowAttributes = documentEntry.getWorkflowAttributes();
 859  0
                 return createPropertySerializabilityEvaluator(workflowProperties, workflowAttributes);
 860  
             } else {
 861  0
                 LOG.error("Unable to obtain DD DocumentEntry for document type: '" + docTypeName + "'");
 862  
             }
 863  0
         } else {
 864  0
             LOG.error("Unable to obtain document type name for this document: " + this);
 865  
         }
 866  0
         LOG.error("Returning null for the PropertySerializabilityEvaluator");
 867  0
         return null;
 868  
     }
 869  
 
 870  
     public DocumentAttachment getAttachment() {
 871  0
         return this.attachment;
 872  
     }
 873  
 
 874  
     public void setAttachment(DocumentAttachment attachment) {
 875  0
         this.attachment = attachment;
 876  0
     }
 877  
 
 878  
 
 879  
     /**
 880  
      * This overridden method is used to delete the {@link DocumentHeader} object due to the system not being able to manage the {@link DocumentHeader} object via mapping files
 881  
      *
 882  
      * @see org.kuali.rice.krad.bo.PersistableBusinessObjectBase#postRemove()
 883  
      */
 884  
     @Override
 885  
     protected void postRemove() {
 886  0
         super.postRemove();
 887  0
         getDocumentHeaderService().deleteDocumentHeader(getDocumentHeader());
 888  0
     }
 889  
 
 890  
     /**
 891  
      * This overridden method is used to retrieve the {@link DocumentHeader} object due to the system not being able to manage the {@link DocumentHeader} object via mapping files
 892  
      *
 893  
      * @see org.kuali.rice.krad.bo.PersistableBusinessObjectBase#postLoad()
 894  
      */
 895  
     @Override
 896  
     protected void postLoad() {
 897  0
         super.postLoad();
 898  0
         setDocumentHeader(getDocumentHeaderService().getDocumentHeaderById(getDocumentNumber()));
 899  0
     }
 900  
 
 901  
     /**
 902  
      * This overridden method is used to insert the {@link DocumentHeader} object due to the system not being able to manage the {@link DocumentHeader} object via mapping files
 903  
      *
 904  
      * @see org.kuali.rice.krad.bo.PersistableBusinessObjectBase#prePersist()
 905  
      */
 906  
     @Override
 907  
     protected void prePersist() {
 908  0
         super.prePersist();
 909  0
         getDocumentHeaderService().saveDocumentHeader(getDocumentHeader());
 910  0
     }
 911  
 
 912  
     /**
 913  
      * This overridden method is used to save the {@link DocumentHeader} object due to the system not being able to manage the {@link DocumentHeader} object via mapping files
 914  
      *
 915  
      * @see org.kuali.rice.krad.bo.PersistableBusinessObjectBase#preUpdate()
 916  
      */
 917  
     @Override
 918  
     protected void preUpdate() {
 919  0
         super.preUpdate();
 920  0
         getDocumentHeaderService().saveDocumentHeader(getDocumentHeader());
 921  0
     }
 922  
 
 923  
     /**
 924  
      * This method to check whether the document class implements SessionDocument
 925  
      *
 926  
      * @return
 927  
      */
 928  
     public boolean isSessionDocument() {
 929  0
         return SessionDocument.class.isAssignableFrom(this.getClass());
 930  
     }
 931  
 
 932  
     /**
 933  
      * Returns whether or not the new maintainable object supports custom lock descriptors. Will always return false if the new maintainable is null.
 934  
      *
 935  
      * @see org.kuali.rice.krad.document.Document#useCustomLockDescriptors()
 936  
      * @see org.kuali.rice.krad.maintenance.Maintainable#useCustomLockDescriptors()
 937  
      */
 938  
     @Override
 939  
     public boolean useCustomLockDescriptors() {
 940  0
         return (newMaintainableObject != null && newMaintainableObject.useCustomLockDescriptors());
 941  
     }
 942  
 
 943  
     /**
 944  
      * Returns the custom lock descriptor generated by the new maintainable object, if defined. Will throw a PessimisticLockingException if
 945  
      * the new maintainable is null.
 946  
      *
 947  
      * @see org.kuali.rice.krad.document.Document#getCustomLockDescriptor(org.kuali.rice.kim.bo.Person)
 948  
      * @see org.kuali.rice.krad.maintenance.Maintainable#getCustomLockDescriptor(org.kuali.rice.kim.bo.Person)
 949  
      */
 950  
     @Override
 951  
     public String getCustomLockDescriptor(Person user) {
 952  0
         if (newMaintainableObject == null) {
 953  0
             throw new PessimisticLockingException("Maintenance Document " + getDocumentNumber() +
 954  
                     " is using pessimistic locking with custom lock descriptors, but no new maintainable object has been defined");
 955  
         }
 956  0
         return newMaintainableObject.getCustomLockDescriptor(user);
 957  
     }
 958  
 
 959  
     protected MaintenanceDocumentDictionaryService getMaintenanceDocumentDictionaryService() {
 960  0
         if (maintenanceDocumentDictionaryService == null) {
 961  0
             maintenanceDocumentDictionaryService = KRADServiceLocatorWeb.getMaintenanceDocumentDictionaryService();
 962  
         }
 963  0
         return maintenanceDocumentDictionaryService;
 964  
     }
 965  
 
 966  
     protected MaintenanceDocumentService getMaintenanceDocumentService() {
 967  0
         if (maintenanceDocumentService == null) {
 968  0
             maintenanceDocumentService = KRADServiceLocatorWeb.getMaintenanceDocumentService();
 969  
         }
 970  0
         return maintenanceDocumentService;
 971  
     }
 972  
 
 973  
     protected DocumentHeaderService getDocumentHeaderService() {
 974  0
         if (documentHeaderService == null) {
 975  0
             documentHeaderService = KRADServiceLocatorWeb.getDocumentHeaderService();
 976  
         }
 977  0
         return documentHeaderService;
 978  
     }
 979  
 
 980  
     protected DocumentService getDocumentService() {
 981  0
         if (documentService == null) {
 982  0
             documentService = KRADServiceLocatorWeb.getDocumentService();
 983  
         }
 984  0
         return documentService;
 985  
     }
 986  
 
 987  
     //for issue KULRice3070
 988  
     protected boolean checkAllowsRecordDeletion() {
 989  0
         Boolean allowsRecordDeletion = KRADServiceLocatorWeb.getMaintenanceDocumentDictionaryService().getAllowsRecordDeletion(this.getNewMaintainableObject().getBoClass());
 990  0
         if (allowsRecordDeletion != null) {
 991  0
             return allowsRecordDeletion.booleanValue();
 992  
         } else {
 993  0
             return false;
 994  
         }
 995  
     }
 996  
 
 997  
     //for KULRice3070
 998  
     protected boolean checkMaintenanceAction() {
 999  0
         return this.getNewMaintainableObject().getMaintenanceAction().equals(KRADConstants.MAINTENANCE_DELETE_ACTION);
 1000  
     }
 1001  
 
 1002  
     //for KULRice3070
 1003  
     protected boolean checkDeletePermission(BusinessObject businessObject) {
 1004  
 
 1005  0
         boolean allowsMaintain = false;
 1006  
 
 1007  0
         String maintDocTypeName = KRADServiceLocatorWeb.getMaintenanceDocumentDictionaryService().getDocumentTypeName(businessObject.getClass());
 1008  
 
 1009  0
         if (StringUtils.isNotBlank(maintDocTypeName)) {
 1010  0
             allowsMaintain = KRADServiceLocatorWeb.getBusinessObjectAuthorizationService().canMaintain(businessObject, GlobalVariables.getUserSession().getPerson(), maintDocTypeName);
 1011  
         }
 1012  0
         return allowsMaintain;
 1013  
     }
 1014  
 }