001: /*
002: * PersistenceContext.java
003: *
004: * Created on Jun 22, 2007, 11:16:08 AM
005: *
006: * To change this template, choose Tools | Template Manager
007: * and open the template in the editor.
008: */
009:
010: package it.biobytes.ammentos;
011:
012: import it.biobytes.ammentos.cache.FrameworkCache;
013: import it.biobytes.ammentos.query.Query;
014: import it.biobytes.ammentos.query.QueryFilter;
015: import it.biobytes.ammentos.util.ReferenceMarker;
016: import java.util.HashMap;
017: import java.util.List;
018: import java.util.Map;
019: import java.util.logging.Logger;
020: import javax.sql.DataSource;
021:
022: /**
023: *
024: * @author davide
025: */
026: public class PersistenceContext {
027: private DataSource m_dataSource;
028: private Logger m_logger = Logger.getLogger("ammentos");
029: private ThreadLocal<FrameworkState> state;
030: private ThreadLocal<Transaction> transaction;
031: private ThreadLocal<EntityIterable> iterable;
032: private FrameworkCache cache = new FrameworkCache();
033:
034: protected Transaction getTransaction() {
035: return transaction.get();
036: }
037:
038: protected void setTransaction(Transaction transaction) {
039: this .transaction.set(transaction);
040: }
041:
042: protected FrameworkState getState() {
043: return state.get();
044: }
045:
046: protected void setState(FrameworkState state) {
047: this .state.set(state);
048: }
049:
050: protected void setIterable(EntityIterable iterable) {
051: this .iterable.set(iterable);
052: }
053:
054: public EntityIterable getIterable() {
055: return iterable.get();
056: }
057:
058: /** Mantains weak references to loaded objects **/
059: private Map<Class, ReferenceMarker> m_loadedObjectsMarkers;
060:
061: protected PersistenceContext(DataSource dataSource) {
062: m_dataSource = dataSource;
063: m_loadedObjectsMarkers = new HashMap<Class, ReferenceMarker>();
064: transaction = new ThreadLocal<Transaction>();
065: state = new ThreadLocal<FrameworkState>();
066: iterable = new ThreadLocal<EntityIterable>();
067: }
068:
069: protected void setDataSource(DataSource dataSource) {
070: m_dataSource = dataSource;
071: }
072:
073: public DataSource getDataSource() {
074: return m_dataSource;
075: }
076:
077: /**
078: * Saves the provided object instance. If a transaction is opened this operation
079: * will be actually performed when the commitTransaction() method will be called
080: * @param obj The object to save
081: * @throws it.biobytes.ammentos.PersistenceException If any errors occurr while saving the object
082: */
083: public <T> void save(T obj) throws PersistenceException {
084: Ammentos.openContext(this );
085: Ammentos.save(obj);
086: Ammentos.closeContext();
087: }
088:
089: /**
090: * Saves the provided object instance, regardless the object is already present
091: * into the target domain. If the object is already present the call corresponds to
092: * a normale save() method, otherwise a delete() method followed by a new save() method
093: * is called.
094: *
095: * @param obj The object to override
096: * @throws it.biobytes.ammentos.PersistenceException If any errors occurr while saving the object
097: */
098: public <T> void override(T obj) throws PersistenceException {
099: Ammentos.openContext(this );
100: Ammentos.override(obj);
101: Ammentos.closeContext();
102: }
103:
104: /**
105: * Deletes the object. If a transaction is opened this operation will be actually
106: * performed when the commitTransaction() method will be called
107: * @param obj The object to delete
108: * @throws it.biobytes.ammentos.PersistenceException
109: */
110: public <T> void delete(T obj) throws PersistenceException {
111: Ammentos.openContext(this );
112: Ammentos.delete(obj);
113: Ammentos.closeContext();
114: }
115:
116: /**
117: * Deletes all the objects of class c matching the provided QueryFilter.
118: * If a transaction is opened this operation will be actually
119: * performed when the commitTransaction() method will be called
120: */
121: public <T> void delete(Class<T> c, QueryFilter filter)
122: throws PersistenceException {
123: Ammentos.openContext(this );
124: Ammentos.delete(c, filter);
125: Ammentos.closeContext();
126: }
127:
128: /**
129: * Loads the object whith the provided primary key
130: * @param c
131: * @param primaryKey
132: * @throws it.biobytes.ammentos.PersistenceException
133: * @return
134: */
135: public <T> T load(Class<T> c, Object primaryKey)
136: throws PersistenceException {
137: T res = null;
138: Ammentos.openContext(this );
139: res = Ammentos.load(c, primaryKey);
140: Ammentos.closeContext();
141: return res;
142: }
143:
144: /**
145: * Loads the objects which match the provided query. The returned list is
146: * unmodifiabale.
147: * @param c
148: * @param qry
149: * @throws it.biobytes.ammentos.PersistenceException
150: * @return
151: */
152: public <T> List<T> load(Class<T> c, Query qry)
153: throws PersistenceException {
154: List<T> res = null;
155: Ammentos.openContext(this );
156: res = Ammentos.load(c, qry);
157: Ammentos.closeContext();
158: return res;
159: }
160:
161: /**
162: * Loads the objects which match the provided query.
163: * @param c
164: * @param filter
165: * @throws it.biobytes.ammentos.PersistenceException
166: * @return
167: */
168: public <T> List<T> load(Class<T> c, QueryFilter filter)
169: throws PersistenceException {
170: List<T> res = null;
171: Ammentos.openContext(this );
172: res = Ammentos.load(c, filter);
173: Ammentos.closeContext();
174: return res;
175: }
176:
177: /**
178: * Lookup the object of the provided class whith the specified primary key.
179: * This methods uses an internal caching mechanism which dramatically increases
180: * the performance, so use this method instead of load(Class,String) whenever
181: * is possible to obtain the best performance in retrieving objects.
182: * @param c
183: * @param primaryKey
184: * @throws it.biobytes.ammentos.PersistenceException
185: * @return
186: */
187: public <T> T lookup(Class<T> c, Object primaryKey)
188: throws PersistenceException {
189: T res = null;
190: Ammentos.openContext(this );
191: res = Ammentos.lookup(c, primaryKey);
192: Ammentos.closeContext();
193: return res;
194: }
195:
196: /**
197: * Counts the objects matching the provided query
198: * @param c
199: * @param qry
200: * @return
201: * @throws it.biobytes.ammentos.PersistenceException
202: */
203: public <T> int count(Class<T> c, Query qry)
204: throws PersistenceException {
205: int res = 0;
206: Ammentos.openContext(this );
207: res = Ammentos.count(c, qry);
208: Ammentos.closeContext();
209: return res;
210: }
211:
212: /**
213: * Counts the objects matching the provided query filter
214: * @param c
215: * @param qry
216: * @return
217: * @throws it.biobytes.ammentos.PersistenceException
218: */
219: public <T> int count(Class<T> c, QueryFilter filter)
220: throws PersistenceException {
221: int res = 0;
222: Ammentos.openContext(this );
223: res = Ammentos.count(c, filter);
224: Ammentos.closeContext();
225: return res;
226: }
227:
228: /**
229: * This method represents a shortcut for loading objects with queries when the
230: * expected return value is only one object. A persistenceException will
231: * be thrown if the query returns more than one value.
232: *
233: * @param c
234: * @param query
235: * @return
236: * @throws it.biobytes.ammentos.PersistenceException
237: */
238: public <T> T loadUnique(Class<T> c, Query qry)
239: throws PersistenceException {
240: T res = null;
241: Ammentos.openContext(this );
242: res = Ammentos.loadUnique(c, qry);
243: Ammentos.closeContext();
244: return res;
245: }
246:
247: /**
248: * This method represents a shortcut for loading objects with queries when the
249: * expected return value is only one object. A persistenceException will
250: * be thrown if the query returns more than one value.
251: *
252: * @param c
253: * @param filter
254: * @return
255: * @throws it.biobytes.ammentos.PersistenceException
256: */
257: public <T> T loadUnique(Class<T> c, QueryFilter filter)
258: throws PersistenceException {
259: T res = null;
260: Ammentos.openContext(this );
261: res = Ammentos.loadUnique(c, filter);
262: Ammentos.closeContext();
263: return res;
264: }
265:
266: /**
267: * Returns an updatable list of objects which match the provided query. By
268: * calling add() and remove() method on this list the objects will be
269: * respectively saved or removed from their persistor.
270: */
271: public <T> List<T> loadUpdatable(Class<T> c, Query qry)
272: throws PersistenceException {
273: List<T> res = null;
274: Ammentos.openContext(this );
275: res = Ammentos.loadUpdatable(c, qry);
276: Ammentos.closeContext();
277: return res;
278: }
279:
280: public void openTransaction() throws PersistenceException {
281: Ammentos.openContext(this );
282: Ammentos.openTransaction();
283: Ammentos.closeContext();
284: }
285:
286: public void openTransaction(int isolationLevel)
287: throws PersistenceException {
288: Ammentos.openContext(this );
289: Ammentos.openTransaction(isolationLevel);
290: Ammentos.closeContext();
291: }
292:
293: public void commitTransaction() throws PersistenceException {
294: Ammentos.openContext(this );
295: Ammentos.commitTransaction();
296: Ammentos.closeContext();
297: }
298:
299: public void rollbackTransaction() throws PersistenceException {
300: Ammentos.openContext(this );
301: Ammentos.rollbackTransaction();
302: Ammentos.closeContext();
303: }
304:
305: public <T> Iterable<T> iterate(Class<T> c, Query qry)
306: throws PersistenceException {
307: Iterable<T> res = null;
308: Ammentos.openContext(this );
309: res = Ammentos.iterate(c, qry);
310: Ammentos.closeContext();
311: return res;
312: }
313:
314: public void closeIteration() throws PersistenceException {
315: Ammentos.openContext(this );
316: Ammentos.rollbackTransaction();
317: Ammentos.closeContext();
318: }
319:
320: protected <T> void markAsLoaded(Class<T> c, T obj) {
321: ReferenceMarker marker = m_loadedObjectsMarkers.get(c);
322: if (marker == null) {
323: marker = new ReferenceMarker();
324: m_loadedObjectsMarkers.put(c, marker);
325: }
326: marker.mark(obj);
327:
328: m_logger.info("Object " + System.identityHashCode(obj)
329: + " marked as loaded");
330: }
331:
332: protected <T> void unmarkAsLoaded(Class<T> c, T obj) {
333: ReferenceMarker marker = m_loadedObjectsMarkers.get(c);
334: if (marker == null) {
335: marker = new ReferenceMarker();
336: m_loadedObjectsMarkers.put(c, marker);
337: }
338: marker.unmark(obj);
339: m_logger.info("Object " + System.identityHashCode(obj)
340: + " unmarked");
341: }
342:
343: protected <T> boolean isLoaded(Class<T> c, T obj) {
344: ReferenceMarker marker = m_loadedObjectsMarkers.get(c);
345: return ((marker != null) && (marker.isMarked(obj)));
346: }
347:
348: public FrameworkCache getCache() {
349: return cache;
350: }
351: }
|