View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package javax.faces.model;
20  
21  import javax.faces.FacesException;
22  import java.sql.ResultSet;
23  import java.sql.SQLException;
24  import java.sql.ResultSetMetaData;
25  import java.util.*;
26  
27  /**
28   * see Javadoc of <a href="http://java.sun.com/javaee/javaserverfaces/1.2/docs/api/index.html">JSF Specification</a>
29   *
30   * @author Thomas Spiegl (latest modification by $Author: skitching $)
31   * @author Martin Marinschek
32   * @version $Revision: 676298 $ $Date: 2008-07-13 05:31:48 -0500 (Sun, 13 Jul 2008) $
33   */
34  public class ResultSetDataModel extends DataModel
35  {
36      // FIELDS
37  
38      private int _currentIndex = -1;
39  
40      /**
41       * The ResultSet being wrapped by this DataModel.
42       */
43      private ResultSet _resultSet = null;
44  
45      /**
46       * The MetaData of the ResultSet being wrapped by this DataModel.
47       */
48      private ResultSetMetaData _resultSetMetadata = null;
49  
50  
51      /**
52       *  Indicator for an updated row at the current position.
53       */
54      private boolean _currentRowUpdated = false;
55  
56      // CONSTRUCTORS
57      public ResultSetDataModel()
58      {
59          this(null);
60      }
61  
62      public ResultSetDataModel(ResultSet resultSet)
63      {
64  
65          super();
66          setWrappedData(resultSet);
67  
68      }
69  
70      /** We don't know how many rows the result set has without scrolling
71       * through the whole thing.
72       */
73      public int getRowCount()
74      {
75          return -1;
76      }
77  
78      /** Get the actual data of this row
79       *  wrapped into a map.
80       *  The specification is very strict about what has to be
81       *  returned from here, so check the spec before
82       *  modifying anything here.
83       */
84      public Object getRowData()
85      {
86          if (_resultSet == null)
87          {
88              return null;
89          }
90          else if (!isRowAvailable())
91          {
92              throw new IllegalArgumentException(
93                      "the requested row is not available in the ResultSet - you have scrolled beyond the end.");
94          }
95  
96          try
97          {
98              return new WrapResultSetMap(String.CASE_INSENSITIVE_ORDER);
99          }
100         catch (SQLException e)
101         {
102             throw new FacesException(e);
103         }
104     }
105 
106     public int getRowIndex()
107     {
108         return _currentIndex;
109     }
110 
111     public Object getWrappedData()
112     {
113         return _resultSet;
114     }
115 
116     public boolean isRowAvailable()
117     {
118         if (_resultSet == null)
119         {
120             return false;
121         }
122         else if (_currentIndex < 0)
123         {
124             return false;
125         }
126 
127         try
128         {
129             return _resultSet.absolute(_currentIndex + 1);
130         }
131         catch (SQLException e)
132         {
133             throw new FacesException(e);
134         }
135     }
136 
137     public void setRowIndex(int rowIndex)
138     {
139         if (rowIndex < -1)
140         {
141             throw new IllegalArgumentException(
142                     "you cannot set the rowIndex to anything less than 0");
143         }
144 
145         // Handle the case of an updated row
146         if (_currentRowUpdated && _resultSet != null)
147         {
148             try
149             {
150                 if (!_resultSet.rowDeleted())
151                     _resultSet.updateRow();
152 
153                 setCurrentRowUpdated(false);
154             }
155             catch (SQLException e)
156             {
157                 throw new FacesException(e);
158             }
159         }
160 
161         int old = _currentIndex;
162         _currentIndex = rowIndex;
163 
164         //if no underlying data has been set, the listeners
165         //need not be notified
166         if (_resultSet == null)
167             return;
168 
169         //Notify all listeners of the upated row
170         DataModelListener [] listeners = getDataModelListeners();
171 
172         if ((old != _currentIndex) && (listeners != null))
173         {
174             Object rowData = null;
175 
176             if (isRowAvailable())
177             {
178                 rowData = getRowData();
179             }
180 
181             DataModelEvent event =
182                 new DataModelEvent(this, _currentIndex, rowData);
183 
184             int n = listeners.length;
185 
186             for (int i = 0; i < n; i++)
187             {
188                 if (listeners[i]!=null)
189                 {
190                     listeners[i].rowSelected(event);
191                 }
192             }
193         }
194     }
195 
196     public void setWrappedData(Object data)
197     {
198         if (data == null)
199         {
200             _resultSetMetadata = null;
201             _resultSet = null;
202             setRowIndex(-1);
203         }
204         else
205         {
206             _resultSetMetadata = null;
207             _resultSet = (ResultSet) data;
208             _currentIndex = -1;
209             setRowIndex(0);
210         }
211     }
212 
213     private ResultSetMetaData getResultSetMetadata()
214     {
215         if (_resultSetMetadata == null)
216         {
217             try
218             {
219                 _resultSetMetadata = _resultSet.getMetaData();
220             }
221             catch (SQLException e)
222             {
223                 throw new FacesException(e);
224             }
225         }
226 
227         return _resultSetMetadata;
228     }
229 
230     private void setCurrentRowUpdated(boolean currentRowUpdated)
231     {
232         _currentRowUpdated = currentRowUpdated;
233     }
234 
235     /* A map wrapping the result set and calling
236     * the corresponding operations on the result set,
237     * first setting the correct row index.
238     */
239     private class WrapResultSetMap extends TreeMap
240     {
241         private static final long serialVersionUID = -4321143404567038922L;
242         private int _currentIndex;
243 
244         public WrapResultSetMap(Comparator comparator) throws SQLException
245         {
246             super(comparator);
247 
248             _currentIndex = ResultSetDataModel.this._currentIndex;
249 
250             _resultSet.absolute(_currentIndex + 1);
251 
252             int columnCount = getResultSetMetadata().getColumnCount();
253 
254             for (int i = 1; i <= columnCount; i++) {
255                 super.put(getResultSetMetadata().getColumnName(i),
256                           getResultSetMetadata().getColumnName(i));
257             }
258         }
259 
260         public void clear()
261         {
262             throw new UnsupportedOperationException(
263                     "It is not allowed to remove from this map");
264         }
265 
266         public boolean containsValue(Object value)
267         {
268             Set<Object> keys = keySet();
269             for (Iterator<Object> iterator = keys.iterator(); iterator.hasNext();) {
270                 Object object = get(iterator.next());
271                 if (object == null) {
272                     return value == null;
273                 }
274                 if (object.equals(value)) {
275                     return true;
276                 }
277 
278             }
279             return false;
280         }
281 
282         public Set entrySet()
283         {
284             return new WrapResultSetEntries(this);
285         }
286 
287         public Object get(Object key)
288         {
289             if (!containsKey(key))
290                 return null;
291 
292             return basicGet(key);
293         }
294 
295 
296         private Object basicGet(Object key)
297         {  //#################################################### remove
298             try
299             {
300                 _resultSet.absolute(_currentIndex + 1);
301 
302                 return _resultSet.getObject((String) getUnderlyingKey(key));
303 
304             }
305             catch (SQLException e)
306             {
307                 throw new FacesException(e);
308             }
309         }
310 
311 
312         public Set<Object> keySet()
313         {
314             return new WrapResultSetKeys(this);
315         }
316 
317         public Object put(Object key, Object value)
318         {
319             if (!containsKey(key))
320                 throw new IllegalArgumentException(
321                         "underlying result set does not provide this key");
322 
323             if (!(key instanceof String))
324                 throw new IllegalArgumentException(
325                         "key must be of type 'String', is of type : "+(key==null?"null":key.getClass().getName()));
326 
327             try
328             {
329                 _resultSet.absolute(_currentIndex + 1);
330 
331                 Object oldValue = _resultSet.getObject((String) getUnderlyingKey(key));
332 
333                 if(oldValue==null?value==null:oldValue.equals(value))
334                     return oldValue;
335 
336                 _resultSet.updateObject((String) getUnderlyingKey(key), value);
337 
338                 setCurrentRowUpdated(true);
339 
340                 return oldValue;
341             }
342             catch (SQLException e)
343             {
344                 throw new FacesException(e);
345             }
346         }
347 
348         public void putAll(Map map)
349         {
350             for (Iterator i = map.entrySet().iterator(); i.hasNext(); )
351             {
352                 Map.Entry entry = (Map.Entry) i.next();
353                 put(entry.getKey(), entry.getValue());
354             }
355         }
356 
357         public Object remove(Object key)
358         {
359             throw new UnsupportedOperationException(
360                     "It is not allowed to remove entries from this set.");
361         }
362 
363         public Collection<Object> values()
364         {
365             return new WrapResultSetValues(this);
366         }
367 
368         Object getUnderlyingKey(Object key)
369         {
370             return super.get(key);
371         }
372 
373         Iterator getUnderlyingKeys()
374         {
375             return super.keySet().iterator();
376         }
377 
378     }
379 
380     private static class WrapResultSetEntries extends AbstractSet
381     {
382         private WrapResultSetMap _wrapMap;
383 
384         public WrapResultSetEntries(WrapResultSetMap wrapMap)
385         {
386             _wrapMap = wrapMap;
387         }
388 
389         public boolean add(Object o)
390         {
391             throw new UnsupportedOperationException(
392                     "it is not allowed to add to this set");
393         }
394 
395         public boolean addAll(Collection c)
396         {
397             throw new UnsupportedOperationException(
398                     "it is not allowed to add to this set");
399         }
400 
401         public void clear()
402         {
403             throw new UnsupportedOperationException(
404                     "it is not allowed to remove from this set"
405             );
406         }
407 
408         public boolean contains(Object o)
409         {
410             if (o == null)
411                 throw new NullPointerException();
412             if (!(o instanceof Map.Entry))
413                 return false;
414 
415             Map.Entry e = (Map.Entry) o;
416             Object key = e.getKey();
417 
418             if (!_wrapMap.containsKey(key))
419                 return false;
420 
421             Object value = e.getValue();
422             Object cmpValue = _wrapMap.get(key);
423 
424             return value==null?cmpValue==null:value.equals(cmpValue);
425         }
426 
427         public boolean isEmpty()
428         {
429             return _wrapMap.isEmpty();
430         }
431 
432         public Iterator iterator()
433         {
434             return new WrapResultSetEntriesIterator(_wrapMap);
435         }
436 
437         public boolean remove(Object o)
438         {
439             throw new UnsupportedOperationException(
440                     "it is not allowed to remove from this set");
441         }
442 
443         public boolean removeAll(Collection c)
444         {
445             throw new UnsupportedOperationException(
446                     "it is not allowed to remove from this set");
447         }
448 
449         public boolean retainAll(Collection c)
450         {
451             throw new UnsupportedOperationException(
452                     "it is not allowed to remove from this set");
453         }
454 
455         public int size()
456         {
457             return _wrapMap.size();
458         }
459     }
460 
461 
462     private static class WrapResultSetEntriesIterator implements Iterator
463     {
464 
465         private WrapResultSetMap _wrapMap = null;
466         private Iterator<Object> _keyIterator = null;
467 
468         public WrapResultSetEntriesIterator(WrapResultSetMap wrapMap)
469         {
470             _wrapMap = wrapMap;
471             _keyIterator = _wrapMap.keySet().iterator();
472         }
473 
474         public boolean hasNext()
475         {
476             return _keyIterator.hasNext();
477         }
478 
479         public Object next()
480         {
481             return new WrapResultSetEntry(_wrapMap, _keyIterator.next());
482         }
483 
484         public void remove()
485         {
486             throw new UnsupportedOperationException(
487                     "It is not allowed to remove from this iterator"
488             );
489         }
490 
491     }
492 
493     private static class WrapResultSetEntry implements Map.Entry {
494 
495         private WrapResultSetMap _wrapMap;
496         private Object _entryKey;
497 
498         public WrapResultSetEntry(WrapResultSetMap wrapMap, Object entryKey)
499         {
500             _wrapMap = wrapMap;
501             _entryKey = entryKey;
502         }
503 
504 
505         public boolean equals(Object o)
506         {
507             if (o == null)
508                 return false;
509 
510             if (!(o instanceof Map.Entry))
511                 return false;
512 
513             Map.Entry cmpEntry = (Map.Entry) o;
514 
515             if(_entryKey ==null?cmpEntry.getKey()!=null:
516                     !_entryKey.equals(cmpEntry.getKey()))
517                 return false;
518 
519             Object value = _wrapMap.get(_entryKey);
520             Object cmpValue = cmpEntry.getValue();
521 
522             return value==null?cmpValue!=null:value.equals(cmpValue);
523         }
524 
525         public Object getKey()
526         {
527             return _entryKey;
528         }
529 
530         public Object getValue()
531         {
532             return _wrapMap.get(_entryKey);
533         }
534 
535         public int hashCode()
536         {
537             int result;
538             result = (_entryKey != null ? _entryKey.hashCode() : 0);
539             result = 29 * result + (_wrapMap.get(_entryKey) != null ?
540                     _wrapMap.get(_entryKey).hashCode() : 0);
541             return result;
542         }
543 
544         public Object setValue(Object value)
545         {
546             Object oldValue = _wrapMap.get(_entryKey);
547             _wrapMap.put(_entryKey, value);
548             return oldValue;
549         }
550     }
551 
552     private static class WrapResultSetKeys extends AbstractSet
553     {
554         private WrapResultSetMap _wrapMap;
555 
556         public WrapResultSetKeys(WrapResultSetMap wrapMap) {
557             _wrapMap = wrapMap;
558         }
559 
560         public boolean add(Object o)
561         {
562             throw new UnsupportedOperationException(
563                     "It is not allowed to add to this set");
564         }
565 
566         public boolean addAll(Collection c)
567         {
568             throw new UnsupportedOperationException(
569                     "It is not allowed to add to this set");
570         }
571 
572         public void clear()
573         {
574             throw new UnsupportedOperationException(
575                     "It is not allowed to remove from this set"
576             );
577         }
578 
579         public boolean contains(Object obj)
580         {
581             return _wrapMap.containsKey(obj);
582         }
583 
584         public boolean isEmpty()
585         {
586             return _wrapMap.isEmpty();
587         }
588 
589         public Iterator iterator()
590         {
591             return new WrapResultSetKeysIterator(_wrapMap);
592         }
593 
594         public boolean remove(Object o)
595         {
596             throw new UnsupportedOperationException(
597                     "It is not allowed to remove from this set");
598         }
599 
600         public boolean removeAll(Collection c)
601         {
602             throw new UnsupportedOperationException(
603                     "It is not allowed to remove from this set");
604         }
605 
606         public boolean retainAll(Collection c)
607         {
608             throw new UnsupportedOperationException(
609                     "It is not allowed to remove from this set");
610         }
611 
612         public int size()
613         {
614             return _wrapMap.size();
615         }
616     }
617 
618     private static class WrapResultSetKeysIterator implements Iterator
619     {
620         private Iterator _keyIterator = null;
621 
622         public WrapResultSetKeysIterator(WrapResultSetMap map)
623         {
624             _keyIterator = map.getUnderlyingKeys();
625         }
626 
627         public boolean hasNext()
628         {
629             return _keyIterator.hasNext();
630         }
631 
632         public Object next()
633         {
634             return _keyIterator.next();
635         }
636 
637         public void remove()
638         {
639             throw new UnsupportedOperationException(
640                     "it is not allowed to remove from this iterator");
641         }
642 
643     }
644 
645     private static class WrapResultSetValues extends AbstractCollection
646     {
647         private WrapResultSetMap _wrapMap;
648 
649         public WrapResultSetValues(WrapResultSetMap wrapMap)
650         {
651             _wrapMap = wrapMap;
652         }
653 
654         public boolean add(Object o)
655         {
656             throw new UnsupportedOperationException(
657                     "it is not allowed to add to this collection"
658             );
659         }
660 
661         public boolean addAll(Collection c)
662         {
663             throw new UnsupportedOperationException(
664                 "it is not allowed to add to this collection"
665             );
666         }
667 
668         public void clear()
669         {
670             throw new UnsupportedOperationException(
671                 "it is not allowed to remove from this collection"
672             );
673         }
674 
675         public boolean contains(Object value)
676         {
677             return _wrapMap.containsValue(value);
678         }
679 
680         public Iterator iterator()
681         {
682             return new WrapResultSetValuesIterator(_wrapMap);
683         }
684 
685         public boolean remove(Object o)
686         {
687             throw new UnsupportedOperationException();
688         }
689 
690         public boolean removeAll(Collection c)
691         {
692             throw new UnsupportedOperationException(
693                     "it is not allowed to remove from this collection");
694         }
695 
696         public boolean retainAll(Collection c)
697         {
698             throw new UnsupportedOperationException(
699                     "it is not allowed to remove from this collection");
700         }
701 
702         public int size()
703         {
704             return _wrapMap.size();
705         }
706 
707     }
708 
709 
710     private static class WrapResultSetValuesIterator implements Iterator
711     {
712 
713         private WrapResultSetMap _wrapMap;
714         private Iterator<Object> _keyIterator;
715 
716         public WrapResultSetValuesIterator(WrapResultSetMap wrapMap)
717         {
718             _wrapMap = wrapMap;
719             _keyIterator = _wrapMap.keySet().iterator();
720         }
721 
722         public boolean hasNext()
723         {
724             return _keyIterator.hasNext();
725         }
726 
727         public Object next()
728         {
729             return _wrapMap.get(_keyIterator.next());
730         }
731 
732         public void remove()
733         {
734             throw new UnsupportedOperationException(
735                     "it is not allowed to remove from this map"
736             );
737         }
738 
739     }
740 
741 }