Index: src/org/openide/nodes/FilterNode.java =================================================================== RCS file: /cvs/openide/src/org/openide/nodes/FilterNode.java,v --- src/org/openide/nodes/FilterNode.java 26 May 2004 13:46:20 -0000 1.91 +++ src/org/openide/nodes/FilterNode.java 2 Jul 2004 23:42:27 -0000 @@ -708,6 +708,27 @@ return original.getCookie (type); } + /** This method is called from NodeLookup and if it is then + * this means somebody overriden the getCookie method. + */ + void lookupCookieItems (Class clazz, Set/*Lookup.Item*/ toAdd) { + if (Node.Cookie.class.isAssignableFrom (clazz)) { + Object c = getCookie (clazz); + if (c != null) { + toAdd.add (new NodeLookup.LookupItem (c)); + } + } else { + Lookup.Result res = getOriginal ().getLookup ().lookup (new Lookup.Template (clazz)); + java.util.Iterator it = res.allItems ().iterator (); + while (it.hasNext ()) { + Lookup.Item item = (Lookup.Item)it.next (); + if (!Node.class.isAssignableFrom (item.getType ())) { + toAdd.add (new NodeLookup.DelegatePair (item)); + } + } + } + } + /** If this is FilterNode without any changes (subclassed, changed children) * and the original provides handle, stores them and * returns a new handle for the proxy. Index: src/org/openide/nodes/Node.java =================================================================== RCS file: /cvs/openide/src/org/openide/nodes/Node.java,v --- src/org/openide/nodes/Node.java 4 Jun 2004 18:39:40 -0000 1.85 +++ src/org/openide/nodes/Node.java 2 Jul 2004 23:42:28 -0000 @@ -628,6 +628,27 @@ return null; } + /** Lookups items from lookup. Use only from NodeLookup!!!! + * Is reimplemented in FilterNode + * @param toAdd adds all items that satisfy that template + */ + void lookupCookieItems (Class c, Set/*Lookup.Item*/ toAdd) { + Lookup l = internalLookup (true); + if (l != null && ! (l instanceof NodeLookup)) { + java.util.Iterator it = getLookup ().lookup ( + new org.openide.util.Lookup.Template (c) + ).allItems ().iterator (); + while (it.hasNext ()) { + toAdd.add (it.next ()); + } + } else { + Object o = getCookie (c); + if (o != null) { + toAdd.add (new NodeLookup.LookupItem (o)); + } + } + } + /** Obtains a Lookup represeting additional content of this Node. * If the lookup was provided in a constructor, it is returned here, * if not, a lookup based on the content of getCookie @@ -1417,7 +1438,7 @@ /** template for changes in cookies */ - private static final Lookup.Template TEMPL_COOKIE = new Lookup.Template (Node.Cookie.class); + static final Lookup.Template TEMPL_COOKIE = new Lookup.Template (Object.class); /** Lock for initialication */ private static final Object INIT_LOCK = new Object(); Index: src/org/openide/nodes/NodeLookup.java =================================================================== RCS file: /cvs/openide/src/org/openide/nodes/NodeLookup.java,v --- src/org/openide/nodes/NodeLookup.java 22 Mar 2004 09:45:34 -0000 1.8 +++ src/org/openide/nodes/NodeLookup.java 2 Jul 2004 23:42:28 -0000 @@ -54,23 +54,24 @@ * @param colleciton to put Pair into if found */ private static void addCookie (Node node, Class c, Collection collection) { - Object res; + java.util.HashSet toAdd = new java.util.HashSet (); AbstractLookup.Pair pair; Object prev = CookieSet.entryQueryMode (c); try { - res = node.getCookie (c); + node.lookupCookieItems (c, toAdd); } finally { pair = CookieSet.exitQueryMode (prev); } - if (pair == null) { - if (res == null) { - return; - } - pair = new LookupItem (res); + if (pair != null) { + toAdd.clear (); + toAdd.add (pair); } - collection.add (pair); + java.util.Iterator it = toAdd.iterator (); + while (it.hasNext ()) { + collection.add (it.next ()); + } } @@ -78,18 +79,27 @@ * @param template the template */ protected final void beforeLookup (Template template) { - Class type = template.getType (); + if (NO_COOKIE_CHANGE.get () == this) { + // no beforeLookup mangling we just want all the pairs see X1 + return; + } - if (type == Object.class) { + Class origType = template.getType (); + + Class type; + if (origType == Object.class) { type = Node.Cookie.class; + } else { + type = origType; } if (Node.Cookie.class.isAssignableFrom (type)) { - if (!queriedCookieClasses.contains (type)) { - synchronized (this) { - queriedCookieClasses.add (type); - } - + boolean queriedCookieClassesChanged; + synchronized (this) { + queriedCookieClassesChanged = this.queriedCookieClasses.add (type); + } + + if (queriedCookieClassesChanged) { Object prev = NO_COOKIE_CHANGE.get (); try { NO_COOKIE_CHANGE.set (node); @@ -98,6 +108,31 @@ NO_COOKIE_CHANGE.set (prev); } } + + if (type == origType) { + // e.g. we really searched for cookie, + return; // and do not do the special treatment of FilterNode + // as the cookie was either found or not and in such + // case it is not supposed to be found + } + } + + if (node instanceof FilterNode && !Node.Cookie.class.isAssignableFrom (origType)) { + // still ask + boolean queriedCookieClassesChanged; + synchronized (this) { + queriedCookieClassesChanged = this.queriedCookieClasses.add (type); + } + + if (queriedCookieClassesChanged) { + Object prev = NO_COOKIE_CHANGE.get (); + try { + NO_COOKIE_CHANGE.set (node); + addCookie (node, origType, this); + } finally { + NO_COOKIE_CHANGE.set (prev); + } + } } } /** See #40734 and NodeLookupTest and CookieActionIsTooSlowTest. @@ -113,10 +148,30 @@ // if it is cookie change, do the rescan, try to keep order synchronized (this) { java.util.HashSet toQuery = new java.util.HashSet (queriedCookieClasses); - Iterator it = lookup (new Template (Node.Cookie.class)).allItems ().iterator (); + Iterator it; + Object prev = NO_COOKIE_CHANGE.get (); + try { + NO_COOKIE_CHANGE.set (this); + it = lookup (Node.TEMPL_COOKIE).allItems ().iterator (); + } finally { + NO_COOKIE_CHANGE.set (prev); + } instances.add (new LookupItem (node)); while (it.hasNext()) { Item item = (Item)it.next (); + + if (item instanceof DelegatePair) { + // we are filter node then + org.openide.util.Lookup del = ((FilterNode)node).getOriginal ().getLookup (); + org.openide.util.Lookup.Item found = del.lookupItem (new org.openide.util.Lookup.Template ( + item.getType (), item.getId (), item.getInstance () + )); + if (found != null) { + instances.add (new DelegatePair (found)); + } + continue; + } + Class c = item.getType (); toQuery.remove (c); addCookie (node, c, instances); @@ -190,7 +245,7 @@ } /** Simple Pair to hold cookies and nodes */ - private static class LookupItem extends AbstractLookup.Pair { + static class LookupItem extends AbstractLookup.Pair { private Object instance; public LookupItem( Object instance ) { @@ -232,5 +287,49 @@ return c.isInstance (instance); } } // End of LookupItem class + + /** Simple Pair that delegates to another pair */ + static class DelegatePair extends AbstractLookup.Pair { + private org.openide.util.Lookup.Item item; + + public DelegatePair ( org.openide.util.Lookup.Item item) { + this.item = item; + } + + public String getDisplayName() { + return item.getDisplayName (); + } + + public String getId () { + return item.getId (); + } + + public Object getInstance() { + return item.getInstance (); + } + + public Class getType() { + return item.getType (); + } + + public boolean equals( Object object ) { + if ( object instanceof DelegatePair ) { + return item.equals (((DelegatePair)object).item); + } + return false; + } + + public int hashCode() { + return item.hashCode() + 777; + } + + protected boolean creatorOf(Object obj) { + return obj == getInstance (); + } + + protected boolean instanceOf(Class c) { + return c.isAssignableFrom (getType ()); + } + } // End of DelegatePair class } Index: test/unit/src/org/openide/nodes/NodeLookupTest.java =================================================================== RCS file: /cvs/openide/test/unit/src/org/openide/nodes/NodeLookupTest.java,v --- test/unit/src/org/openide/nodes/NodeLookupTest.java 22 Mar 2004 09:45:35 -0000 1.17 +++ test/unit/src/org/openide/nodes/NodeLookupTest.java 2 Jul 2004 23:42:28 -0000 @@ -60,6 +60,7 @@ public void testChangesAreFiredFromLookupThruFilterNodeWithOverWrittenGetCookie () { final Node.Cookie myInstance = new Node.Cookie () { }; + final Node.Cookie notMyInstance = new Node.Cookie () { }; final ArrayList queries = new ArrayList (); InstanceContent ic = new InstanceContent (); @@ -68,6 +69,10 @@ public Node.Cookie getCookie (Class clazz) { queries.add (clazz); + if (clazz == notMyInstance.getClass ()) { + return null; + } + if (clazz == myInstance.getClass ()) { return myInstance; } @@ -78,9 +83,10 @@ 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); + checkInstanceInGetLookup (notMyInstance, ic, node, false); + // by overwriting the FilterNode.getCookie we say the lookup + // to provide all non-cookie content from its delegate + checkInstanceInGetLookup ("Some string", ic, node, true); 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 ()));