/*****************************************************************************
* 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 Mar 1, 2005
*
* Author Ben Yu
* ZBS
*/
package jfun.yan.containers;
import java.util.LinkedHashSet;
import jfun.yan.Component;
import jfun.yan.ComponentMap;
import jfun.yan.Dependency;
import jfun.yan.Registrar;
/**
* This class manages parent-child relationship between
* two conainers.
* In this container, components in the child container
* can use those from parent container as dependency.
* But components from parent container cannot see
* those from child containers.
* <p>
* Codehaus.org.
*
* @author Ben Yu
*
*/
public class InheritedRegistrar implements Registrar {
private final Registrar parent;
private final Registrar child;
/**
* Get the child container.
* @return the child container.
*/
public Registrar getChild() {
return child;
}
/**
* Get the parent container.
* @return the parent container.
*/
public Registrar getParent() {
return parent;
}
/**
* Create an InheritedRegistrar object.
* The parent container and the child container are not modified.
* @param parent the parent container.
* @param child the child contaiiner.
*/
public InheritedRegistrar(final Registrar parent, final Registrar child) {
this.parent = parent;
this.child = child;
}
/**
* registers the component to the child container.
*/
public void registerComponent(Object key, Component cc) {
child.registerComponent(key, cc);
}
/**
* unregisters components of a provided type from child container.
*/
public void unregisterComponentsOfType(Class type){
child.unregisterComponentsOfType(type);
}
/**
* unregisters a component identified by a key
* from child container.
* Nothing is done if the key is not found in the child container.
*/
public void unregisterComponent(Object key) {
child.unregisterComponent(key);
//parent.unregisterComponent(key);
}
public boolean containsKey(Object key){
return child.containsKey(key) || parent.containsKey(key);
}
public boolean containsType(Class type){
return child.containsType(type) || parent.containsType(type);
}
/**
* retrieves a component identified by a key.
* The key is first looked up in the child container,
* if not found, the parent container is looked up.
*/
public Component getComponent(Object key) {
Component cc = child.getComponent(key);
if(cc==null) return parent.getComponent(key);
else return cc;
}
/**
* retrieves a component of a provided type.
* the child container is first looked up,
* if no such component is found, the parent container is looked up.
*/
public Component getComponentOfType(Class type){
Component c1 = getComponent(type);
if(c1!=null) return c1;
c1 = child.getComponentOfType(type);
if(c1!=null) return c1;
else return parent.getComponentOfType(type);
}
/**
* retrieves all components of a provided type
* from both the parent container and the child container.
* <br>
* components from the parent container are placed
* before those from child container.
*/
public java.util.List getComponentsOfType(Class type){
final java.util.List ret = parent.getComponentsOfType(type);
ret.addAll(child.getComponentsOfType(type));
return ret;
}
/**
* gets all components from both the parent container and
* the child container.
* <p>
* Components from the parent container are placed before
* those from the child container.
*/
public java.util.Collection getComponents(){
final java.util.List ret = new java.util.ArrayList(parent.getComponents());
ret.addAll(child.getComponents());
return ret;
}
/**
* Gets the Dependency object for a component of
* a provided type.
* <br>
* If the component type can be found in the child container,
* the dependency is looked up in the child container.
* Otherwise, parent container is looked up and the parent container
* is used to resolve all cascaded dependencies.
*/
public Dependency getDependencyOfType(Class type, ComponentMap cmap){
if(type==null || child.containsType(type))
return child.getDependencyOfType(type, cmap);
else return parent.getDependencyOfType(type, parent);
}
/**
* Gets the Dependency object for a component identified by a key.
* <br>
* If the component key can be found in the child container,
* the dependency is looked up in the child container.
* Otherwise, parent container is looked up and the parent container
* is used to resolve all cascaded dependencies.
*/
public Dependency getDependency(Object key, ComponentMap cmap){
//we do not use SimpleDependency because the parent and child may provide additional functionality.
if(key==null || child.containsKey(key))
return child.getDependency(key, cmap);
else
return parent.getDependency(key, parent);
/*
final Dependency ac1 = child.getDependency(key, cmap);
final Dependency ac2 = parent.getDependency(key, parent);
final ComponentMap outer = this;
return new Dependency(){
public ComponentMap getComponentMap(){return outer;}
public Object getArgument(int i, Class type){
try{
return ac1.getArgument(i, type);
}
catch(UnresolvedComponentException e){
return ac2.getArgument(i, type);
}
}
public Class verifyArgument(int i, Class type){
try{
return ac1.verifyArgument(i, type);
}
catch(UnresolvedComponentException e){
return ac2.verifyArgument(i, type);
}
}
public Object getProperty(Object k, Class type){
try{
return ac1.getProperty(k, type);
}
catch(UnresolvedComponentException e){
return ac2.getProperty(k, type);
}
}
public Class verifyProperty(Object k, Class type){
try{
return ac1.verifyProperty(k, type);
}
catch(UnresolvedComponentException e){
return ac2.verifyProperty(k, type);
}
}
public Object getContext(){
return ac1.getContext();
}
};*/
}
/**
* Verifies all components in this container.
* Components in the child container use the provided ComponentMap
* to resolve dependency; while those from the parent container
* use the parent container itself for resolving dependency.
*/
public void verify(ComponentMap cmap) {
child.verify(cmap);
parent.verify(parent);
}
/*
public Object getComponent(Object key, ComponentMap cmap) {
try{
return child.getComponent(key, cmap);
}
catch(KeyResolutionException e){
return parent.getComponent(key, cmap);
}
}*/
/**
* Get the component keys from both parent and child containers.
* Keys from the parent container are placed before those
* from the child container.
*/
public java.util.Set keys(){
final LinkedHashSet hset = new LinkedHashSet(parent.keys());
hset.addAll(child.keys());
return hset;
}
public boolean equals(Object obj) {
if(obj instanceof InheritedRegistrar){
final InheritedRegistrar ic2 = (InheritedRegistrar)obj;
return parent.equals(ic2.parent) && child.equals(ic2.child);
}
else return false;
}
public int hashCode() {
return parent.hashCode()*31 + child.hashCode();
}
public String toString() {
return child.toString()+":"+parent;
}
}