1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  package org.kuali.rice.kns.lookup;
17  
18  import org.apache.commons.beanutils.PropertyUtils;
19  import org.apache.commons.lang.StringUtils;
20  import org.kuali.rice.core.api.CoreApiServiceLocator;
21  import org.kuali.rice.core.api.encryption.EncryptionService;
22  import org.kuali.rice.core.api.search.SearchOperator;
23  import org.kuali.rice.krad.bo.BusinessObject;
24  import org.kuali.rice.krad.bo.ExternalizableBusinessObject;
25  import org.kuali.rice.krad.datadictionary.BusinessObjectEntry;
26  import org.kuali.rice.krad.datadictionary.RelationshipDefinition;
27  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
28  import org.kuali.rice.krad.service.ModuleService;
29  import org.kuali.rice.krad.util.BeanPropertyComparator;
30  import org.kuali.rice.krad.util.ExternalizableBusinessObjectUtils;
31  import org.kuali.rice.krad.util.KRADConstants;
32  import org.kuali.rice.krad.util.ObjectUtils;
33  import org.springframework.transaction.annotation.Transactional;
34  
35  import java.security.GeneralSecurityException;
36  import java.util.ArrayList;
37  import java.util.Collections;
38  import java.util.HashMap;
39  import java.util.HashSet;
40  import java.util.Iterator;
41  import java.util.List;
42  import java.util.Map;
43  import java.util.Set;
44  
45  
46  
47  
48  @Deprecated
49  @Transactional
50  public class KualiLookupableHelperServiceImpl extends AbstractLookupableHelperServiceImpl {
51  
52      protected static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KualiLookupableHelperServiceImpl.class);
53      protected boolean searchUsingOnlyPrimaryKeyValues = false;
54  
55  
56      
57  
58  
59  
60  
61  
62  
63  
64      public List<? extends BusinessObject> getSearchResults(Map<String, String> fieldValues) {
65          return getSearchResultsHelper(
66                  org.kuali.rice.krad.lookup.LookupUtils.forceUppercase(getBusinessObjectClass(), fieldValues), false);
67      }
68  
69  
70      
71  
72  
73  
74  
75  
76  
77  
78      public List<? extends BusinessObject> getSearchResultsUnbounded(Map<String, String> fieldValues) {
79          return getSearchResultsHelper(
80                  org.kuali.rice.krad.lookup.LookupUtils.forceUppercase(getBusinessObjectClass(), fieldValues), true);
81      }
82  
83      
84  
85      
86  
87  
88  
89  
90      protected boolean isExternalBusinessObjectProperty(Object sampleBo, String propertyName) {
91          try {
92          	if ( propertyName.indexOf( "." ) > 0 && !StringUtils.contains( propertyName, "add." ) ) {
93  	        	Class propertyClass = PropertyUtils.getPropertyType(
94  						sampleBo, StringUtils.substringBeforeLast( propertyName, "." ) );
95  	        	if ( propertyClass != null ) {
96  	        		return ExternalizableBusinessObjectUtils.isExternalizableBusinessObjectInterface( propertyClass );
97  	        	} else {
98  	        		if ( LOG.isDebugEnabled() ) {
99  	        			LOG.debug( "unable to get class for " + StringUtils.substringBeforeLast( propertyName, "." ) + " on " + sampleBo.getClass().getName() );
100 	        		}
101 	        	}
102         	}
103         } catch (Exception e) {
104         	LOG.debug("Unable to determine type of property for " + sampleBo.getClass().getName() + "/" + propertyName, e );
105         }
106         return false;
107     }
108 
109     
110 
111 
112 
113 
114 
115 
116     protected String getExternalBusinessObjectProperty(Object sampleBo, String propertyName) {
117     	if ( propertyName.indexOf( "." ) > 0 && !StringUtils.contains( propertyName, "add." ) ) {
118     		return StringUtils.substringBeforeLast( propertyName, "." );
119     	}
120         return null;
121     }
122 
123     
124 
125 
126     protected boolean hasExternalBusinessObjectProperty(Class boClass, Map<String,String> fieldValues ) {
127     	try {
128 	    	Object sampleBo = boClass.newInstance();
129 	    	for ( String key : fieldValues.keySet() ) {
130 	    		if ( isExternalBusinessObjectProperty( sampleBo, key )) {
131 	    			return true;
132 	    		}
133 	    	}
134     	} catch ( Exception ex ) {
135         	LOG.debug("Unable to check " + boClass + " for EBO properties.", ex );
136     	}
137     	return false;
138     }
139 
140     
141 
142 
143 
144     protected Map<String,String> removeExternalizableBusinessObjectFieldValues(Class boClass, Map<String,String> fieldValues ) {
145     	Map<String,String> eboFieldValues = new HashMap<String,String>();
146     	try {
147 	    	Object sampleBo = boClass.newInstance();
148 	    	for ( String key : fieldValues.keySet() ) {
149 	    		if ( !isExternalBusinessObjectProperty( sampleBo, key )) {
150 	    			eboFieldValues.put( key, fieldValues.get( key ) );
151 	    		}
152 	    	}
153     	} catch ( Exception ex ) {
154         	LOG.debug("Unable to check " + boClass + " for EBO properties.", ex );
155     	}
156     	return eboFieldValues;
157     }
158 
159     
160 
161 
162 
163     protected Map<String,String> getExternalizableBusinessObjectFieldValues(String eboPropertyName, Map<String,String> fieldValues ) {
164     	Map<String,String> eboFieldValues = new HashMap<String,String>();
165     	for ( String key : fieldValues.keySet() ) {
166     		if ( key.startsWith( eboPropertyName + "." ) ) {
167     			eboFieldValues.put( StringUtils.substringAfterLast( key, "." ), fieldValues.get( key ) );
168     		}
169     	}
170     	return eboFieldValues;
171     }
172 
173     
174 
175 
176 
177 
178     protected List<String> getExternalizableBusinessObjectProperties(Class boClass, Map<String,String> fieldValues ) {
179     	Set<String> eboPropertyNames = new HashSet<String>();
180     	try {
181 	    	Object sampleBo = boClass.newInstance();
182 	    	for ( String key : fieldValues.keySet() ) {
183 	    		if ( isExternalBusinessObjectProperty( sampleBo, key )) {
184 	    			eboPropertyNames.add( StringUtils.substringBeforeLast( key, "." ) );
185 	    		}
186 	    	}
187     	} catch ( Exception ex ) {
188         	LOG.debug("Unable to check " + boClass + " for EBO properties.", ex );
189     	}
190     	return new ArrayList<String>(eboPropertyNames);
191     }
192 
193     
194 
195 
196 
197 
198 
199 
200 
201     protected Class<? extends ExternalizableBusinessObject> getExternalizableBusinessObjectClass(Class boClass, String propertyName) {
202         try {
203         	return PropertyUtils.getPropertyType(
204 					boClass.newInstance(), StringUtils.substringBeforeLast( propertyName, "." ) );
205         } catch (Exception e) {
206         	LOG.debug("Unable to determine type of property for " + boClass.getName() + "/" + propertyName, e );
207         }
208         return null;
209     }
210 
211     
212 
213 
214 
215 
216 
217 
218 
219 
220 
221 
222 
223     protected List<? extends BusinessObject> getSearchResultsHelper(Map<String, String> fieldValues, boolean unbounded) {
224         
225         LookupUtils.removeHiddenCriteriaFields(getBusinessObjectClass(), fieldValues);
226 
227         searchUsingOnlyPrimaryKeyValues = getLookupService().allPrimaryKeyValuesPresentAndNotWildcard(getBusinessObjectClass(), fieldValues);
228 
229         setBackLocation(fieldValues.get(KRADConstants.BACK_LOCATION));
230         setDocFormKey(fieldValues.get(KRADConstants.DOC_FORM_KEY));
231         setReferencesToRefresh(fieldValues.get(KRADConstants.REFERENCES_TO_REFRESH));
232         List searchResults;
233     	Map<String,String> nonBlankFieldValues = new HashMap<String, String>();
234     	for (String fieldName : fieldValues.keySet()) {
235     		String fieldValue = fieldValues.get(fieldName);
236     		if (StringUtils.isNotBlank(fieldValue) ) {
237     			if (fieldValue.endsWith(EncryptionService.ENCRYPTION_POST_PREFIX)) {
238     				String encryptedValue = StringUtils.removeEnd(fieldValue, EncryptionService.ENCRYPTION_POST_PREFIX);
239     				try {
240                         if(CoreApiServiceLocator.getEncryptionService().isEnabled()) {
241     					    fieldValue = getEncryptionService().decrypt(encryptedValue);
242                         }
243     				}
244     				catch (GeneralSecurityException e) {
245             			LOG.error("Error decrypting value for business object " + getBusinessObjectService() + " attribute " + fieldName, e);
246             			throw new RuntimeException("Error decrypting value for business object " + getBusinessObjectService() + " attribute " + fieldName, e);
247             		}
248     			}
249     			nonBlankFieldValues.put(fieldName, fieldValue);
250     		}
251     	}
252 
253         
254         if ( ExternalizableBusinessObjectUtils.isExternalizableBusinessObject( getBusinessObjectClass() ) ) {
255         	ModuleService eboModuleService = KRADServiceLocatorWeb.getKualiModuleService().getResponsibleModuleService( getBusinessObjectClass() );
256         	BusinessObjectEntry ddEntry = eboModuleService.getExternalizableBusinessObjectDictionaryEntry(getBusinessObjectClass());
257         	Map<String,String> filteredFieldValues = new HashMap<String, String>();
258         	for (String fieldName : nonBlankFieldValues.keySet()) {
259         		if (ddEntry.getAttributeNames().contains(fieldName)) {
260         			filteredFieldValues.put(fieldName, nonBlankFieldValues.get(fieldName));
261         		}
262         	}
263         	searchResults = eboModuleService.getExternalizableBusinessObjectsListForLookup(getBusinessObjectClass(), (Map)filteredFieldValues, unbounded);
264         
265         } else if ( hasExternalBusinessObjectProperty( getBusinessObjectClass(), nonBlankFieldValues ) ) {
266         	if ( LOG.isDebugEnabled() ) {
267         		LOG.debug( "has EBO reference: " + getBusinessObjectClass() );
268         		LOG.debug( "properties: " + nonBlankFieldValues );
269         	}
270         	
271         	Map<String,String> nonEboFieldValues = removeExternalizableBusinessObjectFieldValues( getBusinessObjectClass(), nonBlankFieldValues );
272         	if ( LOG.isDebugEnabled() ) {
273         		LOG.debug( "Non EBO properties removed: " + nonEboFieldValues );
274         	}
275         	
276         	List<String> eboPropertyNames = getExternalizableBusinessObjectProperties( getBusinessObjectClass(), nonBlankFieldValues );
277         	if ( LOG.isDebugEnabled() ) {
278         		LOG.debug( "EBO properties: " + eboPropertyNames );
279         	}
280         	
281         	for ( String eboPropertyName : eboPropertyNames ) {
282         		
283         		Map<String,String> eboFieldValues = getExternalizableBusinessObjectFieldValues( eboPropertyName, nonBlankFieldValues );
284             	if ( LOG.isDebugEnabled() ) {
285             		LOG.debug( "EBO properties for master EBO property: " + eboPropertyName );
286             		LOG.debug( "properties: " + eboFieldValues );
287             	}
288             	
289             	ModuleService eboModuleService = KRADServiceLocatorWeb.getKualiModuleService().getResponsibleModuleService( getExternalizableBusinessObjectClass( getBusinessObjectClass(), eboPropertyName) );
290             	
291          	 	List eboResults = Collections.emptyList();
292          	 	if (eboModuleService != null) 
293          	 	{
294          	 		eboResults = eboModuleService.getExternalizableBusinessObjectsListForLookup( getExternalizableBusinessObjectClass( getBusinessObjectClass(), eboPropertyName), (Map)eboFieldValues, unbounded);
295          	 	}
296          	 		else
297          	 	{
298          	 		LOG.debug( "EBO ModuleService is null: " + eboPropertyName );
299          	 	}
300         		
301         		
302 
303         		
304         		Class eboParentClass;
305         		String eboParentPropertyName;
306         		if ( ObjectUtils.isNestedAttribute( eboPropertyName ) ) {
307         			eboParentPropertyName = StringUtils.substringBeforeLast( eboPropertyName, "." );
308 	        		try {
309 	        			eboParentClass = PropertyUtils.getPropertyType( getBusinessObjectClass().newInstance(), eboParentPropertyName );
310 	        		} catch ( Exception ex ) {
311 	        			throw new RuntimeException( "Unable to create an instance of the business object class: " + getBusinessObjectClass().getName(), ex );
312 	        		}
313         		} else {
314         			eboParentClass = getBusinessObjectClass();
315         			eboParentPropertyName = null;
316         		}
317         		if ( LOG.isDebugEnabled() ) {
318         			LOG.debug( "determined EBO parent class/property name: " + eboParentClass + "/" + eboParentPropertyName );
319         		}
320         		
321         		
322         		
323         		RelationshipDefinition rd = getBusinessObjectMetaDataService().getBusinessObjectRelationshipDefinition( eboParentClass, eboPropertyName );
324         		if ( LOG.isDebugEnabled() ) {
325         			LOG.debug( "Obtained RelationshipDefinition for " + eboPropertyName );
326         			LOG.debug( rd );
327         		}
328 
329         		
330         		
331         		
332         		
333         		if ( ObjectUtils.isNotNull(rd)) {
334 	        		if ( rd.getPrimitiveAttributes().size() > 1 ) {
335 	        			throw new RuntimeException( "EBO Links don't work for relationships with multiple-field primary keys." );
336 	        		}
337 	        		String boProperty = rd.getPrimitiveAttributes().get( 0 ).getSourceName();
338 	        		String eboProperty = rd.getPrimitiveAttributes().get( 0 ).getTargetName();
339 	        		StringBuffer boPropertyValue = new StringBuffer();
340 	        		
341 	        		
342 	        		for ( Object ebo : eboResults ) {
343 	        			if ( boPropertyValue.length() != 0 ) {
344 	        				boPropertyValue.append( SearchOperator.OR.op() );
345 	        			}
346 	        			try {
347 	        				boPropertyValue.append( PropertyUtils.getProperty( ebo, eboProperty ).toString() );
348 	        			} catch ( Exception ex ) {
349 	        				LOG.warn( "Unable to get value for " + eboProperty + " on " + ebo );
350 	        			}
351 	        		}
352 	        		if ( eboParentPropertyName == null ) {
353 	        			
354 	        			nonEboFieldValues.put( boProperty, boPropertyValue.toString() );
355 	        		} else {
356 	        			
357 	        			nonEboFieldValues.put( eboParentPropertyName + "." + boProperty, boPropertyValue.toString() );
358 	        		}
359         		}
360         	}
361         	if ( LOG.isDebugEnabled() ) {
362         		LOG.debug( "Passing these results into the lookup service: " + nonEboFieldValues );
363         	}
364         	
365         	
366     		searchResults = (List) getLookupService().findCollectionBySearchHelper(getBusinessObjectClass(), nonEboFieldValues, unbounded);
367         } else {
368             searchResults = (List) getLookupService().findCollectionBySearchHelper(getBusinessObjectClass(), nonBlankFieldValues, unbounded);
369         }
370         
371         if (searchResults == null) {
372         	searchResults = new ArrayList();
373         }
374 
375         
376         List defaultSortColumns = getDefaultSortColumns();
377         if (defaultSortColumns.size() > 0) {
378             Collections.sort(searchResults, new BeanPropertyComparator(defaultSortColumns, true));
379         }
380         return searchResults;
381     }
382 
383 
384     
385 
386 
387     @Override
388     public boolean isSearchUsingOnlyPrimaryKeyValues() {
389         return searchUsingOnlyPrimaryKeyValues;
390 }
391 
392 
393     
394 
395 
396 
397 
398 
399 
400 
401 
402     @Override
403     public String getPrimaryKeyFieldLabels() {
404         StringBuilder buf = new StringBuilder();
405         List<String> primaryKeyFieldNames = KRADServiceLocatorWeb.getLegacyDataAdapter().listPrimaryKeyFieldNames(getBusinessObjectClass());
406         Iterator<String> pkIter = primaryKeyFieldNames.iterator();
407         while (pkIter.hasNext()) {
408             String pkFieldName = (String) pkIter.next();
409             buf.append(getDataDictionaryService().getAttributeLabel(getBusinessObjectClass(), pkFieldName));
410             if (pkIter.hasNext()) {
411                 buf.append(", ");
412             }
413         }
414         return buf.length() == 0 ? KRADConstants.NOT_AVAILABLE_STRING : buf.toString();
415     }
416 
417 
418 }
419