// BlogBridge -- RSS feed reader, manager, and web based service // Copyright (C) 2002-2006 by R. Pito Salas // // This program 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 program 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 // // Contact: R. Pito Salas // mailto:pitosalas@users.sourceforge.net // More information: about BlogBridge // http://www.blogbridge.com // http://sourceforge.net/projects/blogbridge // // $Id: HsqlGuidesPM.java,v 1.26 2007/10/03 11:41:56 spyromus Exp $ // package com.salas.bb.persistence.backend; import com.salas.bb.domain.*; import com.salas.bb.persistence.PersistenceException; import com.salas.bb.utils.i18n.Strings; import java.sql.PreparedStatement; import java.sql.SQLException; import java.text.MessageFormat; import java.util.logging.Level; import java.util.logging.Logger; /** * HSQL manager of guides. It takes care only about handling guides. */ final class HsqlGuidesPM { private static final Logger LOG = Logger.getLogger(HsqlGuidesPM.class.getName()); /** Persistence manager context. */ private final HsqlPersistenceManager context; /** Unsupported guide type. */ private static final String MSG_UNSUPPORTED = Strings.error("db.unsupported.guide.type"); /** Guide is already in database. */ private static final String MSG_ALREADY_IN_DB = Strings.error("db.guide.is.already.in.database"); /** Guide is not in database yet. */ private static final String MSG_NOT_IN_DB = Strings.error("db.guide.is.not.in.database"); /** * Creates manager. * * @param aContext context used for communication back. */ public HsqlGuidesPM(HsqlPersistenceManager aContext) { context = aContext; } /** * Inserts guide into database. * * @param guide guide to insert. * @param position position in the set. * * @throws NullPointerException if guide isn't specified. * @throws IllegalStateException if guide is already in database. * @throws IllegalArgumentException if guide is of unsupported type. * @throws SQLException if database operation fails. */ public void insertGuide(IGuide guide, int position) throws SQLException { if (guide == null) throw new NullPointerException(HsqlPersistenceManager.MSG_GUIDE_UNSPECIFIED); if (!(guide instanceof StandardGuide)) throw new IllegalArgumentException(MSG_UNSUPPORTED); if (guide.getID() != -1) throw new IllegalStateException(MSG_ALREADY_IN_DB); int type = 0; PreparedStatement stmt = context.getPreparedStatement( "INSERT INTO GUIDES (TITLE, ICONKEY, TYPE, POS, AUTOFEEDSDISCOVERY, " + "PUBLISHINGENABLED, PUBLISHINGTITLE, PUBLISHINGTAGS, PUBLISHINGPUBLIC, " + "PUBLISHINGURL, LASTPUBLISHINGTIME, PUBLISHINGRATING, NOTIFICATIONSALLOWED, MOBILE)" + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); try { stmt.setString(1, guide.getTitle()); stmt.setString(2, guide.getIconKey()); stmt.setInt(3, type); stmt.setInt(4, position); stmt.setBoolean(5, guide.isAutoFeedsDiscovery()); stmt.setBoolean(6, guide.isPublishingEnabled()); stmt.setString(7, guide.getPublishingTitle()); stmt.setString(8, guide.getPublishingTags()); stmt.setBoolean(9, guide.isPublishingPublic()); stmt.setString(10, guide.getPublishingURL()); stmt.setLong(11, guide.getLastPublishingTime()); stmt.setInt(12, guide.getPublishingRating()); stmt.setBoolean(13, guide.isNotificationsAllowed()); stmt.setBoolean(14, guide.isMobile()); int rows = stmt.executeUpdate(); if (rows == 0) throw new SQLException(Strings.error("db.failed.to.insert.row.for.guide")); guide.setID(context.getInsertedID()); // Insert a stats record long now = System.currentTimeMillis(); stmt = context.getPreparedStatement("INSERT INTO GUIDESTATS " + "(GUIDEID, INIT_TIME, RESET_TIME) VALUES (?, ?, ?)"); stmt.setLong(1, guide.getID()); stmt.setLong(2, now); stmt.setLong(3, now); rows = stmt.executeUpdate(); if (rows == 0) throw new SQLException("Failed to add a guide stats row"); } finally { stmt.close(); } } /** * Removes guide from database. * * @param guide guide to remove. * * @throws NullPointerException if guide isn't specified. * @throws IllegalStateException if guide is not in database. * @throws SQLException if database operation fails. * @throws PersistenceException is database error appears. */ public void removeGuide(IGuide guide) throws SQLException, PersistenceException { guideCheck(guide); removeGuideComponents(guide); IFeed[] feeds = guide.getFeeds(); PreparedStatement stmt = context.getPreparedStatement( "DELETE FROM GUIDES WHERE ID=?"); try { stmt.setLong(1, guide.getID()); int rows = stmt.executeUpdate(); if (rows == 0) throw new SQLException(Strings.error("db.failed.to.remove.row.with.guide")); } finally { stmt.close(); } // Clear ID's guide.setID(-1); // Remove feeds for (IFeed feed : feeds) { feed.removeParentGuide(guide); context.removeFeedIfNoRefs(feed); } } /** * Removes all components of the guide. * * @param aGuide guide. * * @throws PersistenceException if persistent operation fails. */ private void removeGuideComponents(IGuide aGuide) throws PersistenceException { if (aGuide instanceof StandardGuide) { StandardGuide sguide = (StandardGuide)aGuide; // Remove reading lists ReadingList[] lists = sguide.getReadingLists(); for (ReadingList list : lists) { sguide.remove(list, true); context.removeReadingList(list); } } } /** * Updates guide information in database. * * @param guide guide to update. * @param position position in the set. * * @throws NullPointerException if guide isn't specified. * @throws IllegalStateException if guide is not in database. * @throws SQLException if database operation fails. */ public void updateGuide(IGuide guide, int position) throws SQLException { guideCheck(guide); PreparedStatement stmt = context.getPreparedStatement( "UPDATE GUIDES SET TITLE=?, ICONKEY=?, POS=?, AUTOFEEDSDISCOVERY=?, " + "PUBLISHINGENABLED=?, PUBLISHINGTITLE=?, PUBLISHINGTAGS=?, PUBLISHINGPUBLIC=?, " + "PUBLISHINGURL=?, LASTPUBLISHINGTIME=?, PUBLISHINGRATING=?, LASTUPDATETIME=?, " + "NOTIFICATIONSALLOWED=?, MOBILE=? " + "WHERE ID=?"); try { stmt.setString(1, guide.getTitle()); stmt.setString(2, guide.getIconKey()); stmt.setInt(3, position); stmt.setBoolean(4, guide.isAutoFeedsDiscovery()); stmt.setBoolean(5, guide.isPublishingEnabled()); stmt.setString(6, guide.getPublishingTitle()); stmt.setString(7, guide.getPublishingTags()); stmt.setBoolean(8, guide.isPublishingPublic()); stmt.setString(9, guide.getPublishingURL()); stmt.setLong(10, guide.getLastPublishingTime()); stmt.setInt(11, guide.getPublishingRating()); stmt.setLong(12, guide.getLastUpdateTime()); stmt.setBoolean(13, guide.isNotificationsAllowed()); stmt.setBoolean(14, guide.isMobile()); stmt.setLong(15, guide.getID()); int rows = stmt.executeUpdate(); if (rows == 0) { LOG.log(Level.SEVERE, MessageFormat.format( Strings.error("db.hsql.updated.0.rows.at.guides.guideid.0"), guide.getID())); } } finally { stmt.close(); } } public void updateGuidePositions(GuidesSet set) throws SQLException { PreparedStatement stmt = context.getPreparedStatement( "UPDATE GUIDES SET POS=? WHERE ID=?"); int count = set.getGuidesCount(); int pos = 0; for (int i = 0; i < count; i++) { IGuide guide = set.getGuideAt(i); if (guide.getID() != -1) { stmt.setInt(1, pos++); stmt.setLong(2, guide.getID()); stmt.executeUpdate(); } } } /** * Adds new record to the list of the deleted feeds associated with the guide. * * @param guide guide. * @param feedKey feed key. * * @throws SQLException if database operation fails. */ public void addDeletedFeedToGuide(IGuide guide, String feedKey) throws SQLException { guideCheck(guide); PreparedStatement stmt = context.getPreparedStatement( "INSERT INTO DELETEDFEEDS (GUIDEID, FEEDKEY) VALUES (?, ?)"); try { stmt.setLong(1, guide.getID()); stmt.setString(2, feedKey); int rows = stmt.executeUpdate(); if (rows == 0) { LOG.log(Level.SEVERE, MessageFormat.format( Strings.error("db.nothing.added.to.deletedfeeds.guideid.0.feedkey.1"), guide.getID(), feedKey)); } } finally { stmt.close(); } } /** * Removes all records about deleted feeds associated with the given guide. * * @param guide guide. * * @throws SQLException if database operation fails. */ public void removeDeletedFeedsFromGuide(IGuide guide) throws SQLException { guideCheck(guide); PreparedStatement stmt = context.getPreparedStatement( "DELETE FROM DELETEDFEEDS WHERE GUIDEID=?"); try { stmt.setLong(1, guide.getID()); stmt.executeUpdate(); } finally { stmt.close(); } } /** * Verification of the guide. * * @param guide guide to verify. */ private static void guideCheck(IGuide guide) { if (guide == null) throw new NullPointerException(HsqlPersistenceManager.MSG_GUIDE_UNSPECIFIED); if (!(guide instanceof StandardGuide)) throw new IllegalArgumentException(MSG_UNSUPPORTED); if (guide.getID() == -1) throw new IllegalStateException(MSG_NOT_IN_DB); } }