package org.sef4j.core.util.factorydef;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* repositories of object created by definition
* = composite of Repositories by type
*/
public class ObjectByDefRepositories {
private static final Logger LOG = LoggerFactory.getLogger(ObjectByDefRepositories.class);
private Map<Class<?>,SharedObjectByDefRepository<?,?>> repositories = new HashMap<Class<?>,SharedObjectByDefRepository<?,?>>();
// private Object lock = new Object();
// ------------------------------------------------------------------------
public ObjectByDefRepositories() {
}
public void close() {
for(SharedObjectByDefRepository<?,?> repository : repositories.values()) {
repository.close();
}
repositories = null;
}
// ------------------------------------------------------------------------
@SuppressWarnings("unchecked")
public <TDef,T> SharedObjectByDefRepository<TDef,T> getOrCreateRepositoryForClass(Class<TDef> clss) {
SharedObjectByDefRepository<?,?> res = repositories.get(clss);
if (res == null) {
res = new SharedObjectByDefRepository<TDef,T>(this, clss.getCanonicalName());
repositories.put(clss, res);
}
return (SharedObjectByDefRepository<TDef,T>) res;
}
public <TDef,T> void registerFactoryFor(Class<TDef> clss, SharedObjectByDefFactory<TDef,T> factory) {
SharedObjectByDefRepository<TDef,T> repo = getOrCreateRepositoryForClass(clss);
repo.registerFactory(factory);
}
public SharedObjectByDefRepository<?,?> repositoryForClass(Class<?> clss) {
SharedObjectByDefRepository<?, ?> res = repositories.get(clss);
for(Class<?> superClss = clss; ; superClss = superClss.getSuperclass()) {
res = repositories.get(clss);
if (res != null) {
break;
}
if (superClss == Object.class) {
break;
}
}
if (res == null) {
LOG.warn("no repository for class:" + clss);
throw new IllegalArgumentException();
}
return res;
}
/**
* register an object by its key definition
* utility method for <code>repositoryForClass(def.getClass()).register(def)</code>
*/
public <TDef,T> SharedRef<T> getOrCreateByDef(TDef def, Object key) {
Class<?> clss = def.getClass();
SharedObjectByDefRepository<?, ?> repoObj = repositoryForClass(clss);
@SuppressWarnings("unchecked")
SharedObjectByDefRepository<TDef,T> repo = (SharedObjectByDefRepository<TDef,T>) repoObj;
SharedRef<T> res = repo.getOrCreateByDef(def, key);
return res;
}
/**
* helper downcast for <code>getOrCreateByDef(def)</code>
*/
public <TDef,T> SharedRef<T> getOrCreateByDef(TDef def, Object key, Class<T> clss) {
SharedRef<T> res = getOrCreateByDef(def, key);
if (clss != null && !clss.isInstance(res.getObject())) {
throw new ClassCastException();
}
return res;
}
public <TDef,T> List<SharedRef<T>> getOrCreateByDefs(Collection<TDef> defs) {
List<SharedRef<T>> res = new ArrayList<SharedRef<T>>();
for(TDef def : defs) {
SharedRef<T> resElt = getOrCreateByDef(def, null);
res.add(resElt);
}
return res;
}
// ------------------------------------------------------------------------
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("ObjectByDefRepositories[\n");
for(SharedObjectByDefRepository<?,?> repo : repositories.values()) {
sb.append(repo.toString());
sb.append("\n");
}
sb.append("]");
return sb.toString();
}
}