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.krad.keyvalues;
017
018import org.apache.commons.lang.StringUtils;
019import org.apache.log4j.Logger;
020import org.kuali.rice.core.api.util.ClassLoaderUtils;
021import org.kuali.rice.core.api.util.ConcreteKeyValue;
022import org.kuali.rice.core.api.util.KeyValue;
023import org.kuali.rice.kim.api.services.KimApiServiceLocator;
024import org.kuali.rice.kim.api.type.KimType;
025import org.kuali.rice.kim.api.type.KimTypeAttribute;
026import org.kuali.rice.kim.framework.services.KimFrameworkServiceLocator;
027import org.kuali.rice.kim.framework.type.KimTypeService;
028import org.kuali.rice.krad.datadictionary.AttributeDefinition;
029import org.kuali.rice.krad.datadictionary.BusinessObjectEntry;
030import org.kuali.rice.krad.service.DataDictionaryService;
031import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
032
033import java.util.ArrayList;
034import java.util.Collections;
035import java.util.List;
036
037/**
038 * @author Kuali Rice Team (rice.collab@kuali.org)
039 */
040public class KimAttributeValuesFinder extends KeyValuesBase {
041
042        private static final Logger LOG = Logger.getLogger( KimAttributeValuesFinder.class );
043
044        protected String kimTypeId;
045        protected String kimAttributeName;
046    private DataDictionaryService dataDictionaryService;
047
048    protected DataDictionaryService getDataDictionaryService() {
049                if ( dataDictionaryService == null ) {
050                        dataDictionaryService = KRADServiceLocatorWeb.getDataDictionaryService();
051                }
052                return this.dataDictionaryService;
053        }
054
055        /**
056         * @see KeyValuesFinder#getKeyValues()
057         */
058        @Override
059        public List<KeyValue> getKeyValues() {
060        KimType kimType = KimApiServiceLocator.getKimTypeInfoService().getKimType(kimTypeId);
061        if ( kimType != null ) {
062                KimTypeService service = KimFrameworkServiceLocator.getKimTypeService(kimType);
063                if ( service != null ) {
064                                return getAttributeValidValues(kimTypeId,kimAttributeName);
065                }
066                LOG.error( "Unable to get type service " + kimType.getServiceName() );
067        } else {
068                LOG.error( "Unable to obtain KIM type for kimTypeId=" + kimTypeId );
069        }
070        return Collections.emptyList();
071        }
072
073    private List<KeyValue> getAttributeValidValues(String kimTypeId, String attributeName) {
074                if ( LOG.isDebugEnabled() ) {
075                        LOG.debug( "getAttributeValidValues(" + kimTypeId + "," + attributeName + ")");
076                }
077                KimTypeAttribute attrib = KimApiServiceLocator.getKimTypeInfoService().getKimType(kimTypeId).getAttributeDefinitionByName(attributeName);
078                if ( LOG.isDebugEnabled() ) {
079                        LOG.debug( "Found Attribute definition: " + attrib );
080                }
081                List<KeyValue> pairs = null;
082                if ( StringUtils.isNotBlank(attrib.getKimAttribute().getComponentName()) ) {
083                        try {
084                                Class.forName(attrib.getKimAttribute().getComponentName());
085                                try {
086                                        pairs = getLocalDataDictionaryAttributeValues(attrib);
087                                } catch ( ClassNotFoundException ex ) {
088                                        LOG.error( "Got a ClassNotFoundException resolving a values finder - since this should have been executing in the context of the host system - this should not happen.");
089                                        return Collections.emptyList();
090                                }
091                        } catch ( ClassNotFoundException ex ) {
092                                LOG.error( "Got a ClassNotFoundException resolving a component name (" + attrib.getKimAttribute().getComponentName() + ") - since this should have been executing in the context of the host system - this should not happen.");
093                        }
094                } else {
095                        pairs = getCustomValueFinderValues(attrib);
096                }
097        return pairs;
098        }
099
100    protected List<KeyValue> getCustomValueFinderValues(KimTypeAttribute attrib) {
101                return Collections.emptyList();
102        }
103
104    protected List<KeyValue> getLocalDataDictionaryAttributeValues(KimTypeAttribute attr) throws ClassNotFoundException {
105
106                BusinessObjectEntry entry = getDataDictionaryService().getDataDictionary().getBusinessObjectEntry(attr.getKimAttribute().getComponentName());
107                if ( entry == null ) {
108                        LOG.warn( "Unable to obtain BusinessObjectEntry for component name: " + attr.getKimAttribute().getComponentName() );
109                        return Collections.emptyList();
110                }
111                AttributeDefinition definition = entry.getAttributeDefinition(attr.getKimAttribute().getAttributeName());
112                if ( definition == null ) {
113                        LOG.warn( "No attribute named " + attr.getKimAttribute().getAttributeName() + " found on BusinessObjectEntry for: " + attr.getKimAttribute().getComponentName() );
114                        return Collections.emptyList();
115                }
116
117        List<KeyValue> pairs = new ArrayList<KeyValue>();
118                String keyValuesFinderName = definition.getControl().getValuesFinderClass();
119                if ( StringUtils.isNotBlank(keyValuesFinderName)) {
120                        try {
121                                KeyValuesFinder finder = (KeyValuesFinder)Class.forName(keyValuesFinderName).newInstance();
122                                if (finder instanceof PersistableBusinessObjectValuesFinder) {
123                        ((PersistableBusinessObjectValuesFinder) finder).setBusinessObjectClass(
124                            ClassLoaderUtils.getClass(definition.getControl().getBusinessObjectClass()));
125                        ((PersistableBusinessObjectValuesFinder) finder).setKeyAttributeName(definition.getControl().getKeyAttribute());
126                        ((PersistableBusinessObjectValuesFinder) finder).setLabelAttributeName(definition.getControl().getLabelAttribute());
127                        if (definition.getControl().getIncludeBlankRow() != null) {
128                                ((PersistableBusinessObjectValuesFinder) finder).setIncludeBlankRow(definition.getControl().getIncludeBlankRow());
129                        }
130                        ((PersistableBusinessObjectValuesFinder) finder).setIncludeKeyInDescription(definition.getControl().getIncludeKeyInLabel());
131                                }
132
133                for (KeyValue pair : finder.getKeyValues()) {
134                    pairs.add(new ConcreteKeyValue(pair));
135                }
136
137                        } catch ( ClassNotFoundException ex ) {
138                                LOG.info( "Unable to find class: " + keyValuesFinderName + " in the current context." );
139                                throw ex;
140                        } catch (Exception e) {
141                                LOG.error("Unable to build a KeyValuesFinder for " + attr.getKimAttribute().getAttributeName(), e);
142                        }
143                } else {
144                        LOG.warn( "No values finder class defined on the control definition (" + definition.getControl() + ") on BO / attr = " + attr.getKimAttribute().getComponentName() + " / " + attr.getKimAttribute().getAttributeName() );
145                }
146                return pairs;
147        }
148
149        /**
150         * @return the kimAttributeName
151         */
152        public String getKimAttributeName() {
153                return this.kimAttributeName;
154        }
155
156        /**
157         * @param kimAttributeName the kimAttributeName to set
158         */
159        public void setKimAttributeName(String kimAttributeName) {
160                this.kimAttributeName = kimAttributeName;
161        }
162
163        /**
164         * @return the kimTypeId
165         */
166        public String getKimTypeId() {
167                return this.kimTypeId;
168        }
169
170        /**
171         * @param kimTypeId the kimTypeId to set
172         */
173        public void setKimTypeId(String kimTypeId) {
174                this.kimTypeId = kimTypeId;
175        }
176
177}