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.lang.BooleanUtils;
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.core.api.util.RiceKeyConstants;
24 import org.kuali.rice.core.api.util.type.TypeUtils;
25 import org.kuali.rice.krad.bo.ExternalizableBusinessObject;
26 import org.kuali.rice.krad.datadictionary.BusinessObjectEntry;
27 import org.kuali.rice.krad.datadictionary.DataObjectEntry;
28 import org.kuali.rice.krad.datadictionary.validation.constraint.ValidCharactersConstraint;
29 import org.kuali.rice.krad.service.DataObjectAuthorizationService;
30 import org.kuali.rice.krad.service.DocumentDictionaryService;
31 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
32 import org.kuali.rice.krad.service.LookupService;
33 import org.kuali.rice.krad.service.ModuleService;
34 import org.kuali.rice.krad.uif.UifConstants;
35 import org.kuali.rice.krad.uif.UifParameters;
36 import org.kuali.rice.krad.uif.UifPropertyPaths;
37 import org.kuali.rice.krad.uif.control.Control;
38 import org.kuali.rice.krad.uif.control.FilterableLookupCriteriaControl;
39 import org.kuali.rice.krad.uif.control.FilterableLookupCriteriaControlPostData;
40 import org.kuali.rice.krad.uif.control.HiddenControl;
41 import org.kuali.rice.krad.uif.control.ValueConfiguredControl;
42 import org.kuali.rice.krad.uif.element.Link;
43 import org.kuali.rice.krad.uif.field.InputField;
44 import org.kuali.rice.krad.uif.lifecycle.ViewPostMetadata;
45 import org.kuali.rice.krad.uif.service.impl.ViewHelperServiceImpl;
46 import org.kuali.rice.krad.uif.util.ComponentUtils;
47 import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
48 import org.kuali.rice.krad.uif.util.ScriptUtils;
49 import org.kuali.rice.krad.util.BeanPropertyComparator;
50 import org.kuali.rice.krad.util.ErrorMessage;
51 import org.kuali.rice.krad.util.GlobalVariables;
52 import org.kuali.rice.krad.util.KRADConstants;
53 import org.kuali.rice.krad.util.KRADUtils;
54 import org.kuali.rice.krad.util.MessageMap;
55 import org.kuali.rice.krad.util.UrlFactory;
56
57 import java.security.GeneralSecurityException;
58 import java.util.ArrayList;
59 import java.util.Collection;
60 import java.util.Collections;
61 import java.util.HashMap;
62 import java.util.HashSet;
63 import java.util.List;
64 import java.util.Map;
65 import java.util.Properties;
66 import java.util.Set;
67 import java.util.regex.Matcher;
68 import java.util.regex.Pattern;
69
70
71
72
73
74
75
76
77
78
79 public class LookupableImpl extends ViewHelperServiceImpl implements Lookupable {
80 private static final long serialVersionUID = 1885161468871327740L;
81 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(LookupableImpl.class);
82
83 private Class<?> dataObjectClass;
84
85 private transient DataObjectAuthorizationService dataObjectAuthorizationService;
86 private transient DocumentDictionaryService documentDictionaryService;
87 private transient LookupService lookupService;
88 private transient EncryptionService encryptionService;
89
90
91
92
93 @Override
94 public Collection<?> performSearch(LookupForm form, Map<String, String> searchCriteria, boolean bounded) {
95
96 Map<String, String> adjustedSearchCriteria = processSearchCriteria(form, searchCriteria);
97
98 boolean isValidCriteria = validateSearchParameters(form, adjustedSearchCriteria);
99 if (!isValidCriteria) {
100 return new ArrayList<Object>();
101 }
102
103 List<String> wildcardAsLiteralSearchCriteria = identifyWildcardDisabledFields(form, adjustedSearchCriteria);
104
105 Integer searchResultsLimit = null;
106 if (bounded) {
107 searchResultsLimit = LookupUtils.getSearchResultsLimit(getDataObjectClass(), form);
108 }
109
110
111
112 if (adjustedSearchCriteria == null) {
113 MessageMap messageMap = GlobalVariables.getMessageMap();
114 messageMap.putInfoForSectionId(UifConstants.MessageKeys.LOOKUP_RESULT_MESSAGES,
115 RiceKeyConstants.INFO_LOOKUP_RESULTS_NONE_FOUND);
116 return new ArrayList<Object>();
117 }
118
119 Collection<?> searchResults = null;
120
121
122 if (ExternalizableBusinessObject.class.isAssignableFrom(getDataObjectClass())) {
123 searchResults = getSearchResultsForEBO(adjustedSearchCriteria, !bounded);
124 } else {
125 searchResults = getSearchResults(adjustedSearchCriteria, wildcardAsLiteralSearchCriteria, !bounded,
126 searchResultsLimit);
127 }
128
129 generateLookupResultsMessages(adjustedSearchCriteria, searchResults, bounded, searchResultsLimit);
130
131 Collection<?> sortedResults;
132 if (searchResults != null) {
133 sortedResults = new ArrayList<Object>(searchResults);
134
135 sortSearchResults(form, (List<?>) sortedResults);
136 } else {
137 sortedResults = new ArrayList<Object>();
138 }
139
140 return sortedResults;
141 }
142
143
144
145
146
147
148
149
150
151
152 protected Collection<?> executeSearch(Map<String, String> adjustedSearchCriteria,
153 List<String> wildcardAsLiteralSearchCriteria, boolean bounded, Integer searchResultsLimit) {
154 return getLookupService().findCollectionBySearchHelper(getDataObjectClass(), adjustedSearchCriteria,
155 wildcardAsLiteralSearchCriteria, !bounded, searchResultsLimit);
156 }
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173 protected Map<String, String> processSearchCriteria(LookupForm lookupForm, Map<String, String> searchCriteria) {
174 Map<String, InputField> criteriaFields = new HashMap<String, InputField>();
175 if (lookupForm.getView() != null) {
176 criteriaFields = getCriteriaFieldsForValidation((LookupView) lookupForm.getView(), lookupForm);
177 }
178
179
180 Map<String, String> filteredSearchCriteria = LookupUtils.preprocessDateFields(searchCriteria);
181
182
183 for (String fieldName : searchCriteria.keySet()) {
184 InputField inputField = criteriaFields.get(fieldName);
185
186 if ((inputField == null) || !(inputField instanceof LookupInputField)) {
187 continue;
188 }
189
190 LookupInputField lookupInputField = (LookupInputField) inputField;
191 String propertyName = lookupInputField.getPropertyName();
192
193
194 ViewPostMetadata viewPostMetadata = lookupForm.getViewPostMetadata();
195 if (viewPostMetadata != null) {
196 Object componentPostData = viewPostMetadata.getComponentPostData(lookupForm.getViewId(),
197 UifConstants.PostMetadata.FILTERABLE_LOOKUP_CRITERIA);
198 Map<String, FilterableLookupCriteriaControlPostData> filterableLookupCriteria =
199 (Map<String, FilterableLookupCriteriaControlPostData>) componentPostData;
200
201
202 if (filterableLookupCriteria != null && filterableLookupCriteria.containsKey(propertyName)) {
203 FilterableLookupCriteriaControlPostData postData = filterableLookupCriteria.get(propertyName);
204 Class<? extends FilterableLookupCriteriaControl> controlClass = postData.getControlClass();
205 FilterableLookupCriteriaControl control = KRADUtils.createNewObjectFromClass(controlClass);
206
207 filteredSearchCriteria = control.filterSearchCriteria(propertyName, filteredSearchCriteria,
208 postData);
209 }
210
211
212 filteredSearchCriteria = lookupInputField.filterSearchCriteria(filteredSearchCriteria);
213
214
215 if (filteredSearchCriteria == null) {
216 return null;
217 }
218 }
219 }
220
221
222 Map<String, String> processedSearchCriteria = new HashMap<String, String>();
223 for (String fieldName : filteredSearchCriteria.keySet()) {
224 String fieldValue = filteredSearchCriteria.get(fieldName);
225
226
227 InputField inputField = criteriaFields.get(fieldName);
228 if (((inputField != null) && (inputField.getControl() instanceof HiddenControl)) || StringUtils.isBlank(
229 fieldValue)) {
230 continue;
231 }
232
233
234 boolean isSecure = KRADUtils.isSecure(fieldName, dataObjectClass);
235
236 if (StringUtils.endsWith(fieldValue, EncryptionService.ENCRYPTION_POST_PREFIX)) {
237 fieldValue = StringUtils.removeEnd(fieldValue, EncryptionService.ENCRYPTION_POST_PREFIX);
238 isSecure = true;
239 }
240
241
242 if (isSecure) {
243 try {
244 if (CoreApiServiceLocator.getEncryptionService().isEnabled()) {
245 fieldValue = getEncryptionService().decrypt(fieldValue);
246 }
247 } catch (GeneralSecurityException e) {
248 String message = "Data object class " + dataObjectClass + " property " + fieldName
249 + " should have been encrypted, but there was a problem decrypting it.";
250 LOG.error(message);
251
252 throw new RuntimeException(message, e);
253 }
254 }
255
256 processedSearchCriteria.put(fieldName, fieldValue);
257 }
258
259 return processedSearchCriteria;
260 }
261
262
263
264
265
266
267
268
269 protected List<String> identifyWildcardDisabledFields(LookupForm lookupForm, Map<String, String> searchCriteria) {
270 List<String> wildcardAsLiteralPropertyNames = new ArrayList<String>();
271
272 if (searchCriteria != null) {
273 Map<String, InputField> criteriaFields = new HashMap<String, InputField>();
274 if (lookupForm.getView() != null) {
275 criteriaFields = getCriteriaFieldsForValidation((LookupView) lookupForm.getView(), lookupForm);
276 }
277
278 for (String fieldName : searchCriteria.keySet()) {
279 InputField inputField = criteriaFields.get(fieldName);
280 if ((inputField == null) || !(inputField instanceof LookupInputField)) {
281 continue;
282 }
283
284 if ((LookupInputField.class.isAssignableFrom(inputField.getClass())) && (((LookupInputField) inputField)
285 .isDisableWildcardsAndOperators())) {
286 wildcardAsLiteralPropertyNames.add(fieldName);
287 }
288 }
289 }
290
291 return wildcardAsLiteralPropertyNames;
292 }
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309 protected boolean validateSearchParameters(LookupForm form, Map<String, String> searchCriteria) {
310 boolean valid = true;
311
312 if (searchCriteria == null) {
313 return valid;
314 }
315
316
317
318
319
320
321
322 if (form.getViewPostMetadata() == null) {
323 return valid;
324 }
325
326 Set<String> unprocessedSearchCriteria = new HashSet<String>(searchCriteria.keySet());
327 for (Map.Entry<String, Map<String, Object>> lookupCriteria : form.getViewPostMetadata().getLookupCriteria()
328 .entrySet()) {
329 String propertyName = lookupCriteria.getKey();
330 Map<String, Object> lookupCriteriaAttributes = lookupCriteria.getValue();
331
332 unprocessedSearchCriteria.remove(propertyName);
333
334 if (isCriteriaRequired(lookupCriteriaAttributes) && StringUtils.isBlank(searchCriteria.get(propertyName))) {
335 GlobalVariables.getMessageMap().putError(propertyName, RiceKeyConstants.ERROR_REQUIRED,
336 getCriteriaLabel(form, (String) lookupCriteriaAttributes.get(
337 UifConstants.LookupCriteriaPostMetadata.COMPONENT_ID)));
338 }
339
340 ValidCharactersConstraint constraint = getSearchCriteriaConstraint(lookupCriteriaAttributes);
341 if (constraint != null) {
342 validateSearchParameterConstraint(form, propertyName, lookupCriteriaAttributes, searchCriteria.get(
343 propertyName), constraint);
344 }
345
346 if (searchCriteria.containsKey(propertyName)) {
347 validateSearchParameterWildcardAndOperators(form, propertyName, lookupCriteriaAttributes,
348 searchCriteria.get(propertyName));
349 }
350 }
351
352
353 for (String readOnlyItem : form.getReadOnlyFieldsList()) {
354 unprocessedSearchCriteria.remove(readOnlyItem);
355 }
356
357 if (!unprocessedSearchCriteria.isEmpty()) {
358 throw new RuntimeException(
359 "Invalid search value sent for property name(s): " + unprocessedSearchCriteria.toString());
360 }
361
362 if (GlobalVariables.getMessageMap().hasErrors()) {
363 valid = false;
364 }
365
366 return valid;
367 }
368
369
370
371
372
373
374
375
376
377 protected void validateSearchParameterWildcardAndOperators(LookupForm form, String propertyName,
378 Map<String, Object> lookupCriteriaAttributes, String searchPropertyValue) {
379 if (StringUtils.isBlank(searchPropertyValue)) {
380 return;
381 }
382
383
384 boolean found = false;
385 for (SearchOperator op : SearchOperator.QUERY_CHARACTERS) {
386 String queryCharacter = op.op();
387
388 if (searchPropertyValue.contains(queryCharacter)) {
389 found = true;
390 }
391 }
392
393
394 if (!found) {
395 return;
396 }
397
398 if (isCriteriaWildcardDisabled(lookupCriteriaAttributes)) {
399 Class<?> propertyType = ObjectPropertyUtils.getPropertyType(getDataObjectClass(), propertyName);
400
401 if (TypeUtils.isIntegralClass(propertyType) || TypeUtils.isDecimalClass(propertyType) ||
402 TypeUtils.isTemporalClass(propertyType)) {
403 GlobalVariables.getMessageMap().putError(propertyName,
404 RiceKeyConstants.ERROR_WILDCARDS_AND_OPERATORS_NOT_ALLOWED_ON_FIELD, getCriteriaLabel(form, (String) lookupCriteriaAttributes.get(
405 UifConstants.LookupCriteriaPostMetadata.COMPONENT_ID)));
406 } else if (TypeUtils.isStringClass(propertyType)) {
407 GlobalVariables.getMessageMap().putInfo(propertyName,
408 RiceKeyConstants.INFO_WILDCARDS_AND_OPERATORS_TREATED_LITERALLY, getCriteriaLabel(form, (String) lookupCriteriaAttributes.get(
409 UifConstants.LookupCriteriaPostMetadata.COMPONENT_ID)));
410 }
411 } else if (isCriteriaSecure(lookupCriteriaAttributes)) {
412 GlobalVariables.getMessageMap().putError(propertyName, RiceKeyConstants.ERROR_SECURE_FIELD,
413 getCriteriaLabel(form, (String) lookupCriteriaAttributes.get(
414 UifConstants.LookupCriteriaPostMetadata.COMPONENT_ID)));
415 }
416 }
417
418
419
420
421
422
423
424
425
426
427 protected void validateSearchParameterConstraint(LookupForm form, String propertyName,
428 Map<String, Object> lookupCriteriaAttributes, String searchPropertyValue,
429 ValidCharactersConstraint validCharactersConstraint) {
430 if (StringUtils.isBlank(searchPropertyValue)) {
431 return;
432 }
433
434 Matcher matcher = Pattern.compile(validCharactersConstraint.getValue()).matcher(searchPropertyValue);
435 if (!matcher.find()) {
436 String[] prefixParams = {getCriteriaLabel(form, (String) lookupCriteriaAttributes.get(
437 UifConstants.LookupCriteriaPostMetadata.COMPONENT_ID))};
438 ErrorMessage errorMessage = new ErrorMessage(validCharactersConstraint.getMessageKey(),
439 validCharactersConstraint.getValidationMessageParamsArray());
440 errorMessage.setMessagePrefixKey(UifConstants.Messages.PROPERTY_NAME_PREFIX);
441 errorMessage.setMessagePrefixParameters(prefixParams);
442 GlobalVariables.getMessageMap().putError(propertyName, errorMessage);
443 }
444 }
445
446
447
448
449
450
451
452
453 protected String getCriteriaLabel(LookupForm form, String componentId) {
454 return (String) form.getViewPostMetadata().getComponentPostData(componentId, UifConstants.PostMetadata.LABEL);
455 }
456
457
458
459
460
461
462
463 protected boolean isCriteriaWildcardDisabled(Map lookupCriteria) {
464 return BooleanUtils.isTrue((Boolean) lookupCriteria.get(UifConstants.LookupCriteriaPostMetadata.DISABLE_WILDCARDS_AND_OPERATORS));
465 }
466
467
468
469
470
471
472
473 protected boolean isCriteriaRequired(Map lookupCriteria) {
474 return BooleanUtils.isTrue((Boolean) lookupCriteria.get(UifConstants.LookupCriteriaPostMetadata.REQUIRED));
475 }
476
477
478
479
480
481
482
483 protected boolean isCriteriaSecure(Map lookupCriteria) {
484 return BooleanUtils.isTrue((Boolean) lookupCriteria.get(UifConstants.LookupCriteriaPostMetadata.SECURE_VALUE));
485 }
486
487
488
489
490
491
492
493 protected ValidCharactersConstraint getSearchCriteriaConstraint(Map lookupCriteria) {
494 return (ValidCharactersConstraint) lookupCriteria.get(
495 UifConstants.LookupCriteriaPostMetadata.VALID_CHARACTERS_CONSTRAINT);
496 }
497
498
499
500
501
502
503
504
505
506
507
508
509 protected void generateLookupResultsMessages(Map<String, String> searchCriteria, Collection<?> searchResults,
510 boolean bounded, Integer searchResultsLimit) {
511 MessageMap messageMap = GlobalVariables.getMessageMap();
512
513 Long searchResultsSize = Long.valueOf(0);
514 if (searchResults instanceof CollectionIncomplete
515 && ((CollectionIncomplete<?>) searchResults).getActualSizeIfTruncated() > 0) {
516 searchResultsSize = ((CollectionIncomplete<?>) searchResults).getActualSizeIfTruncated();
517 } else if (searchResults != null) {
518 searchResultsSize = Long.valueOf(searchResults.size());
519 }
520
521 if (searchResultsSize == 0) {
522 messageMap.putInfoForSectionId(UifConstants.MessageKeys.LOOKUP_RESULT_MESSAGES,
523 RiceKeyConstants.INFO_LOOKUP_RESULTS_NONE_FOUND);
524 } else if (searchResultsSize == 1) {
525 messageMap.putInfoForSectionId(UifConstants.MessageKeys.LOOKUP_RESULT_MESSAGES,
526 RiceKeyConstants.INFO_LOOKUP_RESULTS_DISPLAY_ONE);
527 } else if (searchResultsSize > 1) {
528 boolean resultsExceedsLimit =
529 bounded && (searchResultsLimit != null) && (searchResultsSize > searchResultsLimit);
530
531 if (resultsExceedsLimit) {
532 messageMap.putInfoForSectionId(UifConstants.MessageKeys.LOOKUP_RESULT_MESSAGES,
533 RiceKeyConstants.INFO_LOOKUP_RESULTS_EXCEEDS_LIMIT, searchResultsSize.toString(),
534 searchResultsLimit.toString());
535 }
536 }
537
538 Boolean usingPrimaryKey = getLookupService().allPrimaryKeyValuesPresentAndNotWildcard(getDataObjectClass(),
539 searchCriteria);
540
541 if (usingPrimaryKey) {
542 List<String> pkNames = getLegacyDataAdapter().listPrimaryKeyFieldNames(getDataObjectClass());
543
544 List<String> pkLabels = new ArrayList<String>();
545 for (String pkName : pkNames) {
546 pkLabels.add(getDataDictionaryService().getAttributeLabel(getDataObjectClass(), pkName));
547 }
548
549 messageMap.putInfoForSectionId(UifConstants.MessageKeys.LOOKUP_RESULT_MESSAGES,
550 RiceKeyConstants.INFO_LOOKUP_RESULTS_USING_PRIMARY_KEY, StringUtils.join(pkLabels, ","));
551 }
552 }
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567 protected void sortSearchResults(LookupForm form, List<?> searchResults) {
568 List<String> defaultSortColumns = null;
569 boolean defaultSortAscending = true;
570
571 if (form.getView() != null) {
572 defaultSortColumns = ((LookupView) form.getView()).getDefaultSortAttributeNames();
573 defaultSortAscending = ((LookupView) form.getView()).isDefaultSortAscending();
574 }
575
576 boolean hasExpression = false;
577 if (defaultSortColumns != null) {
578 for (String sortColumn : defaultSortColumns) {
579 if (sortColumn == null) {
580 hasExpression = true;
581 }
582 }
583 }
584
585 if (hasExpression) {
586 defaultSortColumns = null;
587 }
588
589 if ((defaultSortColumns != null) && (!defaultSortColumns.isEmpty())) {
590 BeanPropertyComparator comparator = new BeanPropertyComparator(defaultSortColumns, true);
591 if (defaultSortAscending) {
592 Collections.sort(searchResults, comparator);
593 } else {
594 Collections.sort(searchResults, Collections.reverseOrder(comparator));
595 }
596 }
597 }
598
599
600
601
602
603
604
605
606
607
608
609 protected Collection<?> getSearchResults(Map<String, String> searchCriteria,
610 List<String> wildcardAsLiteralSearchCriteria, boolean unbounded, Integer searchResultsLimit) {
611
612 try {
613 if (LookupUtils.hasExternalBusinessObjectProperty(getDataObjectClass(), searchCriteria)) {
614 searchCriteria = LookupUtils.adjustCriteriaForNestedEBOs(getDataObjectClass(),
615 searchCriteria, unbounded);
616
617 if (LOG.isDebugEnabled()) {
618 LOG.debug("Passing these results into the lookup service: " + searchCriteria);
619 }
620 }
621 } catch (IllegalAccessException e) {
622 throw new RuntimeException("Error trying to check for nested external business objects", e);
623 } catch (InstantiationException e1) {
624 throw new RuntimeException("Error trying to check for nested external business objects", e1);
625 }
626
627
628 return executeSearch(searchCriteria, wildcardAsLiteralSearchCriteria, !unbounded, searchResultsLimit);
629 }
630
631
632
633
634
635
636
637
638
639
640 protected List<?> getSearchResultsForEBO(Map<String, String> searchCriteria, boolean unbounded) {
641 ModuleService eboModuleService = KRADServiceLocatorWeb.getKualiModuleService().getResponsibleModuleService(
642 getDataObjectClass());
643
644 BusinessObjectEntry ddEntry = eboModuleService.getExternalizableBusinessObjectDictionaryEntry(
645 getDataObjectClass());
646
647 Map<String, String> filteredFieldValues = new HashMap<String, String>();
648 for (String fieldName : searchCriteria.keySet()) {
649 if (ddEntry.getAttributeNames().contains(fieldName)) {
650 filteredFieldValues.put(fieldName, searchCriteria.get(fieldName));
651 }
652 }
653
654 Map<String, Object> translatedValues = KRADUtils.coerceRequestParameterTypes(
655 (Class<? extends ExternalizableBusinessObject>) getDataObjectClass(), filteredFieldValues);
656
657 List<?> searchResults = eboModuleService.getExternalizableBusinessObjectsListForLookup(
658 (Class<? extends ExternalizableBusinessObject>) getDataObjectClass(), (Map) translatedValues,
659 unbounded);
660
661 return searchResults;
662 }
663
664
665
666
667 @Override
668 public Map<String, String> performClear(LookupForm form, Map<String, String> lookupCriteria) {
669 Map<String, String> clearedLookupCriteria = new HashMap<String, String>();
670
671 Map<String, InputField> criteriaFieldMap = new HashMap<String, InputField>();
672 if (form.getView() != null) {
673 criteriaFieldMap = getCriteriaFieldsForValidation((LookupView) form.getView(), form);
674 }
675
676
677 List<String> readOnlyFieldsList = form.getReadOnlyFieldsList();
678
679 for (Map.Entry<String, String> searchKeyValue : lookupCriteria.entrySet()) {
680 String searchPropertyName = searchKeyValue.getKey();
681 String searchPropertyValue = searchKeyValue.getValue();
682
683 InputField inputField = criteriaFieldMap.get(searchPropertyName);
684
685 if (readOnlyFieldsList == null || !readOnlyFieldsList.contains(searchPropertyName)) {
686 if (inputField != null && inputField.getDefaultValue() != null) {
687 searchPropertyValue = inputField.getDefaultValue().toString();
688 } else {
689 searchPropertyValue = "";
690 }
691 }
692
693 clearedLookupCriteria.put(searchPropertyName, searchPropertyValue);
694 }
695
696 return clearedLookupCriteria;
697 }
698
699
700
701
702 @Override
703 public void buildReturnUrlForResult(Link returnLink, Object model) {
704 LookupForm lookupForm = (LookupForm) model;
705
706 Map<String, Object> returnLinkContext = returnLink.getContext();
707 LookupView lookupView = returnLinkContext == null ? null : (LookupView) returnLinkContext.get(
708 UifConstants.ContextVariableNames.VIEW);
709 Object dataObject = returnLinkContext == null ? null : returnLinkContext.get(
710 UifConstants.ContextVariableNames.LINE);
711
712
713 if ((dataObject == null) || (!isResultReturnable(dataObject))) {
714 returnLink.setRender(false);
715
716 return;
717 }
718
719 String dataReturnValue = "true";
720 if (lookupForm.isReturnByScript()) {
721 Map<String, String> translatedKeyValues = getTranslatedReturnKeyValues(lookupView, lookupForm, dataObject);
722
723 dataReturnValue = ScriptUtils.translateValue(translatedKeyValues);
724
725 returnLink.setHref("#");
726
727 String dialogId = lookupForm.getShowDialogId();
728 if (StringUtils.isNotBlank(dialogId)) {
729 returnLink.setHref(returnLink.getHref() + dialogId);
730 }
731 } else if (StringUtils.isBlank(returnLink.getHref())) {
732 String href = getReturnUrl(lookupView, lookupForm, dataObject);
733
734 if (StringUtils.isNotBlank(href)) {
735 returnLink.setHref(href);
736 } else {
737 returnLink.setRender(false);
738 return;
739 }
740
741 String target = lookupForm.getReturnTarget();
742
743 if (StringUtils.isNotBlank(target)) {
744 returnLink.setTarget(target);
745 }
746 }
747
748
749 returnLink.addDataAttribute(UifConstants.DataAttributes.RETURN, dataReturnValue);
750
751
752 if (StringUtils.isBlank(returnLink.getTitle())) {
753 String linkLabel = StringUtils.defaultIfBlank(getConfigurationService().getPropertyValueAsString(
754 KRADConstants.Lookup.TITLE_RETURN_URL_PREPENDTEXT_PROPERTY), StringUtils.EMPTY);
755
756 Map<String, String> returnKeyValues = getReturnKeyValues(lookupView, lookupForm, dataObject);
757
758 String title = KRADUtils.buildAttributeTitleString(linkLabel, getDataObjectClass(), returnKeyValues);
759 returnLink.setTitle(title);
760 }
761 }
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776 protected boolean isResultReturnable(Object dataObject) {
777 return true;
778 }
779
780
781
782
783
784
785
786
787
788
789
790 protected String getReturnUrl(LookupView lookupView, LookupForm lookupForm, Object dataObject) {
791 Properties props = getReturnUrlParameters(lookupView, lookupForm, dataObject);
792
793 String href = "";
794 if (StringUtils.isNotBlank(lookupForm.getReturnLocation())) {
795 href = UrlFactory.parameterizeUrl(lookupForm.getReturnLocation(), props);
796 }
797
798 return href;
799 }
800
801
802
803
804
805
806
807
808
809
810 protected Properties getReturnUrlParameters(LookupView lookupView, LookupForm lookupForm, Object dataObject) {
811 Properties props = new Properties();
812 props.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, KRADConstants.RETURN_METHOD_TO_CALL);
813
814 if (StringUtils.isNotBlank(lookupForm.getReturnFormKey())) {
815 props.put(UifParameters.FORM_KEY, lookupForm.getReturnFormKey());
816 }
817
818 props.put(KRADConstants.REFRESH_CALLER, lookupView.getId());
819 props.put(KRADConstants.REFRESH_DATA_OBJECT_CLASS, getDataObjectClass().getName());
820
821 if (StringUtils.isNotBlank(lookupForm.getReferencesToRefresh())) {
822 props.put(UifParameters.REFERENCES_TO_REFRESH, lookupForm.getReferencesToRefresh());
823 }
824
825
826 String selectedCollectionId = null;
827 String selectedCollectionPath = null;
828 String selectedLineIndex = null;
829 if (lookupForm.getInitialRequestParameters() != null) {
830 String[] ids = lookupForm.getInitialRequestParameters().get(UifParameters.SELECTED_COLLECTION_ID);
831 if (ids != null && ids.length > 0) {
832 selectedCollectionId = ids[0];
833 }
834
835 String[] paths = lookupForm.getInitialRequestParameters().get(UifParameters.SELECTED_COLLECTION_PATH);
836 if (paths != null && paths.length > 0) {
837 selectedCollectionPath = paths[0];
838 }
839
840 String[] lines = lookupForm.getInitialRequestParameters().get(UifParameters.SELECTED_LINE_INDEX);
841 if (lines != null && lines.length > 0) {
842 selectedLineIndex = lines[0];
843 }
844 }
845
846 if (StringUtils.isNotBlank(selectedLineIndex)) {
847 props.put(UifPropertyPaths.ACTION_PARAMETERS + "[" + UifParameters.SELECTED_LINE_INDEX + "]",
848 selectedLineIndex);
849 }
850
851 if (StringUtils.isNotBlank(selectedCollectionId)) {
852 props.put(UifPropertyPaths.ACTION_PARAMETERS + "[" + UifParameters.SELECTED_COLLECTION_ID + "]",
853 selectedCollectionId);
854 }
855
856 if (StringUtils.isNotBlank(selectedCollectionPath)) {
857 props.put(UifPropertyPaths.ACTION_PARAMETERS + "[" + UifParameters.SELECTED_COLLECTION_PATH + "]",
858 selectedCollectionPath);
859 }
860
861 String dialogId = lookupForm.getShowDialogId();
862 if (StringUtils.isNotBlank(dialogId)) {
863 props.put(UifPropertyPaths.ACTION_PARAMETERS + "[" + UifParameters.DIALOG_ID + "]", dialogId);
864 }
865
866 if (StringUtils.isNotBlank(lookupForm.getQuickfinderId())) {
867 props.put(UifParameters.QUICKFINDER_ID, lookupForm.getQuickfinderId());
868 }
869
870 Map<String, String> returnKeyValues = getTranslatedReturnKeyValues(lookupView, lookupForm, dataObject);
871 props.putAll(returnKeyValues);
872
873 return props;
874 }
875
876
877
878
879
880
881
882
883
884
885 protected Map<String, String> getTranslatedReturnKeyValues(LookupView lookupView, LookupForm lookupForm,
886 Object dataObject) {
887 Map<String, String> translatedKeyValues = new HashMap<String, String>();
888
889 Map<String, String> returnKeyValues = getReturnKeyValues(lookupView, lookupForm, dataObject);
890
891 for (String returnKey : returnKeyValues.keySet()) {
892 String returnValue = returnKeyValues.get(returnKey);
893
894
895 if (lookupForm.getFieldConversions().containsKey(returnKey)) {
896 returnKey = lookupForm.getFieldConversions().get(returnKey);
897 }
898
899 translatedKeyValues.put(returnKey, returnValue);
900 }
901
902 return translatedKeyValues;
903 }
904
905
906
907
908
909
910
911
912
913 protected Map<String, String> getReturnKeyValues(LookupView lookupView, LookupForm lookupForm, Object dataObject) {
914 List<String> returnKeys;
915
916 if (lookupForm.getFieldConversions() != null && !lookupForm.getFieldConversions().isEmpty()) {
917 returnKeys = new ArrayList<String>(lookupForm.getFieldConversions().keySet());
918 } else {
919 returnKeys = getLegacyDataAdapter().listPrimaryKeyFieldNames(getDataObjectClass());
920 }
921
922 List<String> secureReturnKeys = lookupView.getAdditionalSecurePropertyNames();
923
924 return KRADUtils.getPropertyKeyValuesFromDataObject(returnKeys, secureReturnKeys, dataObject);
925 }
926
927
928
929
930 @Override
931 public void buildMaintenanceActionLink(Link actionLink, Object model, String maintenanceMethodToCall) {
932 LookupForm lookupForm = (LookupForm) model;
933
934 Map<String, Object> actionLinkContext = actionLink.getContext();
935 Object dataObject = actionLinkContext == null ? null : actionLinkContext.get(
936 UifConstants.ContextVariableNames.LINE);
937
938 List<String> pkNames = getLegacyDataAdapter().listPrimaryKeyFieldNames(getDataObjectClass());
939
940
941 if (StringUtils.isBlank(actionLink.getHref())) {
942 String href = getMaintenanceActionUrl(lookupForm, dataObject, maintenanceMethodToCall, pkNames);
943 if (StringUtils.isBlank(href)) {
944 actionLink.setRender(false);
945
946 return;
947 }
948
949 actionLink.setHref(href);
950 }
951
952
953 if (StringUtils.isBlank(actionLink.getTitle())) {
954 List<String> linkLabels = new ArrayList<String>();
955
956
957 String linkText = actionLink.getLinkText();
958
959
960 if (StringUtils.isNotBlank(linkText)) {
961 linkLabels.add(linkText);
962 }
963
964
965 DataObjectEntry dataObjectEntry = getDataDictionaryService().getDataDictionary().getDataObjectEntry(
966 getDataObjectClass().getName());
967 String dataObjectLabel = dataObjectEntry != null ? dataObjectEntry.getObjectLabel() : null;
968
969
970 if (StringUtils.isNotBlank(dataObjectLabel)) {
971 linkLabels.add(dataObjectLabel);
972 }
973
974
975 String titleActionUrlPrependText = getConfigurationService().getPropertyValueAsString(
976 KRADConstants.Lookup.TITLE_ACTION_URL_PREPENDTEXT_PROPERTY);
977
978
979 Map<String, String> primaryKeyValues = KRADUtils.getPropertyKeyValuesFromDataObject(pkNames, dataObject);
980
981
982 if (StringUtils.isNotBlank(titleActionUrlPrependText) && !primaryKeyValues.isEmpty()) {
983 linkLabels.add(titleActionUrlPrependText);
984 }
985
986 String linkLabel = StringUtils.defaultIfBlank(StringUtils.join(linkLabels, " "), StringUtils.EMPTY);
987 String title = KRADUtils.buildAttributeTitleString(linkLabel, getDataObjectClass(), primaryKeyValues);
988 actionLink.setTitle(title);
989 }
990 }
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005 protected String getMaintenanceActionUrl(LookupForm lookupForm, Object dataObject, String methodToCall,
1006 List<String> pkNames) {
1007 LookupView lookupView = (LookupView) lookupForm.getView();
1008
1009 Properties props = new Properties();
1010 props.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, methodToCall);
1011
1012 Map<String, String> primaryKeyValues = KRADUtils.getPropertyKeyValuesFromDataObject(pkNames, dataObject);
1013 for (String primaryKey : primaryKeyValues.keySet()) {
1014 String primaryKeyValue = primaryKeyValues.get(primaryKey);
1015
1016 props.put(primaryKey, primaryKeyValue);
1017 }
1018
1019 if (StringUtils.isNotBlank(lookupForm.getReturnLocation())) {
1020 props.put(KRADConstants.RETURN_LOCATION_PARAMETER, lookupForm.getReturnLocation());
1021 }
1022
1023 props.put(UifParameters.DATA_OBJECT_CLASS_NAME, lookupForm.getDataObjectClassName());
1024 props.put(UifParameters.VIEW_TYPE_NAME, UifConstants.ViewType.MAINTENANCE.name());
1025
1026 String maintenanceMapping = KRADConstants.Maintenance.REQUEST_MAPPING_MAINTENANCE;
1027 if (lookupView != null && StringUtils.isNotBlank(lookupView.getMaintenanceUrlMapping())) {
1028 maintenanceMapping = lookupView.getMaintenanceUrlMapping();
1029 }
1030
1031 return UrlFactory.parameterizeUrl(maintenanceMapping, props);
1032 }
1033
1034
1035
1036
1037 @Override
1038 public void buildMultiValueSelectField(InputField selectField, Object model) {
1039 LookupForm lookupForm = (LookupForm) model;
1040
1041 Map<String, Object> selectFieldContext = selectField.getContext();
1042 Object lineDataObject = selectFieldContext == null ? null : selectFieldContext.get(
1043 UifConstants.ContextVariableNames.LINE);
1044 if (lineDataObject == null) {
1045 throw new RuntimeException("Unable to get data object for line from component: " + selectField.getId());
1046 }
1047
1048 Control selectControl = selectField.getControl();
1049 if ((selectControl != null) && (selectControl instanceof ValueConfiguredControl)) {
1050
1051 List<String> fromFieldNames = new ArrayList<String>(lookupForm.getFieldConversions().keySet());
1052
1053 fromFieldNames = new ArrayList<String>(KRADUtils.getPropertyKeyValuesFromDataObject(fromFieldNames,
1054 lineDataObject).keySet());
1055
1056 Collections.sort(fromFieldNames);
1057 lookupForm.setMultiValueReturnFields(fromFieldNames);
1058 String lineIdentifier = "";
1059 for (String fromFieldName : fromFieldNames) {
1060 Object fromFieldValue = ObjectPropertyUtils.getPropertyValue(lineDataObject, fromFieldName);
1061
1062 if (fromFieldValue != null) {
1063 lineIdentifier += fromFieldValue;
1064 }
1065
1066 lineIdentifier += ":";
1067 }
1068 lineIdentifier = StringUtils.removeEnd(lineIdentifier, ":");
1069
1070 ((ValueConfiguredControl) selectControl).setValue(lineIdentifier);
1071 }
1072 }
1073
1074
1075
1076
1077 @Override
1078 public boolean allowsMaintenanceNewOrCopyAction() {
1079 boolean allowsNewOrCopy = false;
1080
1081 String maintDocTypeName = getMaintenanceDocumentTypeName();
1082 if (StringUtils.isNotBlank(maintDocTypeName)) {
1083 allowsNewOrCopy = getDataObjectAuthorizationService().canCreate(getDataObjectClass(),
1084 GlobalVariables.getUserSession().getPerson(), maintDocTypeName);
1085 }
1086
1087 return allowsNewOrCopy;
1088 }
1089
1090
1091
1092
1093 @Override
1094 public boolean allowsMaintenanceEditAction(Object dataObject) {
1095 boolean allowsEdit = false;
1096
1097 String maintDocTypeName = getMaintenanceDocumentTypeName();
1098 if (StringUtils.isNotBlank(maintDocTypeName)) {
1099 allowsEdit = getDataObjectAuthorizationService().canMaintain(dataObject,
1100 GlobalVariables.getUserSession().getPerson(), maintDocTypeName);
1101 }
1102
1103 return allowsEdit;
1104 }
1105
1106
1107
1108
1109 @Override
1110 public boolean allowsMaintenanceDeleteAction(Object dataObject) {
1111 boolean allowsMaintain = false;
1112
1113 String maintDocTypeName = getMaintenanceDocumentTypeName();
1114 if (StringUtils.isNotBlank(maintDocTypeName)) {
1115 allowsMaintain = getDataObjectAuthorizationService().canMaintain(dataObject,
1116 GlobalVariables.getUserSession().getPerson(), maintDocTypeName);
1117 }
1118
1119 boolean allowsDelete = getDocumentDictionaryService().getAllowsRecordDeletion(getDataObjectClass());
1120
1121 return allowsDelete && allowsMaintain;
1122 }
1123
1124
1125
1126
1127
1128
1129 protected String getMaintenanceDocumentTypeName() {
1130 DocumentDictionaryService dd = getDocumentDictionaryService();
1131
1132 return dd.getMaintenanceDocumentTypeName(getDataObjectClass());
1133 }
1134
1135
1136
1137
1138
1139
1140
1141
1142 protected Map<String, InputField> getCriteriaFieldsForValidation(LookupView lookupView, LookupForm form) {
1143 Map<String, InputField> criteriaFieldMap = new HashMap<String, InputField>();
1144
1145 if (lookupView.getCriteriaFields() == null) {
1146 return criteriaFieldMap;
1147 }
1148
1149 List<InputField> fields = null;
1150 if (lookupView.getCriteriaGroup().getItems().size() > 0) {
1151 fields = ComponentUtils.getNestedContainerComponents(lookupView.getCriteriaGroup(), InputField.class);
1152 } else if (lookupView.getCriteriaFields().size() > 0) {
1153
1154
1155 fields = ComponentUtils.getComponentsOfType(lookupView.getCriteriaFields(), InputField.class);
1156 } else {
1157 fields = new ArrayList<InputField>();
1158 }
1159 for (InputField field : fields) {
1160 criteriaFieldMap.put(field.getPropertyName(), field);
1161 }
1162
1163 return criteriaFieldMap;
1164 }
1165
1166
1167
1168
1169 @Override
1170 public Class<?> getDataObjectClass() {
1171 return this.dataObjectClass;
1172 }
1173
1174
1175
1176
1177 @Override
1178 public void setDataObjectClass(Class<?> dataObjectClass) {
1179 this.dataObjectClass = dataObjectClass;
1180 }
1181
1182 protected DataObjectAuthorizationService getDataObjectAuthorizationService() {
1183 if (dataObjectAuthorizationService == null) {
1184 this.dataObjectAuthorizationService = KRADServiceLocatorWeb.getDataObjectAuthorizationService();
1185 }
1186 return dataObjectAuthorizationService;
1187 }
1188
1189 public void setDataObjectAuthorizationService(DataObjectAuthorizationService dataObjectAuthorizationService) {
1190 this.dataObjectAuthorizationService = dataObjectAuthorizationService;
1191 }
1192
1193 public DocumentDictionaryService getDocumentDictionaryService() {
1194 if (documentDictionaryService == null) {
1195 documentDictionaryService = KRADServiceLocatorWeb.getDocumentDictionaryService();
1196 }
1197 return documentDictionaryService;
1198 }
1199
1200 public void setDocumentDictionaryService(DocumentDictionaryService documentDictionaryService) {
1201 this.documentDictionaryService = documentDictionaryService;
1202 }
1203
1204 protected LookupService getLookupService() {
1205 if (lookupService == null) {
1206 this.lookupService = KRADServiceLocatorWeb.getLookupService();
1207 }
1208 return lookupService;
1209 }
1210
1211 public void setLookupService(LookupService lookupService) {
1212 this.lookupService = lookupService;
1213 }
1214
1215 protected EncryptionService getEncryptionService() {
1216 if (encryptionService == null) {
1217 this.encryptionService = CoreApiServiceLocator.getEncryptionService();
1218 }
1219 return encryptionService;
1220 }
1221
1222 public void setEncryptionService(EncryptionService encryptionService) {
1223 this.encryptionService = encryptionService;
1224 }
1225
1226 }