/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun * Microsystems, Inc. All Rights Reserved. */ package org.openide.util.lookup; import java.util.*; import java.lang.ref.WeakReference; import org.openide.util.lookup.AbstractLookup; import org.openide.util.lookup.AbstractLookup.Pair; /** A special content implementation that can be passed to AbstractLookup * and provides methods for registration of instances and lazy instances. * <PRE> * InstanceContent ic = new InstanceContent (); * AbstractLookup al = new AbstractLookup (ic); * * ic.add (new Object ()); * ic.add (new Dimension (...)); * * Dimension theDim = (Dimension)al.lookup (Dimension.class); * </PRE> * * @author Jaroslav Tulach * * @since 1.25 */ public final class InstanceContent extends AbstractLookup.Content { /** The method to add instance to the lookup with. * @param inst instance */ public final void add (Object inst) { addPair(new SimpleItem (inst)); } /** The method to add instance to the lookup with. * @param inst instance * @param conv convertor which postponing an instantiation, * if <code>conv==null</code> then the instance is registered directly. */ public final void add (Object inst, Convertor conv) { addPair(new ConvertingItem(inst, conv)); } /** Remove instance. * @param inst instance */ public final void remove (Object inst) { removePair (new SimpleItem (inst)); } /** Remove instance added with a convertor. * @param inst instance * @param conv convertor, if <code>conv==null</code> it is same like * remove(Object) */ public final void remove (Object inst, Convertor conv) { removePair (new ConvertingItem (inst, conv)); } /** Changes all pairs in the lookup to new values. Converts collection of * instances to collection of pairs. * @param col the collection of (Item) objects * @param conv the convertor to use or null */ public final void set (Collection col, Convertor conv) { ArrayList l = new ArrayList(col.size()); Iterator it = col.iterator(); if (conv == null) { while (it.hasNext()) { l.add (new SimpleItem (it.next())); } } else { while (it.hasNext()) { l.add (new ConvertingItem (it.next(), conv)); } } setPairs (l); } /** Instance of one item representing an object. */ final static class SimpleItem extends Pair { private Object obj; /** Create an item. * @obj object to register */ public SimpleItem (Object obj) { if (obj == null) throw new NullPointerException(); this.obj = obj; } /** Tests whether this item can produce object * of class c. */ public boolean instanceOf(Class c) { return c.isInstance (obj); } /** Get instance of registered object. If convertor is specified then * method InstanceLookup.Convertor.convertor is used and weak reference * to converted object is saved. * @return the instance of the object. */ public Object getInstance() { return obj; } public boolean equals (Object o) { if (o instanceof SimpleItem) { return obj.equals(((SimpleItem) o).obj); } else { return false; } } public int hashCode () { return obj.hashCode (); } /** An identity of the item. * @return string representing the item, that can be used for * persistance purposes to locate the same item next time */ public String getId() { return "IL[" + obj.toString (); // NOI18N } /** Getter for display name of the item. */ public String getDisplayName () { return obj.toString (); } /** Method that can test whether an instance of a class has been created * by this item. * * @param obj the instance * @return if the item has already create an instance and it is the same * as obj. */ protected boolean creatorOf(Object obj) { return obj == this.obj; } /** The class of this item. * @return the correct class */ public Class getType() { return obj.getClass (); } } // end of SimpleItem /** Instance of one item registered in the map. */ final static class ConvertingItem extends Pair { /** registered object */ private Object obj; /** Reference to converted object. */ private WeakReference ref; /** convertor to use */ private Convertor conv; /** Create an item. * @obj object to register * @conv a convertor, can be <code>null</code>. */ public ConvertingItem(Object obj, Convertor conv) { this.obj = obj; this.conv = conv; } /** Tests whether this item can produce object * of class c. */ public boolean instanceOf(Class c) { return c.isAssignableFrom (getType ()); } /** Returns converted object or null if obj has not been converted yet * or reference was cleared by garbage collector. */ private Object getConverted() { if (ref == null) return null; return ref.get(); } /** Get instance of registered object. If convertor is specified then * method InstanceLookup.Convertor.convertor is used and weak reference * to converted object is saved. * @return the instance of the object. */ public synchronized Object getInstance() { Object converted = getConverted(); if (converted == null) { converted = conv.convert(obj); ref = new WeakReference(converted); } return converted; } public boolean equals (Object o) { if (o instanceof ConvertingItem) { return obj.equals(((ConvertingItem) o).obj); } else { return false; } } public int hashCode () { return obj.hashCode (); } /** An identity of the item. * @return string representing the item, that can be used for * persistance purposes to locate the same item next time */ public String getId() { return conv.id (obj); } /** Getter for display name of the item. */ public String getDisplayName () { return conv.displayName (obj); } /** Method that can test whether an instance of a class has been created * by this item. * * @param obj the instance * @return if the item has already create an instance and it is the same * as obj. */ protected boolean creatorOf(Object obj) { if (conv == null) { return obj == this.obj; } else { return obj == getConverted (); } } /** The class of this item. * @return the correct class */ public Class getType() { if (conv == null) { return obj.getClass (); } Object converted = getConverted(); if (converted == null) return conv.type(obj); return converted.getClass (); } } // end of ConvertingItem /** Convertor postpones an instantiation of an object. * @since 1.25 */ public static interface Convertor { /** Convert obj to other object. There is no need to implement * cache mechanism. It is provided by InstanceLookup.Item.getInstance(). * Method should be called more than once because Lookup holds * just weak reference. * * @param obj the registered object * @return the object converted from this object */ public Object convert (Object obj); /** Return type of converted object. * @param obj the registered object * @return the class that will be produced from this object (class or * superclass of convert (obj)) */ public Class type (Object obj); /** Computes the ID of the resulted object. * @param obj the registered object * @return the ID for the object */ public String id (Object obj); /** The human presentable name for the object. * @param obj the registered object * @return the name representing the object for the user */ public String displayName (Object obj); } }