001/**
002 * Copyright 2005-2015 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.kns.inquiry;
017
018import org.apache.commons.collections.BidiMap;
019import org.apache.commons.collections.bidimap.DualHashBidiMap;
020import org.apache.commons.lang.StringUtils;
021import org.kuali.rice.core.api.CoreApiServiceLocator;
022import org.kuali.rice.core.api.config.property.ConfigurationService;
023import org.kuali.rice.core.api.encryption.EncryptionService;
024import org.kuali.rice.core.web.format.Formatter;
025import org.kuali.rice.kns.datadictionary.InquirySectionDefinition;
026import org.kuali.rice.kns.lookup.HtmlData;
027import org.kuali.rice.kns.lookup.HtmlData.AnchorHtmlData;
028import org.kuali.rice.kns.lookup.LookupUtils;
029import org.kuali.rice.kns.service.BusinessObjectAuthorizationService;
030import org.kuali.rice.kns.service.BusinessObjectDictionaryService;
031import org.kuali.rice.kns.service.BusinessObjectMetaDataService;
032import org.kuali.rice.kns.service.KNSServiceLocator;
033import org.kuali.rice.kns.util.InactiveRecordsHidingUtils;
034import org.kuali.rice.kns.web.ui.Section;
035import org.kuali.rice.kns.web.ui.SectionBridge;
036import org.kuali.rice.krad.bo.BusinessObject;
037import org.kuali.rice.krad.bo.DataObjectRelationship;
038import org.kuali.rice.krad.bo.DocumentHeader;
039import org.kuali.rice.krad.bo.ExternalizableBusinessObject;
040import org.kuali.rice.krad.datadictionary.AttributeSecurity;
041import org.kuali.rice.krad.inquiry.InquirableImpl;
042import org.kuali.rice.krad.lookup.CollectionIncomplete;
043import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
044import org.kuali.rice.krad.service.LookupService;
045import org.kuali.rice.krad.service.ModuleService;
046import org.kuali.rice.krad.util.ExternalizableBusinessObjectUtils;
047import org.kuali.rice.krad.util.GlobalVariables;
048import org.kuali.rice.krad.util.KRADConstants;
049import org.kuali.rice.krad.util.ObjectUtils;
050import org.kuali.rice.krad.util.UrlFactory;
051
052import java.security.GeneralSecurityException;
053import java.util.ArrayList;
054import java.util.Collection;
055import java.util.Collections;
056import java.util.HashMap;
057import java.util.Iterator;
058import java.util.List;
059import java.util.Map;
060import java.util.Properties;
061
062/**
063 * Kuali inquirable implementation. Implements methods necessary to retrieve the
064 * business object and render the ui.
065 * 
066 * NOTE: this class is not thread safe. When using this class or any subclasses
067 * in Spring, make sure that this is not a singleton service, or serious errors
068 * may occur.
069 * 
070 * @author Kuali Rice Team (rice.collab@kuali.org)
071 */
072public class KualiInquirableImpl extends InquirableImpl implements Inquirable {
073        private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KualiInquirableImpl.class);
074
075        protected LookupService lookupService;
076        protected BusinessObjectAuthorizationService businessObjectAuthorizationService;
077        protected BusinessObjectDictionaryService businessObjectDictionaryService;
078        protected BusinessObjectMetaDataService businessObjectMetaDataService;
079        protected EncryptionService encryptionService;
080
081        protected Map<String, Boolean> inactiveRecordDisplay;
082
083        public static final String INQUIRY_TITLE_PREFIX = "title.inquiry.url.value.prependtext";
084
085        /**
086         * Default constructor, initializes services from spring
087         */
088        public KualiInquirableImpl() {
089                inactiveRecordDisplay = new HashMap<String, Boolean>();
090        }
091
092        /**
093         * TODO: generics do not match between call to module service and call to
094         * lookup service
095         * 
096         * @see Inquirable#retrieveDataObject(java.util.Map)
097         */
098        @SuppressWarnings("rawtypes")
099        @Override
100        public Object retrieveDataObject(Map fieldValues) {
101                if (getDataObjectClass() == null) {
102                        LOG.error("Data object class not set in inquirable.");
103                        throw new RuntimeException(
104                                        "Data object class not set in inquirable.");
105                }
106
107                CollectionIncomplete<Object> searchResults = null;
108                ModuleService moduleService = KRADServiceLocatorWeb
109                                .getKualiModuleService().getResponsibleModuleService(
110                                                getDataObjectClass());
111                if (moduleService != null
112                                && moduleService.isExternalizable(getDataObjectClass())) {
113                        BusinessObject bo = moduleService.getExternalizableBusinessObject(
114                                        getBusinessObjectClass(), fieldValues);
115                        if (bo != null) {
116                                ArrayList<Object> list = new ArrayList<Object>(1);
117                                list.add(bo);
118                                searchResults = new CollectionIncomplete<Object>(list, 1L);
119                        }
120                } else {
121                        // TODO: If this is to get a single BO, why using the lookup
122                        // service?
123                        searchResults = (CollectionIncomplete<Object>) getLookupService()
124                                        .findCollectionBySearch(getBusinessObjectClass(),
125                                                        fieldValues);
126                }
127                
128                BusinessObject foundObject = null;
129                if (searchResults != null && searchResults.size() > 0) {
130                        foundObject = (BusinessObject) searchResults.get(0);
131                }
132                
133                return foundObject;
134        }
135
136    /**
137         * Return a business object by searching with map, the map keys should be a
138         * property name of the business object, with the map value as the value to
139         * search for.
140         */
141    @Deprecated
142        public BusinessObject getBusinessObject(Map fieldValues) {
143                return (BusinessObject) retrieveDataObject(fieldValues);
144        }
145
146        /**
147         * Objects extending KualiInquirableBase must specify the Section objects
148         * used to display the inquiry result.
149         */
150        @Deprecated
151        public List<Section> getSections(BusinessObject bo) {
152
153                List<Section> sections = new ArrayList<Section>();
154                if (getBusinessObjectClass() == null) {
155                        LOG.error("Business object class not set in inquirable.");
156                        throw new RuntimeException("Business object class not set in inquirable.");
157                }
158
159                InquiryRestrictions inquiryRestrictions = KNSServiceLocator.getBusinessObjectAuthorizationService()
160                                .getInquiryRestrictions(bo, GlobalVariables.getUserSession().getPerson());
161
162                Collection<InquirySectionDefinition> inquirySections = getBusinessObjectDictionaryService().getInquirySections(
163                                getBusinessObjectClass());
164                for (Iterator<InquirySectionDefinition> iter = inquirySections.iterator(); iter.hasNext();) {
165                        InquirySectionDefinition inquirySection = iter.next();
166                        if (!inquiryRestrictions.isHiddenSectionId(inquirySection.getId())) {
167                                Section section = SectionBridge.toSection(this, inquirySection, bo, inquiryRestrictions);
168                                sections.add(section);
169                        }
170                }
171
172                return sections;
173        }
174
175        /**
176         * Helper method to build an inquiry url for a result field.
177         * 
178         * @param bo
179         *            the business object instance to build the urls for
180         * @param propertyName
181         *            the property which links to an inquirable
182         * @return String url to inquiry
183         */
184        @Deprecated
185        public HtmlData getInquiryUrl(BusinessObject businessObject, String attributeName, boolean forceInquiry) {
186                Properties parameters = new Properties();
187                AnchorHtmlData hRef = new AnchorHtmlData(KRADConstants.EMPTY_STRING, KRADConstants.EMPTY_STRING);
188                parameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, "start");
189
190                Class inquiryBusinessObjectClass = null;
191                String attributeRefName = "";
192                boolean isPkReference = false;
193
194                boolean doesNestedReferenceHaveOwnPrimitiveReference = false;
195                BusinessObject nestedBusinessObject = null;
196
197                Class businessObjectClass = ObjectUtils.materializeClassForProxiedObject(businessObject);
198                if (attributeName.equals(getBusinessObjectDictionaryService().getTitleAttribute(businessObjectClass))) {
199                        inquiryBusinessObjectClass = businessObjectClass;
200                        isPkReference = true;
201                }
202                else {
203                        if (ObjectUtils.isNestedAttribute(attributeName)) {
204                                // if we have a reference object, we should determine if we
205                                // should either provide an inquiry link to
206                                // the reference object itself, or some other nested primitive.
207
208                                // for example, if the attribute is
209                                // "referenceObject.someAttribute", and there is no primitive
210                                // reference for
211                                // "someAttribute", then an inquiry link is provided to the
212                                // "referenceObject". If it does have a primitive reference,
213                                // then
214                                // the inquiry link is directed towards it instead
215                                String nestedReferenceName = ObjectUtils.getNestedAttributePrefix(attributeName);
216                                Object nestedReferenceObject = ObjectUtils.getNestedValue(businessObject, nestedReferenceName);
217
218                                if (ObjectUtils.isNotNull(nestedReferenceObject) && nestedReferenceObject instanceof BusinessObject) {
219                                        nestedBusinessObject = (BusinessObject) nestedReferenceObject;
220                                        String nestedAttributePrimitive = ObjectUtils.getNestedAttributePrimitive(attributeName);
221                                        Class nestedBusinessObjectClass = ObjectUtils
222                                                        .materializeClassForProxiedObject(nestedBusinessObject);
223
224                                        if (nestedAttributePrimitive.equals(getBusinessObjectDictionaryService().getTitleAttribute(
225                                                        nestedBusinessObjectClass))) {
226                                                // we are going to inquiry the record that contains the
227                                                // attribute we're rendering an inquiry URL for
228                                                inquiryBusinessObjectClass = nestedBusinessObjectClass;
229                                                // I know it's already set to false, just to show how
230                                                // this variable is set
231                                                doesNestedReferenceHaveOwnPrimitiveReference = false;
232                                        }
233                                        else {
234                                                Map primitiveReference = LookupUtils.getPrimitiveReference(nestedBusinessObject,
235                                                                nestedAttributePrimitive);
236                                                if (primitiveReference != null && !primitiveReference.isEmpty()) {
237                                                        attributeRefName = (String) primitiveReference.keySet().iterator().next();
238                                                        inquiryBusinessObjectClass = (Class) primitiveReference.get(attributeRefName);
239                                                        doesNestedReferenceHaveOwnPrimitiveReference = true;
240                                                }
241                                                else {
242                                                        // we are going to inquiry the record that contains
243                                                        // the attribute we're rendering an inquiry URL for
244                                                        inquiryBusinessObjectClass = ObjectUtils
245                                                                        .materializeClassForProxiedObject(nestedBusinessObject);
246                                                        // I know it's already set to false, just to show
247                                                        // how this variable is set
248                                                        doesNestedReferenceHaveOwnPrimitiveReference = false;
249                                                }
250                                        }
251                                }
252                        }
253                        else {
254                                Map primitiveReference = LookupUtils.getPrimitiveReference(businessObject, attributeName);
255                                if (primitiveReference != null && !primitiveReference.isEmpty()) {
256                                        attributeRefName = (String) primitiveReference.keySet().iterator().next();
257                                        inquiryBusinessObjectClass = (Class) primitiveReference.get(attributeRefName);
258                                }
259                        }
260                }
261
262                if (inquiryBusinessObjectClass != null && DocumentHeader.class.isAssignableFrom(inquiryBusinessObjectClass)) {
263                        String documentNumber = (String) ObjectUtils.getPropertyValue(businessObject, attributeName);
264                        if (!StringUtils.isBlank(documentNumber)) {
265                                // if NullPointerException on the following line, maybe the
266                                // Spring bean wasn't injected w/ KualiConfigurationException,
267                                // or if
268                                // instances of a sub-class of this class are not Spring
269                                // created, then override getKualiConfigurationService() in the
270                                // subclass
271                                // to return the configuration service from a Spring service
272                                // locator (or set it).
273                                hRef.setHref(getKualiConfigurationService().getPropertyValueAsString(KRADConstants.WORKFLOW_URL_KEY)
274                                                + KRADConstants.DOCHANDLER_DO_URL + documentNumber + KRADConstants.DOCHANDLER_URL_CHUNK);
275                        }
276                        return hRef;
277                }
278
279                if (inquiryBusinessObjectClass == null
280                                || getBusinessObjectDictionaryService().isInquirable(inquiryBusinessObjectClass) == null
281                                || !getBusinessObjectDictionaryService().isInquirable(inquiryBusinessObjectClass).booleanValue()) {
282                        return hRef;
283                }
284
285                synchronized (SUPER_CLASS_TRANSLATOR_LIST) {
286                        for (Class clazz : SUPER_CLASS_TRANSLATOR_LIST) {
287                                if (clazz.isAssignableFrom(inquiryBusinessObjectClass)) {
288                                        inquiryBusinessObjectClass = clazz;
289                                        break;
290                                }
291                        }
292                }
293
294                if (!inquiryBusinessObjectClass.isInterface()
295                                && ExternalizableBusinessObject.class.isAssignableFrom(inquiryBusinessObjectClass)) {
296                        inquiryBusinessObjectClass = ExternalizableBusinessObjectUtils
297                                        .determineExternalizableBusinessObjectSubInterface(inquiryBusinessObjectClass);
298                }
299
300                parameters.put(KRADConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, inquiryBusinessObjectClass.getName());
301
302                // listPrimaryKeyFieldNames returns an unmodifiable list. So a copy is
303                // necessary.
304                List<String> keys = new ArrayList<String>(getBusinessObjectMetaDataService().listPrimaryKeyFieldNames(
305                                inquiryBusinessObjectClass));
306
307                if (keys == null) {
308                        keys = Collections.emptyList();
309                }
310
311                DataObjectRelationship dataObjectRelationship = null;
312
313                if (attributeRefName != null && !"".equals(attributeRefName)) {
314                        dataObjectRelationship = getBusinessObjectMetaDataService().getBusinessObjectRelationship(
315                                        businessObject, attributeRefName);
316
317                        if (dataObjectRelationship != null && dataObjectRelationship.getParentToChildReferences() != null) {
318                                for (String targetNamePrimaryKey : dataObjectRelationship.getParentToChildReferences().values()) {
319                                        keys.add(targetNamePrimaryKey);
320                                }
321                        }
322                }
323                // build key value url parameters used to retrieve the business object
324                String keyName = null;
325                String keyConversion = null;
326                Map<String, String> fieldList = new HashMap<String, String>();
327                for (Iterator iter = keys.iterator(); iter.hasNext();) {
328                        keyName = (String) iter.next();
329                        keyConversion = keyName;
330                        if (ObjectUtils.isNestedAttribute(attributeName)) {
331                                if (doesNestedReferenceHaveOwnPrimitiveReference) {
332                                        String nestedAttributePrefix = ObjectUtils.getNestedAttributePrefix(attributeName);
333                                        // String foreignKeyFieldName =
334                                        // getBusinessObjectMetaDataService().getForeignKeyFieldName(
335                                        // inquiryBusinessObjectClass.getClass(), attributeRefName,
336                                        // keyName);
337
338                                        String foreignKeyFieldName = getBusinessObjectMetaDataService().getForeignKeyFieldName(
339                                                        nestedBusinessObject.getClass(), attributeRefName, keyName);
340                                        keyConversion = nestedAttributePrefix + "." + foreignKeyFieldName;
341                                }
342                                else {
343                                        keyConversion = ObjectUtils.getNestedAttributePrefix(attributeName) + "." + keyName;
344                                }
345                        }
346                        else {
347                                if (isPkReference) {
348                                        keyConversion = keyName;
349                                }
350                                else if (dataObjectRelationship != null) {
351                                        // Using BusinessObjectMetaDataService instead of
352                                        // PersistenceStructureService
353                                        // since otherwise, relationship information from
354                                        // datadictionary is not used at all
355                                        // Also, BOMDS.getBusinessObjectRelationship uses
356                                        // PersistenceStructureService,
357                                        // so both datadictionary and the persistance layer get
358                                        // covered
359                                        /*
360                                         * DataObjectRelationship dataObjectRelationship =
361                                         * getBusinessObjectMetaDataService
362                                         * ().getBusinessObjectRelationship( businessObject,
363                                         * attributeRefName);
364                                         */
365                                        BidiMap bidiMap = new DualHashBidiMap(dataObjectRelationship.getParentToChildReferences());
366                                        keyConversion = (String) bidiMap.getKey(keyName);
367                                        // keyConversion =
368                                        // getPersistenceStructureService().getForeignKeyFieldName(businessObject.getClass(),
369                                        // attributeRefName, keyName);
370                                }
371                        }
372                        Object keyValue = null;
373                        if (keyConversion != null) {
374                                keyValue = ObjectUtils.getPropertyValue(businessObject, keyConversion);
375                        }
376
377                        if (keyValue == null) {
378                                keyValue = "";
379                        }
380                        else if (keyValue instanceof java.sql.Date) { // format the date for
381                                                                                                                        // passing in url
382                                if (Formatter.findFormatter(keyValue.getClass()) != null) {
383                                        Formatter formatter = Formatter.getFormatter(keyValue.getClass());
384                                        keyValue = (String) formatter.format(keyValue);
385                                }
386                        }
387                        else {
388                                keyValue = keyValue.toString();
389                        }
390
391                        // Encrypt value if it is a field that has restriction that prevents
392                        // a value from being shown to user,
393                        // because we don't want the browser history to store the restricted
394                        // attribute's value in the URL
395                        AttributeSecurity attributeSecurity = KRADServiceLocatorWeb.getDataDictionaryService().getAttributeSecurity(
396                                        businessObject.getClass().getName(), keyName);
397                        if (attributeSecurity != null && attributeSecurity.hasRestrictionThatRemovesValueFromUI()) {
398                                try {
399                    if(CoreApiServiceLocator.getEncryptionService().isEnabled()) {
400                                            keyValue = getEncryptionService().encrypt(keyValue);
401                    }
402                                }
403                                catch (GeneralSecurityException e) {
404                                        LOG.error("Exception while trying to encrypted value for inquiry framework.", e);
405                                        throw new RuntimeException(e);
406                                }
407                        }
408
409                        parameters.put(keyName, keyValue);
410                        fieldList.put(keyName, keyValue.toString());
411                }
412
413                return getHyperLink(inquiryBusinessObjectClass, fieldList,
414                                UrlFactory.parameterizeUrl(KRADConstants.INQUIRY_ACTION, parameters));
415        }
416
417        @Deprecated
418        protected AnchorHtmlData getHyperLink(Class inquiryClass, Map<String, String> fieldList, String inquiryUrl) {
419                AnchorHtmlData a = new AnchorHtmlData(inquiryUrl, KRADConstants.EMPTY_STRING);
420                a.setTitle(HtmlData.getTitleText(this.createTitleText(inquiryClass), inquiryClass, fieldList));
421                return a;
422        }
423
424        /**
425         * Gets text to prepend to the inquiry link title
426         * 
427         * @param dataObjectClass
428         *            - data object class being inquired into
429         * @return String title prepend text
430         */
431        @Deprecated
432        protected String createTitleText(Class<?> dataObjectClass) {
433                String titleText = "";
434
435                String titlePrefixProp = getKualiConfigurationService().getPropertyValueAsString(INQUIRY_TITLE_PREFIX);
436                if (StringUtils.isNotBlank(titlePrefixProp)) {
437                        titleText += titlePrefixProp + " ";
438                }
439
440                String objectLabel = getDataDictionaryService().getDataDictionary()
441                                .getBusinessObjectEntry(dataObjectClass.getName()).getObjectLabel();
442                if (StringUtils.isNotBlank(objectLabel)) {
443                        titleText += objectLabel + " ";
444                }
445
446                return titleText;
447        }
448
449        @Deprecated
450        public void addAdditionalSections(List columns, BusinessObject bo) {
451        }
452
453        /**
454         * @see Inquirable#getHtmlMenuBar()
455         */
456        @Deprecated
457        public String getHtmlMenuBar() {
458                // TODO: replace with inquiry menu bar
459                return getBusinessObjectDictionaryService().getLookupMenuBar(getBusinessObjectClass());
460        }
461
462        /**
463         * @see Inquirable#getTitle()
464         */
465        @Deprecated
466        public String getTitle() {
467                return getBusinessObjectDictionaryService().getInquiryTitle(getBusinessObjectClass());
468        }
469
470    /**
471         * @param businessObjectClass
472         *            The dataObjectClass to set.
473         */
474        @Deprecated
475        public void setBusinessObjectClass(Class businessObjectClass) {
476                this.dataObjectClass = businessObjectClass;
477        }
478
479        /**
480     * @return Returns the dataObjectClass.
481     */
482    @Deprecated
483    public Class getBusinessObjectClass() {
484        return dataObjectClass;
485    }
486    
487        /**
488         * @see Inquirable#getInactiveRecordDisplay()
489         */
490        @Deprecated
491        public Map<String, Boolean> getInactiveRecordDisplay() {
492                return inactiveRecordDisplay;
493        }
494
495        /**
496         * @see Inquirable#getShowInactiveRecords(java.lang.String)
497         */
498        @Deprecated
499        public boolean getShowInactiveRecords(String collectionName) {
500                return InactiveRecordsHidingUtils.getShowInactiveRecords(inactiveRecordDisplay, collectionName);
501        }
502
503        /**
504         * @see Inquirable#setShowInactiveRecords(java.lang.String,
505         *      boolean)
506         */
507        @Deprecated
508        public void setShowInactiveRecords(String collectionName, boolean showInactive) {
509                InactiveRecordsHidingUtils.setShowInactiveRecords(inactiveRecordDisplay, collectionName, showInactive);
510        }
511
512        protected LookupService getLookupService() {
513                if (lookupService == null) {
514                        lookupService = KRADServiceLocatorWeb.getLookupService();
515                }
516                return lookupService;
517        }
518
519        public void setLookupService(LookupService lookupService) {
520                this.lookupService = lookupService;
521        }
522
523        protected BusinessObjectDictionaryService getBusinessObjectDictionaryService() {
524                if (businessObjectDictionaryService == null) {
525                        businessObjectDictionaryService = KNSServiceLocator.getBusinessObjectDictionaryService();
526                }
527                return businessObjectDictionaryService;
528        }
529
530        public void setBusinessObjectDictionaryService(BusinessObjectDictionaryService businessObjectDictionaryService) {
531                this.businessObjectDictionaryService = businessObjectDictionaryService;
532        }
533
534        protected EncryptionService getEncryptionService() {
535                if (encryptionService == null) {
536                        encryptionService = CoreApiServiceLocator.getEncryptionService();
537                }
538                return this.encryptionService;
539        }
540
541        public void setEncryptionService(EncryptionService encryptionService) {
542                this.encryptionService = encryptionService;
543        }
544
545        protected ConfigurationService getKualiConfigurationService() {
546                return getConfigurationService();
547        }
548
549        protected BusinessObjectMetaDataService getBusinessObjectMetaDataService() {
550                if (businessObjectMetaDataService == null) {
551                        businessObjectMetaDataService = KNSServiceLocator.getBusinessObjectMetaDataService();
552                }
553                return this.businessObjectMetaDataService;
554        }
555
556        public void setBusinessObjectMetaDataService(BusinessObjectMetaDataService businessObjectMetaDataService) {
557                this.businessObjectMetaDataService = businessObjectMetaDataService;
558        }
559
560        protected BusinessObjectAuthorizationService getBusinessObjectAuthorizationService() {
561                if (this.businessObjectAuthorizationService == null) {
562                        this.businessObjectAuthorizationService = KNSServiceLocator.getBusinessObjectAuthorizationService();
563                }
564                return this.businessObjectAuthorizationService;
565        }
566
567        public void setBusinessObjectAuthorizationService(
568                        BusinessObjectAuthorizationService businessObjectAuthorizationService) {
569                this.businessObjectAuthorizationService = businessObjectAuthorizationService;
570        }
571
572        @Deprecated
573        protected AnchorHtmlData getInquiryUrlForPrimaryKeys(Class clazz, Object businessObject, List<String> primaryKeys,
574                        String displayText) {
575                if (businessObject == null)
576                        return new AnchorHtmlData(KRADConstants.EMPTY_STRING, KRADConstants.EMPTY_STRING);
577
578                Properties parameters = new Properties();
579                parameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, KRADConstants.START_METHOD);
580                parameters.put(KRADConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, clazz.getName());
581
582                String titleAttributeValue;
583                Map<String, String> fieldList = new HashMap<String, String>();
584                for (String primaryKey : primaryKeys) {
585                        titleAttributeValue = (String) ObjectUtils.getPropertyValue(businessObject, primaryKey);
586                        parameters.put(primaryKey, titleAttributeValue);
587                        fieldList.put(primaryKey, titleAttributeValue);
588                }
589                if (StringUtils.isEmpty(displayText))
590                        return getHyperLink(clazz, fieldList, UrlFactory.parameterizeUrl(KRADConstants.INQUIRY_ACTION, parameters));
591                else
592                        return getHyperLink(clazz, fieldList, UrlFactory.parameterizeUrl(KRADConstants.INQUIRY_ACTION, parameters),
593                                        displayText);
594        }
595
596        @Deprecated
597        protected AnchorHtmlData getHyperLink(Class inquiryClass, Map<String, String> fieldList, String inquiryUrl,
598                        String displayText) {
599                AnchorHtmlData a = new AnchorHtmlData(inquiryUrl, KRADConstants.EMPTY_STRING, displayText);
600                a.setTitle(AnchorHtmlData.getTitleText(getKualiConfigurationService().getPropertyValueAsString(
601                INQUIRY_TITLE_PREFIX)
602                                + " "
603                                + getDataDictionaryService().getDataDictionary().getBusinessObjectEntry(inquiryClass.getName())
604                                                .getObjectLabel() + " ", inquiryClass, fieldList));
605                return a;
606        }
607
608}