001: /*
002: * Copyright 2004 (C) TJDO.
003: * All rights reserved.
004: *
005: * This software is distributed under the terms of the TJDO License version 1.0.
006: * See the terms of the TJDO License in the documentation provided with this software.
007: *
008: * $Id: AbstractMapStore.java,v 1.6 2004/01/18 03:01:06 jackknifebarber Exp $
009: */
010:
011: package com.triactive.jdo.store;
012:
013: import com.triactive.jdo.PersistenceManager;
014: import com.triactive.jdo.StateManager;
015: import java.sql.Connection;
016: import java.sql.PreparedStatement;
017: import java.sql.ResultSet;
018: import java.sql.SQLException;
019: import java.util.Iterator;
020: import java.util.HashMap;
021: import java.util.Map;
022: import java.util.NoSuchElementException;
023: import javax.jdo.JDODataStoreException;
024: import javax.jdo.JDOHelper;
025: import javax.jdo.JDOUnsupportedOptionException;
026: import javax.jdo.JDOUserException;
027: import org.apache.log4j.Category;
028:
029: abstract class AbstractMapStore implements MapStore {
030: private static final Category LOG = Category
031: .getInstance(AbstractMapStore.class);
032:
033: protected StoreManager storeMgr;
034: protected DatabaseAdapter dba;
035: protected ColumnMapping ownerMapping;
036: protected ColumnMapping keyMapping;
037: protected ColumnMapping valueMapping;
038: protected Column ownerColumn;
039: protected Column keyColumn;
040: protected Column valueColumn;
041: protected Class keyType;
042: protected Class valueType;
043: protected boolean keysAreEmbedded;
044: protected boolean valuesAreEmbedded;
045: protected String loadStmt;
046: protected String getStmt;
047: protected String sizeStmt;
048: protected String containsValueStmt;
049: protected String containsEntryStmt;
050: protected String clearStmt;
051:
052: public AbstractMapStore() {
053: }
054:
055: public StoreManager getStoreManager() {
056: return storeMgr;
057: }
058:
059: public Class getKeyType() {
060: return keyType;
061: }
062:
063: public Class getValueType() {
064: return valueType;
065: }
066:
067: protected boolean validateKeyForReading(StateManager sm, Object key) {
068: if (!keysAreEmbedded) {
069: PersistenceManager pm = sm.getPersistenceManager();
070:
071: if (!JDOHelper.isPersistent(key)
072: || pm != JDOHelper.getPersistenceManager(key))
073: return false;
074: }
075:
076: return true;
077: }
078:
079: protected boolean validateValueForReading(StateManager sm,
080: Object value) {
081: if (!valuesAreEmbedded) {
082: PersistenceManager pm = sm.getPersistenceManager();
083:
084: if (!JDOHelper.isPersistent(value)
085: || pm != JDOHelper.getPersistenceManager(value))
086: return false;
087: }
088:
089: return true;
090: }
091:
092: protected void validateKeyForWriting(StateManager sm, Object key) {
093: if (!keysAreEmbedded) {
094: PersistenceManager pm = sm.getPersistenceManager();
095:
096: if (!JDOHelper.isPersistent(key))
097: pm.makePersistent(key);
098: else if (pm != JDOHelper.getPersistenceManager(key))
099: throw new JDOUserException(
100: "Can't write key from a different persistence manager",
101: JDOHelper.getObjectId(key));
102: }
103: }
104:
105: protected void validateValueForWriting(StateManager sm, Object value) {
106: if (!valuesAreEmbedded) {
107: PersistenceManager pm = sm.getPersistenceManager();
108:
109: if (!JDOHelper.isPersistent(value))
110: pm.makePersistent(value);
111: else if (pm != JDOHelper.getPersistenceManager(value))
112: throw new JDOUserException(
113: "Can't write value from a different persistence manager",
114: JDOHelper.getObjectId(value));
115: }
116: }
117:
118: public Map load(StateManager sm) {
119: HashMap contents = new HashMap();
120: PersistenceManager pm = sm.getPersistenceManager();
121:
122: try {
123: Connection conn = pm.getConnection(false);
124:
125: try {
126: PreparedStatement ps = conn.prepareStatement(loadStmt);
127:
128: try {
129: ownerMapping.setObject(pm, ps, 1, sm.getObject());
130:
131: long startTime = System.currentTimeMillis();
132:
133: ResultSet rs = ps.executeQuery();
134:
135: try {
136: if (LOG.isDebugEnabled())
137: LOG
138: .debug("Time = "
139: + (System
140: .currentTimeMillis() - startTime)
141: + " ms: " + loadStmt);
142:
143: while (rs.next())
144: contents.put(keyMapping
145: .getObject(pm, rs, 1), valueMapping
146: .getObject(pm, rs, 2));
147: } finally {
148: rs.close();
149: }
150: } finally {
151: ps.close();
152: }
153: } finally {
154: pm.releaseConnection(conn);
155: }
156: } catch (SQLException e) {
157: throw dba.newDataStoreException("Load request failed: "
158: + loadStmt, e);
159: }
160:
161: return contents;
162: }
163:
164: public int size(StateManager sm) {
165: int numRows;
166: PersistenceManager pm = sm.getPersistenceManager();
167:
168: try {
169: Connection conn = pm.getConnection(false);
170:
171: try {
172: PreparedStatement ps = conn.prepareStatement(sizeStmt);
173:
174: try {
175: ownerMapping.setObject(pm, ps, 1, sm.getObject());
176:
177: long startTime = System.currentTimeMillis();
178:
179: ResultSet rs = ps.executeQuery();
180:
181: try {
182: if (LOG.isDebugEnabled())
183: LOG
184: .debug("Time = "
185: + (System
186: .currentTimeMillis() - startTime)
187: + " ms: " + sizeStmt);
188:
189: if (!rs.next())
190: throw new JDODataStoreException(
191: "Size request returned no result row: "
192: + sizeStmt);
193:
194: numRows = rs.getInt(1);
195:
196: storeMgr.logSQLWarnings(rs);
197: } finally {
198: rs.close();
199: }
200: } finally {
201: ps.close();
202: }
203: } finally {
204: pm.releaseConnection(conn);
205: }
206: } catch (SQLException e) {
207: throw dba.newDataStoreException("Size request failed: "
208: + sizeStmt, e);
209: }
210:
211: return numRows;
212: }
213:
214: public boolean isEmpty(StateManager sm) {
215: /* There are probably more efficient ways of doing this in SQL. */
216: return size(sm) == 0;
217: }
218:
219: protected Object get0(StateManager sm, Object key)
220: throws NoSuchElementException {
221: if (!validateKeyForReading(sm, key))
222: return null;
223:
224: Object value;
225: PersistenceManager pm = sm.getPersistenceManager();
226:
227: try {
228: Connection conn = pm.getConnection(false);
229:
230: try {
231: PreparedStatement ps = conn.prepareStatement(getStmt);
232:
233: try {
234: ownerMapping.setObject(pm, ps, 1, sm.getObject());
235: keyMapping.setObject(pm, ps, 2, key);
236:
237: long startTime = System.currentTimeMillis();
238:
239: ResultSet rs = ps.executeQuery();
240:
241: try {
242: if (LOG.isDebugEnabled())
243: LOG
244: .debug("Time = "
245: + (System
246: .currentTimeMillis() - startTime)
247: + " ms: " + getStmt);
248:
249: if (!rs.next())
250: throw new NoSuchElementException();
251:
252: value = valueMapping.getObject(pm, rs, 1);
253:
254: storeMgr.logSQLWarnings(rs);
255: } finally {
256: rs.close();
257: }
258: } finally {
259: ps.close();
260: }
261: } finally {
262: pm.releaseConnection(conn);
263: }
264: } catch (SQLException e) {
265: throw dba.newDataStoreException("Get request failed: "
266: + getStmt, e);
267: }
268:
269: return value;
270: }
271:
272: public boolean containsKey(StateManager sm, Object key) {
273: try {
274: get0(sm, key);
275: return true;
276: } catch (NoSuchElementException e) {
277: return false;
278: }
279: }
280:
281: public boolean containsValue(StateManager sm, Object value) {
282: if (!validateValueForReading(sm, value))
283: return false;
284:
285: boolean exists = false;
286: PersistenceManager pm = sm.getPersistenceManager();
287:
288: try {
289: Connection conn = pm.getConnection(false);
290:
291: try {
292: PreparedStatement ps = conn
293: .prepareStatement(containsValueStmt);
294:
295: try {
296: ownerMapping.setObject(pm, ps, 1, sm.getObject());
297: valueMapping.setObject(pm, ps, 2, value);
298:
299: long startTime = System.currentTimeMillis();
300:
301: ResultSet rs = ps.executeQuery();
302:
303: try {
304: if (LOG.isDebugEnabled())
305: LOG
306: .debug("Time = "
307: + (System
308: .currentTimeMillis() - startTime)
309: + " ms: "
310: + containsValueStmt);
311:
312: if (rs.next())
313: exists = true;
314:
315: storeMgr.logSQLWarnings(rs);
316: } finally {
317: rs.close();
318: }
319: } finally {
320: ps.close();
321: }
322: } finally {
323: pm.releaseConnection(conn);
324: }
325: } catch (SQLException e) {
326: throw dba.newDataStoreException(
327: "containsValue request failed: "
328: + containsValueStmt, e);
329: }
330:
331: return exists;
332: }
333:
334: public boolean containsEntry(StateManager sm, Object key,
335: Object value) {
336: if (!validateKeyForReading(sm, value))
337: return false;
338: if (!validateValueForReading(sm, value))
339: return false;
340:
341: boolean exists = false;
342: PersistenceManager pm = sm.getPersistenceManager();
343:
344: try {
345: Connection conn = pm.getConnection(false);
346:
347: try {
348: PreparedStatement ps = conn
349: .prepareStatement(containsEntryStmt);
350:
351: try {
352: ownerMapping.setObject(pm, ps, 1, sm.getObject());
353: keyMapping.setObject(pm, ps, 2, value);
354: valueMapping.setObject(pm, ps, 3, value);
355:
356: long startTime = System.currentTimeMillis();
357:
358: ResultSet rs = ps.executeQuery();
359:
360: try {
361: if (LOG.isDebugEnabled())
362: LOG
363: .debug("Time = "
364: + (System
365: .currentTimeMillis() - startTime)
366: + " ms: "
367: + containsEntryStmt);
368:
369: if (rs.next())
370: exists = true;
371:
372: storeMgr.logSQLWarnings(rs);
373: } finally {
374: rs.close();
375: }
376: } finally {
377: ps.close();
378: }
379: } finally {
380: pm.releaseConnection(conn);
381: }
382: } catch (SQLException e) {
383: throw dba.newDataStoreException(
384: "containsEntry request failed: "
385: + containsEntryStmt, e);
386: }
387:
388: return exists;
389: }
390:
391: public Object get(StateManager sm, Object key) {
392: try {
393: return get0(sm, key);
394: } catch (NoSuchElementException e) {
395: return null;
396: }
397: }
398:
399: public void putAll(StateManager sm, Map m) {
400: Iterator i = m.entrySet().iterator();
401:
402: while (i.hasNext()) {
403: Map.Entry e = (Map.Entry) i.next();
404: put(sm, e.getKey(), e.getValue());
405: }
406: }
407:
408: public void clear(StateManager sm) {
409: PersistenceManager pm = sm.getPersistenceManager();
410:
411: try {
412: Connection conn = pm.getConnection(true);
413:
414: try {
415: PreparedStatement ps = conn.prepareStatement(clearStmt);
416:
417: try {
418: ownerMapping.setObject(pm, ps, 1, sm.getObject());
419:
420: long startTime = System.currentTimeMillis();
421:
422: ps.executeUpdate();
423:
424: if (LOG.isDebugEnabled())
425: LOG
426: .debug("Time = "
427: + (System.currentTimeMillis() - startTime)
428: + " ms: " + clearStmt);
429: } finally {
430: ps.close();
431: }
432: } finally {
433: pm.releaseConnection(conn);
434: }
435: } catch (SQLException e) {
436: throw dba.newDataStoreException("Clear request failed: "
437: + clearStmt, e);
438: }
439: }
440:
441: public Queryable keySetQuery(StateManager sm) {
442: throw new JDOUnsupportedOptionException(
443: "Cannot query sets obtained by Map.keySet() (yet)");
444: }
445:
446: public Queryable valuesQuery(StateManager sm) {
447: throw new JDOUnsupportedOptionException(
448: "Cannot query sets obtained by Map.values() (yet)");
449: }
450:
451: public Queryable entrySetQuery(StateManager sm) {
452: throw new JDOUnsupportedOptionException(
453: "Cannot query sets obtained by Map.entrySet() (yet)");
454: }
455: }
|