/*
   * (non-Javadoc)
   *
   * @see org.seasar.extension.jdbc.ResultSetHandler#handle(java.sql.ResultSet)
   */
  @SuppressWarnings("unchecked")
  public Object handle(ResultSet rs) throws SQLException {
    // Set<String(columnName)>
    final Set columnNames = createColumnNames(rs.getMetaData());

    // Map<String(columnName), PropertyType>
    Map propertyCache = null; // [DAO-118] (2007/08/26)

    // Map<String(relationNoSuffix), Map<String(columnName), PropertyType>>
    Map relationPropertyCache = null; // [DAO-118] (2007/08/25)

    final int relSize = getBeanMetaData().getRelationPropertyTypeSize();
    final RelationRowCache relRowCache = new RelationRowCache(relSize);

    int count = 0;
    while (rs.next()) {
      // Lazy initialization because if the result is zero, the cache is
      // unused.
      if (propertyCache == null) {
        propertyCache = createPropertyCache(columnNames);
      }
      if (relationPropertyCache == null) {
        relationPropertyCache = createRelationPropertyCache(columnNames);
      }

      // Create row instance of base table by row property cache.
      final Object row = createRow(rs, propertyCache);

      for (int i = 0; i < relSize; ++i) {
        RelationPropertyType rpt = getBeanMetaData().getRelationPropertyType(i);
        if (rpt == null) {
          continue;
        }
        Object relationRow = null;
        Map relKeyValues = new HashMap();
        // TODO 1レコード目でnullが返るなら、2レコード目以降は不要では?
        RelationKey relKey = createRelationKey(rs, rpt, columnNames, relKeyValues);
        if (relKey != null) {
          relationRow = relRowCache.getRelationRow(i, relKey);
          if (relationRow == null) {
            relationRow =
                createRelationRow(rs, rpt, columnNames, relKeyValues, relationPropertyCache);
            relRowCache.addRelationRow(i, relKey, relationRow);
          }
        }
        if (relationRow != null) {
          PropertyDesc pd = rpt.getPropertyDesc();
          pd.setValue(row, relationRow);
          postCreateRow(relationRow);
        }
      }
      postCreateRow(row);
      count++;
      if (!fetchHandler.execute(row)) {
        break;
      }
    }
    return Integer.valueOf(count);
  }