/*****************************************************************************
* Copyright (C) Codehaus.org. All rights reserved. *
* ------------------------------------------------------------------------- *
* The software in this package is published under the terms of the BSD *
* style license a copy of which has been included with this distribution in *
* the LICENSE.txt file. *
*****************************************************************************/
/*
* Created on Feb 27, 2005
*
* Author Ben Yu
* ZBS
*/
package jfun.yan.containers;
import java.util.Iterator;
import java.util.LinkedHashMap;
import jfun.yan.AmbiguousComponentResolutionException;
import jfun.yan.Component;
import jfun.yan.ComponentMap;
import jfun.yan.Dependency;
import jfun.yan.Registrar;
import jfun.yan.SimpleDependency;
import jfun.yan.YanException;
import jfun.yan.util.ReflectionUtil;
/**
* A simple implementation of Registrar.
* It ensures the Component objects and instances are retrieved and
* created in the same order as the Component objects are registered.
* <br>
* This implementation enables auto-wiring.
* It uses {@link SimpleDependency} to resolve parameters and properties.
* <br>
* It is also thread-safe.
* <p>
* Codehaus.org.
*
* @author Ben Yu
*
*/
public class SimpleRegistrar
implements Registrar, java.io.Serializable{
private final LinkedHashMap creators = new LinkedHashMap();
public synchronized int size(){
return creators.size();
}
public synchronized java.util.Set keys(){
return java.util.Collections.unmodifiableSet(creators.keySet());
}
public synchronized java.util.Collection getComponents(){
return java.util.Collections.unmodifiableCollection(creators.values());
}
public synchronized boolean containsKey(final Object key){
return creators.containsKey(key);
}
public synchronized Component getComponent(final Object key) {
return (Component)creators.get(key);
}
public synchronized boolean containsType(final Class type){
Component cc = getComponent(type);
if(cc!=null){
final Class ctype = cc.getType();
if(ctype == null
|| ReflectionUtil.isAssignableFrom(type, ctype)){
//if the type is dynamically bound, we trust the key.
return true;
}
cc = null;
}
for(Iterator it=creators.values().iterator();it.hasNext();){
final Component cci = (Component)it.next();
final Class typei = cci.getType();
if(typei!=null && !void.class.equals(typei) &&
//void type does actively feed itself to a by-type search.
//It does suppress type error when forced to match against another type.
ReflectionUtil.isAssignableFrom(
type, typei)){
return true;
}
}
return false;
}
public synchronized Component getComponentOfType(final Class type){
Component cc = getComponent(type);
if(cc!=null){
final Class ctype = cc.getType();
if(ctype == null
|| ReflectionUtil.isAssignableFrom(type, ctype)){
//if the type is dynamically bound, we trust the key.
return cc;
}
cc = null;
}
Class subtype = null;
for(Iterator it=creators.values().iterator();it.hasNext();){
final Component cci = (Component)it.next();
final Class typei = cci.getType();
if(typei!=null && !void.class.equals(typei) &&
//void type does actively feed itself to a by-type search.
//It does suppress type error when forced to match against another type.
ReflectionUtil.isAssignableFrom(
type, typei)){
if(subtype!=null){
throw
new AmbiguousComponentResolutionException(type, subtype, typei);
}
else{
subtype = typei;
cc = cci;
}
}
}
return cc;
}
public synchronized java.util.List getComponentsOfType(final Class type){
final java.util.ArrayList ret = new java.util.ArrayList();
for(Iterator it=creators.values().iterator();it.hasNext();){
final Component cci = (Component)it.next();
final Class typei = cci.getType();
if(typei!=null &&
!void.class.equals(typei) && ReflectionUtil.isAssignableFrom(
type, typei)){
ret.add(cci);
}
}
return ret;
}
public synchronized void unregisterComponentsOfType(Class type){
for(Iterator it=creators.values().iterator();it.hasNext();){
final Component cci = (Component)it.next();
final Class typei = cci.getType();
if(typei!=null && ReflectionUtil.isAssignableFrom(
type, typei)){
it.remove();
}
}
}
public synchronized void registerComponent(Object key,
Component cc) {
creators.put(key, cc);
}
public synchronized void unregisterComponent(Object key) {
creators.remove(key);
}
public synchronized void verify(final ComponentMap cmap) {
for(Iterator it=creators.keySet().iterator();it.hasNext();){
final Object ki = it.next();
try{
final Component cc = (Component)creators.get(ki);
cc.verify(cmap.getDependency(ki, cmap));
}
catch(YanException e){
e.push("verify <" + ki +">");
throw e;
}
}
}
/**
* This uses SimpleDependency which resolves parameters and
* arguments by type.
* Different resolution policy can be provided by overriding this method.
*/
public synchronized Dependency getDependency(final Object ckey
,final ComponentMap cmap){
return new SimpleDependency(ckey, cmap);
}
/**
* This uses SimpleDependency which resolves parameters and
* arguments by type.
* Different resolution policy can be provided by overriding this method.
*/
public synchronized Dependency getDependencyOfType(
final Class type, final ComponentMap cmap){
return new SimpleDependency(type, cmap);
}
public synchronized boolean equals(Object obj) {
if(obj instanceof SimpleRegistrar){
final SimpleRegistrar sc2 = (SimpleRegistrar)obj;
return creators.equals(sc2.creators);
}
else return false;
}
public synchronized int hashCode() {
return creators.hashCode();
}
public synchronized String toString() {
return creators.toString();
}
}