View Javadoc

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