/* * AbstractPeer.java * * This work is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * * This work is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * * Copyright (c) 2004 Per Cederberg. All rights reserved. */ package org.liquidsite.core.data; import java.util.ArrayList; import org.liquidsite.util.db.DatabaseDataException; import org.liquidsite.util.db.DatabaseException; import org.liquidsite.util.db.DatabaseQuery; import org.liquidsite.util.db.DatabaseResults; import org.liquidsite.util.log.Log; /** * An abstract data object peer. This class provides some of the * functionality needed by all data object peers. The data object * peers each provide specialized static methods for operating on the * data objects by retrieving and storing them to the data source * (i.e. a database). * * @author Per Cederberg, <per at percederberg dot net> * @version 1.0 */ public abstract class AbstractPeer { /** * The class logger. */ private static final Log LOG = new Log(AbstractPeer.class); /** * The data object name. */ private String name; /** * Creates a new peer for the specified database object. * * @param name the database object name */ protected AbstractPeer(String name) { this.name = name; } /** * Returns a new instance of the data object. * * @return a new instance of the data object */ protected abstract AbstractData getDataObject(); /** * Performs a database query that returns a single number as the * result. The data source will NOT be closed after this * operation. * * @param src the data source to use * @param query the database query * * @return the query result number, or * zero (0) if no results were found * * @throws DataObjectException if the query couldn't be executed * correctly, or the results were malformed */ protected long count(DataSource src, DatabaseQuery query) throws DataObjectException { DatabaseResults res; res = execute(src, "counting " + name + " rows or size", query); try { if (res.getRowCount() > 0) { return res.getRow(0).getLong(0); } else { return 0; } } catch (DatabaseDataException e) { LOG.error(e.getMessage()); throw new DataObjectException(e); } } /** * Performs a database select query. This query is supposed to * return either one or zero rows. The data source will NOT be * closed after this operation. * * @param src the data source to use * @param query the database query * * @return the database object found, or * null if the query didn't match any row * * @throws DataObjectException if the query couldn't be executed * correctly, or the results were malformed */ protected AbstractData select(DataSource src, DatabaseQuery query) throws DataObjectException { DatabaseResults res; res = execute(src, "reading " + name, query); return createObject(res); } /** * Performs a database list select query. This query is supposed * to zero or more rows. The data source will NOT be closed after * this operation. * * @param src the data source to use * @param query the database query * * @return the list of database objects found * * @throws DataObjectException if the query couldn't be executed * correctly, or the results were malformed */ protected ArrayList selectList(DataSource src, DatabaseQuery query) throws DataObjectException { DatabaseResults res; res = execute(src, "reading " + name + " list", query); return createObjectList(res); } /** * Performs a database insert statement. No database results are * returned. The data source will NOT be closed after this * operation. * * @param src the data source to use * @param query the database query * * @throws DataObjectException if the statement couldn't be * executed correctly */ protected void insert(DataSource src, DatabaseQuery query) throws DataObjectException { execute(src, "inserting " + name, query); } /** * Performs a database update statement. No database results are * returned. The data source will NOT be closed after this * operation. * * @param src the data source to use * @param query the database query * * @throws DataObjectException if the statement couldn't be * executed correctly */ protected void update(DataSource src, DatabaseQuery query) throws DataObjectException { execute(src, "updating " + name, query); } /** * Performs a database delete statement. No database results are * returned. The data source will NOT be closed after this * operation. * * @param src the data source to use * @param query the database query * * @throws DataObjectException if the statement couldn't be * executed correctly */ protected void delete(DataSource src, DatabaseQuery query) throws DataObjectException { execute(src, "deleting " + name, query); } /** * Executes a database query or statement. This method should * normally not be called directly by subclasses, unless a query * does not return results compatible with the data object. * * @param src the data source to use * @param log the log message * @param query the database query * * @return the database results for a query, or * null for database statements * * @throws DataObjectException if the query or statement * couldn't be executed correctly */ private DatabaseResults execute(DataSource src, String log, DatabaseQuery query) throws DataObjectException { DatabaseResults res; try { LOG.trace(log); res = src.getConnection().execute(query); LOG.trace("done " + log); } catch (DatabaseException e) { LOG.error(log, e); throw new DataObjectException(log, e); } return res; } /** * Creates a new instance of the data object. The object will be * initialized with data from the specified database results. * * @param res the database results * * @return a new instance of the data object, or * null if the database results were empty * * @throws DataObjectException if the database results were * malformed */ private AbstractData createObject(DatabaseResults res) throws DataObjectException { AbstractData data; String message; if (res.getRowCount() < 1) { return null; } else { try { data = getDataObject(); data.setAll(res.getRow(0)); } catch (DatabaseDataException e) { message = "reading " + name; LOG.error(message, e); throw new DataObjectException(message, e); } } return data; } /** * Creates a list of new instances of data objects. The objects * will be initialized with data from the specified database * results. * * @param res the database results * * @return a list of new data objects (may be empty) * * @throws DataObjectException if the database results were * malformed */ private ArrayList createObjectList(DatabaseResults res) throws DataObjectException { ArrayList list = new ArrayList(); AbstractData data; String message; for (int i = 0; i < res.getRowCount(); i++) { data = getDataObject(); try { data.setAll(res.getRow(i)); } catch (DatabaseDataException e) { message = "reading " + name + " list"; LOG.error(message, e); throw new DataObjectException(message, e); } list.add(data); } return list; } }