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 }