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.BooleanUtils;
20 import org.apache.commons.lang.StringUtils;
21 import org.kuali.rice.core.api.CoreApiServiceLocator;
22 import org.kuali.rice.core.api.config.property.ConfigurationService;
23 import org.kuali.rice.core.api.encryption.EncryptionService;
24 import org.kuali.rice.core.api.search.SearchOperator;
25 import org.kuali.rice.core.api.util.RiceKeyConstants;
26 import org.kuali.rice.core.api.util.type.TypeUtils;
27 import org.kuali.rice.kim.api.identity.Person;
28 import org.kuali.rice.krad.bo.ExternalizableBusinessObject;
29 import org.kuali.rice.krad.datadictionary.BusinessObjectEntry;
30 import org.kuali.rice.krad.datadictionary.RelationshipDefinition;
31 import org.kuali.rice.krad.service.DataObjectAuthorizationService;
32 import org.kuali.rice.krad.service.DataObjectMetaDataService;
33 import org.kuali.rice.krad.service.DocumentDictionaryService;
34 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
35 import org.kuali.rice.krad.service.LookupService;
36 import org.kuali.rice.krad.service.ModuleService;
37 import org.kuali.rice.krad.uif.UifConstants;
38 import org.kuali.rice.krad.uif.UifParameters;
39 import org.kuali.rice.krad.uif.UifPropertyPaths;
40 import org.kuali.rice.krad.uif.control.Control;
41 import org.kuali.rice.krad.uif.control.HiddenControl;
42 import org.kuali.rice.krad.uif.control.ValueConfiguredControl;
43 import org.kuali.rice.krad.uif.element.Action;
44 import org.kuali.rice.krad.uif.field.InputField;
45 import org.kuali.rice.krad.uif.field.LookupInputField;
46 import org.kuali.rice.krad.uif.service.impl.ViewHelperServiceImpl;
47 import org.kuali.rice.krad.uif.util.ComponentUtils;
48 import org.kuali.rice.krad.uif.util.LookupInquiryUtils;
49 import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
50 import org.kuali.rice.krad.uif.view.LookupView;
51 import org.kuali.rice.krad.uif.view.View;
52 import org.kuali.rice.krad.util.BeanPropertyComparator;
53 import org.kuali.rice.krad.util.GlobalVariables;
54 import org.kuali.rice.krad.util.KRADConstants;
55 import org.kuali.rice.krad.util.KRADUtils;
56 import org.kuali.rice.krad.util.ObjectUtils;
57 import org.kuali.rice.krad.util.UrlFactory;
58 import org.kuali.rice.krad.web.form.LookupForm;
59
60 import java.security.GeneralSecurityException;
61 import java.util.ArrayList;
62 import java.util.Collection;
63 import java.util.Collections;
64 import java.util.HashMap;
65 import java.util.List;
66 import java.util.Map;
67 import java.util.Properties;
68
69
70
71
72
73
74 public class LookupableImpl extends ViewHelperServiceImpl implements Lookupable {
75 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(LookupableImpl.class);
76
77 private Class<?> dataObjectClass;
78
79 private transient ConfigurationService configurationService;
80 private transient DataObjectAuthorizationService dataObjectAuthorizationService;
81 private transient DataObjectMetaDataService dataObjectMetaDataService;
82 private transient DocumentDictionaryService documentDictionaryService;
83 private transient LookupService lookupService;
84 private transient EncryptionService encryptionService;
85
86
87
88
89
90
91
92
93
94 @Override
95 public void performInitialization(View view, Object model) {
96 if (!LookupView.class.isAssignableFrom(view.getClass())) {
97 throw new IllegalArgumentException(
98 "View class '" + view.getClass() + " is not assignable from the '" + LookupView.class + "'");
99 }
100
101 LookupView lookupView = (LookupView) view;
102 setDataObjectClass(lookupView.getDataObjectClassName());
103
104 super.performInitialization(view, model);
105 }
106
107
108
109
110 @Override
111 public void initSuppressAction(LookupForm lookupForm) {
112 LookupViewAuthorizerBase lookupAuthorizer = (LookupViewAuthorizerBase) lookupForm.getView().getAuthorizer();
113 Person user = GlobalVariables.getUserSession().getPerson();
114 ((LookupView) lookupForm.getView()).setSuppressActions(!lookupAuthorizer.canInitiateDocument(lookupForm, user));
115 }
116
117
118
119
120 @Override
121 public Collection<?> performSearch(LookupForm form, Map<String, String> searchCriteria, boolean bounded) {
122 Collection<?> displayList;
123
124
125 displayList = getSearchResults(form, LookupUtils.forceUppercase(getDataObjectClass(), searchCriteria),
126 !bounded);
127
128
129 for (Object object : displayList) {
130 if (isResultReturnable(object)) {
131 form.setAtLeastOneRowReturnable(true);
132 }
133 }
134
135 return displayList;
136 }
137
138
139
140
141
142
143
144
145
146
147 protected List<?> getSearchResults(LookupForm form, Map<String, String> searchCriteria, boolean unbounded) {
148 List<?> searchResults;
149
150
151 Map<String, String> nonBlankSearchCriteria = processSearchCriteria(form, searchCriteria);
152
153
154
155 if (nonBlankSearchCriteria == null) {
156 return new ArrayList<Object>();
157 }
158
159
160 if (ExternalizableBusinessObject.class.isAssignableFrom(getDataObjectClass())) {
161 return getSearchResultsForEBO(nonBlankSearchCriteria, unbounded);
162 }
163
164
165
166 try {
167 Integer searchResultsLimit = null;
168 Boolean isUsingPrimaryKey = false;
169
170 if (!unbounded) {
171 searchResultsLimit = LookupUtils.getSearchResultsLimit(getDataObjectClass(), form);
172 }
173
174 if (LookupUtils.hasExternalBusinessObjectProperty(getDataObjectClass(), nonBlankSearchCriteria)) {
175 Map<String, String> eboSearchCriteria = adjustCriteriaForNestedEBOs(nonBlankSearchCriteria, unbounded);
176
177 if (LOG.isDebugEnabled()) {
178 LOG.debug("Passing these results into the lookup service: " + eboSearchCriteria);
179 }
180
181
182 searchResults = (List<?>) getLookupService().findCollectionBySearchHelper(getDataObjectClass(),
183 eboSearchCriteria, unbounded, searchResultsLimit);
184 isUsingPrimaryKey = getLookupService().allPrimaryKeyValuesPresentAndNotWildcard(getDataObjectClass(),
185 eboSearchCriteria);
186 } else {
187 searchResults = (List<?>) getLookupService().findCollectionBySearchHelper(getDataObjectClass(),
188 nonBlankSearchCriteria, unbounded, searchResultsLimit);
189 isUsingPrimaryKey = getLookupService().allPrimaryKeyValuesPresentAndNotWildcard(getDataObjectClass(),
190 nonBlankSearchCriteria);
191 }
192
193 List<String> pkLabels = new ArrayList<String>();
194 if (isUsingPrimaryKey) {
195 List<String> pkNames = getDataObjectMetaDataService().listPrimaryKeyFieldNames(getDataObjectClass());
196 for (String pkName : pkNames) {
197 pkLabels.add(getDataDictionaryService().getAttributeLabel(getDataObjectClass(), pkName));
198 }
199 }
200 Integer searchResultsSize = searchResults != null ? searchResults.size() : 0;
201 generateLookupResultsMessages(unbounded, isUsingPrimaryKey, searchResultsSize, searchResultsLimit,
202 pkLabels);
203
204 } catch (IllegalAccessException e) {
205 throw new RuntimeException("Error trying to perform search", e);
206 } catch (InstantiationException e1) {
207 throw new RuntimeException("Error trying to perform search", e1);
208 }
209
210 if (searchResults == null) {
211 searchResults = new ArrayList<Object>();
212 } else {
213 sortSearchResults(form, searchResults);
214 }
215
216 return searchResults;
217 }
218
219
220
221
222
223
224
225
226
227
228 private void generateLookupResultsMessages(boolean unbounded, boolean usingPrimaryKey, Integer searchResultsSize,
229 Integer searchResultsLimit, List<String> pkLabels) {
230
231 Boolean resultsExceedsLimit = !unbounded
232 && searchResultsLimit != null
233 && searchResultsSize > 0
234 && searchResultsSize > searchResultsLimit ? true : false;
235 String resultsPropertyName = "LookupResultMessages";
236
237 if (usingPrimaryKey) {
238 GlobalVariables.getMessageMap().putInfoForSectionId(resultsPropertyName,
239 RiceKeyConstants.INFO_LOOKUP_RESULTS_USING_PRIMARY_KEY, StringUtils.join(pkLabels, ","));
240 }
241 if (searchResultsSize == 0) {
242 GlobalVariables.getMessageMap().putInfoForSectionId(resultsPropertyName,
243 RiceKeyConstants.INFO_LOOKUP_RESULTS_NONE_FOUND);
244 } else if (searchResultsSize == 1) {
245 GlobalVariables.getMessageMap().putInfoForSectionId(resultsPropertyName,
246 RiceKeyConstants.INFO_LOOKUP_RESULTS_DISPLAY_ONE);
247 } else if (searchResultsSize > 1) {
248 if (!unbounded && resultsExceedsLimit) {
249 GlobalVariables.getMessageMap().putInfoForSectionId(resultsPropertyName,
250 RiceKeyConstants.INFO_LOOKUP_RESULTS_EXCEEDS_LIMIT, searchResultsSize.toString(),
251 searchResultsLimit.toString());
252 } else {
253 GlobalVariables.getMessageMap().putInfoForSectionId(resultsPropertyName,
254 RiceKeyConstants.INFO_LOOKUP_RESULTS_DISPLAY_ALL, searchResultsSize.toString());
255 }
256 }
257 }
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274 protected void sortSearchResults(LookupForm form, List<?> searchResults) {
275 List<String> defaultSortColumns = null;
276 boolean defaultSortAscending = true;
277
278
279 if (form.getPostedView() != null) {
280 defaultSortColumns = ((LookupView) form.getPostedView()).getDefaultSortAttributeNames();
281 defaultSortAscending = ((LookupView) form.getPostedView()).isDefaultSortAscending();
282 }
283
284 else if (form.getView() != null) {
285 defaultSortColumns = ((LookupView) form.getView()).getDefaultSortAttributeNames();
286 defaultSortAscending = ((LookupView) form.getView()).isDefaultSortAscending();
287 boolean hasExpression = false;
288 if (defaultSortColumns != null) {
289 for (String sortColumn : defaultSortColumns) {
290 if (sortColumn == null) {
291 hasExpression = true;
292 }
293 }
294 }
295
296 if (hasExpression) {
297 defaultSortColumns = null;
298 }
299 }
300
301 if ((defaultSortColumns != null) && (!defaultSortColumns.isEmpty())) {
302 BeanPropertyComparator comparator = new BeanPropertyComparator(defaultSortColumns, true);
303 if (defaultSortAscending) {
304 Collections.sort(searchResults, comparator);
305 } else {
306 Collections.sort(searchResults, Collections.reverseOrder(comparator));
307 }
308 }
309 }
310
311
312
313
314
315
316
317
318
319
320
321
322
323 protected Map<String, String> processSearchCriteria(LookupForm lookupForm, Map<String, String> searchCriteria) {
324 Map<String, InputField> criteriaFields = new HashMap<String, InputField>();
325 if (lookupForm.getPostedView() != null) {
326 criteriaFields = getCriteriaFieldsForValidation((LookupView) lookupForm.getPostedView(), lookupForm);
327 }
328
329 Map<String, String> filteredSearchCriteria = new HashMap<String, String>(searchCriteria);
330 for (String fieldName : searchCriteria.keySet()) {
331 InputField inputField = criteriaFields.get(fieldName);
332 if ((inputField == null) || !(inputField instanceof LookupInputField)) {
333 continue;
334 }
335
336 filteredSearchCriteria = ((LookupInputField) inputField).filterSearchCriteria(filteredSearchCriteria);
337 if (filteredSearchCriteria == null) {
338 return null;
339 }
340 }
341
342 Map<String, String> nonBlankSearchCriteria = new HashMap<String, String>();
343 for (String fieldName : filteredSearchCriteria.keySet()) {
344 String fieldValue = filteredSearchCriteria.get(fieldName);
345
346
347 InputField inputField = criteriaFields.get(fieldName);
348 if ((inputField != null) && (inputField.getControl() instanceof HiddenControl)) {
349 continue;
350 }
351
352
353 if (StringUtils.isNotBlank(fieldValue)) {
354 if (fieldValue.endsWith(EncryptionService.ENCRYPTION_POST_PREFIX)) {
355 String encryptedValue = StringUtils.removeEnd(fieldValue, EncryptionService.ENCRYPTION_POST_PREFIX);
356 try {
357 if (CoreApiServiceLocator.getEncryptionService().isEnabled()) {
358 fieldValue = getEncryptionService().decrypt(encryptedValue);
359 }
360 } catch (GeneralSecurityException e) {
361 LOG.error("Error decrypting value for business object class " + getDataObjectClass() +
362 " attribute " + fieldName, e);
363 throw new RuntimeException(
364 "Error decrypting value for business object class " + getDataObjectClass() +
365 " attribute " + fieldName, e);
366 }
367 }
368
369 nonBlankSearchCriteria.put(fieldName, fieldValue);
370 }
371 }
372
373 return nonBlankSearchCriteria;
374 }
375
376
377
378
379
380
381
382
383
384 protected List<?> getSearchResultsForEBO(Map<String, String> searchCriteria, boolean unbounded) {
385 ModuleService eboModuleService = KRADServiceLocatorWeb.getKualiModuleService().getResponsibleModuleService(
386 getDataObjectClass());
387 BusinessObjectEntry ddEntry = eboModuleService.getExternalizableBusinessObjectDictionaryEntry(
388 getDataObjectClass());
389
390 Map<String, String> filteredFieldValues = new HashMap<String, String>();
391 for (String fieldName : searchCriteria.keySet()) {
392 if (ddEntry.getAttributeNames().contains(fieldName)) {
393 filteredFieldValues.put(fieldName, searchCriteria.get(fieldName));
394 }
395 }
396
397 List<?> searchResults = eboModuleService.getExternalizableBusinessObjectsListForLookup(
398 (Class<? extends ExternalizableBusinessObject>) getDataObjectClass(), (Map) filteredFieldValues,
399 unbounded);
400
401 return searchResults;
402 }
403
404
405
406
407
408
409
410
411
412 protected Map<String, String> adjustCriteriaForNestedEBOs(Map<String, String> searchCriteria,
413 boolean unbounded) throws InstantiationException, IllegalAccessException {
414 if (LOG.isDebugEnabled()) {
415 LOG.debug("has EBO reference: " + getDataObjectClass());
416 LOG.debug("properties: " + searchCriteria);
417 }
418
419
420 Map<String, String> nonEboFieldValues = LookupUtils.removeExternalizableBusinessObjectFieldValues(
421 getDataObjectClass(), searchCriteria);
422 if (LOG.isDebugEnabled()) {
423 LOG.debug("Non EBO properties removed: " + nonEboFieldValues);
424 }
425
426
427 List<String> eboPropertyNames = LookupUtils.getExternalizableBusinessObjectProperties(getDataObjectClass(),
428 searchCriteria);
429 if (LOG.isDebugEnabled()) {
430 LOG.debug("EBO properties: " + eboPropertyNames);
431 }
432
433
434 for (String eboPropertyName : eboPropertyNames) {
435
436 Map<String, String> eboFieldValues = LookupUtils.getExternalizableBusinessObjectFieldValues(eboPropertyName,
437 searchCriteria);
438 if (LOG.isDebugEnabled()) {
439 LOG.debug("EBO properties for master EBO property: " + eboPropertyName);
440 LOG.debug("properties: " + eboFieldValues);
441 }
442
443
444 ModuleService eboModuleService = KRADServiceLocatorWeb.getKualiModuleService().getResponsibleModuleService(
445 LookupUtils.getExternalizableBusinessObjectClass(getDataObjectClass(), eboPropertyName));
446
447
448
449 List<?> eboResults = Collections.emptyList();
450 if (eboModuleService != null) {
451 eboResults = eboModuleService.getExternalizableBusinessObjectsListForLookup(
452 LookupUtils.getExternalizableBusinessObjectClass(getDataObjectClass(), eboPropertyName),
453 (Map) eboFieldValues, unbounded);
454 } else {
455 LOG.debug("EBO ModuleService is null: " + eboPropertyName);
456 }
457
458
459
460
461
462 Class<?> eboParentClass;
463 String eboParentPropertyName;
464 if (ObjectUtils.isNestedAttribute(eboPropertyName)) {
465 eboParentPropertyName = StringUtils.substringBeforeLast(eboPropertyName, ".");
466 try {
467 eboParentClass = PropertyUtils.getPropertyType(getDataObjectClass().newInstance(),
468 eboParentPropertyName);
469 } catch (Exception ex) {
470 throw new RuntimeException(
471 "Unable to create an instance of the business object class: " + getDataObjectClass()
472 .getName(), ex);
473 }
474 } else {
475 eboParentClass = getDataObjectClass();
476 eboParentPropertyName = null;
477 }
478
479 if (LOG.isDebugEnabled()) {
480 LOG.debug("determined EBO parent class/property name: " + eboParentClass + "/" + eboParentPropertyName);
481 }
482
483
484
485
486
487 RelationshipDefinition rd = getDataObjectMetaDataService().getDictionaryRelationship(eboParentClass,
488 eboPropertyName);
489 if (LOG.isDebugEnabled()) {
490 LOG.debug("Obtained RelationshipDefinition for " + eboPropertyName);
491 LOG.debug(rd);
492 }
493
494
495
496
497
498
499
500 if (ObjectUtils.isNotNull(rd)) {
501 if (rd.getPrimitiveAttributes().size() > 1) {
502 throw new RuntimeException(
503 "EBO Links don't work for relationships with multiple-field primary keys.");
504 }
505 String boProperty = rd.getPrimitiveAttributes().get(0).getSourceName();
506 String eboProperty = rd.getPrimitiveAttributes().get(0).getTargetName();
507 StringBuffer boPropertyValue = new StringBuffer();
508
509
510
511
512 for (Object ebo : eboResults) {
513 if (boPropertyValue.length() != 0) {
514 boPropertyValue.append(SearchOperator.OR.op());
515 }
516 try {
517 boPropertyValue.append(PropertyUtils.getProperty(ebo, eboProperty).toString());
518 } catch (Exception ex) {
519 LOG.warn("Unable to get value for " + eboProperty + " on " + ebo);
520 }
521 }
522
523 if (eboParentPropertyName == null) {
524
525 nonEboFieldValues.put(boProperty, boPropertyValue.toString());
526 } else {
527
528
529 nonEboFieldValues.put(eboParentPropertyName + "." + boProperty, boPropertyValue.toString());
530 }
531 }
532 }
533
534 return nonEboFieldValues;
535 }
536
537
538
539
540 @Override
541 public Map<String, String> performClear(LookupForm form, Map<String, String> searchCriteria) {
542 Map<String, InputField> criteriaFieldMap = new HashMap<String, InputField>();
543 if (form.getPostedView() == null) {
544 criteriaFieldMap = getCriteriaFieldsForValidation((LookupView) form.getPostedView(), form);
545 }
546
547 List<String> readOnlyFieldsList = form.getReadOnlyFieldsList();
548
549 Map<String, String> clearedSearchCriteria = new HashMap<String, String>();
550 for (Map.Entry<String, String> searchKeyValue : searchCriteria.entrySet()) {
551 String searchPropertyName = searchKeyValue.getKey();
552
553 InputField inputField = criteriaFieldMap.get(searchPropertyName);
554
555 if (readOnlyFieldsList != null && readOnlyFieldsList.contains(searchPropertyName)) {
556 clearedSearchCriteria.put(searchPropertyName, searchKeyValue.getValue());
557 } else if (inputField != null) {
558
559
560
561
562
563
564
565
566
567 clearedSearchCriteria.put(searchPropertyName, inputField.getDefaultValue());
568 } else {
569 clearedSearchCriteria.put(searchPropertyName, "");
570 }
571 }
572
573 return clearedSearchCriteria;
574 }
575
576
577
578
579 @Override
580 public boolean validateSearchParameters(LookupForm form, Map<String, String> searchCriteria) {
581 boolean valid = true;
582
583
584
585 if (form.getPostedView() == null) {
586 return valid;
587 }
588
589 Map<String, InputField> criteriaFields = getCriteriaFieldsForValidation((LookupView) form.getPostedView(),
590 form);
591
592
593 List<String> hiddenCriteria = new ArrayList<String>();
594 for (InputField field : criteriaFields.values()) {
595 if (field.getAdditionalHiddenPropertyNames() != null) {
596 hiddenCriteria.addAll(field.getAdditionalHiddenPropertyNames());
597 }
598 }
599
600
601
602 for (Map.Entry<String, String> searchKeyValue : searchCriteria.entrySet()) {
603 String searchPropertyName = searchKeyValue.getKey();
604 String searchPropertyValue = searchKeyValue.getValue();
605
606 InputField inputField = criteriaFields.get(searchPropertyName);
607
608 String adjustedSearchPropertyPath = UifPropertyPaths.LOOKUP_CRITERIA + "[" + searchPropertyName + "]";
609 if (inputField == null && hiddenCriteria.contains(adjustedSearchPropertyPath)) {
610 return valid;
611 }
612
613
614 if ((inputField == null) && !searchPropertyName.contains(
615 KRADConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX)) {
616 throw new RuntimeException("Invalid search field sent for property name: " + searchPropertyName);
617 }
618
619 if (inputField != null) {
620 if (StringUtils.isBlank(searchPropertyValue) && inputField.getRequired()) {
621 GlobalVariables.getMessageMap().putError(inputField.getPropertyName(),
622 RiceKeyConstants.ERROR_REQUIRED, inputField.getLabel());
623 }
624
625 validateSearchParameterWildcardAndOperators(inputField, searchPropertyValue);
626 }
627 }
628 if (GlobalVariables.getMessageMap().hasErrors()) {
629 valid = false;
630 }
631
632 return valid;
633 }
634
635
636
637
638
639
640
641
642 protected Map<String, InputField> getCriteriaFieldsForValidation(LookupView lookupView, LookupForm form) {
643 Map<String, InputField> criteriaFieldMap = new HashMap<String, InputField>();
644
645 if (lookupView.getCriteriaFields() == null) {
646 return criteriaFieldMap;
647 }
648
649
650
651 List<InputField> fields = ComponentUtils.getComponentsOfTypeDeep(lookupView.getCriteriaFields(),
652 InputField.class);
653 for (InputField field : fields) {
654 criteriaFieldMap.put(field.getPropertyName(), field);
655 }
656
657 return criteriaFieldMap;
658 }
659
660
661
662
663
664
665
666
667 protected void validateSearchParameterWildcardAndOperators(InputField inputField, String searchPropertyValue) {
668 if (StringUtils.isBlank(searchPropertyValue)) {
669 return;
670 }
671
672
673 boolean found = false;
674 for (SearchOperator op : SearchOperator.QUERY_CHARACTERS) {
675 String queryCharacter = op.op();
676
677 if (searchPropertyValue.contains(queryCharacter)) {
678 found = true;
679 }
680 }
681
682 if (!found) {
683 return;
684 }
685
686 String attributeLabel = inputField.getLabel();
687 if ((LookupInputField.class.isAssignableFrom(inputField.getClass())) && (((LookupInputField) inputField)
688 .isDisableWildcardsAndOperators())) {
689 Object dataObjectExample = null;
690 try {
691 dataObjectExample = getDataObjectClass().newInstance();
692 } catch (Exception e) {
693 LOG.error("Exception caught instantiating " + getDataObjectClass().getName(), e);
694 throw new RuntimeException("Cannot instantiate " + getDataObjectClass().getName(), e);
695 }
696
697 Class<?> propertyType = ObjectPropertyUtils.getPropertyType(getDataObjectClass(),
698 inputField.getPropertyName());
699 if (TypeUtils.isIntegralClass(propertyType) || TypeUtils.isDecimalClass(propertyType) ||
700 TypeUtils.isTemporalClass(propertyType)) {
701 GlobalVariables.getMessageMap().putError(inputField.getPropertyName(),
702 RiceKeyConstants.ERROR_WILDCARDS_AND_OPERATORS_NOT_ALLOWED_ON_FIELD, attributeLabel);
703 }
704
705 if (TypeUtils.isStringClass(propertyType)) {
706 GlobalVariables.getMessageMap().putInfo(inputField.getPropertyName(),
707 RiceKeyConstants.INFO_WILDCARDS_AND_OPERATORS_TREATED_LITERALLY, attributeLabel);
708 }
709 } else {
710 if (getDataObjectAuthorizationService().attributeValueNeedsToBeEncryptedOnFormsAndLinks(
711 getDataObjectClass(), inputField.getPropertyName())) {
712 if (!searchPropertyValue.endsWith(EncryptionService.ENCRYPTION_POST_PREFIX)) {
713
714
715
716
717
718
719 GlobalVariables.getMessageMap().putError(inputField.getPropertyName(),
720 RiceKeyConstants.ERROR_SECURE_FIELD, attributeLabel);
721 }
722 }
723 }
724 }
725
726
727
728
729 public void getReturnUrlForResults(Action returnLink, Object model) {
730 LookupForm lookupForm = (LookupForm) model;
731 LookupView lookupView = (LookupView) returnLink.getContext().get(UifConstants.ContextVariableNames.VIEW);
732
733 Object dataObject = returnLink.getContext().get(UifConstants.ContextVariableNames.LINE);
734
735
736 if ((dataObject == null) || (!isResultReturnable(dataObject))) {
737 returnLink.setRender(false);
738 return;
739 }
740
741
742 String href = getReturnUrl(lookupView, lookupForm, dataObject);
743 if (StringUtils.isBlank(href)) {
744 returnLink.setRender(false);
745 return;
746 }
747
748
749 String linkLabel = getConfigurationService().getPropertyValueAsString(
750 KRADConstants.Lookup.TITLE_RETURN_URL_PREPENDTEXT_PROPERTY);
751 returnLink.setActionLabel(linkLabel);
752
753 List<String> returnKeys = getReturnKeys(lookupView, lookupForm, dataObject);
754 Map<String, String> returnKeyValues = KRADUtils.getPropertyKeyValuesFromDataObject(returnKeys, dataObject);
755
756 String title = LookupInquiryUtils.getLinkTitleText(linkLabel, getDataObjectClass(), returnKeyValues);
757 returnLink.setTitle(title);
758
759
760 String returnTarget = lookupView.getReturnTarget();
761 if (returnTarget != null) {
762 returnLink.setActionScript("window.open(\"" + href + "\", '" + returnTarget + "');");
763
764
765 if (!returnTarget.equals("_self")) {
766
767 if (lookupView.isReturnByScript()) {
768 Properties props = getReturnUrlParameters(lookupView, lookupForm, dataObject);
769
770 StringBuilder script = new StringBuilder("e.preventDefault();");
771 for (String returnField : lookupForm.getFieldConversions().values()) {
772 if (props.containsKey(returnField)) {
773 Object value = props.get(returnField);
774 script = script.append(
775 "returnLookupResultByScript(\"" + returnField + "\", '" + value + "');");
776 }
777 }
778 returnLink.setActionScript(script.append("closeLightbox();").toString());
779 } else {
780
781 returnLink.setActionScript("e.preventDefault();closeLightbox();showLoading();" +
782 "returnLookupResultReload(\"" + href + "\", '" + returnTarget + "');");
783 }
784 }
785 } else {
786
787
788 returnLink.setActionScript("window.open(\"" + href + "\", '_self');");
789 }
790 }
791
792
793
794
795
796
797
798
799
800
801
802
803
804 protected String getReturnUrl(LookupView lookupView, LookupForm lookupForm, Object dataObject) {
805 Properties props = getReturnUrlParameters(lookupView, lookupForm, dataObject);
806
807 String href = "";
808 if (StringUtils.isNotBlank(lookupForm.getReturnLocation())) {
809 href = UrlFactory.parameterizeUrl(lookupForm.getReturnLocation(), props);
810 }
811
812 return href;
813 }
814
815
816
817
818
819
820
821
822
823
824 protected Properties getReturnUrlParameters(LookupView lookupView, LookupForm lookupForm, Object dataObject) {
825 Properties props = new Properties();
826 props.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, KRADConstants.RETURN_METHOD_TO_CALL);
827
828 if (StringUtils.isNotBlank(lookupForm.getReturnFormKey())) {
829 props.put(UifParameters.FORM_KEY, lookupForm.getReturnFormKey());
830 }
831
832 props.put(KRADConstants.REFRESH_CALLER, lookupView.getId());
833 props.put(KRADConstants.REFRESH_DATA_OBJECT_CLASS, getDataObjectClass().getName());
834
835 if (StringUtils.isNotBlank(lookupForm.getDocNum())) {
836 props.put(UifParameters.DOC_NUM, lookupForm.getDocNum());
837 }
838
839 if (StringUtils.isNotBlank(lookupForm.getReferencesToRefresh())) {
840 props.put(KRADConstants.REFERENCES_TO_REFRESH, lookupForm.getReferencesToRefresh());
841 }
842
843 List<String> returnKeys = getReturnKeys(lookupView, lookupForm, dataObject);
844 Map<String, String> returnKeyValues = KRADUtils.getPropertyKeyValuesFromDataObject(returnKeys, dataObject);
845
846 for (String returnKey : returnKeyValues.keySet()) {
847 String returnValue = returnKeyValues.get(returnKey);
848 if (lookupForm.getFieldConversions().containsKey(returnKey)) {
849 returnKey = lookupForm.getFieldConversions().get(returnKey);
850 }
851
852 props.put(returnKey, returnValue);
853 }
854
855 return props;
856 }
857
858
859
860
861
862
863
864
865
866
867
868 protected List<String> getReturnKeys(LookupView lookupView, LookupForm lookupForm, Object dataObject) {
869 List<String> returnKeys;
870 if (lookupForm.getFieldConversions() != null && !lookupForm.getFieldConversions().isEmpty()) {
871 returnKeys = new ArrayList<String>(lookupForm.getFieldConversions().keySet());
872 } else {
873 returnKeys = getDataObjectMetaDataService().listPrimaryKeyFieldNames(getDataObjectClass());
874 }
875
876 return returnKeys;
877 }
878
879
880
881
882 public void getMaintenanceActionLink(Action actionLink, Object model, String maintenanceMethodToCall) {
883 LookupForm lookupForm = (LookupForm) model;
884 LookupView lookupView = (LookupView) actionLink.getContext().get(UifConstants.ContextVariableNames.VIEW);
885 Object dataObject = actionLink.getContext().get(UifConstants.ContextVariableNames.LINE);
886
887 List<String> pkNames = getDataObjectMetaDataService().listPrimaryKeyFieldNames(getDataObjectClass());
888
889
890 String href = getActionUrlHref(lookupForm, dataObject, maintenanceMethodToCall, pkNames);
891 if (StringUtils.isBlank(href)) {
892 actionLink.setRender(false);
893 return;
894 }
895
896 actionLink.setActionScript("window.open('" + href + "', '_self');");
897
898
899 String prependTitleText = actionLink.getActionLabel() + " " +
900 getDataDictionaryService().getDataDictionary().getDataObjectEntry(getDataObjectClass().getName())
901 .getObjectLabel() + " " +
902 getConfigurationService().getPropertyValueAsString(
903 KRADConstants.Lookup.TITLE_ACTION_URL_PREPENDTEXT_PROPERTY);
904
905 Map<String, String> primaryKeyValues = KRADUtils.getPropertyKeyValuesFromDataObject(pkNames, dataObject);
906 String title = LookupInquiryUtils.getLinkTitleText(prependTitleText, getDataObjectClass(), primaryKeyValues);
907 actionLink.setTitle(title);
908 lookupForm.setAtLeastOneRowHasActions(true);
909 }
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925 protected String getActionUrlHref(LookupForm lookupForm, Object dataObject, String methodToCall,
926 List<String> pkNames) {
927 LookupView lookupView = (LookupView) lookupForm.getView();
928
929 Properties props = new Properties();
930 props.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, methodToCall);
931
932 Map<String, String> primaryKeyValues = KRADUtils.getPropertyKeyValuesFromDataObject(pkNames, dataObject);
933 for (String primaryKey : primaryKeyValues.keySet()) {
934 String primaryKeyValue = primaryKeyValues.get(primaryKey);
935
936 props.put(primaryKey, primaryKeyValue);
937 }
938
939 if (StringUtils.isNotBlank(lookupForm.getReturnLocation())) {
940 props.put(KRADConstants.RETURN_LOCATION_PARAMETER, lookupForm.getReturnLocation());
941 }
942
943 props.put(UifParameters.DATA_OBJECT_CLASS_NAME, lookupForm.getDataObjectClassName());
944 props.put(UifParameters.VIEW_TYPE_NAME, UifConstants.ViewType.MAINTENANCE.name());
945
946 String maintenanceMapping = KRADConstants.Maintenance.REQUEST_MAPPING_MAINTENANCE;
947 if (StringUtils.isNotBlank(lookupView.getMaintenanceUrlMapping())) {
948 maintenanceMapping = lookupView.getMaintenanceUrlMapping();
949 }
950
951 return UrlFactory.parameterizeUrl(maintenanceMapping, props);
952 }
953
954
955
956
957
958
959 @Override
960 public void setMultiValueLookupSelect(InputField selectField, Object model) {
961 LookupForm lookupForm = (LookupForm) model;
962 Object lineDataObject = selectField.getContext().get(UifConstants.ContextVariableNames.LINE);
963 if (lineDataObject == null) {
964 throw new RuntimeException("Unable to get data object for line from component: " + selectField.getId());
965 }
966
967 Control selectControl = ((InputField) selectField).getControl();
968 if ((selectControl != null) && (selectControl instanceof ValueConfiguredControl)) {
969 String lineIdentifier = "";
970
971
972 Map<String, String> fieldConversions = lookupForm.getFieldConversions();
973 List<String> fromFieldNames = new ArrayList<String>(fieldConversions.keySet());
974 Collections.sort(fromFieldNames);
975 for (String fromFieldName : fromFieldNames) {
976 Object fromFieldValue = ObjectPropertyUtils.getPropertyValue(lineDataObject, fromFieldName);
977 if (fromFieldValue != null) {
978 lineIdentifier += fromFieldValue;
979 }
980 lineIdentifier += ":";
981 }
982 lineIdentifier = StringUtils.removeEnd(lineIdentifier, ":");
983
984 ((ValueConfiguredControl) selectControl).setValue(lineIdentifier);
985 }
986 }
987
988
989
990
991
992
993
994
995
996 public boolean allowsMaintenanceNewOrCopyAction() {
997 boolean allowsNewOrCopy = false;
998
999 String maintDocTypeName = getMaintenanceDocumentTypeName();
1000 if (StringUtils.isNotBlank(maintDocTypeName)) {
1001 allowsNewOrCopy = getDataObjectAuthorizationService().canCreate(getDataObjectClass(),
1002 GlobalVariables.getUserSession().getPerson(), maintDocTypeName);
1003 }
1004
1005 return allowsNewOrCopy;
1006 }
1007
1008
1009
1010
1011
1012
1013
1014 public boolean allowsMaintenanceEditAction(Object dataObject) {
1015 boolean allowsEdit = false;
1016
1017 String maintDocTypeName = getMaintenanceDocumentTypeName();
1018 if (StringUtils.isNotBlank(maintDocTypeName)) {
1019 allowsEdit = getDataObjectAuthorizationService().canMaintain(dataObject,
1020 GlobalVariables.getUserSession().getPerson(), maintDocTypeName);
1021 }
1022
1023 return allowsEdit;
1024 }
1025
1026
1027
1028
1029
1030
1031
1032 public boolean allowsMaintenanceDeleteAction(Object dataObject) {
1033 boolean allowsMaintain = false;
1034 boolean allowsDelete = false;
1035
1036 String maintDocTypeName = getMaintenanceDocumentTypeName();
1037 if (StringUtils.isNotBlank(maintDocTypeName)) {
1038 allowsMaintain = getDataObjectAuthorizationService().canMaintain(dataObject,
1039 GlobalVariables.getUserSession().getPerson(), maintDocTypeName);
1040 }
1041
1042 allowsDelete = getDocumentDictionaryService().getAllowsRecordDeletion(getDataObjectClass());
1043
1044 return allowsDelete && allowsMaintain;
1045 }
1046
1047
1048
1049
1050
1051
1052 protected String getMaintenanceDocumentTypeName() {
1053 DocumentDictionaryService dd = getDocumentDictionaryService();
1054 String maintDocTypeName = dd.getMaintenanceDocumentTypeName(getDataObjectClass());
1055
1056 return maintDocTypeName;
1057 }
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072 protected boolean isResultReturnable(Object dataObject) {
1073 return true;
1074 }
1075
1076
1077
1078
1079 @Override
1080 public void setDataObjectClass(Class<?> dataObjectClass) {
1081 this.dataObjectClass = dataObjectClass;
1082 }
1083
1084
1085
1086
1087 @Override
1088 public Class<?> getDataObjectClass() {
1089 return this.dataObjectClass;
1090 }
1091
1092 public void setConfigurationService(ConfigurationService configurationService) {
1093 this.configurationService = configurationService;
1094 }
1095
1096 protected DataObjectAuthorizationService getDataObjectAuthorizationService() {
1097 if (dataObjectAuthorizationService == null) {
1098 this.dataObjectAuthorizationService = KRADServiceLocatorWeb.getDataObjectAuthorizationService();
1099 }
1100 return dataObjectAuthorizationService;
1101 }
1102
1103 public void setDataObjectAuthorizationService(DataObjectAuthorizationService dataObjectAuthorizationService) {
1104 this.dataObjectAuthorizationService = dataObjectAuthorizationService;
1105 }
1106
1107 protected DataObjectMetaDataService getDataObjectMetaDataService() {
1108 if (dataObjectMetaDataService == null) {
1109 this.dataObjectMetaDataService = KRADServiceLocatorWeb.getDataObjectMetaDataService();
1110 }
1111 return dataObjectMetaDataService;
1112 }
1113
1114 public void setDataObjectMetaDataService(DataObjectMetaDataService dataObjectMetaDataService) {
1115 this.dataObjectMetaDataService = dataObjectMetaDataService;
1116 }
1117
1118 public DocumentDictionaryService getDocumentDictionaryService() {
1119 if (documentDictionaryService == null) {
1120 documentDictionaryService = KRADServiceLocatorWeb.getDocumentDictionaryService();
1121 }
1122 return documentDictionaryService;
1123 }
1124
1125 public void setDocumentDictionaryService(DocumentDictionaryService documentDictionaryService) {
1126 this.documentDictionaryService = documentDictionaryService;
1127 }
1128
1129 protected LookupService getLookupService() {
1130 if (lookupService == null) {
1131 this.lookupService = KRADServiceLocatorWeb.getLookupService();
1132 }
1133 return lookupService;
1134 }
1135
1136 public void setLookupService(LookupService lookupService) {
1137 this.lookupService = lookupService;
1138 }
1139
1140 protected EncryptionService getEncryptionService() {
1141 if (encryptionService == null) {
1142 this.encryptionService = CoreApiServiceLocator.getEncryptionService();
1143 }
1144 return encryptionService;
1145 }
1146
1147 public void setEncryptionService(EncryptionService encryptionService) {
1148 this.encryptionService = encryptionService;
1149 }
1150 }