/*
* Copyright (c) 1998-2011 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package javax.faces.model;
import javax.faces.*;
import java.util.*;
import java.sql.*;
public class ResultSetDataModel extends DataModel
{
private ResultSet _rs;
private ResultSetMetaData _metaData;
private DataMap _map;
private int _rowIndex = -1;
public ResultSetDataModel()
{
}
public ResultSetDataModel(ResultSet value)
{
_rs = value;
setRowIndex(0);
}
public int getRowCount()
{
return -1;
}
public Object getRowData()
{
if (_rs == null)
return null;
else if (isRowAvailable()) {
if (_map == null)
_map = new DataMap(_rs, getMetaData());
return _map;
}
else
throw new IllegalArgumentException();
}
public boolean isRowAvailable()
{
try {
return _rs != null && _rs.absolute(getRowIndex() + 1);
} catch (SQLException e) {
throw new FacesException(e);
}
}
public Object getWrappedData()
{
return _rs;
}
public void setWrappedData(Object data)
{
_rs = (ResultSet) data;
_metaData = null;
_map = null;
setRowIndex(0);
}
public int getRowIndex()
{
return _rowIndex;
}
public void setRowIndex(int index)
{
if (_rs != null && index < -1)
throw new IllegalArgumentException("rowIndex '" + index + "' cannot be less than -1.");
DataModelListener []listeners = getDataModelListeners();
if (listeners.length > 0 && _rs != null && _rowIndex != index) {
DataModelEvent event = new DataModelEvent(this, index, _rs);
for (int i = 0; i < listeners.length; i++) {
listeners[i].rowSelected(event);
}
}
_rowIndex = index;
}
private ResultSetMetaData getMetaData()
{
try {
if (_metaData == null) {
_metaData = _rs.getMetaData();
}
return _metaData;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
static class DataMap extends AbstractMap<String,Object> {
private ResultSet _rs;
private ResultSetMetaData _metaData;
private int _columnCount;
private Set<String> _keySet;
private Set<Entry<String,Object>> _entrySet;
DataMap(ResultSet resultSet, ResultSetMetaData metaData)
{
_rs = resultSet;
_metaData = metaData;
try {
_columnCount = _metaData.getColumnCount();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public Object get(Object key)
{
int column = getColumn(String.valueOf(key));
if (column < 0)
throw new IllegalArgumentException("'" + key + "' is an unknown column");
try {
return _rs.getObject(column + 1);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public Object remove(Object key)
{
throw new UnsupportedOperationException();
}
@Override
public void clear()
{
throw new UnsupportedOperationException();
}
public Set<String> keySet()
{
if (_keySet == null)
_keySet = new DataMapKeySet(_metaData);
return _keySet;
}
public Collection<Object> values()
{
return new DataMapValues(_rs, _columnCount);
}
@Override
public boolean containsKey(Object v)
{
String key = String.valueOf(v);
return getColumn(key) >= 0;
}
@Override
public Object put(String k, Object value)
{
try {
String key = String.valueOf(k);
int column = getColumn(key) + 1;
if (column <= 0)
throw new IllegalArgumentException();
_rs.updateObject(column, value);
return null;
} catch (SQLException e) {
throw new RuntimeException(e);
} catch (RuntimeException e) {
throw e;
}
}
public Set<Entry<String,Object>> entrySet()
{
if (_entrySet == null)
_entrySet = new DataMapEntrySet(_rs, _metaData);
return _entrySet;
}
private int getColumn(String key)
{
try {
for (int i = 0; i < _columnCount; i++) {
if (_metaData.getColumnName(i + 1).equalsIgnoreCase(key))
return i;
}
return -1;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
private static class DataMapKeySet
extends AbstractSet<String>
{
private ResultSetMetaData _metaData;
private int _columnCount;
DataMapKeySet(ResultSetMetaData metaData)
{
_metaData = metaData;
try {
_columnCount = _metaData.getColumnCount();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public int size()
{
return _columnCount;
}
@Override
public boolean contains(Object v)
{
try {
String key = String.valueOf(v);
for (int i = 0; i < _columnCount; i++) {
if (_metaData.getColumnName(i + 1).equalsIgnoreCase(key))
return true;
}
return false;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public boolean remove(Object key)
{
throw new UnsupportedOperationException();
}
public Iterator<String> iterator()
{
ArrayList<String> keys = new ArrayList<String>();
try {
for (int i = 0; i < _columnCount; i++) {
keys.add(_metaData.getColumnName(i + 1));
}
return Collections.unmodifiableList(keys).iterator();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
private static class DataMapValues
extends AbstractCollection
{
private ResultSet _rs;
private int _columnCount;
DataMapValues(ResultSet rs, int columnCount)
{
_rs = rs;
_columnCount = columnCount;
}
public int size()
{
return _columnCount;
}
@Override
public boolean contains(Object v)
{
try {
if (v == null)
return false;
for (int i = 0; i < _columnCount; i++) {
if (v.equals(_rs.getObject(i + 1)))
return true;
}
return false;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public boolean remove(Object key)
{
throw new UnsupportedOperationException();
}
public Iterator iterator()
{
ArrayList values = new ArrayList();
try {
for (int i = 0; i < _columnCount; i++) {
values.add(_rs.getObject(i + 1));
}
return Collections.unmodifiableList(values).iterator();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
private static class DataMapEntrySet
extends AbstractSet<Map.Entry<String,Object>>
{
private ResultSet _rs;
private ResultSetMetaData _metaData;
private int _columnCount;
private int _index;
DataMapEntrySet(ResultSet rs, ResultSetMetaData metaData)
{
_rs = rs;
_metaData = metaData;
try {
_columnCount = _metaData.getColumnCount();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public int size()
{
return _columnCount;
}
@Override
public boolean remove(Object key)
{
throw new UnsupportedOperationException();
}
public Iterator<Map.Entry<String,Object>> iterator()
{
return new EntrySetIterator(_rs, _metaData, _columnCount);
}
}
static class EntrySetIterator implements Iterator<Map.Entry<String,Object>>
{
private ResultSet _rs;
private ResultSetMetaData _metaData;
private Entry _entry = new Entry();
private int _count;
private int _index;
EntrySetIterator(ResultSet rs, ResultSetMetaData metaData, int count)
{
_rs = rs;
_metaData = metaData;
_count = count;
}
public boolean hasNext()
{
return _index < _count;
}
public Map.Entry<String,Object> next()
{
if (_index++ < _count)
return _entry;
else
return null;
}
public void remove()
{
throw new UnsupportedOperationException();
}
class Entry implements Map.Entry<String,Object> {
public String getKey()
{
try {
return _metaData.getColumnName(_index);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public Object getValue()
{
try {
return _rs.getObject(_index);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public Object setValue(Object value)
{
try {
_rs.updateObject(_index, value);
} catch (SQLException e) {
throw new RuntimeException(e);
}
return null;
}
}
}
}