EMMA Coverage Report (generated Sun May 02 20:42:29 CEST 2010)
[all classes][hu.netmind.beankeeper]

COVERAGE SUMMARY FOR SOURCE FILE [Store.java]

nameclass, %method, %block, %line, %
Store.java100% (1/1)89%  (16/18)72%  (123/170)75%  (31.7/42)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class Store100% (1/1)89%  (16/18)72%  (123/170)75%  (31.7/42)
Store (DataSource): void 0%   (0/1)0%   (0/42)0%   (0/14)
getPersistenceId (Object): Long 0%   (0/1)0%   (0/5)0%   (0/1)
<static initializer> 100% (1/1)100% (4/4)100% (1/1)
Store (String, String): void 100% (1/1)100% (47/47)100% (15/15)
close (): void 100% (1/1)100% (4/4)100% (2/2)
find (String): List 100% (1/1)100% (6/6)100% (1/1)
find (String, Object []): List 100% (1/1)100% (6/6)100% (1/1)
findSingle (String): Object 100% (1/1)100% (6/6)100% (1/1)
findSingle (String, Object []): Object 100% (1/1)100% (6/6)100% (1/1)
getConfigurationTracker (): ConfigurationTracker 100% (1/1)100% (3/3)100% (1/1)
getEventDispatcher (): EventDispatcher 100% (1/1)100% (3/3)100% (1/1)
getLockTracker (): LockTracker 100% (1/1)100% (3/3)100% (1/1)
getPersistenceMetaData (Object): PersistenceMetaData 100% (1/1)100% (5/5)100% (1/1)
getTransactionTracker (): TransactionTracker 100% (1/1)100% (3/3)100% (1/1)
getTypeHandlerTracker (): TypeHandlerTracker 100% (1/1)100% (3/3)100% (1/1)
init (Map): void 100% (1/1)100% (14/14)100% (4/4)
remove (Object): void 100% (1/1)100% (5/5)100% (2/2)
save (Object): void 100% (1/1)100% (5/5)100% (2/2)

1/**
2 * Copyright (C) 2006 NetMind Consulting Bt.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 3 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 */
18 
19package hu.netmind.beankeeper;
20 
21import hu.netmind.beankeeper.service.impl.StoreContextImpl;
22import hu.netmind.beankeeper.service.StoreContext;
23import java.util.*;
24import org.apache.log4j.Logger;
25import javax.sql.DataSource;
26import hu.netmind.beankeeper.transaction.TransactionTracker;
27import hu.netmind.beankeeper.lock.LockTracker;
28import hu.netmind.beankeeper.config.ConfigurationTracker;
29import hu.netmind.beankeeper.event.EventDispatcher;
30import hu.netmind.beankeeper.object.PersistenceMetaData;
31import hu.netmind.beankeeper.object.ObjectTracker;
32import hu.netmind.beankeeper.store.StoreService;
33import hu.netmind.beankeeper.query.QueryService;
34import hu.netmind.beankeeper.type.TypeHandlerTracker;
35 
36/**
37 * This store class is the entry point to the persistence library. To
38 * store, remove or select given objects, just use the appropriate
39 * methods.
40 * @author Brautigam Robert
41 * @version Revision: $Revision$
42 */
43public class Store
44{
45   private static Logger logger = Logger.getLogger(Store.class);
46 
47   private StoreContext context = null;
48   private StoreService store = null;
49   private LockTracker lockTracker = null;
50   private ConfigurationTracker config = null;
51   private EventDispatcher eventDispatcher = null;
52   private TransactionTracker transactionTracker = null;
53   private ObjectTracker objectTracker = null;
54   private QueryService queryService = null;
55   private TypeHandlerTracker typeHandlerTracker = null;
56 
57   /**
58    * Instantiate a store. Note that you should only make one
59    * store instance for each datasource you might want to use, all
60    * methods are thread-safe, so you can use the single instance 
61    * in more threads.
62    * @param driverClass The driver class to register.
63    * @param url The driver's jdbc url (including username and password).
64    */
65   public Store(String driverClass, String url)
66   {
67      Map parameters = new HashMap();
68      parameters.put(StoreContext.PARAM_DRIVERCLASS,driverClass);
69      parameters.put(StoreContext.PARAM_DRIVERURL,url);
70      init(parameters);
71   }
72 
73   /**
74    * Instantiate a store. Note that you should only make one
75    * store instance for each datasource you might want to use, all
76    * methods are thread-safe, so you can use the single instance 
77    * in more threads.
78    */
79   public Store(DataSource dataSource)
80   {
81      Map parameters = new HashMap();
82      parameters.put(StoreContext.PARAM_DATASOURCE,dataSource);
83      init(parameters);
84   }
85 
86   /**
87    * Construct this store with the given parameters.
88    */
89   private void init(Map parameters)
90   {
91      // Create context
92      context = new StoreContextImpl();
93      context.init(parameters);
94      // Get services
95      context.injectServices(this);
96   }
97 
98   /**
99    * Close the store, and release all resources. This method is automatically
100    * invoked as a JVM shutdown hook, so it does not have to be called at all.
101    */
102   public void close()
103   {
104      context.release();
105   }
106   
107   /**
108    * Get the transaction tracker associated with this store. The transaction
109    * tracker can be used to create transactions, and listen for transactional
110    * events.
111    * @return The transaction tracker.
112    */
113   public TransactionTracker getTransactionTracker()
114   {
115      return transactionTracker;
116   }
117 
118   /**
119    * Get the configuration tracker for this Store.
120    */
121   public ConfigurationTracker getConfigurationTracker()
122   {
123      return config;
124   }
125 
126   /**
127    * Get the lock tracker. This tracker can be used to lock and unlock
128    * objects for exclusive operations.
129    */
130   public LockTracker getLockTracker()
131   {
132      return lockTracker;
133   }
134 
135   /**
136    * Get the type handler which is responisble for saving fields
137    * other than primitive types.
138    */
139   public TypeHandlerTracker getTypeHandlerTracker()
140   {
141      return typeHandlerTracker;
142   }
143 
144   /**
145    * Get the event dispatcher in which the caller may register
146    * listeners.
147    */
148   public EventDispatcher getEventDispatcher()
149   {
150      return eventDispatcher;
151   }
152 
153   /**
154    * Get the persistence id for an object. This method always returns
155    * a valid id, even if the object is not saved, or otherwise has
156    * no persistence id. If the object is later saved, this persistence id
157    * is always preserved.<br>
158    * Same as: <code>getPersistenceMetaData(obj).getPersistenceId()</code>.
159    * @return A persistence id, and never null.
160    */
161   public Long getPersistenceId(Object obj)
162   {
163      return getPersistenceMetaData(obj).getPersistenceId();
164   }
165 
166   /**
167    * Get the persistence meta-data object for a given object. Metadata
168    * is always available, even for non-saved objects.
169    */
170   public PersistenceMetaData getPersistenceMetaData(Object obj)
171   {
172      return objectTracker.getMetaData(obj);
173   }
174 
175 
176   /**
177    * Save the given object to the store. The given object's all private
178    * non-transient fields will be saved. If the object  was not selected
179    * from the store, and not yet saved, it will be created in the store,
180    * and a unique id will be assigned, so all subsequent calls to save
181    * the given object will only modify the already existing instance in
182    * store. A few tips:<br>
183    * <ul>
184    *    <li>Use simple beans. Although this library does not scan
185    *    methods to determine the attributes to save, it is a good
186    *    idea to simplify work with them.</li>
187    *    <li>If you do not use simple beans, watch out that your
188    *    object does not reference unnecessary objects, because
189    *    if it does, all will be saved/inserted and tracked.</li>
190    *    <li>You CAN use objects which reference other beans though.
191    *    But beware, that all objects which are directly referenced
192    *    will be loaded when the parent object loads.</li>
193    *    <li>You CAN use Map, and List types in your
194    *    beans. Check the documentation.</li>
195    * </ul>
196    * <i>Note:</i>A save operation is not recursive. It does not traverse
197    * the object hierarchy, only saves the object given, and does not save
198    * objects referenced, except when referenced object does not exist
199    * yet. If a referenced object does not yet exist, it will be inserted
200    * into database (and recursively all referenced objects of that object).
201    * <i>Implementation note:</i>This class is the intelligent part of
202    * the framework, an intentionally so. This is the class that coordinates
203    * all other classes, trackers and functions together.
204    * @param obj The object to save.
205    * @throws StoreException If save is not successfull.
206    */
207   public void save(Object obj)
208   {
209      store.save(obj);
210   }
211 
212   /**
213    * Remove the object given. If the object is not stored yet, no
214    * operation will take place.
215    * @param obj The object to remove.
216    * @throws StoreException If remove is not successfull.
217    */
218   public void remove(Object obj)
219   {
220      store.remove(obj);
221   }
222 
223   /**
224    * Query an object from the datastore. The List returned is 
225    * a lazy list, the implementation tries to limit the communication
226    * with the database layer, as much as possible and pratical. Only
227    * parts of the list will be loaded when an item is referenced, not
228    * the whole list. Some features of the query language:<br>
229    * <pre>find book where book.name='Snow Crash'</pre>
230    * The statement always starts with the keyword 'find', and all
231    * keywords and parts of the statement not between apostrophs are
232    * case in-sensitive.<br>
233    * The second word of the statement determines
234    * the class you are trying to find. You can abbreviate the classname
235    * (strip the package) if it is unique, but you can use the full
236    * name (com.acme.book) if you wish, but then you MUST provide an
237    * alias name (see below)<br>
238    * The following parts are all optional. First, there can be
239    * a select statement, to specify which objects to select which are
240    * instances of given class. If you want to have a where part, the
241    * third word should be 'where'. After it there should be an
242    * expression almost as in SQL. Parts of the expression can be:<br>
243    * <ul>
244    *    <li><strong>Member attributes of classes.</strong> The class given previously
245    *    (the target of statement) is always available as declared. If
246    *    you wish to use other classes, they can be referenced by
247    *    class (abbreviated or fully declared). For example
248    *    <pre>find book where book.author=author and author.birthdate=1959</pre>
249    *    Of course Book, and Author classes must exits in the store with
250    *    given attributes.
251    *    Note also, that the above statement can be simply written:
252    *    <pre>find book where book.author.birthdate=1959</pre>
253    *    You can name the classes you are referencing for later
254    *    use (handy if you must "join" the class with itself):
255    *    <pre>find book where book.author=otherbook(book).author and otherbook.name='Snow Crash'</pre>
256    *    Here, the "otherbook" does not refer to a class, it is only another
257    *    name for the class book, and means, that is should be not the same
258    *    instance as the one referenced with "book".
259    *    </li>
260    *    <li><strong>"Now" constant</strong>: For easy use the current date/time
261    *    is represented with the special word 'now'. So you can write:
262    *    <pre>find movie where movie.startdate &gt; now</pre>
263    *    This also means, that attributes named 'now' must be escaped (prefixed
264    *    with it's table name).
265    *    <li><strong>Constants</strong>: Numbers and strings, see examples above. 
266    *    Dates and objects can be given by using the question mark (?), and adding the object
267    *    as parameters (same as in jdbc).</li>
268    *    <li><strong>The operators</strong>: &lt;, &gt;, =, !=, like, is null, not null, is not null.
269    *    Note however, that not all database backends are required to support
270    *    all of these. If they are not supported, an exception will be thrown.</li>
271    *    <li><strong>Logical operators</strong>: or, and, not. See examples above.</li>
272    *    <li><strong>Grouping with parenthesis.</strong> As usual in expressions,
273    *    you can use grouping:
274    *    <pre>find book where ((book.author.firstname='Neal') and (book.author.lastname='Stephenson'))</pre>
275    *    </li>
276    *    <li><strong>Special container operator</strong>: contains. 
277    *    These are used in conjunction with container types such as Map and List:
278    *    <pre>find book where book.genres contains genre and genre.name='postcyberpunk'</pre>
279    *    <pre>find author where author.books contains book and book.name='Snow Crash'</pre>
280    *    A container operator can not be negated, an exception will be thrown,
281    *    if the expression would try to do that.
282    *    </li>
283    *    <li><strong>Special map operator</strong>: [, ]. These are used when
284    *    referencing a Map. Note also, that [] can only contain strings.
285    *    <pre>find book where book.metadata['author']=author and author.name='Neal Stephenson</pre>
286    *    However, if after a map operator an attribute is referenced, 
287    *    there is a mandatory class specifier:
288    *    <pre>find book where book.metadata['author'](author).name='Neal Stephenson</pre>
289    *    </li>
290    * </ul><br>
291    * You can also sort the result list with the 'order by' command:
292    * <pre>find book order by book.name asc</pre>
293    * The order by command takes attributes as aguments. 
294    * You can give more than one attribute separated by commas.
295    * Also you can append 'asc' (ascending) or 'desc' (descending) to
296    * mark the direction of sort.
297    * <pre>find book order by book.author.name asc, book.name desc</pre>
298    * Note, that method will silently return an empty list, if the
299    * specified table or one specified in where clause does not exist.<br>
300    * For more detailed information, check the documentation.
301    * @param statement The query statement to select.
302    */
303   public List find(String statement)
304   {
305      return queryService.find(statement,null);
306   }
307 
308   /**
309    * Same as <code>find(statement)</code>. When a statement contains
310    * the question mark (?), the object which should be in the place of
311    * the mark should be given as parameters (parameters are usually of
312    * Date, or custom classes).
313    * @param statement The query statement to execute.
314    * @param parameters The parameters.
315    */
316   public List find(String statement, Object[] parameters)
317   {
318      return queryService.find(statement,parameters);
319   }
320 
321   /**
322    * Same as <code>find(statement,parameters)</code>, but the result should be
323    * a single object.
324    * @param statement The query statement to execute.
325    * @param parameters The parameters to the statement.
326    * @return The object selected, or null if no such object exists. If
327    * the result contains more objects, an arbitrary one is selected.
328    */
329   public Object findSingle(String statement, Object[] parameters)
330   {
331      return queryService.findSingle(statement,parameters);
332   }
333 
334   /**
335    * Same as <code>find(statement)</code>, but the result should be
336    * a single object.
337    * @param statement The query statement to execute.
338    * @return The object selected, or null if no such object exists. If
339    * the result contains more objects, an arbitrary one is selected.
340    */
341   public Object findSingle(String statement)
342   {
343      return queryService.findSingle(statement,null);
344   }
345 
346}
347 
348 
349 

[all classes][hu.netmind.beankeeper]
EMMA 2.0.5312debian (C) Vladimir Roubtsov