All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openide.nodes.CookieSet Maven / Gradle / Ivy

Go to download

The NetBeans Platform is a generic base for desktop applications. It provides the services common to almost all large desktop applications: window management, menus, settings and storage, an update manager, and file access. Get a head start by reusing these standard components, allowing you to concentrate fully on your application's business logic.

The newest version!
/*
 *                 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-2003 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.openide.nodes;

import java.util.*;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.EventListenerList;

/** Support class for storing cookies and
* retriving them by representation class.
* Provides simple notifications about changes
* in cookies.
*
* @author Jaroslav Tulach
*/
public final class CookieSet extends Object {
    /** variable to allow effecient communication with NodeLookup */
    private static ThreadLocal QUERY_MODE = new ThreadLocal ();
    
    /** list of cookies (Class, Node.Cookie) */
    private HashMap map = new HashMap (31);

    /** set of listeners */
    private EventListenerList listeners = new EventListenerList ();

    /** Default constructor. */
    public CookieSet() {}
    
    /** Add a new cookie to the set. If a cookie of the same
    * actual (not representation!) class is already there,
    * it is replaced.
    * 

Cookies inserted earlier are given preference during lookup, * in case a supplied representation class matches more than one cookie * in the set. * * @param cookie cookie to add */ public void add (Node.Cookie cookie) { synchronized (this) { registerCookie (cookie.getClass (), cookie); } fireChangeEvent (); } /** Remove a cookie from the set. * @param cookie the cookie to remove */ public void remove (Node.Cookie cookie) { synchronized (this) { unregisterCookie (cookie.getClass (), cookie); } fireChangeEvent (); } /** Get a cookie. * * @param clazz the representation class * @return a cookie assignable to the representation class, or null if there is none */ public Node.Cookie getCookie (Class clazz) { Node.Cookie ret = null; synchronized (this) { R r = findR (clazz); if (r == null) { return null; } ret = r.cookie (); } if (ret instanceof CookieEntry) { if (clazz == QUERY_MODE.get ()) { // we expected to be asked for this class // set cookie entry as a result QUERY_MODE.set (ret); ret = null; } else { // unwrap the cookie ret = ((CookieEntry) ret).getCookie(true); } } return ret; } /** Add a listener to changes in the cookie set. * @param l the listener to add */ public void addChangeListener (ChangeListener l) { listeners.add (ChangeListener.class, l); } /** Remove a listener to changes in the cookie set. * @param l the listener to remove */ public void removeChangeListener (ChangeListener l) { listeners.remove (ChangeListener.class, l); } /** Node lookup starts its non-important query. */ static Object entryQueryMode (Class c) { Object prev = QUERY_MODE.get (); QUERY_MODE.set (c); return prev; } /** Exits query mode. */ static org.openide.util.lookup.AbstractLookup.Pair exitQueryMode (Object prev) { Object cookie = QUERY_MODE.get (); QUERY_MODE.set (prev); if (cookie instanceof CookieSet.CookieEntry) { return new CookieEntryPair ((CookieSet.CookieEntry)cookie); } else { return null; } } /** Fires change event */ private void fireChangeEvent () { Object[] arr = listeners.getListenerList(); if (arr.length > 0) { ChangeEvent ev = null; // Process the listeners last to first, notifying // those that are interested in this event for (int i = arr.length-2; i>=0; i-=2) { if (arr[i] == ChangeListener.class) { if (ev == null) { ev = new ChangeEvent (this); } ((ChangeListener)arr[i + 1]).stateChanged (ev); } } } } /** Attaches cookie to given class and all its superclasses and * superinterfaces. * * @param c class or null * @param cookie cookie to attach */ private void registerCookie (Class c, Node.Cookie cookie) { if ((c == null) || !Node.Cookie.class.isAssignableFrom(c)) return; R r = findR (c); if (r == null) { r = new R (); map.put (c, r); } r.add (cookie); registerCookie (c.getSuperclass (), cookie); Class[] inter = c.getInterfaces (); for (int i = 0; i < inter.length; i++) { registerCookie (inter[i], cookie); } } /** Removes cookie from the class and all its superclasses and * superinterfaces. * * @param c class or null * @param cookie cookie to attach */ private void unregisterCookie (Class c, Node.Cookie cookie) { if ( c == null || !Node.Cookie.class.isAssignableFrom(c) ) return; // if different cookie is attached to class c stop removing R r = findR (c); if (r != null) { // remove the cookie r.remove (cookie); } unregisterCookie (c.getSuperclass (), cookie); Class[] inter = c.getInterfaces (); for (int i = 0; i < inter.length; i++) { unregisterCookie (inter[i], cookie); } } /** Registers a Factory for given cookie class */ public void add(Class cookieClass, Factory factory) { if (factory == null) { throw new IllegalArgumentException(); } synchronized (this) { registerCookie (cookieClass, new CookieEntry(factory, cookieClass)); } fireChangeEvent (); } /** Registers a Factory for given cookie classes */ public void add(Class[] cookieClass, Factory factory) { if (factory == null) { throw new IllegalArgumentException(); } synchronized (this) { for (int i = 0; i < cookieClass.length; i++) { registerCookie (cookieClass[i], new CookieEntry(factory, cookieClass[i])); } } fireChangeEvent (); } /** * Unregisters a Factory for given cookie class * @since 2.6 */ public void remove(Class cookieClass, Factory factory) { if (factory == null) { throw new IllegalArgumentException(); } synchronized (this) { R r = findR(cookieClass); if (r != null) { Node.Cookie c = r.cookie(); if (c instanceof CookieEntry) { CookieEntry ce = (CookieEntry)c; if (ce.factory == factory) { unregisterCookie (cookieClass, c); } } } } fireChangeEvent (); } /** * Unregisters a Factory for given cookie classes * @since 2.6 */ public void remove(Class[] cookieClass, Factory factory) { if (factory == null) { throw new IllegalArgumentException(); } synchronized (this) { for (int i = 0; i < cookieClass.length; i++) { R r = findR(cookieClass[i]); if (r != null) { Node.Cookie c = r.cookie(); if (c instanceof CookieEntry) { CookieEntry ce = (CookieEntry)c; if (ce.factory == factory) { unregisterCookie (cookieClass[i], c); } } } } } fireChangeEvent (); } /** Finds a result in a map. */ private R findR (Class c) { return (R)map.get (c); } /** Finds base class for a cookie. * @param c cookie * @return base class */ private static Class baseForCookie (Node.Cookie c) { if (c instanceof CookieEntry) { return ((CookieEntry)c).klass; } return c.getClass (); } /** Factory for creating cookies of given Class */ public static interface Factory { /** Creates a Node.Cookie of given class. The method * may be called more than once. */ public Node.Cookie createCookie(Class klass); } /** Entry for one Cookie */ private static class CookieEntry implements Node.Cookie { /** Factory for the cookie */ final Factory factory; /** Class of the cookie */ private final Class klass; /** A Referenec to the cookie */ private Reference cookie; /** Constructs new FactoryEntry */ public CookieEntry(Factory factory, Class klass) { this.factory = factory; this.klass = klass; } /** Getter for the cookie. * Synchronized because we don't want to run factory.createCookie * symultaneously from two threads. */ public synchronized Node.Cookie getCookie(boolean create) { Node.Cookie ret; if (create) { if ((cookie == null) || ((ret = (Node.Cookie) cookie.get()) == null)) { ret = factory.createCookie(klass); if (ret == null) return null; cookie = new WeakReference(ret); } } else { ret = (Node.Cookie) (cookie == null ? null : cookie.get ()); } return ret; } } // end of CookieEntry /** Pair that represents an entry. */ private static final class CookieEntryPair extends org.openide.util.lookup.AbstractLookup.Pair { private CookieEntry entry; public CookieEntryPair (CookieEntry e) { this.entry = e; } protected boolean creatorOf(Object obj) { return obj == entry.getCookie (false); } public String getDisplayName() { return getId (); } public String getId() { return entry.klass.getName (); } public Object getInstance() { return entry.getCookie (true); } public Class getType() { return entry.klass; } protected boolean instanceOf(Class c) { return c.isAssignableFrom(entry.klass); } public int hashCode () { return entry.hashCode () + 5; } public boolean equals (Object obj) { if (obj instanceof CookieEntryPair) { return ((CookieEntryPair)obj).entry == entry; } return false; } } // end of CookieEntryPair /** Implementation of the result. */ private static final class R extends Object { /** list of registered cookies */ public List cookies; /** base class of the first cookie registered here */ public Class base; R() {} /** Adds a cookie. * @return true if adding should continue on superclasses should continue */ public void add (Node.Cookie cookie) { if (cookies == null) { cookies = new ArrayList (1); cookies.add (cookie); base = baseForCookie (cookie); return; } Class newBase = baseForCookie (cookie); if (base == null || newBase.isAssignableFrom (base)) { cookies.set (0, cookie); base = newBase; } else { cookies.add (cookie); } } /** Removes a cookie. * @return true if empty */ public boolean remove (Node.Cookie cookie) { if (cookies == null) { return true; } if (cookies.remove (cookie) && cookies.size () == 0) { base = null; cookies = null; return true; } base = baseForCookie ((Node.Cookie)cookies.get (0)); return false; } /** @return the cookie for this result or null */ public Node.Cookie cookie () { return cookies == null || cookies.isEmpty () ? null : (Node.Cookie)cookies.get (0); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy