1/**
2 * Copyright 2006-2013 the original author or authors.
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 */
16package org.objenesis;
17
18import java.util.HashMap;
19import java.util.Map;
20
21import org.objenesis.instantiator.ObjectInstantiator;
22import org.objenesis.strategy.InstantiatorStrategy;
23
24/**
25 * Base class to extend if you want to have a class providing your own default strategy. Can also be
26 * instantiated directly.
27 *
28 * @author Henri Tremblay
29 */
30public class ObjenesisBase implements Objenesis {
31
32   /** Strategy used by this Objenesi implementation to create classes */
33   protected final InstantiatorStrategy strategy;
34
35   /** Strategy cache. Key = Class, Value = InstantiatorStrategy */
36   protected Map cache;
37
38   /**
39    * Constructor allowing to pick a strategy and using cache
40    *
41    * @param strategy Strategy to use
42    */
43   public ObjenesisBase(InstantiatorStrategy strategy) {
44      this(strategy, true);
45   }
46
47   /**
48    * Flexible constructor allowing to pick the strategy and if caching should be used
49    *
50    * @param strategy Strategy to use
51    * @param useCache If {@link ObjectInstantiator}s should be cached
52    */
53   public ObjenesisBase(InstantiatorStrategy strategy, boolean useCache) {
54      if(strategy == null) {
55         throw new IllegalArgumentException("A strategy can't be null");
56      }
57      this.strategy = strategy;
58      this.cache = useCache ? new HashMap() : null;
59   }
60
61   public String toString() {
62      return getClass().getName() + " using " + strategy.getClass().getName()
63         + (cache == null ? " without" : " with") + " caching";
64   }
65
66   /**
67    * Will create a new object without any constructor being called
68    *
69    * @param clazz Class to instantiate
70    * @return New instance of clazz
71    */
72   public Object newInstance(Class clazz) {
73      return getInstantiatorOf(clazz).newInstance();
74   }
75
76   /**
77    * Will pick the best instantiator for the provided class. If you need to create a lot of
78    * instances from the same class, it is way more efficient to create them from the same
79    * ObjectInstantiator than calling {@link #newInstance(Class)}.
80    *
81    * @param clazz Class to instantiate
82    * @return Instantiator dedicated to the class
83    */
84   public synchronized ObjectInstantiator getInstantiatorOf(Class clazz) {
85      if(cache == null) {
86         return strategy.newInstantiatorOf(clazz);
87      }
88      ObjectInstantiator instantiator = (ObjectInstantiator) cache.get(clazz.getName());
89      if(instantiator == null) {
90         instantiator = strategy.newInstantiatorOf(clazz);
91         cache.put(clazz.getName(), instantiator);
92      }
93      return instantiator;
94   }
95
96}
97