Coverage Report - org.kuali.rice.krad.maintenance.MaintainableImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
MaintainableImpl
0%
0/136
0%
0/46
1.756
 
 1  
 /*
 2  
  * Copyright 2007 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 1.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/ecl1.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.maintenance;
 17  
 
 18  
 import org.apache.commons.lang.StringUtils;
 19  
 import org.apache.ojb.broker.metadata.ClassNotPersistenceCapableException;
 20  
 import org.kuali.rice.core.api.CoreApiServiceLocator;
 21  
 import org.kuali.rice.core.api.encryption.EncryptionService;
 22  
 import org.kuali.rice.kim.bo.Person;
 23  
 import org.kuali.rice.krad.bo.BusinessObject;
 24  
 import org.kuali.rice.krad.bo.DocumentHeader;
 25  
 import org.kuali.rice.krad.bo.PersistableBusinessObject;
 26  
 import org.kuali.rice.krad.document.MaintenanceDocument;
 27  
 import org.kuali.rice.krad.document.MaintenanceLock;
 28  
 import org.kuali.rice.krad.exception.PessimisticLockingException;
 29  
 import org.kuali.rice.krad.service.BusinessObjectService;
 30  
 import org.kuali.rice.krad.service.DataObjectAuthorizationService;
 31  
 import org.kuali.rice.krad.service.DataObjectMetaDataService;
 32  
 import org.kuali.rice.krad.service.DocumentDictionaryService;
 33  
 import org.kuali.rice.krad.service.KRADServiceLocator;
 34  
 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
 35  
 import org.kuali.rice.krad.service.LookupService;
 36  
 import org.kuali.rice.krad.service.MaintenanceDocumentService;
 37  
 import org.kuali.rice.krad.uif.container.CollectionGroup;
 38  
 import org.kuali.rice.krad.uif.container.View;
 39  
 import org.kuali.rice.krad.uif.service.impl.ViewHelperServiceImpl;
 40  
 import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
 41  
 import org.kuali.rice.krad.util.KRADConstants;
 42  
 import org.kuali.rice.krad.util.ObjectUtils;
 43  
 import org.kuali.rice.krad.web.form.MaintenanceForm;
 44  
 
 45  
 import java.security.GeneralSecurityException;
 46  
 import java.util.ArrayList;
 47  
 import java.util.Collection;
 48  
 import java.util.Iterator;
 49  
 import java.util.List;
 50  
 import java.util.Map;
 51  
 
 52  
 /**
 53  
  * Default implementation of the <code>Maintainable</code> interface
 54  
  *
 55  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 56  
  */
 57  0
 public class MaintainableImpl extends ViewHelperServiceImpl implements Maintainable {
 58  
     private static final long serialVersionUID = 9125271369161634992L;
 59  
 
 60  0
     private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(MaintainableImpl.class);
 61  
 
 62  
     private String documentNumber;
 63  
     private Object dataObject;
 64  
     private Class<?> dataObjectClass;
 65  
     private String maintenanceAction;
 66  
 
 67  
     private transient LookupService lookupService;
 68  
     private transient DataObjectAuthorizationService dataObjectAuthorizationService;
 69  
     private transient DataObjectMetaDataService dataObjectMetaDataService;
 70  
     private transient DocumentDictionaryService documentDictionaryService;
 71  
     private transient EncryptionService encryptionService;
 72  
     private transient BusinessObjectService businessObjectService;
 73  
     private transient MaintenanceDocumentService maintenanceDocumentService;
 74  
 
 75  
     /**
 76  
      * @see Maintainable#retrieveObjectForEditOrCopy(java.util.Map)
 77  
      */
 78  
     @Override
 79  
     public Object retrieveObjectForEditOrCopy(MaintenanceDocument document, Map<String, String> dataObjectKeys) {
 80  0
         Object dataObject = null;
 81  
 
 82  
         try {
 83  0
             dataObject = getLookupService().findObjectBySearch(getDataObjectClass(), dataObjectKeys);
 84  0
         } catch (ClassNotPersistenceCapableException ex) {
 85  0
             if (!document.getOldMaintainableObject().isExternalBusinessObject()) {
 86  0
                 throw new RuntimeException("Data Object Class: " + getDataObjectClass() +
 87  
                         " is not persistable and is not externalizable - configuration error");
 88  
             }
 89  
             // otherwise, let fall through
 90  0
         }
 91  
 
 92  0
         return dataObject;
 93  
     }
 94  
 
 95  
     /**
 96  
      * @see org.kuali.rice.krad.maintenance.Maintainable#setDocumentNumber
 97  
      */
 98  
     @Override
 99  
     public void setDocumentNumber(String documentNumber) {
 100  0
         this.documentNumber = documentNumber;
 101  0
     }
 102  
 
 103  
     /**
 104  
      * @see org.kuali.rice.krad.maintenance.Maintainable#getDocumentTitle
 105  
      */
 106  
     @Override
 107  
     public String getDocumentTitle(MaintenanceDocument document) {
 108  
         // default implementation is to allow MaintenanceDocumentBase to
 109  
         // generate the doc title
 110  0
         return "";
 111  
     }
 112  
 
 113  
     /**
 114  
      * @see org.kuali.rice.krad.maintenance.Maintainable#getDataObject
 115  
      */
 116  
     @Override
 117  
     public Object getDataObject() {
 118  0
         return dataObject;
 119  
     }
 120  
 
 121  
     /**
 122  
      * @see org.kuali.rice.krad.maintenance.Maintainable#setDataObject
 123  
      */
 124  
     @Override
 125  
     public void setDataObject(Object object) {
 126  0
         this.dataObject = object;
 127  0
     }
 128  
 
 129  
     /**
 130  
      * @see org.kuali.rice.krad.maintenance.Maintainable#getDataObjectClass
 131  
      */
 132  
     @Override
 133  
     public Class getDataObjectClass() {
 134  0
         return dataObjectClass;
 135  
     }
 136  
 
 137  
     /**
 138  
      * @see org.kuali.rice.krad.maintenance.Maintainable#setDataObjectClass
 139  
      */
 140  
     @Override
 141  
     public void setDataObjectClass(Class dataObjectClass) {
 142  0
         this.dataObjectClass = dataObjectClass;
 143  0
     }
 144  
 
 145  
     /**
 146  
      * @see org.kuali.rice.krad.maintenance.Maintainable#getMaintenanceAction
 147  
      */
 148  
     @Override
 149  
     public String getMaintenanceAction() {
 150  0
         return maintenanceAction;
 151  
     }
 152  
 
 153  
     /**
 154  
      * @see org.kuali.rice.krad.maintenance.Maintainable#setMaintenanceAction
 155  
      */
 156  
     @Override
 157  
     public void setMaintenanceAction(String maintenanceAction) {
 158  0
         this.maintenanceAction = maintenanceAction;
 159  0
     }
 160  
 
 161  
     /**
 162  
      * Note: as currently implemented, every key field for a given
 163  
      * data object class must have a visible getter
 164  
      *
 165  
      * @see org.kuali.rice.krad.maintenance.Maintainable#generateMaintenanceLocks
 166  
      */
 167  
     @Override
 168  
     public List<MaintenanceLock> generateMaintenanceLocks() {
 169  0
         List<MaintenanceLock> maintenanceLocks = new ArrayList<MaintenanceLock>();
 170  0
         StringBuffer lockRepresentation = new StringBuffer(dataObjectClass.getName());
 171  0
         lockRepresentation.append(KRADConstants.Maintenance.LOCK_AFTER_CLASS_DELIM);
 172  
 
 173  0
         Object bo = getDataObject();
 174  0
         List keyFieldNames = getDocumentDictionaryService().getLockingKeys(getDocumentTypeName());
 175  
 
 176  0
         for (Iterator i = keyFieldNames.iterator(); i.hasNext(); ) {
 177  0
             String fieldName = (String) i.next();
 178  0
             Object fieldValue = ObjectUtils.getPropertyValue(bo, fieldName);
 179  0
             if (fieldValue == null) {
 180  0
                 fieldValue = "";
 181  
             }
 182  
 
 183  
             // check if field is a secure
 184  0
             if (getDataObjectAuthorizationService()
 185  
                     .attributeValueNeedsToBeEncryptedOnFormsAndLinks(dataObjectClass, fieldName)) {
 186  
                 try {
 187  0
                     fieldValue = getEncryptionService().encrypt(fieldValue);
 188  0
                 } catch (GeneralSecurityException e) {
 189  0
                     LOG.error("Unable to encrypt secure field for locking representation " + e.getMessage());
 190  0
                     throw new RuntimeException(
 191  
                             "Unable to encrypt secure field for locking representation " + e.getMessage());
 192  0
                 }
 193  
             }
 194  
 
 195  0
             lockRepresentation.append(fieldName);
 196  0
             lockRepresentation.append(KRADConstants.Maintenance.LOCK_AFTER_FIELDNAME_DELIM);
 197  0
             lockRepresentation.append(String.valueOf(fieldValue));
 198  0
             if (i.hasNext()) {
 199  0
                 lockRepresentation.append(KRADConstants.Maintenance.LOCK_AFTER_VALUE_DELIM);
 200  
             }
 201  0
         }
 202  
 
 203  0
         MaintenanceLock maintenanceLock = new MaintenanceLock();
 204  0
         maintenanceLock.setDocumentNumber(documentNumber);
 205  0
         maintenanceLock.setLockingRepresentation(lockRepresentation.toString());
 206  0
         maintenanceLocks.add(maintenanceLock);
 207  
 
 208  0
         return maintenanceLocks;
 209  
     }
 210  
 
 211  
     /**
 212  
      * Retrieves the document type name from the data dictionary based on
 213  
      * business object class
 214  
      */
 215  
     protected String getDocumentTypeName() {
 216  0
         return getDocumentDictionaryService().getMaintenanceDocumentTypeName(dataObjectClass);
 217  
     }
 218  
 
 219  
     /**
 220  
      * @see org.kuali.rice.krad.maintenance.Maintainable#saveDataObject
 221  
      */
 222  
     @Override
 223  
     public void saveDataObject() {
 224  0
         if (dataObject instanceof PersistableBusinessObject) {
 225  0
             getBusinessObjectService().linkAndSave((PersistableBusinessObject) dataObject);
 226  
         } else {
 227  0
             throw new RuntimeException(
 228  
                     "Cannot save object of type: " + dataObjectClass + " with business object service");
 229  
         }
 230  0
     }
 231  
 
 232  
     /**
 233  
      * @see org.kuali.rice.krad.maintenance.Maintainable#deleteDataObject
 234  
      */
 235  
     @Override
 236  
     public void deleteDataObject() {
 237  0
         if (dataObject == null) {
 238  0
             return;
 239  
         }
 240  
 
 241  0
         if (dataObject instanceof PersistableBusinessObject) {
 242  0
             getBusinessObjectService().delete((PersistableBusinessObject) dataObject);
 243  0
             dataObject = null;
 244  
         } else {
 245  0
             throw new RuntimeException(
 246  
                     "Cannot delete object of type: " + dataObjectClass + " with business object service");
 247  
         }
 248  0
     }
 249  
 
 250  
     /**
 251  
      * @see org.kuali.rice.krad.maintenance.Maintainable#doRouteStatusChange
 252  
      */
 253  
     @Override
 254  
     public void doRouteStatusChange(DocumentHeader documentHeader) {
 255  
         // no default implementation
 256  0
     }
 257  
 
 258  
     /**
 259  
      * @see org.kuali.rice.krad.maintenance.Maintainable#getLockingDocumentId
 260  
      */
 261  
     @Override
 262  
     public String getLockingDocumentId() {
 263  0
         return getMaintenanceDocumentService().getLockingDocumentId(this, documentNumber);
 264  
     }
 265  
 
 266  
     /**
 267  
      * @see org.kuali.rice.krad.maintenance.Maintainable#getWorkflowEngineDocumentIdsToLock
 268  
      */
 269  
     @Override
 270  
     public List<Long> getWorkflowEngineDocumentIdsToLock() {
 271  0
         return null;
 272  
     }
 273  
 
 274  
     /**
 275  
      * Default implementation simply returns false to indicate that custom
 276  
      * lock descriptors are not supported by MaintainableImpl. If custom
 277  
      * lock descriptors are needed, the appropriate subclasses should override
 278  
      * this method
 279  
      *
 280  
      * @see org.kuali.rice.krad.maintenance.Maintainable#useCustomLockDescriptors
 281  
      */
 282  
     @Override
 283  
     public boolean useCustomLockDescriptors() {
 284  0
         return false;
 285  
     }
 286  
 
 287  
     /**
 288  
      * Default implementation just throws a PessimisticLockingException.
 289  
      * Subclasses of MaintainableImpl that need support for custom lock
 290  
      * descriptors should override this method
 291  
      *
 292  
      * @see org.kuali.rice.krad.maintenance.Maintainable#getCustomLockDescriptor
 293  
      */
 294  
     @Override
 295  
     public String getCustomLockDescriptor(Person user) {
 296  0
         throw new PessimisticLockingException("The Maintainable for document " + documentNumber +
 297  
                 " is using pessimistic locking with custom lock descriptors, but the Maintainable has not overridden the getCustomLockDescriptor method");
 298  
     }
 299  
 
 300  
     /**
 301  
      * @see org.kuali.rice.krad.maintenance.Maintainable#isBoNotesEnabled
 302  
      */
 303  
     @Override
 304  
     public boolean isNotesEnabled() {
 305  0
         if (BusinessObject.class.isAssignableFrom(dataObjectClass)) {
 306  0
             return getDataObjectMetaDataService().areNotesSupported(dataObjectClass);
 307  
         }
 308  
 
 309  0
         return false;
 310  
     }
 311  
 
 312  
     /**
 313  
      * @see org.kuali.rice.krad.maintenance.MaintainableImpl#isExternalBusinessObject
 314  
      */
 315  
     @Override
 316  
     public boolean isExternalBusinessObject() {
 317  0
         return false;
 318  
     }
 319  
 
 320  
     /**
 321  
      * @see org.kuali.rice.krad.maintenance.MaintainableImpl#prepareExternalBusinessObject
 322  
      */
 323  
     @Override
 324  
     public void prepareExternalBusinessObject(BusinessObject businessObject) {
 325  
         // by default do nothing
 326  0
     }
 327  
 
 328  
     /**
 329  
      * Checks whether the data object is not null and has its primary key values populated
 330  
      *
 331  
      * @see org.kuali.rice.krad.maintenance.MaintainableImpl#isOldDataObjectInDocument
 332  
      */
 333  
     @Override
 334  
     public boolean isOldDataObjectInDocument() {
 335  0
         boolean isOldDataObjectInExistence = true;
 336  
 
 337  0
         if (getDataObject() == null) {
 338  0
             isOldDataObjectInExistence = false;
 339  
         } else {
 340  0
             Map<String, ?> keyFieldValues = getDataObjectMetaDataService().getPrimaryKeyFieldValues(getDataObject());
 341  0
             for (Object keyValue : keyFieldValues.values()) {
 342  0
                 if (keyValue == null) {
 343  0
                     isOldDataObjectInExistence = false;
 344  0
                 } else if ((keyValue instanceof String) && StringUtils.isBlank((String) keyValue)) {
 345  0
                     isOldDataObjectInExistence = false;
 346  
                 }
 347  
 
 348  0
                 if (!isOldDataObjectInExistence) {
 349  0
                     break;
 350  
                 }
 351  
             }
 352  
         }
 353  
 
 354  0
         return isOldDataObjectInExistence;
 355  
     }
 356  
 
 357  
     /**
 358  
      * @see org.kuali.rice.krad.maintenance.Maintainable#prepareForSave
 359  
      */
 360  
     @Override
 361  
     public void prepareForSave() {
 362  
         // by default do nothing
 363  0
     }
 364  
 
 365  
     /**
 366  
      * @see org.kuali.rice.krad.maintenance.Maintainable#processAfterRetrieve
 367  
      */
 368  
     @Override
 369  
     public void processAfterRetrieve() {
 370  
         // by default do nothing
 371  0
     }
 372  
 
 373  
     /**
 374  
      * @see org.kuali.rice.krad.maintenance.MaintainableImpl#setupNewFromExisting
 375  
      */
 376  
     @Override
 377  
     public void setupNewFromExisting(MaintenanceDocument document, Map<String, String[]> parameters) {
 378  
         // by default do nothing
 379  0
     }
 380  
 
 381  
     /**
 382  
      * @see org.kuali.rice.krad.maintenance.Maintainable#processAfterCopy
 383  
      */
 384  
     @Override
 385  
     public void processAfterCopy(MaintenanceDocument document, Map<String, String[]> requestParameters) {
 386  
         // by default do nothing
 387  0
     }
 388  
 
 389  
     /**
 390  
      * @see org.kuali.rice.krad.maintenance.Maintainable#processAfterEdit
 391  
      */
 392  
     @Override
 393  
     public void processAfterEdit(MaintenanceDocument document, Map<String, String[]> requestParameters) {
 394  
         // by default do nothing
 395  0
     }
 396  
 
 397  
     /**
 398  
      * @see org.kuali.rice.krad.maintenance.Maintainable#processAfterNew
 399  
      */
 400  
     @Override
 401  
     public void processAfterNew(MaintenanceDocument document, Map<String, String[]> requestParameters) {
 402  
         // by default do nothing
 403  0
     }
 404  
 
 405  
     /**
 406  
      * @see org.kuali.rice.krad.maintenance.Maintainable#processAfterPost
 407  
      */
 408  
     @Override
 409  
     public void processAfterPost(MaintenanceDocument document, Map<String, String[]> requestParameters) {
 410  
         // by default do nothing
 411  0
     }
 412  
 
 413  
     /**
 414  
      * In the case of edit maintenance adds a new blank line to the old side
 415  
      *
 416  
      * TODO: should this write some sort of missing message on the old side
 417  
      * instead?
 418  
      *
 419  
      * @see org.kuali.rice.krad.uif.service.impl.ViewHelperServiceImpl#processAfterAddLine(org.kuali.rice.krad.uif.container.View,
 420  
      *      org.kuali.rice.krad.uif.container.CollectionGroup, java.lang.Object,
 421  
      *      java.lang.Object)
 422  
      */
 423  
     @Override
 424  
     protected void processAfterAddLine(View view, CollectionGroup collectionGroup, Object model, Object addLine) {
 425  0
         super.processAfterAddLine(view, collectionGroup, model, addLine);
 426  
 
 427  0
         if (KRADConstants.MAINTENANCE_EDIT_ACTION.equals(maintenanceAction)) {
 428  0
             MaintenanceForm maintenanceForm = (MaintenanceForm) model;
 429  0
             MaintenanceDocument document = maintenanceForm.getDocument();
 430  
 
 431  
             // get the old object's collection
 432  0
             Collection<Object> oldCollection = ObjectPropertyUtils
 433  
                     .getPropertyValue(document.getOldMaintainableObject().getDataObject(),
 434  
                             collectionGroup.getPropertyName());
 435  
             try {
 436  0
                 Object blankLine = getDataObjectClass().newInstance();
 437  0
                 oldCollection.add(blankLine);
 438  0
             } catch (Exception e) {
 439  0
                 throw new RuntimeException("Unable to create new line instance for old maintenance object", e);
 440  0
             }
 441  
         }
 442  0
     }
 443  
 
 444  
     /**
 445  
      * Retrieves the document number configured on this maintainable
 446  
      *
 447  
      * @return String document number
 448  
      */
 449  
     protected String getDocumentNumber() {
 450  0
         return this.documentNumber;
 451  
     }
 452  
 
 453  
     protected LookupService getLookupService() {
 454  0
         if (lookupService == null) {
 455  0
             lookupService = KRADServiceLocatorWeb.getLookupService();
 456  
         }
 457  0
         return this.lookupService;
 458  
     }
 459  
 
 460  
     public void setLookupService(LookupService lookupService) {
 461  0
         this.lookupService = lookupService;
 462  0
     }
 463  
 
 464  
     protected DataObjectAuthorizationService getDataObjectAuthorizationService() {
 465  0
         if (dataObjectAuthorizationService == null) {
 466  0
             this.dataObjectAuthorizationService = KRADServiceLocatorWeb.getDataObjectAuthorizationService();
 467  
         }
 468  0
         return dataObjectAuthorizationService;
 469  
     }
 470  
 
 471  
     public void setDataObjectAuthorizationService(DataObjectAuthorizationService dataObjectAuthorizationService) {
 472  0
         this.dataObjectAuthorizationService = dataObjectAuthorizationService;
 473  0
     }
 474  
 
 475  
     protected DataObjectMetaDataService getDataObjectMetaDataService() {
 476  0
         if (dataObjectMetaDataService == null) {
 477  0
             this.dataObjectMetaDataService = KRADServiceLocatorWeb.getDataObjectMetaDataService();
 478  
         }
 479  0
         return dataObjectMetaDataService;
 480  
     }
 481  
 
 482  
     public void setDataObjectMetaDataService(DataObjectMetaDataService dataObjectMetaDataService) {
 483  0
         this.dataObjectMetaDataService = dataObjectMetaDataService;
 484  0
     }
 485  
 
 486  
     public DocumentDictionaryService getDocumentDictionaryService() {
 487  0
         if (documentDictionaryService == null) {
 488  0
             this.documentDictionaryService = KRADServiceLocatorWeb.getDocumentDictionaryService();
 489  
         }
 490  0
         return documentDictionaryService;
 491  
     }
 492  
 
 493  
     public void setDocumentDictionaryService(DocumentDictionaryService documentDictionaryService) {
 494  0
         this.documentDictionaryService = documentDictionaryService;
 495  0
     }
 496  
 
 497  
     protected EncryptionService getEncryptionService() {
 498  0
         if (encryptionService == null) {
 499  0
             encryptionService = CoreApiServiceLocator.getEncryptionService();
 500  
         }
 501  0
         return encryptionService;
 502  
     }
 503  
 
 504  
     public void setEncryptionService(EncryptionService encryptionService) {
 505  0
         this.encryptionService = encryptionService;
 506  0
     }
 507  
 
 508  
     protected BusinessObjectService getBusinessObjectService() {
 509  0
         if (businessObjectService == null) {
 510  0
             businessObjectService = KRADServiceLocator.getBusinessObjectService();
 511  
         }
 512  0
         return businessObjectService;
 513  
     }
 514  
 
 515  
     public void setBusinessObjectService(BusinessObjectService businessObjectService) {
 516  0
         this.businessObjectService = businessObjectService;
 517  0
     }
 518  
 
 519  
     protected MaintenanceDocumentService getMaintenanceDocumentService() {
 520  0
         if (maintenanceDocumentService == null) {
 521  0
             maintenanceDocumentService = KRADServiceLocatorWeb.getMaintenanceDocumentService();
 522  
         }
 523  0
         return maintenanceDocumentService;
 524  
     }
 525  
 
 526  
     public void setMaintenanceDocumentService(MaintenanceDocumentService maintenanceDocumentService) {
 527  0
         this.maintenanceDocumentService = maintenanceDocumentService;
 528  0
     }
 529  
 }