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 }