/*
* Copyright 2001-2013 Steven Grimm <koreth[remove] at midwinter dot com>
* and Geert Bevin (gbevin[remove] at uwyn dot com)
* Licensed under the Apache License, Version 2.0 (the "License")
*/
package com.uwyn.rife.tools;
import com.uwyn.rife.ioc.HierarchicalProperties;
import com.uwyn.rife.ioc.exceptions.MandatoryPropertyMissingException;
import java.util.HashMap;
import java.util.Map;
/**
* Maintains a map of singletons of various classes, instantiating new
* ones as needed.
*
* @author Steven Grimm (koreth[remove] at midwinter dot com)
* @since 1.6
*/
public class SingletonFactory<T>
{
private Class<T> klass;
private Map<String, T> singletons = new HashMap<>();
public SingletonFactory(Class<T> klass)
{
this.klass = klass;
}
/**
* Returns a singleton with a particular identifier, or creates one with
* a particular class if none exists.
*
* @param className the name of the class a singleton has to be obtained
* for
* @param identifier an identifier to differentiate several singletons for
* the same class
* @return the requested singleton instance
* @since 1.6
*/
public synchronized T getInstance(String className, String identifier)
throws ClassNotFoundException, InstantiationException, IllegalAccessException
{
if (singletons.containsKey(identifier))
{
return singletons.get(identifier);
}
Class<T> klass = (Class)Class.forName(className);
if (!this.klass.isAssignableFrom(klass))
{
throw new ClassCastException("Can't cast " + className + " to " + this.klass.getName());
}
T obj = klass.newInstance();
singletons.put(identifier, obj);
return obj;
}
/**
* Returns a singleton instance of a class.
*
* @param className the name of the class a singleton has to be obtained
* for
* @return the requested singleton instance
* @since 1.6
*/
public T getInstance(String className)
throws ClassNotFoundException, InstantiationException, IllegalAccessException
{
return getInstance(className, className);
}
/**
* Returns an instance of a class based on a required property name from a
* properties collection.
*
* @param properties The properties where the class name has to be obtained from
* @param propertyName Which property contains the class name
* @param relativeTo Class whose package should be used if no package is
* specified in the property
* @return the requested singleton instance
* @since 1.6
*/
public T getInstance(HierarchicalProperties properties, String propertyName, Class relativeTo)
throws MandatoryPropertyMissingException, ClassNotFoundException, InstantiationException, IllegalAccessException
{
String className = properties.getValueString(propertyName);
if (null == className)
{
throw new MandatoryPropertyMissingException(propertyName);
}
if (!className.contains("."))
{
className = relativeTo.getPackage().getName() + "." + className;
}
return getInstance(className);
}
}