KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > opensubsystems > patterns > listdata > util > AsyncDataLoader


1 /*
2  * Copyright (c) 2003 - 2007 OpenSubsystems s.r.o. Slovak Republic. All rights reserved.
3  *
4  * Project: OpenSubsystems
5  *
6  * $Id: AsyncDataLoader.java,v 1.9 2007/01/07 06:14:10 bastafidli Exp $
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; version 2 of the License.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */

21  
22 package org.opensubsystems.patterns.listdata.util;
23
24 import java.util.List JavaDoc;
25 import java.util.Properties JavaDoc;
26 import java.util.logging.Level JavaDoc;
27 import java.util.logging.Logger JavaDoc;
28
29 import org.opensubsystems.core.error.OSSException;
30 import org.opensubsystems.core.logic.ControllerManager;
31 import org.opensubsystems.core.util.Config;
32 import org.opensubsystems.core.util.GlobalConstants;
33 import org.opensubsystems.core.util.Log;
34 import org.opensubsystems.patterns.listdata.data.ListOptions;
35 import org.opensubsystems.patterns.listdata.logic.ListController;
36
37 /**
38  * Thread used to load data asynchronously using list controller interface.
39  *
40  * The class, which wants to perform async data processing will usually derive
41  * new class inline and define method createAddItemsRunnable.
42  *
43  * TODO: Performance: We may want to convert this to Runnable and the user pool
44  * of threads to run them instead of creating new thread all the time.
45  *
46  * @version $Id: AsyncDataLoader.java,v 1.9 2007/01/07 06:14:10 bastafidli Exp $
47  * @author Miro Halas
48  * @code.reviewer Miro Halas
49  * @code.reviewed 1.5 2006/03/13 16:58:37 bastafidli
50  */

51 public class AsyncDataLoader extends Thread JavaDoc
52 {
53    // Configuration settings ///////////////////////////////////////////////////
54

55    /**
56     * Configuration setting for how many items to load at once when loading data
57     * in the background. If this is equal to ListOptions.PAGE_SIZE_ALL then
58     * all items will be loaded at once.
59     */

60    public static final String JavaDoc ASYNC_LOADER_PAGE_SIZE = "oss.listdata.asyncloader.pagesize";
61    
62    // Constants ////////////////////////////////////////////////////////////////
63

64    /**
65     * Default value for how many items to load at once when loading data in the
66     * background.
67     */

68    // TODO: Performance: Tune this size to provide optimal performance.
69
public static final int ASYNC_LOADER_PAGE_SIZE_DEFAULT = 50;
70    
71    /**
72     * This object should be used as a placeholder when there is nothing to do
73     * to prevent creation of new objects and exhausting memory.
74     */

75    public static final Runnable JavaDoc NOTHING_TO_DO = new Runnable JavaDoc()
76                                                 {
77                                                    public void run()
78                                                    {
79                                                    }
80                                                 };
81    
82    // Attributes ///////////////////////////////////////////////////////////////
83

84    /**
85     * Identification of this loader which is send back to owner to distinguish
86     * if there are multiple loader present.
87     */

88    protected int m_iLoaderIdentification;
89                                                 
90    /**
91     * Owner which is loading with data using this thread.
92     */

93    protected AsyncDataLoaderOwner m_owner;
94    
95    /**
96     * Class for the list factory to use.
97     */

98    protected Class JavaDoc m_clsListFactoryClassName;
99    
100    /**
101     * Value uniquely identifying the current state of the object to which
102     * the data should be added. This is used to detect when to stop loading
103     * by increasing the value of the original variable to be different from
104     * this value.
105     */

106    protected int m_iCurrentObjectVersion;
107
108    // Cached values ////////////////////////////////////////////////////////////
109

110    /**
111     * Logger for this class
112     */

113    private static Logger JavaDoc s_logger = Log.getInstance(AsyncDataLoader.class);
114
115    /**
116     * How many items to load at once when loading data in the background.
117     * If this is equal to ListOptions.PAGE_SIZE_ALL then all items will be
118     * loaded at once.
119     */

120    protected static int s_iPageSize;
121    
122    // Constructors /////////////////////////////////////////////////////////////
123

124    /**
125     * Static initializer.
126     */

127    static
128    {
129       // Read configuration parameters
130
Properties JavaDoc prpSettings;
131
132       prpSettings = Config.getInstance().getPropertiesSafely();
133       s_iPageSize = Config.getIntPropertyInRange(
134                               prpSettings,
135                               ASYNC_LOADER_PAGE_SIZE,
136                               ASYNC_LOADER_PAGE_SIZE_DEFAULT,
137                               "Asynchronous data loader page size",
138                               0, // 0 is allowed since ListOptions.PAGE_SIZE_ALL is defined as 0
139
Integer.MAX_VALUE);
140    }
141    
142    /**
143     * Construct new loader.
144     *
145     * @param iLoaderIdentification - identification of this loader which is send
146     * back to owner to distinguish if there are
147     * multiple loader present
148     * @param owner - owner of this data loader
149     * TODO: Improve: It doesn't necessarily make sence for everybody to know
150     * what factory class to user
151     * @param clsListFactoryClassName - name of the class for the list factory
152     * to use
153     * @param iObjectVersion - value uniquely identifying the current state of the object
154     * to which the data should be added
155     */

156    public AsyncDataLoader(
157       int iLoaderIdentification,
158       AsyncDataLoaderOwner owner,
159       Class JavaDoc clsListFactoryClassName,
160       int iObjectVersion
161    )
162    {
163       if (GlobalConstants.ERROR_CHECKING)
164       {
165          assert owner != null : "Owner of the data loader cannot be null.";
166          assert clsListFactoryClassName != null : "List factory class cannot be null.";
167       }
168
169       m_iLoaderIdentification = iLoaderIdentification;
170       m_owner = owner;
171       m_clsListFactoryClassName = clsListFactoryClassName;
172       m_iCurrentObjectVersion = iObjectVersion;
173    }
174    
175    // Public methods ///////////////////////////////////////////////////////////
176

177    /**
178     * {@inheritDoc}
179     */

180    public void run(
181    )
182    {
183       ListController listLoader;
184       ListOptions listData = getInitialListOptions();
185       Object JavaDoc[] data;
186       List JavaDoc lstData;
187           
188       try
189       {
190          listLoader = getListController();
191          data = listLoader.getShowList(listData);
192          if (data != null)
193          {
194             listData = (ListOptions)data[0];
195             lstData = (List JavaDoc)data[1];
196                                                               
197             while ((listData != null) && (lstData != null) && (!lstData.isEmpty()))
198             {
199                // TODO: Feature: Add ability to pause loading of data.
200
// As soon as we load the first data we know the total amount
201
// of data and therefore we can on a screen adjust a scrollbar
202
// then we load/show only as much data (or maybe little more) as
203
// the screen allows to see. Only when user scrolls up and down
204
// we would load additional data
205
if (stopLoading())
206                {
207                   break;
208                }
209                processData(lstData, m_iCurrentObjectVersion);
210                
211                if (stopLoading())
212                {
213                   break;
214                }
215                else
216                {
217                   if (listData.getEndPosition() != listData.getActualListSize())
218                   {
219                      data = listLoader.getNextPage(listData);
220                      if (data == null)
221                      {
222                         break;
223                      }
224                      else
225                      {
226                         listData = (ListOptions)data[0];
227                         lstData = (List JavaDoc)data[1];
228                      }
229                   }
230                   else
231                   {
232                      // We are done
233
break;
234                   }
235                }
236             }
237
238             allDataLoaded();
239          }
240       }
241       catch (Throwable JavaDoc thr)
242       {
243          s_logger.log(Level.WARNING,
244                       "Unexpected error has occured while loading data.", thr);
245       }
246    }
247
248    // Helper methods ///////////////////////////////////////////////////////////
249

250    /**
251     * Return the initial ListOptions structure used to load the list of data
252     * objects. This method may be overriden if some parameters should be preset.
253     *
254     * @return ListOptions - initialized list options
255     */

256    protected ListOptions getInitialListOptions(
257    )
258    {
259       ListOptions options = new ListOptions(m_clsListFactoryClassName);
260       options.setPageSize(s_iPageSize);
261       // Give owner chance to modify the default settings
262
options = m_owner.getInitialListOptions(this, options);
263       
264       return options;
265    }
266    
267    /**
268     * This method should return true if the async thread should stop loading data.
269     *
270     * @return boolean - true if the async thread should stop loading data, false
271     * to continue loading
272     */

273    protected boolean stopLoading(
274    )
275    {
276       return m_owner.stopLoading(this);
277    }
278    
279    /**
280     * Process data which were asynchronously loaded.
281     *
282     * @param lstDataToAdd - list of data items to add to the container
283     * @param iOriginalObjectVersion - version of the object by which the data
284     * should be processed, which is the version which was used to
285     * construct this object. If the version of the object at the time when
286     * the data are being processed is different from this version, then
287     * the data will not be processed or the processing of the data stops.
288     */

289    protected void processData(
290       final List JavaDoc lstDataToAdd,
291       final int iOriginalObjectVersion
292
293    )
294    {
295       m_owner.processData(this, lstDataToAdd, iOriginalObjectVersion);
296    }
297    
298    /**
299     * This function is called where data loading finished. It is useful if you
300     * want do same changes or ask for information relevant to the whole dataset.
301     */

302    protected void allDataLoaded()
303    {
304       m_owner.allDataLoaded(this);
305    }
306    
307    /**
308     * Get list controller to use.
309     *
310     * @return ListController
311     * @throws OSSException - an error has occured
312     */

313    protected ListController getListController(
314    ) throws OSSException
315    {
316       ListController controller;
317       
318       controller = (ListController)ControllerManager.getInstance(
319                                                         ListController.class);
320       
321       return controller;
322    }
323 }
324
Popular Tags