1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.uif.service.impl;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.kuali.rice.core.api.CoreApiServiceLocator;
20 import org.kuali.rice.core.api.config.property.ConfigurationService;
21 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
22 import org.kuali.rice.krad.service.LookupService;
23 import org.kuali.rice.krad.uif.UifConstants;
24 import org.kuali.rice.krad.uif.UifParameters;
25 import org.kuali.rice.krad.uif.component.MethodInvokerConfig;
26 import org.kuali.rice.krad.uif.field.AttributeQuery;
27 import org.kuali.rice.krad.uif.field.AttributeQueryResult;
28 import org.kuali.rice.krad.uif.field.InputField;
29 import org.kuali.rice.krad.uif.service.AttributeQueryService;
30 import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
31 import org.kuali.rice.krad.uif.view.View;
32 import org.kuali.rice.krad.uif.widget.LocationSuggest;
33 import org.kuali.rice.krad.uif.widget.Suggest;
34 import org.kuali.rice.krad.util.BeanPropertyComparator;
35
36 import java.text.MessageFormat;
37 import java.util.ArrayList;
38 import java.util.Collection;
39 import java.util.Collections;
40 import java.util.HashMap;
41 import java.util.List;
42 import java.util.Map;
43
44
45
46
47
48
49
50 public class AttributeQueryServiceImpl implements AttributeQueryService {
51 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(
52 AttributeQueryServiceImpl.class);
53
54 private LookupService lookupService;
55 private ConfigurationService configurationService;
56
57
58
59
60
61
62 @Override
63 public AttributeQueryResult performFieldSuggestQuery(View view, String fieldId, String fieldTerm,
64 Map<String, String> queryParameters) {
65 AttributeQueryResult queryResult = new AttributeQueryResult();
66
67
68 InputField inputField = (InputField) view.getViewIndex().getComponentById(fieldId);
69 if (inputField == null) {
70 throw new RuntimeException("Unable to find attribute field instance for id: " + fieldId);
71 }
72
73 Suggest fieldSuggest = inputField.getSuggest();
74 AttributeQuery suggestQuery = fieldSuggest.getSuggestQuery();
75
76
77 Map<String, String> additionalCriteria = new HashMap<String, String>();
78 additionalCriteria.put(fieldSuggest.getValuePropertyName(), fieldTerm + "*");
79
80
81 Collection<?> results = null;
82 if (suggestQuery.hasConfiguredMethod()) {
83 Object queryMethodResult = executeAttributeQueryMethod(view, suggestQuery, queryParameters, true,
84 fieldTerm);
85 if ((queryMethodResult != null) && (queryMethodResult instanceof Collection<?>)) {
86 results = (Collection<?>) queryMethodResult;
87 }
88 } else {
89 results = executeAttributeQueryCriteria(suggestQuery, queryParameters, additionalCriteria);
90 }
91
92
93 if (results != null) {
94 if (fieldSuggest.isReturnFullQueryObject()) {
95 queryResult.setResultData((List<Object>) results);
96 } else {
97 retrievePropertiesOnResults(queryResult, results, fieldSuggest);
98 }
99 }
100
101 return queryResult;
102 }
103
104
105
106
107
108
109
110
111
112 protected void retrievePropertiesOnResults(AttributeQueryResult queryResult, Collection<?> results,
113 Suggest fieldSuggest) {
114 List<Object> suggestData = new ArrayList<Object>();
115 for (Object result : results) {
116 if (result == null) {
117 continue;
118 }
119
120 Map<String, String> propMap = new HashMap<String, String>();
121
122
123 if (result instanceof String) {
124 propMap.put(UifParameters.VALUE, (String) result);
125 propMap.put(UifParameters.LABEL, (String) result);
126 }
127
128
129 Object suggestFieldValue = null;
130 if (StringUtils.isNotBlank(fieldSuggest.getValuePropertyName())) {
131 suggestFieldValue = ObjectPropertyUtils.getPropertyValue(result, fieldSuggest.getValuePropertyName());
132 } else if (ObjectPropertyUtils.isReadableProperty(result, UifParameters.VALUE)) {
133 suggestFieldValue = ObjectPropertyUtils.getPropertyValue(result, UifParameters.VALUE);
134 }
135
136 if (suggestFieldValue != null) {
137 propMap.put(UifParameters.VALUE, suggestFieldValue.toString());
138 }
139
140
141 Object suggestFieldLabel = null;
142 if (StringUtils.isNotBlank(fieldSuggest.getLabelPropertyName())) {
143 suggestFieldLabel = ObjectPropertyUtils.getPropertyValue(result, fieldSuggest.getLabelPropertyName());
144 } else if (ObjectPropertyUtils.isReadableProperty(result, UifParameters.LABEL)) {
145 suggestFieldLabel = ObjectPropertyUtils.getPropertyValue(result, UifParameters.LABEL);
146 }
147
148 if (suggestFieldLabel != null) {
149 propMap.put(UifParameters.LABEL, suggestFieldLabel.toString());
150 }
151
152
153 if (fieldSuggest instanceof LocationSuggest) {
154 handleLocationSuggestProperties((LocationSuggest) fieldSuggest, result, propMap);
155 }
156
157
158 handleAdditionalSuggestProperties(fieldSuggest, result, propMap);
159
160
161 if (!propMap.isEmpty()) {
162
163 suggestData.add(propMap);
164 }
165 }
166
167 queryResult.setResultData(suggestData);
168 }
169
170
171
172
173
174
175
176
177 private void handleAdditionalSuggestProperties(Suggest fieldSuggest, Object result, Map<String, String> propMap){
178 if (fieldSuggest.getAdditionalPropertiesToReturn() != null){
179
180 for(String propName: fieldSuggest.getAdditionalPropertiesToReturn()){
181 Object propValue = null;
182
183 if(StringUtils.isNotBlank(propName)
184 && ObjectPropertyUtils.isReadableProperty(result, propName)){
185 propValue = ObjectPropertyUtils.getPropertyValue(result, propName);
186 }
187
188 if (propValue != null){
189 propMap.put(propName, propValue.toString());
190 }
191 }
192 }
193 }
194
195
196
197
198
199
200
201
202 private void handleLocationSuggestProperties(LocationSuggest fieldSuggest, Object result, Map<String, String> propMap){
203
204
205 Object suggestHrefValue = null;
206 if(StringUtils.isNotBlank(fieldSuggest.getHrefPropertyName())
207 && ObjectPropertyUtils.isReadableProperty(result, fieldSuggest.getHrefPropertyName())){
208 suggestHrefValue = ObjectPropertyUtils.getPropertyValue(result, fieldSuggest.getHrefPropertyName());
209 }
210
211
212 if(suggestHrefValue != null){
213 propMap.put(fieldSuggest.getHrefPropertyName(), suggestHrefValue.toString());
214 }
215
216
217 Object addUrlValue = null;
218 if(StringUtils.isNotBlank(fieldSuggest.getAdditionalUrlPathPropertyName())
219 && ObjectPropertyUtils.isReadableProperty(result, fieldSuggest.getAdditionalUrlPathPropertyName())){
220 addUrlValue = ObjectPropertyUtils.getPropertyValue(result, fieldSuggest.getAdditionalUrlPathPropertyName());
221 }
222
223
224 if(addUrlValue != null){
225 propMap.put(fieldSuggest.getAdditionalUrlPathPropertyName(), addUrlValue.toString());
226 }
227
228 if(fieldSuggest.getRequestParameterPropertyNames() == null){
229 return;
230 }
231
232
233 for(String key: fieldSuggest.getRequestParameterPropertyNames().keySet()){
234 String prop = fieldSuggest.getRequestParameterPropertyNames().get(key);
235 Object propValue = null;
236
237 if(StringUtils.isNotBlank(prop)
238 && ObjectPropertyUtils.isReadableProperty(result, prop)){
239 propValue = ObjectPropertyUtils.getPropertyValue(result, prop);
240 }
241
242 if (propValue != null){
243 propMap.put(prop, propValue.toString());
244 }
245 }
246
247 }
248
249
250
251
252
253 @Override
254 public AttributeQueryResult performFieldQuery(View view, String fieldId, Map<String, String> queryParameters) {
255 AttributeQueryResult queryResult = new AttributeQueryResult();
256
257
258 InputField inputField = (InputField) view.getViewIndex().getComponentById(fieldId);
259 if (inputField == null) {
260 throw new RuntimeException("Unable to find attribute field instance for id: " + fieldId);
261 }
262
263 AttributeQuery fieldQuery = inputField.getAttributeQuery();
264 if (fieldQuery == null) {
265 throw new RuntimeException("Field query not defined for field instance with id: " + fieldId);
266 }
267
268
269 Object resultObject = null;
270 if (fieldQuery.hasConfiguredMethod()) {
271 Object queryMethodResult = executeAttributeQueryMethod(view, fieldQuery, queryParameters, false, null);
272 if (queryMethodResult != null) {
273
274 if (queryMethodResult instanceof AttributeQueryResult) {
275 return (AttributeQueryResult) queryMethodResult;
276 }
277
278
279 if (queryMethodResult instanceof Collection<?>) {
280 Collection<?> methodResultCollection = (Collection<?>) queryMethodResult;
281 if (!methodResultCollection.isEmpty()) {
282 resultObject = methodResultCollection.iterator().next();
283 }
284 } else {
285 resultObject = queryMethodResult;
286 }
287 }
288 } else {
289
290 Collection<?> results = executeAttributeQueryCriteria(fieldQuery, queryParameters, null);
291
292 if ((results != null) && !results.isEmpty()) {
293
294 if (results.size() > 1) {
295
296 resultObject = null;
297 } else {
298 resultObject = results.iterator().next();
299 }
300 }
301 }
302
303 if (resultObject != null) {
304
305 Map<String, String> resultFieldData = new HashMap<String, String>();
306 for (String fromField : fieldQuery.getReturnFieldMapping().keySet()) {
307 String returnField = fieldQuery.getReturnFieldMapping().get(fromField);
308
309 String fieldValueStr = "";
310 Object fieldValue = ObjectPropertyUtils.getPropertyValue(resultObject, fromField);
311 if (fieldValue != null) {
312 fieldValueStr = fieldValue.toString();
313 }
314 resultFieldData.put(returnField, fieldValueStr);
315 }
316 queryResult.setResultFieldData(resultFieldData);
317
318 fieldQuery.setReturnMessageText("");
319 } else {
320
321 if (fieldQuery.isRenderNotFoundMessage()) {
322 String messageTemplate = getConfigurationService().getPropertyValueAsString(
323 UifConstants.MessageKeys.QUERY_DATA_NOT_FOUND);
324 String message = MessageFormat.format(messageTemplate, inputField.getLabel());
325 fieldQuery.setReturnMessageText(message.toLowerCase());
326 }
327 }
328
329
330 queryResult.setResultMessage(fieldQuery.getReturnMessageText());
331 queryResult.setResultMessageStyleClasses(fieldQuery.getReturnMessageStyleClasses());
332
333 return queryResult;
334 }
335
336
337
338
339
340
341
342
343
344
345
346
347 protected Object executeAttributeQueryMethod(View view, AttributeQuery attributeQuery,
348 Map<String, String> queryParameters, boolean isSuggestQuery, String queryTerm) {
349 String queryMethodToCall = attributeQuery.getQueryMethodToCall();
350 MethodInvokerConfig queryMethodInvoker = attributeQuery.getQueryMethodInvokerConfig();
351
352 if (queryMethodInvoker == null) {
353 queryMethodInvoker = new MethodInvokerConfig();
354 }
355
356
357
358 if (StringUtils.isBlank(queryMethodInvoker.getTargetMethod())) {
359 queryMethodInvoker.setTargetMethod(queryMethodToCall);
360 }
361
362
363 if ((queryMethodInvoker.getTargetClass() == null) && (queryMethodInvoker.getTargetObject() == null)) {
364 queryMethodInvoker.setTargetObject(view.getViewHelperService());
365 }
366
367
368 List<Object> arguments = new ArrayList<Object>();
369 if ((attributeQuery.getQueryMethodArgumentFieldList() != null) && (!attributeQuery
370 .getQueryMethodArgumentFieldList().isEmpty())) {
371
372 int numQueryMethodArguments = attributeQuery.getQueryMethodArgumentFieldList().size();
373 if (isSuggestQuery) {
374 numQueryMethodArguments += 1;
375 }
376
377 Class[] argumentTypes = queryMethodInvoker.getArgumentTypes();
378 if ((argumentTypes == null) || (argumentTypes.length != numQueryMethodArguments)) {
379 throw new RuntimeException(
380 "Query method argument field list size does not match found number of method arguments");
381 }
382
383 for (int i = 0; i < attributeQuery.getQueryMethodArgumentFieldList().size(); i++) {
384 String methodArgumentFromField = attributeQuery.getQueryMethodArgumentFieldList().get(i);
385 if (queryParameters.containsKey(methodArgumentFromField)) {
386 arguments.add(queryParameters.get(methodArgumentFromField));
387 } else {
388 arguments.add(null);
389 }
390 }
391 }
392
393 if (isSuggestQuery) {
394 arguments.add(queryTerm);
395 }
396
397 queryMethodInvoker.setArguments(arguments.toArray());
398
399 try {
400 queryMethodInvoker.prepare();
401
402 return queryMethodInvoker.invoke();
403 } catch (Exception e) {
404 throw new RuntimeException("Unable to invoke query method: " + queryMethodInvoker.getTargetMethod(), e);
405 }
406 }
407
408
409
410
411
412
413
414
415
416
417 protected Collection<?> executeAttributeQueryCriteria(AttributeQuery attributeQuery,
418 Map<String, String> queryParameters, Map<String, String> additionalCriteria) {
419 Collection<?> results = null;
420
421
422 Map<String, String> queryCriteria = new HashMap<String, String>();
423 for (String fieldName : attributeQuery.getQueryFieldMapping().values()) {
424 if (queryParameters.containsKey(fieldName) && StringUtils.isNotBlank(queryParameters.get(fieldName))) {
425 queryCriteria.put(fieldName, queryParameters.get(fieldName));
426 }
427 }
428
429
430 for (String fieldName : attributeQuery.getAdditionalCriteria().keySet()) {
431 queryCriteria.put(fieldName, attributeQuery.getAdditionalCriteria().get(fieldName));
432 }
433
434
435 if (additionalCriteria != null) {
436 queryCriteria.putAll(additionalCriteria);
437 }
438
439 Class<?> queryClass = null;
440 try {
441 queryClass = Class.forName(attributeQuery.getDataObjectClassName());
442 } catch (ClassNotFoundException e) {
443 throw new RuntimeException(
444 "Invalid data object class given for suggest query: " + attributeQuery.getDataObjectClassName(), e);
445 }
446
447
448 results = getLookupService().findCollectionBySearchUnbounded(queryClass, queryCriteria);
449
450
451 if (!attributeQuery.getSortPropertyNames().isEmpty() && (results != null) && (results.size() > 1)) {
452 Collections.sort((List<?>) results, new BeanPropertyComparator(attributeQuery.getSortPropertyNames()));
453 }
454
455 return results;
456 }
457
458
459
460
461
462
463 protected LookupService getLookupService() {
464 if (lookupService == null) {
465 lookupService = KRADServiceLocatorWeb.getLookupService();
466 }
467
468 return lookupService;
469 }
470
471
472
473
474
475
476 public void setLookupService(LookupService lookupService) {
477 this.lookupService = lookupService;
478 }
479
480
481
482
483
484
485 protected ConfigurationService getConfigurationService() {
486 if (configurationService == null) {
487 configurationService = CoreApiServiceLocator.getKualiConfigurationService();
488 }
489
490 return configurationService;
491 }
492
493
494
495
496
497
498 public void setConfigurationService(ConfigurationService configurationService) {
499 this.configurationService = configurationService;
500 }
501 }