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-2004 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.modules.java.ui.nodes.elements;

import java.util.*;
import java.util.List;
import java.lang.ref.WeakReference;

import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.nodes.FilterNode;
import org.openide.cookies.FilterCookie;
import org.openide.util.Utilities;
import org.openide.ErrorManager;
import org.openide.loaders.DataObject;
import org.netbeans.jmi.javamodel.Resource;
import org.netbeans.jmi.javamodel.JavaClass;
import org.netbeans.jmi.javamodel.JavaEnum;
import org.netbeans.jmi.javamodel.AnnotationType;
import org.netbeans.modules.java.ui.nodes.SourceNodeFactory;
import org.netbeans.modules.java.ui.nodes.JavaSourceNodeFactory;
import org.netbeans.modules.javacore.internalapi.JavaMetamodel;
import org.netbeans.api.mdr.events.*;

import javax.jmi.reflect.JmiException;
import javax.jmi.reflect.InvalidObjectException;

/** Normal implementation of children for source element nodes.
* 

* Ordering and filtering of the children can be customized * using {@link SourceElementFilter}. * {@link FilterCookie} is implemented to provide a means * for user customization of the filter. *

The child list listens to changes in the source element, as well as the filter, and * automatically updates itself as appropriate. *

A child factory can be used to cause the children list to create * non-default child nodes, if desired, both at the time of the creation * of the children list, and when new children are added. *

The children list may be unattached to any source element temporarily, * in which case it will have no children (except possibly an error indicator). * * @author Dafe Simonek, Jan Jancura, Jan Pokorsky */ public class SourceChildren extends Children.Keys implements FilterCookie, ChildrenProvider.KeyHandler { /** The key describing state of source element */ static final Object NOT_KEY = new Object(); /** The key describing state of source element */ static final Object ERROR_KEY = new Object(); /** PACKAGE modifier support */ private static int PPP_MASK = SourceElementFilter.PUBLIC + SourceElementFilter.PRIVATE + SourceElementFilter.PROTECTED; /** The resource whose subelements are represented. */ protected Resource element; /** Filter for elements. Can be null, in which case * modifier filtering is disabled, and ordering may be reset to the default order. */ protected SourceElementFilter filter; /** Factory for obtaining class nodes. */ protected SourceNodeFactory factory; /** Weak listener to the resource changes. */ private JMIListener wElementL; /** Flag saying whether we have our nodes initialized */ private boolean nodesInited = false; private final ChildrenProvider chprovider = new ChildrenProvider(this); /** * this helps to track the resource identity if the resource gets invalidated. * Can be null. */ private DataObject resourceHolder; // init ................................................................................ /** Create a children list with the default factory and no attached source element. */ public SourceChildren() { this (JavaSourceNodeFactory.getDefault(), null); } /** Create a children list with the default factory. * @param resource source element to attach to, or null */ public SourceChildren(Resource resource) { this(JavaSourceNodeFactory.getDefault(), resource); } /** Create a children list with no attached source element. * @param factory a factory for creating children */ public SourceChildren(SourceNodeFactory factory) { this(factory, null); } /** Create a children list. * @param factory a factory for creating children * @param resource source element to attach to, or null */ public SourceChildren(SourceNodeFactory factory, Resource resource) { this.element = resource; this.factory = factory; this.filter = new SourceElementFilter(); this.resourceHolder = resource != null? JavaMetamodel.getManager().getDataObject(resource): null; } // FilterCookie implementation ............................................................. /* @return The class of currently asociated filter or null * if no filter is asociated with these children. */ public Class getFilterClass() { return SourceElementFilter.class; } /* @return The filter currently asociated with these children */ public Object getFilter() { return filter; } /* Sets new filter for these children. * @param filter New filter. Null == disable filtering. */ public void setFilter(Object filter) { if (!(filter instanceof SourceElementFilter)) throw new IllegalArgumentException(); this.filter = (SourceElementFilter) filter; // change element nodes according to the new filter if (nodesInited) refreshAllKeys(); } // Children implementation .............................................................. protected void addNotify () { if (element != null) { // listen to the source element property changes if (wElementL == null) { wElementL = new JMIListener(this, (MDRChangeSource) element); } ((MDRChangeSource) element).addListener(wElementL); } refreshAllKeys(); nodesInited = true; } protected void removeNotify () { if (element != null) { ((MDRChangeSource) element).removeListener(wElementL); } chprovider.clear(); nodesInited = false; } protected Node[] createNodes(Object key) { Node[] nodes; if (NOT_KEY.equals(key)) { nodes = new Node[] {factory.createWaitNode()}; } else if (key instanceof Node) { nodes = new Node[] {new FilterNode((Node) key)}; } else if (key instanceof Node[]) { Node[] ns = (Node[]) key; nodes = new Node[ns.length]; for (int i = 0; i < ns.length; i++) { Node orig = ns[i]; nodes[i] = orig == null? orig: new FilterNode(orig); } } else if (ERROR_KEY.equals(key)) { nodes = new Node[] {factory.createWaitNode()}; } else { // never should get here nodes = new Node[] {factory.createErrorNode()}; ErrorManager.getDefault().notify( ErrorManager.WARNING, new IllegalStateException("key: " + key) // NOI18N ); } return nodes; } private Node[] createNodesImpl(Object key) throws JmiException { // find out the type of the key and create appropriate node Node n; if (key instanceof JavaEnum) { n = factory.createEnumNode((JavaEnum) key); } else if (key instanceof AnnotationType) { n = factory.createAnnotationTypeNode((AnnotationType) key); } else if (key instanceof JavaClass) { n = factory.createClassNode((JavaClass) key); } else if (NOT_KEY.equals(key)) { n = factory.createWaitNode(); } else { // never should get here n = factory.createErrorNode(); } return new Node[] {n}; } public Node[] getNodes(boolean optimalResult) { if (!optimalResult || element == null) { return getNodes(); } chprovider.waitFinished(); return getNodes(); } public Node findChild(String name) { Node n = super.findChild(name); if (n == null) { chprovider.waitFinished(); n = super.findChild(name); } return n; } // main public methods .................................................................. /** Get the currently attached source element. * @return the element, or null if unattached */ public Resource getElement() { return element; } /** Set a new source element to get information about children from. * @param element the new element, or null to detach */ public void setElement(final Resource element) { if (this.element != null) { ((MDRChangeSource) element).removeListener(wElementL); } this.element = element; if (this.element != null) { if (this.resourceHolder == null) { this.resourceHolder = JavaMetamodel.getManager().getDataObject(element); } if (wElementL == null) { wElementL = new JMIListener(this, (MDRChangeSource) this.element); } else { wElementL.source = (MDRChangeSource) element; } ((MDRChangeSource) this.element).addListener(wElementL); } // change element nodes according to the new element if (nodesInited) { refreshAllKeys(); } } // other methods .......................................................................... /** Updates all the keys (elements) according to the current * filter and ordering */ private void refreshAllKeys () { List keys; if (element == null) { keys = Collections.singletonList(ERROR_KEY); setKeys(keys); } else { if (!nodesInited) { keys = Collections.singletonList(NOT_KEY); setKeys(keys); } chprovider.recomputeChildren(); } } private List collectKeysImpl() { int[] order = (filter == null || (filter.getOrder() == null)) ? SourceElementFilter.DEFAULT_ORDER : filter.getOrder(); final List keys = new LinkedList(); try { JavaMetamodel.getDefaultRepository().beginTrans(false); try { if (!element.isValid()) { keys.add(ERROR_KEY); return keys; } // build ordered and filtered keys for the subelements for (int i = 0; i < order.length; i++) addKeysOfType(keys, order[i]); } finally { JavaMetamodel.getDefaultRepository().endTrans(); } } catch (InvalidObjectException ex) { // some element is invalid. MDR will notify listeners about that change later keys.clear(); keys.add(ERROR_KEY); } catch (JmiException ex) { ErrorManager.getDefault().notify(ErrorManager.WARNING, ex); } return keys; } /** Filters and adds the keys of specified type to the given * key collection. */ private void addKeysOfType (Collection keys, final int elementType) { if (elementType == SourceElementFilter.IMPORT) { // PENDING imports are not solved yet...maybe ImportsChildren??? //keys.addAll(Arrays.asList(element.getImports())); return; } else { List/**/ cls; if ((filter != null) && filter.isAllClasses()) { cls = SourceEditSupport.getAllClasses(element); } else { cls = element.getClassifiers(); } for (Iterator it = cls.iterator(); it.hasNext(); ) { JavaClass classElement = (JavaClass) it.next(); int modifiers = classElement.getModifiers(); if ((modifiers & PPP_MASK) == 0) modifiers += SourceElementFilter.PACKAGE; if ((filter.getModifiers () & modifiers) == 0) continue; if (classElement instanceof JavaEnum) { if ((elementType & SourceElementFilter.ENUM) != 0) keys.add(classElement); } else if (classElement.isInterface()) { if ((elementType & SourceElementFilter.INTERFACE) != 0) keys.add(classElement); } else if ((elementType & SourceElementFilter.CLASS) != 0) keys.add(classElement); } } } public List collectKeys() { return this.collectKeysImpl(); } public Node[] prepareNodes(Object key) { return this.createNodesImpl(key); } public void presentKeys(List/**/ keys, List/**/ nodes) { setKeys(nodes); } // innerclasses ........................................................................... /** The listener for listening to the resource changes */ private static final class JMIListener extends WeakReference implements MDRChangeListener, Runnable { private MDRChangeSource source; public JMIListener(SourceChildren referent, MDRChangeSource source) { super(referent, Utilities.activeReferenceQueue()); this.source = source; } public void change(MDRChangeEvent e) { final SourceChildren sc = (SourceChildren) get(); if (sc == null) return; if (e instanceof AttributeEvent) { if (sc.element == null || !sc.element.isValid()) return; final AttributeEvent ae = (AttributeEvent) e; if ("classifiers".equals(ae.getAttributeName()) && sc.nodesInited) { // NOI18N sc.refreshAllKeys(); } } else if (e instanceof InstanceEvent) { // keeps track of the resource identity InstanceEvent ie = (InstanceEvent) e; Object o = ie.getInstance(); if (o == sc.element && !sc.element.isValid()) { DataObject dobj = sc.resourceHolder; if (dobj != null && dobj.isValid()) { Resource newRes = JavaMetamodel.getManager().getResource(dobj.getPrimaryFile()); sc.setElement(newRes); } else { sc.setElement(null); } } } } public void run() { source.removeListener(this); } } }

... 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.