001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.wicket.spring;
018
019import java.util.ArrayList;
020import java.util.Collection;
021import java.util.HashMap;
022import java.util.HashSet;
023import java.util.List;
024import java.util.Map;
025import java.util.Set;
026
027import org.springframework.core.ResolvableType;
028
029/**
030 * Convenience class to extract information about the type and generics of a field to inject.
031 * The field is a List, a Map or a Set and the generic type of its elements is extracted as well
032 * 
033 * @author Tobias Soloschenko
034 * @author Andrea Del Bene
035 */
036public class FieldBeansCollector
037{
038        private final FieldType fieldType;
039        
040        private final Map<Object, Object> beansToInjectMap;
041        
042        private final Collection<Object> beansToInjectColl;
043        
044        public enum FieldType
045        {
046                LIST, SET, MAP, NONE
047        }
048
049        public FieldBeansCollector(final ResolvableType fieldResolvableType)
050        {
051                Class<?> clazz = fieldResolvableType.resolve();
052                
053                // The required code starts here which replaces
054                if (clazz == Map.class)
055                {
056                        fieldType = FieldType.MAP;
057                        // the getGeneric has to be called with 1 because the map contains the typified
058                        // information in the value generic
059                        beansToInjectColl = null;
060                        beansToInjectMap = new HashMap<>();
061                }
062                else if (clazz == Set.class)
063                {
064                        fieldType = FieldType.SET;
065                        beansToInjectColl = new HashSet<>();
066                        beansToInjectMap = null;
067                }
068                else if (clazz == List.class)
069                {
070                        fieldType = FieldType.LIST;
071                        beansToInjectColl = new ArrayList<>();
072                        beansToInjectMap = null;
073                }
074                else
075                {
076                        fieldType = FieldType.NONE;
077                        beansToInjectColl = null;
078                        beansToInjectMap = null;
079                }
080        }
081        
082        /**
083         * Returns an instance containing all the beans collected for the field and
084         * compatible with the type of the field.
085         * 
086         * @return the instance to inject into the field.
087         */
088        public Object getBeansToInject()
089        {
090                if (beansToInjectMap != null && beansToInjectMap.size() > 0)
091                {
092                        return beansToInjectMap;
093                }
094                
095                if (beansToInjectColl != null && beansToInjectColl.size() > 0)
096                {
097                        return beansToInjectColl;
098                }
099                
100                return null;
101        }
102        
103        /**
104         * Adds compatible bean to the field. This means that the field type is Map, a List or a Set
105         * and that the given bean is compatible with its elements type.
106         * 
107         * @param beanName
108         *                              the name of the bean to inject
109         * @param bean
110         *                              the bean to inject
111         */
112        public void addBean(String beanName, Object bean)
113        {
114                switch (fieldType)
115                {
116                        case LIST : 
117                        case SET :
118                                beansToInjectColl.add(bean);
119                                break;
120                        case MAP :
121                                beansToInjectMap.put(beanName, bean);
122                                break;
123                        default :
124                                break;
125                }
126        }
127        
128        public FieldType getFieldType()
129        {
130                return fieldType;
131        }
132}