package com.idega.repository.data;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.idega.util.ArrayUtil;
import com.idega.util.datastructures.HashMatrix;
/**
* <p>Title: idegaWeb</p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) 2003</p>
* <p>Company: idega Software</p>
* @author <a href="thomas@idega.is">Thomas Hilbig</a>
* @version 1.0
* Created on Jun 14, 2004
*/
public class ImplementorRepository implements Singleton {
private static Instantiator instantiator = new Instantiator() { public Object getInstance() { return new ImplementorRepository();}};
private static final String GENERAL = "general";
static public ImplementorRepository getInstance() {
return (ImplementorRepository) SingletonRepository.getRepository().getInstance(ImplementorRepository.class, instantiator);
}
private HashMatrix interfaceCallerImplementor = null;
private ImplementorRepository(){
// should not be initialized by constructor
}
public void addImplementorForCaller(Class interfaceClass, Class callerClass, Class implementorClass) {
if (this.interfaceCallerImplementor == null) {
this.interfaceCallerImplementor = new HashMatrix();
}
String interfaceClassName = interfaceClass.getName();
String callerClassName = (callerClass == null) ? GENERAL : callerClass.getName();
String implementorClassName = implementorClass.getName();
if (this.interfaceCallerImplementor.containsKey(interfaceClassName, callerClassName)) {
List implementorNames = (List) this.interfaceCallerImplementor.get(interfaceClassName, callerClassName);
if (implementorNames.contains(implementorClassName)) {
// already added
return;
}
// add the name to the existing list
implementorNames.add(implementorClassName);
}
else{
// new entry
List implementorNames = new ArrayList(1);
implementorNames.add(implementorClassName);
this.interfaceCallerImplementor.put(interfaceClassName, callerClassName, implementorNames);
}
}
public void addImplementor(Class interfaceClass, Class implementationClass) {
addImplementorForCaller(interfaceClass, null, implementationClass);
}
public Object newInstance(Class interfaceClass, Class callerClass) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
List implementors = getValidImplementorClasses(interfaceClass, callerClass);
// get the first one
if (implementors == null) {
throw new ClassNotFoundException("[ImplementorRepository] ImImplementor for interface " + interfaceClass.getName() + "could not be found");
}
Class implementorClass = (Class) implementors.get(0);
return implementorClass.newInstance();
}
public Object newInstanceOrNull(Class interfaceClass, Class callerClass) {
try {
return newInstance(interfaceClass, callerClass);
}
catch (ClassNotFoundException e) {
return null;
}
catch (InstantiationException e) {
return null;
}
catch (IllegalAccessException e) {
return null;
}
}
public List newInstances(Class interfaceClass, Class callerClass) {
List implementors = getValidImplementorClasses(interfaceClass, callerClass);
List instances = null;
if (implementors == null) {
// return empty list
return new ArrayList(0);
}
instances = new ArrayList(implementors.size());
Iterator iterator = implementors.iterator();
while (iterator.hasNext()) {
Class aClass = (Class) iterator.next();
try {
Object object = aClass.newInstance();
instances.add(object);
}
catch (InstantiationException e) {
// ignore
}
catch (IllegalAccessException e) {
// ignore
}
}
return instances;
}
public Class getAnyClassImpl(Class interfaceClass, Class callerClass) {
List validClasses = getValidImplementorClasses(interfaceClass, callerClass);
if (validClasses == null || validClasses.isEmpty()) {
return null;
}
return (Class) validClasses.get(0);
}
/**
*
* @param interfaceClass
* @param callerClass
* @return null or a non-empty list
*/
private List getImplementorNames(Class interfaceClass, Class callerClass) {
if (this.interfaceCallerImplementor == null) {
return null;
}
String interfaceClassName = interfaceClass.getName();
String callerClassName = callerClass.getName();
if (! this.interfaceCallerImplementor.containsKey(interfaceClassName, callerClassName)) {
callerClassName = GENERAL;
}
List implementors = (List) this.interfaceCallerImplementor.get(interfaceClassName, callerClassName);
if (implementors == null || implementors.isEmpty()) {
return null;
}
return implementors;
}
private List getValidImplementorClasses(Class interfaceClass, Class callerClass) {
List names = getImplementorNames(interfaceClass, callerClass);
if (names == null) {
return null;
}
List classes = new ArrayList(names.size());
Iterator iterator = names.iterator();
while (iterator.hasNext()) {
String name = (String) iterator.next();
try {
Class implementorClass = RefactorClassRegistry.forName(name);
classes.add(implementorClass);
}
catch (ClassNotFoundException e) {
// do nothing, not very likely that a class is registered but doesn't exist
e.printStackTrace();
}
}
if (classes.isEmpty()) {
return null;
}
return classes;
}
/**
* Checks if the caller class is considered to be of the specified type.
* Use that method only for interfaces that are used as flags like Clonable.
* If that method returns true it doesn't mean that you can cast an instance of
* the callerClass to the specified class.
* If you are going to perform a cast use the instanceOf check.
* @param interfaceClass
* @param callerClass
* @return true if the callerClass is considered to be of the specified type.
*/
public boolean isTypeOf(Class interfaceClass, Class callerClass) {
// first part:
// does the same like "instanceOf"
//
// get all super classes and check for the interface
List classes = new ArrayList();
Class superClass = callerClass;
while (superClass != null) {
Class[] interfaces = superClass.getInterfaces();
if (ArrayUtil.contains(interfaces,interfaceClass)) {
// if the method is left at the place a cast could be done
return true;
}
classes.add(superClass);
superClass = superClass.getSuperclass();
}
// second part:
// not found? check if there are some registered implementors that are considered as interface implementors
// Important note: You can't cast the caller to that type! You can only check if that class is of that type.
List implementorClasses = getValidImplementorClasses(interfaceClass, callerClass);
if (implementorClasses == null) {
return false;
}
Iterator iterator = implementorClasses.iterator();
while (iterator.hasNext()) {
Class implementor = (Class) iterator.next();
if (classes.contains(implementor)) {
return true;
}
}
return false;
}
}