001    /**
002     * Copyright 2010-2013 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     */
016    package org.kuali.common.jdbc.supplier;
017    
018    import java.util.ArrayList;
019    import java.util.List;
020    import java.util.Map;
021    
022    import org.apache.commons.io.FilenameUtils;
023    import org.apache.commons.lang3.StringUtils;
024    import org.kuali.common.jdbc.spring.SqlConfigUtils;
025    import org.kuali.common.util.Assert;
026    import org.kuali.common.util.CollectionUtils;
027    import org.kuali.common.util.LocationUtils;
028    import org.kuali.common.util.ReflectionUtils;
029    import org.kuali.common.util.nullify.NullUtils;
030    import org.kuali.common.util.spring.SpringUtils;
031    import org.springframework.beans.BeanUtils;
032    import org.springframework.beans.factory.FactoryBean;
033    import org.springframework.core.env.Environment;
034    
035    /**
036     * @deprecated
037     */
038    @Deprecated
039    public class LocationSuppliersFactoryBean implements FactoryBean<List<LocationSupplier>> {
040    
041            public static final String DEFAULT_RESOURCES_SUFFIX = SqlConfigUtils.RESOURCES_SUFFIX;
042    
043            String resourcesSuffix = DEFAULT_RESOURCES_SUFFIX;
044            Environment env;
045            String propertyKey;
046            Map<String, LocationSupplierSourceBean> extensionMappings;
047            LocationSupplierContext context;
048    
049            @Override
050            public List<LocationSupplier> getObject() {
051    
052                    // Make sure we are configured correctly
053                    Assert.notNull(env, "env is null");
054                    Assert.notNull(propertyKey, "propertyKey is null");
055                    Assert.notNull(extensionMappings, "extensionMappings is null");
056                    Assert.notNull(context, "context is null");
057    
058                    // Get a list of locations using properties, prefix, and listSuffix
059                    List<String> locations = getLocations(env, propertyKey, resourcesSuffix);
060    
061                    // Convert the locations into LocationSupplier's based on extension
062                    return getSuppliers(locations, extensionMappings);
063            }
064    
065            protected List<LocationSupplier> getSuppliers(List<String> locations, Map<String, LocationSupplierSourceBean> mappings) {
066    
067                    // Allocate some storage for our suppliers
068                    List<LocationSupplier> suppliers = new ArrayList<LocationSupplier>();
069    
070                    // Create a local copy of the locations, so we can remove entries as they are processed
071                    List<String> locationsToMap = new ArrayList<String>(locations);
072    
073                    // Loop through the mappings and attempt to match a suffix of any of the locations
074                    for (String suffix : mappings.keySet()) {
075                            List<String> matchedLocations = new ArrayList<String>();
076                            for (String location : locationsToMap) {
077    
078                                    if (location.endsWith(suffix)) {
079                                            // if the location ends with the current suffix, get the Location Supplier Source Bean
080                                            LocationSupplierSourceBean sourceBean = mappings.get(suffix);
081    
082                                            // get a new LocationSupplier instance and add it to the list
083                                            suppliers.add(getLocationSupplierInstance(sourceBean, location));
084    
085                                            // add the current location to the list of matched locations for this suffix
086                                            matchedLocations.add(location);
087                                    }
088                            }
089    
090                            // remove all matched locations from the list of locations we need to yet map
091                            locationsToMap.removeAll(matchedLocations);
092                    }
093    
094                    // Cycle through the list of locations, creating one supplier per location
095                    for (String location : locationsToMap) {
096    
097                            // Extract the extension from the location
098                            String extension = FilenameUtils.getExtension(location);
099    
100                            // The map holds the concrete LocationSupplier implementation to use for each extension
101                            LocationSupplierSourceBean sourceBean = mappings.get(extension);
102    
103                            // Unknown extension type
104                            if (sourceBean == null) {
105                                    throw new IllegalArgumentException("Unknown extension [" + extension + "]");
106                            }
107    
108                            // create a LocationSupplier instance and add it to the list
109                            suppliers.add(getLocationSupplierInstance(sourceBean, location));
110                    }
111    
112                    // Return the fully configured list of suppliers
113                    return suppliers;
114            }
115    
116            /**
117             * Build a new LocationSupplier instance from a LocationSupplierSourceBean
118             * 
119             * @param sourceBean
120             *            the LocationSupplierSourceBean
121             * @param location
122             *            the context location for the new instance
123             * 
124             * @return a new instance of LocationSupplier with properties from the LocationSupplierSourceBean
125             */
126            protected LocationSupplier getLocationSupplierInstance(LocationSupplierSourceBean sourceBean, String location) {
127                    String contextLocation = LocationSupplierUtils.getContextLocation(context, location);
128    
129                    // Request a new supplier from the builder
130                    LocationSupplier supplier = sourceBean.getSupplierInstance();
131    
132                    LocationSupplier newInstance = ReflectionUtils.newInstance(supplier.getClass());
133                    BeanUtils.copyProperties(supplier, newInstance);
134    
135                    // set the location of the LocationSupplier as a "context location"
136                    newInstance.setLocation(contextLocation);
137    
138                    return newInstance;
139            }
140    
141            /**
142             * Get all the resources (in order) for the propertyKey passed in. The value behind the
143             */
144            protected List<String> getLocations(Environment env, String propertyKey, String resourcesSuffix) {
145    
146                    // Extract the list of resources (comma delimited)
147                    String csv = SpringUtils.getProperty(env, propertyKey, NullUtils.NONE);
148    
149                    // If no resources were provided, we are done
150                    if (NullUtils.isNullOrNone(csv)) {
151                            return new ArrayList<String>();
152                    }
153    
154                    // Parse the CSV into a list of resources
155                    List<String> resources = CollectionUtils.getTrimmedListFromCSV(csv);
156    
157                    // Allocate some storage for the locations we find
158                    List<String> locations = new ArrayList<String>();
159                    for (String resource : resources) {
160    
161                            if (StringUtils.endsWithIgnoreCase(resource, resourcesSuffix)) {
162                                    // If the resource file ends with .resources, it's a list of resources, it is not a resource itself
163                                    locations.addAll(LocationUtils.getLocations(resource));
164                            } else {
165                                    // Otherwise it is a resource itself
166                                    locations.add(resource);
167                            }
168                    }
169    
170                    // Return the list of resources
171                    return locations;
172            }
173    
174            @Override
175            public Class<?> getObjectType() {
176                    return List.class;
177            }
178    
179            @Override
180            public boolean isSingleton() {
181                    return false;
182            }
183    
184            public String getResourcesSuffix() {
185                    return resourcesSuffix;
186            }
187    
188            public void setResourcesSuffix(String resourcesSuffix) {
189                    this.resourcesSuffix = resourcesSuffix;
190            }
191    
192            public Environment getEnv() {
193                    return env;
194            }
195    
196            public void setEnv(Environment env) {
197                    this.env = env;
198            }
199    
200            public String getPropertyKey() {
201                    return propertyKey;
202            }
203    
204            public void setPropertyKey(String propertyKey) {
205                    this.propertyKey = propertyKey;
206            }
207    
208            public Map<String, LocationSupplierSourceBean> getExtensionMappings() {
209                    return extensionMappings;
210            }
211    
212            public void setExtensionMappings(Map<String, LocationSupplierSourceBean> extensionMappings) {
213                    this.extensionMappings = extensionMappings;
214            }
215    
216            public LocationSupplierContext getContext() {
217                    return context;
218            }
219    
220            public void setContext(LocationSupplierContext context) {
221                    this.context = context;
222            }
223    
224    }