blob: 346e4e474a2f3e73e11e9f4cc28a1d972fe32cfe [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.jdbc.kernel;
import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Array;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Ref;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import java.util.Stack;
import org.apache.openjpa.jdbc.meta.ClassMapping;
import org.apache.openjpa.jdbc.meta.FieldMapping;
import org.apache.openjpa.jdbc.meta.JavaSQLTypes;
import org.apache.openjpa.jdbc.meta.QueryResultMapping;
import org.apache.openjpa.jdbc.schema.Column;
import org.apache.openjpa.jdbc.sql.AbstractResult;
import org.apache.openjpa.jdbc.sql.Joins;
import org.apache.openjpa.jdbc.sql.Result;
import org.apache.openjpa.jdbc.sql.SQLExceptions;
import org.apache.openjpa.lib.rop.ResultObjectProvider;
import org.apache.openjpa.util.StoreException;
import org.apache.openjpa.util.UnsupportedException;
/**
* Provides the data from query result mapped by a {@link QueryResultMapping}.
*
* @author Pinaki Poddar
* @author Abe White
*/
class MappedQueryResultObjectProvider
implements ResultObjectProvider {
private final QueryResultMapping _map;
private final JDBCStore _store;
private final JDBCFetchConfiguration _fetch;
private final MappingResult _mres;
/**
* Constructor.
*
* @param res the result data
*/
public MappedQueryResultObjectProvider(QueryResultMapping map,
JDBCStore store, JDBCFetchConfiguration fetch, Result res) {
_map = map;
_store = store;
_fetch = (fetch == null) ? store.getFetchConfiguration() : fetch;
_mres = new MappingResult(res);
}
public boolean supportsRandomAccess() {
try {
return _mres.supportsRandomAccess();
} catch (Throwable t) {
return false;
}
}
public void open() {
}
public Object getResultObject()
throws SQLException {
QueryResultMapping.PCResult[] pcs = _map.getPCResults();
Object[] cols = _map.getColumnResults();
// single object cases
if (pcs.length == 0 && cols.length == 1)
return _mres.getObject(cols[0], JavaSQLTypes.JDBC_DEFAULT, null);
if (pcs.length == 1 && cols.length == 0)
return _mres.load(pcs[0], _store, _fetch);
// multiple objects
Object[] ret = new Object[pcs.length + cols.length];
for (int i = 0; i < pcs.length; i++)
ret[i] = _mres.load(pcs[i], _store, _fetch);
for (int i = 0; i < cols.length; i++)
ret[pcs.length + i] = _mres.getObject(cols[i],
JavaSQLTypes.JDBC_DEFAULT, null);
return ret;
}
public boolean next()
throws SQLException {
return _mres.next();
}
public boolean absolute(int pos)
throws SQLException {
return _mres.absolute(pos);
}
public int size()
throws SQLException {
if (_fetch.getLRSSize() == LRSSizes.SIZE_UNKNOWN
|| !supportsRandomAccess())
return Integer.MAX_VALUE;
return _mres.size();
}
public void reset() {
throw new UnsupportedException();
}
public void close() {
_mres.close();
}
public void handleCheckedException(Exception e) {
if (e instanceof SQLException)
throw SQLExceptions.getStore((SQLException) e,
_store.getDBDictionary());
throw new StoreException(e);
}
/**
* Result type that maps requests using a given
* {@link QueryResultMapping.PCResult}.
*/
private static class MappingResult
extends AbstractResult {
private final Result _res;
private final Stack _requests = new Stack();
private QueryResultMapping.PCResult _pc = null;
/**
* Supply delegate on construction.
*/
public MappingResult(Result res) {
_res = res;
}
/**
* Load an instance of the given type. Should be used in place of
* {@link Result#load}.
*/
public Object load(QueryResultMapping.PCResult pc, JDBCStore store,
JDBCFetchConfiguration fetch)
throws SQLException {
_pc = pc;
try {
return load(pc.getCandidateTypeMapping(), store, fetch);
} finally {
_pc = null;
}
}
public Object load(ClassMapping mapping, JDBCStore store,
JDBCFetchConfiguration fetch)
throws SQLException {
return load(mapping, store, fetch, null);
}
public Object load(ClassMapping mapping, JDBCStore store,
JDBCFetchConfiguration fetch, Joins joins)
throws SQLException {
if (_pc == null)
return super.load(mapping, store, fetch, joins);
// we go direct to the store manager so we can tell it not to load
// anything additional
return ((JDBCStoreManager) store).load(mapping, fetch,
_pc.getExcludes(_requests), this);
}
public Object getEager(FieldMapping key) {
Object ret = _res.getEager(key);
if (_pc == null || ret != null)
return ret;
return (_pc.hasEager(_requests, key)) ? this : null;
}
public void putEager(FieldMapping key, Object res) {
_res.putEager(key, res);
}
public void close() {
_res.close();
}
public Joins newJoins() {
return _res.newJoins();
}
public boolean supportsRandomAccess()
throws SQLException {
return _res.supportsRandomAccess();
}
public ClassMapping getBaseMapping() {
return _res.getBaseMapping();
}
public int size()
throws SQLException {
return _res.size();
}
public void startDataRequest(Object mapping) {
_requests.push(mapping);
}
public void endDataRequest() {
_requests.pop();
}
public boolean wasNull()
throws SQLException {
return _res.wasNull();
}
protected Object translate(Object obj, Joins joins) {
return (_pc == null) ? obj : _pc.map(_requests, obj, joins);
}
protected boolean absoluteInternal(int row)
throws SQLException {
return _res.absolute(row);
}
protected boolean nextInternal()
throws SQLException {
return _res.next();
}
protected boolean containsInternal(Object obj, Joins joins)
throws SQLException {
return _res.contains(translate(obj, joins));
}
protected Array getArrayInternal(Object obj, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getArray((Column) obj, joins);
return _res.getArray(obj);
}
protected InputStream getAsciiStreamInternal(Object obj, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getAsciiStream((Column) obj, joins);
return _res.getAsciiStream(obj);
}
protected BigDecimal getBigDecimalInternal(Object obj, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getBigDecimal((Column) obj, joins);
return _res.getBigDecimal(obj);
}
protected Number getNumberInternal(Object obj, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getNumber((Column) obj, joins);
return _res.getNumber(obj);
}
protected BigInteger getBigIntegerInternal(Object obj, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getBigInteger((Column) obj, joins);
return _res.getBigInteger(obj);
}
protected InputStream getBinaryStreamInternal(Object obj, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getBinaryStream((Column) obj, joins);
return _res.getBinaryStream(obj);
}
protected Blob getBlobInternal(Object obj, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getBlob((Column) obj, joins);
return _res.getBlob(obj);
}
protected boolean getBooleanInternal(Object obj, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getBoolean((Column) obj, joins);
return _res.getBoolean(obj);
}
protected byte getByteInternal(Object obj, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getByte((Column) obj, joins);
return _res.getByte(obj);
}
protected byte[] getBytesInternal(Object obj, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getBytes((Column) obj, joins);
return _res.getBytes(obj);
}
protected Calendar getCalendarInternal(Object obj, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getCalendar((Column) obj, joins);
return _res.getCalendar(obj);
}
protected char getCharInternal(Object obj, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getChar((Column) obj, joins);
return _res.getChar(obj);
}
protected Reader getCharacterStreamInternal(Object obj, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getCharacterStream((Column) obj, joins);
return _res.getCharacterStream(obj);
}
protected Clob getClobInternal(Object obj, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getClob((Column) obj, joins);
return _res.getClob(obj);
}
protected Date getDateInternal(Object obj, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getDate((Column) obj, joins);
return _res.getDate(obj);
}
protected java.sql.Date getDateInternal(Object obj, Calendar cal,
Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getDate((Column) obj, cal, joins);
return _res.getDate(obj, cal);
}
protected double getDoubleInternal(Object obj, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getDouble((Column) obj, joins);
return _res.getDouble(obj);
}
protected float getFloatInternal(Object obj, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getFloat((Column) obj, joins);
return _res.getFloat(obj);
}
protected int getIntInternal(Object obj, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getInt((Column) obj, joins);
return _res.getInt(obj);
}
protected Locale getLocaleInternal(Object obj, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getLocale((Column) obj, joins);
return _res.getLocale(obj);
}
protected long getLongInternal(Object obj, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getLong((Column) obj, joins);
return _res.getLong(obj);
}
protected Object getObjectInternal(Object obj, int metaTypeCode,
Object arg, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getObject((Column) obj, arg, joins);
return _res.getObject(obj, metaTypeCode, arg);
}
protected Object getSQLObjectInternal(Object obj, Map map, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getSQLObject((Column) obj, map, joins);
return _res.getSQLObject(obj, map);
}
protected Object getStreamInternal(JDBCStore store, Object obj,
int metaTypeCode, Object arg, Joins joins) throws SQLException {
if (obj instanceof Column)
return _res.getObject((Column) obj, arg, joins);
return _res.getObject(obj, metaTypeCode, arg);
}
protected Ref getRefInternal(Object obj, Map map, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getRef((Column) obj, map, joins);
return _res.getRef(obj, map);
}
protected short getShortInternal(Object obj, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getShort((Column) obj, joins);
return _res.getShort(obj);
}
protected String getStringInternal(Object obj, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getString((Column) obj, joins);
return _res.getString(obj);
}
protected Time getTimeInternal(Object obj, Calendar cal, Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getTime((Column) obj, cal, joins);
return _res.getTime(obj, cal);
}
protected Timestamp getTimestampInternal(Object obj, Calendar cal,
Joins joins)
throws SQLException {
if (obj instanceof Column)
return _res.getTimestamp((Column) obj, cal, joins);
return _res.getTimestamp(obj, cal);
}
}
}