1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  package org.kuali.rice.kns.lookup;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.core.api.config.property.ConfigContext;
20  import org.kuali.rice.coreservice.framework.CoreFrameworkServiceLocator;
21  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
22  import org.kuali.rice.core.api.CoreApiServiceLocator;
23  import org.kuali.rice.core.api.config.property.ConfigurationService;
24  import org.kuali.rice.core.api.encryption.EncryptionService;
25  import org.kuali.rice.core.api.search.SearchOperator;
26  import org.kuali.rice.core.api.util.RiceKeyConstants;
27  import org.kuali.rice.core.api.util.cache.CopiedObject;
28  import org.kuali.rice.core.api.util.type.TypeUtils;
29  import org.kuali.rice.core.web.format.DateFormatter;
30  import org.kuali.rice.core.web.format.Formatter;
31  import org.kuali.rice.kim.api.identity.Person;
32  import org.kuali.rice.kns.document.authorization.BusinessObjectRestrictions;
33  import org.kuali.rice.kns.document.authorization.FieldRestriction;
34  import org.kuali.rice.kns.inquiry.Inquirable;
35  import org.kuali.rice.kns.service.BusinessObjectAuthorizationService;
36  import org.kuali.rice.kns.service.BusinessObjectDictionaryService;
37  import org.kuali.rice.kns.service.BusinessObjectMetaDataService;
38  import org.kuali.rice.kns.service.KNSServiceLocator;
39  import org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService;
40  import org.kuali.rice.kns.util.FieldUtils;
41  import org.kuali.rice.kns.util.KNSConstants;
42  import org.kuali.rice.kns.web.comparator.CellComparatorHelper;
43  import org.kuali.rice.kns.web.struts.form.LookupForm;
44  import org.kuali.rice.kns.web.struts.form.MultipleValueLookupForm;
45  import org.kuali.rice.kns.web.ui.Column;
46  import org.kuali.rice.kns.web.ui.Field;
47  import org.kuali.rice.kns.web.ui.ResultRow;
48  import org.kuali.rice.kns.web.ui.Row;
49  import org.kuali.rice.krad.bo.BusinessObject;
50  import org.kuali.rice.krad.bo.PersistableBusinessObject;
51  import org.kuali.rice.krad.datadictionary.AttributeSecurity;
52  import org.kuali.rice.krad.datadictionary.mask.MaskFormatter;
53  import org.kuali.rice.krad.exception.ValidationException;
54  import org.kuali.rice.krad.service.BusinessObjectService;
55  import org.kuali.rice.krad.service.DataDictionaryService;
56  import org.kuali.rice.krad.service.KRADServiceLocator;
57  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
58  import org.kuali.rice.krad.service.LookupService;
59  import org.kuali.rice.krad.service.PersistenceStructureService;
60  import org.kuali.rice.krad.service.SequenceAccessorService;
61  import org.kuali.rice.krad.util.ExternalizableBusinessObjectUtils;
62  import org.kuali.rice.krad.util.GlobalVariables;
63  import org.kuali.rice.krad.util.KRADConstants;
64  import org.kuali.rice.krad.util.ObjectUtils;
65  import org.kuali.rice.krad.util.UrlFactory;
66  
67  import java.security.GeneralSecurityException;
68  import java.sql.Date;
69  import java.util.ArrayList;
70  import java.util.Collection;
71  import java.util.HashMap;
72  import java.util.HashSet;
73  import java.util.Iterator;
74  import java.util.List;
75  import java.util.Map;
76  import java.util.Properties;
77  import java.util.Set;
78  
79  
80  
81  
82  
83  public abstract class AbstractLookupableHelperServiceImpl implements LookupableHelperService {
84  
85      protected static final String TITLE_RETURN_URL_PREPENDTEXT_PROPERTY = "title.return.url.value.prependtext";
86      protected static final String TITLE_ACTION_URL_PREPENDTEXT_PROPERTY = "title.action.url.value.prependtext";
87      protected static final String ACTION_URLS_CHILDREN_SEPARATOR = " | ";
88      protected static final String ACTION_URLS_CHILDREN_STARTER = " [";
89      protected static final String ACTION_URLS_CHILDREN_END = "]";
90      protected static final String ACTION_URLS_SEPARATOR = "  ";
91      protected static final String ACTION_URLS_EMPTY = " ";
92  
93      protected static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AbstractLookupableHelperServiceImpl.class);
94  
95      protected Class businessObjectClass;
96      protected Map<String, String[]> parameters;
97      protected BusinessObjectDictionaryService businessObjectDictionaryService;
98      protected BusinessObjectMetaDataService businessObjectMetaDataService;
99      protected DataDictionaryService dataDictionaryService;
100     protected PersistenceStructureService persistenceStructureService;
101     protected EncryptionService encryptionService;
102     protected List<String> readOnlyFieldsList;
103     protected String backLocation;
104     protected String docFormKey;
105     protected Map fieldConversions;
106     protected LookupService lookupService;
107     protected List<Row> rows;
108     protected String referencesToRefresh;
109     protected SequenceAccessorService sequenceAccessorService;
110     protected BusinessObjectService businessObjectService;
111     protected LookupResultsService lookupResultsService;
112     protected String docNum;
113     protected ConfigurationService configurationService;
114     protected ParameterService parameterService;
115     protected BusinessObjectAuthorizationService businessObjectAuthorizationService;
116 
117     
118 
119 
120     public String getDocNum() {
121         return this.docNum;
122     }
123 
124     
125 
126 
127     public void setDocNum(String docNum) {
128         this.docNum = docNum;
129     }
130 
131     public AbstractLookupableHelperServiceImpl() {
132         rows = null;
133     }
134 
135     
136 
137 
138 
139 
140     public boolean checkForAdditionalFields(Map<String, String> fieldValues) {
141         return false;
142     }
143 
144     
145 
146 
147     public Class getBusinessObjectClass() {
148         return businessObjectClass;
149     }
150 
151     
152 
153 
154     public void setBusinessObjectClass(Class businessObjectClass) {
155         this.businessObjectClass = businessObjectClass;
156         setRows();
157     }
158 
159     
160 
161 
162     public Map<String, String[]> getParameters() {
163         return parameters;
164     }
165 
166     
167 
168 
169     public void setParameters(Map<String, String[]> parameters) {
170         this.parameters = parameters;
171     }
172 
173     
174 
175 
176 
177 
178     public DataDictionaryService getDataDictionaryService() {
179         return dataDictionaryService != null ? dataDictionaryService : KRADServiceLocatorWeb.getDataDictionaryService();
180     }
181 
182     
183 
184 
185 
186 
187     public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
188         this.dataDictionaryService = dataDictionaryService;
189     }
190 
191     
192 
193 
194 
195 
196     public BusinessObjectDictionaryService getBusinessObjectDictionaryService() {
197         return businessObjectDictionaryService != null ? businessObjectDictionaryService : KNSServiceLocator
198                 .getBusinessObjectDictionaryService();
199     }
200 
201     
202 
203 
204 
205 
206 
207     public void setBusinessObjectDictionaryService(BusinessObjectDictionaryService businessObjectDictionaryService) {
208         this.businessObjectDictionaryService = businessObjectDictionaryService;
209     }
210 
211     
212 
213 
214 
215 
216     public BusinessObjectMetaDataService getBusinessObjectMetaDataService() {
217         return businessObjectMetaDataService != null ? businessObjectMetaDataService : KNSServiceLocator
218                 .getBusinessObjectMetaDataService();
219     }
220 
221     
222 
223 
224 
225 
226     public void setBusinessObjectMetaDataService(BusinessObjectMetaDataService businessObjectMetaDataService) {
227         this.businessObjectMetaDataService = businessObjectMetaDataService;
228     }
229 
230     
231 
232 
233 
234 
235     protected PersistenceStructureService getPersistenceStructureService() {
236         return persistenceStructureService != null ? persistenceStructureService : KRADServiceLocator
237                 .getPersistenceStructureService();
238     }
239 
240     
241 
242 
243 
244 
245     public void setPersistenceStructureService(PersistenceStructureService persistenceStructureService) {
246         this.persistenceStructureService = persistenceStructureService;
247     }
248 
249     
250 
251 
252 
253 
254     protected EncryptionService getEncryptionService() {
255         return encryptionService != null ? encryptionService : CoreApiServiceLocator.getEncryptionService();
256     }
257 
258     
259 
260 
261 
262 
263     public void setEncryptionService(EncryptionService encryptionService) {
264         this.encryptionService = encryptionService;
265     }
266 
267     protected MaintenanceDocumentDictionaryService maintenanceDocumentDictionaryService;
268 
269     public MaintenanceDocumentDictionaryService getMaintenanceDocumentDictionaryService() {
270         if (maintenanceDocumentDictionaryService == null) {
271             maintenanceDocumentDictionaryService = KNSServiceLocator.getMaintenanceDocumentDictionaryService();
272         }
273         return maintenanceDocumentDictionaryService;
274     }
275 
276 
277     public BusinessObjectAuthorizationService getBusinessObjectAuthorizationService() {
278         if (businessObjectAuthorizationService == null) {
279             businessObjectAuthorizationService = KNSServiceLocator.getBusinessObjectAuthorizationService();
280         }
281         return businessObjectAuthorizationService;
282     }
283 
284     protected Inquirable kualiInquirable;
285 
286     public Inquirable getKualiInquirable() {
287         if (kualiInquirable == null) {
288             kualiInquirable = KNSServiceLocator.getKualiInquirable();
289         }
290         return kualiInquirable;
291     }
292 
293     public void setMaintenanceDocumentDictionaryService(MaintenanceDocumentDictionaryService maintenanceDocumentDictionaryService) {
294         this.maintenanceDocumentDictionaryService = maintenanceDocumentDictionaryService;
295     }
296 
297     public void setKualiInquirable(Inquirable kualiInquirable) {
298         this.kualiInquirable = kualiInquirable;
299     }
300 
301 
302     public ConfigurationService getKualiConfigurationService() {
303         if (configurationService == null) {
304             configurationService = KRADServiceLocator.getKualiConfigurationService();
305         }
306         return configurationService;
307     }
308 
309     public void setParameterService(ConfigurationService configurationService) {
310         this.configurationService = configurationService;
311     }
312 
313 
314     public ParameterService getParameterService() {
315         if (parameterService == null) {
316             parameterService = CoreFrameworkServiceLocator.getParameterService();
317         }
318         return parameterService;
319     }
320 
321     public void setParameterService(ParameterService parameterService) {
322         this.parameterService = parameterService;
323     }
324 
325     
326 
327 
328 
329 
330     public boolean allowsMaintenanceNewOrCopyAction() {
331         boolean allowsNewOrCopy = false;
332 
333         String maintDocTypeName = getMaintenanceDocumentTypeName();
334         Class boClass = this.getBusinessObjectClass();
335 
336         if (StringUtils.isNotBlank(maintDocTypeName)) {
337             allowsNewOrCopy = getBusinessObjectAuthorizationService().canCreate(boClass, GlobalVariables.getUserSession().getPerson(), maintDocTypeName);
338         }
339         return allowsNewOrCopy;
340     }
341 
342     protected boolean allowsMaintenanceEditAction(BusinessObject businessObject) {
343         boolean allowsEdit = false;
344 
345         String maintDocTypeName = getMaintenanceDocumentTypeName();
346 
347         if (StringUtils.isNotBlank(maintDocTypeName)) {
348             allowsEdit = getBusinessObjectAuthorizationService().canMaintain(businessObject, GlobalVariables.getUserSession().getPerson(), maintDocTypeName);
349         }
350         return allowsEdit;
351     }
352 
353 
354     
355 
356 
357 
358 
359 
360 
361     final public String getMaintenanceUrl(BusinessObject businessObject, HtmlData htmlData, List pkNames, BusinessObjectRestrictions businessObjectRestrictions) {
362         htmlData.setTitle(getActionUrlTitleText(businessObject, htmlData.getDisplayText(), pkNames, businessObjectRestrictions));
363         return htmlData.constructCompleteHtmlTag();
364     }
365 
366     
367 
368 
369 
370 
371 
372 
373     final public String getActionUrls(BusinessObject businessObject, List pkNames, BusinessObjectRestrictions businessObjectRestrictions) {
374         StringBuffer actions = new StringBuffer();
375         List<HtmlData> htmlDataList = getCustomActionUrls(businessObject, pkNames);
376         for (HtmlData htmlData : htmlDataList) {
377             actions.append(getMaintenanceUrl(businessObject, htmlData, pkNames, businessObjectRestrictions));
378             if (htmlData.getChildUrlDataList() != null) {
379                 if (htmlData.getChildUrlDataList().size() > 0) {
380                     actions.append(ACTION_URLS_CHILDREN_STARTER);
381                     for (HtmlData childURLData : htmlData.getChildUrlDataList()) {
382                         actions.append(getMaintenanceUrl(businessObject, childURLData, pkNames, businessObjectRestrictions));
383                         actions.append(ACTION_URLS_CHILDREN_SEPARATOR);
384                     }
385                     if (actions.toString().endsWith(ACTION_URLS_CHILDREN_SEPARATOR))
386                         actions.delete(actions.length() - ACTION_URLS_CHILDREN_SEPARATOR.length(), actions.length());
387                     actions.append(ACTION_URLS_CHILDREN_END);
388                 }
389             }
390             actions.append(ACTION_URLS_SEPARATOR);
391         }
392         if (actions.toString().endsWith(ACTION_URLS_SEPARATOR))
393             actions.delete(actions.length() - ACTION_URLS_SEPARATOR.length(), actions.length());
394         return actions.toString();
395     }
396 
397     
398 
399 
400 
401 
402 
403 
404 
405     public List<HtmlData> getCustomActionUrls(BusinessObject businessObject, List pkNames) {
406         List<HtmlData> htmlDataList = new ArrayList<HtmlData>();
407         if (allowsMaintenanceEditAction(businessObject)) {
408             htmlDataList.add(getUrlData(businessObject, KRADConstants.MAINTENANCE_EDIT_METHOD_TO_CALL, pkNames));
409         }
410         if (allowsMaintenanceNewOrCopyAction()) {
411             htmlDataList.add(getUrlData(businessObject, KRADConstants.MAINTENANCE_COPY_METHOD_TO_CALL, pkNames));
412         }
413         if (allowsMaintenanceDeleteAction(businessObject)) {
414             htmlDataList.add(getUrlData(businessObject, KRADConstants.MAINTENANCE_DELETE_METHOD_TO_CALL, pkNames));
415         }
416         return htmlDataList;
417     }
418 
419     
420 
421 
422 
423 
424 
425     protected boolean allowsMaintenanceDeleteAction(BusinessObject businessObject) {
426 
427         boolean allowsMaintain = false;
428         boolean allowsDelete = false;
429 
430         String maintDocTypeName = getMaintenanceDocumentTypeName();
431 
432         if (StringUtils.isNotBlank(maintDocTypeName)) {
433             allowsMaintain = getBusinessObjectAuthorizationService().canMaintain(businessObject, GlobalVariables.getUserSession().getPerson(), maintDocTypeName);
434         }
435 
436         allowsDelete = KNSServiceLocator.getMaintenanceDocumentDictionaryService().getAllowsRecordDeletion(businessObjectClass);
437 
438         return allowsDelete && allowsMaintain;
439     }
440 
441     
442 
443 
444 
445 
446 
447 
448 
449 
450 
451 
452     protected HtmlData.AnchorHtmlData getUrlData(BusinessObject businessObject, String methodToCall, String displayText, List pkNames) {
453 
454         String href = getActionUrlHref(businessObject, methodToCall, pkNames);
455         
456         HtmlData.AnchorHtmlData anchorHtmlData = new HtmlData.AnchorHtmlData(href, methodToCall, displayText);
457         return anchorHtmlData;
458     }
459 
460     
461 
462 
463 
464 
465 
466 
467 
468     protected HtmlData.AnchorHtmlData getUrlData(BusinessObject businessObject, String methodToCall, List pkNames) {
469         return getUrlData(businessObject, methodToCall, methodToCall, pkNames);
470     }
471 
472     
473 
474 
475 
476 
477     protected List<HtmlData> getEmptyActionUrls() {
478         return new ArrayList<HtmlData>();
479     }
480 
481     protected HtmlData getEmptyAnchorHtmlData() {
482         return new HtmlData.AnchorHtmlData();
483     }
484 
485     
486 
487 
488 
489 
490 
491 
492 
493 
494 
495     protected String getActionUrlHref(BusinessObject businessObject, String methodToCall, List pkNames) {
496         Properties parameters = new Properties();
497         parameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, methodToCall);
498         
499         parameters.put(KRADConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, businessObject.getClass().getName());
500         parameters.putAll(getParametersFromPrimaryKey(businessObject, pkNames));
501         if (StringUtils.isNotBlank(getReturnLocation())) {
502             parameters.put(KRADConstants.RETURN_LOCATION_PARAMETER, getReturnLocation());
503         }
504         return UrlFactory.parameterizeUrl(KRADConstants.MAINTENANCE_ACTION, parameters);
505     }
506 
507     protected Properties getParametersFromPrimaryKey(BusinessObject businessObject, List pkNames) {
508         Properties parameters = new Properties();
509         for (Iterator iter = pkNames.iterator(); iter.hasNext();) {
510             String fieldNm = (String) iter.next();
511 
512             
513             if (getDataDictionaryService().getAttributeDefinition(businessObjectClass.getName(), fieldNm) == null) {
514                 String errorMessage = "The field " + fieldNm + " could not be found in the data dictionary for class "
515                         + businessObjectClass.getName() + ", and thus it could not be determined whether it is a secure field.";
516 
517                 if (ConfigContext.getCurrentContextConfig().getBooleanProperty(KNSConstants.EXCEPTION_ON_MISSING_FIELD_CONVERSION_ATTRIBUTE, false)) {
518                     throw new RuntimeException(errorMessage);
519                 } else {
520                     LOG.error(errorMessage);
521                     continue;
522                 }
523             }
524 
525             Object fieldVal = ObjectUtils.getPropertyValue(businessObject, fieldNm);
526             if (fieldVal == null) {
527                 fieldVal = KRADConstants.EMPTY_STRING;
528             }
529             if (fieldVal instanceof java.sql.Date) {
530                 String formattedString = "";
531                 if (Formatter.findFormatter(fieldVal.getClass()) != null) {
532                     Formatter formatter = Formatter.getFormatter(fieldVal.getClass());
533                     formattedString = (String) formatter.format(fieldVal);
534                     fieldVal = formattedString;
535                 }
536             }
537 
538             
539             if (getBusinessObjectAuthorizationService().attributeValueNeedsToBeEncryptedOnFormsAndLinks(businessObjectClass, fieldNm)) {
540                 LOG.warn("field name " + fieldNm + " is a secure value and not included in pk parameter results");
541                 continue;
542             }
543 
544             parameters.put(fieldNm, fieldVal.toString());
545         }
546         return parameters;
547     }
548 
549     
550 
551 
552 
553 
554 
555 
556 
557 
558 
559     protected String getActionUrlTitleText(BusinessObject businessObject, String displayText, List pkNames, BusinessObjectRestrictions businessObjectRestrictions) {
560         String prependTitleText = displayText + " "
561                 + getDataDictionaryService().getDataDictionary().getBusinessObjectEntry(getBusinessObjectClass().getName()).getObjectLabel()
562                 + " "
563                 + this.getKualiConfigurationService().getPropertyValueAsString(TITLE_ACTION_URL_PREPENDTEXT_PROPERTY);
564         return HtmlData.getTitleText(prependTitleText, businessObject, pkNames, businessObjectRestrictions);
565     }
566 
567     
568 
569 
570 
571 
572 
573     protected String getMaintenanceDocumentTypeName() {
574         MaintenanceDocumentDictionaryService dd = getMaintenanceDocumentDictionaryService();
575         String maintDocTypeName = dd.getDocumentTypeName(getBusinessObjectClass());
576         return maintDocTypeName;
577     }
578 
579     
580 
581 
582 
583 
584     public List<String> getReadOnlyFieldsList() {
585         return readOnlyFieldsList;
586     }
587 
588 
589     
590 
591 
592 
593 
594     public void setReadOnlyFieldsList(List<String> readOnlyFieldsList) {
595         this.readOnlyFieldsList = readOnlyFieldsList;
596     }
597 
598     protected HashMap<String, Boolean> noLookupResultFieldInquiryCache = new HashMap<String, Boolean>();
599     protected HashMap<Class, Class> inquirableClassCache = new HashMap<Class, Class>();
600     protected HashMap<String, Boolean> forceLookupResultFieldInquiryCache = new HashMap<String, Boolean>();
601 
602     
603 
604 
605 
606 
607 
608 
609     public HtmlData getInquiryUrl(BusinessObject bo, String propertyName) {
610         HtmlData inquiryUrl = new HtmlData.AnchorHtmlData();
611 
612         String cacheKey = bo.getClass().getName() + "." + propertyName;
613         Boolean noLookupResultFieldInquiry = noLookupResultFieldInquiryCache.get(cacheKey);
614         if (noLookupResultFieldInquiry == null) {
615             noLookupResultFieldInquiry = getBusinessObjectDictionaryService().noLookupResultFieldInquiry(bo.getClass(), propertyName);
616             if (noLookupResultFieldInquiry == null) {
617                 noLookupResultFieldInquiry = Boolean.TRUE;
618             }
619             noLookupResultFieldInquiryCache.put(cacheKey, noLookupResultFieldInquiry);
620         }
621         if (!noLookupResultFieldInquiry) {
622 
623             Class<Inquirable> inquirableClass = inquirableClassCache.get(bo.getClass());
624             if (!inquirableClassCache.containsKey(bo.getClass())) {
625                 inquirableClass = getBusinessObjectDictionaryService().getInquirableClass(bo.getClass());
626                 inquirableClassCache.put(bo.getClass(), inquirableClass);
627             }
628             Inquirable inq = null;
629             try {
630                 if (inquirableClass != null) {
631                     inq = inquirableClass.newInstance();
632                 } else {
633                     inq = getKualiInquirable();
634                     if (LOG.isDebugEnabled()) {
635                         LOG.debug("Default Inquirable Class: " + inq.getClass());
636                     }
637                 }
638                 Boolean forceLookupResultFieldInquiry = forceLookupResultFieldInquiryCache.get(cacheKey);
639                 if (forceLookupResultFieldInquiry == null) {
640                     forceLookupResultFieldInquiry = getBusinessObjectDictionaryService().forceLookupResultFieldInquiry(bo.getClass(), propertyName);
641                     if (forceLookupResultFieldInquiry == null) {
642                         forceLookupResultFieldInquiry = Boolean.FALSE;
643                     }
644                     forceLookupResultFieldInquiryCache.put(cacheKey, forceLookupResultFieldInquiry);
645                 }
646                 inquiryUrl = inq.getInquiryUrl(bo, propertyName, forceLookupResultFieldInquiry);
647             } catch (Exception ex) {
648                 LOG.error("unable to create inquirable to get inquiry URL", ex);
649             }
650         }
651 
652         return inquiryUrl;
653     }
654 
655     protected CopiedObject<ArrayList<Column>> resultColumns = null;
656 
657     
658 
659 
660     public List<Column> getColumns() {
661         if (resultColumns == null) {
662             ArrayList<Column> columns = new ArrayList<Column>();
663             for (String attributeName : getBusinessObjectDictionaryService().getLookupResultFieldNames(getBusinessObjectClass())) {
664                 Column column = new Column();
665                 column.setPropertyName(attributeName);
666                 String columnTitle = getDataDictionaryService().getAttributeLabel(getBusinessObjectClass(), attributeName);
667                 Boolean useShortLabel = getBusinessObjectDictionaryService().getLookupResultFieldUseShortLabel(businessObjectClass, attributeName);
668                 if (useShortLabel != null && useShortLabel) {
669                     columnTitle = getDataDictionaryService().getAttributeShortLabel(getBusinessObjectClass(), attributeName);
670                 }
671                 if (StringUtils.isBlank(columnTitle)) {
672                     columnTitle = getDataDictionaryService().getCollectionLabel(getBusinessObjectClass(), attributeName);
673                 }
674                 column.setColumnTitle(columnTitle);
675                 column.setMaxLength(getColumnMaxLength(attributeName));
676 
677                 if (!businessObjectClass.isInterface()) {
678                     try {
679                         column.setFormatter(ObjectUtils.getFormatterWithDataDictionary(getBusinessObjectClass()
680                                 .newInstance(), attributeName));
681                     } catch (InstantiationException e) {
682                         LOG.info("Unable to get new instance of business object class: " + businessObjectClass.getName(), e);
683                         
684                     } catch (IllegalAccessException e) {
685                         LOG.info("Unable to get new instance of business object class: " + businessObjectClass.getName(), e);
686                         
687                     }
688                 }
689 
690                 String alternateDisplayPropertyName = getBusinessObjectDictionaryService()
691                         .getLookupFieldAlternateDisplayAttributeName(getBusinessObjectClass(), attributeName);
692                 if (StringUtils.isNotBlank(alternateDisplayPropertyName)) {
693                     column.setAlternateDisplayPropertyName(alternateDisplayPropertyName);
694                 }
695 
696                 String additionalDisplayPropertyName = getBusinessObjectDictionaryService()
697                         .getLookupFieldAdditionalDisplayAttributeName(getBusinessObjectClass(), attributeName);
698                 if (StringUtils.isNotBlank(additionalDisplayPropertyName)) {
699                     column.setAdditionalDisplayPropertyName(additionalDisplayPropertyName);
700                 } else {
701                     boolean translateCodes = getBusinessObjectDictionaryService().tranlateCodesInLookup(getBusinessObjectClass());
702                     if (translateCodes) {
703                         FieldUtils.setAdditionalDisplayPropertyForCodes(getBusinessObjectClass(), attributeName, column);
704                     }
705                 }
706 
707                 column.setTotal(getBusinessObjectDictionaryService().getLookupResultFieldTotal(getBusinessObjectClass(), attributeName));
708 
709                 columns.add(column);
710             }
711             resultColumns = ObjectUtils.deepCopyForCaching(columns);
712             return columns;
713         }
714         return resultColumns.getContent();
715     }
716 
717     protected static Integer RESULTS_DEFAULT_MAX_COLUMN_LENGTH = null;
718 
719     protected int getColumnMaxLength(String attributeName) {
720         Integer fieldDefinedMaxLength = getBusinessObjectDictionaryService().getLookupResultFieldMaxLength(getBusinessObjectClass(), attributeName);
721         if (fieldDefinedMaxLength == null) {
722             if (RESULTS_DEFAULT_MAX_COLUMN_LENGTH == null) {
723                 try {
724                     RESULTS_DEFAULT_MAX_COLUMN_LENGTH = Integer.valueOf(getParameterService().getParameterValueAsString(
725                             KRADConstants.KNS_NAMESPACE, KRADConstants.DetailTypes.LOOKUP_PARM_DETAIL_TYPE, KRADConstants.RESULTS_DEFAULT_MAX_COLUMN_LENGTH));
726                 } catch (NumberFormatException ex) {
727                     LOG.error("Lookup field max length parameter not found and unable to parse default set in system parameters (RESULTS_DEFAULT_MAX_COLUMN_LENGTH).");
728                 }
729             }
730             return RESULTS_DEFAULT_MAX_COLUMN_LENGTH.intValue();
731         }
732         return fieldDefinedMaxLength.intValue();
733     }
734 
735     
736 
737 
738     public String getBackLocation() {
739         return backLocation;
740     }
741 
742     
743 
744 
745     public void setBackLocation(String backLocation) {
746         this.backLocation = backLocation;
747     }
748 
749     
750 
751 
752     public String getReturnLocation() {
753         return backLocation;
754     }
755 
756     
757 
758 
759 
760 
761     final public HtmlData getReturnUrl(BusinessObject businessObject, Map fieldConversions, String lookupImpl, List returnKeys, BusinessObjectRestrictions businessObjectRestrictions) {
762         String href = getReturnHref(businessObject, fieldConversions, lookupImpl, returnKeys);
763         String returnUrlAnchorLabel =
764                 this.getKualiConfigurationService().getPropertyValueAsString(TITLE_RETURN_URL_PREPENDTEXT_PROPERTY);
765         HtmlData.AnchorHtmlData anchor = new HtmlData.AnchorHtmlData(href, HtmlData.getTitleText(returnUrlAnchorLabel, businessObject, returnKeys, businessObjectRestrictions));
766         anchor.setDisplayText(returnUrlAnchorLabel);
767         return anchor;
768     }
769 
770     
771 
772 
773 
774 
775 
776 
777 
778 
779     final protected String getReturnHref(BusinessObject businessObject, Map fieldConversions, String lookupImpl, List returnKeys) {
780         if (StringUtils.isNotBlank(backLocation)) {
781             return UrlFactory.parameterizeUrl(backLocation, getParameters(
782                     businessObject, fieldConversions, lookupImpl, returnKeys));
783         }
784         return "";
785     }
786 
787     
788 
789 
790     public HtmlData getReturnUrl(BusinessObject businessObject, LookupForm lookupForm, List returnKeys, BusinessObjectRestrictions businessObjectRestrictions) {
791         Properties parameters = getParameters(
792                 businessObject, lookupForm.getFieldConversions(), lookupForm.getLookupableImplServiceName(), returnKeys);
793         if (StringUtils.isEmpty(lookupForm.getHtmlDataType()) || HtmlData.ANCHOR_HTML_DATA_TYPE.equals(lookupForm.getHtmlDataType()))
794             return getReturnAnchorHtmlData(businessObject, parameters, lookupForm, returnKeys, businessObjectRestrictions);
795         else
796             return getReturnInputHtmlData(businessObject, parameters, lookupForm, returnKeys, businessObjectRestrictions);
797     }
798 
799     protected HtmlData getReturnInputHtmlData(BusinessObject businessObject, Properties parameters, LookupForm lookupForm, List returnKeys, BusinessObjectRestrictions businessObjectRestrictions) {
800         String returnUrlAnchorLabel =
801                 this.getKualiConfigurationService().getPropertyValueAsString(TITLE_RETURN_URL_PREPENDTEXT_PROPERTY);
802         String name = KRADConstants.MULTIPLE_VALUE_LOOKUP_SELECTED_OBJ_ID_PARAM_PREFIX + lookupForm.getLookupObjectId();
803         HtmlData.InputHtmlData input = new HtmlData.InputHtmlData(name, HtmlData.InputHtmlData.CHECKBOX_INPUT_TYPE);
804         input.setTitle(HtmlData.getTitleText(returnUrlAnchorLabel, businessObject, returnKeys, businessObjectRestrictions));
805         if (((MultipleValueLookupForm) lookupForm).getCompositeObjectIdMap() == null ||
806                 ((MultipleValueLookupForm) lookupForm).getCompositeObjectIdMap().get(
807                         ((PersistableBusinessObject) businessObject).getObjectId()) == null) {
808             input.setChecked("");
809         } else {
810             input.setChecked(HtmlData.InputHtmlData.CHECKBOX_CHECKED_VALUE);
811         }
812         input.setValue(HtmlData.InputHtmlData.CHECKBOX_CHECKED_VALUE);
813         return input;
814     }
815 
816     protected HtmlData getReturnAnchorHtmlData(BusinessObject businessObject, Properties parameters, LookupForm lookupForm, List returnKeys, BusinessObjectRestrictions businessObjectRestrictions) {
817         String returnUrlAnchorLabel =
818                 this.getKualiConfigurationService().getPropertyValueAsString(TITLE_RETURN_URL_PREPENDTEXT_PROPERTY);
819         HtmlData.AnchorHtmlData anchor = new HtmlData.AnchorHtmlData(
820                 getReturnHref(parameters, lookupForm, returnKeys),
821                 HtmlData.getTitleText(returnUrlAnchorLabel, businessObject, returnKeys, businessObjectRestrictions));
822         anchor.setDisplayText(returnUrlAnchorLabel);
823         return anchor;
824     }
825 
826     protected String getReturnHref(Properties parameters, LookupForm lookupForm, List returnKeys) {
827         if (StringUtils.isNotBlank(backLocation)) {
828             String href = UrlFactory.parameterizeUrl(backLocation, parameters);
829             return addToReturnHref(href, lookupForm);
830         }
831         return "";
832     }
833 
834     protected String addToReturnHref(String href, LookupForm lookupForm) {
835         String lookupAnchor = "";
836         if (StringUtils.isNotEmpty(lookupForm.getAnchor())) {
837             lookupAnchor = lookupForm.getAnchor();
838         }
839         href += "&anchor=" + lookupAnchor + "&docNum=" + (StringUtils.isEmpty(getDocNum()) ? "" : getDocNum());
840         return href;
841     }
842 
843     protected Properties getParameters(BusinessObject bo, Map<String, String> fieldConversions, String lookupImpl, List returnKeys) {
844         Properties parameters = new Properties();
845         parameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, KRADConstants.RETURN_METHOD_TO_CALL);
846         if (getDocFormKey() != null) {
847             parameters.put(KRADConstants.DOC_FORM_KEY, getDocFormKey());
848         }
849         if (lookupImpl != null) {
850             parameters.put(KRADConstants.REFRESH_CALLER, lookupImpl);
851         }
852         if (getDocNum() != null) {
853             parameters.put(KRADConstants.DOC_NUM, getDocNum());
854         }
855 
856         if (getReferencesToRefresh() != null) {
857             parameters.put(KRADConstants.REFERENCES_TO_REFRESH, getReferencesToRefresh());
858         }
859 
860         Iterator returnKeysIt = getReturnKeys().iterator();
861         while (returnKeysIt.hasNext()) {
862             String fieldNm = (String) returnKeysIt.next();
863 
864             
865             if (getDataDictionaryService().getAttributeDefinition(businessObjectClass.getName(), fieldNm) == null) {
866                 String errorMessage = "The field " + fieldNm + " could not be found in the data dictionary for class "
867                         + businessObjectClass.getName() + ", and thus it could not be determined whether it is a secure field.";
868 
869                 if (ConfigContext.getCurrentContextConfig().getBooleanProperty(KNSConstants.EXCEPTION_ON_MISSING_FIELD_CONVERSION_ATTRIBUTE, false)) {
870                     throw new RuntimeException(errorMessage);
871                 } else {
872                     LOG.error(errorMessage);
873                     continue;
874                 }
875             }
876 
877             Object fieldVal = ObjectUtils.getPropertyValue(bo, fieldNm);
878             if (fieldVal == null) {
879                 fieldVal = KRADConstants.EMPTY_STRING;
880             }
881 
882             if (getBusinessObjectAuthorizationService().attributeValueNeedsToBeEncryptedOnFormsAndLinks(businessObjectClass, fieldNm)) {
883                 LOG.warn("field name " + fieldNm + " is a secure value and not included in parameter results");
884                 continue;
885             }
886 
887             
888             if (fieldVal instanceof Date) {
889                 DateFormatter dateFormatter = new DateFormatter();
890                 fieldVal = dateFormatter.format(fieldVal);
891             }
892 
893             if (fieldConversions.containsKey(fieldNm)) {
894                 fieldNm = (String) fieldConversions.get(fieldNm);
895             }
896 
897             parameters.put(fieldNm, fieldVal.toString());
898         }
899 
900         return parameters;
901     }
902 
903     
904 
905 
906     public List<String> getReturnKeys() {
907         List<String> returnKeys;
908         if (fieldConversions != null && !fieldConversions.isEmpty()) {
909             returnKeys = new ArrayList<String>(fieldConversions.keySet());
910         } else {
911             returnKeys = getBusinessObjectMetaDataService().listPrimaryKeyFieldNames(getBusinessObjectClass());
912         }
913 
914         return returnKeys;
915     }
916 
917     
918 
919 
920 
921 
922     public String getDocFormKey() {
923         return docFormKey;
924     }
925 
926     
927 
928 
929 
930 
931     public void setDocFormKey(String docFormKey) {
932         this.docFormKey = docFormKey;
933     }
934 
935     
936 
937 
938     public void setFieldConversions(Map fieldConversions) {
939         this.fieldConversions = fieldConversions;
940     }
941 
942     
943 
944 
945 
946 
947     protected LookupService getLookupService() {
948         return lookupService != null ? lookupService : KRADServiceLocatorWeb.getLookupService();
949     }
950 
951     
952 
953 
954 
955 
956     public void setLookupService(LookupService lookupService) {
957         this.lookupService = lookupService;
958     }
959 
960     
961 
962 
963 
964 
965     public List<String> getDefaultSortColumns() {
966         return getBusinessObjectDictionaryService().getLookupDefaultSortFieldNames(getBusinessObjectClass());
967     }
968 
969     
970 
971 
972 
973 
974     public void validateSearchParameters(Map<String, String> fieldValues) {
975         List<String> lookupFieldAttributeList = null;
976         if (getBusinessObjectMetaDataService().isLookupable(getBusinessObjectClass())) {
977             lookupFieldAttributeList = getBusinessObjectMetaDataService().getLookupableFieldNames(getBusinessObjectClass());
978         }
979         if (lookupFieldAttributeList == null) {
980             throw new RuntimeException("Lookup not defined for business object " + getBusinessObjectClass());
981         }
982         for (Iterator iter = lookupFieldAttributeList.iterator(); iter.hasNext();) {
983             String attributeName = (String) iter.next();
984             if (fieldValues.containsKey(attributeName)) {
985                 
986                 String attributeLabel = getDataDictionaryService().getAttributeLabel(getBusinessObjectClass(), attributeName);
987 
988                 String attributeValue = (String) fieldValues.get(attributeName);
989 
990                 
991                 if (StringUtils.isBlank(attributeValue)) {
992                     if ((getBusinessObjectDictionaryService().getLookupAttributeRequired(getBusinessObjectClass(), attributeName)).booleanValue()) {
993                         GlobalVariables.getMessageMap().putError(attributeName, RiceKeyConstants.ERROR_REQUIRED, attributeLabel);
994                     }
995                 }
996                 validateSearchParameterWildcardAndOperators(attributeName, attributeValue);
997             }
998         }
999 
1000         if (GlobalVariables.getMessageMap().hasErrors()) {
1001             throw new ValidationException("errors in search criteria");
1002         }
1003     }
1004 
1005     protected void validateSearchParameterWildcardAndOperators(String attributeName, String attributeValue) {
1006         if (StringUtils.isBlank(attributeValue))
1007             return;
1008 
1009         
1010         boolean found = false;
1011         for (SearchOperator op : SearchOperator.QUERY_CHARACTERS) {
1012             String queryCharacter = op.op();
1013 
1014             if (attributeValue.contains(queryCharacter)) {
1015                 found = true;
1016             }
1017         }
1018         if (!found)
1019             return;
1020 
1021         String attributeLabel = getDataDictionaryService().getAttributeLabel(getBusinessObjectClass(), attributeName);
1022         if (getBusinessObjectDictionaryService().isLookupFieldTreatWildcardsAndOperatorsAsLiteral(businessObjectClass, attributeName)) {
1023             BusinessObject example = null;
1024             try {
1025                 example = (BusinessObject) businessObjectClass.newInstance();
1026             } catch (Exception e) {
1027                 LOG.error("Exception caught instantiating " + businessObjectClass.getName(), e);
1028                 throw new RuntimeException("Cannot instantiate " + businessObjectClass.getName(), e);
1029             }
1030 
1031             Class propertyType = ObjectUtils.getPropertyType(example, attributeName, getPersistenceStructureService());
1032             if (TypeUtils.isIntegralClass(propertyType) || TypeUtils.isDecimalClass(propertyType) || TypeUtils.isTemporalClass(propertyType)) {
1033                 GlobalVariables.getMessageMap().putError(attributeName, RiceKeyConstants.ERROR_WILDCARDS_AND_OPERATORS_NOT_ALLOWED_ON_FIELD, attributeLabel);
1034             }
1035             if (TypeUtils.isStringClass(propertyType)) {
1036                 GlobalVariables.getMessageMap().putInfo(attributeName, RiceKeyConstants.INFO_WILDCARDS_AND_OPERATORS_TREATED_LITERALLY, attributeLabel);
1037             }
1038         } else {
1039             if (getBusinessObjectAuthorizationService().attributeValueNeedsToBeEncryptedOnFormsAndLinks(businessObjectClass, attributeName)) {
1040                 if (!attributeValue.endsWith(EncryptionService.ENCRYPTION_POST_PREFIX)) {
1041                     
1042 
1043                     
1044                     
1045 
1046                     GlobalVariables.getMessageMap().putError(attributeName, RiceKeyConstants.ERROR_SECURE_FIELD, attributeLabel);
1047                 }
1048             }
1049         }
1050     }
1051 
1052     
1053 
1054 
1055 
1056     protected void setRows() {
1057         List<String> lookupFieldAttributeList = null;
1058         if (getBusinessObjectMetaDataService().isLookupable(getBusinessObjectClass())) {
1059             lookupFieldAttributeList = getBusinessObjectMetaDataService().getLookupableFieldNames(
1060                     getBusinessObjectClass());
1061         }
1062         if (lookupFieldAttributeList == null) {
1063             throw new RuntimeException("Lookup not defined for business object " + getBusinessObjectClass());
1064         }
1065 
1066         
1067         List fields = new ArrayList();
1068         try {
1069             fields = FieldUtils.createAndPopulateFieldsForLookup(lookupFieldAttributeList, getReadOnlyFieldsList(),
1070                     getBusinessObjectClass());
1071         } catch (InstantiationException e) {
1072             throw new RuntimeException("Unable to create instance of business object class" + e.getMessage());
1073         } catch (IllegalAccessException e) {
1074             throw new RuntimeException("Unable to create instance of business object class" + e.getMessage());
1075         }
1076 
1077         int numCols = getBusinessObjectDictionaryService().getLookupNumberOfColumns(this.getBusinessObjectClass());
1078 
1079         this.rows = FieldUtils.wrapFields(fields, numCols);
1080     }
1081 
1082     public List<Row> getRows() {
1083         return rows;
1084     }
1085 
1086     public abstract List<? extends BusinessObject> getSearchResults(Map<String, String> fieldValues);
1087 
1088     
1089 
1090 
1091 
1092 
1093 
1094 
1095     public List<? extends BusinessObject> getSearchResultsUnbounded(Map<String, String> fieldValues) {
1096         throw new UnsupportedOperationException("Lookupable helper services do not always support getSearchResultsUnbounded");
1097     }
1098 
1099     
1100 
1101 
1102 
1103 
1104 
1105 
1106 
1107     public Collection<? extends BusinessObject> performLookup(LookupForm lookupForm, Collection<ResultRow> resultTable, boolean bounded) {
1108         Map lookupFormFields = lookupForm.getFieldsForLookup();
1109 
1110         setBackLocation((String) lookupFormFields.get(KRADConstants.BACK_LOCATION));
1111         setDocFormKey((String) lookupFormFields.get(KRADConstants.DOC_FORM_KEY));
1112         Collection<? extends BusinessObject> displayList;
1113 
1114         LookupUtils.preProcessRangeFields(lookupFormFields);
1115 
1116         
1117         if (bounded) {
1118             displayList = getSearchResults(lookupFormFields);
1119         } else {
1120             displayList = getSearchResultsUnbounded(lookupFormFields);
1121         }
1122 
1123         boolean hasReturnableRow = false;
1124 
1125         List<String> returnKeys = getReturnKeys();
1126         List<String> pkNames = getBusinessObjectMetaDataService().listPrimaryKeyFieldNames(getBusinessObjectClass());
1127         Person user = GlobalVariables.getUserSession().getPerson();
1128 
1129         
1130         
1131         for (BusinessObject element : displayList) {
1132             BusinessObject baseElement = element;
1133             
1134             
1135             
1136             
1137             
1138             
1139 
1140 
1141 
1142 
1143 
1144 
1145 
1146 
1147 
1148 
1149             final String lookupId = KNSServiceLocator.getLookupResultsService().getLookupId(baseElement);
1150             if (lookupId != null) {
1151                 lookupForm.setLookupObjectId(lookupId);
1152             }
1153 
1154             BusinessObjectRestrictions businessObjectRestrictions = getBusinessObjectAuthorizationService()
1155                     .getLookupResultRestrictions(element, user);
1156 
1157             HtmlData returnUrl = getReturnUrl(element, lookupForm, returnKeys, businessObjectRestrictions);
1158             String actionUrls = getActionUrls(element, pkNames, businessObjectRestrictions);
1159             
1160             if ("".equals(actionUrls)) {
1161                 actionUrls = ACTION_URLS_EMPTY;
1162             }
1163 
1164             List<Column> columns = getColumns();
1165             for (Iterator iterator = columns.iterator(); iterator.hasNext();) {
1166                 Column col = (Column) iterator.next();
1167 
1168                 String propValue = ObjectUtils.getFormattedPropertyValue(element, col.getPropertyName(), col.getFormatter());
1169                 Class propClass = getPropertyClass(element, col.getPropertyName());
1170 
1171                 col.setComparator(CellComparatorHelper.getAppropriateComparatorForPropertyClass(propClass));
1172                 col.setValueComparator(CellComparatorHelper.getAppropriateValueComparatorForPropertyClass(propClass));
1173 
1174                 String propValueBeforePotientalMasking = propValue;
1175                 propValue = maskValueIfNecessary(element.getClass(), col.getPropertyName(), propValue,
1176                         businessObjectRestrictions);
1177                 col.setPropertyValue(propValue);
1178 
1179                 
1180                 if (StringUtils.equals(propValueBeforePotientalMasking, propValue)) {
1181                     if (StringUtils.isNotBlank(col.getAlternateDisplayPropertyName())) {
1182                         String alternatePropertyValue = ObjectUtils.getFormattedPropertyValue(element, col
1183                                 .getAlternateDisplayPropertyName(), null);
1184                         col.setPropertyValue(alternatePropertyValue);
1185                     }
1186 
1187                     if (StringUtils.isNotBlank(col.getAdditionalDisplayPropertyName())) {
1188                         String additionalPropertyValue = ObjectUtils.getFormattedPropertyValue(element, col
1189                                 .getAdditionalDisplayPropertyName(), null);
1190                         col.setPropertyValue(col.getPropertyValue() + " *-* " + additionalPropertyValue);
1191                     }
1192                 } else {
1193                     col.setTotal(false);
1194                 }
1195 
1196                 if (col.isTotal()) {
1197                     Object unformattedPropValue = ObjectUtils.getPropertyValue(element, col.getPropertyName());
1198                     col.setUnformattedPropertyValue(unformattedPropValue);
1199                 }
1200 
1201                 if (StringUtils.isNotBlank(propValue)) {
1202                     col.setColumnAnchor(getInquiryUrl(element, col.getPropertyName()));
1203                 }
1204             }
1205 
1206             ResultRow row = new ResultRow(columns, returnUrl.constructCompleteHtmlTag(), actionUrls);
1207             row.setRowId(returnUrl.getName());
1208             row.setReturnUrlHtmlData(returnUrl);
1209 
1210             
1211             
1212             
1213             
1214             if (getBusinessObjectDictionaryService().isExportable(getBusinessObjectClass())) {
1215                 row.setBusinessObject(element);
1216             }
1217 
1218             if (lookupId != null) {
1219                 row.setObjectId(lookupId);
1220             }
1221 
1222             boolean rowReturnable = isResultReturnable(element);
1223             row.setRowReturnable(rowReturnable);
1224             if (rowReturnable) {
1225                 hasReturnableRow = true;
1226             }
1227             resultTable.add(row);
1228         }
1229 
1230         lookupForm.setHasReturnableRow(hasReturnableRow);
1231 
1232         return displayList;
1233     }
1234 
1235     
1236 
1237 
1238 
1239 
1240 
1241 
1242 
1243     protected Class getPropertyClass(BusinessObject element, String propertyName) {
1244         Class propClass = null;
1245 
1246         try {
1247             propClass = ObjectUtils.getPropertyType(element, propertyName, getPersistenceStructureService());
1248 
1249         } catch (Exception e) {
1250             throw new RuntimeException("Cannot access PropertyType for property " + "'" + propertyName + "' "
1251                     + " on an instance of '" + element.getClass().getName() + "'.", e);
1252         }
1253 
1254         return propClass;
1255     }
1256 
1257 
1258 
1259     protected String maskValueIfNecessary(Class businessObjectClass, String propertyName, String propertyValue, BusinessObjectRestrictions businessObjectRestrictions) {
1260         String maskedPropertyValue = propertyValue;
1261         if (businessObjectRestrictions != null) {
1262             FieldRestriction fieldRestriction = businessObjectRestrictions.getFieldRestriction(propertyName);
1263             if (fieldRestriction != null && (fieldRestriction.isMasked() || fieldRestriction.isPartiallyMasked())) {
1264                 maskedPropertyValue = fieldRestriction.getMaskFormatter().maskValue(propertyValue);
1265             }
1266         }
1267         return maskedPropertyValue;
1268     }
1269 
1270 
1271     protected void setReferencesToRefresh(String referencesToRefresh) {
1272         this.referencesToRefresh = referencesToRefresh;
1273     }
1274 
1275     public String getReferencesToRefresh() {
1276         return referencesToRefresh;
1277     }
1278 
1279     protected SequenceAccessorService getSequenceAccessorService() {
1280         return sequenceAccessorService != null ? sequenceAccessorService : KRADServiceLocator
1281                 .getSequenceAccessorService();
1282     }
1283 
1284     public void setSequenceAccessorService(SequenceAccessorService sequenceAccessorService) {
1285         this.sequenceAccessorService = sequenceAccessorService;
1286     }
1287 
1288     public BusinessObjectService getBusinessObjectService() {
1289         return businessObjectService != null ? businessObjectService : KRADServiceLocator.getBusinessObjectService();
1290     }
1291 
1292     public void setBusinessObjectService(BusinessObjectService businessObjectService) {
1293         this.businessObjectService = businessObjectService;
1294     }
1295 
1296     protected LookupResultsService getLookupResultsService() {
1297         return lookupResultsService != null ? lookupResultsService : KNSServiceLocator.getLookupResultsService();
1298     }
1299 
1300     public void setLookupResultsService(LookupResultsService lookupResultsService) {
1301         this.lookupResultsService = lookupResultsService;
1302     }
1303 
1304     
1305 
1306 
1307 
1308     public boolean isSearchUsingOnlyPrimaryKeyValues() {
1309         
1310         return false;
1311     }
1312 
1313     
1314 
1315 
1316 
1317 
1318 
1319     public String getPrimaryKeyFieldLabels() {
1320         return KRADConstants.NOT_AVAILABLE_STRING;
1321     }
1322 
1323     
1324 
1325 
1326     public boolean isResultReturnable(BusinessObject object) {
1327         return true;
1328     }
1329 
1330     
1331 
1332 
1333 
1334 
1335     public void performClear(LookupForm lookupForm) {
1336         for (Iterator iter = this.getRows().iterator(); iter.hasNext();) {
1337             Row row = (Row) iter.next();
1338             for (Iterator iterator = row.getFields().iterator(); iterator.hasNext();) {
1339                 Field field = (Field) iterator.next();
1340                 if (field.isSecure()) {
1341                     field.setSecure(false);
1342                     field.setDisplayMaskValue(null);
1343                     field.setEncryptedValue(null);
1344                 }
1345 
1346                 if (!field.getFieldType().equals(Field.RADIO)) {
1347                     field.setPropertyValue(field.getDefaultValue());
1348                     if (field.getFieldType().equals(Field.MULTISELECT)) {
1349                         field.setPropertyValues(null);
1350                     }
1351                 }
1352             }
1353         }
1354     }
1355 
1356     
1357 
1358 
1359     public boolean shouldDisplayHeaderNonMaintActions() {
1360         return true;
1361     }
1362 
1363     
1364 
1365 
1366     public boolean shouldDisplayLookupCriteria() {
1367         return true;
1368     }
1369 
1370     
1371 
1372 
1373     public String getSupplementalMenuBar() {
1374         return new String();
1375     }
1376 
1377     
1378 
1379 
1380     public String getTitle() {
1381         return getBusinessObjectDictionaryService().getLookupTitle(getBusinessObjectClass());
1382     }
1383 
1384     
1385 
1386 
1387     public boolean performCustomAction(boolean ignoreErrors) {
1388         return false;
1389     }
1390 
1391     
1392 
1393 
1394     public Field getExtraField() {
1395         return null;
1396     }
1397 
1398     public boolean allowsNewOrCopyAction(String documentTypeName) {
1399         throw new UnsupportedOperationException("Function not supported.");
1400     }
1401 
1402     
1403 
1404 
1405 
1406 
1407     public void applyFieldAuthorizationsFromNestedLookups(Field field) {
1408         BusinessObjectAuthorizationService boAuthzService = this.getBusinessObjectAuthorizationService();
1409         if (!Field.MULTI_VALUE_FIELD_TYPES.contains(field.getFieldType())) {
1410             if (field.getPropertyValue() != null && field.getPropertyValue().endsWith(EncryptionService.ENCRYPTION_POST_PREFIX)) {
1411                 if (boAuthzService.attributeValueNeedsToBeEncryptedOnFormsAndLinks(businessObjectClass, field.getPropertyName())) {
1412                     AttributeSecurity attributeSecurity = getDataDictionaryService().getAttributeSecurity(businessObjectClass.getName(), field.getPropertyName());
1413                     Person user = GlobalVariables.getUserSession().getPerson();
1414                     String decryptedValue = "";
1415                     try {
1416                         String cipherText = StringUtils.removeEnd(field.getPropertyValue(), EncryptionService.ENCRYPTION_POST_PREFIX);
1417                         if(CoreApiServiceLocator.getEncryptionService().isEnabled()) {
1418                             decryptedValue = getEncryptionService().decrypt(cipherText);
1419                         }
1420                     } catch (GeneralSecurityException e) {
1421                         throw new RuntimeException("Error decrypting value for business object " + businessObjectClass + " attribute " + field.getPropertyName(), e);
1422                     }
1423                     if (attributeSecurity.isMask() && !boAuthzService.canFullyUnmaskField(user,
1424                             businessObjectClass, field.getPropertyName(), null)) {
1425                         MaskFormatter maskFormatter = attributeSecurity.getMaskFormatter();
1426                         field.setEncryptedValue(field.getPropertyValue());
1427                         field.setDisplayMaskValue(maskFormatter.maskValue(decryptedValue));
1428                         field.setSecure(true);
1429                     } else if (attributeSecurity.isPartialMask() && !boAuthzService.canPartiallyUnmaskField(user,
1430                             businessObjectClass, field.getPropertyName(), null)) {
1431                         MaskFormatter maskFormatter = attributeSecurity.getPartialMaskFormatter();
1432                         field.setEncryptedValue(field.getPropertyValue());
1433                         field.setDisplayMaskValue(maskFormatter.maskValue(decryptedValue));
1434                         field.setSecure(true);
1435                     } else {
1436                         field.setPropertyValue(org.kuali.rice.krad.lookup.LookupUtils
1437                                 .forceUppercase(businessObjectClass, field.getPropertyName(), decryptedValue));
1438                     }
1439                 } else {
1440                     throw new RuntimeException("Field " + field.getPersonNameAttributeName() + " was encrypted on " + businessObjectClass.getName() +
1441                             " lookup was encrypted when it should not have been encrypted according to the data dictionary.");
1442                 }
1443             }
1444         } else {
1445             if (boAuthzService.attributeValueNeedsToBeEncryptedOnFormsAndLinks(businessObjectClass, field.getPropertyName())) {
1446                 LOG.error("Cannot handle multiple value field types that have field authorizations, please implement custom lookupable helper service");
1447                 throw new RuntimeException("Cannot handle multiple value field types that have field authorizations.");
1448             }
1449         }
1450     }
1451 
1452     
1453 
1454 
1455 
1456 
1457 
1458 
1459 
1460 
1461 
1462     public void applyConditionalLogicForFieldDisplay() {
1463         Set<String> readOnlyFields = getConditionallyReadOnlyPropertyNames();
1464         Set<String> requiredFields = getConditionallyRequiredPropertyNames();
1465         Set<String> hiddenFields = getConditionallyHiddenPropertyNames();
1466 
1467         for (Iterator iter = this.getRows().iterator(); iter.hasNext();) {
1468             Row row = (Row) iter.next();
1469             for (Iterator iterator = row.getFields().iterator(); iterator.hasNext();) {
1470                 Field field = (Field) iterator.next();
1471 
1472                 if (readOnlyFields != null && readOnlyFields.contains(field.getPropertyName())) {
1473                     field.setReadOnly(true);
1474                 }
1475 
1476                 if (requiredFields != null && requiredFields.contains(field.getPropertyName())) {
1477                     field.setFieldRequired(true);
1478                 }
1479 
1480                 if (hiddenFields != null && hiddenFields.contains(field.getPropertyName())) {
1481                     field.setFieldType(Field.HIDDEN);
1482                 }
1483             }
1484         }
1485     }
1486 
1487     
1488 
1489 
1490 
1491 
1492     public Set<String> getConditionallyReadOnlyPropertyNames() {
1493         return new HashSet<String>();
1494     }
1495 
1496     
1497 
1498 
1499 
1500 
1501     public Set<String> getConditionallyRequiredPropertyNames() {
1502         return new HashSet<String>();
1503     }
1504 
1505     
1506 
1507 
1508 
1509 
1510     public Set<String> getConditionallyHiddenPropertyNames() {
1511         return new HashSet<String>();
1512     }
1513 
1514     
1515 
1516 
1517 
1518 
1519 
1520 
1521     protected String getCurrentSearchFieldValue(String propertyName) {
1522         String currentValue = null;
1523 
1524         boolean fieldFound = false;
1525         for (Iterator iter = this.getRows().iterator(); iter.hasNext();) {
1526             Row row = (Row) iter.next();
1527             for (Iterator iterator = row.getFields().iterator(); iterator.hasNext();) {
1528                 Field field = (Field) iterator.next();
1529 
1530                 if (StringUtils.equalsIgnoreCase(propertyName, field.getPropertyName())) {
1531                     if (Field.MULTI_VALUE_FIELD_TYPES.contains(field.getFieldType())) {
1532                         currentValue = StringUtils.join(field.getPropertyValues(), ";");
1533                     } else {
1534                         currentValue = field.getPropertyValue();
1535                     }
1536                     fieldFound = true;
1537                 }
1538 
1539                 if (fieldFound) {
1540                     break;
1541                 }
1542             }
1543 
1544             if (fieldFound) {
1545                 break;
1546             }
1547         }
1548 
1549         return currentValue;
1550     }
1551 }