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.module.purap.document; 017 018 import java.security.GeneralSecurityException; 019 import java.util.Collection; 020 import java.util.List; 021 022 import org.kuali.kfs.module.purap.businessobject.ReceivingAddress; 023 import org.kuali.kfs.module.purap.document.service.ReceivingAddressService; 024 import org.kuali.kfs.sys.KFSConstants; 025 import org.kuali.kfs.sys.context.SpringContext; 026 import org.kuali.kfs.sys.document.FinancialSystemMaintainable; 027 import org.kuali.rice.core.service.EncryptionService; 028 import org.kuali.rice.kns.bo.DocumentHeader; 029 import org.kuali.rice.kns.document.MaintenanceLock; 030 import org.kuali.rice.kns.service.BusinessObjectAuthorizationService; 031 import org.kuali.rice.kns.service.BusinessObjectService; 032 import org.kuali.rice.kns.service.DataDictionaryService; 033 import org.kuali.rice.kns.util.ObjectUtils; 034 import org.kuali.rice.kns.workflow.service.KualiWorkflowDocument; 035 036 /** 037 * ReceivingAddressMaintainableImpl is a special implementation of FinancialSystemMaintainable for ReceivingAddresss. 038 * It generates extra locks for other receiving addresses related to the one being updated in the maintenance document, 039 * and updates the ones affected during post-processing to enforce certain contraints among these objects. 040 */ 041 public class ReceivingAddressMaintainableImpl extends FinancialSystemMaintainable { 042 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(ReceivingAddressMaintainableImpl.class); 043 044 /** 045 * Generates the appropriate maintenance locks for {@link ReceivingAddress} 046 * 047 * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#generateMaintenanceLocks() 048 */ 049 @Override 050 public List<MaintenanceLock> generateMaintenanceLocks() { 051 ReceivingAddress receivingAddress = (ReceivingAddress) this.businessObject; 052 List<MaintenanceLock> locks = super.generateMaintenanceLocks(); 053 if ( receivingAddress.isDefaultIndicator() && receivingAddress.isActive() ) { 054 locks.add(createMaintenanceLock(new String[] { "chartOfAccountsCode", "organizationCode", "defaultIndicator", "active" })); 055 } 056 return locks; 057 } 058 059 /** 060 * Creates a maintenance lock for the field names supplied. 061 * 062 * @param fieldNames 063 * @return the maintenance lock for supplied field names 064 */ 065 private MaintenanceLock createMaintenanceLock(String[] fieldNames) { 066 MaintenanceLock lock = new MaintenanceLock(); 067 lock.setDocumentNumber(this.documentNumber); 068 lock.setLockingRepresentation(createLockingRepresentation(fieldNames)); 069 return lock; 070 } 071 072 /** 073 * Creates a locking representation for the field names supplied. 074 * 075 * @param fieldNames 076 * @return locking representation string 077 */ 078 private String createLockingRepresentation(String[] fieldNames) { 079 StringBuilder lockRepresentation = new StringBuilder(); 080 081 lockRepresentation.append(ReceivingAddress.class.getName()); 082 lockRepresentation.append(KFSConstants.Maintenance.AFTER_CLASS_DELIM); 083 084 DataDictionaryService dataDictionaryService = SpringContext.getBean(DataDictionaryService.class); 085 EncryptionService encryptionService = SpringContext.getBean(EncryptionService.class); 086 087 int count = 0; 088 for (String fieldName : fieldNames) { 089 lockRepresentation.append(fieldName); 090 lockRepresentation.append(KFSConstants.Maintenance.AFTER_FIELDNAME_DELIM); 091 lockRepresentation.append(retrieveFieldValueForLock(fieldName, dataDictionaryService, encryptionService)); 092 if (count < (fieldNames.length - 1)) { 093 lockRepresentation.append(KFSConstants.Maintenance.AFTER_VALUE_DELIM); 094 } 095 count += 1; 096 } 097 098 return lockRepresentation.toString(); 099 } 100 101 /** 102 * Returns the field value of a given field, converting the value to a String and encrypting it if necessary. 103 * 104 * @param fieldName 105 * @param ddService 106 * @return string field value for a lock 107 */ 108 private String retrieveFieldValueForLock(String fieldName, DataDictionaryService ddService, EncryptionService encryptionService) { 109 Object fieldValue = ObjectUtils.getPropertyValue(this.businessObject, fieldName); 110 if (fieldValue == null) { 111 fieldValue = ""; 112 } 113 114 // check if field is a secure 115 if (SpringContext.getBean(BusinessObjectAuthorizationService.class).attributeValueNeedsToBeEncryptedOnFormsAndLinks(getBoClass(), fieldName)) { 116 try { 117 fieldValue = encryptionService.encrypt(fieldValue); 118 } 119 catch (GeneralSecurityException e) { 120 LOG.error("Unable to encrypt secure field for locking representation " + e.getMessage()); 121 throw new RuntimeException("Unable to encrypt secure field for locking representation " + e.getMessage()); 122 } 123 } 124 return String.valueOf(fieldValue); 125 } 126 127 /** 128 * Checks if there's any active receiving address set to default other than this one; 129 * if so, set them to non-default. 130 * 131 * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#doRouteStatusChange(org.kuali.rice.kns.bo.DocumentHeader) 132 */ 133 @Override 134 public void doRouteStatusChange(DocumentHeader header) { 135 super.doRouteStatusChange(header); 136 137 ReceivingAddress ra = (ReceivingAddress) getBusinessObject(); 138 // proceed only if this bo is active and default. 139 if ( !ra.isActive() || !ra.isDefaultIndicator() ) 140 return; 141 142 KualiWorkflowDocument workflowDoc = header.getWorkflowDocument(); 143 // this code is only executed when the final approval occurs 144 if (workflowDoc.stateIsProcessed()) { 145 /* 146 Map criteria = new HashMap(); 147 criteria.put(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, ra.getChartOfAccountsCode()); 148 criteria.put(KFSPropertyConstants.ORGANIZATION_CODE, ra.getOrganizationCode()); 149 criteria.put(PurapPropertyConstants.RCVNG_ADDR_DFLT_IND, true); 150 criteria.put(PurapPropertyConstants.RCVNG_ADDR_ACTIVE, true); 151 List<ReceivingAddress> addresses = (List)SpringContext.getBean(BusinessObjectService.class).findMatching(ReceivingAddress.class, criteria); 152 */ 153 Collection<ReceivingAddress> addresses = SpringContext.getBean(ReceivingAddressService.class).findDefaultByChartOrg(ra.getChartOfAccountsCode(),ra.getOrganizationCode()); 154 for ( ReceivingAddress rai : addresses ) { 155 if ( !rai.getReceivingAddressIdentifier().equals(ra.getReceivingAddressIdentifier()) ) { 156 rai.setDefaultIndicator(false); 157 SpringContext.getBean(BusinessObjectService.class).save(rai); 158 } 159 } 160 } 161 } 162 163 }