import java.util.*;

/** CacheManager maintains handles to a set of arbitrary objects.
 * Any class of object may be added,
 * then objects of any specified class may be retrieved.
 * For generality,
 * all retrieved objects are returned as an Object [] array.
 * The caller cannot cast this as a more specific array,
 * but must cast the individual elements.
 * <P>
 * <IMG SRC="/cgi-bin/counter">
 * Note! Keeping a CacheManager handle to an otherwise obsolete object,
 * prevents it from being garbage collected,
 * thus is a kind of memory leak. */

public class CacheManager extends Vector {

    static CacheManager me = null;

/** Constructor saves a handle to the one CacheManager instance,
 * which may then be requested from anywhere in the program. */

    public CacheManager () {
	if (null == me) me = this;
    }

/** Provide a handle to the one CacheManager instance,
 * creating it if that has not already been done.
 * This class method may be requested from anywhere in the program. */

    public static CacheManager getCacheManager () {
	if (null == me) new CacheManager ();
        return me;
    }

/** Add Object to the cache.
 * @param o the object to add.
 * @return the object added. */

    public Object add (Object o) {
	addElement (o);
	return o;
    }

/** Remove Object from the cache.
 * @param o the object to remove. */

    public void remove (Object o) {
	removeElement (o);
    }

/** Return those objects of given class if any,
 * in array of length showing how many are found.
 * @param c class of objects wanted.
 * @return array of objects of given class,
 * or of subclass that extends the given class,
 * or null if none exist in the cache. */

    public Object [] getByClass (Class c) {
	int count = 0;
	Enumeration e = elements ();
	while (e.hasMoreElements ())
	    if (c.isInstance (e.nextElement ()))
		count++;

	if (count == 0) return null;

        Object o;
	Object [] gots = new Object [count];

	count = 0;
	e = elements ();
	while (e.hasMoreElements ())
	    if (c.isInstance (o = e.nextElement ()))
		gots [count++] = o;

	return gots;
    }

/** Return those objects of given class if any,
 * in array of length showing how many are found.
 * @param name local or fully qualified name of
 * class of objects wanted.
 * @return array of objects of given class,
 * or of subclass that extends the given class,
 * or null if none exist in the cache. */

    public Object [] getByClassName (String name)
    throws ClassNotFoundException {
        return getByClass (Class.forName (name));
    }

/** Return those objects of given class if any,
 * in array of length showing how many are found.
 * The calling code need not know or care about the class,
 * just requesting objects like the given one.
 * @param o example object of class of objects wanted.
 * @return array of objects of given class,
 * or of subclass that extends the given class,
 * or null if none exist in the cache. */

    public Object [] getByClassExample (Object o) {
        return getByClass (o.getClass ());
    }

/** We could define a Listener interface,
 * to notify registered Listeners of add / remove events,
 * according to classes they are interested in. */

}
/* <IMG SRC="/cgi-bin/counter">*/
////////////////////////////////////////////////
