This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 153347
Collapse All | Expand All

(-)a/openide.nodes/apichanges.xml (+24 lines)
Lines 46-51 Link Here
46
<apidef name="nodes">Nodes API</apidef>
46
<apidef name="nodes">Nodes API</apidef>
47
</apidefs>
47
</apidefs>
48
<changes>
48
<changes>
49
    <change id="ChildFactory.Detachable">
50
        <api name="nodes"/>
51
        <summary>Adding public int Children.getNodesCount(boolean optimalResult), protected Children.Keys(boolean lazy),
52
        Children.snapshot(), NodeMemberEvent.getSnapshot(), NodeReorderEvent.getSnapshot()</summary>
53
        <version major="7" minor="7"/>
54
        <date day="17" month="11" year="2008"/>
55
        <author login="tboudreau"/>
56
        <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible"/>
57
        <description>
58
            <a href="@TOP@/org/openide/nodes/ChildFactory.html">ChildFactory</a>
59
            is useful for creating node children lazily on a background thread,
60
            and for simplifying working with Children.Keys.  One oversight in
61
            the original API was providing for notification that the ChildFactory
62
            is no longer in use and should clean up any resources and detach
63
            any listeners it can.
64
            <p>
65
            ChildFactory.Detachable is an abstract class which adds
66
            addNotify() and removeNotify() methods to ChildFactory.  addNotify()
67
            is called immediately before the first call to createKeys() after
68
            creation or a call to removeNotify().
69
        </description>
70
        <class package="org.openide.nodes" name="ChildFactory"/>
71
        <issue number="153347"/>
72
    </change>
49
    <change id="Children.Keys.lazy">
73
    <change id="Children.Keys.lazy">
50
        <api name="nodes"/>
74
        <api name="nodes"/>
51
        <summary>Adding public int Children.getNodesCount(boolean optimalResult), protected Children.Keys(boolean lazy),
75
        <summary>Adding public int Children.getNodesCount(boolean optimalResult), protected Children.Keys(boolean lazy),
(-)a/openide.nodes/src/org/openide/nodes/AsynchChildren.java (-4 / +16 lines)
Lines 85-94 Link Here
85
    }
85
    }
86
    
86
    
87
    protected @Override void removeNotify() {
87
    protected @Override void removeNotify() {
88
        cancelled = true;
88
        try {
89
        task.cancel();
89
            cancelled = true;
90
        initialized = false;
90
            task.cancel();
91
        setKeys (Collections.<Object>emptyList());
91
            initialized = false;
92
            setKeys (Collections.<Object>emptyList());
93
            factory.removeNotify();
94
        } finally {
95
            if (notified) {
96
                factory.removeNotify();
97
            }
98
        }
92
    }
99
    }
93
    
100
    
94
    /**
101
    /**
Lines 136-141 Link Here
136
    }
143
    }
137
144
138
    volatile boolean cancelled = false;
145
    volatile boolean cancelled = false;
146
    volatile boolean notified;
139
    public void run() {
147
    public void run() {
140
        if (Thread.interrupted()) {
148
        if (Thread.interrupted()) {
141
            setKeys (Collections.<T>emptyList());
149
            setKeys (Collections.<T>emptyList());
Lines 144-149 Link Here
144
        List <T> keys = new LinkedList <T> ();
152
        List <T> keys = new LinkedList <T> ();
145
        boolean done;
153
        boolean done;
146
        do {
154
        do {
155
            if (!notified) {
156
                notified = true;
157
                factory.addNotify();
158
            }
147
            done = factory.createKeys (keys);
159
            done = factory.createKeys (keys);
148
            if (cancelled || Thread.interrupted()) {
160
            if (cancelled || Thread.interrupted()) {
149
                setKeys (Collections.<T>emptyList());
161
                setKeys (Collections.<T>emptyList());
(-)a/openide.nodes/src/org/openide/nodes/ChildFactory.java (+36 lines)
Lines 198-203 Link Here
198
        }
198
        }
199
        this.observer = new WeakReference <Observer> (observer);
199
        this.observer = new WeakReference <Observer> (observer);
200
    }
200
    }
201
202
    void removeNotify() {
203
        //do nothing
204
    }
205
206
    void addNotify() {
207
        //do nothing
208
    }
201
    
209
    
202
    interface Observer {
210
    interface Observer {
203
        public void refresh(boolean immediate);
211
        public void refresh(boolean immediate);
Lines 217-220 Link Here
217
            super(orig);
225
            super(orig);
218
        }
226
        }
219
    }
227
    }
228
229
    /**
230
     * Subclass of ChildFactory with lifecycle methods which will be called
231
     * on first use and last use.
232
     *
233
     * @param <T> The key type for this child factory
234
     */
235
    public static abstract class Detachable<T> extends ChildFactory<T>{
236
        /**
237
         * Called immediately before the first call to createKeys().  Override
238
         * to set up listening for changes, allocating expensive-to-create
239
         * resources, etc.
240
         */
241
        @Override
242
        protected void addNotify() {
243
            //do nothing
244
        }
245
        /**
246
         * Called when this child factory is no longer in use, to dispose of
247
         * resources, detach listeners, etc.  Does nothing by default;  override
248
         * if you need notification when not in use anymore.
249
         */
250
        @Override
251
        protected void removeNotify() {
252
            //do nothing
253
        }
254
255
    }
220
}
256
}
(-)a/openide.nodes/src/org/openide/nodes/SynchChildren.java (+2 lines)
Lines 64-75 Link Here
64
    volatile boolean active = false;
64
    volatile boolean active = false;
65
    protected @Override void addNotify() {
65
    protected @Override void addNotify() {
66
        active = true;
66
        active = true;
67
        factory.addNotify();
67
        refresh(true);
68
        refresh(true);
68
    }
69
    }
69
    
70
    
70
    protected @Override void removeNotify() {
71
    protected @Override void removeNotify() {
71
        active = false;
72
        active = false;
72
        setKeys(Collections.<T>emptyList());
73
        setKeys(Collections.<T>emptyList());
74
        factory.removeNotify();
73
    }
75
    }
74
    
76
    
75
    protected Node[] createNodes(T key) {
77
    protected Node[] createNodes(T key) {
(-)a/openide.nodes/test/unit/src/org/openide/nodes/ChildFactoryTest.java (-3 / +80 lines)
Lines 44-51 Link Here
44
import java.beans.*;
44
import java.beans.*;
45
import java.util.*;
45
import java.util.*;
46
import junit.framework.TestCase;
46
import junit.framework.TestCase;
47
import org.openide.nodes.*;
47
import org.openide.nodes.ChildFactory.Detachable;
48
import org.openide.nodes.NodeAdapter;
49
import org.openide.util.NbBundle;
48
import org.openide.util.NbBundle;
50
49
51
/** Test for AsynchChildren, ChildFactory and SynchChildren.
50
/** Test for AsynchChildren, ChildFactory and SynchChildren.
Lines 214-220 Link Here
214
        assertTrue(kids.cancelled);
213
        assertTrue(kids.cancelled);
215
        assertTrue(factory.cancelled);
214
        assertTrue(factory.cancelled);
216
    }
215
    }
217
    
216
217
    public void testAddRemoveNotifySynch() throws Exception {
218
        DetachableImpl r = new DetachableImpl();
219
        Children ch = Children.create(r, false);
220
        new AbstractNode (ch);
221
        ch.addNotify();
222
        r.assertAdded();
223
        Node[] n = ch.getNodes(true);
224
        assertEquals (2, n.length);
225
        assertEquals ("foo", n[0].getDisplayName());
226
        assertEquals ("bar", n[1].getDisplayName());
227
        ch.removeNotify();
228
        r.assertRemoved();
229
    }
230
231
    public void testAddRemoveNotifyAsynch() throws Exception {
232
        DetachableImpl r = new DetachableImpl();
233
        Children ch = Children.create(r, true);
234
        new AbstractNode (ch);
235
        ch.addNotify();
236
        synchronized(r) {
237
            r.wait(1000);
238
        }
239
        r.assertAdded();
240
        Node[] n = ch.getNodes(true);
241
        assertEquals (2, n.length);
242
        assertEquals ("foo", n[0].getDisplayName());
243
        assertEquals ("bar", n[1].getDisplayName());
244
        ch.removeNotify();
245
        synchronized(r) {
246
            r.wait(1000);
247
        }
248
        r.assertRemoved();
249
    }
250
251
218
    static final class ProviderImpl extends ChildFactory <String> {
252
    static final class ProviderImpl extends ChildFactory <String> {
219
        Object lock = new Object();
253
        Object lock = new Object();
220
        volatile boolean wait = false;
254
        volatile boolean wait = false;
Lines 421-424 Link Here
421
            refresh(true);
455
            refresh(true);
422
        }
456
        }
423
    }
457
    }
458
459
    private static final class DetachableImpl extends Detachable<String> {
460
        boolean removed;
461
        boolean added;
462
463
        @Override
464
        protected boolean createKeys(List<String> toPopulate) {
465
            toPopulate.add("foo");
466
            toPopulate.add("bar");
467
            synchronized(this) {
468
                notifyAll();
469
            }
470
            return true;
471
        }
472
473
        @Override
474
        protected void removeNotify() {
475
            synchronized(this) {
476
                notifyAll();
477
            }
478
            removed = true;
479
        }
480
481
        @Override
482
        protected Node createNodeForKey(String key) {
483
            AbstractNode nd = new AbstractNode(Children.LEAF);
484
            nd.setDisplayName(key);
485
            return nd;
486
        }
487
488
        @Override
489
        protected void addNotify() {
490
            added = true;
491
        }
492
493
        void assertAdded() {
494
            assertTrue (added);
495
        }
496
497
        void assertRemoved() {
498
            assertTrue (removed);
499
        }
500
    }
424
}
501
}

Return to bug 153347