1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.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.coreservice.framework.CoreFrameworkServiceLocator;
24 import org.kuali.rice.krad.bo.ExternalizableBusinessObject;
25 import org.kuali.rice.krad.data.KradDataServiceLocator;
26 import org.kuali.rice.krad.datadictionary.RelationshipDefinition;
27 import org.kuali.rice.krad.datadictionary.exception.UnknownBusinessClassAttributeException;
28 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
29 import org.kuali.rice.krad.service.ModuleService;
30 import org.kuali.rice.krad.uif.UifConstants;
31 import org.kuali.rice.krad.uif.UifPropertyPaths;
32 import org.kuali.rice.krad.uif.lifecycle.ComponentPostMetadata;
33 import org.kuali.rice.krad.uif.lifecycle.ViewPostMetadata;
34 import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
35 import org.kuali.rice.krad.util.ExternalizableBusinessObjectUtils;
36 import org.kuali.rice.krad.util.KRADConstants;
37 import org.kuali.rice.krad.util.KRADPropertyConstants;
38 import org.kuali.rice.krad.util.KRADUtils;
39 import org.kuali.rice.krad.web.form.UifFormBase;
40 import org.springframework.beans.PropertyAccessorUtils;
41
42 import javax.servlet.http.HttpServletRequest;
43
44 import java.sql.Date;
45 import java.sql.Timestamp;
46 import java.text.ParseException;
47 import java.util.ArrayList;
48 import java.util.Calendar;
49 import java.util.Collections;
50 import java.util.HashMap;
51 import java.util.HashSet;
52 import java.util.List;
53 import java.util.Map;
54 import java.util.Set;
55
56
57
58
59
60
61 public class LookupUtils {
62 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(LookupUtils.class);
63 private static final String[] searchList = new String[SearchOperator.QUERY_CHARACTERS.size()];
64
65 static {
66 int index = 0;
67 for (SearchOperator operator : SearchOperator.QUERY_CHARACTERS) {
68 searchList[index++] = operator.op();
69 }
70 }
71
72 private static final String[] replacementList = Collections.nCopies(searchList.length, "").toArray(new String[0]);
73
74 private LookupUtils() {}
75
76
77
78
79
80
81
82
83
84
85
86
87
88 public static String retrieveLookupParameterValue(UifFormBase form, HttpServletRequest request,
89 Class<?> lookupObjectClass, String propertyName, String parameterName) {
90
91 if (KRADUtils.isSecure(propertyName, lookupObjectClass)) {
92 LOG.warn("field name " + propertyName + " is a secure value and not returned in parameter result value");
93 return null;
94 }
95
96 String parameterValue = "";
97
98
99 if (StringUtils.startsWith(parameterName, "'") && StringUtils.endsWith(parameterName, "'")) {
100 parameterValue = StringUtils.substringBetween(parameterName, "'");
101 } else if (parameterValue.startsWith(KRADConstants.LOOKUP_PARAMETER_LITERAL_PREFIX
102 + KRADConstants.LOOKUP_PARAMETER_LITERAL_DELIMITER)) {
103 parameterValue = StringUtils.removeStart(parameterValue, KRADConstants.LOOKUP_PARAMETER_LITERAL_PREFIX
104 + KRADConstants.LOOKUP_PARAMETER_LITERAL_DELIMITER);
105 }
106
107 else if (request.getParameterMap().containsKey(parameterName)) {
108 parameterValue = request.getParameter(parameterName);
109 }
110
111 else {
112 parameterValue = ObjectPropertyUtils.getPropertyValueAsText(form, parameterName);
113 }
114
115 return parameterValue;
116 }
117
118
119
120
121
122
123 public static String getBaseLookupUrl() {
124 return CoreApiServiceLocator.getKualiConfigurationService().getPropertyValueAsString(
125 KRADConstants.KRAD_LOOKUP_URL_KEY);
126 }
127
128
129
130
131
132
133
134
135
136
137
138 public static String forceUppercase(Class<?> dataObjectClass, String fieldName, String fieldValue) {
139
140 if (StringUtils.isBlank(fieldValue)) {
141 return fieldValue;
142 }
143
144
145 if (dataObjectClass == null) {
146 throw new IllegalArgumentException("Parameter dataObjectClass passed in with null value.");
147 }
148
149 if (StringUtils.isBlank(fieldName)) {
150 throw new IllegalArgumentException("Parameter fieldName passed in with empty value.");
151 }
152
153 if (!KRADServiceLocatorWeb.getDataDictionaryService().isAttributeDefined(dataObjectClass, fieldName)
154 .booleanValue()) {
155 return fieldValue;
156 }
157
158 boolean forceUpperCase = false;
159 try {
160 forceUpperCase = KRADServiceLocatorWeb.getDataDictionaryService()
161 .getAttributeForceUppercase(dataObjectClass, fieldName).booleanValue();
162 } catch (UnknownBusinessClassAttributeException ubae) {
163
164 }
165
166 if (forceUpperCase && !fieldValue.endsWith(EncryptionService.ENCRYPTION_POST_PREFIX)) {
167 return fieldValue.toUpperCase();
168 }
169
170 return fieldValue;
171 }
172
173
174
175
176
177
178
179
180
181 public static Map<String, String> forceUppercase(Class<?> dataObjectClass, Map<String, String> fieldValues) {
182 if (dataObjectClass == null) {
183 throw new IllegalArgumentException("Parameter boClass passed in with null value.");
184 }
185
186 if (fieldValues == null) {
187 throw new IllegalArgumentException("Parameter fieldValues passed in with null value.");
188 }
189
190 for (String fieldName : fieldValues.keySet()) {
191 fieldValues.put(fieldName, forceUppercase(dataObjectClass, fieldName, fieldValues.get(fieldName)));
192 }
193
194 return fieldValues;
195 }
196
197
198
199
200
201
202
203
204
205
206
207 public static Integer getSearchResultsLimit(Class dataObjectClass, LookupForm lookupForm) {
208 Integer limit = KRADServiceLocatorWeb.getViewDictionaryService().getResultSetLimitForLookup(dataObjectClass,
209 lookupForm);
210 if (limit == null) {
211 limit = getApplicationSearchResultsLimit();
212 }
213
214 return limit;
215 }
216
217
218
219
220
221
222 public static Integer getApplicationSearchResultsLimit() {
223 String limitString = CoreFrameworkServiceLocator.getParameterService()
224 .getParameterValueAsString(KRADConstants.KRAD_NAMESPACE,
225 KRADConstants.DetailTypes.LOOKUP_PARM_DETAIL_TYPE,
226 KRADConstants.SystemGroupParameterNames.LOOKUP_RESULTS_LIMIT);
227 if (limitString != null) {
228 return Integer.valueOf(limitString);
229 }
230
231 return null;
232 }
233
234
235
236
237
238
239 public static Integer getApplicationMultipleValueSearchResultsLimit() {
240 String limitString = CoreFrameworkServiceLocator.getParameterService()
241 .getParameterValueAsString(KRADConstants.KRAD_NAMESPACE,
242 KRADConstants.DetailTypes.LOOKUP_PARM_DETAIL_TYPE,
243 KRADConstants.SystemGroupParameterNames.MULTIPLE_VALUE_LOOKUP_RESULTS_LIMIT);
244 if (limitString != null) {
245 return Integer.valueOf(limitString);
246 }
247
248 return null;
249 }
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265 public static Timestamp getActiveDateTimestampForCriteria(Map searchValues) {
266 Date activeDate = CoreApiServiceLocator.getDateTimeService().getCurrentSqlDate();
267
268 Timestamp activeTimestamp = null;
269 if (searchValues.containsKey(KRADPropertyConstants.ACTIVE_AS_OF_DATE)) {
270 String activeAsOfDate = (String) searchValues.get(KRADPropertyConstants.ACTIVE_AS_OF_DATE);
271 if (StringUtils.isNotBlank(activeAsOfDate)) {
272 try {
273 activeDate = CoreApiServiceLocator.getDateTimeService()
274 .convertToSqlDate(KRADUtils.clean(activeAsOfDate));
275 } catch (ParseException e) {
276
277 try {
278 activeTimestamp = CoreApiServiceLocator.getDateTimeService()
279 .convertToSqlTimestamp(KRADUtils.clean(activeAsOfDate));
280 } catch (ParseException e1) {
281 throw new RuntimeException("Unable to convert date: " + KRADUtils.clean(activeAsOfDate));
282 }
283 }
284 }
285 }
286
287
288 if (activeTimestamp == null) {
289 Calendar cal = Calendar.getInstance();
290
291 cal.setTime(activeDate);
292 cal.set(Calendar.HOUR, cal.getMaximum(Calendar.HOUR));
293 cal.set(Calendar.MINUTE, cal.getMaximum(Calendar.MINUTE));
294 cal.set(Calendar.SECOND, cal.getMaximum(Calendar.SECOND));
295
296 activeTimestamp = new Timestamp(cal.getTime().getTime());
297 }
298
299 return activeTimestamp;
300 }
301
302
303
304
305
306
307
308
309 public static Map<String, String> preprocessDateFields(Map<String, String> searchCriteria) {
310 Map<String, String> fieldsToUpdate = new HashMap<String, String>();
311 Map<String, String> searchCriteriaUpdated = new HashMap<String, String>(searchCriteria);
312
313 Set<String> fieldsForLookup = searchCriteria.keySet();
314 for (String propName : fieldsForLookup) {
315 if (propName.startsWith(KRADConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX)) {
316 String from_DateValue = searchCriteria.get(propName);
317 String dateFieldName =
318 StringUtils.remove(propName, KRADConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX);
319 String to_DateValue = searchCriteria.get(dateFieldName);
320 String newPropValue = to_DateValue;
321
322 if (StringUtils.isNotEmpty(from_DateValue) && StringUtils.isNotEmpty(to_DateValue)) {
323 newPropValue = from_DateValue + SearchOperator.BETWEEN + to_DateValue;
324 } else if (StringUtils.isNotEmpty(from_DateValue) && StringUtils.isEmpty(to_DateValue)) {
325 newPropValue = SearchOperator.GREATER_THAN_EQUAL.op() + from_DateValue;
326 } else if (StringUtils.isNotEmpty(to_DateValue) && StringUtils.isEmpty(from_DateValue)) {
327 newPropValue = SearchOperator.LESS_THAN_EQUAL.op() + to_DateValue;
328 }
329
330 fieldsToUpdate.put(dateFieldName, newPropValue);
331 }
332 }
333
334
335 Set<String> keysToUpdate = fieldsToUpdate.keySet();
336 for (String updateKey : keysToUpdate) {
337 searchCriteriaUpdated.put(updateKey, fieldsToUpdate.get(updateKey));
338 }
339
340 return searchCriteriaUpdated;
341 }
342
343
344
345
346
347
348
349
350
351
352 public static boolean hasExternalBusinessObjectProperty(Class<?> boClass,
353 Map<String, String> fieldValues) throws IllegalAccessException, InstantiationException {
354 Object sampleBo = boClass.newInstance();
355 for (String key : fieldValues.keySet()) {
356 if (isExternalBusinessObjectProperty(sampleBo, key)) {
357 return true;
358 }
359 }
360
361 return false;
362 }
363
364
365
366
367
368
369
370
371
372
373 public static boolean isExternalBusinessObjectProperty(Object sampleBo, String propertyName) {
374 if (propertyName.indexOf(".") > 0 && !StringUtils.contains(propertyName, "add.")) {
375 Class<?> propertyClass =
376 ObjectPropertyUtils.getPropertyType(sampleBo, StringUtils.substringBeforeLast(propertyName, "."));
377 if (propertyClass != null) {
378 return ExternalizableBusinessObjectUtils.isExternalizableBusinessObjectInterface(propertyClass);
379 }
380 }
381
382 return false;
383 }
384
385
386
387
388
389
390
391
392
393
394 public static Map<String, String> removeExternalizableBusinessObjectFieldValues(Class<?> boClass,
395 Map<String, String> fieldValues) throws IllegalAccessException, InstantiationException {
396 Map<String, String> eboFieldValues = new HashMap<String, String>();
397 Object sampleBo = boClass.newInstance();
398 for (String key : fieldValues.keySet()) {
399 if (!isExternalBusinessObjectProperty(sampleBo, key)) {
400 eboFieldValues.put(key, fieldValues.get(key));
401 }
402 }
403
404 return eboFieldValues;
405 }
406
407
408
409
410
411
412
413
414
415 public static Map<String, String> getExternalizableBusinessObjectFieldValues(String eboPropertyName,
416 Map<String, String> fieldValues) {
417 Map<String, String> eboFieldValues = new HashMap<String, String>();
418 for (String key : fieldValues.keySet()) {
419 if (key.startsWith(eboPropertyName + ".")) {
420 eboFieldValues.put(StringUtils.substringAfterLast(key, "."), fieldValues.get(key));
421 }
422 }
423
424 return eboFieldValues;
425 }
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440 public static List<String> getExternalizableBusinessObjectProperties(Class<?> boClass,
441 Map<String, String> fieldValues) throws IllegalAccessException, InstantiationException {
442 Set<String> eboPropertyNames = new HashSet<String>();
443
444 Object sampleBo = boClass.newInstance();
445 for (String key : fieldValues.keySet()) {
446 if (isExternalBusinessObjectProperty(sampleBo, key)) {
447 eboPropertyNames.add(StringUtils.substringBeforeLast(key, "."));
448 }
449 }
450
451 return new ArrayList<String>(eboPropertyNames);
452 }
453
454
455
456
457
458
459
460
461
462
463
464 public static Class<? extends ExternalizableBusinessObject> getExternalizableBusinessObjectClass(Class<?> boClass,
465 String propertyName) throws IllegalAccessException, InstantiationException {
466 return (Class<? extends ExternalizableBusinessObject>) ObjectPropertyUtils
467 .getPropertyType(boClass.newInstance(), StringUtils.substringBeforeLast(propertyName, "."));
468 }
469
470
471
472
473
474
475
476
477
478
479
480 public static Map<String, String> adjustCriteriaForNestedEBOs(Class<?> dataObjectClass,
481 Map<String, String> searchCriteria,
482 boolean unbounded) throws InstantiationException, IllegalAccessException {
483
484 Map<String, String> nonEboFieldValues = removeExternalizableBusinessObjectFieldValues(
485 dataObjectClass, searchCriteria);
486 if (LOG.isDebugEnabled()) {
487 LOG.debug("Non EBO properties removed: " + nonEboFieldValues);
488 }
489
490
491 List<String> eboPropertyNames = getExternalizableBusinessObjectProperties(dataObjectClass, searchCriteria);
492 if (LOG.isDebugEnabled()) {
493 LOG.debug("EBO properties: " + eboPropertyNames);
494 }
495
496
497 for (String eboPropertyName : eboPropertyNames) {
498
499 Map<String, String> eboFieldValues = LookupUtils.getExternalizableBusinessObjectFieldValues(eboPropertyName,
500 searchCriteria);
501 if (LOG.isDebugEnabled()) {
502 LOG.debug("EBO properties for master EBO property: " + eboPropertyName);
503 LOG.debug("properties: " + eboFieldValues);
504 }
505
506
507 ModuleService eboModuleService = KRADServiceLocatorWeb.getKualiModuleService().getResponsibleModuleService(
508 getExternalizableBusinessObjectClass(dataObjectClass, eboPropertyName));
509
510
511 List<?> eboResults = Collections.emptyList();
512 if (eboModuleService != null) {
513 eboResults = eboModuleService.getExternalizableBusinessObjectsListForLookup(
514 getExternalizableBusinessObjectClass(dataObjectClass, eboPropertyName),
515 (Map) eboFieldValues, unbounded);
516 } else {
517 LOG.debug("EBO ModuleService is null: " + eboPropertyName);
518 }
519
520
521 Class<?> eboParentClass;
522 String eboParentPropertyName;
523 if (PropertyAccessorUtils.isNestedOrIndexedProperty(eboPropertyName)) {
524 eboParentPropertyName = StringUtils.substringBeforeLast(eboPropertyName, ".");
525 try {
526 eboParentClass = KradDataServiceLocator.getDataObjectService().wrap(dataObjectClass.newInstance()).getPropertyType(
527 eboParentPropertyName);
528 } catch (Exception ex) {
529 throw new RuntimeException(
530 "Unable to create an instance of the business object class: " + dataObjectClass
531 .getName(), ex);
532 }
533 } else {
534 eboParentClass = dataObjectClass;
535 eboParentPropertyName = null;
536 }
537
538 if (LOG.isDebugEnabled()) {
539 LOG.debug("determined EBO parent class/property name: " + eboParentClass + "/" + eboParentPropertyName);
540 }
541
542
543
544
545 RelationshipDefinition rd = KRADServiceLocatorWeb.getLegacyDataAdapter().getDictionaryRelationship(
546 eboParentClass, eboPropertyName);
547 if (LOG.isDebugEnabled()) {
548 LOG.debug("Obtained RelationshipDefinition for " + eboPropertyName);
549 LOG.debug(rd);
550 }
551
552
553
554
555
556
557
558 if (KRADUtils.isNotNull(rd)) {
559 if (rd.getPrimitiveAttributes().size() > 1) {
560 throw new RuntimeException(
561 "EBO Links don't work for relationships with multiple-field primary keys.");
562 }
563 String boProperty = rd.getPrimitiveAttributes().get(0).getSourceName();
564 String eboProperty = rd.getPrimitiveAttributes().get(0).getTargetName();
565 StringBuffer boPropertyValue = new StringBuffer();
566
567
568
569 for (Object ebo : eboResults) {
570 if (boPropertyValue.length() != 0) {
571 boPropertyValue.append(SearchOperator.OR.op());
572 }
573 try {
574 boPropertyValue.append(PropertyUtils.getProperty(ebo, eboProperty).toString());
575 } catch (Exception ex) {
576 LOG.warn("Unable to get value for " + eboProperty + " on " + ebo);
577 }
578 }
579
580 if (eboParentPropertyName == null) {
581
582 nonEboFieldValues.put(boProperty, boPropertyValue.toString());
583 } else {
584
585 nonEboFieldValues.put(eboParentPropertyName + "." + boProperty, boPropertyValue.toString());
586 }
587 }
588 }
589
590 return nonEboFieldValues;
591 }
592
593
594
595
596
597
598
599 public static String scrubQueryCharacters(String criteriaValue) {
600 return StringUtils.replaceEach(criteriaValue, searchList, replacementList);
601 }
602
603
604
605
606
607
608
609
610
611
612
613 public static String generateMultiValueKey(Object lineDataObject, List<String> fieldConversionKeys) {
614 String lineIdentifier = "";
615
616 if(fieldConversionKeys == null || fieldConversionKeys.isEmpty()) {
617 lineIdentifier =
618 KRADServiceLocatorWeb.getLegacyDataAdapter().getDataObjectIdentifierString(lineDataObject);
619 } else {
620 Collections.sort(fieldConversionKeys);
621 for (String fromFieldName : fieldConversionKeys) {
622 Object fromFieldValue = ObjectPropertyUtils.getPropertyValue(lineDataObject, fromFieldName);
623
624 if (fromFieldValue != null) {
625 lineIdentifier += fromFieldValue;
626 }
627
628 lineIdentifier += ":";
629 }
630 lineIdentifier = StringUtils.removeEnd(lineIdentifier, ":");
631 }
632
633 return lineIdentifier;
634 }
635
636
637
638
639
640
641
642 public static void refreshLookupResultSelections(LookupForm form) {
643 int displayStart = 0;
644 int displayLength = 0;
645
646
647 ViewPostMetadata viewPostMetadata = form.getViewPostMetadata();
648 if (viewPostMetadata != null) {
649
650
651 synchronized (viewPostMetadata) {
652 ComponentPostMetadata oldCollectionGroup = viewPostMetadata.getComponentPostMetadata("uLookupResults");
653 displayStart = (Integer) oldCollectionGroup.getData(UifConstants.PostMetadata.COLL_DISPLAY_START);
654 displayLength = (Integer) oldCollectionGroup.getData(UifConstants.PostMetadata.COLL_DISPLAY_LENGTH);
655 }
656 }
657
658 List<? extends Object> lookupResults = (List<? extends Object>) form.getLookupResults();
659 List<String> fromFieldNames = form.getMultiValueReturnFields();
660
661 Set<String> selectedLines = form.getSelectedCollectionLines().get(UifPropertyPaths.LOOKUP_RESULTS);
662 Set<String> selectedLookupResultsCache = form.getSelectedLookupResultsCache();
663
664 selectedLines = (selectedLines == null) ? new HashSet<String>() : selectedLines;
665
666 for(int i = displayStart; i < displayStart + displayLength; i++ ) {
667 if(i >= form.getLookupResults().size()) break;
668
669 Object lineItem = lookupResults.get(i);
670 String lineIdentifier = LookupUtils.generateMultiValueKey(lineItem, fromFieldNames);
671
672 if(!selectedLines.contains(lineIdentifier)) {
673 selectedLookupResultsCache.remove(lineIdentifier);
674 } else {
675 selectedLookupResultsCache.add(lineIdentifier);
676 }
677 }
678
679 selectedLines.addAll( selectedLookupResultsCache );
680
681 form.getSelectedCollectionLines().put(UifPropertyPaths.LOOKUP_RESULTS, selectedLines);
682 }
683
684 }