001/** 002 * Copyright 2005-2015 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.rice.kns.lookup; 017 018import java.sql.Timestamp; 019import java.util.ArrayList; 020import java.util.Collection; 021import java.util.HashMap; 022import java.util.List; 023import java.util.Map; 024import java.util.Set; 025 026import org.apache.commons.codec.binary.Base64; 027import org.kuali.rice.core.api.CoreApiServiceLocator; 028import org.kuali.rice.kns.web.ui.ResultRow; 029import org.kuali.rice.krad.bo.BusinessObject; 030import org.kuali.rice.krad.dao.PersistedLookupMetadataDao; 031import org.kuali.rice.krad.exception.AuthorizationException; 032import org.kuali.rice.krad.service.BusinessObjectService; 033import org.kuali.rice.krad.util.KRADConstants; 034import org.kuali.rice.krad.util.ObjectUtils; 035 036/** 037 * @deprecated Only used by KNS classes, use KRAD. 038 */ 039@Deprecated 040public class LookupResultsServiceImpl implements LookupResultsService { 041 private BusinessObjectService businessObjectService; 042 private PersistedLookupMetadataDao persistedLookupMetadataDao; 043 private LookupResultsSupportStrategyService persistableBusinessObjectSupportStrategy; 044 private LookupResultsSupportStrategyService dataDictionarySupportStrategy; 045 private LookupResultsSupportStrategyService dataObjectBaseSupportStrategy; 046 047 public LookupResultsServiceImpl() { 048 dataObjectBaseSupportStrategy = new DataObjectBaseLookupResultsSupportStrategyImpl(); 049 } 050 051 /** 052 * @see org.kuali.rice.krad.lookup.LookupResultsService#persistResultsTable(java.lang.String, java.util.List, java.lang.String) 053 */ 054 @Override 055 public void persistResultsTable(String lookupResultsSequenceNumber, List<ResultRow> resultTable, String personId) throws Exception { 056 String resultTableString = new String(Base64.encodeBase64(ObjectUtils.toByteArray(resultTable))); 057 058 Timestamp now = CoreApiServiceLocator.getDateTimeService().getCurrentTimestamp(); 059 060 LookupResults lookupResults = retrieveLookupResults(lookupResultsSequenceNumber); 061 if (lookupResults == null) { 062 lookupResults = new LookupResults(); 063 lookupResults.setLookupResultsSequenceNumber(lookupResultsSequenceNumber); 064 } 065 lookupResults.setLookupResultsSequenceNumber(lookupResultsSequenceNumber); 066 lookupResults.setLookupPersonId(personId); 067 lookupResults.setSerializedLookupResults(resultTableString); 068 lookupResults.setLookupDate(now); 069 businessObjectService.save(lookupResults); 070 } 071 072 /** 073 * @see org.kuali.rice.krad.lookup.LookupResultsService#persistSelectedObjectIds(java.lang.String, java.util.Set, java.lang.String) 074 */ 075 @Override 076 public void persistSelectedObjectIds(String lookupResultsSequenceNumber, Set<String> selectedObjectIds, String personId) throws Exception { 077 SelectedObjectIds selectedObjectIdsBO = retrieveSelectedObjectIds(lookupResultsSequenceNumber); 078 if (selectedObjectIdsBO == null) { 079 selectedObjectIdsBO = new SelectedObjectIds(); 080 selectedObjectIdsBO.setLookupResultsSequenceNumber(lookupResultsSequenceNumber); 081 } 082 selectedObjectIdsBO.setLookupResultsSequenceNumber(lookupResultsSequenceNumber); 083 selectedObjectIdsBO.setLookupPersonId(personId); 084 selectedObjectIdsBO.setSelectedObjectIds( 085 LookupUtils.convertSetOfObjectIdsToString(selectedObjectIds)); 086 selectedObjectIdsBO.setLookupDate(CoreApiServiceLocator.getDateTimeService().getCurrentTimestamp()); 087 businessObjectService.save(selectedObjectIdsBO); 088 } 089 090 /** 091 * Retrieves the LookupResults BO with the given sequence number. Does not check authentication. 092 * @param lookupResultsSequenceNumber 093 * @return 094 * @throws Exception 095 */ 096 protected LookupResults retrieveLookupResults(String lookupResultsSequenceNumber) throws Exception { 097 Map<String, String> queryCriteria = new HashMap<String, String>(); 098 queryCriteria.put(KRADConstants.LOOKUP_RESULTS_SEQUENCE_NUMBER, lookupResultsSequenceNumber); 099 LookupResults lookupResults = businessObjectService.findByPrimaryKey(LookupResults.class, queryCriteria); 100 101 return lookupResults; 102 } 103 104 /** 105 * Retrieves the SelectedObjectIds BO with the given sequence number. Does not check authentication. 106 * @param lookupResultsSequenceNumber 107 * @return 108 * @throws Exception 109 */ 110 protected SelectedObjectIds retrieveSelectedObjectIds(String lookupResultsSequenceNumber) throws Exception { 111 Map<String, String> queryCriteria = new HashMap<String, String>(); 112 queryCriteria.put(KRADConstants.LOOKUP_RESULTS_SEQUENCE_NUMBER, lookupResultsSequenceNumber); 113 SelectedObjectIds selectedObjectIds = businessObjectService.findByPrimaryKey(SelectedObjectIds.class, queryCriteria); 114 115 return selectedObjectIds; 116 } 117 118 /** 119 * @see org.kuali.rice.krad.lookup.LookupResultsService#isAuthorizedToAccessLookupResults(java.lang.String, java.lang.String) 120 */ 121 @Override 122 public boolean isAuthorizedToAccessLookupResults(String lookupResultsSequenceNumber, String personId) { 123 try { 124 LookupResults lookupResults = retrieveLookupResults(lookupResultsSequenceNumber); 125 return isAuthorizedToAccessLookupResults(lookupResults, personId); 126 } 127 catch (Exception e) { 128 return false; 129 } 130 } 131 132 /** 133 * Returns whether the user ID parameter is allowed to view the results. 134 * 135 * @param lookupResults 136 * @param personId 137 * @return 138 */ 139 protected boolean isAuthorizedToAccessLookupResults(LookupResults lookupResults, String personId) { 140 return isAuthorizedToAccessMultipleValueLookupMetadata(lookupResults, personId); 141 } 142 143 /** 144 * @see org.kuali.rice.krad.lookup.LookupResultsService#isAuthorizedToAccessSelectedObjectIds(java.lang.String, java.lang.String) 145 */ 146 @Override 147 public boolean isAuthorizedToAccessSelectedObjectIds(String lookupResultsSequenceNumber, String personId) { 148 try { 149 SelectedObjectIds selectedObjectIds = retrieveSelectedObjectIds(lookupResultsSequenceNumber); 150 return isAuthorizedToAccessSelectedObjectIds(selectedObjectIds, personId); 151 } 152 catch (Exception e) { 153 return false; 154 } 155 } 156 157 /** 158 * Returns whether the user ID parameter is allowed to view the selected object IDs 159 * 160 * @param selectedObjectIds 161 * @param personId 162 * @return 163 */ 164 protected boolean isAuthorizedToAccessSelectedObjectIds(SelectedObjectIds selectedObjectIds, String personId) { 165 return isAuthorizedToAccessMultipleValueLookupMetadata(selectedObjectIds, personId); 166 } 167 168 169 /** 170 * @see org.kuali.rice.krad.lookup.LookupResultsService#retrieveResultsTable(java.lang.String, java.lang.String) 171 */ 172 @Override 173 public List<ResultRow> retrieveResultsTable(String lookupResultsSequenceNumber, String personId) throws Exception { 174 LookupResults lookupResults = retrieveLookupResults(lookupResultsSequenceNumber); 175 if (!isAuthorizedToAccessLookupResults(lookupResults, personId)) { 176 // TODO: use the other identifier 177 throw new AuthorizationException(personId, "retrieve lookup results", "lookup sequence number " + lookupResultsSequenceNumber); 178 } 179 List<ResultRow> resultTable = (List<ResultRow>) ObjectUtils.fromByteArray(Base64.decodeBase64(lookupResults.getSerializedLookupResults().getBytes())); 180 return resultTable; 181 } 182 183 /** 184 * Figures out which support strategy to defer to and uses that service to retrieve the results; if the bo class doesn't qualify with any support strategy, an exception is thrown. A nasty one, too. 185 * 186 * @see org.kuali.rice.krad.lookup.LookupResultsService#retrieveSelectedResultBOs(java.lang.String, java.lang.Class, java.lang.String) 187 */ 188 @Override 189 public <T extends BusinessObject> Collection<T> retrieveSelectedResultBOs(String lookupResultsSequenceNumber, Class<T> boClass, String personId) throws Exception { 190 final LookupResultsSupportStrategyService supportService = getQualifingSupportStrategy(boClass); 191 if (supportService == null) { 192 throw new RuntimeException("BusinessObject class "+boClass.getName()+" cannot be used within a multiple value lookup; it either needs to be a PersistableBusinessObject or have both its primary keys and a lookupable defined in its data dictionary entry"); 193 } 194 195 SelectedObjectIds selectedObjectIds = retrieveSelectedObjectIds(lookupResultsSequenceNumber); 196 197 if (!isAuthorizedToAccessSelectedObjectIds(selectedObjectIds, personId)) { 198 // TODO: use the other identifier 199 throw new AuthorizationException(personId, "retrieve lookup results", "lookup sequence number " + lookupResultsSequenceNumber); 200 } 201 202 Set<String> setOfSelectedObjIds = LookupUtils 203 .convertStringOfObjectIdsToSet(selectedObjectIds.getSelectedObjectIds()); 204 205 if (setOfSelectedObjIds.isEmpty()) { 206 // OJB throws exception if querying on empty set 207 return new ArrayList<T>(); 208 } 209 210 return supportService.retrieveSelectedResultBOs(boClass, setOfSelectedObjIds); 211 } 212 213 /** 214 * Given the business object class, determines the best qualifying LookupResultsSupportStrategyService to use 215 * 216 * @param boClass a business object class 217 * @return an LookupResultsSupportStrategyService implementation, or null if no qualifying strategies could be found 218 */ 219 protected LookupResultsSupportStrategyService getQualifingSupportStrategy(Class boClass) { 220 if (getPersistableBusinessObjectSupportStrategy().qualifiesForStrategy(boClass)) { 221 return getPersistableBusinessObjectSupportStrategy(); 222 } else if ( dataObjectBaseSupportStrategy.qualifiesForStrategy(boClass) ) { 223 return dataObjectBaseSupportStrategy; 224 } else if (getDataDictionarySupportStrategy().qualifiesForStrategy(boClass)) { 225 return getDataDictionarySupportStrategy(); 226 } 227 return null; 228 } 229 230 /** 231 * @see org.kuali.rice.krad.lookup.LookupResultsService#clearPersistedLookupResults(java.lang.String) 232 */ 233 @Override 234 public void clearPersistedLookupResults(String lookupResultsSequenceNumber) throws Exception { 235 LookupResults lookupResults = retrieveLookupResults(lookupResultsSequenceNumber); 236 if (lookupResults != null) { 237 businessObjectService.delete(lookupResults); 238 } 239 } 240 241 /** 242 * @see org.kuali.rice.krad.lookup.LookupResultsService#clearPersistedSelectedObjectIds(java.lang.String) 243 */ 244 @Override 245 public void clearPersistedSelectedObjectIds(String lookupResultsSequenceNumber) throws Exception { 246 SelectedObjectIds selectedObjectIds = retrieveSelectedObjectIds(lookupResultsSequenceNumber); 247 if (selectedObjectIds != null) { 248 businessObjectService.delete(selectedObjectIds); 249 } 250 } 251 252 /** 253 * Figures out which LookupResultsServiceSupportStrategy to defer to, and uses that to get the lookup id 254 * @see org.kuali.rice.krad.lookup.LookupResultsService#getLookupId(org.kuali.rice.krad.bo.BusinessObject) 255 */ 256 @Override 257 public String getLookupId(BusinessObject businessObject) { 258 final LookupResultsSupportStrategyService supportService = getQualifingSupportStrategy(businessObject.getClass()); 259 if (supportService == null) { 260 return null; // this may happen quite often, so let's just return null - no exception here 261 } 262 return supportService.getLookupIdForBusinessObject(businessObject); 263 } 264 265 public BusinessObjectService getBusinessObjectService() { 266 return businessObjectService; 267 } 268 269 public void setBusinessObjectService(BusinessObjectService businessObjectService) { 270 this.businessObjectService = businessObjectService; 271 } 272 273 /** 274 * Determines whether the passed in user ID is allowed to view the lookup metadata (object IDs or results table) 275 * @param mvlm 276 * @param personId 277 * @return 278 */ 279 protected boolean isAuthorizedToAccessMultipleValueLookupMetadata(MultipleValueLookupMetadata mvlm, String personId) { 280 return personId.equals(mvlm.getLookupPersonId()); 281 } 282 283 284 @Override 285 public void deleteOldLookupResults(Timestamp expirationDate) { 286 persistedLookupMetadataDao.deleteOldLookupResults(expirationDate); 287 288 } 289 290 @Override 291 public void deleteOldSelectedObjectIds(Timestamp expirationDate) { 292 persistedLookupMetadataDao.deleteOldSelectedObjectIds(expirationDate); 293 } 294 295 public PersistedLookupMetadataDao getPersistedLookupMetadataDao() { 296 return persistedLookupMetadataDao; 297 } 298 299 public void setPersistedLookupMetadataDao(PersistedLookupMetadataDao persistedLookupMetadataDao) { 300 this.persistedLookupMetadataDao = persistedLookupMetadataDao; 301 } 302 303 /** 304 * @return the persistableBusinessObjectSupportStrategy 305 */ 306 public LookupResultsSupportStrategyService getPersistableBusinessObjectSupportStrategy() { 307 return this.persistableBusinessObjectSupportStrategy; 308 } 309 310 /** 311 * @return the dataDictionarySupportStrategy 312 */ 313 public LookupResultsSupportStrategyService getDataDictionarySupportStrategy() { 314 return this.dataDictionarySupportStrategy; 315 } 316 317 /** 318 * @param persistableBusinessObjectSupportStrategy the persistableBusinessObjectSupportStrategy to set 319 */ 320 public void setPersistableBusinessObjectSupportStrategy( 321 LookupResultsSupportStrategyService persistableBusinessObjectSupportStrategy) { 322 this.persistableBusinessObjectSupportStrategy = persistableBusinessObjectSupportStrategy; 323 } 324 325 /** 326 * @param dataDictionarySupportStrategy the dataDictionarySupportStrategy to set 327 */ 328 public void setDataDictionarySupportStrategy( 329 LookupResultsSupportStrategyService dataDictionarySupportStrategy) { 330 this.dataDictionarySupportStrategy = dataDictionarySupportStrategy; 331 } 332 333} 334