/*
This file is part of leafdigital leafChat.
leafChat is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
leafChat is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with leafChat. If not, see <http://www.gnu.org/licenses/>.
Copyright 2011 Samuel Marshall.
*/
package leafchat.core;
import java.util.*;
import leafchat.core.api.*;
/** Provide access to all factory objects */
public class FactoryManager
{
// Singleton behaviour (yes, this class is a singleton; yes, that's confusing)
/** Single instance */
private static FactoryManager fm=new FactoryManager();
/**
* @return Single instance
*/
public static FactoryManager get()
{
return fm;
}
/** Private constructor to prevent separate construction */
private FactoryManager() {}
// Actual implementation
/** Actual storage of factories */
private Map<Class<? extends FactoryObject>, Factory> factories =
new HashMap<Class<? extends FactoryObject>, Factory>();
/**
* Creates a new instance of the given interface.
* @param interfaceClass Desired interface
* @return New object implementing interface
* @throws BugException If a factory for that interface doesn't exist,
* or the new object doesn't implement the interface
* @throws GeneralException If the factory reports an error
*/
public<C extends FactoryObject> C newInstance(Class<C> interfaceClass)
throws GeneralException
{
Factory f;
synchronized(factories)
{
f = factories.get(interfaceClass);
}
if(f==null)
{
throw new BugException("There is no factory for the desired interface "
+ interfaceClass.getName());
}
C o = f.newInstance(interfaceClass);
if(!interfaceClass.isAssignableFrom(o.getClass()))
{
throw new BugException(
"Factory returned object that does not match interface "+
interfaceClass.getName()+": "+o);
}
return o;
}
/**
* Registers a factory.
* @param cInterface Interface of objects that can be created
* @param f Factory that will create these objects
* @throws BugException If a factory for this interface already exists
*/
public void add(Class<? extends FactoryObject> cInterface, Factory f)
{
synchronized(factories)
{
if(factories.containsKey(cInterface))
throw new BugException(
"There is already a factory for interface "+cInterface.getName());
factories.put(cInterface,f);
}
}
/**
* Unregisters a factory.
* @param cInterface Interface of objects that cannot now be created
* @param f Factory being removed
* @throws BugException If factory doesn't exist or isn't == f
*/
public void remove(Class<? extends FactoryObject> cInterface,Factory f)
{
synchronized(factories)
{
if(factories.get(cInterface)==f)
factories.remove(cInterface);
else
throw new BugException(
"There is no factory for interface "+cInterface.getName()+
", or it doesn't match the given one for removal");
}
}
}