/*
* Copyright (C) 2004 TiongHiang Lee
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Email: thlee@onemindsoft.org
*/
package org.onemind.commons.java.datastructure;
import java.util.*;
/**
* Associate a class and an value object and resolve the mapping through the
* class hierachy.
*
* For example, if a value object A is assosiated with Number class that
* means it is associated with the Number class and all the subclasses of
* object class. However, if a mapping exists for Integer, the InheritableValueMap
* will return the value object associated for the Integer.
*
* The stopClass controls when the InheritableValueMap stop resolving mapping and
* return null (when c==stopClass.getSuperClass()). The stopClass also control
* the hierachy of object that can be added the the map - meaning
* stopClass.isAssignableFrom(c) must evaluate to true when c is added as mapping key.
*
* @author TiongHiang Lee (thlee@onemindsoft.org)
* @version $Id: InheritableValueMap.java,v 1.3 2005/02/17 19:57:31 thlee Exp $ $Name: $
*/
public class InheritableValueMap
{
/** the mapping * */
private Map _map = new HashMap();
/** the stop class * */
private Class _stopClass;
/**
* Use Object.class as stop class {@inheritDoc}
*/
public InheritableValueMap()
{
this(Object.class);
}
/**
* {@inheritDoc}
* @param stopClass the stop class
*/
public InheritableValueMap(Class stopClass)
{
_stopClass = stopClass;
}
/**
* Add the mapping between the class c and the object o. The object o must be the stopClass or a subclass of the stopClass
* @param c the class
* @param o the object
*/
public void put(Class c, Object o)
{
if (!_stopClass.isAssignableFrom(c))
{
throw new IllegalArgumentException("Cannot add key class " + c
+ " that is not a subclass of stopClass " + _stopClass);
}
_map.put(c, o);
}
/**
* Resolve the object associated with class c
* @param c the class
* @return the object associated with class c, or null
*/
public Object resolve(Class c)
{
if (c == null)
{ //add protection
return null;
} else if (!_stopClass.isAssignableFrom(c))
{
throw new RuntimeException(
"Cannot get entry for key class that is not a subclass of stopClass "
+ _stopClass);
}
while (c != _stopClass.getSuperclass())
{
Object o = _map.get(c);
if (o != null)
{
return o;
}
c = c.getSuperclass();
}
return null;
}
/**
* Return the key classes
* @return the classes
*/
public final Set keySet()
{
return _map.keySet();
}
/**
* Resolve all the mapping that could have apply to c in class c's inheritance hierachy
* @param c the class
* @return the Collection contains all the mappings
*/
public Collection resolveAll(Class c)
{
if (!_stopClass.isAssignableFrom(c))
{
throw new RuntimeException(
"Cannot get entry for key class that is not a subclass of stopClass "
+ _stopClass);
}
List l = new ArrayList();
while (c != _stopClass.getSuperclass())
{
Object o = _map.get(c);
if (o != null)
{
l.add(o);
}
c = c.getSuperclass();
}
return l;
}
}