001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: * $Header:$
018: */
019:
020: package org.apache.beehive.controls.system.jdbc;
021:
022: import org.apache.beehive.controls.api.ControlException;
023: import org.apache.beehive.controls.api.context.ControlBeanContext;
024: import org.apache.beehive.controls.system.jdbc.JdbcControl.SQL;
025:
026: import java.lang.reflect.Method;
027: import java.lang.reflect.Array;
028: import java.sql.ResultSet;
029: import java.sql.ResultSetMetaData;
030: import java.sql.SQLException;
031: import java.util.ArrayList;
032: import java.util.Calendar;
033:
034: /**
035: * Default ResultSetMapper implementation for Objects.
036: */
037: public class DefaultObjectResultSetMapper extends ResultSetMapper {
038:
039: /**
040: * static reference to the TypeMappingsFactory for this class
041: */
042: protected static final TypeMappingsFactory _tmf = TypeMappingsFactory
043: .getInstance();
044:
045: /**
046: * Map the ResultSet to the method's return type. The object type returned is defined by the return type of the method.
047: *
048: * @param context A ControlBeanContext instance, see Beehive controls javadoc for additional information
049: * @param m Method assoicated with this call.
050: * @param resultSet Result set to map.
051: * @param cal A Calendar instance for time/date value resolution.
052: * @return The Object resulting from the ResultSet
053: */
054: public Object mapToResultType(ControlBeanContext context, Method m,
055: ResultSet resultSet, Calendar cal) {
056:
057: final Class returnType = m.getReturnType();
058: final boolean isArray = returnType.isArray();
059:
060: try {
061: if (isArray) {
062: final SQL methodSQL = context.getMethodPropertySet(m,
063: SQL.class);
064: return arrayFromResultSet(resultSet, methodSQL
065: .arrayMaxLength(), returnType, cal);
066: } else {
067: if (!resultSet.next()) {
068: return _tmf.fixNull(m.getReturnType());
069: }
070: return RowMapperFactory.getRowMapper(resultSet,
071: returnType, cal).mapRowToReturnType();
072: }
073: } catch (SQLException e) {
074: throw new ControlException(e.getMessage(), e);
075: }
076: }
077:
078: //
079: // ////////////////////////////////// PRIVATE METHODS //////////////////////////////////////////
080: //
081:
082: /**
083: * Invoked when the return type of the method is an array type.
084: *
085: * @param rs ResultSet to process.
086: * @param maxRows The maximum size of array to create, a value of 0 indicates that the array
087: * size will be the same as the result set size (no limit).
088: * @param arrayClass The class of object contained within the array
089: * @param cal A calendar instance to use for date/time values
090: * @return An array of the specified class type
091: * @throws SQLException On error.
092: */
093: protected Object arrayFromResultSet(ResultSet rs, int maxRows,
094: Class arrayClass, Calendar cal) throws SQLException {
095:
096: ArrayList<Object> list = new ArrayList<Object>();
097: Class componentType = arrayClass.getComponentType();
098: RowMapper rowMapper = RowMapperFactory.getRowMapper(rs,
099: componentType, cal);
100:
101: // a value of zero indicates that all rows from the resultset should be included.
102: if (maxRows == 0) {
103: maxRows = -1;
104: }
105:
106: int numRows;
107: boolean hasMoreRows = rs.next();
108: for (numRows = 0; numRows != maxRows && hasMoreRows; numRows++) {
109: list.add(rowMapper.mapRowToReturnType());
110: hasMoreRows = rs.next();
111: }
112:
113: Object array = Array.newInstance(componentType, numRows);
114: try {
115: for (int i = 0; i < numRows; i++) {
116: Array.set(array, i, list.get(i));
117: }
118: } catch (IllegalArgumentException iae) {
119: ResultSetMetaData md = rs.getMetaData();
120: // assuming no errors in resultSetObject() this can only happen
121: // for single column result sets.
122: throw new ControlException(
123: "The declared Java type for array "
124: + componentType.getName()
125: + "is incompatible with the SQL format of column "
126: + md.getColumnName(1)
127: + md.getColumnTypeName(1)
128: + "which returns objects of type + "
129: + list.get(0).getClass().getName());
130: }
131: return array;
132: }
133: }
|