001/**
002 * Copyright 2005-2016 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.data.provider.spring;
017
018import java.util.Collection;
019import java.util.List;
020import java.util.Map;
021
022import org.kuali.rice.core.api.util.ClassLoaderUtils;
023import org.kuali.rice.krad.data.metadata.DataObjectMetadata;
024import org.kuali.rice.krad.data.metadata.impl.DataObjectMetadataImpl;
025import org.kuali.rice.krad.data.provider.impl.MetadataProviderBase;
026import org.springframework.beans.factory.support.DefaultListableBeanFactory;
027import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
028import org.springframework.core.io.DefaultResourceLoader;
029
030/**
031 * Metadata provider which can be configured via the standard spring mechanisms.
032 *
033 * <p>
034 * The bean locations are listed as part of the metadata provider service definition. The beans in this provider are
035 * loaded into a separate context from all other beans in Rice.
036 * </p>
037 * 
038 * @author Kuali Rice Team (rice.collab@kuali.org)
039 * 
040 */
041public class SpringMetadataProviderImpl extends MetadataProviderBase {
042        private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger
043                        .getLogger(SpringMetadataProviderImpl.class);
044
045    /**
046     * The locations of the bean resources.
047     */
048        protected List<String> resourceLocations;
049
050    /**
051     * The default resource loader to use.
052     */
053        protected DefaultResourceLoader resourceLoader = new DefaultResourceLoader(ClassLoaderUtils.getDefaultClassLoader());
054
055    /**
056     * The default bean factory to use.
057     */
058        protected DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
059
060    /**
061     * Creates a metadata provider which can be configured via the standard spring mechanisms.
062     */
063        public SpringMetadataProviderImpl() {
064                LOG.debug("Building SpringMetadataProviderImpl");
065        }
066
067    /**
068     * {@inheritDoc}
069     */
070        @Override
071        public synchronized void initializeMetadata(Collection<Class<?>> types) {
072                // First, extract the data from the spring configuration into a form usable by the Spring XML parser
073                if (LOG.isDebugEnabled()) {
074                        LOG.debug("Loading Metadata Bean Definitions from Locations:");
075                        for (String loc : resourceLocations) {
076                                LOG.debug(loc);
077                        }
078                }
079                // Now, parse the beans and load them into the bean factory
080                XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(beanFactory);
081                String configFileLocationsArray[] = new String[resourceLocations.size()];
082                configFileLocationsArray = resourceLocations.toArray(configFileLocationsArray);
083                xmlReader.loadBeanDefinitions(configFileLocationsArray);
084
085                // extract the objects from the bean factory, by pulling all the DataObjectMetadata objects
086                Map<String, DataObjectMetadata> metadataObjects = beanFactory.getBeansOfType(DataObjectMetadata.class);
087                if (LOG.isInfoEnabled()) {
088                        LOG.info(metadataObjects.size() + " DataObjectMetadata objects in Spring configuration files");
089                }
090                // populate the map
091                masterMetadataMap.clear();
092                for (DataObjectMetadata metadata : metadataObjects.values()) {
093                        if (metadata.getType() != null) {
094                                if (metadata instanceof DataObjectMetadataImpl) {
095                                        ((DataObjectMetadataImpl) metadata).setProviderName(this.getClass().getSimpleName());
096                                }
097                                masterMetadataMap.put(metadata.getType(), metadata);
098                        } else {
099                                LOG.error("Configuration Error.  MetadataObject in the Spring context contained a null DataObjectType reference: "
100                                                + metadata);
101                        }
102                }
103        }
104
105    /**
106     * Gets the locations of the bean resources.
107     *
108     * @return the locations of the bean resources.
109     */
110        public List<String> getResourceLocations() {
111                return resourceLocations;
112        }
113
114    /**
115     * Setter for the resource locations.
116     *
117     * @param resourceLocations the resource locations to set.
118     */
119        public void setResourceLocations(List<String> resourceLocations) {
120                if (LOG.isDebugEnabled()) {
121                        LOG.debug("Resource locations set to: " + resourceLocations);
122                }
123                this.resourceLocations = resourceLocations;
124        }
125
126    /**
127     * {@inheritDoc}
128     */
129        @Override
130        public String toString() {
131                return getClass().getName() + " : " + resourceLocations;
132        }
133}