001/* 002 * Copyright 2008 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.module.purap.document; 017 018import org.kuali.ole.module.purap.businessobject.ReceivingAddress; 019import org.kuali.ole.module.purap.document.service.ReceivingAddressService; 020import org.kuali.ole.sys.OLEConstants; 021import org.kuali.ole.sys.context.SpringContext; 022import org.kuali.ole.sys.document.FinancialSystemMaintainable; 023import org.kuali.rice.core.api.encryption.EncryptionService; 024import org.kuali.rice.kew.api.WorkflowDocument; 025import org.kuali.rice.kns.service.BusinessObjectAuthorizationService; 026import org.kuali.rice.kns.service.DataDictionaryService; 027import org.kuali.rice.krad.bo.DocumentHeader; 028import org.kuali.rice.krad.maintenance.MaintenanceLock; 029import org.kuali.rice.krad.service.BusinessObjectService; 030import org.kuali.rice.krad.util.ObjectUtils; 031 032import java.security.GeneralSecurityException; 033import java.util.Collection; 034import java.util.List; 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 */ 041public 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(getDocumentNumber()); 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(OLEConstants.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(OLEConstants.Maintenance.AFTER_FIELDNAME_DELIM); 091 lockRepresentation.append(retrieveFieldValueForLock(fieldName, dataDictionaryService, encryptionService)); 092 if (count < (fieldNames.length - 1)) { 093 lockRepresentation.append(OLEConstants.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 } catch (GeneralSecurityException e) { 119 LOG.error("Unable to encrypt secure field for locking representation " + e.getMessage()); 120 throw new RuntimeException("Unable to encrypt secure field for locking representation " + e.getMessage()); 121 } 122 } 123 return String.valueOf(fieldValue); 124 } 125 126 /** 127 * Checks if there's any active receiving address set to default other than this one; 128 * if so, set them to non-default. 129 * 130 * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#doRouteStatusChange(org.kuali.rice.krad.bo.DocumentHeader) 131 */ 132 @Override 133 public void doRouteStatusChange(DocumentHeader header) { 134 super.doRouteStatusChange(header); 135 136 ReceivingAddress ra = (ReceivingAddress) getBusinessObject(); 137 // proceed only if this bo is active and default. 138 if (!ra.isActive() || !ra.isDefaultIndicator()) 139 return; 140 141 WorkflowDocument workflowDoc = header.getWorkflowDocument(); 142 // this code is only executed when the final approval occurs 143 if (workflowDoc.isProcessed()) { 144 /* 145 Map criteria = new HashMap(); 146 criteria.put(OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE, ra.getChartOfAccountsCode()); 147 criteria.put(OLEPropertyConstants.ORGANIZATION_CODE, ra.getOrganizationCode()); 148 criteria.put(PurapPropertyConstants.RCVNG_ADDR_DFLT_IND, true); 149 criteria.put(PurapPropertyConstants.RCVNG_ADDR_ACTIVE, true); 150 List<ReceivingAddress> addresses = (List)SpringContext.getBean(BusinessObjectService.class).findMatching(ReceivingAddress.class, criteria); 151 */ 152 Collection<ReceivingAddress> addresses = SpringContext.getBean(ReceivingAddressService.class).findDefaultByChartOrg(ra.getChartOfAccountsCode(), ra.getOrganizationCode()); 153 for (ReceivingAddress rai : addresses) { 154 if (!rai.getReceivingAddressIdentifier().equals(ra.getReceivingAddressIdentifier())) { 155 rai.setDefaultIndicator(false); 156 SpringContext.getBean(BusinessObjectService.class).save(rai); 157 } 158 } 159 } 160 } 161 162}