001 package org.tynamo.builder;
002
003 import org.slf4j.Logger;
004 import org.tynamo.exception.TynamoRuntimeException;
005
006 import java.lang.reflect.Constructor;
007 import java.util.HashMap;
008 import java.util.Map;
009
010 /**
011 * Fulfils the "Director" role in the Tynamo implementation of
012 * GOF's <a href="http://en.wikipedia.org/wiki/Builder_pattern">Builder pattern</a>
013 *
014 * Constructs an object using the Builder interface
015 */
016 public class BuilderDirector
017 {
018
019 private final Logger logger;
020
021 Map<Class, Builder> builders;
022
023 public BuilderDirector(Logger logger)
024 {
025 this.logger = logger;
026 builders = new HashMap<Class, Builder>();
027 }
028
029 public BuilderDirector(Logger logger, Map<Class, Builder> builders)
030 {
031 this.logger = logger;
032 this.builders = builders;
033 }
034
035 /**
036 * Create a new instance of an object of class 'type' using a Builder.
037 *
038 * @param type is a class whose instance should be created, it shouldn't be NULL
039 * @return a newly created object
040 */
041 public <T> T createNewInstance(final Class<T> type)
042 {
043 Builder<T> builder = (Builder<T>) builders.get(type);
044 if (builder != null)
045 {
046 return builder.build();
047 } else
048 {
049 return createNewInstanceFromEmptyConstructor(type);
050 }
051 }
052
053 /**
054 * Create a new instance of an object of class 'type' using an empty constructor.
055 *
056 * @param type is a class whose instance should be created
057 * @return a newly created object
058 */
059 private <T> T createNewInstanceFromEmptyConstructor(final Class<T> type)
060 {
061 try
062 {
063 Constructor constructor = type.getDeclaredConstructor();
064 constructor.setAccessible(true);
065 return (T) constructor.newInstance();
066
067 } catch (Exception ex)
068 {
069 logger.error(String.format("Can't create an instance of %s using an empty constructor.", type));
070 throw new TynamoRuntimeException(ex, type);
071 }
072 }
073 }