KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jdesktop > dataset > provider > LoadTask


1 /*
2  * $Id: LoadTask.java,v 1.2 2005/02/28 18:28:01 rbair Exp $
3  *
4  * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
5  * Santa Clara, California 95054, U.S.A. All rights reserved.
6  */

7
8 package org.jdesktop.dataset.provider;
9
10 import java.util.LinkedList JavaDoc;
11 import javax.swing.Icon JavaDoc;
12 import javax.swing.SwingUtilities JavaDoc;
13 import org.jdesktop.dataset.DataTable;
14
15
16 /**
17  *
18  * @author rbair
19  */

20 public abstract class LoadTask extends AbstractTask {
21     /**
22      * This linked list contains "LoadItem" objects. As a specific unit of data
23      * is loaded (for instance, all of the data needed for a specific
24      * DataTable), a new LoadItem is created and placed at the tail of the
25      * loadQueue. The scheduleLoad method then executes and the current items in
26      * the queue are removed and passed to the loadData method. This queue is
27      * accessed from multiple threads (many threads put data into the queue, one
28      * thread removes items from the queue). Synchronization occurs on the
29      * loadQueue.
30      */

31     private LinkedList JavaDoc loadQueue = new LinkedList JavaDoc();
32
33     /**
34      * Object used for collescing multiple calls to scheduleLoad into one call
35      * to loadData.
36      */

37     private LoadNotifier loadNotifier = new LoadNotifier();
38
39     /**
40      * The DataTables that are being loaded.
41      */

42     private DataTable[] tables;
43
44     /**
45      * Creates a new LoadTask. The param is the array of DataTables to be
46      * loaded on this thread
47      */

48     public LoadTask(DataTable[] tables) {
49         this.tables = tables == null ? new DataTable[0] : tables;
50     }
51
52     /**
53      * @inheritDoc
54      */

55     public void run() {
56         setIndeterminate(true);
57         try {
58             //TODO If meta-data of any kind needs to be loaded, this is the place to do it
59
readData(tables);
60             scheduleLoad();
61             setProgress(getMaximum());
62         } catch (Exception JavaDoc e) {
63             final Throwable JavaDoc error = e;
64             e.printStackTrace();
65             setProgress(getMaximum());
66         }
67     }
68
69     /**
70      * Subclasses must implement this
71      * method to read the data from the data store and place it in a data
72      * structure which is <b>disconnected </b> from the DataTable. When
73      * increments of data are ready to be loaded into the model, this method
74      * should invoke <code>scheduleLoad</code>, which will cause
75      * <code>loadData</code> to be called on the event dispatch thread, where
76      * the model may be safely updated. Progress events may be fired from this
77      * method.
78      * <p>
79      * A final <code>scheduleLoad</code> will be called automatically at the
80      * conclusion of the loading process, so it is not technically necessary
81      * for this method to call <code>scheduleLoad</code> at all unless you
82      * want to support partial loads.
83      *
84      * @see #scheduleLoad
85      * @throws Exception
86      * if errors occur while reading data
87      */

88     protected abstract void readData(final DataTable[] tables) throws Exception JavaDoc;
89
90     /**
91      * Invoked internally once the <code>readData</code> method calls
92      * <code>scheduleLoad</code> to schedule the loading of an increment of
93      * data to the DataTable. This method is called on the event dispatch thread,
94      * therefore it is safe to mutate the model from this method. Subclasses
95      * must implement this method to load the current contents of the
96      * disconnected data structure into the DataTable. Note that because there
97      * is an unpredictable delay between the time <code>scheduleLoad</code> is
98      * called from the &quot;reader&quot; thread and <code>loadData</code>
99      * executes on the event dispatch thread, there may be more data available
100      * for loading than was available when <code>scheduleLoad</code> was
101      * invoked. All available data should be loaded from this method.
102      * <p>
103      * This method should fire an appropriate progress event to notify progress
104      * listeners when:
105      * <ul>
106      * <li>incremental load occurs(for determinate load operations)</li>
107      * <li>load completes</li>
108      * <li>exception occurs</li>
109      * </ul>
110      * </p>
111      *
112      * @see #fireProgressStarted(int, int)
113      * @see #fireProgressEnded()
114      * @see #fireException
115      */

116     protected abstract void loadData(LoadItem[] items);
117
118     /**
119      * Invoked by the <code>readData</code> method from the &quot;reader&quot;
120      * thread to schedule a subsequent call to <code>loadData</code> on the
121      * event dispatch thread. If <code>readData</code> invokes
122      * <code>scheduleLoad</code> multiple times before <code>loadData</code>
123      * has the opportunity to execute on the event dispatch thread, those
124      * requests will be collapsed, resulting in only a single call to
125      * <code>loadData</code>.
126      *
127      * @see #readData
128      * @see #loadData
129      */

130     protected void scheduleLoad(LoadItem item) {
131         synchronized (loadQueue) {
132             if (item != null) {
133                 loadQueue.addLast(item);
134             }
135             if (!loadNotifier.isPending()) {
136                 loadNotifier.setPending(true);
137                 SwingUtilities.invokeLater(loadNotifier);
138             }
139         }
140     }
141
142     /**
143      * Same as <code>scheduleLoad(LoadItem)</code>, except that this method
144      * will simply schedule a load operation for any remaining items in the
145      * queue, but will not add any items to the queue.
146      */

147     protected void scheduleLoad() {
148         scheduleLoad(null);
149     }
150
151     /**
152      * @inheritDoc
153      */

154     public String JavaDoc getDescription() {
155         return "<html><h3>Loading data</h3></html>";
156     }
157
158     /**
159      * @inheritDoc
160      */

161     public Icon JavaDoc getIcon() {
162         return null;
163     }
164
165     /**
166      * @inheritDoc
167      */

168     public String JavaDoc getMessage() {
169         return "Loading item " + (getProgress() + 1) + " of " + getMaximum();
170     }
171
172     /**
173      * @inheritDoc
174      */

175     public boolean cancel() throws Exception JavaDoc {
176         return false;
177     }
178
179     /**
180      * Represents a Unit of data, ready to be loaded.
181      */

182     public static final class LoadItem<E> {
183         public DataTable table;
184
185         public E data;
186
187         public LoadItem(DataTable table, E data) {
188             this.table = table;
189             this.data = data;
190         }
191     }
192
193     /**
194      *
195      */

196     private class LoadNotifier implements Runnable JavaDoc {
197         private boolean pending = false;
198
199         LoadNotifier() {
200         }
201
202         public synchronized void setPending(boolean pending) {
203             this.pending = pending;
204         }
205
206         public synchronized boolean isPending() {
207             return pending;
208         }
209
210         public void run() {
211             synchronized (loadQueue) {
212                 if (loadQueue.size() > 0) {
213                     LoadItem[] items = (LoadItem[]) loadQueue
214                             .toArray(new LoadItem[loadQueue.size()]);
215                     loadQueue.clear();
216                     loadData(items);
217                 }
218                 setPending(false);
219             }
220         }
221     }
222 }
223
Popular Tags