001 /* 002 * Copyright 2011 The Kuali Foundation. 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.kfs.coa.document; 017 018 import java.security.GeneralSecurityException; 019 import java.sql.Date; 020 import java.util.List; 021 import java.util.Map; 022 023 import org.apache.commons.lang.StringUtils; 024 import org.kuali.kfs.coa.businessobject.AccountDelegate; 025 import org.kuali.kfs.coa.businessobject.AccountDelegateGlobal; 026 import org.kuali.kfs.coa.service.AccountDelegateService; 027 import org.kuali.kfs.sys.KFSConstants; 028 import org.kuali.kfs.sys.context.SpringContext; 029 import org.kuali.kfs.sys.document.FinancialSystemMaintainable; 030 import org.kuali.rice.core.service.EncryptionService; 031 import org.kuali.rice.kim.service.RoleManagementService; 032 import org.kuali.rice.kns.bo.DocumentHeader; 033 import org.kuali.rice.kns.document.MaintenanceDocument; 034 import org.kuali.rice.kns.document.MaintenanceLock; 035 import org.kuali.rice.kns.service.BusinessObjectAuthorizationService; 036 import org.kuali.rice.kns.service.DataDictionaryService; 037 import org.kuali.rice.kns.service.DateTimeService; 038 import org.kuali.rice.kns.service.KNSServiceLocator; 039 import org.kuali.rice.kns.util.ObjectUtils; 040 041 /** 042 * This class is a special implementation of Maintainable specifically for Account Delegates. It was created to correctly update the 043 * default Start Date on edits and copies, ala JIRA #KULRNE-62. 044 */ 045 public class AccountDelegateMaintainableImpl extends FinancialSystemMaintainable { 046 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AccountDelegateMaintainableImpl.class); 047 048 /** 049 * This method will reset AccountDelegate's Start Date to the current timestamp on edits and copies 050 * 051 * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#processAfterRetrieve() 052 */ 053 @Override 054 public void processAfterCopy( MaintenanceDocument document, Map<String,String[]> parameters ) { 055 this.setStartDateDefault(); 056 super.processAfterCopy( document, parameters ); 057 } 058 059 /** 060 * This method will reset AccountDelegate's Start Date to the current timestamp on edits and copies 061 * 062 * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#processAfterEdit() 063 */ 064 @Override 065 public void processAfterEdit( MaintenanceDocument document, Map<String,String[]> parameters ) { 066 this.setStartDateDefault(); 067 super.processAfterEdit( document, parameters ); 068 } 069 070 /** 071 * This method sets the start date on {@link Delegate} BO 072 */ 073 protected void setStartDateDefault() { 074 if (this.businessObject != null && this.businessObject instanceof AccountDelegate) { 075 AccountDelegate delegate = (AccountDelegate) this.businessObject; 076 delegate.setAccountDelegateStartDate(new Date(SpringContext.getBean(DateTimeService.class).getCurrentDate().getTime())); 077 } 078 } 079 080 /** 081 * Generates the appropriate maintenance locks for the {@link Delegate} 082 * 083 * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#generateMaintenanceLocks() 084 */ 085 @Override 086 public List<MaintenanceLock> generateMaintenanceLocks() { 087 AccountDelegate delegate = (AccountDelegate) this.businessObject; 088 List<MaintenanceLock> locks = super.generateMaintenanceLocks(); 089 if (delegate.isAccountsDelegatePrmrtIndicator()) { 090 locks.add(createMaintenanceLock(new String[] { "chartOfAccountsCode", "accountNumber", "financialDocumentTypeCode", "accountsDelegatePrmrtIndicator" })); 091 } 092 return locks; 093 } 094 095 @Override 096 public String getLockingDocumentId() { 097 String lock = super.getLockingDocumentId(); 098 if (StringUtils.isNotBlank(lock)) 099 return lock; 100 else { 101 AccountDelegateService accountDelegateService = SpringContext.getBean(AccountDelegateService.class); 102 lock = accountDelegateService.getLockingDocumentId(this, this.documentNumber); 103 return lock; 104 } 105 } 106 107 /** 108 * This method creates a maintenance lock for the field names supplied 109 * 110 * @param fieldNames 111 * @return the maintenance lock for supplied field names 112 */ 113 protected MaintenanceLock createMaintenanceLock(String[] fieldNames) { 114 MaintenanceLock lock = new MaintenanceLock(); 115 lock.setDocumentNumber(this.documentNumber); 116 lock.setLockingRepresentation(createLockingRepresentation(fieldNames)); 117 return lock; 118 119 } 120 121 /** 122 * This method create a locking representation for the field names supplied 123 * 124 * @param fieldNames 125 * @return locking representation string 126 */ 127 protected String createLockingRepresentation(String[] fieldNames) { 128 StringBuilder lockRepresentation = new StringBuilder(); 129 130 lockRepresentation.append(AccountDelegate.class.getName()); 131 lockRepresentation.append(KFSConstants.Maintenance.AFTER_CLASS_DELIM); 132 133 DataDictionaryService dataDictionaryService = KNSServiceLocator.getDataDictionaryService(); 134 EncryptionService encryptionService = KNSServiceLocator.getEncryptionService(); 135 136 int count = 0; 137 for (String fieldName : fieldNames) { 138 lockRepresentation.append(fieldName); 139 lockRepresentation.append(KFSConstants.Maintenance.AFTER_FIELDNAME_DELIM); 140 lockRepresentation.append(retrieveFieldValueForLock(fieldName, dataDictionaryService, encryptionService)); 141 if (count < (fieldNames.length - 1)) { 142 lockRepresentation.append(KFSConstants.Maintenance.AFTER_VALUE_DELIM); 143 } 144 count += 1; 145 } 146 147 148 return lockRepresentation.toString(); 149 } 150 151 /** 152 * This method returns the field value of a given field, converting the value to a String and encrypting it if necessary 153 * 154 * @param fieldName 155 * @param ddService 156 * @return string field value for a lock 157 */ 158 protected String retrieveFieldValueForLock(String fieldName, DataDictionaryService ddService, EncryptionService encryptionService) { 159 Object fieldValue = ObjectUtils.getPropertyValue(this.businessObject, fieldName); 160 if (fieldValue == null) { 161 fieldValue = ""; 162 } 163 164 // check if field is a secure 165 if (SpringContext.getBean(BusinessObjectAuthorizationService.class).attributeValueNeedsToBeEncryptedOnFormsAndLinks(getBoClass(), fieldName)) { 166 try { 167 fieldValue = encryptionService.encrypt(fieldValue); 168 } 169 catch (GeneralSecurityException e) { 170 LOG.error("Unable to encrypt secure field for locking representation " + e.getMessage()); 171 throw new RuntimeException("Unable to encrypt secure field for locking representation " + e.getMessage()); 172 } 173 } 174 return String.valueOf(fieldValue); 175 } 176 177 /** 178 * This method created a MaintenanceLock for the chartOfAccountsCode and accountNumber for an AccountDelegateGlobal. 179 * 180 * @return the MainenanceLock 181 */ 182 183 public MaintenanceLock createGlobalAccountLock() { 184 185 String[] fields = {"chartOfAccountsCode", "accountNumber"}; 186 MaintenanceLock lock = new MaintenanceLock(); 187 lock.setDocumentNumber(this.documentNumber); 188 189 StringBuilder lockRepresentation = new StringBuilder(); 190 191 lockRepresentation.append(AccountDelegateGlobal.class.getName()); 192 lockRepresentation.append(KFSConstants.Maintenance.AFTER_CLASS_DELIM); 193 194 DataDictionaryService dataDictionaryService = KNSServiceLocator.getDataDictionaryService(); 195 EncryptionService encryptionService = KNSServiceLocator.getEncryptionService(); 196 197 int count = 0; 198 for (String fieldName : fields) { 199 lockRepresentation.append(fieldName); 200 lockRepresentation.append(KFSConstants.Maintenance.AFTER_FIELDNAME_DELIM); 201 lockRepresentation.append(retrieveFieldValueForLock(fieldName, dataDictionaryService, encryptionService)); 202 if (count < (fields.length - 1)) { 203 lockRepresentation.append(KFSConstants.Maintenance.AFTER_VALUE_DELIM); 204 } 205 count += 1; 206 } 207 208 lock.setLockingRepresentation(lockRepresentation.toString()); 209 210 return lock; 211 } 212 213 /** 214 * Overridden so that after account delegate is saved, it updates the proper account delegate role 215 * Defers saving to a service to guarantee that the delegate saves in a separate transaction 216 * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#saveBusinessObject() 217 */ 218 @Override 219 public void saveBusinessObject() { 220 final AccountDelegate accountDelegate = (AccountDelegate)getBusinessObject(); 221 final AccountDelegateService accountDelegateService = SpringContext.getBean(AccountDelegateService.class); 222 223 accountDelegateService.saveForMaintenanceDocument(accountDelegate); 224 225 accountDelegateService.updateDelegationRole(); 226 } 227 228 229 }