001: /*
002: * Copyright 2002 (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: QueryResult.java,v 1.5 2003/10/10 22:22:15 pierreg0 Exp $
009: */
010:
011: package com.triactive.jdo.store;
012:
013: import java.sql.ResultSet;
014: import java.sql.SQLException;
015: import java.util.AbstractCollection;
016: import java.util.ArrayList;
017: import java.util.Collection;
018: import java.util.Iterator;
019: import java.util.NoSuchElementException;
020: import javax.jdo.JDODataStoreException;
021: import javax.jdo.JDOUserException;
022:
023: public final class QueryResult extends AbstractCollection {
024: private final Query query;
025: private final Query.ResultObjectFactory rof;
026: private ResultSet rs;
027: private final StoreManager storeMgr;
028:
029: private boolean moreResultSetRows;
030: private ArrayList resultObjs = new ArrayList();
031:
032: public QueryResult(Query query, Query.ResultObjectFactory rof,
033: ResultSet rs) throws SQLException {
034: this .query = query;
035: this .rof = rof;
036: this .rs = rs;
037:
038: storeMgr = query.getStoreManager();
039:
040: if (!(moreResultSetRows = rs.next()))
041: closeResultSet();
042: else if (!query.getPersistenceManager().currentTransaction()
043: .isActive())
044: advanceToEndOfResultSet();
045: }
046:
047: private void advanceToEndOfResultSet() {
048: /* Advance through any remaining result set rows. */
049: while (moreResultSetRows)
050: nextResultSetElement();
051: }
052:
053: private boolean isOpen() {
054: return resultObjs != null;
055: }
056:
057: private void assertIsOpen() {
058: if (!isOpen())
059: throw new JDOUserException("Query result has been closed");
060: }
061:
062: private Object nextResultSetElement() {
063: Object nextElement = rof.getObject(rs);
064:
065: storeMgr.logSQLWarnings(rs);
066:
067: resultObjs.add(nextElement);
068:
069: try {
070: if (!(moreResultSetRows = rs.next()))
071: closeResultSet();
072: } catch (SQLException e) {
073: throw storeMgr.getDatabaseAdapter().newDataStoreException(
074: "Failed reading result set", e);
075: }
076:
077: return nextElement;
078: }
079:
080: public Iterator iterator() {
081: assertIsOpen();
082:
083: return new QueryResultIterator();
084: }
085:
086: private class QueryResultIterator implements Iterator {
087: private int nextRowNum = 0;
088:
089: public QueryResultIterator() {
090: }
091:
092: public boolean hasNext() {
093: synchronized (QueryResult.this ) {
094: if (!isOpen())
095: return false;
096:
097: return nextRowNum < resultObjs.size() ? true
098: : moreResultSetRows;
099: }
100: }
101:
102: public Object next() {
103: synchronized (QueryResult.this ) {
104: if (!isOpen())
105: throw new NoSuchElementException(
106: "This query result has been closed");
107:
108: Object nextElement = null;
109:
110: if (nextRowNum < resultObjs.size())
111: nextElement = resultObjs.get(nextRowNum);
112: else if (moreResultSetRows)
113: nextElement = nextResultSetElement();
114: else
115: throw new NoSuchElementException(
116: "No more elements in query result");
117:
118: ++nextRowNum;
119:
120: return nextElement;
121: }
122: }
123:
124: public void remove() {
125: throw new UnsupportedOperationException(
126: "Query result sets are not modifiable");
127: }
128: }
129:
130: public synchronized boolean contains(Object o) {
131: assertIsOpen();
132: advanceToEndOfResultSet();
133:
134: return resultObjs.contains(o);
135: }
136:
137: public synchronized boolean containsAll(Collection c) {
138: assertIsOpen();
139: advanceToEndOfResultSet();
140:
141: return resultObjs.containsAll(c);
142: }
143:
144: public synchronized boolean isEmpty() {
145: assertIsOpen();
146:
147: return resultObjs.isEmpty() && !moreResultSetRows;
148: }
149:
150: public synchronized int size() {
151: assertIsOpen();
152: advanceToEndOfResultSet();
153:
154: return resultObjs.size();
155: }
156:
157: public synchronized Object[] toArray() {
158: assertIsOpen();
159: advanceToEndOfResultSet();
160:
161: return resultObjs.toArray();
162: }
163:
164: public synchronized Object[] toArray(Object[] a) {
165: assertIsOpen();
166: advanceToEndOfResultSet();
167:
168: return resultObjs.toArray(a);
169: }
170:
171: private void closeResultSet() {
172: if (rs != null) {
173: try {
174: try {
175: rs.getStatement().close();
176: } catch (SQLException e) {
177: throw storeMgr.getDatabaseAdapter()
178: .newDataStoreException(
179: "Closing query result failed", e);
180: }
181: } finally {
182: rs = null;
183: }
184: }
185: }
186:
187: public synchronized void close() {
188: resultObjs = null;
189: moreResultSetRows = false;
190:
191: closeResultSet();
192: }
193: }
|