001 package com.sptci.prevayler;
002
003 import static com.sptci.prevayler.PrevalentSystemFactory.getPrevayler;
004 import com.sptci.prevayler.query.Count;
005 import com.sptci.prevayler.query.Fetch;
006 import com.sptci.prevayler.query.FetchByIndex;
007 import com.sptci.prevayler.query.FetchByIndices;
008 import com.sptci.prevayler.query.FetchRange;
009 import com.sptci.prevayler.query.Search;
010 import com.sptci.prevayler.transaction.Delete;
011 import com.sptci.prevayler.transaction.Save;
012 import org.apache.lucene.search.Filter;
013 import org.apache.lucene.search.Query;
014 import org.apache.lucene.search.Sort;
015
016 import java.util.Collection;
017 import java.util.Map;
018
019 /**
020 * A facade around the prevalent system used to present a more natural
021 * programming interface than that provided by prevayler.
022 *
023 * <p>The following shows sample use of this class:</p>
024 * <pre>
025 * import com.sptci.prevayler.PrevalentException;
026 * import com.sptci.prevayler.PrevalentManager;
027 *
028 * ...
029 * MyPrevalentObject po = new MyPrevalentObject( ... );
030 * po.setXxx( ... );
031 *
032 * final PrevalentManager<MyPrevalentObject> pm = new PrevalentManager<MyPrevalentObject>();
033 * try
034 * {
035 * po = pm.save( po );
036 * System.out.format( "Total MyPrevalentObjects in system: %d%n",
037 * po.count( MyPrevalentObject.class ) );
038 * }
039 * catch ( PrevalentException pex )
040 * {
041 * // handle error
042 * }
043 * </pre>
044 *
045 * <p>© Copyright 2008 <a href='http://sptci.com/' target='_top'>Sans
046 * Pareil Technologies, Inc.</a></p>
047 *
048 * @see PrevalentSystemFactory
049 * @author Rakesh Vidyadharan 2008-07-12
050 * @version $Id: PrevalentManager.java 22 2008-11-24 19:04:25Z sptrakesh $
051 */
052 public class PrevalentManager<P extends PrevalentObject> implements Database<P>
053 {
054 private static final long serialVersionUID = 1l;
055
056 /**
057 * Save the specified prevalent object to the prevalent system. If the
058 * object does not exist, it is created. It it exists, the persisted
059 * object is updated.
060 *
061 * @param object The prevalent object to save to the prevalent system.
062 * @return The updated prevalent object instance.
063 * @throws PrevalentException If errors are encountered while saving the
064 * prevalent object.
065 */
066 @SuppressWarnings( {"unchecked"} )
067 public P save( final P object ) throws PrevalentException
068 {
069 try
070 {
071 final Save<P> save = new Save<P>( object );
072 return (P) getPrevayler().execute( save );
073 }
074 catch ( PrevalentException pex )
075 {
076 throw pex;
077 }
078 catch ( Throwable t )
079 {
080 throw new PrevalentException( "Error saving object of type: " +
081 object.getClass().getName(), t );
082 }
083 }
084
085 /**
086 * Delete the specified prevalent object from the prevalent system. Note
087 * that constraint rules may cause an exception to be raised leaving the
088 * object still persisted.
089 *
090 * @param object The prevalent object to delete from the prevalent system.
091 * @return The modified prevalent object. In particular the {@link
092 * com.sptci.prevayler.PrevalentObject#getObjectId()} will return
093 * <code>null</code> if the object is deleted.
094 * @throws PrevalentException If errors are encountered while deleting the
095 * object. More specific sub-classes such as {@link DeleteException}
096 * are thrown when configured rules are violated.
097 */
098 @SuppressWarnings( {"unchecked"} )
099 public P delete( final P object ) throws PrevalentException
100 {
101 try
102 {
103 final Delete<P> delete = new Delete<P>( object );
104 return (P) getPrevayler().execute( delete );
105 }
106 catch ( PrevalentException pex )
107 {
108 throw pex;
109 }
110 catch ( Throwable t )
111 {
112 throw new PrevalentException( "Error deleting object with oid: " +
113 object.getObjectId() + " and type: " +
114 object.getClass().getName(), t );
115 }
116 }
117
118 /**
119 * Return the total number of persistent instance of the specified type
120 * in the prevalent system. This method is typically used to implement
121 * paginated views of the persistent data.
122 *
123 * @param type The type of object whose persistent instance count is to
124 * be retrieved.
125 * @return The total number of persistent instances of the specified type.
126 * @throws PrevalentException If errors are encountered while fetching the
127 * object count.
128 */
129 @SuppressWarnings( {"unchecked"} )
130 public int count( final Class type ) throws PrevalentException
131 {
132 try
133 {
134 return (Integer) getPrevayler().execute( new Count( type ) );
135 }
136 catch ( PrevalentException pex )
137 {
138 throw pex;
139 }
140 catch ( Throwable t )
141 {
142 throw new PrevalentException(
143 "Error retrieving object count for type: " + type, t );
144 }
145 }
146
147 /**
148 * Return the prevalent object identified by the object id specified.
149 *
150 * @param type The type of the persisted object which has the specified
151 * object id.
152 * @param objectId The object id of the prevalent object.
153 * @return The prevalent object if found or <code>null</code>.
154 * @throws PrevalentException If errors are encountered while fetching the
155 * persistent object.
156 */
157 @SuppressWarnings( {"unchecked"} )
158 public P fetch( final Class type, final Object objectId )
159 throws PrevalentException
160 {
161 try
162 {
163 final Fetch fetch = new Fetch( type, objectId );
164 return (P) getPrevayler().execute( fetch );
165 }
166 catch ( PrevalentException pex )
167 {
168 throw pex;
169 }
170 catch ( Throwable t )
171 {
172 throw new PrevalentException(
173 "Error fetching prevalent object with objectId: " +
174 objectId + " and type: " + type.getName(), t );
175 }
176 }
177
178 /**
179 * Return the collection of prevalent objects in the specified range.
180 * Objects are returned in insertion order.
181 *
182 * @param type The type of the persisted objects which are to be fetched.
183 * @param start The starting index (inclusive) of the range of objects
184 * to fetch.
185 * @param end The ending index (exclusive) of the range of objects to
186 * fetch.
187 * @return The collection of persistent objects. Returns an empty
188 * collection if no objects are found in the specified range.
189 * @throws PrevalentException If errors are encountered while retrieving
190 * the persisted objects.
191 */
192 @SuppressWarnings( {"unchecked"} )
193 public Collection<P> fetch( final Class type, final long start,
194 final long end ) throws PrevalentException
195 {
196 try
197 {
198 final FetchRange range = new FetchRange( type, start, end );
199 return (Collection<P>) getPrevayler().execute( range );
200 }
201 catch ( PrevalentException pex )
202 {
203 throw pex;
204 }
205 catch ( Throwable t )
206 {
207 throw new PrevalentException(
208 "Error fetching prevalent objects in range: " +
209 start + "-" + end + " and type: " + type.getName(), t );
210 }
211 }
212
213 /**
214 * Retrieve the collection of prevelant objects of the specified type
215 * that are indexed by the specified field and value.
216 *
217 * @param type The type of the persisted objects which are to be fetched.
218 * @param field The name of the indexed field in the prevalent class.
219 * @param value The value of the indexed field in the prevalent class.
220 * @return The collection of persistent objects. Returns an empty
221 * collection if no objects are found with the specified indexed value.
222 * @throws PrevalentException If errors are encountered while retrieving
223 * the persisted objects.
224 */
225 @SuppressWarnings( {"unchecked"} )
226 public Collection<P> fetch( final Class type, final String field,
227 final Object value ) throws PrevalentException
228 {
229 try
230 {
231 final FetchByIndex index = new FetchByIndex( type, field, value );
232 return (Collection<P>) getPrevayler().execute( index );
233 }
234 catch ( PrevalentException pex )
235 {
236 throw pex;
237 }
238 catch ( Throwable t )
239 {
240 throw new PrevalentException(
241 "Error fetching prevalent objects for indexed field: " + field +
242 " with value: " + value + " and type: " + type.getName(), t );
243 }
244 }
245
246 /**
247 * Retrieve the collection of prevelant objects of the specified type
248 * that are indexed by the specified fields and values. The results
249 * represent a <code>union</code> of the prevalent objects matching each
250 * parameter in the collection of parameters (an <code>or</code> query).
251 *
252 * @see #fetchByIndices
253 * @param type The type of the persisted objects which are to be fetched.
254 * @param parameters The map of field-name to value mappings to use
255 * to fetch instances.
256 * @return The collection of persistent objects. Returns an empty
257 * collection if no objects are found with the specified indexed value.
258 * @throws PrevalentException If errors are encountered while retrieving
259 * the persisted objects.
260 */
261 public Collection<P> fetchUnion( final Class type,
262 final Map<String,?> parameters ) throws PrevalentException
263 {
264 return fetchByIndices( type, parameters,
265 FetchByIndices.AggregationType.UNION );
266 }
267
268 /**
269 * Retrieve the collection of prevelant objects of the specified type
270 * that are indexed by the specified fields and values. The results
271 * represent an <code>intersection</code> of the prevalent objects matching
272 * each parameter in the collection of parameters (an <code>or</code> query).
273 *
274 * @see #fetchByIndices
275 * @param type The type of the persisted objects which are to be fetched.
276 * @param parameters The map of field-name to value mappings to use
277 * to fetch instances.
278 * @return The collection of persistent objects. Returns an empty
279 * collection if no objects are found with the specified indexed value.
280 * @throws PrevalentException If errors are encountered while retrieving
281 * the persisted objects.
282 */
283 public Collection<P> fetchIntersection( final Class type,
284 final Map<String,?> parameters ) throws PrevalentException
285 {
286 return fetchByIndices( type, parameters,
287 FetchByIndices.AggregationType.INTERSECTION );
288 }
289
290 /** {@inheritDoc} */
291 @SuppressWarnings( {"unchecked"} )
292 public Collection<P> search( final Query query, final int count ) throws PrevalentException
293 {
294 try
295 {
296 final Search search = new Search( query, count );
297 return (Collection<P>) getPrevayler().execute( search );
298 }
299 catch ( PrevalentException pex )
300 {
301 throw pex;
302 }
303 catch ( Throwable t )
304 {
305 throw new PrevalentException( "Error executing query: " + query, t );
306 }
307 }
308
309 /** {@inheritDoc} */
310 @SuppressWarnings( {"unchecked"} )
311 public Collection<P> search( final Query query, final Filter filter,
312 final int count ) throws PrevalentException
313 {
314 try
315 {
316 final Search search = new Search( query, filter, count );
317 return (Collection<P>) getPrevayler().execute( search );
318 }
319 catch ( PrevalentException pex )
320 {
321 throw pex;
322 }
323 catch ( Throwable t )
324 {
325 throw new PrevalentException( "Error executing query: " + query +
326 " with filter: " + filter, t );
327 }
328 }
329
330 /** {@inheritDoc} */
331 @SuppressWarnings( {"unchecked"} )
332 public Collection<P> search( final Query query, final Filter filter,
333 final int count, final Sort sort ) throws PrevalentException
334 {
335 try
336 {
337 final Search search = new Search( query, filter, count, sort );
338 return (Collection<P>) getPrevayler().execute( search );
339 }
340 catch ( PrevalentException pex )
341 {
342 throw pex;
343 }
344 catch ( Throwable t )
345 {
346 throw new PrevalentException( "Error executing query: " + query +
347 " with filter: " + filter + " and sort: " + sort, t );
348 }
349 }
350
351
352 /**
353 * Retrieve the collection of prevelant objects of the specified type
354 * that are indexed by the specified fields and values.
355 *
356 * @param type The type of the persisted objects which are to be fetched.
357 * @param parameters The map of field-name to value mappings to use
358 * to fetch instances.
359 * @param resultType The type of aggregation to be used for the result set.
360 * @return The collection of persistent objects. Returns an empty
361 * collection if no objects are found with the specified indexed value.
362 * @throws PrevalentException If errors are encountered while retrieving
363 * the persisted objects.
364 */
365 @SuppressWarnings( {"unchecked"} )
366 protected Collection<P> fetchByIndices( final Class type,
367 final Map<String,?> parameters,
368 final FetchByIndices.AggregationType resultType )
369 throws PrevalentException
370 {
371 try
372 {
373 final FetchByIndices indices =
374 new FetchByIndices( type, parameters, resultType );
375 return (Collection<P>) getPrevayler().execute( indices );
376 }
377 catch ( PrevalentException pex )
378 {
379 throw pex;
380 }
381 catch ( Throwable t )
382 {
383 throw new PrevalentException(
384 "Error fetching prevalent objects of type: " + type.getName(), t );
385 }
386 }
387 }