alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 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.loaders;

import org.openide.util.Lookup;
import org.openide.nodes.*;
import org.openide.cookies.FilterCookie;
import org.openide.cookies.ElementCookie;
import org.openide.cookies.SourceCookie;
import org.openide.src.SourceElement;
import org.openide.util.WeakListener;
import org.openide.util.RequestProcessor;

import java.util.*;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;

/**
* Supports working with a set of filters defined by data objects.
* Provides a keyed list of children
* taken from a {@link org.openide.loaders.DataFolder}.
* 

An instance of this filter in its default settings * accepts all {@link org.openide.loaders.DataObject}s. *

* Additional specific filters can be added to this filter with {@link #putFilter} * to filter particular kinds of data objects. *

* Also it is possible to registering filter editor classes and to * obtain them, so as to allow modifications to the filter by the user. *

* The effect of this filter is that: *

    *
  • By default, all data objects in the folder will be "keys" * (i.e. grouping categories). *
  • Particular types of data objects can be suppressed as keys * (and corresponding children), according to the loader's data object * representation class. *
  • Data objects not providing {@link ElementCookie} will be shown as the * sole child for their key. *
  • Data objects providing ElementCookie will not be shown * directly; rather their "elements parent" will be consulted. By default * all the children it provides will be spliced into the children list * keyed by the data object. *
  • ElementCookie-enabled children will be filtered * before being used as the children for a key; the filter used will be applied * to a copy of the elements parent node, so that it may handle the filter * logic. Filters may be added according to the type of the filter, which * is specified by a filter representation class. *
*/ public class DataObjectFilter extends Children.Keys { // static .......................................................................... /** represen. class (DO) => filter class */ private static Hashtable doToFilter = new Hashtable (); /** Personal request processor */ private static RequestProcessor processor = new RequestProcessor (); /** Register a new filter type for a given type of data object. * @param representationClass the designated super class of all data objects that can use * this filter * @param filterClass the class of a filter to use for such data objects * @see FilterCookie#getFilterClass */ public static void registerFilterClass ( Class representationClass, Class filterClass ) { doToFilter.put (representationClass, filterClass); } /** Get the filter class currently registered for a data object representation class. * @return the proper filter class, or null */ public static Class getFilterClass (Class representationClass) { return (Class) doToFilter.get (representationClass); } // variables ...................................................................... /** represen. class (DO) => represen. class (DO) */ private Hashtable acceptedDOs = new Hashtable (); /** filter class => filter */ private Hashtable filters = new Hashtable (); /** current representing DF */ private DataFolder dataFolder; /** Filters DOs */ private DataFilter filter; /** Listens on DataFolder */ private PropertyChangeListener folderFerret; /** Keeps listener */ private PropertyChangeListener folderFerretKeeper; /** Listens Nodes */ private NodeListener ferret; /** Node => DO */ private Hashtable noToDo = new Hashtable (); /** DO => Node */ // private Hashtable doToNo = new Hashtable (); /** true if subnodes of this node are visible */ private boolean nodesInited = false; // init ........................................................................... /** Create a new filter which will accept given set of data objects. * Initially unattached to any data folder. * @param representationClasses representation classes of data objects to be shown */ public DataObjectFilter (Class[] representationClasses) { filter = new DataFilter () { public boolean acceptDataObject (DataObject obj) { Enumeration e = acceptedDOs.keys (); Class c = obj.getClass (); while (e.hasMoreElements ()) { if (((Class) e.nextElement ()).isAssignableFrom (c)) { return true; } } return false; } }; folderFerret = WeakListener.propertyChange ( folderFerretKeeper = new PropertyChangeListener () { public void propertyChange (PropertyChangeEvent ev) { if (nodesInited) { if (ev.getPropertyName().equals(DataFolder.PROP_CHILDREN)) { refreshAll (); } } } }, null ); ferret = new NodeAdapter () { public void childrenAdded (NodeMemberEvent ev) { refresh ((DataObject) noToDo.get (ev.getSource ())); } public void childrenRemoved (NodeMemberEvent ev) { refresh ((DataObject) noToDo.get (ev.getSource ())); } }; int i, k = representationClasses.length; for (i = 0; i < k; i++) acceptedDOs.put (representationClasses [i], representationClasses [i]); //System.out.println ("#DOF: " + (++dof)); // NOI18N } //static int dof = 0; //static int refreshAllCounter = 0; //static int createNodesCount = 0; // protected void finalize () { TESTING //System.out.println ("#DOF end: " + (--dof)); // NOI18N // } /** Create a new filter which will accept all data objects. * Initially unattached to any data folder. */ public DataObjectFilter () { this (new Class [] {}); DataLoader[] loaders = ((DataLoaderPool)Lookup.getDefault().lookup(DataLoaderPool.class)).toArray(); int i, k = loaders.length; for (i = 0; i < k; i++) { Class c = loaders [i].getRepresentationClass (); if (DataFolder.class.isAssignableFrom (c)) continue; acceptedDOs.put (c, c); } } /** Create a new filter which will accept all data objects in a given folder. * @param dataFolder the folder to filter */ public DataObjectFilter (DataFolder dataFolder) { this (); this.dataFolder = dataFolder; } // main methods .................................................................. /** * Add a filter for a certain type of data object. * The previous filter, if any, will be removed. * @param filterClass the representation class this filter belongs to * @param filter the filter to use for all data objects requesting this type of filter, * via {@link FilterCookie#getFilterClass}. May be null to remove. */ public void putFilter (Class filterClass, Object filter) { //System.out.println ("putFilter: "); // NOI18N Object old = filters.get (filterClass); if (old == null) { if (filter == null) return; } else if ((filter != null) && filter.equals (old)) return; if (filter == null) filters.remove (filterClass); else filters.put (filterClass, filter); if (nodesInited) refreshNodes (); //System.out.println ("putFilter end: "); // NOI18N } /** * Permit a representation class of data object to be shown * (after appropriate filtering). * By default all are shown, so this need be used only to counteract * {@link #removeLoader}. * @param representationClass the data object representation class */ public void addLoader (Class representationClass) { acceptedDOs.put (representationClass, representationClass); if (nodesInited) refreshAll (); } /** * Prevent a representation class of data object from being show at all. * @param representationClass the data object representation class * @see org.openide.loaders.DataLoader#getRepresentationClass */ public void removeLoader (Class representationClass) { Object filter = doToFilter.get (representationClass); if (filter != null) filters.remove (filter); acceptedDOs.remove (representationClass); if (nodesInited) refreshAll (); } /** Attach the support to a different folder. * @param f the new folder */ public synchronized void setDataFolder (DataFolder f) { if ((dataFolder != null) && (f != null) && dataFolder.equals (f) ) return; if (dataFolder != null) { dataFolder.removePropertyChangeListener (folderFerret); cancel (); } dataFolder = f; //System.out.println ("DOF.setDataFolder: " + ((dataFolder == null) ? "null" : "" + dataFolder.getPrimaryFile ()) + " " + nodesInited); // NOI18N // if (nodesInited) refreshAll (); if (dataFolder != null) dataFolder.addPropertyChangeListener (folderFerret); } /** Get the folder this support is attached to. * @return the folder */ public DataFolder getDataFolder () { return dataFolder; } // children implementation ......................................................... /* Overrides initNodes to run the preparation task of the * data object filter, call refreshKeys and start to * listen to the changes in the element too. */ protected void addNotify () { // setKeysHelper (Collections.EMPTY_SET); // refreshAll (); nodesInited = true; //System.out.println ("DOF.addNotify"); // NOI18N } protected void removeNotify () { setKeysHelper (Collections.EMPTY_SET); nodesInited = false; //System.out.println ("DOF.removeNotify"); // NOI18N } /** Create children for a data-object key. * If {@link ElementCookie} is provided, then the proxy node's children * are used for this node's children (for this key), after possible filtering * based on the {@link #putFilter current filters}. * If ElementCookie is not provided, then * (a copy of) this data's object's delegate node is used as the sole child * for this key. * @param key a {@link org.openide.loaders.DataObject} to create representative children for * @return a list of child nodes for this key */ protected Node[] createNodes (Object key) { DataObject DO = (DataObject) key; if (!currentKeys.contains (DO)) { //System.out.println (" createNodes !!!!!!!!!!!! " + DO.getPrimaryFile ()); // NOI18N return new Node[] {}; } //System.out.println (" createNodes: " + (++createNodesCount) + " " + DO.getPrimaryFile ()); // NOI18N ElementCookie ec = (ElementCookie) DO.getCookie (ElementCookie.class); Node root; if (ec == null) { root = DO.getNodeDelegate ().cloneNode (); //System.out.println (" createNodes end: " + (--createNodesCount) + " " + DO.getPrimaryFile ()); // NOI18N return new Node[] {root}; } root = ec.getElementsParent (); FilterCookie fc = (FilterCookie) root.getCookie (FilterCookie.class); if (fc != null) { Object filter = filters.get (fc.getFilterClass ()); if (filter != null) fc.setFilter (filter); } //System.out.println (" createNodes1 "); // NOI18N Node[] n = root.getChildren ().getNodes (); // Connect to node... if (noToDo.get (root) == null) { root.addNodeListener (ferret); noToDo.put (root, key); } // doToNo.put (key, root); int i, k = n.length; Node[] nn = new Node [k]; for (i = 0; i < k; i++) nn [i] = n [i].cloneNode (); //System.out.println (" createNodes end: " + (--createNodesCount) + " " + DO.getPrimaryFile ()); // NOI18N return nn; } // other methods ................................................................... /** Helper accessing method. * Collection getKeys () { return keys; } */ Collection keys; /** Refreshs all current keys. */ void refreshAllKeys () { setKeys (Collections.EMPTY_SET); setKeys (keys); } /** Helper accessing method. */ void setKeysHelper (Collection l) { setKeys (keys = l); } /** Helper accessing method. */ void refreskKeyHelper (Object l) { refreshKey (l); } private synchronized void cancel () { currentTask = null; //System.out.println ("cancel: "); // NOI18N Enumeration e = noToDo.keys (); while (e.hasMoreElements ()) { Node n = (Node) e.nextElement (); n.removeNodeListener (ferret); } noToDo = new Hashtable (); // doToNo = new Hashtable (); //System.out.println ("cancel end: "); // NOI18N } private Runnable currentTask; private HashSet currentKeys; /** * Refreshs all dataobjects from current folder. */ private void refreshAll () { if (dataFolder == null) { setKeysHelper (Collections.EMPTY_SET); return; } //final DataFolder df = dataFolder; currentKeys = new HashSet (); //System.out.println ("refreshAll prepare: " + df.getPrimaryFile () + " by " + Thread.currentThread ().getName ()); // NOI18N processor.postRequest (currentTask = new Runnable () { public void run () { if (currentTask != this) { //System.out.println ("refreshAll !!!!!!" + " " + df.getPrimaryFile ()); // NOI18N return; } //System.out.println ("refreshAll: " + (++refreshAllCounter) + " " + df.getPrimaryFile ()); // NOI18N List newDo = dataFolder.getChildrenList (); int i; for (i = newDo.size () - 1; i >= 0; i--) if (!filter.acceptDataObject ((DataObject) newDo.get (i))) newDo.remove (i); // LinkedList ll = new LinkedList (getKeys ()); if (currentTask != this) { //System.out.println ("refreshAll2 !!!!!!" + " " + df.getPrimaryFile ()); // NOI18N return; } //System.out.println ("PARSING " + df.getPrimaryFile () + " ........................................................................."); // NOI18N currentKeys = new HashSet (newDo); LinkedList ll = new LinkedList (); int k = newDo.size (); for (i = 0; i < k; i++) { DataObject o = (DataObject) newDo.get (i); SourceCookie sc = (SourceCookie) o.getCookie (SourceCookie.class); if (sc != null) { SourceElement se = sc.getSource (); se.prepare ().waitFinished (); if (currentTask != this) { //System.out.println ("refreshAll3 !!!!!!" + " " + df.getPrimaryFile ()); // NOI18N return; } } ll.add (o); setKeysHelper (ll); /* if (!getKeys ().contains (o)) { // Disconnect from node... Node n = (Node) doToNo.remove (o); if (n == null) continue; noToDo.remove (n); n.removeNodeListener (ferret); } */ } //System.out.println ("refreshAll end: " + (--refreshAllCounter) + " " + df.getPrimaryFile ()); // NOI18N } }); } private Runnable currentTask1; /** * Refreshs all dataobjects from current folder. */ private void refreshNodes () { if (dataFolder == null) { setKeysHelper (Collections.EMPTY_SET); return; } processor.postRequest (currentTask1 = new Runnable () { public void run () { //System.out.println (" refreshNodes: "); // NOI18N if (dataFolder == null) return; if (this != currentTask1) return; /* JST: Not necessary anymore Collection c = getKeys (); setKeysHelper (Collections.EMPTY_SET); setKeysHelper (c); */ refreshAllKeys (); //System.out.println (" refreshNodes end: "); // NOI18N } }); } /** * Refreshs given dataobject from current folder. */ private void refresh (final DataObject key) { if (!currentKeys.contains (key)) { //System.out.println (" refresh key prepare !!!!!: " + key.getPrimaryFile ()); // NOI18N return; } if (!filter.acceptDataObject (key)) return; //System.out.println (" refresh key prepare: " + key.getPrimaryFile () + " by " + Thread.currentThread ().getName ()); // NOI18N processor.postRequest (new Runnable () { public void run () { if (!currentKeys.contains (key)) { //System.out.println (" refresh key !!!!!!: " + key.getPrimaryFile ()); // NOI18N return; } //System.out.println (" refresh key: " + key.getPrimaryFile ()); // NOI18N refreskKeyHelper (key); } }); } }
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.