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