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 net.sf.jguiraffe.di.BeanProvider;
19 import net.sf.jguiraffe.di.BeanStore;
20 import net.sf.jguiraffe.di.Dependency;
21 import net.sf.jguiraffe.di.DependencyProvider;
22
23 /**
24 * <p>
25 * A concrete implementation of the <code>BeanProvider</code> interface that
26 * will always return the same bean instance.
27 * </p>
28 * <p>
29 * When an instance of this class is created, the managed bean instance (and
30 * optionally the target class if a type conversion is required) is passed in.
31 * On its first call the {@link #getBean(DependencyProvider)} method checks
32 * whether a type conversion if required. If this is the case, the conversion is
33 * performed, and the resulting object is stored. Later invocations will then
34 * always return this bean instance. The other methods defined by the
35 * <code>BeanProvider</code> interface are implemented as dummies: There are no
36 * dependencies, and synchronization support is not needed.
37 * </p>
38 * <p>
39 * In addition to the <code>BeanProvider</code> interface, the
40 * <code>Dependency</code> interface is also implemented. This makes it possible
41 * to have static dependencies, which are always resolved to a
42 * <code>BeanProvider</code> returning a constant bean. Dependencies of this
43 * type may seem strange first, but they make sense in some cases. For instance
44 * when a method is to be invoked, its parameters need to be defined. The
45 * current parameter values may be dependencies to other beans in the current
46 * bean store; so they need to be defined using dependencies. In simple cases
47 * however constant values need to be passed (e.g. integers, flags, or string
48 * values). For this purpose such a constant dependency can be used.
49 * </p>
50 * <p>
51 * Instances of this class can be created using the static
52 * <code>getInstance()</code> factory methods. In any case the constant value of
53 * the dependency must be passed in. It is also possible to specify the class of
54 * this dependency. In this case the class will try a type conversion as
55 * described above.
56 * </p>
57 *
58 * @author Oliver Heger
59 * @version $Id: ConstantBeanProvider.java 205 2012-01-29 18:29:57Z oheger $
60 */
61 public final class ConstantBeanProvider extends SimpleBeanProvider implements
62 BeanProvider, Dependency
63 {
64 /** Constant for a dependency that will be resolved to <b>null</b>. */
65 public static final ConstantBeanProvider NULL = new ConstantBeanProvider(
66 null, null);
67
68 /** Stores the managed bean. */
69 private final Object bean;
70
71 /** Stores the class of the bean. */
72 private final Class<?> beanClass;
73
74 /** The converted bean. */
75 private Object convertedBean;
76
77 /**
78 * Creates a new instance of {@code ConstantBeanProvider} and initializes it
79 * with the bean to manage. The class of the bean can also be specified -
80 * this is required if type conversion is needed. Clients use the static
81 * factory method for creating new instances.
82 *
83 * @param conversionClass the class of the bean
84 * @param obj the bean to be managed
85 */
86 private ConstantBeanProvider(Class<?> conversionClass, Object obj)
87 {
88 bean = obj;
89
90 if (conversionClass != null)
91 {
92 beanClass = conversionClass;
93 }
94 else
95 {
96 convertedBean = obj;
97 beanClass = (obj != null) ? obj.getClass() : Object.class;
98 }
99 }
100
101 /**
102 * Returns the bean managed by this provider. This is the same bean as was
103 * passed to the constructor. No type conversion has been performed.
104 *
105 * @return the bean passed to the constructor
106 */
107 public Object getBean()
108 {
109 return bean;
110 }
111
112 /**
113 * Returns the bean managed by this provider. This implementation operates
114 * on the bean that was passed when this object was created. If necessary,
115 * type conversion is performed (the result of this conversion is cached, so
116 * that the conversion is only done on first access).
117 *
118 * @param dependencyProvider the dependency provider
119 * @return the bean managed by this provider
120 */
121 public Object getBean(DependencyProvider dependencyProvider)
122 {
123 if (convertedBean == null && bean != null)
124 {
125 convertedBean =
126 dependencyProvider.getInvocationHelper()
127 .getConversionHelper().convert(beanClass, bean);
128 }
129
130 return convertedBean;
131 }
132
133 /**
134 * Returns the class of the managed bean. If a class was passed on creation
135 * time, it is directly returned. Otherwise, the class is obtained from the
136 * managed bean. If the bean is <b>null</b>, the type
137 * {@code java.lang.Object} is returned.
138 *
139 * @param dependencyProvider the dependency provider
140 * @return the class of the managed bean
141 */
142 public Class<?> getBeanClass(DependencyProvider dependencyProvider)
143 {
144 return beanClass;
145 }
146
147 /**
148 * Returns the <code>BeanProvider</code> this <code>Dependency</code> refers
149 * to. This implementation simply returns the <b>this</b> pointer.
150 *
151 * @param store the bean store
152 * @param depProvider the dependency provider
153 * @return the {@code BeanProvider} this {@code Dependency} refers to
154 */
155 public BeanProvider resolve(BeanStore store, DependencyProvider depProvider)
156 {
157 return this;
158 }
159
160 /**
161 * Returns a string representation of this object. This string will contain
162 * the value of this bean provider.
163 *
164 * @return a string for this object
165 */
166 @Override
167 public String toString()
168 {
169 StringBuilder buf = new StringBuilder(getClass().getName());
170 buf.append(" [ value = ").append(getBean()).append(" ]");
171 return buf.toString();
172 }
173
174 /**
175 * Creates a new instance of this class and initializes it with the bean to
176 * be managed.
177 *
178 * @param bean the bean to be managed
179 * @return the new instance of this class
180 */
181 public static ConstantBeanProvider getInstance(Object bean)
182 {
183 return new ConstantBeanProvider(null, bean);
184 }
185
186 /**
187 * Returns an instance of this class that refers to the specified value of
188 * the given class. If necessary, a conversion will be performed to convert
189 * the value to the given class.
190 *
191 * @param valueClass the class of this bean provider (can be <b>null</b>)
192 * @param value the value of the managed bean
193 * @return the instance representing this value
194 * @throws IllegalArgumentException if a conversion is necessary, but cannot
195 * be performed
196 */
197 public static ConstantBeanProvider getInstance(Class<?> valueClass,
198 Object value)
199 {
200 return new ConstantBeanProvider(valueClass, value);
201 }
202 }