blob: 90bbe2902081daa5212d21908fd942200a9cb81e [file] [log] [blame]
// Copyright 2004 The Apache Software Foundation
//
// Licensed 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 org.apache.tapestry.vlib.ejb.impl;
import java.rmi.RemoteException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ejb.CreateException;
import javax.ejb.FinderException;
import javax.ejb.RemoveException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;
import javax.sql.DataSource;
import org.apache.tapestry.Tapestry;
import org.apache.tapestry.contrib.ejb.XCreateException;
import org.apache.tapestry.contrib.ejb.XEJBException;
import org.apache.tapestry.contrib.ejb.XRemoveException;
import org.apache.tapestry.contrib.jdbc.IStatement;
import org.apache.tapestry.contrib.jdbc.StatementAssembly;
import org.apache.tapestry.vlib.ejb.Book;
import org.apache.tapestry.vlib.ejb.BorrowException;
import org.apache.tapestry.vlib.ejb.IBook;
import org.apache.tapestry.vlib.ejb.IBookHome;
import org.apache.tapestry.vlib.ejb.IPerson;
import org.apache.tapestry.vlib.ejb.IPersonHome;
import org.apache.tapestry.vlib.ejb.IPublisher;
import org.apache.tapestry.vlib.ejb.IPublisherHome;
import org.apache.tapestry.vlib.ejb.LoginException;
import org.apache.tapestry.vlib.ejb.Person;
import org.apache.tapestry.vlib.ejb.Publisher;
import org.apache.tapestry.vlib.ejb.RegistrationException;
import org.apache.tapestry.vlib.ejb.SortColumn;
import org.apache.tapestry.vlib.ejb.SortOrdering;
/**
* Implementation of the {@link org.apache.tapestry.vlib.ejb.IOperations}
* stateless session bean.
*
* <p>Implenents a number of stateless operations for the front end.
*
* @version $Id$
* @author Howard Lewis Ship
*
**/
public class OperationsBean implements SessionBean
{
private SessionContext _context;
private transient Context _environment;
private transient IBookHome _bookHome;
private transient IPersonHome _personHome;
private transient IPublisherHome _publisherHome;
/**
* Data source, retrieved from the ENC property
* "jdbc/dataSource".
*
**/
private transient DataSource _dataSource;
/**
* Sets up the bean. Locates the {@link DataSource} for the bean
* as <code>jdbc/dataSource</code> within the ENC; this data source is
* later used by {@link #getConnection()}.
*
**/
public void ejbCreate()
{
Context initial;
try
{
initial = new InitialContext();
_environment = (Context) initial.lookup("java:comp/env");
}
catch (NamingException e)
{
throw new XEJBException("Could not lookup environment.", e);
}
try
{
_dataSource = (DataSource) _environment.lookup("jdbc/dataSource");
}
catch (NamingException e)
{
e.printStackTrace();
throw new XEJBException("Could not lookup data source.", e);
}
}
public void ejbRemove()
{
}
/**
* Does nothing, not invoked in stateless session beans.
**/
public void ejbPassivate()
{
}
public void setSessionContext(SessionContext value)
{
_context = value;
}
/**
* Does nothing, not invoked in stateless session beans.
*
**/
public void ejbActivate()
{
}
/**
* Finds the book and borrower (by thier primary keys) and updates the book.
*
* <p>The {@link Book} value object is returned.
*
**/
public Book borrowBook(Integer bookId, Integer borrowerId)
throws FinderException, RemoteException, BorrowException
{
IBookHome bookHome = getBookHome();
IPersonHome personHome = getPersonHome();
IBook book = bookHome.findByPrimaryKey(bookId);
if (!book.getLendable())
throw new BorrowException("Book may not be borrowed.");
// Verify that the borrower exists.
personHome.findByPrimaryKey(borrowerId);
// TBD: Check that borrower has authenticated
// findByPrimaryKey() throws an exception if the EJB doesn't exist,
// so we're safe.
personHome.findByPrimaryKey(book.getOwnerId());
// Here's the real work; just setting the holder of the book
// to be the borrower.
book.setHolderId(borrowerId);
return getBook(bookId);
}
/**
* Adds a new book, verifying that the publisher and holder actually exist.
*
**/
public Integer addBook(Map attributes) throws CreateException, RemoteException
{
IBookHome home = getBookHome();
attributes.put("dateAdded", new Timestamp(System.currentTimeMillis()));
IBook book = home.create(attributes);
return (Integer) book.getPrimaryKey();
}
/**
* Adds a book, which will be owned and held by the specified owner.
*
* <p>The publisherName may either be the name of a known publisher, or
* a new name. A new {@link IPublisher} will be created as necessary.
*
* <p>Returns the newly created book, as a {@link Map} of attributes.
*
**/
public Integer addBook(Map attributes, String publisherName)
throws CreateException, RemoteException
{
IPublisher publisher = null;
IPublisherHome publisherHome = getPublisherHome();
// Find or create the publisher.
try
{
publisher = publisherHome.findByName(publisherName);
}
catch (FinderException e)
{
// Ignore, means that no publisher with the given name already exists.
}
if (publisher == null)
publisher = publisherHome.create(publisherName);
attributes.put("publisherId", publisher.getPrimaryKey());
return addBook(attributes);
}
/**
* Updates a book.
*
* <p>Returns the updated book.
*
* @param bookId The primary key of the book to update.
*
**/
public void updateBook(Integer bookId, Map attributes) throws FinderException, RemoteException
{
IBookHome bookHome = getBookHome();
IBook book = bookHome.findByPrimaryKey(bookId);
book.updateEntityAttributes(attributes);
}
/**
* Updates a book, adding a new Publisher at the same time.
*
*
* @param bookPK The primary key of the book to update.
* @param attributes attributes to change
* @param publisherName The name of the new publisher.
* @throws FinderException if the book, holder or publisher can not be located.
* @throws CreateException if the {@link IPublisher} can not be created.
**/
public void updateBook(Integer bookId, Map attributes, String publisherName)
throws CreateException, FinderException, RemoteException
{
IPublisher publisher = null;
IPublisherHome publisherHome = getPublisherHome();
try
{
publisher = publisherHome.findByName(publisherName);
}
catch (FinderException e)
{
// Ignore, means we need to create the Publisher
}
if (publisher == null)
publisher = publisherHome.create(publisherName);
// Don't duplicate all that other code!
attributes.put("publisherId", publisher.getPrimaryKey());
updateBook(bookId, attributes);
}
public void updatePerson(Integer personId, Map attributes)
throws FinderException, RemoteException
{
IPersonHome home = getPersonHome();
IPerson person = home.findByPrimaryKey(personId);
person.updateEntityAttributes(attributes);
}
public Publisher[] getPublishers()
{
Connection connection = null;
IStatement statement = null;
ResultSet set = null;
List list = new ArrayList();
try
{
connection = getConnection();
StatementAssembly assembly = new StatementAssembly();
assembly.newLine("SELECT PUBLISHER_ID, NAME");
assembly.newLine("FROM PUBLISHER");
assembly.newLine("ORDER BY NAME");
statement = assembly.createStatement(connection);
set = statement.executeQuery();
while (set.next())
{
Integer primaryKey = (Integer) set.getObject(1);
String name = set.getString(2);
list.add(new Publisher(primaryKey, name));
}
}
catch (SQLException ex)
{
ex.printStackTrace();
throw new XEJBException("Could not fetch all Publishers.", ex);
}
finally
{
close(connection, statement, set);
}
// Convert from List to Publisher[]
return (Publisher[]) list.toArray(new Publisher[list.size()]);
}
/**
* Fetchs all {@link IPerson} beans in the database and converts them
* to {@link Person} objects.
*
* Returns the {@link Person}s sorted by last name, then first.
**/
public Person[] getPersons()
{
Connection connection = null;
IStatement statement = null;
ResultSet set = null;
List list = new ArrayList();
try
{
connection = getConnection();
StatementAssembly assembly = buildBasePersonQuery();
assembly.newLine("ORDER BY LAST_NAME, FIRST_NAME");
statement = assembly.createStatement(connection);
set = statement.executeQuery();
Object[] columns = new Object[Person.N_COLUMNS];
while (set.next())
{
list.add(convertRowToPerson(set, columns));
}
}
catch (SQLException ex)
{
throw new XEJBException("Could not fetch all Persons.", ex);
}
finally
{
close(connection, statement, set);
}
return (Person[]) list.toArray(new Person[list.size()]);
}
/**
* Gets the {@link Person} for primary key.
*
* @throws FinderException if the Person does not exist.
**/
public Person getPerson(Integer personId) throws FinderException
{
Connection connection = null;
IStatement statement = null;
ResultSet set = null;
Person result = null;
try
{
connection = getConnection();
StatementAssembly assembly = buildBasePersonQuery();
assembly.newLine("WHERE ");
assembly.add("PERSON_ID = ");
assembly.addParameter(personId);
assembly.newLine("ORDER BY LAST_NAME, FIRST_NAME");
statement = assembly.createStatement(connection);
set = statement.executeQuery();
if (!set.next())
throw new FinderException("Person #" + personId + " does not exist.");
Object[] columns = new Object[Person.N_COLUMNS];
result = convertRowToPerson(set, columns);
}
catch (SQLException ex)
{
throw new XEJBException("Unable to perform database query.", ex);
}
finally
{
close(connection, statement, set);
}
return result;
}
public Person login(String email, String password) throws RemoteException, LoginException
{
IPersonHome home = getPersonHome();
IPerson person = null;
Person result = null;
try
{
person = home.findByEmail(email);
}
catch (FinderException ex)
{
throw new LoginException("Unknown e-mail address.", false);
}
if (!person.getPassword().equals(password))
throw new LoginException("Invalid password.", true);
try
{
result = getPerson((Integer) person.getPrimaryKey());
}
catch (FinderException ex)
{
throw new LoginException("Could not read person.", false);
}
if (result.isLockedOut())
throw new LoginException("You have been locked out of the Virtual Library.", false);
// Set the last access time for any subsequent login.
person.setLastAccess(new Timestamp(System.currentTimeMillis()));
return result;
}
public Map getPersonAttributes(Integer personId) throws FinderException, RemoteException
{
IPersonHome home = getPersonHome();
IPerson person = home.findByPrimaryKey(personId);
return person.getEntityAttributes();
}
/**
* Retrieves a single {@link Book} by its primary key.
*
* @throws FinderException if the Book does not exist.
*
**/
public Book getBook(Integer bookId) throws FinderException
{
Connection connection = null;
IStatement statement = null;
ResultSet set = null;
Book result = null;
try
{
connection = getConnection();
StatementAssembly assembly = buildBaseBookQuery();
assembly.addSep(" AND ");
assembly.add("book.BOOK_ID = ");
assembly.addParameter(bookId);
statement = assembly.createStatement(connection);
set = statement.executeQuery();
if (!set.next())
throw new FinderException("Book " + bookId + " does not exist.");
Object[] columns = new Object[Book.N_COLUMNS];
result = convertRowToBook(set, columns);
}
catch (SQLException ex)
{
throw new XEJBException("Unable to perform database query.", ex);
}
finally
{
close(connection, statement, set);
}
return result;
}
public Map getBookAttributes(Integer bookId) throws FinderException, RemoteException
{
IBookHome home = getBookHome();
IBook book = home.findByPrimaryKey(bookId);
return book.getEntityAttributes();
}
/**
* Attempts to register a new user, first checking that the
* e-mail and names are unique. Returns the primary key of the
* new {@link IPerson}.
*
**/
public Person registerNewUser(String firstName, String lastName, String email, String password)
throws RegistrationException, CreateException, RemoteException
{
IPersonHome home;
if (password == null || password.trim().length() == 0)
throw new RegistrationException("Must specify a password.");
validateUniquePerson(firstName, lastName, email);
home = getPersonHome();
Map attributes = new HashMap();
attributes.put("lastName", lastName.trim());
attributes.put("firstName", firstName.trim());
attributes.put("email", email.trim());
attributes.put("password", password.trim());
attributes.put("lastAccess", new Timestamp(System.currentTimeMillis()));
IPerson person = home.create(attributes);
Integer personId = (Integer) person.getPrimaryKey();
try
{
return getPerson(personId);
}
catch (FinderException ex)
{
throw new XCreateException("Unable to find newly created Person.", ex);
}
}
public Book deleteBook(Integer bookId) throws RemoveException, RemoteException
{
IBookHome home = getBookHome();
Book result = null;
try
{
result = getBook(bookId);
}
catch (FinderException ex)
{
throw new XRemoveException(ex);
}
home.remove(bookId);
return result;
}
/**
* Transfers a number of books to a new owner.
*
**/
public void transferBooks(Integer newOwnerId, Integer[] bookIds)
throws FinderException, RemoteException
{
if (bookIds == null)
throw new RemoteException("Must supply non-null list of books to transfer.");
if (newOwnerId == null)
throw new RemoteException("Must provide an owner for the books.");
// Verify that the new owner exists.
IPersonHome personHome = getPersonHome();
personHome.findByPrimaryKey(newOwnerId);
// Direct SQL would be more efficient, but this'll probably do.
IBookHome home = getBookHome();
for (int i = 0; i < bookIds.length; i++)
{
IBook book = home.findByPrimaryKey(bookIds[i]);
book.setOwnerId(newOwnerId);
}
}
public void updatePublishers(Publisher[] updated, Integer[] deleted)
throws FinderException, RemoveException, RemoteException
{
IPublisherHome home = getPublisherHome();
if (updated != null)
{
for (int i = 0; i < updated.length; i++)
{
IPublisher publisher = home.findByPrimaryKey(updated[i].getId());
publisher.setName(updated[i].getName());
}
}
if (deleted != null)
{
for (int i = 0; i < deleted.length; i++)
{
home.remove(deleted[i]);
}
}
}
public void updatePersons(
Person[] updated,
Integer[] resetPassword,
String newPassword,
Integer[] deleted,
Integer adminId)
throws FinderException, RemoveException, RemoteException
{
IPersonHome home = getPersonHome();
int count = Tapestry.size(updated);
for (int i = 0; i < count; i++)
{
Person u = updated[i];
IPerson person = home.findByPrimaryKey(u.getId());
person.setAdmin(u.isAdmin());
person.setLockedOut(u.isLockedOut());
}
count = Tapestry.size(resetPassword);
for (int i = 0; i < count; i++)
{
IPerson person = home.findByPrimaryKey(resetPassword[i]);
person.setPassword(newPassword);
}
count = Tapestry.size(deleted);
if (count > 0)
{
returnBooksFromDeletedPersons(deleted);
moveBooksFromDeletedPersons(deleted, adminId);
}
for (int i = 0; i < count; i++)
home.remove(deleted[i]);
}
/**
* Invoked to update all books owned by people about to be deleted, to
* reassign the books holder back to the owner.
*
**/
private void returnBooksFromDeletedPersons(Integer deletedPersonIds[]) throws RemoveException
{
StatementAssembly assembly = new StatementAssembly();
assembly.add("UPDATE BOOK");
assembly.newLine("SET HOLDER_ID = OWNER_ID");
assembly.newLine("WHERE HOLDER_ID IN (");
assembly.addParameterList(deletedPersonIds, ", ");
assembly.add(")");
executeUpdate(assembly);
}
/**
* Invoked to execute a bulk update that moves books to the new admin.
*
**/
private void moveBooksFromDeletedPersons(Integer deletedPersonIds[], Integer adminId)
throws RemoveException
{
StatementAssembly assembly = new StatementAssembly();
assembly.add("UPDATE BOOK");
assembly.newLine("SET OWNER_ID = ");
assembly.addParameter(adminId);
assembly.newLine("WHERE OWNER_ID IN (");
assembly.addParameterList(deletedPersonIds, ", ");
assembly.add(")");
executeUpdate(assembly);
}
private void executeUpdate(StatementAssembly assembly) throws XRemoveException
{
Connection connection = null;
IStatement statement = null;
try
{
connection = getConnection();
statement = assembly.createStatement(connection);
statement.executeUpdate();
statement.close();
statement = null;
connection.close();
connection = null;
}
catch (SQLException ex)
{
throw new XRemoveException(
"Unable to execute " + assembly + ": " + ex.getMessage(),
ex);
}
finally
{
close(connection, statement, null);
}
}
/**
* Translates the next row from the result set into a {@link Book}.
*
* <p>This works with queries generated by {@link #buildBaseBookQuery()}.
*
**/
protected Book convertRowToBook(ResultSet set, Object[] columns) throws SQLException
{
int column = 1;
columns[Book.ID_COLUMN] = set.getObject(column++);
columns[Book.TITLE_COLUMN] = set.getString(column++);
columns[Book.DESCRIPTION_COLUMN] = set.getString(column++);
columns[Book.ISBN_COLUMN] = set.getString(column++);
columns[Book.OWNER_ID_COLUMN] = set.getObject(column++);
columns[Book.OWNER_NAME_COLUMN] =
buildName(set.getString(column++), set.getString(column++));
columns[Book.HOLDER_ID_COLUMN] = set.getObject(column++);
columns[Book.HOLDER_NAME_COLUMN] =
buildName(set.getString(column++), set.getString(column++));
columns[Book.PUBLISHER_ID_COLUMN] = set.getObject(column++);
columns[Book.PUBLISHER_NAME_COLUMN] = set.getString(column++);
columns[Book.AUTHOR_COLUMN] = set.getString(column++);
columns[Book.HIDDEN_COLUMN] = getBoolean(set, column++);
columns[Book.LENDABLE_COLUMN] = getBoolean(set, column++);
columns[Book.DATE_ADDED_COLUMN] = set.getTimestamp(column++);
return new Book(columns);
}
private String buildName(String firstName, String lastName)
{
if (firstName == null)
return lastName;
return firstName + " " + lastName;
}
/**
* All queries must use this exact set of select columns, so that
* {@link #convertRow(ResultSet, Object[])} can build
* the correct {@link Book} from each row.
*
**/
private static final String[] BOOK_SELECT_COLUMNS =
{
"book.BOOK_ID",
"book.TITLE",
"book.DESCRIPTION",
"book.ISBN",
"owner.PERSON_ID",
"owner.FIRST_NAME",
"owner.LAST_NAME",
"holder.PERSON_ID",
"holder.FIRST_NAME",
"holder.LAST_NAME",
"publisher.PUBLISHER_ID",
"publisher.NAME",
"book.AUTHOR",
"book.HIDDEN",
"book.LENDABLE",
"book.DATE_ADDED" };
private static final String[] BOOK_ALIAS_COLUMNS =
{ "BOOK book", "PERSON owner", "PERSON holder", "PUBLISHER publisher" };
private static final String[] BOOK_JOINS =
{
"book.OWNER_ID = owner.PERSON_ID",
"book.HOLDER_ID = holder.PERSON_ID",
"book.PUBLISHER_ID = publisher.PUBLISHER_ID" };
private static final Map BOOK_SORT_ASCENDING = new HashMap();
private static final Map BOOK_SORT_DESCENDING = new HashMap();
static {
BOOK_SORT_ASCENDING.put(SortColumn.TITLE, "book.TITLE");
BOOK_SORT_ASCENDING.put(SortColumn.HOLDER, "holder.LAST_NAME, holder.FIRST_NAME");
BOOK_SORT_ASCENDING.put(SortColumn.OWNER, "owner.FIRST_NAME, owner.LAST_NAME");
BOOK_SORT_ASCENDING.put(SortColumn.PUBLISHER, "publisher.NAME");
BOOK_SORT_ASCENDING.put(SortColumn.AUTHOR, "book.AUTHOR");
BOOK_SORT_DESCENDING.put(SortColumn.TITLE, "book.TITLE DESC");
BOOK_SORT_DESCENDING.put(
SortColumn.HOLDER,
"holder.LAST_NAME DESC, holder.FIRST_NAME DESC");
BOOK_SORT_DESCENDING.put(SortColumn.OWNER, "owner.FIRST_NAME DESC, owner.LAST_NAME DESC");
BOOK_SORT_DESCENDING.put(SortColumn.PUBLISHER, "publisher.NAME DESC");
BOOK_SORT_DESCENDING.put(SortColumn.AUTHOR, "book.AUTHOR DESC");
}
protected StatementAssembly buildBaseBookQuery()
{
StatementAssembly result = new StatementAssembly();
result.newLine("SELECT ");
result.addList(BOOK_SELECT_COLUMNS, ", ");
result.newLine("FROM ");
result.addList(BOOK_ALIAS_COLUMNS, ", ");
result.newLine("WHERE ");
result.addList(BOOK_JOINS, " AND ");
return result;
}
/**
* Adds a sort ordering clause to the statement. If ordering is null,
* orders by book title.
*
* @param assembly to update
* @param ordering defines the column to sort on, and the order (ascending or descending)
* @since 3.0
*
*
**/
protected void addSortOrdering(StatementAssembly assembly, SortOrdering ordering)
{
if (ordering == null)
{
assembly.newLine("ORDER BY book.TITLE");
return;
}
Map sorts = ordering.isDescending() ? BOOK_SORT_DESCENDING : BOOK_SORT_ASCENDING;
String term = (String) sorts.get(ordering.getColumn());
assembly.newLine("ORDER BY ");
assembly.add(term);
}
protected void addSubstringSearch(StatementAssembly assembly, String column, String value)
{
if (value == null)
return;
String trimmed = value.trim();
if (trimmed.length() == 0)
return;
// Here's the McKoi dependency: LOWER() is a database-specific
// SQL function.
assembly.addSep(" AND LOWER(");
assembly.add(column);
assembly.add(") LIKE");
assembly.addParameter("%" + trimmed.toLowerCase() + "%");
}
/**
* Closes the resultSet (if not null), then the statement (if not null),
* then the Connection (if not null). Exceptions are written to System.out.
*
**/
protected void close(Connection connection, IStatement statement, ResultSet resultSet)
{
if (resultSet != null)
{
try
{
resultSet.close();
}
catch (SQLException ex)
{
System.out.println("Exception closing result set.");
ex.printStackTrace();
}
}
if (statement != null)
{
try
{
statement.close();
}
catch (SQLException ex)
{
System.out.println("Exception closing statement.");
ex.printStackTrace();
}
}
if (connection != null)
{
try
{
connection.close();
}
catch (SQLException ex)
{
System.out.println("Exception closing connection.");
ex.printStackTrace();
}
}
}
private IPersonHome getPersonHome()
{
if (_personHome == null)
{
try
{
Object raw = _environment.lookup("ejb/Person");
_personHome = (IPersonHome) PortableRemoteObject.narrow(raw, IPersonHome.class);
}
catch (NamingException ex)
{
throw new XEJBException("Could not lookup Person home interface.", ex);
}
}
return _personHome;
}
private IPublisherHome getPublisherHome()
{
if (_publisherHome == null)
{
try
{
Object raw = _environment.lookup("ejb/Publisher");
_publisherHome =
(IPublisherHome) PortableRemoteObject.narrow(raw, IPublisherHome.class);
}
catch (NamingException e)
{
throw new XEJBException("Could not lookup Publisher home interface.", e);
}
}
return _publisherHome;
}
private IBookHome getBookHome()
{
if (_bookHome == null)
{
try
{
Object raw = _environment.lookup("ejb/Book");
_bookHome = (IBookHome) PortableRemoteObject.narrow(raw, IBookHome.class);
}
catch (NamingException e)
{
throw new XEJBException("Could not lookup Book home interface.", e);
}
}
return _bookHome;
}
/**
* Gets a new connection from the data source.
*
**/
protected Connection getConnection()
{
try
{
return _dataSource.getConnection();
}
catch (SQLException e)
{
throw new XEJBException("Unable to get database connection from pool.", e);
}
}
protected StatementAssembly buildBasePersonQuery()
{
StatementAssembly result;
result = new StatementAssembly();
result.newLine("SELECT PERSON_ID, FIRST_NAME, LAST_NAME, EMAIL, ");
result.newLine(" LOCKED_OUT, ADMIN, LAST_ACCESS");
result.newLine("FROM PERSON");
return result;
}
/**
* Translates the next row from the result set into a {@link Person}.
*
* <p>This works with queries generated by {@link #buildBasePersonQuery()}.
*
**/
protected Person convertRowToPerson(ResultSet set, Object[] columns) throws SQLException
{
int column = 1;
columns[Person.ID_COLUMN] = set.getObject(column++);
columns[Person.FIRST_NAME_COLUMN] = set.getString(column++);
columns[Person.LAST_NAME_COLUMN] = set.getString(column++);
columns[Person.EMAIL_COLUMN] = set.getString(column++);
columns[Person.LOCKED_OUT_COLUMN] = getBoolean(set, column++);
columns[Person.ADMIN_COLUMN] = getBoolean(set, column++);
columns[Person.LAST_ACCESS_COLUMN] = set.getTimestamp(column++);
return new Person(columns);
}
private Boolean getBoolean(ResultSet set, int index) throws SQLException
{
return set.getBoolean(index) ? Boolean.TRUE : Boolean.FALSE;
}
private void validateUniquePerson(String firstName, String lastName, String email)
throws RegistrationException
{
Connection connection = null;
IStatement statement = null;
ResultSet set = null;
String trimmedEmail = email.trim().toLowerCase();
String trimmedLastName = lastName.trim().toLowerCase();
String trimmedFirstName = firstName.trim().toLowerCase();
try
{
connection = getConnection();
StatementAssembly assembly = new StatementAssembly();
assembly.newLine("SELECT PERSON_ID");
assembly.newLine("FROM PERSON");
assembly.newLine("WHERE ");
assembly.add("LOWER(EMAIL) = ");
assembly.addParameter(trimmedEmail);
statement = assembly.createStatement(connection);
set = statement.executeQuery();
if (set.next())
throw new RegistrationException("Email address is already in use by another user.");
close(null, statement, set);
assembly = new StatementAssembly();
assembly.newLine("SELECT PERSON_ID");
assembly.newLine("FROM PERSON");
assembly.newLine("WHERE ");
assembly.add("LOWER(FIRST_NAME) = ");
assembly.addParameter(trimmedFirstName);
assembly.addSep(" AND ");
assembly.add("LOWER(LAST_NAME) = ");
assembly.addParameter(trimmedLastName);
statement = assembly.createStatement(connection);
set = statement.executeQuery();
if (set.next())
throw new RegistrationException("Name provided is already in use by another user.");
}
catch (SQLException e)
{
throw new RegistrationException("Could not access database: " + e.getMessage(), e);
}
finally
{
close(connection, statement, set);
}
}
public Book returnBook(Integer bookId) throws RemoteException, FinderException
{
IBookHome bookHome = getBookHome();
IBook book = bookHome.findByPrimaryKey(bookId);
Integer ownerPK = book.getOwnerId();
book.setHolderId(ownerPK);
return getBook(bookId);
}
}