#173975: More consistency between AbstractLookup and ProxyLookup. Also it shall be enough to addLookupListener to be notified about changes now
1.1 --- a/openide.util/src/org/openide/util/lookup/ProxyLookup.java Thu Oct 22 12:10:55 2009 +0200
1.2 +++ b/openide.util/src/org/openide/util/lookup/ProxyLookup.java Fri Oct 30 11:01:37 2009 +0100
1.3 @@ -394,14 +394,12 @@
1.4 return weakL.getResults();
1.5 }
1.6
1.7 - for (int i = 0; i < arr.length; i++) {
1.8 - arr[i].addLookupListener(weakL);
1.9 - }
1.10 -
1.11 weakL.setResults(arr);
1.12 -
1.13 - return arr;
1.14 }
1.15 + for (int i = 0; i < arr.length; i++) {
1.16 + arr[i].addLookupListener(weakL);
1.17 + }
1.18 + return arr;
1.19 }
1.20 }
1.21
1.22 @@ -471,6 +469,7 @@
1.23 }
1.24
1.25 listeners.add(LookupListener.class, l);
1.26 + initResults();
1.27 }
1.28
1.29 /** Just delegates.
1.30 @@ -519,8 +518,9 @@
1.31
1.32 // if the call to beforeLookup resulted in deletion of caches
1.33 synchronized (proxy()) {
1.34 - if (getCache() != null) {
1.35 - Collection result = getCache()[indexToCache];
1.36 + Collection[] cc = getCache();
1.37 + if (cc != null && cc != NO_CACHE) {
1.38 + Collection result = cc[indexToCache];
1.39 if (result != null) {
1.40 return result;
1.41 }
1.42 @@ -561,15 +561,16 @@
1.43
1.44
1.45 synchronized (proxy()) {
1.46 - if (getCache() == null) {
1.47 + Collection[] cc = getCache();
1.48 + if (cc == null || cc == NO_CACHE) {
1.49 // initialize the cache to indicate this result is in use
1.50 - setCache(new Collection[3]);
1.51 + setCache(cc = new Collection[3]);
1.52 }
1.53
1.54 if (arr == weakL.getResults()) {
1.55 // updates the results, if the results have not been
1.56 // changed during the computation of allInstances
1.57 - getCache()[indexToCache] = ret;
1.58 + cc[indexToCache] = ret;
1.59 }
1.60 }
1.61
1.62 @@ -583,49 +584,58 @@
1.63 }
1.64
1.65 protected void collectFires(Collection<Object> evAndListeners) {
1.66 - // clear cached instances
1.67 - Collection oldItems;
1.68 - Collection oldInstances;
1.69 - synchronized (proxy()) {
1.70 - if (getCache() == null) {
1.71 - // nobody queried the result yet
1.72 - return;
1.73 - }
1.74 - oldInstances = getCache()[0];
1.75 - oldItems = getCache()[2];
1.76 -
1.77 -
1.78 - if (listeners == null || listeners.getListenerCount() == 0) {
1.79 - // clear the cache
1.80 - setCache(new Collection[3]);
1.81 - return;
1.82 - }
1.83 -
1.84 - // ignore events if they arrive as a result of call to allItems
1.85 - // or allInstances, bellow...
1.86 - setCache(null);
1.87 - }
1.88 -
1.89 boolean modified = true;
1.90
1.91 - if (oldItems != null) {
1.92 - Collection newItems = allItems();
1.93 - if (oldItems.equals(newItems)) {
1.94 - modified = false;
1.95 + try {
1.96 + // clear cached instances
1.97 + Collection oldItems;
1.98 + Collection oldInstances;
1.99 + synchronized (proxy()) {
1.100 + final Collection[] cc = getCache();
1.101 + if (cc == NO_CACHE) {
1.102 + return;
1.103 + }
1.104 +
1.105 + oldInstances = cc == null ? null : cc[0];
1.106 + oldItems = cc == null ? null : cc[2];
1.107 +
1.108 +
1.109 + if (listeners == null || listeners.getListenerCount() == 0) {
1.110 + // clear the cache
1.111 + setCache(new Collection[3]);
1.112 + return;
1.113 + }
1.114 +
1.115 + // ignore events if they arrive as a result of call to allItems
1.116 + // or allInstances, bellow...
1.117 + setCache(NO_CACHE);
1.118 }
1.119 - } else {
1.120 - if (oldInstances != null) {
1.121 - Collection newInstances = allInstances();
1.122 - if (oldInstances.equals(newInstances)) {
1.123 +
1.124 + if (oldItems != null) {
1.125 + Collection newItems = allItems();
1.126 + if (oldItems.equals(newItems)) {
1.127 modified = false;
1.128 }
1.129 } else {
1.130 - synchronized (proxy()) {
1.131 - if (getCache() == null) {
1.132 - // we have to initialize the cache
1.133 - // to show that the result has been initialized
1.134 - setCache(new Collection[3]);
1.135 + if (oldInstances != null) {
1.136 + Collection newInstances = allInstances();
1.137 + if (oldInstances.equals(newInstances)) {
1.138 + modified = false;
1.139 }
1.140 + } else {
1.141 + synchronized (proxy()) {
1.142 + if (getCache() == NO_CACHE) {
1.143 + // we have to initialize the cache
1.144 + // to show that the result has been initialized
1.145 + setCache(new Collection[3]);
1.146 + }
1.147 + }
1.148 + }
1.149 + }
1.150 + } finally {
1.151 + synchronized (proxy()) {
1.152 + if (getCache() == NO_CACHE) {
1.153 + setCache(null);
1.154 }
1.155 }
1.156 }
1.157 @@ -673,6 +683,7 @@
1.158 assert Thread.holdsLock(proxy());
1.159 this.cache = cache;
1.160 }
1.161 + private static final Collection[] NO_CACHE = new Collection[0];
1.162 }
1.163 private static final class WeakRef<T> extends WeakReference<R> implements Runnable {
1.164 final WeakResult<T> result;
2.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupBaseHid.java Thu Oct 22 12:10:55 2009 +0200
2.2 +++ b/openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupBaseHid.java Fri Oct 30 11:01:37 2009 +0100
2.3 @@ -1386,12 +1386,12 @@
2.4 public void testChangeOfNodeDoesNotFireChangeInActionMap() {
2.5 ActionMap am = new ActionMap();
2.6 Lookup s = Lookups.singleton(am);
2.7 - doChangeOfNodeDoesNotFireChangeInActionMap(am, s, false);
2.8 + doChangeOfNodeDoesNotFireChangeInActionMap(am, s, false, 0);
2.9 }
2.10 public void testChangeOfNodeDoesNotFireChangeInActionMapSimple() {
2.11 ActionMap am = new ActionMap();
2.12 Lookup s = Lookups.singleton(am);
2.13 - doChangeOfNodeDoesNotFireChangeInActionMap(am, s, true);
2.14 + doChangeOfNodeDoesNotFireChangeInActionMap(am, s, true, 0);
2.15 }
2.16
2.17 public void testChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookupSimple() {
2.18 @@ -1424,12 +1424,12 @@
2.19 }
2.20
2.21 Before s = new Before();
2.22 - doChangeOfNodeDoesNotFireChangeInActionMap(am, s, wrapBySimple);
2.23 + doChangeOfNodeDoesNotFireChangeInActionMap(am, s, wrapBySimple, 1);
2.24
2.25 assertNull("beforeLookup called once", s.ic);
2.26 }
2.27
2.28 - private void doChangeOfNodeDoesNotFireChangeInActionMap(final ActionMap am, Lookup actionMapLookup, final boolean wrapBySimple) {
2.29 + private void doChangeOfNodeDoesNotFireChangeInActionMap(final ActionMap am, Lookup actionMapLookup, final boolean wrapBySimple, int firstChange) {
2.30 Lookup[] lookups = { lookup, actionMapLookup };
2.31
2.32 class Provider implements Lookup.Provider {
2.33 @@ -1470,7 +1470,7 @@
2.34 ActionMap am1 = (ActionMap)c.iterator().next();
2.35 assertEquals("Am is there", am, am1);
2.36
2.37 - assertEquals("No change in first get", 0, ll.getCount());
2.38 + assertEquals("Correct # of changes in first get", firstChange, ll.getCount());
2.39
2.40 Object m1 = new InputMap();
2.41 Object m2 = new InputMap();
3.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupTest.java Thu Oct 22 12:10:55 2009 +0200
3.2 +++ b/openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupTest.java Fri Oct 30 11:01:37 2009 +0100
3.3 @@ -47,6 +47,7 @@
3.4 import java.util.*;
3.5 import java.util.concurrent.Executors;
3.6 import java.util.concurrent.TimeUnit;
3.7 +import junit.framework.Test;
3.8 import org.netbeans.junit.*;
3.9 import org.openide.util.Lookup;
3.10 import org.openide.util.lookup.AbstractLookup.Pair;
3.11 @@ -78,11 +79,7 @@
3.12
3.13 public void clearCaches () {
3.14 }
3.15 -
3.16 - public static void main(java.lang.String[] args) {
3.17 - junit.textui.TestRunner.run(new NbTestSuite(AbstractLookupTest.class));
3.18 - }
3.19 -
3.20 +
3.21 static class LkpResultCanBeGargageCollectedAndClearsTheResult extends AbstractLookup {
3.22 public int cleared;
3.23 public int dirty;
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/openide.util/test/unit/src/org/openide/util/lookup/ProxyLookup173975Test.java Fri Oct 30 11:01:37 2009 +0100
4.3 @@ -0,0 +1,108 @@
4.4 +/*
4.5 + * To change this template, choose Tools | Templates
4.6 + * and open the template in the editor.
4.7 + */
4.8 +package org.openide.util.lookup;
4.9 +
4.10 +import java.util.Collection;
4.11 +import java.util.Collections;
4.12 +import org.junit.Assert;
4.13 +import org.junit.Test;
4.14 +import org.openide.util.Lookup;
4.15 +import org.openide.util.LookupEvent;
4.16 +import org.openide.util.LookupListener;
4.17 +import org.openide.util.lookup.AbstractLookup.Storage;
4.18 +
4.19 +public class ProxyLookup173975Test {
4.20 +
4.21 + public ProxyLookup173975Test() {
4.22 + }
4.23 +
4.24 + boolean called = false;
4.25 +
4.26 + @Test
4.27 + public void testAbstractLookupWithoutAllInstances() {
4.28 + registerLookupListenerAndAddSomething(false, false, false);
4.29 + }
4.30 +
4.31 + @Test
4.32 + public void testAbstractLookupWithAllInstances() {
4.33 + registerLookupListenerAndAddSomething(false, true, false);
4.34 + }
4.35 +
4.36 + @Test
4.37 + public void testAbstractLookupInheritanceTreeWithoutAllInstances() {
4.38 + registerLookupListenerAndAddSomething(false, false, true);
4.39 + }
4.40 +
4.41 + @Test
4.42 + public void testAbstractLookupInheritanceTreeWithAllInstances() {
4.43 + registerLookupListenerAndAddSomething(false, true, true);
4.44 + }
4.45 +
4.46 + @Test
4.47 + public void testProxyLookupWithoutAllInstances() {
4.48 + registerLookupListenerAndAddSomething(true, false, false);
4.49 + }
4.50 +
4.51 + @Test
4.52 + public void testProxyLookupWithAllInstances() {
4.53 + registerLookupListenerAndAddSomething(true, true, false);
4.54 + }
4.55 +
4.56 + @Test
4.57 + public void testProxyLookupInheritanceTreeWithoutAllInstances() {
4.58 + registerLookupListenerAndAddSomething(true, false, true);
4.59 + }
4.60 +
4.61 + @Test
4.62 + public void testProxyLookupInheritanceTreeWithAllInstances() {
4.63 + registerLookupListenerAndAddSomething(true, true, true);
4.64 + }
4.65 +
4.66 + private void registerLookupListenerAndAddSomething(boolean useProxy, boolean callAllInstances, boolean inheritanceTree) {
4.67 + called = false;
4.68 + InstanceContent aInstanceContent = new InstanceContent();
4.69 + Storage<?> s = inheritanceTree ? new InheritanceTree() : new ArrayStorage();
4.70 + Lookup aLookup = new AbstractLookup(aInstanceContent, s);
4.71 + if (useProxy) {
4.72 + aLookup = new ProxyLookup(aLookup);
4.73 + }
4.74 + Lookup.Result<ObjectInLookup> result = aLookup.lookupResult(ObjectInLookup.class);
4.75 + if (callAllInstances) {
4.76 + result.allInstances(); // TO GET SUCCESS
4.77 + }
4.78 + result.addLookupListener(new LookupListener() {
4.79 +
4.80 + public void resultChanged(LookupEvent ev) {
4.81 + Lookup.Result aResult = (Lookup.Result) ev.getSource();
4.82 + Collection c = aResult.allInstances();
4.83 + if (!c.isEmpty()) {
4.84 + called = true;
4.85 + }
4.86 + }
4.87 + });
4.88 +
4.89 + aInstanceContent.set(Collections.singleton(
4.90 + new ObjectInLookup("Set Object in Lookup)")), null);
4.91 + Assert.assertTrue("Listener was notified", called);
4.92 + }
4.93 +
4.94 + public class ObjectInLookup {
4.95 +
4.96 + private final String name;
4.97 +
4.98 + public ObjectInLookup(String name) {
4.99 + this.name = name;
4.100 + }
4.101 +
4.102 + public String getName() {
4.103 + return this.name;
4.104 + }
4.105 +
4.106 + @Override
4.107 + public String toString() {
4.108 + return "objectinlookup:" + getName();
4.109 + }
4.110 + }
4.111 +}