001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019: package org.apache.openjpa.jdbc.kernel;
020:
021: import java.io.InputStream;
022: import java.io.Reader;
023: import java.math.BigDecimal;
024: import java.math.BigInteger;
025: import java.sql.Array;
026: import java.sql.Blob;
027: import java.sql.Clob;
028: import java.sql.Ref;
029: import java.sql.SQLException;
030: import java.sql.Time;
031: import java.sql.Timestamp;
032: import java.util.Calendar;
033: import java.util.Date;
034: import java.util.Locale;
035: import java.util.Map;
036: import java.util.Stack;
037:
038: import org.apache.openjpa.jdbc.meta.ClassMapping;
039: import org.apache.openjpa.jdbc.meta.FieldMapping;
040: import org.apache.openjpa.jdbc.meta.JavaSQLTypes;
041: import org.apache.openjpa.jdbc.meta.QueryResultMapping;
042: import org.apache.openjpa.jdbc.schema.Column;
043: import org.apache.openjpa.jdbc.sql.AbstractResult;
044: import org.apache.openjpa.jdbc.sql.Joins;
045: import org.apache.openjpa.jdbc.sql.Result;
046: import org.apache.openjpa.jdbc.sql.SQLExceptions;
047: import org.apache.openjpa.lib.rop.ResultObjectProvider;
048: import org.apache.openjpa.util.StoreException;
049: import org.apache.openjpa.util.UnsupportedException;
050:
051: /**
052: * Provides the data from query result mapped by a {@link QueryResultMapping}.
053: *
054: * @author Pinaki Poddar
055: * @author Abe White
056: */
057: class MappedQueryResultObjectProvider implements ResultObjectProvider {
058:
059: private final QueryResultMapping _map;
060: private final JDBCStore _store;
061: private final JDBCFetchConfiguration _fetch;
062: private final MappingResult _mres;
063:
064: /**
065: * Constructor.
066: *
067: * @param res the result data
068: */
069: public MappedQueryResultObjectProvider(QueryResultMapping map,
070: JDBCStore store, JDBCFetchConfiguration fetch, Result res) {
071: _map = map;
072: _store = store;
073: _fetch = (fetch == null) ? store.getFetchConfiguration()
074: : fetch;
075: _mres = new MappingResult(res);
076: }
077:
078: public boolean supportsRandomAccess() {
079: try {
080: return _mres.supportsRandomAccess();
081: } catch (Throwable t) {
082: return false;
083: }
084: }
085:
086: public void open() {
087: }
088:
089: public Object getResultObject() throws SQLException {
090: QueryResultMapping.PCResult[] pcs = _map.getPCResults();
091: Object[] cols = _map.getColumnResults();
092:
093: // single object cases
094: if (pcs.length == 0 && cols.length == 1)
095: return _mres.getObject(cols[0], JavaSQLTypes.JDBC_DEFAULT,
096: null);
097: if (pcs.length == 1 && cols.length == 0)
098: return _mres.load(pcs[0], _store, _fetch);
099:
100: // multiple objects
101: Object[] ret = new Object[pcs.length + cols.length];
102: for (int i = 0; i < pcs.length; i++)
103: ret[i] = _mres.load(pcs[i], _store, _fetch);
104: for (int i = 0; i < cols.length; i++)
105: ret[pcs.length + i] = _mres.getObject(cols[i],
106: JavaSQLTypes.JDBC_DEFAULT, null);
107: return ret;
108: }
109:
110: public boolean next() throws SQLException {
111: return _mres.next();
112: }
113:
114: public boolean absolute(int pos) throws SQLException {
115: return _mres.absolute(pos);
116: }
117:
118: public int size() throws SQLException {
119: if (_fetch.getLRSSize() == LRSSizes.SIZE_UNKNOWN
120: || !supportsRandomAccess())
121: return Integer.MAX_VALUE;
122: return _mres.size();
123: }
124:
125: public void reset() {
126: throw new UnsupportedException();
127: }
128:
129: public void close() {
130: _mres.close();
131: }
132:
133: public void handleCheckedException(Exception e) {
134: if (e instanceof SQLException)
135: throw SQLExceptions.getStore((SQLException) e, _store
136: .getDBDictionary());
137: throw new StoreException(e);
138: }
139:
140: /**
141: * Result type that maps requests using a given
142: * {@link QueryResultMapping.PCResult}.
143: */
144: private static class MappingResult extends AbstractResult {
145:
146: private final Result _res;
147: private final Stack _requests = new Stack();
148: private QueryResultMapping.PCResult _pc = null;
149:
150: /**
151: * Supply delegate on construction.
152: */
153: public MappingResult(Result res) {
154: _res = res;
155: }
156:
157: /**
158: * Load an instance of the given type. Should be used in place of
159: * {@link Result#load}.
160: */
161: public Object load(QueryResultMapping.PCResult pc,
162: JDBCStore store, JDBCFetchConfiguration fetch)
163: throws SQLException {
164: _pc = pc;
165: try {
166: return load(pc.getCandidateTypeMapping(), store, fetch);
167: } finally {
168: _pc = null;
169: }
170: }
171:
172: public Object load(ClassMapping mapping, JDBCStore store,
173: JDBCFetchConfiguration fetch) throws SQLException {
174: return load(mapping, store, fetch, null);
175: }
176:
177: public Object load(ClassMapping mapping, JDBCStore store,
178: JDBCFetchConfiguration fetch, Joins joins)
179: throws SQLException {
180: if (_pc == null)
181: return super .load(mapping, store, fetch, joins);
182:
183: // we go direct to the store manager so we can tell it not to load
184: // anything additional
185: return ((JDBCStoreManager) store).load(mapping, fetch, _pc
186: .getExcludes(_requests), this );
187: }
188:
189: public Object getEager(FieldMapping key) {
190: Object ret = _res.getEager(key);
191: if (_pc == null || ret != null)
192: return ret;
193: return (_pc.hasEager(_requests, key)) ? this : null;
194: }
195:
196: public void putEager(FieldMapping key, Object res) {
197: _res.putEager(key, res);
198: }
199:
200: public void close() {
201: _res.close();
202: }
203:
204: public Joins newJoins() {
205: return _res.newJoins();
206: }
207:
208: public boolean supportsRandomAccess() throws SQLException {
209: return _res.supportsRandomAccess();
210: }
211:
212: public ClassMapping getBaseMapping() {
213: return _res.getBaseMapping();
214: }
215:
216: public int size() throws SQLException {
217: return _res.size();
218: }
219:
220: public void startDataRequest(Object mapping) {
221: _requests.push(mapping);
222: }
223:
224: public void endDataRequest() {
225: _requests.pop();
226: }
227:
228: public boolean wasNull() throws SQLException {
229: return _res.wasNull();
230: }
231:
232: protected Object translate(Object obj, Joins joins) {
233: return (_pc == null) ? obj : _pc.map(_requests, obj, joins);
234: }
235:
236: protected boolean absoluteInternal(int row) throws SQLException {
237: return _res.absolute(row);
238: }
239:
240: protected boolean nextInternal() throws SQLException {
241: return _res.next();
242: }
243:
244: protected boolean containsInternal(Object obj, Joins joins)
245: throws SQLException {
246: return _res.contains(translate(obj, joins));
247: }
248:
249: protected Array getArrayInternal(Object obj, Joins joins)
250: throws SQLException {
251: if (obj instanceof Column)
252: return _res.getArray((Column) obj, joins);
253: return _res.getArray(obj);
254: }
255:
256: protected InputStream getAsciiStreamInternal(Object obj,
257: Joins joins) throws SQLException {
258: if (obj instanceof Column)
259: return _res.getAsciiStream((Column) obj, joins);
260: return _res.getAsciiStream(obj);
261: }
262:
263: protected BigDecimal getBigDecimalInternal(Object obj,
264: Joins joins) throws SQLException {
265: if (obj instanceof Column)
266: return _res.getBigDecimal((Column) obj, joins);
267: return _res.getBigDecimal(obj);
268: }
269:
270: protected Number getNumberInternal(Object obj, Joins joins)
271: throws SQLException {
272: if (obj instanceof Column)
273: return _res.getNumber((Column) obj, joins);
274: return _res.getNumber(obj);
275: }
276:
277: protected BigInteger getBigIntegerInternal(Object obj,
278: Joins joins) throws SQLException {
279: if (obj instanceof Column)
280: return _res.getBigInteger((Column) obj, joins);
281: return _res.getBigInteger(obj);
282: }
283:
284: protected InputStream getBinaryStreamInternal(Object obj,
285: Joins joins) throws SQLException {
286: if (obj instanceof Column)
287: return _res.getBinaryStream((Column) obj, joins);
288: return _res.getBinaryStream(obj);
289: }
290:
291: protected Blob getBlobInternal(Object obj, Joins joins)
292: throws SQLException {
293: if (obj instanceof Column)
294: return _res.getBlob((Column) obj, joins);
295: return _res.getBlob(obj);
296: }
297:
298: protected boolean getBooleanInternal(Object obj, Joins joins)
299: throws SQLException {
300: if (obj instanceof Column)
301: return _res.getBoolean((Column) obj, joins);
302: return _res.getBoolean(obj);
303: }
304:
305: protected byte getByteInternal(Object obj, Joins joins)
306: throws SQLException {
307: if (obj instanceof Column)
308: return _res.getByte((Column) obj, joins);
309: return _res.getByte(obj);
310: }
311:
312: protected byte[] getBytesInternal(Object obj, Joins joins)
313: throws SQLException {
314: if (obj instanceof Column)
315: return _res.getBytes((Column) obj, joins);
316: return _res.getBytes(obj);
317: }
318:
319: protected Calendar getCalendarInternal(Object obj, Joins joins)
320: throws SQLException {
321: if (obj instanceof Column)
322: return _res.getCalendar((Column) obj, joins);
323: return _res.getCalendar(obj);
324: }
325:
326: protected char getCharInternal(Object obj, Joins joins)
327: throws SQLException {
328: if (obj instanceof Column)
329: return _res.getChar((Column) obj, joins);
330: return _res.getChar(obj);
331: }
332:
333: protected Reader getCharacterStreamInternal(Object obj,
334: Joins joins) throws SQLException {
335: if (obj instanceof Column)
336: return _res.getCharacterStream((Column) obj, joins);
337: return _res.getCharacterStream(obj);
338: }
339:
340: protected Clob getClobInternal(Object obj, Joins joins)
341: throws SQLException {
342: if (obj instanceof Column)
343: return _res.getClob((Column) obj, joins);
344: return _res.getClob(obj);
345: }
346:
347: protected Date getDateInternal(Object obj, Joins joins)
348: throws SQLException {
349: if (obj instanceof Column)
350: return _res.getDate((Column) obj, joins);
351: return _res.getDate(obj);
352: }
353:
354: protected java.sql.Date getDateInternal(Object obj,
355: Calendar cal, Joins joins) throws SQLException {
356: if (obj instanceof Column)
357: return _res.getDate((Column) obj, cal, joins);
358: return _res.getDate(obj, cal);
359: }
360:
361: protected double getDoubleInternal(Object obj, Joins joins)
362: throws SQLException {
363: if (obj instanceof Column)
364: return _res.getDouble((Column) obj, joins);
365: return _res.getDouble(obj);
366: }
367:
368: protected float getFloatInternal(Object obj, Joins joins)
369: throws SQLException {
370: if (obj instanceof Column)
371: return _res.getFloat((Column) obj, joins);
372: return _res.getFloat(obj);
373: }
374:
375: protected int getIntInternal(Object obj, Joins joins)
376: throws SQLException {
377: if (obj instanceof Column)
378: return _res.getInt((Column) obj, joins);
379: return _res.getInt(obj);
380: }
381:
382: protected Locale getLocaleInternal(Object obj, Joins joins)
383: throws SQLException {
384: if (obj instanceof Column)
385: return _res.getLocale((Column) obj, joins);
386: return _res.getLocale(obj);
387: }
388:
389: protected long getLongInternal(Object obj, Joins joins)
390: throws SQLException {
391: if (obj instanceof Column)
392: return _res.getLong((Column) obj, joins);
393: return _res.getLong(obj);
394: }
395:
396: protected Object getObjectInternal(Object obj,
397: int metaTypeCode, Object arg, Joins joins)
398: throws SQLException {
399: if (obj instanceof Column)
400: return _res.getObject((Column) obj, arg, joins);
401: return _res.getObject(obj, metaTypeCode, arg);
402: }
403:
404: protected Object getSQLObjectInternal(Object obj, Map map,
405: Joins joins) throws SQLException {
406: if (obj instanceof Column)
407: return _res.getSQLObject((Column) obj, map, joins);
408: return _res.getSQLObject(obj, map);
409: }
410:
411: protected Ref getRefInternal(Object obj, Map map, Joins joins)
412: throws SQLException {
413: if (obj instanceof Column)
414: return _res.getRef((Column) obj, map, joins);
415: return _res.getRef(obj, map);
416: }
417:
418: protected short getShortInternal(Object obj, Joins joins)
419: throws SQLException {
420: if (obj instanceof Column)
421: return _res.getShort((Column) obj, joins);
422: return _res.getShort(obj);
423: }
424:
425: protected String getStringInternal(Object obj, Joins joins)
426: throws SQLException {
427: if (obj instanceof Column)
428: return _res.getString((Column) obj, joins);
429: return _res.getString(obj);
430: }
431:
432: protected Time getTimeInternal(Object obj, Calendar cal,
433: Joins joins) throws SQLException {
434: if (obj instanceof Column)
435: return _res.getTime((Column) obj, cal, joins);
436: return _res.getTime(obj, cal);
437: }
438:
439: protected Timestamp getTimestampInternal(Object obj,
440: Calendar cal, Joins joins) throws SQLException {
441: if (obj instanceof Column)
442: return _res.getTimestamp((Column) obj, cal, joins);
443: return _res.getTimestamp(obj, cal);
444: }
445: }
446: }
|