001/**
002 * Copyright 2005-2017 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.service.impl;
017
018import org.apache.commons.beanutils.PropertyUtils;
019import org.apache.commons.lang.StringUtils;
020import org.apache.log4j.Logger;
021import org.kuali.rice.kew.api.KewApiServiceLocator;
022import org.kuali.rice.kns.datadictionary.BusinessObjectEntry;
023import org.kuali.rice.kns.datadictionary.FieldDefinition;
024import org.kuali.rice.kns.datadictionary.InquiryDefinition;
025import org.kuali.rice.kns.datadictionary.InquirySectionDefinition;
026import org.kuali.rice.kns.datadictionary.LookupDefinition;
027import org.kuali.rice.kns.datadictionary.MaintenanceDocumentEntry;
028import org.kuali.rice.kns.inquiry.InquiryAuthorizer;
029import org.kuali.rice.kns.inquiry.InquiryAuthorizerBase;
030import org.kuali.rice.kns.inquiry.InquiryPresentationController;
031import org.kuali.rice.kns.inquiry.InquiryPresentationControllerBase;
032import org.kuali.rice.kns.service.BusinessObjectDictionaryService;
033import org.kuali.rice.krad.bo.BusinessObject;
034import org.kuali.rice.krad.bo.PersistableBusinessObject;
035import org.kuali.rice.krad.bo.PersistableBusinessObjectBaseAdapter;
036import org.kuali.rice.krad.exception.IntrospectionException;
037import org.kuali.rice.krad.service.DataDictionaryService;
038import org.kuali.rice.krad.service.PersistenceStructureService;
039import org.kuali.rice.krad.util.ObjectUtils;
040import org.kuali.rice.krad.valuefinder.ValueFinder;
041
042import java.beans.IndexedPropertyDescriptor;
043import java.beans.PropertyDescriptor;
044import java.lang.reflect.InvocationTargetException;
045import java.util.ArrayList;
046import java.util.Collection;
047import java.util.HashSet;
048import java.util.Iterator;
049import java.util.List;
050import java.util.Set;
051
052/**
053 * This class is the service implementation for the BusinessObjectDictionary.
054 * This is the default, Kuali delivered implementation which leverages the
055 * DataDictionaryService.
056 *
057 * @deprecated Only used by KNS classes, use KRAD.
058 */
059@Deprecated
060public class BusinessObjectDictionaryServiceImpl implements BusinessObjectDictionaryService {
061        private static Logger LOG = Logger
062                        .getLogger(BusinessObjectDictionaryServiceImpl.class);
063
064    private DataDictionaryService dataDictionaryService;
065    private PersistenceStructureService persistenceStructureService;
066
067        public <T extends BusinessObject> InquiryAuthorizer getInquiryAuthorizer(
068                        Class<T> businessObjectClass) {
069                Class inquiryAuthorizerClass = ((BusinessObjectEntry) getDataDictionaryService()
070                                .getDataDictionary().getBusinessObjectEntry(
071                                                businessObjectClass.getName())).getInquiryDefinition()
072                                .getAuthorizerClass();
073                if (inquiryAuthorizerClass == null) {
074                        inquiryAuthorizerClass = InquiryAuthorizerBase.class;
075                }
076                try {
077                        return (InquiryAuthorizer) inquiryAuthorizerClass.newInstance();
078                } catch (Exception e) {
079                        throw new RuntimeException(
080                                        "Unable to instantiate InquiryAuthorizer class: "
081                                                        + inquiryAuthorizerClass, e);
082                }
083        }
084
085        public <T extends BusinessObject> InquiryPresentationController getInquiryPresentationController(
086                        Class<T> businessObjectClass) {
087                Class inquiryPresentationControllerClass = ((BusinessObjectEntry) getDataDictionaryService()
088                                .getDataDictionary().getBusinessObjectEntry(
089                                                businessObjectClass.getName())).getInquiryDefinition()
090                                .getPresentationControllerClass();
091                if (inquiryPresentationControllerClass == null) {
092                        inquiryPresentationControllerClass = InquiryPresentationControllerBase.class;
093                }
094                try {
095                        return (InquiryPresentationController) inquiryPresentationControllerClass
096                                        .newInstance();
097                } catch (Exception e) {
098                        throw new RuntimeException(
099                                        "Unable to instantiate InquiryPresentationController class: "
100                                                        + inquiryPresentationControllerClass, e);
101                }
102        }
103
104    /**
105     * Uses the DataDictionaryService.
106     *
107     * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getBusinessObjectEntries()
108     */
109    public List getBusinessObjectClassnames() {
110                return getDataDictionaryService().getDataDictionary()
111                                .getBusinessObjectClassNames();
112    }
113
114    /**
115     * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#isLookupable(java.lang.Class)
116     */
117    public Boolean isLookupable(Class businessObjectClass) {
118        Boolean isLookupable = Boolean.FALSE;
119
120        BusinessObjectEntry entry = getBusinessObjectEntry(businessObjectClass);
121        if (entry != null) {
122            isLookupable = Boolean.valueOf(entry.hasLookupDefinition());
123        }
124
125        return isLookupable;
126    }
127
128    /**
129     * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#isInquirable(java.lang.Class)
130     */
131    public Boolean isInquirable(Class businessObjectClass) {
132        Boolean isInquirable = Boolean.FALSE;
133
134        BusinessObjectEntry entry = getBusinessObjectEntry(businessObjectClass);
135        if (entry != null) {
136            isInquirable = Boolean.valueOf(entry.hasInquiryDefinition());
137        }
138
139        return isInquirable;
140    }
141
142    /**
143     * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#isMaintainable(java.lang.Class)
144     */
145    public Boolean isMaintainable(Class businessObjectClass) {
146        Boolean isMaintainable = Boolean.FALSE;
147
148        BusinessObjectEntry entry = getBusinessObjectEntry(businessObjectClass);
149        if (entry != null) {
150                        isMaintainable = Boolean
151                                        .valueOf(getMaintenanceDocumentEntry(businessObjectClass) != null);
152        }
153
154        return isMaintainable;
155    }
156    
157
158    /**
159         * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#isExportable(java.lang.Class)
160         */
161        public Boolean isExportable(Class businessObjectClass) {
162                Boolean isExportable = Boolean.FALSE;
163                
164                BusinessObjectEntry entry = getBusinessObjectEntry(businessObjectClass);
165        if (entry != null) {
166            isExportable = entry.getExporterClass() != null;
167        }
168
169        return isExportable;
170        }
171
172        /**
173     * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getLookupFieldNames(java.lang.Class)
174     */
175    public List getLookupFieldNames(Class businessObjectClass) {
176        List results = null;
177
178        LookupDefinition lookupDefinition = getLookupDefinition(businessObjectClass);
179        if (lookupDefinition != null) {
180            results = lookupDefinition.getLookupFieldNames();
181        }
182
183        return results;
184    }
185
186
187    /**
188     * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getLookupTitle(java.lang.Class)
189     */
190    public String getLookupTitle(Class businessObjectClass) {
191        String lookupTitle = "";
192
193        LookupDefinition lookupDefinition = getLookupDefinition(businessObjectClass);
194        if (lookupDefinition != null) {
195            lookupTitle = lookupDefinition.getTitle();
196        }
197
198        return lookupTitle;
199    }
200
201    /**
202     * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getLookupMenuBar(java.lang.Class)
203     */
204    public String getLookupMenuBar(Class businessObjectClass) {
205        String menubar = "";
206
207        LookupDefinition lookupDefinition = getLookupDefinition(businessObjectClass);
208        if (lookupDefinition != null) {
209            if (lookupDefinition.hasMenubar()) {
210                menubar = lookupDefinition.getMenubar();
211            }
212        }
213
214        return menubar;
215    }
216
217
218    /**
219     * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getExtraButtonSource(java.lang.Class)
220     */
221    public String getExtraButtonSource(Class businessObjectClass) {
222        String buttonSource = "";
223
224        LookupDefinition lookupDefinition = getLookupDefinition(businessObjectClass);
225        if (lookupDefinition != null) {
226            if (lookupDefinition.hasExtraButtonSource()) {
227                buttonSource = lookupDefinition.getExtraButtonSource();
228            }
229        }
230
231        return buttonSource;
232    }
233
234    /**
235     * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getExtraButtonParams(java.lang.Class)
236     */
237    public String getExtraButtonParams(Class businessObjectClass) {
238        String buttonParams = "";
239
240        LookupDefinition lookupDefinition = getLookupDefinition(businessObjectClass);
241        if (lookupDefinition != null) {
242            if (lookupDefinition.hasExtraButtonParams()) {
243                buttonParams = lookupDefinition.getExtraButtonParams();
244            }
245        }
246
247        return buttonParams;
248    }
249
250    
251    /**
252     * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getSearchIconOverride(java.lang.Class)
253     */
254    public String getSearchIconOverride(Class businessObjectClass) {
255        String iconUrl = "";
256
257        LookupDefinition lookupDefinition = getLookupDefinition(businessObjectClass);
258        if (lookupDefinition != null) {
259            if (lookupDefinition.hasSearchIconOverride()) {
260                iconUrl = lookupDefinition.getSearchIconOverride();
261            }
262        }
263
264        return iconUrl;
265    }
266
267    
268    /**
269     * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getLookupDefaultSortFieldName(java.lang.Class)
270     */
271    public List<String> getLookupDefaultSortFieldNames(Class businessObjectClass) {
272        List<String> defaultSort = null;
273
274        LookupDefinition lookupDefinition = getLookupDefinition(businessObjectClass);
275        if (lookupDefinition != null) {
276            if (lookupDefinition.hasDefaultSort()) {
277                                defaultSort = lookupDefinition.getDefaultSort()
278                                                .getAttributeNames();
279            }
280        }
281        if (defaultSort == null) {
282            defaultSort = new ArrayList<String>();
283        }
284
285        return defaultSort;
286    }
287
288    /**
289     * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getLookupResultFieldNames(java.lang.Class)
290     */
291    public List<String> getLookupResultFieldNames(Class businessObjectClass) {
292        List<String> results = null;
293
294        LookupDefinition lookupDefinition = getLookupDefinition(businessObjectClass);
295        if (lookupDefinition != null) {
296            results = lookupDefinition.getResultFieldNames();
297        }
298
299        return results;
300    }
301
302    /**
303         * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getLookupResultFieldMaxLength(java.lang.Class,
304         *      java.lang.String)
305     */
306        public Integer getLookupResultFieldMaxLength(Class businessObjectClass,
307                        String resultFieldName) {
308                Integer resultFieldMaxLength = null;
309
310                LookupDefinition lookupDefinition = getLookupDefinition(businessObjectClass);
311                if (lookupDefinition != null) {
312                        FieldDefinition field = lookupDefinition.getResultField(resultFieldName);
313                        if (field != null) {
314                                resultFieldMaxLength = field.getMaxLength();
315                        }
316                }
317
318                return resultFieldMaxLength;
319    }
320
321    /**
322     * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getLookupResultSetLimit(java.lang.Class)
323     */
324    public Integer getLookupResultSetLimit(Class businessObjectClass) {
325        LookupDefinition lookupDefinition = getLookupDefinition(businessObjectClass);
326        if ( lookupDefinition != null ) {
327                        return lookupDefinition.getResultSetLimit(); // TODO: stupid, change
328                                                                                                                        // to return int
329        } else {
330            return null;
331        }
332    }
333    
334    /**
335     * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getMultipleValueLookupResultSetLimit(java.lang.Class)
336     */
337    public Integer getMultipleValueLookupResultSetLimit(Class businessObjectClass) {
338        LookupDefinition lookupDefinition = getLookupDefinition(businessObjectClass);
339        if ( lookupDefinition != null ) {
340            return lookupDefinition.getMultipleValuesResultSetLimit();                                          
341        } else {
342            return null;
343        }
344    }
345
346        /**
347         * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getLookupNumberOfColumns(java.lang.Class)
348         */
349        public Integer getLookupNumberOfColumns(Class businessObjectClass) {
350                // default to 1
351                int numberOfColumns = 1;
352
353                LookupDefinition lookupDefinition = getLookupDefinition(businessObjectClass);
354                if (lookupDefinition != null) {
355                        if (lookupDefinition.getNumOfColumns() > 1) {
356                                numberOfColumns = lookupDefinition.getNumOfColumns();
357                        }
358                }
359
360                return numberOfColumns;
361        }
362
363        /**
364         * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getLookupAttributeRequired(java.lang.Class,
365         *      java.lang.String)
366     */
367        public Boolean getLookupAttributeRequired(Class businessObjectClass,
368                        String attributeName) {
369        Boolean isRequired = null;
370
371                FieldDefinition definition = getLookupFieldDefinition(
372                                businessObjectClass, attributeName);
373        if (definition != null) {
374            isRequired = Boolean.valueOf(definition.isRequired());
375        }
376
377        return isRequired;
378    }
379
380        /**
381         * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getLookupAttributeReadOnly(java.lang.Class,
382         *      java.lang.String)
383         */
384        public Boolean getLookupAttributeReadOnly(Class businessObjectClass, String attributeName) {
385                Boolean readOnly = null;
386
387                FieldDefinition definition = getLookupFieldDefinition(businessObjectClass, attributeName);
388                if (definition != null) {
389                        readOnly = Boolean.valueOf(definition.isReadOnly());
390                }
391
392                return readOnly;
393        }
394
395        /**
396         * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getInquiryFieldNames(java.lang.Class,
397         *      java.lang.String)
398     */
399        public List getInquiryFieldNames(Class businessObjectClass,
400                        String sectionTitle) {
401        List results = null;
402
403                InquirySectionDefinition inquirySection = getInquiryDefinition(
404                                businessObjectClass).getInquirySection(sectionTitle);
405        if (inquirySection != null) {
406            results = inquirySection.getInquiryFieldNames();
407        }
408
409        return results;
410    }
411
412    /**
413     * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getInquirySections(java.lang.Class)
414     */
415    public List<InquirySectionDefinition> getInquirySections(Class businessObjectClass) {
416        List<InquirySectionDefinition> results = null;
417
418                results = getInquiryDefinition(businessObjectClass)
419                                .getInquirySections();
420
421        return results;
422    }
423
424    /**
425     * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getInquiryTitle(java.lang.Class)
426     */
427    public String getInquiryTitle(Class businessObjectClass) {
428        String title = "";
429
430        InquiryDefinition inquiryDefinition = getInquiryDefinition(businessObjectClass);
431        if (inquiryDefinition != null) {
432            title = inquiryDefinition.getTitle();
433        }
434
435        return title;
436    }
437
438    /**
439     * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getInquirableClass(java.lang.Class)
440     */
441    public Class getInquirableClass(Class businessObjectClass) {
442        Class clazz = null;
443
444        InquiryDefinition inquiryDefinition = getInquiryDefinition(businessObjectClass);
445        if (inquiryDefinition != null) {
446            clazz = inquiryDefinition.getInquirableClass();
447        }
448
449        return clazz;
450    }
451
452    /**
453     * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getMaintainableTitle(java.lang.Class)
454     */
455    public String getMaintainableLabel(Class businessObjectClass) {
456        String label = "";
457
458        MaintenanceDocumentEntry entry = getMaintenanceDocumentEntry(businessObjectClass);
459        if (entry != null) {
460            label = KewApiServiceLocator.getDocumentTypeService().getDocumentTypeByName(entry.getDocumentTypeName()).getLabel();
461        }
462
463        return label;
464    }
465
466    /**
467     *
468     * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getLookupableID(java.lang.Class)
469     */
470    public String getLookupableID(Class businessObjectClass) {
471        String lookupableID = null;
472
473        LookupDefinition lookupDefinition = getLookupDefinition(businessObjectClass);
474        if (lookupDefinition != null) {
475            lookupableID = lookupDefinition.getLookupableID();
476        }
477
478        return lookupableID;
479    }
480
481
482    /**
483         * Recurses down the updatable references and collections of a BO,
484         * uppercasing those attributes which are marked as needing to be uppercased
485         * in the data dictionary. Updatability of a reference or collection is
486         * defined by the PersistenceStructureService
487     *
488         * @param bo
489         *            the BO to uppercase
490     *
491     * @see PersistenceStructureService#isCollectionUpdatable(Class, String)
492     * @see PersistenceStructureService#isReferenceUpdatable(Class, String)
493     * @see DataDictionaryService#getAttributeForceUppercase(Class, String)
494     */
495    public void performForceUppercase(BusinessObject bo) {
496        performForceUppercaseCycleSafe(bo, new HashSet<BusinessObject>());
497    }
498    
499    /**
500     * Handles recursion for performForceUppercase in a cycle-safe manner,
501     * keeping track of visited BusinessObjects to prevent infinite recursion.
502     */
503    protected void performForceUppercaseCycleSafe(BusinessObject bo, Set<BusinessObject> visited) {
504        if (visited.contains(bo)) {
505                return;
506        } else {
507                visited.add(bo);
508        }
509                PropertyDescriptor descriptors[] = PropertyUtils
510                                .getPropertyDescriptors(bo);
511        for (int i = 0; i < descriptors.length; ++i) {
512            try {
513                if (descriptors[i] instanceof IndexedPropertyDescriptor) {
514                                        // Skip this case because PropertyUtils.getProperty(bo,
515                                        // descriptors[i].getName()) will throw a
516                    // NoSuchMethodException on those. These
517                                        // fields are usually convenience methods in the BO and in
518                                        // the below code we anyway wouldn't know which index
519                    // .toUpperCase().
520                                } else {
521                                        Object nestedObject = ObjectUtils.getPropertyValue(bo,
522                                                        descriptors[i].getName());
523                                        if (ObjectUtils.isNotNull(nestedObject)
524                                                        && nestedObject instanceof BusinessObject) {
525                                                if (persistenceStructureService
526                                                                .isPersistable(nestedObject.getClass())) {
527                                try {
528                                                                if (persistenceStructureService.hasReference(bo
529                                                                                .getClass(), descriptors[i].getName())) {
530                                                                        if (persistenceStructureService
531                                                                                        .isReferenceUpdatable(
532                                                                                                        bo.getClass(),
533                                                                                                        descriptors[i].getName())) {
534                                                                                if (persistenceStructureService
535                                                                                                .getForeignKeyFieldsPopulationState(
536                                                                                                                (PersistableBusinessObject) bo,
537                                                                                                                descriptors[i]
538                                                                                                                                .getName())
539                                                                                                .isAllFieldsPopulated()) {
540                                                                                        // check FKs to prevent probs caused
541                                                                                        // by referential integrity problems
542                                            performForceUppercaseCycleSafe((BusinessObject) nestedObject, visited);
543                                    }
544                                    }
545                                }
546                                } catch (org.kuali.rice.krad.exception.ReferenceAttributeNotAnOjbReferenceException ranaore) {
547                                                                LOG.debug("Propery " + descriptors[i].getName()
548                                                                                + " is not a foreign key reference.");
549                                }
550                            }
551                    } else if (nestedObject instanceof String) {
552                                                if (dataDictionaryService.isAttributeDefined(
553                                                                bo.getClass(), descriptors[i].getName())
554                                                                .booleanValue()
555                                                                && dataDictionaryService
556                                                                                .getAttributeForceUppercase(
557                                                                                                bo.getClass(),
558                                                                                                descriptors[i].getName())
559                                                                                .booleanValue()) {
560                            String curValue = (String) nestedObject;
561                                                        PropertyUtils.setProperty(bo, descriptors[i]
562                                                                        .getName(), curValue.toUpperCase());
563                        }
564                                        } else {
565                                                if (ObjectUtils.isNotNull(nestedObject)
566                                                                && nestedObject instanceof Collection) {
567                                                        if (persistenceStructureService.hasCollection(bo
568                                                                        .getClass(), descriptors[i].getName())) {
569                                                                if (persistenceStructureService
570                                                                                .isCollectionUpdatable(bo.getClass(),
571                                                                                                descriptors[i].getName())) {
572                                                                        Iterator iter = ((Collection) nestedObject)
573                                                                                        .iterator();
574                            while (iter.hasNext()) {
575                                Object collElem = iter.next();
576                                if (collElem instanceof BusinessObject) {
577                                                                                        if (persistenceStructureService
578                                                                                                        .isPersistable(collElem
579                                                                                                                        .getClass())) {
580                                                performForceUppercaseCycleSafe((BusinessObject) collElem, visited);
581                                            }
582                                        }
583                                    }
584                                }
585                            }
586                        }
587                    }
588                }
589                        } catch (IllegalAccessException e) {
590                                throw new IntrospectionException(
591                                                "unable to performForceUppercase", e);
592                        } catch (InvocationTargetException e) {
593                                throw new IntrospectionException(
594                                                "unable to performForceUppercase", e);
595                        } catch (NoSuchMethodException e) {
596                // if the getter/setter does not exist, just skip over
597                                // throw new
598                                // IntrospectionException("unable to performForceUppercase", e);
599            }
600        }
601    }
602
603    /**
604     * Sets the instance of the data dictionary service.
605     *
606     * @param dataDictionaryService
607     */
608        public void setDataDictionaryService(
609                        DataDictionaryService dataDictionaryService) {
610        this.dataDictionaryService = dataDictionaryService;
611    }
612
613    /**
614     * This method retrieves the instance of the data dictionary service.
615     *
616     * @return An instance of the DataDictionaryService.
617     */
618    public DataDictionaryService getDataDictionaryService() {
619        return this.dataDictionaryService;
620    }
621
622    /**
623     * @param businessObjectClass
624         * @return BusinessObjectEntry for the given dataObjectClass, or null if
625         *         there is none
626         * @throws IllegalArgumentException
627         *             if the given Class is null or is not a BusinessObject class
628     */
629    private BusinessObjectEntry getBusinessObjectEntry(Class businessObjectClass) {
630        validateBusinessObjectClass(businessObjectClass);
631
632                BusinessObjectEntry entry = (BusinessObjectEntry) getDataDictionaryService()
633                                .getDataDictionary().getBusinessObjectEntry(
634                                                businessObjectClass.getName());
635        return entry;
636    }
637
638    /**
639     * @param businessObjectClass
640         * @return MaintenanceDocumentEntry for the given dataObjectClass, or
641         *         null if there is none
642         * @throws IllegalArgumentException
643         *             if the given Class is null or is not a BusinessObject class
644     */
645        private MaintenanceDocumentEntry getMaintenanceDocumentEntry(
646                        Class businessObjectClass) {
647        validateBusinessObjectClass(businessObjectClass);
648
649                MaintenanceDocumentEntry entry = (MaintenanceDocumentEntry) getDataDictionaryService()
650                                .getDataDictionary()
651                                .getMaintenanceDocumentEntryForBusinessObjectClass(
652                                                businessObjectClass);
653        return entry;
654    }
655
656    /**
657     * @param businessObjectClass
658         * @return LookupDefinition for the given dataObjectClass, or null if
659         *         there is none
660         * @throws IllegalArgumentException
661         *             if the given Class is null or is not a BusinessObject class
662     */
663    private LookupDefinition getLookupDefinition(Class businessObjectClass) {
664        LookupDefinition lookupDefinition = null;
665
666        BusinessObjectEntry entry = getBusinessObjectEntry(businessObjectClass);
667        if (entry != null) {
668            if (entry.hasLookupDefinition()) {
669                lookupDefinition = entry.getLookupDefinition();
670            }
671        }
672
673        return lookupDefinition;
674    }
675
676    /**
677     * @param businessObjectClass
678     * @param attributeName
679         * @return FieldDefinition for the given dataObjectClass and lookup
680         *         field name, or null if there is none
681         * @throws IllegalArgumentException
682         *             if the given Class is null or is not a BusinessObject class
683     */
684        private FieldDefinition getLookupFieldDefinition(Class businessObjectClass,
685                        String lookupFieldName) {
686        if (StringUtils.isBlank(lookupFieldName)) {
687                        throw new IllegalArgumentException(
688                                        "invalid (blank) lookupFieldName");
689        }
690
691        FieldDefinition fieldDefinition = null;
692
693        LookupDefinition lookupDefinition = getLookupDefinition(businessObjectClass);
694        if (lookupDefinition != null) {
695            fieldDefinition = lookupDefinition.getLookupField(lookupFieldName);
696        }
697
698        return fieldDefinition;
699    }
700
701    /**
702     * @param businessObjectClass
703     * @param attributeName
704         * @return FieldDefinition for the given dataObjectClass and lookup
705         *         result field name, or null if there is none
706         * @throws IllegalArgumentException
707         *             if the given Class is null or is not a BusinessObject class
708     */
709        private FieldDefinition getLookupResultFieldDefinition(
710                        Class businessObjectClass, String lookupFieldName) {
711        if (StringUtils.isBlank(lookupFieldName)) {
712                        throw new IllegalArgumentException(
713                                        "invalid (blank) lookupFieldName");
714        }
715
716        FieldDefinition fieldDefinition = null;
717
718        LookupDefinition lookupDefinition = getLookupDefinition(businessObjectClass);
719        if (lookupDefinition != null) {
720            fieldDefinition = lookupDefinition.getResultField(lookupFieldName);
721        }
722
723        return fieldDefinition;
724    }
725
726    /**
727     * @param businessObjectClass
728         * @return InquiryDefinition for the given dataObjectClass, or null if
729         *         there is none
730         * @throws IllegalArgumentException
731         *             if the given Class is null or is not a BusinessObject class
732     */
733    private InquiryDefinition getInquiryDefinition(Class businessObjectClass) {
734        InquiryDefinition inquiryDefinition = null;
735
736        BusinessObjectEntry entry = getBusinessObjectEntry(businessObjectClass);
737        if (entry != null) {
738            if (entry.hasInquiryDefinition()) {
739                inquiryDefinition = entry.getInquiryDefinition();
740            }
741        }
742
743        return inquiryDefinition;
744    }
745
746
747    /**
748     * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getTitleAttribute(java.lang.Class)
749     */
750    public String getTitleAttribute(Class businessObjectClass) {
751        String titleAttribute = null;
752
753        BusinessObjectEntry entry = getBusinessObjectEntry(businessObjectClass);
754        if (entry != null) {
755            titleAttribute = entry.getTitleAttribute();
756        }
757
758        return titleAttribute;
759    }
760
761    /**
762     * @param businessObjectClass
763     * @param attributeName
764         * @return FieldDefinition for the given dataObjectClass and field name,
765         *         or null if there is none
766         * @throws IllegalArgumentException
767         *             if the given Class is null or is not a BusinessObject class
768     */
769        private FieldDefinition getInquiryFieldDefinition(
770                        Class businessObjectClass, String fieldName) {
771        if (StringUtils.isBlank(fieldName)) {
772            throw new IllegalArgumentException("invalid (blank) fieldName");
773        }
774
775        FieldDefinition fieldDefinition = null;
776
777        InquiryDefinition inquiryDefinition = getInquiryDefinition(businessObjectClass);
778        if (inquiryDefinition != null) {
779            fieldDefinition = inquiryDefinition.getFieldDefinition(fieldName);
780        }
781
782        return fieldDefinition;
783    }
784
785    /**
786     * @param businessObjectClass
787         * @throws IllegalArgumentException
788         *             if the given Class is null or is not a BusinessObject class
789     */
790    private void validateBusinessObjectClass(Class businessObjectClass) {
791        if (businessObjectClass == null) {
792                        throw new IllegalArgumentException(
793                                        "invalid (null) dataObjectClass");
794        }
795        if ((!BusinessObject.class.isAssignableFrom(businessObjectClass)) &&
796            (!PersistableBusinessObjectBaseAdapter.class.isAssignableFrom(businessObjectClass))) {
797                        throw new IllegalArgumentException("class '"
798                                        + businessObjectClass.getName()
799                                        + "' is not a descendent of BusinessObject or PersistableBusinessObjectBaseAdapter");
800        }
801    }
802
803    /**
804         * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#forceLookupResultFieldInquiry(java.lang.Class,
805         *      java.lang.String)
806     */
807        public Boolean forceLookupResultFieldInquiry(Class businessObjectClass,
808                        String attributeName) {
809        Boolean forceLookup = null;
810        if (getLookupResultFieldDefinition(businessObjectClass, attributeName) != null) {
811                        forceLookup = Boolean.valueOf(getLookupResultFieldDefinition(
812                                        businessObjectClass, attributeName).isForceInquiry());
813        }
814
815        return forceLookup;
816    }
817
818    /**
819         * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#noLookupResultFieldInquiry(java.lang.Class,
820         *      java.lang.String)
821     */
822        public Boolean noLookupResultFieldInquiry(Class businessObjectClass,
823                        String attributeName) {
824        Boolean noLookup = null;
825        if (getLookupResultFieldDefinition(businessObjectClass, attributeName) != null) {
826                        noLookup = Boolean.valueOf(getLookupResultFieldDefinition(
827                                        businessObjectClass, attributeName).isNoInquiry());
828        }
829
830        return noLookup;
831    }
832
833    /**
834         * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#forceLookupFieldLookup(java.lang.Class,
835         *      java.lang.String)
836     */
837        public Boolean forceLookupFieldLookup(Class businessObjectClass,
838                        String attributeName) {
839        Boolean forceLookup = null;
840        if (getLookupFieldDefinition(businessObjectClass, attributeName) != null) {
841                        forceLookup = Boolean.valueOf(getLookupFieldDefinition(
842                                        businessObjectClass, attributeName).isForceLookup());
843        }
844
845        return forceLookup;
846    }
847
848        public Boolean forceInquiryFieldLookup(Class businessObjectClass,
849                        String attributeName) {
850        Boolean forceInquiry = null;
851        if (getLookupFieldDefinition(businessObjectClass, attributeName) != null) {
852                        forceInquiry = Boolean.valueOf(getLookupFieldDefinition(
853                                        businessObjectClass, attributeName).isForceInquiry());
854        }
855
856        return forceInquiry;
857    }
858
859    /**
860         * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#noLookupFieldLookup(java.lang.Class,
861         *      java.lang.String)
862     */
863        public Boolean noLookupFieldLookup(Class businessObjectClass,
864                        String attributeName) {
865        Boolean noLookup = null;
866        if (getLookupFieldDefinition(businessObjectClass, attributeName) != null) {
867                        noLookup = Boolean.valueOf(getLookupFieldDefinition(
868                                        businessObjectClass, attributeName).isNoLookup());
869        }
870
871        return noLookup;
872    }
873
874    /**
875         * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#noLookupFieldLookup(java.lang.Class,
876         *      java.lang.String)
877     */
878        public Boolean noDirectInquiryFieldLookup(Class businessObjectClass,
879                        String attributeName) {
880        Boolean noDirectInquiry = null;
881        if (getLookupFieldDefinition(businessObjectClass, attributeName) != null) {
882                        noDirectInquiry = Boolean.valueOf(getLookupFieldDefinition(
883                                        businessObjectClass, attributeName).isNoDirectInquiry());
884        }
885
886        return noDirectInquiry;
887    }
888
889    /**
890         * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getLookupResultFieldUseShortLabel(java.lang.Class,
891         *      java.lang.String)
892         */
893        public Boolean getLookupResultFieldUseShortLabel(Class businessObjectClass,
894                        String attributeName) {
895        Boolean useShortLabel = null;
896        if (getLookupResultFieldDefinition(businessObjectClass, attributeName) != null) {
897                        useShortLabel = Boolean.valueOf(getLookupResultFieldDefinition(
898                                        businessObjectClass, attributeName).isUseShortLabel());
899        }
900
901        return useShortLabel;
902        }
903
904        /**
905         * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getLookupResultFieldTotal(java.lang.Class,
906         *      java.lang.String)
907         */
908        public Boolean getLookupResultFieldTotal(Class businessObjectClass, String attributeName) {
909                Boolean total = false;
910
911                if (getLookupResultFieldDefinition(businessObjectClass, attributeName) != null) {
912                        total = Boolean.valueOf(getLookupResultFieldDefinition(
913                                        businessObjectClass, attributeName).isTotal());
914                }
915
916                return total;
917        }
918
919        /**
920         * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#forceInquiryFieldInquiry(java.lang.Class,
921         *      java.lang.String)
922     */
923        public Boolean forceInquiryFieldInquiry(Class businessObjectClass,
924                        String attributeName) {
925        Boolean forceInquiry = null;
926        if (getInquiryFieldDefinition(businessObjectClass, attributeName) != null) {
927                        forceInquiry = Boolean.valueOf(getInquiryFieldDefinition(
928                                        businessObjectClass, attributeName).isForceInquiry());
929        }
930
931        return forceInquiry;
932    }
933
934    /**
935         * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#noInquiryFieldInquiry(java.lang.Class,
936         *      java.lang.String)
937     */
938        public Boolean noInquiryFieldInquiry(Class businessObjectClass,
939                        String attributeName) {
940        Boolean noInquiry = null;
941        if (getInquiryFieldDefinition(businessObjectClass, attributeName) != null) {
942                        noInquiry = Boolean.valueOf(getInquiryFieldDefinition(
943                                        businessObjectClass, attributeName).isNoInquiry());
944        }
945
946        return noInquiry;
947    }
948
949    /**
950         * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getLookupFieldDefaultValue(java.lang.Class,
951         *      java.lang.String)
952     */
953        public String getLookupFieldDefaultValue(Class businessObjectClass,
954                        String attributeName) {
955                return getLookupFieldDefinition(businessObjectClass, attributeName)
956                                .getDefaultValue();
957    }
958
959    /**
960     * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getLookupFieldDefaultValueFinderClass(java.lang.Class,
961     *      java.lang.String)
962     */
963        public Class<? extends ValueFinder> getLookupFieldDefaultValueFinderClass(
964                        Class businessObjectClass, String attributeName) {
965                return getLookupFieldDefinition(businessObjectClass, attributeName)
966                                .getDefaultValueFinderClass();
967    }
968
969        /** {@inheritDoc} */
970        public String getLookupFieldQuickfinderParameterString(Class businessObjectClass, String attributeName) {
971                return getLookupFieldDefinition(businessObjectClass, attributeName).getQuickfinderParameterString();
972        }
973
974        /** {@inheritDoc} */
975        public Class<? extends ValueFinder> getLookupFieldQuickfinderParameterStringBuilderClass(Class businessObjectClass, String attributeName) {
976                return getLookupFieldDefinition(businessObjectClass, attributeName).getQuickfinderParameterStringBuilderClass();
977        }
978
979        public void setPersistenceStructureService(
980                        PersistenceStructureService persistenceStructureService) {
981        this.persistenceStructureService = persistenceStructureService;
982    }
983
984        /**
985         * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#isLookupFieldTreatWildcardsAndOperatorsAsLiteral(java.lang.Class, java.lang.String)
986         */
987        public boolean isLookupFieldTreatWildcardsAndOperatorsAsLiteral(Class businessObjectClass, String attributeName) {
988                FieldDefinition lookupFieldDefinition = getLookupFieldDefinition(businessObjectClass, attributeName);
989                return lookupFieldDefinition != null && lookupFieldDefinition.isTreatWildcardsAndOperatorsAsLiteral();
990        }
991        
992        /**
993         * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getInquiryFieldAdditionalDisplayAttributeName(java.lang.Class,
994         *      java.lang.String)
995         */
996        public String getInquiryFieldAdditionalDisplayAttributeName(Class businessObjectClass, String attributeName) {
997                String additionalDisplayAttributeName = null;
998
999                if (getInquiryFieldDefinition(businessObjectClass, attributeName) != null) {
1000                        additionalDisplayAttributeName = getInquiryFieldDefinition(businessObjectClass, attributeName)
1001                                        .getAdditionalDisplayAttributeName();
1002                }
1003
1004                return additionalDisplayAttributeName;
1005        }
1006
1007        /**
1008         * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getInquiryFieldAlternateDisplayAttributeName(java.lang.Class,
1009         *      java.lang.String)
1010         */
1011        public String getInquiryFieldAlternateDisplayAttributeName(Class businessObjectClass, String attributeName) {
1012                String alternateDisplayAttributeName = null;
1013
1014                if (getInquiryFieldDefinition(businessObjectClass, attributeName) != null) {
1015                        alternateDisplayAttributeName = getInquiryFieldDefinition(businessObjectClass, attributeName)
1016                                        .getAlternateDisplayAttributeName();
1017                }
1018
1019                return alternateDisplayAttributeName;
1020        }
1021
1022        /**
1023         * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getLookupFieldAdditionalDisplayAttributeName(java.lang.Class,
1024         *      java.lang.String)
1025         */
1026        public String getLookupFieldAdditionalDisplayAttributeName(Class businessObjectClass, String attributeName) {
1027                String additionalDisplayAttributeName = null;
1028
1029                if (getLookupResultFieldDefinition(businessObjectClass, attributeName) != null) {
1030                        additionalDisplayAttributeName = getLookupResultFieldDefinition(businessObjectClass, attributeName)
1031                                        .getAdditionalDisplayAttributeName();
1032                }
1033
1034                return additionalDisplayAttributeName;
1035        }
1036
1037        /**
1038         * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#getLookupFieldAlternateDisplayAttributeName(java.lang.Class,
1039         *      java.lang.String)
1040         */
1041        public String getLookupFieldAlternateDisplayAttributeName(Class businessObjectClass, String attributeName) {
1042                String alternateDisplayAttributeName = null;
1043
1044                if (getLookupResultFieldDefinition(businessObjectClass, attributeName) != null) {
1045                        alternateDisplayAttributeName = getLookupResultFieldDefinition(businessObjectClass, attributeName)
1046                                        .getAlternateDisplayAttributeName();
1047                }
1048
1049                return alternateDisplayAttributeName;
1050        }
1051        
1052        /**
1053         * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#tranlateCodesInLookup(java.lang.Class)
1054         */
1055        public Boolean tranlateCodesInLookup(Class businessObjectClass) {
1056                boolean translateCodes = false;
1057
1058                if (getLookupDefinition(businessObjectClass) != null) {
1059                        translateCodes = getLookupDefinition(businessObjectClass).isTranslateCodes();
1060                }
1061
1062                return translateCodes;
1063        }
1064
1065        /**
1066         * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#tranlateCodesInInquiry(java.lang.Class)
1067         */
1068        public Boolean tranlateCodesInInquiry(Class businessObjectClass) {
1069                boolean translateCodes = false;
1070
1071                if (getInquiryDefinition(businessObjectClass) != null) {
1072                        translateCodes = getInquiryDefinition(businessObjectClass).isTranslateCodes();
1073                }
1074
1075                return translateCodes;
1076        }
1077
1078        /**
1079         * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#isLookupFieldTriggerOnChange(java.lang.Class,
1080         *      java.lang.String)
1081         */
1082        public boolean isLookupFieldTriggerOnChange(Class businessObjectClass, String attributeName) {
1083                boolean triggerOnChange = false;
1084                if (getLookupFieldDefinition(businessObjectClass, attributeName) != null) {
1085                        triggerOnChange = getLookupFieldDefinition(businessObjectClass, attributeName).isTriggerOnChange();
1086                }
1087
1088                return triggerOnChange;
1089        }
1090
1091        /**
1092         * @see org.kuali.rice.kns.service.BusinessObjectDictionaryService#disableSearchButtonsInLookup(java.lang.Class)
1093         */
1094        public boolean disableSearchButtonsInLookup(Class businessObjectClass) {
1095                boolean disableSearchButtons = false;
1096
1097                if (getLookupDefinition(businessObjectClass) != null) {
1098                        disableSearchButtons = getLookupDefinition(businessObjectClass).isDisableSearchButtons();
1099                }
1100
1101                return disableSearchButtons;
1102        }
1103
1104
1105        
1106}