KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tapestry > vlib > ejb > impl > OperationsBean


1 // Copyright 2004 The Apache Software Foundation
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15 package org.apache.tapestry.vlib.ejb.impl;
16
17 import java.rmi.RemoteException JavaDoc;
18 import java.sql.Connection JavaDoc;
19 import java.sql.ResultSet JavaDoc;
20 import java.sql.SQLException JavaDoc;
21 import java.sql.Timestamp JavaDoc;
22 import java.util.ArrayList JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.List JavaDoc;
25 import java.util.Map JavaDoc;
26
27 import javax.ejb.CreateException JavaDoc;
28 import javax.ejb.FinderException JavaDoc;
29 import javax.ejb.RemoveException JavaDoc;
30 import javax.ejb.SessionBean JavaDoc;
31 import javax.ejb.SessionContext JavaDoc;
32 import javax.naming.Context JavaDoc;
33 import javax.naming.InitialContext JavaDoc;
34 import javax.naming.NamingException JavaDoc;
35 import javax.rmi.PortableRemoteObject JavaDoc;
36 import javax.sql.DataSource JavaDoc;
37
38 import org.apache.tapestry.Tapestry;
39 import org.apache.tapestry.contrib.ejb.XCreateException;
40 import org.apache.tapestry.contrib.ejb.XEJBException;
41 import org.apache.tapestry.contrib.ejb.XRemoveException;
42 import org.apache.tapestry.contrib.jdbc.IStatement;
43 import org.apache.tapestry.contrib.jdbc.StatementAssembly;
44 import org.apache.tapestry.vlib.ejb.Book;
45 import org.apache.tapestry.vlib.ejb.BorrowException;
46 import org.apache.tapestry.vlib.ejb.IBook;
47 import org.apache.tapestry.vlib.ejb.IBookHome;
48 import org.apache.tapestry.vlib.ejb.IPerson;
49 import org.apache.tapestry.vlib.ejb.IPersonHome;
50 import org.apache.tapestry.vlib.ejb.IPublisher;
51 import org.apache.tapestry.vlib.ejb.IPublisherHome;
52 import org.apache.tapestry.vlib.ejb.LoginException;
53 import org.apache.tapestry.vlib.ejb.Person;
54 import org.apache.tapestry.vlib.ejb.Publisher;
55 import org.apache.tapestry.vlib.ejb.RegistrationException;
56 import org.apache.tapestry.vlib.ejb.SortColumn;
57 import org.apache.tapestry.vlib.ejb.SortOrdering;
58
59 /**
60  * Implementation of the {@link org.apache.tapestry.vlib.ejb.IOperations}
61  * stateless session bean.
62  *
63  * <p>Implenents a number of stateless operations for the front end.
64  *
65  * @version $Id: OperationsBean.java,v 1.7 2004/02/19 17:38:07 hlship Exp $
66  * @author Howard Lewis Ship
67  *
68  **/

69
70 public class OperationsBean implements SessionBean JavaDoc
71 {
72     private SessionContext JavaDoc _context;
73     private transient Context JavaDoc _environment;
74     private transient IBookHome _bookHome;
75     private transient IPersonHome _personHome;
76     private transient IPublisherHome _publisherHome;
77
78     /**
79      * Data source, retrieved from the ENC property
80      * "jdbc/dataSource".
81      *
82      **/

83
84     private transient DataSource JavaDoc _dataSource;
85
86     /**
87      * Sets up the bean. Locates the {@link DataSource} for the bean
88      * as <code>jdbc/dataSource</code> within the ENC; this data source is
89      * later used by {@link #getConnection()}.
90      *
91      **/

92
93     public void ejbCreate()
94     {
95         Context JavaDoc initial;
96
97         try
98         {
99             initial = new InitialContext JavaDoc();
100             _environment = (Context JavaDoc) initial.lookup("java:comp/env");
101         }
102         catch (NamingException JavaDoc e)
103         {
104             throw new XEJBException("Could not lookup environment.", e);
105         }
106
107         try
108         {
109             _dataSource = (DataSource JavaDoc) _environment.lookup("jdbc/dataSource");
110         }
111         catch (NamingException JavaDoc e)
112         {
113             e.printStackTrace();
114             throw new XEJBException("Could not lookup data source.", e);
115         }
116     }
117
118     public void ejbRemove()
119     {
120     }
121
122     /**
123      * Does nothing, not invoked in stateless session beans.
124      **/

125
126     public void ejbPassivate()
127     {
128     }
129
130     public void setSessionContext(SessionContext JavaDoc value)
131     {
132         _context = value;
133     }
134
135     /**
136      * Does nothing, not invoked in stateless session beans.
137      *
138      **/

139
140     public void ejbActivate()
141     {
142     }
143
144     /**
145      * Finds the book and borrower (by thier primary keys) and updates the book.
146      *
147      * <p>The {@link Book} value object is returned.
148      *
149      **/

150
151     public Book borrowBook(Integer JavaDoc bookId, Integer JavaDoc borrowerId)
152         throws FinderException JavaDoc, RemoteException JavaDoc, BorrowException
153     {
154         IBookHome bookHome = getBookHome();
155         IPersonHome personHome = getPersonHome();
156
157         IBook book = bookHome.findByPrimaryKey(bookId);
158
159         if (!book.getLendable())
160             throw new BorrowException("Book may not be borrowed.");
161
162         // Verify that the borrower exists.
163

164         personHome.findByPrimaryKey(borrowerId);
165
166         // TBD: Check that borrower has authenticated
167

168         // findByPrimaryKey() throws an exception if the EJB doesn't exist,
169
// so we're safe.
170

171         personHome.findByPrimaryKey(book.getOwnerId());
172
173         // Here's the real work; just setting the holder of the book
174
// to be the borrower.
175

176         book.setHolderId(borrowerId);
177
178         return getBook(bookId);
179     }
180
181     /**
182      * Adds a new book, verifying that the publisher and holder actually exist.
183      *
184      **/

185
186     public Integer JavaDoc addBook(Map JavaDoc attributes) throws CreateException JavaDoc, RemoteException JavaDoc
187     {
188         IBookHome home = getBookHome();
189
190         attributes.put("dateAdded", new Timestamp JavaDoc(System.currentTimeMillis()));
191
192         IBook book = home.create(attributes);
193
194         return (Integer JavaDoc) book.getPrimaryKey();
195     }
196
197     /**
198      * Adds a book, which will be owned and held by the specified owner.
199      *
200      * <p>The publisherName may either be the name of a known publisher, or
201      * a new name. A new {@link IPublisher} will be created as necessary.
202      *
203      * <p>Returns the newly created book, as a {@link Map} of attributes.
204      *
205      **/

206
207     public Integer JavaDoc addBook(Map JavaDoc attributes, String JavaDoc publisherName)
208         throws CreateException JavaDoc, RemoteException JavaDoc
209     {
210         IPublisher publisher = null;
211         IPublisherHome publisherHome = getPublisherHome();
212
213         // Find or create the publisher.
214

215         try
216         {
217             publisher = publisherHome.findByName(publisherName);
218         }
219         catch (FinderException JavaDoc e)
220         {
221             // Ignore, means that no publisher with the given name already exists.
222
}
223
224         if (publisher == null)
225             publisher = publisherHome.create(publisherName);
226
227         attributes.put("publisherId", publisher.getPrimaryKey());
228
229         return addBook(attributes);
230     }
231
232     /**
233      * Updates a book.
234      *
235      * <p>Returns the updated book.
236      *
237      * @param bookId The primary key of the book to update.
238      *
239      **/

240
241     public void updateBook(Integer JavaDoc bookId, Map JavaDoc attributes) throws FinderException JavaDoc, RemoteException JavaDoc
242     {
243         IBookHome bookHome = getBookHome();
244
245         IBook book = bookHome.findByPrimaryKey(bookId);
246
247         book.updateEntityAttributes(attributes);
248     }
249
250     /**
251      * Updates a book, adding a new Publisher at the same time.
252      *
253      *
254      * @param bookPK The primary key of the book to update.
255      * @param attributes attributes to change
256      * @param publisherName The name of the new publisher.
257      * @throws FinderException if the book, holder or publisher can not be located.
258      * @throws CreateException if the {@link IPublisher} can not be created.
259      **/

260
261     public void updateBook(Integer JavaDoc bookId, Map JavaDoc attributes, String JavaDoc publisherName)
262         throws CreateException JavaDoc, FinderException JavaDoc, RemoteException JavaDoc
263     {
264         IPublisher publisher = null;
265
266         IPublisherHome publisherHome = getPublisherHome();
267
268         try
269         {
270             publisher = publisherHome.findByName(publisherName);
271         }
272         catch (FinderException JavaDoc e)
273         {
274             // Ignore, means we need to create the Publisher
275
}
276
277         if (publisher == null)
278             publisher = publisherHome.create(publisherName);
279
280         // Don't duplicate all that other code!
281

282         attributes.put("publisherId", publisher.getPrimaryKey());
283
284         updateBook(bookId, attributes);
285     }
286
287     public void updatePerson(Integer JavaDoc personId, Map JavaDoc attributes)
288         throws FinderException JavaDoc, RemoteException JavaDoc
289     {
290         IPersonHome home = getPersonHome();
291
292         IPerson person = home.findByPrimaryKey(personId);
293
294         person.updateEntityAttributes(attributes);
295     }
296
297     public Publisher[] getPublishers()
298     {
299         Connection JavaDoc connection = null;
300         IStatement statement = null;
301         ResultSet JavaDoc set = null;
302
303         List JavaDoc list = new ArrayList JavaDoc();
304
305         try
306         {
307             connection = getConnection();
308
309             StatementAssembly assembly = new StatementAssembly();
310
311             assembly.newLine("SELECT PUBLISHER_ID, NAME");
312             assembly.newLine("FROM PUBLISHER");
313             assembly.newLine("ORDER BY NAME");
314
315             statement = assembly.createStatement(connection);
316
317             set = statement.executeQuery();
318
319             while (set.next())
320             {
321                 Integer JavaDoc primaryKey = (Integer JavaDoc) set.getObject(1);
322                 String JavaDoc name = set.getString(2);
323
324                 list.add(new Publisher(primaryKey, name));
325             }
326         }
327         catch (SQLException JavaDoc ex)
328         {
329             ex.printStackTrace();
330             throw new XEJBException("Could not fetch all Publishers.", ex);
331         }
332         finally
333         {
334             close(connection, statement, set);
335         }
336
337         // Convert from List to Publisher[]
338

339         return (Publisher[]) list.toArray(new Publisher[list.size()]);
340     }
341
342     /**
343      * Fetchs all {@link IPerson} beans in the database and converts them
344      * to {@link Person} objects.
345      *
346      * Returns the {@link Person}s sorted by last name, then first.
347      **/

348
349     public Person[] getPersons()
350     {
351         Connection JavaDoc connection = null;
352         IStatement statement = null;
353         ResultSet JavaDoc set = null;
354
355         List JavaDoc list = new ArrayList JavaDoc();
356
357         try
358         {
359             connection = getConnection();
360
361             StatementAssembly assembly = buildBasePersonQuery();
362             assembly.newLine("ORDER BY LAST_NAME, FIRST_NAME");
363
364             statement = assembly.createStatement(connection);
365
366             set = statement.executeQuery();
367
368             Object JavaDoc[] columns = new Object JavaDoc[Person.N_COLUMNS];
369
370             while (set.next())
371             {
372                 list.add(convertRowToPerson(set, columns));
373             }
374         }
375         catch (SQLException JavaDoc ex)
376         {
377             throw new XEJBException("Could not fetch all Persons.", ex);
378         }
379         finally
380         {
381             close(connection, statement, set);
382         }
383
384         return (Person[]) list.toArray(new Person[list.size()]);
385     }
386
387     /**
388      * Gets the {@link Person} for primary key.
389      *
390      * @throws FinderException if the Person does not exist.
391      **/

392
393     public Person getPerson(Integer JavaDoc personId) throws FinderException JavaDoc
394     {
395         Connection JavaDoc connection = null;
396         IStatement statement = null;
397         ResultSet JavaDoc set = null;
398
399         Person result = null;
400
401         try
402         {
403             connection = getConnection();
404
405             StatementAssembly assembly = buildBasePersonQuery();
406             assembly.newLine("WHERE ");
407             assembly.add("PERSON_ID = ");
408             assembly.addParameter(personId);
409             assembly.newLine("ORDER BY LAST_NAME, FIRST_NAME");
410
411             statement = assembly.createStatement(connection);
412
413             set = statement.executeQuery();
414
415             if (!set.next())
416                 throw new FinderException JavaDoc("Person #" + personId + " does not exist.");
417
418             Object JavaDoc[] columns = new Object JavaDoc[Person.N_COLUMNS];
419             result = convertRowToPerson(set, columns);
420
421         }
422         catch (SQLException JavaDoc ex)
423         {
424             throw new XEJBException("Unable to perform database query.", ex);
425         }
426         finally
427         {
428             close(connection, statement, set);
429         }
430
431         return result;
432     }
433
434     public Person login(String JavaDoc email, String JavaDoc password) throws RemoteException JavaDoc, LoginException
435     {
436         IPersonHome home = getPersonHome();
437         IPerson person = null;
438         Person result = null;
439
440         try
441         {
442             person = home.findByEmail(email);
443         }
444         catch (FinderException JavaDoc ex)
445         {
446             throw new LoginException("Unknown e-mail address.", false);
447         }
448
449         if (!person.getPassword().equals(password))
450             throw new LoginException("Invalid password.", true);
451
452         try
453         {
454             result = getPerson((Integer JavaDoc) person.getPrimaryKey());
455         }
456         catch (FinderException JavaDoc ex)
457         {
458             throw new LoginException("Could not read person.", false);
459         }
460
461         if (result.isLockedOut())
462             throw new LoginException("You have been locked out of the Virtual Library.", false);
463
464         // Set the last access time for any subsequent login.
465

466         person.setLastAccess(new Timestamp JavaDoc(System.currentTimeMillis()));
467
468         return result;
469     }
470
471     public Map JavaDoc getPersonAttributes(Integer JavaDoc personId) throws FinderException JavaDoc, RemoteException JavaDoc
472     {
473         IPersonHome home = getPersonHome();
474
475         IPerson person = home.findByPrimaryKey(personId);
476
477         return person.getEntityAttributes();
478     }
479
480     /**
481      * Retrieves a single {@link Book} by its primary key.
482      *
483      * @throws FinderException if the Book does not exist.
484      *
485      **/

486
487     public Book getBook(Integer JavaDoc bookId) throws FinderException JavaDoc
488     {
489         Connection JavaDoc connection = null;
490         IStatement statement = null;
491         ResultSet JavaDoc set = null;
492
493         Book result = null;
494
495         try
496         {
497             connection = getConnection();
498
499             StatementAssembly assembly = buildBaseBookQuery();
500             assembly.addSep(" AND ");
501             assembly.add("book.BOOK_ID = ");
502             assembly.addParameter(bookId);
503
504             statement = assembly.createStatement(connection);
505
506             set = statement.executeQuery();
507
508             if (!set.next())
509                 throw new FinderException JavaDoc("Book " + bookId + " does not exist.");
510
511             Object JavaDoc[] columns = new Object JavaDoc[Book.N_COLUMNS];
512             result = convertRowToBook(set, columns);
513
514         }
515         catch (SQLException JavaDoc ex)
516         {
517             throw new XEJBException("Unable to perform database query.", ex);
518         }
519         finally
520         {
521             close(connection, statement, set);
522         }
523
524         return result;
525     }
526
527     public Map JavaDoc getBookAttributes(Integer JavaDoc bookId) throws FinderException JavaDoc, RemoteException JavaDoc
528     {
529         IBookHome home = getBookHome();
530
531         IBook book = home.findByPrimaryKey(bookId);
532
533         return book.getEntityAttributes();
534     }
535
536     /**
537      * Attempts to register a new user, first checking that the
538      * e-mail and names are unique. Returns the primary key of the
539      * new {@link IPerson}.
540      *
541      **/

542
543     public Person registerNewUser(String JavaDoc firstName, String JavaDoc lastName, String JavaDoc email, String JavaDoc password)
544         throws RegistrationException, CreateException JavaDoc, RemoteException JavaDoc
545     {
546         IPersonHome home;
547
548         if (password == null || password.trim().length() == 0)
549             throw new RegistrationException("Must specify a password.");
550
551         validateUniquePerson(firstName, lastName, email);
552
553         home = getPersonHome();
554
555         Map JavaDoc attributes = new HashMap JavaDoc();
556
557         attributes.put("lastName", lastName.trim());
558         attributes.put("firstName", firstName.trim());
559         attributes.put("email", email.trim());
560         attributes.put("password", password.trim());
561         attributes.put("lastAccess", new Timestamp JavaDoc(System.currentTimeMillis()));
562
563         IPerson person = home.create(attributes);
564
565         Integer JavaDoc personId = (Integer JavaDoc) person.getPrimaryKey();
566
567         try
568         {
569             return getPerson(personId);
570         }
571         catch (FinderException JavaDoc ex)
572         {
573             throw new XCreateException("Unable to find newly created Person.", ex);
574         }
575     }
576
577     public Book deleteBook(Integer JavaDoc bookId) throws RemoveException JavaDoc, RemoteException JavaDoc
578     {
579         IBookHome home = getBookHome();
580         Book result = null;
581
582         try
583         {
584             result = getBook(bookId);
585         }
586         catch (FinderException JavaDoc ex)
587         {
588             throw new XRemoveException(ex);
589         }
590
591         home.remove(bookId);
592
593         return result;
594
595     }
596
597     /**
598      * Transfers a number of books to a new owner.
599      *
600      **/

601
602     public void transferBooks(Integer JavaDoc newOwnerId, Integer JavaDoc[] bookIds)
603         throws FinderException JavaDoc, RemoteException JavaDoc
604     {
605         if (bookIds == null)
606             throw new RemoteException JavaDoc("Must supply non-null list of books to transfer.");
607
608         if (newOwnerId == null)
609             throw new RemoteException JavaDoc("Must provide an owner for the books.");
610
611         // Verify that the new owner exists.
612

613         IPersonHome personHome = getPersonHome();
614         personHome.findByPrimaryKey(newOwnerId);
615
616         // Direct SQL would be more efficient, but this'll probably do.
617

618         IBookHome home = getBookHome();
619
620         for (int i = 0; i < bookIds.length; i++)
621         {
622             IBook book = home.findByPrimaryKey(bookIds[i]);
623
624             book.setOwnerId(newOwnerId);
625         }
626     }
627
628     public void updatePublishers(Publisher[] updated, Integer JavaDoc[] deleted)
629         throws FinderException JavaDoc, RemoveException JavaDoc, RemoteException JavaDoc
630     {
631         IPublisherHome home = getPublisherHome();
632
633         if (updated != null)
634         {
635             for (int i = 0; i < updated.length; i++)
636             {
637                 IPublisher publisher = home.findByPrimaryKey(updated[i].getId());
638                 publisher.setName(updated[i].getName());
639             }
640         }
641
642         if (deleted != null)
643         {
644             for (int i = 0; i < deleted.length; i++)
645             {
646                 home.remove(deleted[i]);
647             }
648         }
649     }
650
651     public void updatePersons(
652         Person[] updated,
653         Integer JavaDoc[] resetPassword,
654         String JavaDoc newPassword,
655         Integer JavaDoc[] deleted,
656         Integer JavaDoc adminId)
657         throws FinderException JavaDoc, RemoveException JavaDoc, RemoteException JavaDoc
658     {
659         IPersonHome home = getPersonHome();
660
661         int count = Tapestry.size(updated);
662
663         for (int i = 0; i < count; i++)
664         {
665             Person u = updated[i];
666             IPerson person = home.findByPrimaryKey(u.getId());
667
668             person.setAdmin(u.isAdmin());
669             person.setLockedOut(u.isLockedOut());
670         }
671
672         count = Tapestry.size(resetPassword);
673
674         for (int i = 0; i < count; i++)
675         {
676             IPerson person = home.findByPrimaryKey(resetPassword[i]);
677
678             person.setPassword(newPassword);
679         }
680
681         count = Tapestry.size(deleted);
682
683         if (count > 0)
684         {
685             returnBooksFromDeletedPersons(deleted);
686             moveBooksFromDeletedPersons(deleted, adminId);
687         }
688
689         for (int i = 0; i < count; i++)
690             home.remove(deleted[i]);
691     }
692
693     /**
694      * Invoked to update all books owned by people about to be deleted, to
695      * reassign the books holder back to the owner.
696      *
697      **/

698
699     private void returnBooksFromDeletedPersons(Integer JavaDoc deletedPersonIds[]) throws RemoveException JavaDoc
700     {
701         StatementAssembly assembly = new StatementAssembly();
702
703         assembly.add("UPDATE BOOK");
704         assembly.newLine("SET HOLDER_ID = OWNER_ID");
705         assembly.newLine("WHERE HOLDER_ID IN (");
706         assembly.addParameterList(deletedPersonIds, ", ");
707         assembly.add(")");
708
709         executeUpdate(assembly);
710     }
711
712     /**
713      * Invoked to execute a bulk update that moves books to the new admin.
714      *
715      **/

716
717     private void moveBooksFromDeletedPersons(Integer JavaDoc deletedPersonIds[], Integer JavaDoc adminId)
718         throws RemoveException JavaDoc
719     {
720         StatementAssembly assembly = new StatementAssembly();
721
722         assembly.add("UPDATE BOOK");
723         assembly.newLine("SET OWNER_ID = ");
724         assembly.addParameter(adminId);
725         assembly.newLine("WHERE OWNER_ID IN (");
726         assembly.addParameterList(deletedPersonIds, ", ");
727         assembly.add(")");
728
729         executeUpdate(assembly);
730
731     }
732
733     private void executeUpdate(StatementAssembly assembly) throws XRemoveException
734     {
735         Connection JavaDoc connection = null;
736         IStatement statement = null;
737
738         try
739         {
740             connection = getConnection();
741
742             statement = assembly.createStatement(connection);
743
744             statement.executeUpdate();
745
746             statement.close();
747             statement = null;
748
749             connection.close();
750             connection = null;
751         }
752         catch (SQLException JavaDoc ex)
753         {
754             throw new XRemoveException(
755                 "Unable to execute " + assembly + ": " + ex.getMessage(),
756                 ex);
757         }
758         finally
759         {
760             close(connection, statement, null);
761         }
762     }
763
764     /**
765      * Translates the next row from the result set into a {@link Book}.
766      *
767      * <p>This works with queries generated by {@link #buildBaseBookQuery()}.
768      *
769      **/

770
771     protected Book convertRowToBook(ResultSet JavaDoc set, Object JavaDoc[] columns) throws SQLException JavaDoc
772     {
773         int column = 1;
774
775         columns[Book.ID_COLUMN] = set.getObject(column++);
776         columns[Book.TITLE_COLUMN] = set.getString(column++);
777         columns[Book.DESCRIPTION_COLUMN] = set.getString(column++);
778         columns[Book.ISBN_COLUMN] = set.getString(column++);
779         columns[Book.OWNER_ID_COLUMN] = set.getObject(column++);
780         columns[Book.OWNER_NAME_COLUMN] =
781             buildName(set.getString(column++), set.getString(column++));
782         columns[Book.HOLDER_ID_COLUMN] = set.getObject(column++);
783         columns[Book.HOLDER_NAME_COLUMN] =
784             buildName(set.getString(column++), set.getString(column++));
785         columns[Book.PUBLISHER_ID_COLUMN] = set.getObject(column++);
786         columns[Book.PUBLISHER_NAME_COLUMN] = set.getString(column++);
787         columns[Book.AUTHOR_COLUMN] = set.getString(column++);
788         columns[Book.HIDDEN_COLUMN] = getBoolean(set, column++);
789         columns[Book.LENDABLE_COLUMN] = getBoolean(set, column++);
790         columns[Book.DATE_ADDED_COLUMN] = set.getTimestamp(column++);
791
792         return new Book(columns);
793     }
794
795     private String JavaDoc buildName(String JavaDoc firstName, String JavaDoc lastName)
796     {
797         if (firstName == null)
798             return lastName;
799
800         return firstName + " " + lastName;
801     }
802
803     /**
804      * All queries must use this exact set of select columns, so that
805      * {@link #convertRow(ResultSet, Object[])} can build
806      * the correct {@link Book} from each row.
807      *
808      **/

809
810     private static final String JavaDoc[] BOOK_SELECT_COLUMNS =
811         {
812             "book.BOOK_ID",
813             "book.TITLE",
814             "book.DESCRIPTION",
815             "book.ISBN",
816             "owner.PERSON_ID",
817             "owner.FIRST_NAME",
818             "owner.LAST_NAME",
819             "holder.PERSON_ID",
820             "holder.FIRST_NAME",
821             "holder.LAST_NAME",
822             "publisher.PUBLISHER_ID",
823             "publisher.NAME",
824             "book.AUTHOR",
825             "book.HIDDEN",
826             "book.LENDABLE",
827             "book.DATE_ADDED" };
828
829     private static final String JavaDoc[] BOOK_ALIAS_COLUMNS =
830         { "BOOK book", "PERSON owner", "PERSON holder", "PUBLISHER publisher" };
831
832     private static final String JavaDoc[] BOOK_JOINS =
833         {
834             "book.OWNER_ID = owner.PERSON_ID",
835             "book.HOLDER_ID = holder.PERSON_ID",
836             "book.PUBLISHER_ID = publisher.PUBLISHER_ID" };
837
838     private static final Map JavaDoc BOOK_SORT_ASCENDING = new HashMap JavaDoc();
839     private static final Map JavaDoc BOOK_SORT_DESCENDING = new HashMap JavaDoc();
840
841     static {
842         BOOK_SORT_ASCENDING.put(SortColumn.TITLE, "book.TITLE");
843         BOOK_SORT_ASCENDING.put(SortColumn.HOLDER, "holder.LAST_NAME, holder.FIRST_NAME");
844         BOOK_SORT_ASCENDING.put(SortColumn.OWNER, "owner.FIRST_NAME, owner.LAST_NAME");
845         BOOK_SORT_ASCENDING.put(SortColumn.PUBLISHER, "publisher.NAME");
846         BOOK_SORT_ASCENDING.put(SortColumn.AUTHOR, "book.AUTHOR");
847
848         BOOK_SORT_DESCENDING.put(SortColumn.TITLE, "book.TITLE DESC");
849         BOOK_SORT_DESCENDING.put(
850             SortColumn.HOLDER,
851             "holder.LAST_NAME DESC, holder.FIRST_NAME DESC");
852         BOOK_SORT_DESCENDING.put(SortColumn.OWNER, "owner.FIRST_NAME DESC, owner.LAST_NAME DESC");
853         BOOK_SORT_DESCENDING.put(SortColumn.PUBLISHER, "publisher.NAME DESC");
854         BOOK_SORT_DESCENDING.put(SortColumn.AUTHOR, "book.AUTHOR DESC");
855     }
856
857     protected StatementAssembly buildBaseBookQuery()
858     {
859         StatementAssembly result = new StatementAssembly();
860
861         result.newLine("SELECT ");
862         result.addList(BOOK_SELECT_COLUMNS, ", ");
863
864         result.newLine("FROM ");
865         result.addList(BOOK_ALIAS_COLUMNS, ", ");
866
867         result.newLine("WHERE ");
868         result.addList(BOOK_JOINS, " AND ");
869
870         return result;
871     }
872
873     /**
874      * Adds a sort ordering clause to the statement. If ordering is null,
875      * orders by book title.
876      *
877      * @param assembly to update
878      * @param ordering defines the column to sort on, and the order (ascending or descending)
879      * @since 3.0
880      *
881      *
882      **/

883
884     protected void addSortOrdering(StatementAssembly assembly, SortOrdering ordering)
885     {
886         if (ordering == null)
887         {
888             assembly.newLine("ORDER BY book.TITLE");
889             return;
890         }
891
892         Map JavaDoc sorts = ordering.isDescending() ? BOOK_SORT_DESCENDING : BOOK_SORT_ASCENDING;
893
894         String JavaDoc term = (String JavaDoc) sorts.get(ordering.getColumn());
895
896         assembly.newLine("ORDER BY ");
897         assembly.add(term);
898     }
899
900     protected void addSubstringSearch(StatementAssembly assembly, String JavaDoc column, String JavaDoc value)
901     {
902         if (value == null)
903             return;
904
905         String JavaDoc trimmed = value.trim();
906         if (trimmed.length() == 0)
907             return;
908
909         // Here's the McKoi dependency: LOWER() is a database-specific
910
// SQL function.
911

912         assembly.addSep(" AND LOWER(");
913         assembly.add(column);
914         assembly.add(") LIKE");
915         assembly.addParameter("%" + trimmed.toLowerCase() + "%");
916     }
917
918     /**
919      * Closes the resultSet (if not null), then the statement (if not null),
920      * then the Connection (if not null). Exceptions are written to System.out.
921      *
922      **/

923
924     protected void close(Connection JavaDoc connection, IStatement statement, ResultSet JavaDoc resultSet)
925     {
926         if (resultSet != null)
927         {
928             try
929             {
930                 resultSet.close();
931             }
932             catch (SQLException JavaDoc ex)
933             {
934                 System.out.println("Exception closing result set.");
935                 ex.printStackTrace();
936             }
937         }
938
939         if (statement != null)
940         {
941             try
942             {
943                 statement.close();
944             }
945             catch (SQLException JavaDoc ex)
946             {
947                 System.out.println("Exception closing statement.");
948                 ex.printStackTrace();
949             }
950         }
951
952         if (connection != null)
953         {
954             try
955             {
956                 connection.close();
957             }
958             catch (SQLException JavaDoc ex)
959             {
960                 System.out.println("Exception closing connection.");
961                 ex.printStackTrace();
962             }
963         }
964     }
965
966     private IPersonHome getPersonHome()
967     {
968         if (_personHome == null)
969         {
970             try
971             {
972                 Object JavaDoc raw = _environment.lookup("ejb/Person");
973
974                 _personHome = (IPersonHome) PortableRemoteObject.narrow(raw, IPersonHome.class);
975             }
976             catch (NamingException JavaDoc ex)
977             {
978                 throw new XEJBException("Could not lookup Person home interface.", ex);
979             }
980
981         }
982
983         return _personHome;
984     }
985
986     private IPublisherHome getPublisherHome()
987     {
988         if (_publisherHome == null)
989         {
990             try
991             {
992                 Object JavaDoc raw = _environment.lookup("ejb/Publisher");
993
994                 _publisherHome =
995                     (IPublisherHome) PortableRemoteObject.narrow(raw, IPublisherHome.class);
996             }
997             catch (NamingException JavaDoc e)
998             {
999                 throw new XEJBException("Could not lookup Publisher home interface.", e);
1000            }
1001
1002        }
1003
1004        return _publisherHome;
1005    }
1006
1007    private IBookHome getBookHome()
1008    {
1009        if (_bookHome == null)
1010        {
1011            try
1012            {
1013                Object JavaDoc raw = _environment.lookup("ejb/Book");
1014
1015                _bookHome = (IBookHome) PortableRemoteObject.narrow(raw, IBookHome.class);
1016            }
1017            catch (NamingException JavaDoc e)
1018            {
1019                throw new XEJBException("Could not lookup Book home interface.", e);
1020            }
1021
1022        }
1023
1024        return _bookHome;
1025    }
1026
1027    /**
1028     * Gets a new connection from the data source.
1029     *
1030     **/

1031
1032    protected Connection JavaDoc getConnection()
1033    {
1034        try
1035        {
1036            return _dataSource.getConnection();
1037        }
1038        catch (SQLException JavaDoc e)
1039        {
1040            throw new XEJBException("Unable to get database connection from pool.", e);
1041        }
1042    }
1043
1044    protected StatementAssembly buildBasePersonQuery()
1045    {
1046        StatementAssembly result;
1047
1048        result = new StatementAssembly();
1049
1050        result.newLine("SELECT PERSON_ID, FIRST_NAME, LAST_NAME, EMAIL, ");
1051        result.newLine(" LOCKED_OUT, ADMIN, LAST_ACCESS");
1052        result.newLine("FROM PERSON");
1053
1054        return result;
1055    }
1056
1057    /**
1058     * Translates the next row from the result set into a {@link Person}.
1059     *
1060     * <p>This works with queries generated by {@link #buildBasePersonQuery()}.
1061     *
1062     **/

1063
1064    protected Person convertRowToPerson(ResultSet JavaDoc set, Object JavaDoc[] columns) throws SQLException JavaDoc
1065    {
1066        int column = 1;
1067
1068        columns[Person.ID_COLUMN] = set.getObject(column++);
1069        columns[Person.FIRST_NAME_COLUMN] = set.getString(column++);
1070        columns[Person.LAST_NAME_COLUMN] = set.getString(column++);
1071        columns[Person.EMAIL_COLUMN] = set.getString(column++);
1072        columns[Person.LOCKED_OUT_COLUMN] = getBoolean(set, column++);
1073        columns[Person.ADMIN_COLUMN] = getBoolean(set, column++);
1074        columns[Person.LAST_ACCESS_COLUMN] = set.getTimestamp(column++);
1075
1076        return new Person(columns);
1077    }
1078
1079    private Boolean JavaDoc getBoolean(ResultSet JavaDoc set, int index) throws SQLException JavaDoc
1080    {
1081        return set.getBoolean(index) ? Boolean.TRUE : Boolean.FALSE;
1082    }
1083
1084    private void validateUniquePerson(String JavaDoc firstName, String JavaDoc lastName, String JavaDoc email)
1085        throws RegistrationException
1086    {
1087        Connection JavaDoc connection = null;
1088        IStatement statement = null;
1089        ResultSet JavaDoc set = null;
1090
1091        String JavaDoc trimmedEmail = email.trim().toLowerCase();
1092        String JavaDoc trimmedLastName = lastName.trim().toLowerCase();
1093        String JavaDoc trimmedFirstName = firstName.trim().toLowerCase();
1094
1095        try
1096        {
1097            connection = getConnection();
1098
1099            StatementAssembly assembly = new StatementAssembly();
1100            assembly.newLine("SELECT PERSON_ID");
1101            assembly.newLine("FROM PERSON");
1102            assembly.newLine("WHERE ");
1103
1104            assembly.add("LOWER(EMAIL) = ");
1105            assembly.addParameter(trimmedEmail);
1106
1107            statement = assembly.createStatement(connection);
1108            set = statement.executeQuery();
1109
1110            if (set.next())
1111                throw new RegistrationException("Email address is already in use by another user.");
1112
1113            close(null, statement, set);
1114
1115            assembly = new StatementAssembly();
1116            assembly.newLine("SELECT PERSON_ID");
1117            assembly.newLine("FROM PERSON");
1118            assembly.newLine("WHERE ");
1119
1120            assembly.add("LOWER(FIRST_NAME) = ");
1121            assembly.addParameter(trimmedFirstName);
1122            assembly.addSep(" AND ");
1123            assembly.add("LOWER(LAST_NAME) = ");
1124            assembly.addParameter(trimmedLastName);
1125
1126            statement = assembly.createStatement(connection);
1127            set = statement.executeQuery();
1128
1129            if (set.next())
1130                throw new RegistrationException("Name provided is already in use by another user.");
1131
1132        }
1133        catch (SQLException JavaDoc e)
1134        {
1135            throw new RegistrationException("Could not access database: " + e.getMessage(), e);
1136        }
1137        finally
1138        {
1139            close(connection, statement, set);
1140        }
1141    }
1142
1143    public Book returnBook(Integer JavaDoc bookId) throws RemoteException JavaDoc, FinderException JavaDoc
1144    {
1145        IBookHome bookHome = getBookHome();
1146        IBook book = bookHome.findByPrimaryKey(bookId);
1147
1148        Integer JavaDoc ownerPK = book.getOwnerId();
1149
1150        book.setHolderId(ownerPK);
1151
1152        return getBook(bookId);
1153    }
1154
1155}
Popular Tags