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