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.bc.businessobject.lookup; 017 018 import java.util.ArrayList; 019 import java.util.List; 020 import java.util.Map; 021 022 import org.apache.commons.lang.StringUtils; 023 import org.kuali.kfs.module.bc.BCConstants; 024 import org.kuali.kfs.module.bc.BCKeyConstants; 025 import org.kuali.kfs.module.bc.BCPropertyConstants; 026 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionFundingLock; 027 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionHeader; 028 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionLockSummary; 029 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionPosition; 030 import org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding; 031 import org.kuali.kfs.module.bc.document.service.LockService; 032 import org.kuali.kfs.sys.KFSConstants; 033 import org.kuali.kfs.sys.context.SpringContext; 034 import org.kuali.rice.kim.bo.Person; 035 import org.kuali.rice.kim.service.PersonService; 036 import org.kuali.rice.kns.authorization.BusinessObjectRestrictions; 037 import org.kuali.rice.kns.bo.BusinessObject; 038 import org.kuali.rice.kns.lookup.CollectionIncomplete; 039 import org.kuali.rice.kns.lookup.HtmlData; 040 import org.kuali.rice.kns.lookup.KualiLookupableHelperServiceImpl; 041 import org.kuali.rice.kns.lookup.HtmlData.AnchorHtmlData; 042 import org.kuali.rice.kns.lookup.HtmlData.InputHtmlData; 043 import org.kuali.rice.kns.service.KualiConfigurationService; 044 import org.kuali.rice.kns.util.GlobalVariables; 045 import org.kuali.rice.kns.util.KNSConstants; 046 import org.kuali.rice.kns.web.struts.form.LookupForm; 047 048 /** 049 * Implements custom search routine to find the current budget locks and build up the result List. Set an unlock URL for each lock. 050 */ 051 public class LockMonitorLookupableHelperServiceImpl extends KualiLookupableHelperServiceImpl { 052 private KualiConfigurationService kualiConfigurationService; 053 private PersonService<Person> personService; 054 055 /** 056 * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#getSearchResults(java.util.Map) 057 */ 058 @Override 059 public List<? extends BusinessObject> getSearchResults(Map<String, String> fieldValues) { 060 setBackLocation(fieldValues.get(KFSConstants.BACK_LOCATION)); 061 setDocFormKey(fieldValues.get(KFSConstants.DOC_FORM_KEY)); 062 setReferencesToRefresh(fieldValues.get(KFSConstants.REFERENCES_TO_REFRESH)); 063 064 List<BudgetConstructionLockSummary> results = new ArrayList<BudgetConstructionLockSummary>(); 065 066 // get universal identifier from network id 067 String lockUserID = fieldValues.get(BCPropertyConstants.LOCK_USER_ID); 068 String lockUnivId = getUniversalIdFromNetworkID(lockUserID); 069 070 getAccountLocks(results, lockUnivId); 071 getTransactionLocks(results, lockUnivId); 072 getOrphanFundingLocks(results, lockUnivId); 073 getPositionFundingLocks(results, lockUnivId); 074 getOrphanPositionLocks(results, lockUnivId); 075 076 return new CollectionIncomplete(results, new Long(0)); 077 } 078 079 /** 080 * Calls lock service to retrieve all current account locks and builds a lock summary object for each returned lock. 081 * 082 * @param results - result list to add lock summaries 083 */ 084 protected void getAccountLocks(List<BudgetConstructionLockSummary> results, String lockUnivId) { 085 List<BudgetConstructionHeader> accountLocks = SpringContext.getBean(LockService.class).getAllAccountLocks(lockUnivId); 086 for (BudgetConstructionHeader header : accountLocks) { 087 BudgetConstructionLockSummary lockSummary = new BudgetConstructionLockSummary(); 088 lockSummary.setLockType(BCConstants.LockTypes.ACCOUNT_LOCK); 089 lockSummary.setLockUserId(header.getBudgetLockUser().getPrincipalName()); 090 091 lockSummary.setDocumentNumber(header.getDocumentNumber()); 092 lockSummary.setUniversityFiscalYear(header.getUniversityFiscalYear()); 093 lockSummary.setChartOfAccountsCode(header.getChartOfAccountsCode()); 094 lockSummary.setAccountNumber(header.getAccountNumber()); 095 lockSummary.setSubAccountNumber(header.getSubAccountNumber()); 096 097 results.add(lockSummary); 098 } 099 } 100 101 /** 102 * Calls lock service to retrieve all current transaction locks and builds a lock summary object for each returned lock. 103 * 104 * @param results - result list to add lock summaries 105 */ 106 protected void getTransactionLocks(List<BudgetConstructionLockSummary> results, String lockUnivId) { 107 List<BudgetConstructionHeader> transLocks = SpringContext.getBean(LockService.class).getAllTransactionLocks(lockUnivId); 108 for (BudgetConstructionHeader header : transLocks) { 109 BudgetConstructionLockSummary lockSummary = new BudgetConstructionLockSummary(); 110 lockSummary.setLockType(BCConstants.LockTypes.TRANSACTION_LOCK); 111 lockSummary.setLockUserId(header.getBudgetTransactionLockUser().getPrincipalName()); 112 113 lockSummary.setDocumentNumber(header.getDocumentNumber()); 114 lockSummary.setUniversityFiscalYear(header.getUniversityFiscalYear()); 115 lockSummary.setChartOfAccountsCode(header.getChartOfAccountsCode()); 116 lockSummary.setAccountNumber(header.getAccountNumber()); 117 lockSummary.setSubAccountNumber(header.getSubAccountNumber()); 118 119 results.add(lockSummary); 120 } 121 } 122 123 /** 124 * Calls lock service to retrieve all funding locks that do not have a corresponding position locks and builds a lock summary 125 * object for each returned lock. 126 * 127 * @param results - result list to add lock summaries 128 */ 129 protected void getOrphanFundingLocks(List<BudgetConstructionLockSummary> results, String lockUnivId) { 130 List<BudgetConstructionFundingLock> fundingLocks = SpringContext.getBean(LockService.class).getOrphanedFundingLocks(lockUnivId); 131 for (BudgetConstructionFundingLock fundingLock : fundingLocks) { 132 BudgetConstructionLockSummary lockSummary = new BudgetConstructionLockSummary(); 133 lockSummary.setLockType(BCConstants.LockTypes.FUNDING_LOCK); 134 lockSummary.setLockUserId(fundingLock.getAppointmentFundingLockUser().getPrincipalName()); 135 136 lockSummary.setUniversityFiscalYear(fundingLock.getUniversityFiscalYear()); 137 lockSummary.setChartOfAccountsCode(fundingLock.getChartOfAccountsCode()); 138 lockSummary.setAccountNumber(fundingLock.getAccountNumber()); 139 lockSummary.setSubAccountNumber(fundingLock.getSubAccountNumber()); 140 141 results.add(lockSummary); 142 } 143 } 144 145 /** 146 * Calls lock service to retrieve all current position/funding locks and builds a lock summary object for each returned lock. 147 * 148 * @param results - result list to add lock summaries 149 */ 150 protected void getPositionFundingLocks(List<BudgetConstructionLockSummary> results, String lockUnivId) { 151 List<PendingBudgetConstructionAppointmentFunding> positionFundingLocks = SpringContext.getBean(LockService.class).getAllPositionFundingLocks(lockUnivId); 152 for (PendingBudgetConstructionAppointmentFunding appointmentFunding : positionFundingLocks) { 153 BudgetConstructionLockSummary lockSummary = new BudgetConstructionLockSummary(); 154 lockSummary.setLockType(BCConstants.LockTypes.POSITION_FUNDING_LOCK); 155 lockSummary.setLockUserId(appointmentFunding.getBudgetConstructionPosition().getPositionLockUser().getPrincipalName()); 156 157 lockSummary.setUniversityFiscalYear(appointmentFunding.getUniversityFiscalYear()); 158 lockSummary.setChartOfAccountsCode(appointmentFunding.getChartOfAccountsCode()); 159 lockSummary.setAccountNumber(appointmentFunding.getAccountNumber()); 160 lockSummary.setSubAccountNumber(appointmentFunding.getSubAccountNumber()); 161 162 lockSummary.setPositionNumber(appointmentFunding.getBudgetConstructionPosition().getPositionNumber()); 163 lockSummary.setPositionDescription(appointmentFunding.getBudgetConstructionPosition().getPositionDescription()); 164 165 results.add(lockSummary); 166 } 167 } 168 169 /** 170 * Calls lock service to retrieve all current position locks without a corresponding funding lock and builds a lock summary 171 * object for each returned lock. 172 * 173 * @param results - result list to add lock summaries 174 */ 175 protected void getOrphanPositionLocks(List<BudgetConstructionLockSummary> results, String lockUnivId) { 176 List<BudgetConstructionPosition> positionLocks = SpringContext.getBean(LockService.class).getOrphanedPositionLocks(lockUnivId); 177 for (BudgetConstructionPosition position : positionLocks) { 178 BudgetConstructionLockSummary lockSummary = new BudgetConstructionLockSummary(); 179 lockSummary.setLockType(BCConstants.LockTypes.POSITION_LOCK); 180 lockSummary.setLockUserId(position.getPositionLockUser().getPrincipalName()); 181 182 lockSummary.setUniversityFiscalYear(position.getUniversityFiscalYear()); 183 lockSummary.setPositionNumber(position.getPositionNumber()); 184 lockSummary.setPositionDescription(position.getPositionDescription()); 185 186 results.add(lockSummary); 187 } 188 } 189 190 /** 191 * Builds unlink action for each type of lock. 192 * 193 * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#getCustomActionUrls(org.kuali.rice.kns.bo.BusinessObject, java.util.List) 194 */ 195 @Override 196 public List<HtmlData> getCustomActionUrls(BusinessObject businessObject, List pkNames) { 197 BudgetConstructionLockSummary lockSummary = (BudgetConstructionLockSummary) businessObject; 198 199 String imageDirectory = kualiConfigurationService.getPropertyString(KFSConstants.EXTERNALIZABLE_IMAGES_URL_KEY); 200 String lockFields = lockSummary.getUniversityFiscalYear() + BCConstants.LOCK_STRING_DELIMITER + lockSummary.getChartOfAccountsCode() + BCConstants.LOCK_STRING_DELIMITER + lockSummary.getAccountNumber() + BCConstants.LOCK_STRING_DELIMITER + lockSummary.getSubAccountNumber() + BCConstants.LOCK_STRING_DELIMITER + lockSummary.getPositionNumber() + BCConstants.LOCK_STRING_DELIMITER; 201 lockFields = StringUtils.replace(lockFields, "null", ""); 202 203 String name = KFSConstants.DISPATCH_REQUEST_PARAMETER + "." + BCConstants.TEMP_LIST_UNLOCK_METHOD + "."; 204 name += 205 KFSConstants.METHOD_TO_CALL_PARM1_LEFT_DEL + StringUtils.replace(lockSummary.getLockType()," ","_") + 206 KFSConstants.METHOD_TO_CALL_PARM1_RIGHT_DEL; 207 name += KFSConstants.METHOD_TO_CALL_PARM9_LEFT_DEL + lockFields + KFSConstants.METHOD_TO_CALL_PARM9_RIGHT_DEL; 208 name += 209 KFSConstants.METHOD_TO_CALL_PARM3_LEFT_DEL + lockSummary.getLockUserId() + 210 KFSConstants.METHOD_TO_CALL_PARM3_RIGHT_DEL; 211 String src = imageDirectory + BCConstants.UNLOCK_BUTTON_NAME; 212 String inputType = "image"; 213 String styleClass = "tinybutton"; 214 String border= "0"; 215 216 List<HtmlData> htmlDataList = new ArrayList<HtmlData>(); 217 InputHtmlData inputHtmlData = new InputHtmlData(name, inputType, src); 218 inputHtmlData.setStyleClass(styleClass); 219 inputHtmlData.setBorder(border); 220 htmlDataList.add(inputHtmlData); 221 return htmlDataList; 222 } 223 224 /** 225 * Uses org.kuali.rice.kim.service.PersonService to retrieve user object associated with the given network id (if not blank) and then 226 * returns universal id. Add error to GlobalVariables if the user was not found. 227 * 228 * @param networkID - network id for the user to find 229 * @return universal id for the user or null if not found or the network id was blank 230 */ 231 protected String getUniversalIdFromNetworkID(String networkID) { 232 String universalId = null; 233 if (StringUtils.isNotBlank(networkID)) { 234 Person user = getPersonService().getPersonByPrincipalName(networkID); 235 if (user != null) { 236 universalId = user.getPrincipalId(); 237 } else { 238 GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, BCKeyConstants.ERROR_LOCK_INVALID_USER, networkID); 239 } 240 } 241 242 return universalId; 243 } 244 245 /** 246 * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#getReturnUrl(org.kuali.rice.kns.bo.BusinessObject, java.util.Map, java.lang.String) 247 */ 248 @Override 249 public HtmlData getReturnUrl(BusinessObject businessObject, LookupForm lookupForm, List pkNames, BusinessObjectRestrictions businessObjectRestrictions) { 250 return getEmptyAnchorHtmlData(); 251 } 252 253 /** 254 * Overridden to prevent a validation exception from thrown when the search method is called to refresh the 255 * results after an error is encountered. 256 * 257 * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#validateSearchParameters(java.util.Map) 258 */ 259 @Override 260 public void validateSearchParameters(Map fieldValues) { 261 } 262 263 /** 264 * Since this lookupable is called by the budget lookup action, the context will be KFS, not Rice. So the generated inquiries 265 * will not have the Rice context (kr/) and be invalid. This override adds the Rice context to the inquiry Url to working 266 * around the issue. 267 * 268 * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#getInquiryUrl(org.kuali.rice.kns.bo.BusinessObject, 269 * java.lang.String) 270 */ 271 @Override 272 public HtmlData getInquiryUrl(BusinessObject bo, String propertyName) { 273 AnchorHtmlData inquiryUrl = (AnchorHtmlData)super.getInquiryUrl(bo, propertyName); 274 inquiryUrl.setHref(StringUtils.replace(inquiryUrl.getHref(), KNSConstants.INQUIRY_ACTION, KFSConstants.INQUIRY_ACTION)); 275 276 return inquiryUrl; 277 } 278 279 /** 280 * Sets the kualiConfigurationService attribute value. 281 * 282 * @param kualiConfigurationService The kualiConfigurationService to set. 283 */ 284 public void setKualiConfigurationService(KualiConfigurationService kualiConfigurationService) { 285 this.kualiConfigurationService = kualiConfigurationService; 286 } 287 288 /** 289 * @return Returns the personService. 290 */ 291 protected PersonService<Person> getPersonService() { 292 if(personService==null) 293 personService = SpringContext.getBean(PersonService.class); 294 return personService; 295 } 296 297 }