View Javadoc

1   /*
2    * Copyright 2007-2008 The Kuali Foundation
3    * 
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    * http://www.opensource.org/licenses/ecl2.php
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kns.lookup;
17  
18  import java.sql.Timestamp;
19  import java.util.ArrayList;
20  import java.util.Collection;
21  import java.util.HashMap;
22  import java.util.List;
23  import java.util.Map;
24  import java.util.Set;
25  
26  import org.apache.commons.codec.binary.Base64;
27  import org.kuali.rice.core.api.CoreApiServiceLocator;
28  import org.kuali.rice.kns.web.ui.ResultRow;
29  import org.kuali.rice.krad.bo.BusinessObject;
30  import org.kuali.rice.krad.bo.LookupResults;
31  import org.kuali.rice.krad.bo.MultipleValueLookupMetadata;
32  import org.kuali.rice.krad.bo.SelectedObjectIds;
33  import org.kuali.rice.krad.dao.PersistedLookupMetadataDao;
34  import org.kuali.rice.krad.exception.AuthorizationException;
35  import org.kuali.rice.krad.service.BusinessObjectService;
36  import org.kuali.rice.krad.util.KRADConstants;
37  import org.kuali.rice.krad.util.ObjectUtils;
38  
39  public class LookupResultsServiceImpl implements LookupResultsService {
40      private BusinessObjectService businessObjectService;
41      private PersistedLookupMetadataDao persistedLookupMetadataDao;
42      private LookupResultsSupportStrategyService persistableBusinessObjectSupportStrategy;
43      private LookupResultsSupportStrategyService dataDictionarySupportStrategy;
44      
45      /**
46       * @see org.kuali.rice.krad.lookup.LookupResultsService#persistResultsTable(java.lang.String, java.util.List, java.lang.String)
47       */
48      public void persistResultsTable(String lookupResultsSequenceNumber, List<ResultRow> resultTable, String personId) throws Exception {
49          String resultTableString = new String(Base64.encodeBase64(ObjectUtils.toByteArray(resultTable)));
50          
51          Timestamp now = CoreApiServiceLocator.getDateTimeService().getCurrentTimestamp();
52          
53          LookupResults lookupResults = retrieveLookupResults(lookupResultsSequenceNumber);
54          if (lookupResults == null) {
55              lookupResults = new LookupResults();
56              lookupResults.setLookupResultsSequenceNumber(lookupResultsSequenceNumber);
57          }
58          lookupResults.setLookupResultsSequenceNumber(lookupResultsSequenceNumber);
59          lookupResults.setLookupPersonId(personId);
60          lookupResults.setSerializedLookupResults(resultTableString);
61          lookupResults.setLookupDate(now);
62          businessObjectService.save(lookupResults);
63      }
64  
65      /**
66       * @see org.kuali.rice.krad.lookup.LookupResultsService#persistSelectedObjectIds(java.lang.String, java.util.Set, java.lang.String)
67       */
68      public void persistSelectedObjectIds(String lookupResultsSequenceNumber, Set<String> selectedObjectIds, String personId) throws Exception {
69          SelectedObjectIds selectedObjectIdsBO = retrieveSelectedObjectIds(lookupResultsSequenceNumber);
70          if (selectedObjectIdsBO == null) {
71              selectedObjectIdsBO = new SelectedObjectIds();
72              selectedObjectIdsBO.setLookupResultsSequenceNumber(lookupResultsSequenceNumber);
73          }
74          selectedObjectIdsBO.setLookupResultsSequenceNumber(lookupResultsSequenceNumber);
75          selectedObjectIdsBO.setLookupPersonId(personId);
76          selectedObjectIdsBO.setSelectedObjectIds(
77                  LookupUtils.convertSetOfObjectIdsToString(selectedObjectIds));
78          selectedObjectIdsBO.setLookupDate(CoreApiServiceLocator.getDateTimeService().getCurrentTimestamp());
79          businessObjectService.save(selectedObjectIdsBO);
80      }
81  
82      /**
83       * Retrieves the LookupResults BO with the given sequence number.  Does not check authentication.
84       * @param lookupResultsSequenceNumber
85       * @return
86       * @throws Exception
87       */
88      protected LookupResults retrieveLookupResults(String lookupResultsSequenceNumber) throws Exception {
89          Map<String, String> queryCriteria = new HashMap<String, String>();
90          queryCriteria.put(KRADConstants.LOOKUP_RESULTS_SEQUENCE_NUMBER, lookupResultsSequenceNumber);
91          LookupResults lookupResults = (LookupResults) businessObjectService.findByPrimaryKey(LookupResults.class, queryCriteria);
92          
93          return lookupResults;
94      }
95  
96      /**
97       * Retrieves the SelectedObjectIds BO with the given sequence number.  Does not check authentication.
98       * @param lookupResultsSequenceNumber
99       * @return
100      * @throws Exception
101      */
102     protected SelectedObjectIds retrieveSelectedObjectIds(String lookupResultsSequenceNumber) throws Exception {
103         Map<String, String> queryCriteria = new HashMap<String, String>();
104         queryCriteria.put(KRADConstants.LOOKUP_RESULTS_SEQUENCE_NUMBER, lookupResultsSequenceNumber);
105         SelectedObjectIds selectedObjectIds = (SelectedObjectIds) businessObjectService.findByPrimaryKey(SelectedObjectIds.class, queryCriteria);
106         
107         return selectedObjectIds;
108     }
109 
110     /**
111      * @see org.kuali.rice.krad.lookup.LookupResultsService#isAuthorizedToAccessLookupResults(java.lang.String, java.lang.String)
112      */
113     public boolean isAuthorizedToAccessLookupResults(String lookupResultsSequenceNumber, String personId) {
114         try {
115             LookupResults lookupResults = retrieveLookupResults(lookupResultsSequenceNumber);
116             return isAuthorizedToAccessLookupResults(lookupResults, personId);
117         }
118         catch (Exception e) {
119             return false;
120         }
121     }
122 
123     /**
124      * Returns whether the user ID parameter is allowed to view the results.
125      * 
126      * @param lookupResults
127      * @param personId
128      * @return
129      */
130     protected boolean isAuthorizedToAccessLookupResults(LookupResults lookupResults, String personId) {
131         return isAuthorizedToAccessMultipleValueLookupMetadata(lookupResults, personId);
132     }
133 
134     /**
135      * @see org.kuali.rice.krad.lookup.LookupResultsService#isAuthorizedToAccessSelectedObjectIds(java.lang.String, java.lang.String)
136      */
137     public boolean isAuthorizedToAccessSelectedObjectIds(String lookupResultsSequenceNumber, String personId) {
138         try {
139             SelectedObjectIds selectedObjectIds = retrieveSelectedObjectIds(lookupResultsSequenceNumber);
140             return isAuthorizedToAccessSelectedObjectIds(selectedObjectIds, personId);
141         }
142         catch (Exception e) {
143             return false;
144         }
145     }
146 
147     /**
148      * Returns whether the user ID parameter is allowed to view the selected object IDs
149      * 
150      * @param selectedObjectIds
151      * @param personId
152      * @return
153      */
154     protected boolean isAuthorizedToAccessSelectedObjectIds(SelectedObjectIds selectedObjectIds, String personId) {
155         return isAuthorizedToAccessMultipleValueLookupMetadata(selectedObjectIds, personId);
156     }
157     
158 
159     /**
160      * @see org.kuali.rice.krad.lookup.LookupResultsService#retrieveResultsTable(java.lang.String, java.lang.String)
161      */
162     public List<ResultRow> retrieveResultsTable(String lookupResultsSequenceNumber, String personId) throws Exception {
163         LookupResults lookupResults = retrieveLookupResults(lookupResultsSequenceNumber);
164         if (!isAuthorizedToAccessLookupResults(lookupResults, personId)) {
165             // TODO: use the other identifier
166             throw new AuthorizationException(personId, "retrieve lookup results", "lookup sequence number " + lookupResultsSequenceNumber);
167         }
168         List<ResultRow> resultTable = (List<ResultRow>) ObjectUtils.fromByteArray(Base64.decodeBase64(lookupResults.getSerializedLookupResults().getBytes()));
169         return resultTable;
170     }
171 
172     /**
173      * 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.
174      * 
175      * @see org.kuali.rice.krad.lookup.LookupResultsService#retrieveSelectedResultBOs(java.lang.String, java.lang.Class, java.lang.String)
176      */
177     public <T extends BusinessObject> Collection<T> retrieveSelectedResultBOs(String lookupResultsSequenceNumber, Class<T> boClass, String personId) throws Exception {
178     	final LookupResultsSupportStrategyService supportService = getQualifingSupportStrategy(boClass);
179     	if (supportService == null) {
180     		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");
181     	}
182     	
183     	SelectedObjectIds selectedObjectIds = retrieveSelectedObjectIds(lookupResultsSequenceNumber);
184         
185         if (!isAuthorizedToAccessSelectedObjectIds(selectedObjectIds, personId)) {
186             // TODO: use the other identifier
187             throw new AuthorizationException(personId, "retrieve lookup results", "lookup sequence number " + lookupResultsSequenceNumber);
188         }
189         
190         Set<String> setOfSelectedObjIds = LookupUtils
191                 .convertStringOfObjectIdsToSet(selectedObjectIds.getSelectedObjectIds());
192         
193         if (setOfSelectedObjIds.isEmpty()) {
194             // OJB throws exception if querying on empty set
195             return new ArrayList<T>();
196         }
197     	
198     	return supportService.retrieveSelectedResultBOs(boClass, setOfSelectedObjIds);
199     }
200     
201     /**
202      * Given the business object class, determines the best qualifying LookupResultsSupportStrategyService to use
203      * 
204      * @param boClass a business object class
205      * @return an LookupResultsSupportStrategyService implementation, or null if no qualifying strategies could be found
206      */
207     protected LookupResultsSupportStrategyService getQualifingSupportStrategy(Class boClass) {
208     	if (getPersistableBusinessObjectSupportStrategy().qualifiesForStrategy(boClass)) {
209     		return getPersistableBusinessObjectSupportStrategy();
210     	} else if (getDataDictionarySupportStrategy().qualifiesForStrategy(boClass)) {
211     		return getDataDictionarySupportStrategy();
212     	}
213     	return null;
214     }
215     
216     /**
217      * @see org.kuali.rice.krad.lookup.LookupResultsService#clearPersistedLookupResults(java.lang.String)
218      */
219     public void clearPersistedLookupResults(String lookupResultsSequenceNumber) throws Exception {
220         LookupResults lookupResults = retrieveLookupResults(lookupResultsSequenceNumber);
221         if (lookupResults != null) {
222             businessObjectService.delete(lookupResults);
223         }
224     }
225     
226     /**
227      * @see org.kuali.rice.krad.lookup.LookupResultsService#clearPersistedSelectedObjectIds(java.lang.String)
228      */
229     public void clearPersistedSelectedObjectIds(String lookupResultsSequenceNumber) throws Exception {
230         SelectedObjectIds selectedObjectIds = retrieveSelectedObjectIds(lookupResultsSequenceNumber);
231         if (selectedObjectIds != null) {
232             businessObjectService.delete(selectedObjectIds);
233         }
234     }
235     
236     /**
237 	 * Figures out which LookupResultsServiceSupportStrategy to defer to, and uses that to get the lookup id
238 	 * @see org.kuali.rice.krad.lookup.LookupResultsService#getLookupId(org.kuali.rice.krad.bo.BusinessObject)
239 	 */
240 	public String getLookupId(BusinessObject businessObject) {
241 		final LookupResultsSupportStrategyService supportService = getQualifingSupportStrategy(businessObject.getClass());
242 		if (supportService == null) {
243 			return null; // this may happen quite often, so let's just return null - no exception here
244 		}
245 		return supportService.getLookupIdForBusinessObject(businessObject);
246 	}
247 
248 	public BusinessObjectService getBusinessObjectService() {
249         return businessObjectService;
250     }
251 
252     public void setBusinessObjectService(BusinessObjectService businessObjectService) {
253         this.businessObjectService = businessObjectService;
254     }
255     
256     /**
257      * Determines whether the passed in user ID is allowed to view the lookup metadata (object IDs or results table)
258      * @param mvlm
259      * @param personId
260      * @return
261      */
262     protected boolean isAuthorizedToAccessMultipleValueLookupMetadata(MultipleValueLookupMetadata mvlm, String personId) {
263         return personId.equals(mvlm.getLookupPersonId());
264     }
265 
266     
267     public void deleteOldLookupResults(Timestamp expirationDate) {
268         persistedLookupMetadataDao.deleteOldLookupResults(expirationDate);
269         
270     }
271 
272     public void deleteOldSelectedObjectIds(Timestamp expirationDate) {
273         persistedLookupMetadataDao.deleteOldSelectedObjectIds(expirationDate);
274     }
275 
276     public PersistedLookupMetadataDao getPersistedLookupMetadataDao() {
277         return persistedLookupMetadataDao;
278     }
279 
280     public void setPersistedLookupMetadataDao(PersistedLookupMetadataDao persistedLookupMetadataDao) {
281         this.persistedLookupMetadataDao = persistedLookupMetadataDao;
282     }
283 
284 	/**
285 	 * @return the persistableBusinessObjectSupportStrategy
286 	 */
287 	public LookupResultsSupportStrategyService getPersistableBusinessObjectSupportStrategy() {
288 		return this.persistableBusinessObjectSupportStrategy;
289 	}
290 
291 	/**
292 	 * @return the dataDictionarySupportStrategy
293 	 */
294 	public LookupResultsSupportStrategyService getDataDictionarySupportStrategy() {
295 		return this.dataDictionarySupportStrategy;
296 	}
297 
298 	/**
299 	 * @param persistableBusinessObjectSupportStrategy the persistableBusinessObjectSupportStrategy to set
300 	 */
301 	public void setPersistableBusinessObjectSupportStrategy(
302 			LookupResultsSupportStrategyService persistableBusinessObjectSupportStrategy) {
303 		this.persistableBusinessObjectSupportStrategy = persistableBusinessObjectSupportStrategy;
304 	}
305 
306 	/**
307 	 * @param dataDictionarySupportStrategy the dataDictionarySupportStrategy to set
308 	 */
309 	public void setDataDictionarySupportStrategy(
310 			LookupResultsSupportStrategyService dataDictionarySupportStrategy) {
311 		this.dataDictionarySupportStrategy = dataDictionarySupportStrategy;
312 	}
313     
314 }
315