001/*
002 * Copyright 2002-2017 the original author or authors.
003 *
004 * Licensed under the Apache 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 *      https://www.apache.org/licenses/LICENSE-2.0
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
017package org.springframework.beans.factory.config;
018
019import java.util.ArrayList;
020import java.util.List;
021
022import org.springframework.beans.BeanUtils;
023import org.springframework.beans.TypeConverter;
024import org.springframework.core.ResolvableType;
025
026/**
027 * Simple factory for shared List instances. Allows for central setup
028 * of Lists via the "list" element in XML bean definitions.
029 *
030 * @author Juergen Hoeller
031 * @since 09.12.2003
032 * @see SetFactoryBean
033 * @see MapFactoryBean
034 */
035public class ListFactoryBean extends AbstractFactoryBean<List<Object>> {
036
037        private List<?> sourceList;
038
039        @SuppressWarnings("rawtypes")
040        private Class<? extends List> targetListClass;
041
042
043        /**
044         * Set the source List, typically populated via XML "list" elements.
045         */
046        public void setSourceList(List<?> sourceList) {
047                this.sourceList = sourceList;
048        }
049
050        /**
051         * Set the class to use for the target List. Can be populated with a fully
052         * qualified class name when defined in a Spring application context.
053         * <p>Default is a {@code java.util.ArrayList}.
054         * @see java.util.ArrayList
055         */
056        @SuppressWarnings("rawtypes")
057        public void setTargetListClass(Class<? extends List> targetListClass) {
058                if (targetListClass == null) {
059                        throw new IllegalArgumentException("'targetListClass' must not be null");
060                }
061                if (!List.class.isAssignableFrom(targetListClass)) {
062                        throw new IllegalArgumentException("'targetListClass' must implement [java.util.List]");
063                }
064                this.targetListClass = targetListClass;
065        }
066
067
068        @Override
069        @SuppressWarnings("rawtypes")
070        public Class<List> getObjectType() {
071                return List.class;
072        }
073
074        @Override
075        @SuppressWarnings("unchecked")
076        protected List<Object> createInstance() {
077                if (this.sourceList == null) {
078                        throw new IllegalArgumentException("'sourceList' is required");
079                }
080                List<Object> result = null;
081                if (this.targetListClass != null) {
082                        result = BeanUtils.instantiateClass(this.targetListClass);
083                }
084                else {
085                        result = new ArrayList<Object>(this.sourceList.size());
086                }
087                Class<?> valueType = null;
088                if (this.targetListClass != null) {
089                        valueType = ResolvableType.forClass(this.targetListClass).asCollection().resolveGeneric();
090                }
091                if (valueType != null) {
092                        TypeConverter converter = getBeanTypeConverter();
093                        for (Object elem : this.sourceList) {
094                                result.add(converter.convertIfNecessary(elem, valueType));
095                        }
096                }
097                else {
098                        result.addAll(this.sourceList);
099                }
100                return result;
101        }
102
103}