View Javadoc

1   /*
2    * Copyright 2006-2016 The JGUIraffe Team.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License")
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package net.sf.jguiraffe.di.impl.providers;
17  
18  import java.util.ArrayList;
19  import java.util.Collection;
20  import java.util.Collections;
21  import java.util.HashMap;
22  import java.util.HashSet;
23  import java.util.Iterator;
24  import java.util.LinkedHashMap;
25  import java.util.Map;
26  import java.util.Set;
27  
28  import net.sf.jguiraffe.di.Dependency;
29  import net.sf.jguiraffe.di.DependencyProvider;
30  
31  /**
32   * <p>
33   * A specialized <code>BeanProvider</code> implementation for creating beans of
34   * type <code>java.util.Map</code>.
35   * </p>
36   * <p>
37   * With this bean provider implementation either a
38   * <code>java.util.HashMap</code> or a <code>java.util.LinkedHashMap</code> can
39   * be created and populated. The mechanisms used here are very similar to the
40   * ones used by {@link CollectionBeanProvider}: an instance is
41   * initialized with two lists of {@link Dependency} objects - one
42   * list represents the key, the other list represents the values of the map. The
43   * <code>getDependencies()</code> method returns a union of all these
44   * dependencies. When the <code>Map</code> bean is to be created, a new instance
45   * of the correct <code>Map</code> class is created. Then the dependencies for
46   * the keys and values are resolved, and the corresponding objects are added to
47   * the map.
48   * </p>
49   * <p>
50   * Bean providers of this type are intended to be used together with a
51   * {@link LifeCycleBeanProvider} that controls the creation of new
52   * instances.
53   * </p>
54   * <p>
55   * Implementation note: Objects of this class are immutable and thus can be
56   * shared between multiple threads.
57   * </p>
58   *
59   * @author Oliver Heger
60   * @version $Id: MapBeanProvider.java 205 2012-01-29 18:29:57Z oheger $
61   */
62  public class MapBeanProvider extends SimpleBeanProvider
63  {
64      /** A collection with the dependencies representing the keys of the map. */
65      private final Collection<Dependency> keyDependencies;
66  
67      /** A collection with the dependencies representing the values of the map. */
68      private final Collection<Dependency> valueDependencies;
69  
70      /** Stores the ordered flag. */
71      private final boolean ordered;
72  
73      /**
74       * Creates a new instance of <code>MapBeanProvider</code> and initializes
75       * it.
76       *
77       * @param keyDeps the dependencies for the keys of the map (must not be
78       *        <b>null</b>)
79       * @param valDeps the dependencies for the values of the map (must not be
80       *        <b>null</b>)
81       * @param ordered a flag whether the order of the dependencies should be
82       *        maintained
83       * @throws IllegalArgumentException if either <code>keyDeps</code> or
84       *         <code>valDeps</code> is <b>null</b> or the sizes of the
85       *         collections are different
86       */
87      public MapBeanProvider(Collection<Dependency> keyDeps,
88              Collection<Dependency> valDeps, boolean ordered)
89      {
90          if (keyDeps == null)
91          {
92              throw new IllegalArgumentException(
93                      "Key dependencies must not be null!");
94          }
95          if (valDeps == null)
96          {
97              throw new IllegalArgumentException(
98                      "Value dependencies must not be null!");
99          }
100         if (keyDeps.size() != valDeps.size())
101         {
102             throw new IllegalArgumentException(
103                     "Different number of key and value dependencies!");
104         }
105 
106         keyDependencies = new ArrayList<Dependency>(keyDeps);
107         valueDependencies = new ArrayList<Dependency>(valDeps);
108         this.ordered = ordered;
109     }
110 
111     /**
112      * Returns the dependencies for the keys of the map.
113      *
114      * @return the key dependencies
115      */
116     public Collection<Dependency> getKeyDependencies()
117     {
118         return Collections.unmodifiableCollection(keyDependencies);
119     }
120 
121     /**
122      * Returns the dependencies for the values of the map.
123      *
124      * @return the value dependencies
125      */
126     public Collection<Dependency> getValueDependencies()
127     {
128         return Collections.unmodifiableCollection(valueDependencies);
129     }
130 
131     /**
132      * Returns the ordered flag. This property determines the type of the map
133      * created by this provider.
134      *
135      * @return the ordered flag
136      */
137     public boolean isOrdered()
138     {
139         return ordered;
140     }
141 
142     /**
143      * Returns the bean managed by this provider. This implementation calls
144      * <code>createMap()</code> to create the map. Then the dependencies for
145      * keys and values are resolved and added to the map.
146      *
147      * @param dependencyProvider the dependency provider
148      * @return the managed bean
149      */
150     public Object getBean(DependencyProvider dependencyProvider)
151     {
152         Map<Object, Object> map = createMap();
153         Iterator<Dependency> itVal = valueDependencies.iterator();
154         for (Dependency keyDep : keyDependencies)
155         {
156             Object key = dependencyProvider.getDependentBean(keyDep);
157             Object val = dependencyProvider.getDependentBean(itVal.next());
158             map.put(key, val);
159         }
160 
161         return map;
162     }
163 
164     /**
165      * Returns the class of the managed bean. This implementation simply returns
166      * the unspecific <code>java.util.Map</code> class.
167      *
168      * @param dependencyProvider the dependency provider
169      * @return the class of the bean managed by this provider
170      */
171     public Class<?> getBeanClass(DependencyProvider dependencyProvider)
172     {
173         return Map.class;
174     }
175 
176     /**
177      * Returns the dependencies of this bean provider. This implementation
178      * returns a union of all key and value dependencies.
179      *
180      * @return a set with all dependencies of this bean provider
181      */
182     @Override
183     public Set<Dependency> getDependencies()
184     {
185         Set<Dependency> deps = new HashSet<Dependency>();
186         deps.addAll(keyDependencies);
187         deps.addAll(valueDependencies);
188         return deps;
189     }
190 
191     /**
192      * Creates the map managed by this provider. This implementation checks the
193      * <code>ordered</code> property and either creates a hash map or a linked
194      * hash map.
195      *
196      * @return the map
197      */
198     protected Map<Object, Object> createMap()
199     {
200         return isOrdered() ? new LinkedHashMap<Object, Object>()
201                 : new HashMap<Object, Object>();
202     }
203 }