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

import junit.framework.*;
import junit.textui.TestRunner;
import java.util.*;
import org.openide.nodes.*;

import org.netbeans.junit.*;
import org.openide.cookies.SaveCookie;
import org.openide.util.Lookup;

import org.openide.util.LookupListener;
import org.openide.util.lookup.*;

/** Tests whether notification to NodeListener is fired under Mutex.writeAccess
 *
 * @author Jaroslav Tulach
 */
public class NodeLookupTest extends NbTestCase {
    public NodeLookupTest(String name) {
        super(name);
    }
    
    public static void main(String[] args) {
        TestRunner.run(new NbTestSuite(NodeLookupTest.class));
    }
    
    public void testChangesAreFiredFromLookup () {
        CountableLookup lkp = new CountableLookup ();
        Node node = new AbstractNode (createChildren (), lkp);

        checkGetNodesDoesNotInitializeLookup (node, lkp.queries);
        checkInstanceInGetCookie (new Node.Cookie () {}, lkp.ic, node);
        checkInstanceInGetLookup (new Node.Cookie () {}, lkp.ic, node, true);
        checkInstanceInGetLookup ("Some string", lkp.ic, node, true);
    }

    public void testChangesAreFiredFromLookupThruFilterNode () {
        CountableLookup lkp = new CountableLookup ();
        Node node = new FilterNode (new AbstractNode (createChildren (), lkp));

        checkGetNodesDoesNotInitializeLookup (node, lkp.queries);
        //checkInstanceInGetCookie (new Node.Cookie () {}, ic, node);
        checkInstanceInGetLookup (new Node.Cookie () {}, lkp.ic, node, true);
        checkInstanceInGetLookup ("Some string", lkp.ic, node, true);
    }
    
    public void testChangesAreFiredFromLookupAssociatedToFilterNode () {
        CountableLookup lkp = new CountableLookup ();
        Node node = new FilterNode (Node.EMPTY, Children.LEAF, lkp);

        checkGetNodesDoesNotInitializeLookup (node, lkp.queries);
        checkInstanceInGetCookie (new Node.Cookie () {}, lkp.ic, node);
        checkInstanceInGetLookup (new Node.Cookie () {}, lkp.ic, node, true);
        checkInstanceInGetLookup ("Some string", lkp.ic, node, true);
    }

    public void testChangesAreFiredFromLookupThruFilterNodeWithOverWrittenGetCookie () {
        final Node.Cookie myInstance = new Node.Cookie () { };
        final ArrayList queries = new ArrayList ();
        
        InstanceContent ic = new InstanceContent ();
        AbstractLookup lookup = new AbstractLookup (ic);
        Node node = new FilterNode (new AbstractNode (createChildren (), lookup)) {
            public Node.Cookie getCookie (Class clazz) {
                queries.add (clazz);
                
                if (clazz == myInstance.getClass ()) {
                    return myInstance;
                }
                return super.getCookie (clazz);
            }
        };

        checkGetNodesDoesNotInitializeLookup (node, queries);
        checkInstanceInGetCookie (new Node.Cookie () {}, ic, node);
        checkInstanceInGetLookup (new Node.Cookie () {}, ic, node, true);
        // by overwriting the FilterNode.getCookie we disable enhanced support
        // for non-cookie objects in original lookup
        checkInstanceInGetLookup ("Some string", ic, node, false);
        
        assertEquals ("It is possible to get myInstance from getCookie", myInstance, node.getCookie (myInstance.getClass ()));
        assertEquals ("It also possible to get it from getLookup", myInstance, node.getLookup ().lookup (myInstance.getClass ()));
    }
    
    private void checkInstanceInGetCookie (Object obj, InstanceContent ic, Node node) {
        assertNull ("The node does not contain the object yet", node.getCookie (obj.getClass ()));
        
        Listener listener = new Listener ();
        node.addNodeListener(listener);
        
        ic.add (obj);
        listener.assertEvents ("One change in node", 1, -1);

        if (obj instanceof Node.Cookie) {
            assertEquals ("Can access cookie in the content", obj, node.getCookie (obj.getClass ()));
        } else {
            assertNull ("Cannot access noncookie in the content", node.getCookie (obj.getClass ()));
        }

        ic.remove (obj);
        listener.assertEvents ("One change in node", 1, -1);
    }
    
    private void checkInstanceInGetLookup (Object obj, InstanceContent ic, Node node, boolean shouldBeThere) {
        Listener listener = new Listener ();
        Lookup.Result res = node.getLookup ().lookup (new Lookup.Template (obj.getClass ()));
        Collection ignore = res.allItems ();
        res.addLookupListener(listener);

        ic.add (obj);
        if (shouldBeThere) {
            listener.assertEvents ("One change in node's lookup", -1, 1);
            assertEquals ("Can access object in content via lookup", obj, node.getLookup ().lookup (obj.getClass ()));
        } else {
            assertNull ("Cannot access object in content via lookup", node.getLookup ().lookup (obj.getClass ()));
        }
            
        
        ic.remove (obj);
        if (shouldBeThere) {
            listener.assertEvents ("One change in node's lookup", -1, 1);
        }
        assertNull ("Cookie is removed", node.getLookup ().lookup (obj.getClass ()));
    }
    
    public void testNoPropertyChangeWhenQueryingForAnExistingCookieBug40734 () throws Exception {
        class MyN extends AbstractNode {
            MyN () {
                super (Children.LEAF);
            }
            
            private Node.Cookie my = new Node.Cookie () {
                public String toString () {
                    return "PlainCookie";
                }
            };
            private Node.Cookie save = new SaveCookie () {
                public void save () {
                }
        
                public String toString () {
                    return "SaveCookie";
                }
            };
            public Node.Cookie getCookie (Class c) {
                if (c == Node.Cookie.class) return my;
                if (c == SaveCookie.class) return save;
                
                return null;
            }
            
            public String toString () {
                return "Node";
            }
        };
        FilterNode fn = new FilterNode (new MyN ());
        
        class L extends NodeAdapter implements LookupListener {
            public String ev;
            public org.openide.util.LookupEvent lookup;
            
            public void propertyChange (java.beans.PropertyChangeEvent ev) {
                this.ev = ev.getPropertyName ();
            }
            
            public void resultChanged (org.openide.util.LookupEvent ev) {
                lookup = ev;
            }
        }
        L l = new L ();
        
        Lookup.Template templCookies = new Lookup.Template (Node.Cookie.class);
        fn.addNodeListener (l);
        Lookup.Result res = fn.getLookup ().lookup (templCookies);
        assertEquals ("No event fired0", null, l.ev);
        res.addLookupListener (l);
        Collection items = res.allItems ();
        if (1 != items.size ()) {
            fail ("Wrong items: " + items + " instances: " + res.allInstances ());
        }
        assertEquals ("No event fired1", null, l.ev);
        
        Lookup.Template templSave = new Lookup.Template (SaveCookie.class);
        assertNotNull ("The save cookie is there", fn.getLookup ().lookupItem (templSave));
        assertEquals ("No event fired2", null, l.ev);
        
        assertNotNull ("There is change in all cookies, so event should be fired", l.lookup);
        items = res.allItems ();
        if (2 != items.size ()) {
            fail ("Wrong items: " + items + " instances: " + res.allInstances ());
        }
        
        assertEquals ("No event fired3", null, l.ev);
    }
    
    
    //
    // Test to see correct behaviour from getCookie to lookup
    //
    
    public void testNodeIsInItsLookup () {
        CookieNode n = new CookieNode ();
        assertEquals ("Node is there", n, n.getLookup ().lookup (Node.class));
    }
    
    public void testFilterNodeWithOverridenGetCookieIsInTheLookup () {
        doTestFilterNodeWithOverridenGetCookieIsInTheLookup (new CookieNode (), false);
    }
    
    public void testFilterNodeWithOverridenGetCookieIsInTheLookupWitSaveCookieWithoutQuery () {
        doTestFilterNodeWithOverridenGetCookieIsInTheLookup (new CookieNodeWithCookie (), false);
    }
    
    public void testFilterNodeWithOverridenGetCookieIsInTheLookupWitSaveCookie () {
        doTestFilterNodeWithOverridenGetCookieIsInTheLookup (new CookieNodeWithCookie (), true);
    }
    private void doTestFilterNodeWithOverridenGetCookieIsInTheLookup (CookieNode n, boolean queryForCookie) {
        final ArrayList queries = new ArrayList ();
        class MyFN extends FilterNode {
            public MyFN (Node n) {
                super (n);
            }
            
            public Node.Cookie getCookie (Class clazz) {
                queries.add (clazz);
                return super.getCookie (clazz);
            }
        }
        
        FilterNode fn = new MyFN (n);
        checkGetNodesDoesNotInitializeLookup (fn, queries);
        checkGetNodesDoesNotInitializeLookup (fn, n.queries);
        
        Lookup l = fn.getLookup ();
        
        if (queryForCookie) {
            l.lookup (SaveCookie.class);
        }
        
        // == must be used instead of equals for nodes!!!
        assertTrue ("Node is there", fn == l.lookup (Node.class));
        Collection c = l.lookup (new Lookup.Template (Node.class)).allInstances ();
        
        if (!queryForCookie) {
            assertEquals ("Just one node", 1, c.size ());
        } else {
            assertEquals ("The cookie is implemented by the node, thus there are two nodes", 2, c.size ());
        }
        assertTrue ("And the first is the filter", c.iterator ().next () == fn);
    }
    
    public void testFilterNodeThatDoesNotOverrideGetCookie () {
        doTestFilterNodeThatDoesNotOverrideGetCookie (new CookieNode ());
    }
    
    public void testFilterNodeThatDoesNotOverrideGetCookieWithSaveCookie () {
        doTestFilterNodeThatDoesNotOverrideGetCookie (new CookieNodeWithCookie ());
    }
        
    private void doTestFilterNodeThatDoesNotOverrideGetCookie (CookieNode n) {
        FilterNode fn = new FilterNode (n);
        checkGetNodesDoesNotInitializeLookup (fn, n.queries);
        
        Lookup l = fn.getLookup ();
        
        // == must be used instead of equals for nodes!!!
        assertTrue ("Node is there", fn == l.lookup (Node.class));
        Collection c = l.lookup (new Lookup.Template (Node.class)).allInstances ();
        assertEquals ("Just one node", 1, c.size ());
        assertTrue ("And it is the one", c.iterator ().next () == fn);
    }
    
    public void testChangeInCookieVisibleInLookup () {
        CookieNode n = new CookieNode ();
        checkInstanceInLookup (new Node.Cookie() {}, n.cookieSet(), n.getLookup ());
    }

    public void testChangeInCookieVisibleInLookupThruFilterNode () {
        CookieNode n = new CookieNode ();
        FilterNode f = new FilterNode (n);
        checkInstanceInLookup (new Node.Cookie() {}, n.cookieSet(), f.getLookup ());
    }
    
    public void testChangeInCookieVisibleInLookupThruFilterNodeWhenItOverridesGetCookie () {
        CookieNode n = new CookieNode ();
        
        class MyFilterNode extends FilterNode implements javax.swing.event.ChangeListener {
            public CookieSet set = new CookieSet ();
            
            public MyFilterNode (Node n) {
                super (n);
                set.addChangeListener(this);
            }
            
            public Node.Cookie getCookie (Class cl) {
                Node.Cookie c = super.getCookie (cl);
                if (c != null) {
                    return c;
                }
                return set.getCookie (cl);
            }
            
            public void stateChanged (javax.swing.event.ChangeEvent ev) {
                fireCookieChange ();
            }
        }
                
        MyFilterNode f = new MyFilterNode (n);
        
        checkInstanceInLookup (new Node.Cookie() {}, n.cookieSet(), f.getLookup ());
        checkInstanceInLookup (new Node.Cookie() {}, f.set, f.getLookup ());
    }
    
    public void testFilterNodeDelegatesCorrectly () {
        class CN extends CookieNode implements SaveCookie {
            public CN () {
                getCookieSet ().add (this);
            }
            public void save () {
            }
        }
        
        CN save = new CN ();
        FilterNode node = new FilterNode (save);
        
        Class[] classs={ SaveCookie.class, CN.class };
        
        for( int i = 0; i < classs.length; i++ ) {
            Lookup.Template t = new Lookup.Template (classs[i]);
            Object cookie = node.getLookup ().lookup (t.getType ());
            assertTrue ("it is the right class: " + classs[i] + " : " + cookie, classs[i].isInstance(cookie));
            assertTrue (cookie + " == " + save, cookie == save);

            Lookup.Item item = node.getLookup ().lookupItem (t);
            assertTrue ("Should be " + classs[i] + " is " + item.getType(), classs[i].isAssignableFrom(item.getType()));
            assertTrue ("value is the same", item.getInstance() == save);

            Collection c = node.getLookup ().lookup (t).allInstances ();
            assertEquals ("One save cookie", 1, c.size ());
            assertTrue ("It is the cookie", c.iterator ().next () == save);

            c = node.getLookup ().lookup (t).allItems ();
            assertEquals ("One save cookie", 1, c.size ());
            item = (Lookup.Item)c.iterator().next ();
            assertTrue ("Should be " + classs[i] + " is " + item.getType(), classs[i].isAssignableFrom(item.getType()));
            assertTrue ("value is the same", item.getInstance() == save);
        }
    }
    
    private void checkInstanceInLookup (Node.Cookie obj, CookieSet ic, Lookup l) {
        Listener listener = new Listener ();
        Lookup.Result res = l.lookup (new Lookup.Template (Object.class));
        Collection justToEnsureChangesToListenerWillBeFired = res.allItems ();
        res.addLookupListener(listener);
        
        ic.add (obj);
        listener.assertEvents ("One change in lookup", -1, 1);

        assertEquals ("Can access cookie in the content", obj, l.lookup (obj.getClass ()));

        ic.remove (obj);
        listener.assertEvents ("One change in lookup", -1, 1);
        
        ic.add (obj);
        listener.assertEvents ("One change in lookup", -1, 1);

        assertEquals ("Can access cookie in the content", obj, l.lookup (obj.getClass ()));

        ic.remove (obj);
        listener.assertEvents ("One change in lookup", -1, 1);
    }
    
    private static void checkGetNodesDoesNotInitializeLookup (final org.openide.nodes.Node n, java.util.List queried) {
        assertEquals ("No queries before", Collections.EMPTY_LIST, queried);
        
        class MyCh extends Children.Keys {
            protected void addNotify () {
                setKeys (java.util.Collections.singleton(n));
            }
            
            public void clear () {
                setKeys (java.util.Collections.EMPTY_LIST);
            }
            
            protected Node[] createNodes (Object key) {
                return new Node[] { n };
            }
        };
        MyCh ch = new MyCh ();     
        
        // initialize the node N
        new AbstractNode (ch).getChildren().getNodes ();
        
        assertEquals ("No queries after", Collections.EMPTY_LIST, queried);
        ch.clear ();
        assertEquals ("No queries after clean either", Collections.EMPTY_LIST, queried);
        
    }
    
    //
    // Garbage collect
    //
    
    public void testAbstractNodeWithoutLookupHasCookieSet () {
        CookieNode n = new CookieNode ();
        try {
            n.cookieSet ();
        } catch (RuntimeException ex) {
            fail ("cannot obtain cookie set");
        }
    }
    
    public void testAbstractNodeWithLookupDoesNotHaveCookieSet () {
        CookieNode n = new CookieNode (Lookup.EMPTY);
        try {
            n.cookieSet ();
            fail ("It should not be possible to obtain cookieSet it should throw an exception");
        } catch (RuntimeException ex) {
        }
        try {
            n.setSet (null);
            fail ("It should not be possible to obtain setCookieSet it should throw an exception");
        } catch (RuntimeException ex) {
        }
    }
    
    
    public void testBackwardCompatibleAbstractNodeLookupCanBeGarbageCollected () {
        AbstractNode n = new AbstractNode (createChildren ());
        
        Lookup l = n.getLookup ();
        assertEquals ("Two invocations share the same lookup", l, n.getLookup ());
        
        java.lang.ref.WeakReference ref = new java.lang.ref.WeakReference (l);
        l = null;
        assertGC ("Lookup can be GCed", ref);
    }        

    public void testLazyCookieSet35856 () {
        CookieNode n = new CookieNode ();
        
        class CF implements CookieSet.Factory, org.openide.cookies.OpenCookie, org.openide.cookies.EditCookie, org.openide.cookies.ViewCookie {
            public int cnt;
            public Node.Cookie createCookie(Class klass) {
                cnt++;
                return this;
            }
                
            public void open () {}
            public void edit () {}
            public void view () {}
        }
        CF cf = new CF ();
        // init the node
        n.cookieSet ();
        
        Lookup lookup = n.getLookup ();
        Lookup.Item item;
        Listener l = new Listener ();
        Lookup.Result res = lookup.lookup (new Lookup.Template (Node.Cookie.class));
        assertEquals ("Empty", 0, res.allItems ().size ());
        res.addLookupListener(l);
        
        n.cookieSet ().add (org.openide.cookies.OpenCookie.class, cf);
        l.assertEvents ("Changes in lookup as we added Open", -1, 1);
        assertEquals ("One", 1, res.allItems ().size ());
        assertEquals ("Nothing created", 0, cf.cnt);
        
        n.cookieSet ().add (org.openide.cookies.ViewCookie.class, cf);
        item = n.getLookup ().lookupItem (new Lookup.Template (org.openide.nodes.Node.Cookie.class));
        assertEquals ("First is still OpenCookie", org.openide.cookies.OpenCookie.class, item.getType ());
        assertEquals ("Still one result as we do not listen on ViewCookie", 1, res.allItems ().size ());
        l.assertEvents ("Added View, but we are not listening to it", -1, 0);
        item = n.getLookup ().lookupItem (new Lookup.Template (org.openide.cookies.ViewCookie.class));
        l.assertEvents ("Now we listen and here is a change", -1, 1);
        assertEquals ("Included in result", 2, res.allItems ().size ());
        assertEquals ("Included as second", org.openide.cookies.ViewCookie.class, ((Lookup.Item)res.allItems ().toArray ()[1]).getType ());
        assertEquals ("First remain OpenCookie", org.openide.cookies.OpenCookie.class, ((Lookup.Item)res.allItems ().toArray ()[0]).getType ());
        assertEquals ("Still nothing created by factory", 0, cf.cnt);
        
        
        n.cookieSet ().add (org.openide.cookies.EditCookie.class, cf);
        l.assertEvents ("No change yet", -1, 0);
        assertNotNull ("This triggers the EditCookie listening and creates instance", n.getLookup ().lookup (org.openide.cookies.EditCookie.class));
        l.assertEvents ("Another change", -1, 1);
        assertEquals ("One entry created", 1, cf.cnt);
        assertEquals ("Included in result", 3, res.allItems ().size ());
        Lookup.Item[] arr = (Lookup.Item[])res.allItems ().toArray (new Lookup.Item[0]);
        assertEquals ("Included as second", org.openide.cookies.ViewCookie.class, (arr[1]).getType ());
        assertEquals ("First remain OpenCookie", org.openide.cookies.OpenCookie.class, (arr[0]).getType ());
        assertEquals ("Edit is last", org.openide.cookies.EditCookie.class, (arr[2]).getType ());
        
        n.cookieSet ().remove (org.openide.cookies.OpenCookie.class, cf);
        l.assertEvents ("This is a change for sure", -1, 1);
        assertEquals ("Just two there", 2, res.allItems ().size ());
        assertEquals ("View is first", org.openide.cookies.ViewCookie.class, ((Lookup.Item)res.allItems ().toArray ()[0]).getType ());
        assertEquals ("Edit is second", org.openide.cookies.EditCookie.class, ((Lookup.Item)res.allItems ().toArray ()[1]).getType ());
        
    }
    
    public void testItIsPossibleToWrapACookieSet () {
        final int[] cnt = { 0, 0 };
        CookieNode n = new CookieNode () {
            {
                class F implements CookieSet.Factory, org.openide.cookies.OpenCookie {
                    public Node.Cookie createCookie(Class klass) {
                        return this;
                    }

                    public void open () {
                        cnt[1]++;
                    }
                }
                getCookieSet ().add (org.openide.cookies.OpenCookie.class, new F ());
            }
            public Node.Cookie getCookie (Class c) {
                if (org.openide.cookies.OpenCookie.class == c) {
                    return new org.openide.cookies.OpenCookie () {
                        public void open () {
                            Object s = getCookieSet ().getCookie (org.openide.cookies.OpenCookie.class);
                            cnt[0]++;
                            ((org.openide.cookies.OpenCookie)s).open ();
                        }
                    };
                }
                return super.getCookie (c);
            }
        };
        
        Lookup.Item item = n.getLookup().lookupItem (new Lookup.Template (org.openide.cookies.OpenCookie.class));
        assertNotNull (item);
        assertEquals ("No factory", 0, cnt[1]);
        assertEquals ("No call", 0, cnt[0]);
        
        org.openide.cookies.OpenCookie oc = (org.openide.cookies.OpenCookie)item.getInstance ();
        assertEquals ("No factory", 0, cnt[1]);
        assertEquals ("No call", 0, cnt[0]);
        
        oc.open ();
        assertEquals ("Once factory", 1, cnt[1]);
        assertEquals ("Once call", 1, cnt[0]);
        
    }
    
    private static Children createChildren () {
        return Children.LEAF;
    }
    
    
    private static class Listener extends Object
    implements LookupListener, NodeListener {
        private int cookies;
        private int lookups;
        
        public void assertEvents (String txt, int cookies, int lookups) {
            
            if (cookies != -1) 
                assertEquals (txt + " cookies", cookies, this.cookies);
            if (lookups != -1) 
                assertEquals (txt + " lookups", lookups, this.lookups);
            
            this.cookies = 0;
            this.lookups = 0;
        }
        
        public void childrenAdded(NodeMemberEvent ev) {
        }
        
        public void childrenRemoved(NodeMemberEvent ev) {
        }
        
        public void childrenReordered(NodeReorderEvent ev) {
        }
        
        public void nodeDestroyed(NodeEvent ev) {
        }
        
        public void propertyChange(java.beans.PropertyChangeEvent evt) {
            if (Node.PROP_COOKIE == evt.getPropertyName()) {
                cookies++;
            }
        }
        
        public void resultChanged(org.openide.util.LookupEvent ev) {
            lookups++;
        }
        
    } // end of Listener
    
    private static class CookieNode extends AbstractNode {
        public ArrayList queries = new ArrayList ();
        
        public CookieNode () {
            super (createChildren ());
        }
        public CookieNode (Lookup l) {
            super (createChildren (), l);
        }
        
        public CookieSet cookieSet () {
            return getCookieSet ();
        }
        public void setSet (CookieSet s) {
            super.setCookieSet (s);
        }
        
        public Node.Cookie getCookie (Class c) {
            queries.add (c);
            return super.getCookie (c);
        }
        
    } // end of CookieNode
    
    private static class CookieNodeWithCookie extends CookieNode implements SaveCookie {
        public CookieNodeWithCookie () {
            cookieSet ().add (this);
        }
        
        public void save () {
        }
    }
    
    private static class CountableLookup extends AbstractLookup {
        public final InstanceContent ic;
        public final ArrayList queries;
        
        public CountableLookup () {
            this (new InstanceContent (), new ArrayList ());
        }
        
        private CountableLookup (InstanceContent ic, ArrayList queries) {
            super (ic);
            this.ic = ic;
            this.queries = queries;
        }
        
        protected void beforeLookup (Lookup.Template t) {
            super.beforeLookup (t);
            queries.add (t.getType ());
        }
    }
}

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