Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/clra/web/BoatSet.java


1   /*
2    * Copyright (c) Carnegie Lake Rowing Association 2002. All rights reserved.
3    * Distributed under the GPL license. See doc/COPYING.
4    * $RCSfile: BoatSet.java,v $
5    * $Date: 2003/02/26 03:38:46 $
6    * $Revision: 1.4 $
7    */
8   
9   package com.clra.web;
10  
11  import com.clra.rowing.BoatView;
12  import com.clra.util.DBConfiguration;
13  import com.clra.util.ValidationException;
14  import java.io.InputStream;
15  import java.net.URL;
16  import java.sql.Connection;
17  import java.sql.Driver;
18  import java.sql.DriverManager;
19  import java.sql.PreparedStatement;
20  import java.sql.ResultSet;
21  import java.sql.SQLException;
22  import java.util.Collection;
23  import java.util.Comparator;
24  import java.util.GregorianCalendar;
25  import java.util.HashMap;
26  import java.util.Iterator;
27  import java.util.Map;
28  import java.util.Properties;
29  import java.util.SortedSet;
30  import java.util.TreeSet;
31  import org.apache.log4j.Category;
32  import org.apache.log4j.helpers.Loader;
33  
34  /**
35   * A collection of "finder" methods that return read-only, sorted sets
36   * of boats.<p>
37   * FIXME: when this class changes to a "Session-like" design, make sure
38   * it becomes Serializable.
39   *
40   * @version $Id: BoatSet.java,v 1.4 2003/02/26 03:38:46 rphall Exp $
41   * @author <a href="mailto:rphall@pluto.njcc.com">Rick Hall</a>
42   */
43  public class BoatSet implements SortedSet {
44  
45    private final static String base = BoatSet.class.getName();
46    private final static Category theLog = Category.getInstance( base );
47  
48    /**
49     * The current implementations return data in an in-memory collections.
50     * Since the underlaying Boat database table may already be
51     * cached in memory, this can lead to duplicate caching. Future
52     * implementations should avoid in-memory duplicates by implementing
53     * SortedSet and Iterator methods directly in SQL.<p>
54     */
55    private final SortedSet data = new TreeSet();
56  
57    /**
58     * Finds all active boats of the CLRA. Boats are sorted by name
59     * (the natural comparator for boats).
60     */
61    public static BoatSet findAllActiveBoats()
62      throws WebException {
63  
64      Connection conn = null;
65      PreparedStatement stmt = null;
66      BoatSet retVal = new BoatSet();
67      try {
68        conn = DBConfiguration.getConnection();
69        stmt = conn.prepareStatement(
70            Configuration.SQL_BOAT_01,
71            ResultSet.TYPE_FORWARD_ONLY,
72            ResultSet.CONCUR_READ_ONLY);
73        loadBoatSet( stmt, retVal.data );
74      }
75      catch(SQLException x) {
76        String msg = "SQLException: " + x.getMessage();
77        theLog.fatal( msg, x );
78        throw new WebException( msg );
79      }
80      finally {
81        DBConfiguration.closeSQLStatement( stmt );
82        DBConfiguration.closeSQLConnection( conn );
83      }
84      conn = null;
85      stmt = null;
86  
87      return retVal;
88    } // findAllActiveBoats()
89  
90    /**
91     * Finds the boat that has the given id. This "finder" returns at most
92     * one boat.
93     */
94    public static BoatView findBoatById( int id )
95      throws WebException {
96  
97      Connection conn = null;
98      PreparedStatement stmt = null;
99      BoatView retVal = null;
100     try {
101       conn = DBConfiguration.getConnection();
102       stmt = conn.prepareStatement(
103           Configuration.SQL_BOAT_02,
104           ResultSet.TYPE_FORWARD_ONLY,
105           ResultSet.CONCUR_READ_ONLY);
106       stmt.setInt( 1, id );
107       retVal = loadBoat( stmt );
108     }
109     catch(SQLException x) {
110       String msg = "SQLException for id == '" + id + "': "
111           + x.getMessage();
112       theLog.fatal( msg, x );
113       throw new WebException( msg );
114     }
115     finally {
116       DBConfiguration.closeSQLStatement( stmt );
117       DBConfiguration.closeSQLConnection( conn );
118     }
119     conn = null;
120     stmt = null;
121 
122     return retVal;
123   } // findBoatById(int)
124 
125   /**
126    * Finds the boat that has the given name. Names
127    * are unique, so this "finder" returns at most one boat.
128    */
129   public static BoatView findBoatByName( String name )
130     throws WebException {
131 
132     Connection conn = null;
133     PreparedStatement stmt = null;
134     BoatView retVal = null;
135     try {
136       conn = DBConfiguration.getConnection();
137       stmt = conn.prepareStatement(
138           Configuration.SQL_BOAT_03,
139           ResultSet.TYPE_FORWARD_ONLY,
140           ResultSet.CONCUR_READ_ONLY);
141       stmt.setString( 1, name );
142       retVal = loadBoat( stmt );
143     }
144     catch(SQLException x) {
145       String msg = "SQLException for name == '" + name + "': "
146           + x.getMessage();
147       theLog.fatal( msg, x );
148       throw new WebException( msg );
149     }
150     finally {
151       DBConfiguration.closeSQLStatement( stmt );
152       DBConfiguration.closeSQLConnection( conn );
153     }
154     conn = null;
155     stmt = null;
156 
157     return retVal;
158   } // findBoatByName(String)
159 
160   /** BoatSet instances are created by static "finder" methods */
161   private BoatSet() {}
162 
163   /**
164    * Returns the comparator associated with this sorted set, or
165    * <tt>null</tt> if it uses its elements' natural ordering.
166    *
167    * @return the comparator associated with this sorted set, or
168    *          <tt>null</tt> if it uses its elements' natural ordering.
169    */
170   public Comparator comparator() {
171     return this.data.comparator();
172   }
173 
174   /**
175    * Returns a view of the portion of this sorted set whose elements range
176    * from <tt>fromElement</tt>, inclusive, to <tt>toElement</tt>, exclusive.
177    *
178    * @param fromElement low endpoint (inclusive) of the subSet.
179    * @param toElement high endpoint (exclusive) of the subSet.
180    * @return a view of the specified range within this sorted set.
181    * 
182    * @throws ClassCastException if <tt>fromElement</tt> and
183    *         <tt>toElement</tt> are not <tt>Boat</tt> objects.
184    * @throws IllegalArgumentException if <tt>fromElement</tt> is greater than
185    *         <tt>toElement</tt>; or if this set is itself a subSet, headSet,
186    *         or tailSet, and <tt>fromElement</tt> or <tt>toElement</tt> are
187    *         not within the specified range of the subSet, headSet, or
188    *         tailSet.
189    * @throws NullPointerException if <tt>fromElement</tt> or
190    *         <tt>toElement</tt> is <tt>null</tt>
191    */
192   public SortedSet subSet(Object fromElement, Object toElement) {
193     return this.data.subSet(fromElement,toElement);
194   }
195 
196   /**
197    * Returns a view of the portion of this sorted set whose elements are
198    * strictly less than <tt>toElement</tt>.
199    *
200    * @param toElement high endpoint (exclusive) of the headSet.
201    * @return a view of the specified initial range of this sorted set.
202    * @throws ClassCastException if <tt>toElement</tt> is not compatible
203    *         with this set's comparator (or, if the set has no comparator,
204    *         if <tt>toElement</tt> does not implement <tt>Comparable</tt>).
205    * @throws NullPointerException if <tt>toElement</tt> is <tt>null</tt>
206    * @throws IllegalArgumentException if this set is itself a subSet,
207    *         headSet, or tailSet, and <tt>toElement</tt> is not within the
208    *         specified range of the subSet, headSet, or tailSet.
209    */
210   public SortedSet headSet(Object toElement) {
211     return this.data.headSet(toElement);
212   }
213 
214   /**
215    * Returns a view of the portion of this sorted set whose elements are
216    * greater than or equal to <tt>fromElement</tt>.
217    *
218    * @param fromElement low endpoint (inclusive) of the tailSet.
219    * @return a view of the specified final range of this sorted set.
220    * @throws ClassCastException if <tt>fromElement</tt> is not compatible
221    *         with this set's comparator (or, if the set has no comparator,
222    *         if <tt>fromElement</tt> does not implement <tt>Comparable</tt>).
223    * @throws NullPointerException if <tt>fromElement</tt> is <tt>null</tt>
224    * @throws IllegalArgumentException if this set is itself a subSet,
225    *         headSet, or tailSet, and <tt>fromElement</tt> is not within the
226    *         specified range of the subSet, headSet, or tailSet.
227    */
228   public SortedSet tailSet(Object fromElement) {
229     return this.data.tailSet(fromElement);
230   }
231 
232   /**
233    * Returns the first (lowest) element currently in this sorted set.
234    *
235    * @return the first (lowest) element currently in this sorted set.
236    * @throws    NoSuchElementException sorted set is empty.
237    */
238   public Object first() {
239     return this.data.first();
240   }
241 
242   /**
243    * Returns the last (highest) element currently in this sorted set.
244    *
245    * @return the last (highest) element currently in this sorted set.
246    * @throws    NoSuchElementException sorted set is empty.
247    */
248   public Object last() {
249     return this.data.last();
250   }
251 
252   /**
253    * Returns the number of elements in this set (its cardinality).  If this
254    * set contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
255    * <tt>Integer.MAX_VALUE</tt>.
256    *
257    * @return the number of elements in this set (its cardinality).
258    */
259   public int size() {
260     return this.data.size();
261   }
262 
263   /**
264    * Returns <tt>true</tt> if this set contains no elements.
265    *
266    * @return <tt>true</tt> if this set contains no elements.
267    */
268   public boolean isEmpty() {
269     return this.data.isEmpty();
270   }
271 
272   /**
273    * Returns <tt>true</tt> if this set contains the specified element.
274    *
275    * @param o element whose presence in this set is to be tested.
276    * @return <tt>true</tt> if this set contains the specified element.
277    */
278   public boolean contains(Object o) {
279    /*
280    * formally, returns <tt>true</tt> if and only if this set contains an
281    * element <code>e</code> such that <code>(o==null ? e==null :
282    * o.equals(e))</code>.
283    */
284     return this.data.contains(o);
285   }
286 
287   /**
288    * Returns an iterator over the (sorted) elements in this set.
289    *
290    * @return an iterator over the elements in this set.
291    */
292   public Iterator iterator() {
293     return this.data.iterator();
294   }
295 
296   /**
297    * Returns an array containing all of the elements in this set.
298    *
299    * @return an array containing all of the elements in this set.
300    */
301   public Object[] toArray() {
302     return this.data.toArray();
303   }
304 
305   /**
306    * Returns an array containing all of the elements in this set whose
307    * runtime type is that of the specified array.
308    *
309    * @param a the array into which the elements of this set are to
310    *    be stored, if it is big enough; otherwise, a new array of the
311    *     same runtime type is allocated for this purpose.
312    * @return an array containing the elements of this set.
313    * @throws    ArrayStoreException the runtime type of a is not a supertype
314    * of the runtime type of Boat.
315    */
316   public Object[] toArray(Object a[]) {
317     return this.data.toArray(a);
318   }
319 
320   // Bulk Operations
321 
322   /**
323    * Returns <tt>true</tt> if this set contains all of the elements of the
324    * specified collection.
325    *
326    * @param c collection to be checked for containment in this set.
327    * @return <tt>true</tt> if this set contains all of the elements of the
328    *          specified collection.
329    */
330   public boolean containsAll(Collection c) {
331     return this.data.containsAll(c);
332   }
333 
334   // Comparison and hashing
335 
336   /**
337    * Compares the specified object with this set for equality.
338    *
339    * @param o Object to be compared for equality with this set.
340    * @return <tt>true</tt> if the specified Object is equal to this set.
341    */
342   public boolean equals(Object o) {
343     return this.data.equals(o);
344   }
345 
346   /**
347    * Returns the hash code value for this set.  The hash code of a set is
348    * defined to be the sum of the hash codes of the elements in the set.
349    *
350    * @return the hash code value for this set.
351    */
352   public int hashCode() {
353     return this.data.hashCode();
354   }
355 
356   // Modification Operations are not supported
357 
358   /**
359    * @throws UnsupportedOperationException since the <tt>add</tt> method is
360    *           not supported by this set.
361    */
362   public boolean add(Object o) {
363     throw new UnsupportedOperationException( "not supported" );
364   }
365 
366   /**
367    * @throws UnsupportedOperationException since the <tt>remove</tt> method is
368    *         not supported by this set.
369    */
370   public boolean remove(Object o) {
371     throw new UnsupportedOperationException( "not supported" );
372   }
373 
374   /**
375    * @throws UnsupportedOperationException since the <tt>addAll</tt> method is
376    *       not supported by this set.
377    */
378   public boolean addAll(Collection c) {
379     throw new UnsupportedOperationException( "not supported" );
380   }
381 
382   /**
383    * @throws UnsupportedOperationException since the <tt>retainAll</tt> method
384    *       is not supported by this Collection.
385    */
386   public boolean retainAll(Collection c) {
387     throw new UnsupportedOperationException( "not supported" );
388   }
389 
390   /**
391    * @throws UnsupportedOperationException since the <tt>removeAll</tt>
392    *       method is not supported by this Collection.
393   */
394   public boolean removeAll(Collection c) {
395     throw new UnsupportedOperationException( "not supported" );
396   }
397 
398   /**
399    * @throws UnsupportedOperationException since the <tt>clear</tt> method
400    *       is not supported by this set.
401    */
402   public void clear() {
403     throw new UnsupportedOperationException( "not supported" );
404   }
405 
406   // UTILITIES
407 
408   /** Loads an in-memory object from a database using the specified SQL */
409   private static BoatView loadBoat( PreparedStatement stmt )
410     throws SQLException, WebException {
411 
412     // Initialize result set and return value to facilitate error recovery
413     ResultSet rs = null;
414     BoatView retVal = null;
415 
416     try {
417       rs = stmt.executeQuery();
418       if ( rs.next() ) {
419         retVal = mapRowToBoat(rs);
420       } // if
421     }
422     finally {
423       if (rs != null) {
424         try {
425           rs.close();
426           rs = null;
427         }
428         catch(Exception x) {
429           theLog.error(x.getMessage(),x);
430         }
431       }
432     } // finally
433 
434     return retVal;
435   } // loadBoat(PreparedStatement)
436 
437   /** Loads an in-memory set from a database using the specified SQL */
438   private static void loadBoatSet( PreparedStatement stmt, SortedSet set )
439     throws SQLException, WebException {
440 
441     // Initialize result set to facilitate error recovery
442     ResultSet rs = null;
443     int rowIdx = -1;
444 
445     try {
446       rs = stmt.executeQuery();
447       while ( rs.next() ) {
448         ++rowIdx;
449         BoatView boat = mapRowToBoat(rs);
450         set.add( boat );
451       } // while
452     }
453     finally {
454       if (rs != null) {
455         try {
456           rs.close();
457           rs = null;
458         }
459         catch(Exception x) {
460           theLog.error(x.getMessage(),x);
461         }
462       }
463     } // finally
464   } // loadBoatSet(PreparedStatement,SortedSet)
465 
466   /** Maps a row of SQL ResultSet to a BoatView object */
467   private static BoatView mapRowToBoat( ResultSet rs )
468     throws SQLException, WebException {
469 
470     final int boat_id             = rs.getInt(    "boat_id"   );
471     final String boat_name        = rs.getString( "boat_name" );
472     final int boat_size           = rs.getInt(    "boat_size" );
473     final String boat_type        = rs.getString( "boat_type" );
474 
475     if ( theLog.isDebugEnabled() ) {
476       theLog.debug( boat_id + ", " + boat_name );
477     }
478 
479     BoatView retVal = null;
480     try {
481       retVal = new BoatView( boat_id, boat_name, boat_size, boat_type );
482     }
483     catch( ValidationException x ) {
484       String msg = "Problem with data for boat == '" + boat_id + "', '"
485           + boat_name + "': " + x.getMessage();
486       theLog.fatal( msg, x );
487       throw new WebException( msg );
488     }
489 
490     return retVal;
491   } // mapRowToBoat(ResultSet)
492 
493 } // BoatSet
494 
495 /*
496  * $Log: BoatSet.java,v $
497  * Revision 1.4  2003/02/26 03:38:46  rphall
498  * Added copyright and GPL license
499  *
500  * Revision 1.3  2003/02/19 22:30:31  rphall
501  * Removed gratuitous use of CLRA acronym
502  *
503  * Revision 1.2  2002/02/18 18:05:37  rphall
504  * Ran dos2unix to remove ^M (carriage return) from end of lines
505  */
506