| /* |
| * 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 javax.faces.model; |
| |
| import javax.faces.FacesException; |
| import java.sql.ResultSet; |
| import java.sql.SQLException; |
| import java.sql.ResultSetMetaData; |
| import java.util.*; |
| |
| /** |
| * see Javadoc of <a href="http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/index.html">JSF Specification</a> |
| * |
| * @author Thomas Spiegl (latest modification by $Author$) |
| * @author Martin Marinschek |
| * @version $Revision$ $Date$ |
| */ |
| public class ResultSetDataModel extends DataModel |
| { |
| // FIELDS |
| |
| private int _currentIndex = -1; |
| |
| /** |
| * The ResultSet being wrapped by this DataModel. |
| */ |
| private ResultSet _resultSet = null; |
| |
| /** |
| * The MetaData of the ResultSet being wrapped by this DataModel. |
| */ |
| private ResultSetMetaData _resultSetMetadata = null; |
| |
| |
| /** |
| * Indicator for an updated row at the current position. |
| */ |
| private boolean _currentRowUpdated = false; |
| |
| // CONSTRUCTORS |
| public ResultSetDataModel() |
| { |
| this(null); |
| } |
| |
| public ResultSetDataModel(ResultSet resultSet) |
| { |
| |
| super(); |
| setWrappedData(resultSet); |
| |
| } |
| |
| /** We don't know how many rows the result set has without scrolling |
| * through the whole thing. |
| */ |
| public int getRowCount() |
| { |
| return -1; |
| } |
| |
| /** Get the actual data of this row |
| * wrapped into a map. |
| * The specification is very strict about what has to be |
| * returned from here, so check the spec before |
| * modifying anything here. |
| */ |
| public Object getRowData() |
| { |
| if (_resultSet == null) |
| { |
| return null; |
| } |
| else if (!isRowAvailable()) |
| { |
| throw new IllegalArgumentException( |
| "the requested row is not available in the ResultSet - you have scrolled beyond the end."); |
| } |
| |
| try |
| { |
| return new WrapResultSetMap(String.CASE_INSENSITIVE_ORDER); |
| } |
| catch (SQLException e) |
| { |
| throw new FacesException(e); |
| } |
| } |
| |
| public int getRowIndex() |
| { |
| return _currentIndex; |
| } |
| |
| public Object getWrappedData() |
| { |
| return _resultSet; |
| } |
| |
| public boolean isRowAvailable() |
| { |
| if (_resultSet == null) |
| { |
| return false; |
| } |
| else if (_currentIndex < 0) |
| { |
| return false; |
| } |
| |
| try |
| { |
| return _resultSet.absolute(_currentIndex + 1); |
| } |
| catch (SQLException e) |
| { |
| throw new FacesException(e); |
| } |
| } |
| |
| public void setRowIndex(int rowIndex) |
| { |
| if (rowIndex < -1) |
| { |
| throw new IllegalArgumentException( |
| "you cannot set the rowIndex to anything less than 0"); |
| } |
| |
| // Handle the case of an updated row |
| if (_currentRowUpdated && _resultSet != null) |
| { |
| try |
| { |
| if (!_resultSet.rowDeleted()) |
| _resultSet.updateRow(); |
| |
| setCurrentRowUpdated(false); |
| } |
| catch (SQLException e) |
| { |
| throw new FacesException(e); |
| } |
| } |
| |
| int old = _currentIndex; |
| _currentIndex = rowIndex; |
| |
| //if no underlying data has been set, the listeners |
| //need not be notified |
| if (_resultSet == null) |
| return; |
| |
| //Notify all listeners of the upated row |
| DataModelListener [] listeners = getDataModelListeners(); |
| |
| if ((old != _currentIndex) && (listeners != null)) |
| { |
| Object rowData = null; |
| |
| if (isRowAvailable()) |
| { |
| rowData = getRowData(); |
| } |
| |
| DataModelEvent event = |
| new DataModelEvent(this, _currentIndex, rowData); |
| |
| int n = listeners.length; |
| |
| for (int i = 0; i < n; i++) |
| { |
| if (listeners[i]!=null) |
| { |
| listeners[i].rowSelected(event); |
| } |
| } |
| } |
| } |
| |
| public void setWrappedData(Object data) |
| { |
| if (data == null) |
| { |
| _resultSetMetadata = null; |
| _resultSet = null; |
| setRowIndex(-1); |
| } |
| else |
| { |
| _resultSetMetadata = null; |
| _resultSet = (ResultSet) data; |
| _currentIndex = -1; |
| setRowIndex(0); |
| } |
| } |
| |
| private ResultSetMetaData getResultSetMetadata() |
| { |
| if (_resultSetMetadata == null) |
| { |
| try |
| { |
| _resultSetMetadata = _resultSet.getMetaData(); |
| } |
| catch (SQLException e) |
| { |
| throw new FacesException(e); |
| } |
| } |
| |
| return _resultSetMetadata; |
| } |
| |
| private void setCurrentRowUpdated(boolean currentRowUpdated) |
| { |
| _currentRowUpdated = currentRowUpdated; |
| } |
| |
| /* A map wrapping the result set and calling |
| * the corresponding operations on the result set, |
| * first setting the correct row index. |
| */ |
| private class WrapResultSetMap extends TreeMap |
| { |
| private static final long serialVersionUID = -4321143404567038922L; |
| private int _currentIndex; |
| |
| public WrapResultSetMap(Comparator comparator) throws SQLException |
| { |
| super(comparator); |
| |
| _currentIndex = ResultSetDataModel.this._currentIndex; |
| |
| _resultSet.absolute(_currentIndex + 1); |
| |
| int columnCount = getResultSetMetadata().getColumnCount(); |
| |
| for (int i = 1; i <= columnCount; i++) { |
| super.put(getResultSetMetadata().getColumnName(i), |
| getResultSetMetadata().getColumnName(i)); |
| } |
| } |
| |
| public void clear() |
| { |
| throw new UnsupportedOperationException( |
| "It is not allowed to remove from this map"); |
| } |
| |
| public boolean containsValue(Object value) |
| { |
| Set keys = keySet(); |
| for (Iterator iterator = keys.iterator(); iterator.hasNext();) { |
| Object object = get(iterator.next()); |
| if (object == null) { |
| return value == null; |
| } |
| if (object.equals(value)) { |
| return true; |
| } |
| |
| } |
| return false; |
| } |
| |
| public Set entrySet() |
| { |
| return new WrapResultSetEntries(this); |
| } |
| |
| public Object get(Object key) |
| { |
| if (!containsKey(key)) |
| return null; |
| |
| return basicGet(key); |
| } |
| |
| |
| private Object basicGet(Object key) |
| { //#################################################### remove |
| try |
| { |
| _resultSet.absolute(_currentIndex + 1); |
| |
| return _resultSet.getObject((String) getUnderlyingKey(key)); |
| |
| } |
| catch (SQLException e) |
| { |
| throw new FacesException(e); |
| } |
| } |
| |
| |
| public Set keySet() |
| { |
| return new WrapResultSetKeys(this); |
| } |
| |
| public Object put(Object key, Object value) |
| { |
| if (!containsKey(key)) |
| throw new IllegalArgumentException( |
| "underlying result set does not provide this key"); |
| |
| if (!(key instanceof String)) |
| throw new IllegalArgumentException( |
| "key must be of type 'String', is of type : "+(key==null?"null":key.getClass().getName())); |
| |
| try |
| { |
| _resultSet.absolute(_currentIndex + 1); |
| |
| Object oldValue = _resultSet.getObject((String) getUnderlyingKey(key)); |
| |
| if(oldValue==null?value==null:oldValue.equals(value)) |
| return oldValue; |
| |
| _resultSet.updateObject((String) getUnderlyingKey(key), value); |
| |
| setCurrentRowUpdated(true); |
| |
| return oldValue; |
| } |
| catch (SQLException e) |
| { |
| throw new FacesException(e); |
| } |
| } |
| |
| public void putAll(Map map) |
| { |
| for (Iterator i = map.entrySet().iterator(); i.hasNext(); ) |
| { |
| Map.Entry entry = (Map.Entry) i.next(); |
| put(entry.getKey(), entry.getValue()); |
| } |
| } |
| |
| public Object remove(Object key) |
| { |
| throw new UnsupportedOperationException( |
| "It is not allowed to remove entries from this set."); |
| } |
| |
| public Collection values() |
| { |
| return new WrapResultSetValues(this); |
| } |
| |
| Object getUnderlyingKey(Object key) |
| { |
| return super.get(key); |
| } |
| |
| Iterator getUnderlyingKeys() |
| { |
| return super.keySet().iterator(); |
| } |
| |
| } |
| |
| private static class WrapResultSetEntries extends AbstractSet |
| { |
| private WrapResultSetMap _wrapMap; |
| |
| public WrapResultSetEntries(WrapResultSetMap wrapMap) |
| { |
| _wrapMap = wrapMap; |
| } |
| |
| public boolean add(Object o) |
| { |
| throw new UnsupportedOperationException( |
| "it is not allowed to add to this set"); |
| } |
| |
| public boolean addAll(Collection c) |
| { |
| throw new UnsupportedOperationException( |
| "it is not allowed to add to this set"); |
| } |
| |
| public void clear() |
| { |
| throw new UnsupportedOperationException( |
| "it is not allowed to remove from this set" |
| ); |
| } |
| |
| public boolean contains(Object o) |
| { |
| if (o == null) |
| throw new NullPointerException(); |
| if (!(o instanceof Map.Entry)) |
| return false; |
| |
| Map.Entry e = (Map.Entry) o; |
| Object key = e.getKey(); |
| |
| if (!_wrapMap.containsKey(key)) |
| return false; |
| |
| Object value = e.getValue(); |
| Object cmpValue = _wrapMap.get(key); |
| |
| return value==null?cmpValue==null:value.equals(cmpValue); |
| } |
| |
| public boolean isEmpty() |
| { |
| return _wrapMap.isEmpty(); |
| } |
| |
| public Iterator iterator() |
| { |
| return new WrapResultSetEntriesIterator(_wrapMap); |
| } |
| |
| public boolean remove(Object o) |
| { |
| throw new UnsupportedOperationException( |
| "it is not allowed to remove from this set"); |
| } |
| |
| public boolean removeAll(Collection c) |
| { |
| throw new UnsupportedOperationException( |
| "it is not allowed to remove from this set"); |
| } |
| |
| public boolean retainAll(Collection c) |
| { |
| throw new UnsupportedOperationException( |
| "it is not allowed to remove from this set"); |
| } |
| |
| public int size() |
| { |
| return _wrapMap.size(); |
| } |
| } |
| |
| |
| private static class WrapResultSetEntriesIterator implements Iterator |
| { |
| |
| private WrapResultSetMap _wrapMap = null; |
| private Iterator _keyIterator = null; |
| |
| public WrapResultSetEntriesIterator(WrapResultSetMap wrapMap) |
| { |
| _wrapMap = wrapMap; |
| _keyIterator = _wrapMap.keySet().iterator(); |
| } |
| |
| public boolean hasNext() |
| { |
| return _keyIterator.hasNext(); |
| } |
| |
| public Object next() |
| { |
| return new WrapResultSetEntry(_wrapMap, _keyIterator.next()); |
| } |
| |
| public void remove() |
| { |
| throw new UnsupportedOperationException( |
| "It is not allowed to remove from this iterator" |
| ); |
| } |
| |
| } |
| |
| private static class WrapResultSetEntry implements Map.Entry { |
| |
| private WrapResultSetMap _wrapMap; |
| private Object _entryKey; |
| |
| public WrapResultSetEntry(WrapResultSetMap wrapMap, Object entryKey) |
| { |
| _wrapMap = wrapMap; |
| _entryKey = entryKey; |
| } |
| |
| |
| public boolean equals(Object o) |
| { |
| if (o == null) |
| return false; |
| |
| if (!(o instanceof Map.Entry)) |
| return false; |
| |
| Map.Entry cmpEntry = (Map.Entry) o; |
| |
| if(_entryKey ==null?cmpEntry.getKey()!=null: |
| !_entryKey.equals(cmpEntry.getKey())) |
| return false; |
| |
| Object value = _wrapMap.get(_entryKey); |
| Object cmpValue = cmpEntry.getValue(); |
| |
| return value==null?cmpValue!=null:value.equals(cmpValue); |
| } |
| |
| public Object getKey() |
| { |
| return _entryKey; |
| } |
| |
| public Object getValue() |
| { |
| return _wrapMap.get(_entryKey); |
| } |
| |
| public int hashCode() |
| { |
| int result; |
| result = (_entryKey != null ? _entryKey.hashCode() : 0); |
| result = 29 * result + (_wrapMap.get(_entryKey) != null ? |
| _wrapMap.get(_entryKey).hashCode() : 0); |
| return result; |
| } |
| |
| public Object setValue(Object value) |
| { |
| Object oldValue = _wrapMap.get(_entryKey); |
| _wrapMap.put(_entryKey, value); |
| return oldValue; |
| } |
| } |
| |
| private static class WrapResultSetKeys extends AbstractSet |
| { |
| private WrapResultSetMap _wrapMap; |
| |
| public WrapResultSetKeys(WrapResultSetMap wrapMap) { |
| _wrapMap = wrapMap; |
| } |
| |
| public boolean add(Object o) |
| { |
| throw new UnsupportedOperationException( |
| "It is not allowed to add to this set"); |
| } |
| |
| public boolean addAll(Collection c) |
| { |
| throw new UnsupportedOperationException( |
| "It is not allowed to add to this set"); |
| } |
| |
| public void clear() |
| { |
| throw new UnsupportedOperationException( |
| "It is not allowed to remove from this set" |
| ); |
| } |
| |
| public boolean contains(Object obj) |
| { |
| return _wrapMap.containsKey(obj); |
| } |
| |
| public boolean isEmpty() |
| { |
| return _wrapMap.isEmpty(); |
| } |
| |
| public Iterator iterator() |
| { |
| return new WrapResultSetKeysIterator(_wrapMap); |
| } |
| |
| public boolean remove(Object o) |
| { |
| throw new UnsupportedOperationException( |
| "It is not allowed to remove from this set"); |
| } |
| |
| public boolean removeAll(Collection c) |
| { |
| throw new UnsupportedOperationException( |
| "It is not allowed to remove from this set"); |
| } |
| |
| public boolean retainAll(Collection c) |
| { |
| throw new UnsupportedOperationException( |
| "It is not allowed to remove from this set"); |
| } |
| |
| public int size() |
| { |
| return _wrapMap.size(); |
| } |
| } |
| |
| private static class WrapResultSetKeysIterator implements Iterator |
| { |
| private Iterator _keyIterator = null; |
| |
| public WrapResultSetKeysIterator(WrapResultSetMap map) |
| { |
| _keyIterator = map.getUnderlyingKeys(); |
| } |
| |
| public boolean hasNext() |
| { |
| return _keyIterator.hasNext(); |
| } |
| |
| public Object next() |
| { |
| return _keyIterator.next(); |
| } |
| |
| public void remove() |
| { |
| throw new UnsupportedOperationException( |
| "it is not allowed to remove from this iterator"); |
| } |
| |
| } |
| |
| private static class WrapResultSetValues extends AbstractCollection |
| { |
| private WrapResultSetMap _wrapMap; |
| |
| public WrapResultSetValues(WrapResultSetMap wrapMap) |
| { |
| _wrapMap = wrapMap; |
| } |
| |
| public boolean add(Object o) |
| { |
| throw new UnsupportedOperationException( |
| "it is not allowed to add to this collection" |
| ); |
| } |
| |
| public boolean addAll(Collection c) |
| { |
| throw new UnsupportedOperationException( |
| "it is not allowed to add to this collection" |
| ); |
| } |
| |
| public void clear() |
| { |
| throw new UnsupportedOperationException( |
| "it is not allowed to remove from this collection" |
| ); |
| } |
| |
| public boolean contains(Object value) |
| { |
| return _wrapMap.containsValue(value); |
| } |
| |
| public Iterator iterator() |
| { |
| return new WrapResultSetValuesIterator(_wrapMap); |
| } |
| |
| public boolean remove(Object o) |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public boolean removeAll(Collection c) |
| { |
| throw new UnsupportedOperationException( |
| "it is not allowed to remove from this collection"); |
| } |
| |
| public boolean retainAll(Collection c) |
| { |
| throw new UnsupportedOperationException( |
| "it is not allowed to remove from this collection"); |
| } |
| |
| public int size() |
| { |
| return _wrapMap.size(); |
| } |
| |
| } |
| |
| |
| private static class WrapResultSetValuesIterator implements Iterator |
| { |
| |
| private WrapResultSetMap _wrapMap; |
| private Iterator _keyIterator; |
| |
| public WrapResultSetValuesIterator(WrapResultSetMap wrapMap) |
| { |
| _wrapMap = wrapMap; |
| _keyIterator = _wrapMap.keySet().iterator(); |
| } |
| |
| public boolean hasNext() |
| { |
| return _keyIterator.hasNext(); |
| } |
| |
| public Object next() |
| { |
| return _wrapMap.get(_keyIterator.next()); |
| } |
| |
| public void remove() |
| { |
| throw new UnsupportedOperationException( |
| "it is not allowed to remove from this map" |
| ); |
| } |
| |
| } |
| |
| } |