1 package com.sourceforge.jpatterns.patterns.factory;
2
3 import com.sourceforge.jpatterns.core.JPConstants;
4 import com.sourceforge.jpatterns.core.configuration.exceptions.JPConfigException;
5 import com.sourceforge.jpatterns.patterns.PatternBase;
6 import com.sourceforge.jpatterns.schema.CastorSectionType;
7 import com.sourceforge.jpatterns.schema.Factory;
8 import com.sourceforge.jpatterns.schema.Item;
9 import com.sourceforge.jpatterns.schema.Param;
10 import com.sourceforge.jpatterns.utils.CastorUtils;
11 import com.zmicer.utils.InputArgumentUtils;
12 import com.zmicer.utils.LoggingUtils;
13 import com.zmicer.utils.ReflexionUtils;
14 import org.apache.commons.lang.StringUtils;
15 import org.apache.log4j.Logger;
16
17 import java.util.HashMap;
18 import java.util.List;
19 import java.util.Map;
20
21
22
23
24
25
26
27
28
29
30
31 public class JPFactoryImpl extends PatternBase implements IJPFactory
32 {
33
34
35
36 final public static Logger LOG = Logger.getLogger(JPConstants.LoggingCategory.FACTORY.toString());
37
38
39
40
41 public boolean checkCastorConfig(CastorSectionType castorSectionType)
42 {
43 InputArgumentUtils.checkObjects(castorSectionType);
44 return (castorSectionType instanceof Factory);
45 }
46
47
48
49
50 public Object getImplementation(final Class interfaceClass, final String scope)
51 {
52 return instantiateObjectByItem(retrieveItem(interfaceClass, scope), interfaceClass);
53 }
54
55
56
57
58 public Object getImplementation(final String interfaceClassBaseName, final String scope)
59 {
60 return instantiateObjectByItem(retrieveItem(interfaceClassBaseName, scope), null);
61 }
62
63
64
65
66 public String getImplementationFullName(final Class interfaceClass, final String scope)
67 {
68 return retrieveItem(interfaceClass, scope).getValue();
69 }
70
71
72
73
74 public String getImplementationFullName(final String interfaceClassBaseName, final String scope)
75 {
76 return retrieveItem(interfaceClassBaseName, scope).getValue();
77 }
78
79
80
81
82 public Object getImplementation(final Class interfaceClass, final String implType, final String scope)
83 {
84 InputArgumentUtils.checkObjects(interfaceClass, implType);
85 return instantiateObjectByItemAndType(retrieveItem(interfaceClass, scope), implType, interfaceClass);
86 }
87
88
89
90
91 public Object getImplementation(final String interfaceClassBaseName, final String implType, final String scope)
92 {
93 InputArgumentUtils.checkObjects(interfaceClassBaseName, implType);
94 return instantiateObjectByItemAndType(retrieveItem(interfaceClassBaseName, scope), implType, null);
95 }
96
97
98
99
100 public Map<String, Object> getImplementations(final Class interfaceClass, final String scope)
101 {
102 InputArgumentUtils.checkObjects(interfaceClass);
103 Map<String, Object> result = new HashMap<String, Object>();
104 try
105 {
106 result = validateImplementationsMap(interfaceClass,
107 ReflexionUtils.reflectObjects(getImplementationsNamesByItem(retrieveItem(interfaceClass, scope)), true));
108 }
109 catch (Exception e)
110 {
111 LoggingUtils.logException(LOG, e, "Exception occuried", JPFactoryImpl.class);
112 logAndThrow("The message of exception occuried [" + e.getMessage() + "]");
113 }
114 return result;
115 }
116
117
118
119
120 public Map<String, Object> getImplementations(final String interfaceClassBaseName, final String scope)
121 {
122 InputArgumentUtils.checkObjects(interfaceClassBaseName);
123 Map<String, Object> result = new HashMap<String, Object>();
124 try
125 {
126 result = ReflexionUtils.reflectObjects(getImplementationsNamesByItem(retrieveItem(interfaceClassBaseName, scope)), true);
127 }
128 catch (Exception e)
129 {
130 LoggingUtils.logException(LOG, e, "Exception occuried", JPFactoryImpl.class);
131 logAndThrow("The message of exception occuried [" + e.getMessage() + "]");
132 }
133 return result;
134 }
135
136
137
138
139 public Map<String, String> getImplementationsFullNames(final Class interfaceClass, final String scope)
140 {
141 return getImplementationsNamesByItem(retrieveItem(interfaceClass, scope));
142 }
143
144
145
146
147 public Map<String, String> getImplementationsFullNames(final String interfaceClassBaseName, final String scope)
148 {
149 return getImplementationsNamesByItem(retrieveItem(interfaceClassBaseName, scope));
150 }
151
152
153
154
155 public Object getOperator(final Class productBaseClass, final Class operatorBaseClass, final Object productObj, final String scope)
156 {
157 InputArgumentUtils.checkObjects(productBaseClass, operatorBaseClass, productObj);
158 if (!ReflexionUtils.instanceOf(productObj, productBaseClass))
159 {
160 logAndThrow("The provided object: class [" + productObj.getClass().getName() + "] is not of the class of the product: class[" +
161 productBaseClass.getName() + "]");
162 }
163
164 final Map<String, String> implementations = getImplementationsNamesByItem(
165 retrieveItem(ReflexionUtils.getBaseName(productBaseClass) + "_" + ReflexionUtils.getBaseName(operatorBaseClass), scope));
166 if (null == implementations || implementations.isEmpty())
167 {
168 throw new JPConfigException("The map of the implementations names can not be null: product base class name [" +
169 productBaseClass.getName() + "], operator base class name [" + operatorBaseClass + "], scope [" + scope + "]");
170 }
171
172
173 final String productBaseName = ReflexionUtils.getBaseName(productObj.getClass());
174 if (implementations.containsKey(productBaseName) &&
175 implementations.containsKey(productObj.getClass().getName()))
176 {
177 logAndThrow("Incorrect case when the required operator configuration for product class [" + productBaseClass.getName() +
178 "] is defined using both base and full names of the class of product specified [" + productObj.getClass().getName() + "]. It is " +
179 "incorrect case.");
180 }
181 String className = implementations.get(productBaseName);
182 if (StringUtils.isEmpty(className))
183 {
184 LoggingUtils.debug(LOG, this.getClass(), "The implementation of the provided object was obtained using the full product class " +
185 "definition. Product class [" + productObj.getClass().getName() + "], implementation class [" + className + "].");
186 className = implementations.get(productObj.getClass().getName());
187 }
188
189 if (null == className)
190 {
191 logAndThrow("Can not find the operator defined for the product object with an class [" + productObj.getClass().getName() +
192 "]. The class of the operator [" + operatorBaseClass.getName() + "], the base class of the product [" +
193 productBaseClass.getName() + "]");
194 }
195 final Object result = ReflexionUtils.reflectObject(className, false);
196 if (null == result)
197 {
198 logAndThrow("Can not instantiate the operator with the full class name [" + className + "] for the product of the full class " +
199 "name [" + productObj.getClass().getName() + "]");
200 }
201 else if (!ReflexionUtils.instanceOf(result, operatorBaseClass))
202 {
203 logAndThrow("The obtained operator instance: class [" + result.getClass().getName() + "] is not of the class of the operator " +
204 "was provided: class[" + operatorBaseClass.getName() + "]");
205 }
206 return result;
207 }
208
209
210
211
212 public Map<Object, Object> getOperators(final Class productBaseClass, final Class operatorBaseClass, final List<Object> productObjs,
213 final String scope)
214 {
215 InputArgumentUtils.checkObjects(productBaseClass, operatorBaseClass, productObjs);
216 final Map<Class, Object> classesInfo = new HashMap<Class, Object>();
217 final Map<Object, Object> result = new HashMap<Object, Object>();
218 for (Object product : productObjs)
219 {
220 if (null == classesInfo.get(product.getClass()))
221 {
222 classesInfo.put(product.getClass(), getOperator(productBaseClass, operatorBaseClass, product, scope));
223 }
224 result.put(product, classesInfo.get(product.getClass()));
225 }
226 return result;
227 }
228
229
230
231
232 public boolean check()
233 {
234 return super.check() && (m_castorSection instanceof Factory);
235 }
236
237
238
239
240
241
242
243
244
245 protected Param getParam(final Item item, final String key)
246 {
247 InputArgumentUtils.checkObjects(item, key);
248 for (final Param param : item.getParam())
249 {
250 if (null != param.getName() && param.getName().equals(key))
251 {
252 return param;
253 }
254 }
255 return null;
256 }
257
258
259
260
261
262
263
264
265
266
267
268
269 protected Object instantiateObjectByItem(final Item item, Class claz) throws JPConfigException
270 {
271 if (null == item)
272 {
273 throw new IllegalArgumentException("Item can not be null.");
274 }
275 final String implName = item.getValue();
276 if (null == implName)
277 {
278 logAndThrow("The item should have the value attribute not empty to be processed here. String representation" +
279 CastorUtils.toString(null, item));
280 }
281 final Object object = ReflexionUtils.reflectObject(implName, false);
282 if (null == object)
283 {
284 logAndThrow("Can not instantiate the implementation of the [" + item.getName() +
285 "] using the scope [" + item.getScope() + "]. The name of the implementation we got from the config [" + implName + "]");
286 }
287 if (null != claz)
288 {
289 if (!ReflexionUtils.instanceOf(object, claz))
290 {
291 logAndThrow("The obtained implementation instance: class [" + object.getClass().getName() + "] is not of the class of " +
292 "the interface specified: class[" + claz.getName() + "]");
293 }
294 }
295 return object;
296 }
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311 protected Object instantiateObjectByItemAndType(final Item item, final String type, Class claz) throws JPConfigException
312 {
313 if (null == item)
314 {
315 throw new IllegalArgumentException("Item can not be null.");
316 }
317 final Param param = getParam(item, type);
318 final String message = "Can not find the required implementation defined following the path: section scope [" +
319 m_castorSection.getScope() + "] section name [" + m_castorSection.getName() + "] item scope [" + item.getScope() + "] item name [" +
320 item.getName() + "] implementation type [" + type + "]";
321 if (null == param || StringUtils.isBlank(param.getValue()))
322 {
323 LoggingUtils.error(LOG, JPFactoryImpl.class, message);
324 throw new JPConfigException(message);
325 }
326 final Object object = ReflexionUtils.reflectObject(param.getValue(), false);
327 if (null == object)
328 {
329 logAndThrow("Can not instantiate the implementation of the [" + item.getName() + "] using the scope [" +
330 item.getScope() + "]. The name of the implementation we got from the config [" + param.getValue() + "]");
331 }
332 if (null != claz)
333 {
334 if (!ReflexionUtils.instanceOf(object, claz))
335 {
336 logAndThrow("The obtained implementation instance: class [" + object.getClass().getName() + "] is not of the class of " +
337 "the interface specified: class[" + claz.getName() + "]");
338 }
339 }
340
341 return object;
342 }
343
344
345
346
347
348
349
350
351
352
353
354 protected Map<String, String> getImplementationsNamesByItem(final Item item) throws JPConfigException
355 {
356 if (null == item)
357 {
358 throw new IllegalArgumentException("Item can not be null.");
359 }
360 final Map<String, String> result = new HashMap<String, String>();
361 if (item.getParam().length == 0)
362 {
363 logAndThrow("The item" + CastorUtils.toString(m_castorSection, item) + " doesn't contain the params configuration using which the " +
364 "implementations names should be retrivied.");
365 }
366
367 for (Param param : item.getParam())
368 {
369 if (StringUtils.isBlank(param.getName()) || StringUtils.isBlank(param.getValue()))
370 {
371 logAndThrow("The item" + CastorUtils.toString(m_castorSection, item) + " contains the params with blank name or " +
372 "value. It is illegal case for the this type factory configuration.");
373 }
374 if (result.containsKey(param.getName()))
375 {
376 logAndThrow("The item" + CastorUtils.toString(m_castorSection, item) + " contains the params with duplicated names.");
377 }
378 result.put(param.getName(), param.getValue());
379 }
380 return result;
381 }
382
383
384
385
386
387
388
389
390
391 protected Map<String, Object> validateImplementationsMap(final Class clazz, final Map<String, Object> map)
392 {
393 InputArgumentUtils.checkObjects(clazz, map);
394 for (final Object object : map.values())
395 {
396 if (!ReflexionUtils.instanceOf(object, clazz))
397 {
398 logAndThrow("The map of implememntations was introduced for the class [" + clazz.getName() + "] can not contain the implementation" +
399 " which is not of this class [" + object.getClass().getName() + "].");
400 }
401 }
402 return map;
403 }
404 }