dk.netarkivet.harvester.datamodel.extendedfield.ExtendedFieldDBDAO.java Source code

Java tutorial

Introduction

Here is the source code for dk.netarkivet.harvester.datamodel.extendedfield.ExtendedFieldDBDAO.java

Source

/* File:        $Id$Id$
 * Revision:    $Revision$Revision$
 * Author:      $Author$Author$
 * Date:        $Date$Date$
 *
 * The Netarchive Suite - Software to harvest and preserve websites
 * Copyright 2004-2012 The Royal Danish Library, the Danish State and
 * University Library, the National Library of France and the Austrian
 * National Library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

package dk.netarkivet.harvester.datamodel.extendedfield;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import dk.netarkivet.common.exceptions.ArgumentNotValid;
import dk.netarkivet.common.exceptions.IOFailure;
import dk.netarkivet.common.exceptions.UnknownID;
import dk.netarkivet.common.utils.DBUtils;
import dk.netarkivet.common.utils.ExceptionUtils;
import dk.netarkivet.harvester.datamodel.HarvestDBConnection;
import dk.netarkivet.harvester.datamodel.HarvesterDatabaseTables;

/**
 * A database-based implementation of the ExtendedFieldDBDAO class.
 */
public class ExtendedFieldDBDAO extends ExtendedFieldDAO {
    /** The logger for this class. */
    private final Log log = LogFactory.getLog(getClass());

    /**
     * Constructor for the ExtendedFieldDBDAO object.
     */
    public ExtendedFieldDBDAO() {

        Connection connection = HarvestDBConnection.get();
        try {
            HarvesterDatabaseTables.checkVersion(connection, HarvesterDatabaseTables.EXTENDEDFIELD);
            HarvesterDatabaseTables.checkVersion(connection, HarvesterDatabaseTables.EXTENDEDFIELDVALUE);
        } finally {
            HarvestDBConnection.release(connection);
        }
    }

    @Override
    public synchronized void create(ExtendedField aExtendedField) {
        ArgumentNotValid.checkNotNull(aExtendedField, "aExtendedField");

        Connection connection = HarvestDBConnection.get();
        if (aExtendedField.getExtendedFieldID() != null) {
            log.warn("The extendedFieldID for this extended Field is "
                    + "already set. This should probably never happen.");
        } else {
            aExtendedField.setExtendedFieldID(generateNextID(connection));
        }

        log.debug("Creating " + aExtendedField.toString());

        PreparedStatement statement = null;
        try {
            connection.setAutoCommit(false);
            statement = connection
                    .prepareStatement("" + "INSERT INTO extendedfield " + "            (extendedfield_id, "
                            + "             extendedfieldtype_id, " + "             name, "
                            + "             format, " + "             defaultvalue, " + "             options, "
                            + "             datatype, " + "             mandatory, " + "             sequencenr, "
                            + "             maxlen) " + "VALUES      (?, " + "             ?, " + "             ?, "
                            + "             ?, " + "             ?, " + "             ?, " + "             ?, "
                            + "             ?, " + "             ?, " + "             ?) ");

            statement.setLong(1, aExtendedField.getExtendedFieldID());
            statement.setLong(2, aExtendedField.getExtendedFieldTypeID());
            statement.setString(3, aExtendedField.getName());
            statement.setString(4, aExtendedField.getFormattingPattern());
            statement.setString(5, aExtendedField.getDefaultValue());
            statement.setString(6, aExtendedField.getOptions());
            statement.setInt(7, aExtendedField.getDatatype());
            // the following conversion from boolean to int is necessary, 
            // because the database column 'mandatory' is a integer field 
            // and not a boolean (NAS-2127)
            statement.setInt(8, aExtendedField.isMandatory() ? 1 : 0);
            statement.setInt(9, aExtendedField.getSequencenr());
            statement.setInt(10, aExtendedField.getMaxlen());
            //TODO
            log.debug(statement.toString());

            statement.executeUpdate();
            connection.commit();
        } catch (SQLException e) {
            String message = "SQL error creating extended field " + aExtendedField + " in database" + "\n"
                    + ExceptionUtils.getSQLExceptionCause(e);
            log.warn(message, e);
            throw new IOFailure(message, e);
        } finally {
            DBUtils.closeStatementIfOpen(statement);
            DBUtils.rollbackIfNeeded(connection, "create extended field", aExtendedField);
            HarvestDBConnection.release(connection);
        }
    }

    /**
     * Generates the next id of a extended field. this implementation retrieves
     * the maximum value of extendedfield_id in the DB, and returns this value +
     * 1.
     * @param c an open connection to the HarvestDatabase
     * 
     * @return The next available ID
     */
    private Long generateNextID(Connection c) {
        Long maxVal = DBUtils.selectLongValue(c, "SELECT max(extendedfield_id) FROM extendedfield");

        if (maxVal == null) {
            maxVal = 0L;
        }
        return maxVal + 1L;
    }

    /**
     * Check whether a particular extended Field exists.
     * 
     * @param aExtendedfieldId
     *            Id of the extended field.
     * @return true if the extended field exists.
     */
    public boolean exists(Long aExtendedfieldId) {
        ArgumentNotValid.checkNotNull(aExtendedfieldId, "Long aExtendedfieldId");

        Connection c = HarvestDBConnection.get();
        try {
            return exists(c, aExtendedfieldId);
        } finally {
            HarvestDBConnection.release(c);
        }
    }

    /**
     * Check, if there exists an ExtendedField with a given ID.
     * @param c An open connection to the HarvestDatabase
     * @param aExtendedfieldId An Id for a given Extended Field.
     * @return true, if the extended field with the Id exists; 
     * otherwise false
     */
    private synchronized boolean exists(Connection c, Long aExtendedfieldId) {
        return 1 == DBUtils.selectLongValue(c, "SELECT COUNT(*) FROM extendedfield WHERE extendedfield_id = ?",
                aExtendedfieldId);
    }

    @Override
    public synchronized void update(ExtendedField aExtendedField) {
        ArgumentNotValid.checkNotNull(aExtendedField, "aExtendedField");

        Connection connection = HarvestDBConnection.get();

        PreparedStatement statement = null;
        try {
            final Long extendedfieldId = aExtendedField.getExtendedFieldID();
            if (!exists(connection, extendedfieldId)) {
                throw new UnknownID("Extended Field id " + extendedfieldId + " is not known in persistent storage");
            }

            connection.setAutoCommit(false);

            statement = connection.prepareStatement("" + "UPDATE extendedfield " + "SET    extendedfield_id = ?, "
                    + "       extendedfieldtype_id = ?, " + "       name = ?, " + "       format = ?, "
                    + "       defaultvalue = ?, " + "       options = ?, " + "       datatype = ?, "
                    + "       mandatory = ?, " + "       sequencenr = ?, " + "       maxlen = ? "
                    + "WHERE  extendedfield_id = ? ");

            statement.setLong(1, aExtendedField.getExtendedFieldID());
            statement.setLong(2, aExtendedField.getExtendedFieldTypeID());
            statement.setString(3, aExtendedField.getName());
            statement.setString(4, aExtendedField.getFormattingPattern());
            statement.setString(5, aExtendedField.getDefaultValue());
            statement.setString(6, aExtendedField.getOptions());
            statement.setInt(7, aExtendedField.getDatatype());
            // the following conversion from boolean to int is necessary, 
            // because the database column 'mandatory' is a int field 
            // and not a boolean (NAS-2127)
            statement.setInt(8, aExtendedField.isMandatory() ? 1 : 0);
            statement.setInt(9, aExtendedField.getSequencenr());
            statement.setInt(10, aExtendedField.getMaxlen());
            statement.setLong(11, aExtendedField.getExtendedFieldID());

            //TODO
            log.debug(statement.toString());

            statement.executeUpdate();

            connection.commit();
        } catch (SQLException e) {
            String message = "SQL error updating extendedfield " + aExtendedField + " in database" + "\n"
                    + ExceptionUtils.getSQLExceptionCause(e);
            log.warn(message, e);
            throw new IOFailure(message, e);
        } finally {
            DBUtils.closeStatementIfOpen(statement);
            DBUtils.rollbackIfNeeded(connection, "update extendedfield", aExtendedField);
            HarvestDBConnection.release(connection);
        }
    }

    @Override
    public synchronized ExtendedField read(Long aExtendedfieldId) {
        ArgumentNotValid.checkNotNull(aExtendedfieldId, "aExtendedfieldId");
        Connection connection = HarvestDBConnection.get();
        try {
            return read(connection, aExtendedfieldId);
        } finally {
            HarvestDBConnection.release(connection);
        }
    }

    /**
     * Read an ExtendedField from database.
     * @param connection A connection to the harvestDatabase
     * @param aExtendedfieldId The ID for a given ExtendedField 
     * @return An ExtendedField object for the given ID.
     */
    private synchronized ExtendedField read(Connection connection, Long aExtendedfieldId) {
        if (!exists(connection, aExtendedfieldId)) {
            throw new UnknownID("Extended Field id " + aExtendedfieldId + " is not known in persistent storage");
        }

        ExtendedField extendedField = null;
        PreparedStatement statement = null;
        try {
            statement = connection.prepareStatement("" + "SELECT extendedfieldtype_id, " + "       name, "
                    + "       format, " + "       defaultvalue, " + "       options, " + "       datatype, "
                    + "       mandatory, " + "       sequencenr, " + "       maxlen " + "FROM   extendedfield "
                    + "WHERE  extendedfield_id = ? ");

            statement.setLong(1, aExtendedfieldId);
            ResultSet result = statement.executeQuery();
            result.next();

            long extendedfieldtypeId = result.getLong(1);
            String name = result.getString(2);
            String format = result.getString(3);
            String defaultvalue = result.getString(4);
            String options = result.getString(5);
            int datatype = result.getInt(6);
            //TODO maybe this cast is not necessary
            boolean mandatory = (result.getInt(7) != 0);
            int sequencenr = result.getInt(8);
            int maxlen = result.getInt(9);

            extendedField = new ExtendedField(aExtendedfieldId, extendedfieldtypeId, name, format, datatype,
                    mandatory, sequencenr, defaultvalue, options, maxlen);

            return extendedField;
        } catch (SQLException e) {
            String message = "SQL error reading extended Field " + aExtendedfieldId + " in database" + "\n"
                    + ExceptionUtils.getSQLExceptionCause(e);
            log.warn(message, e);
            throw new IOFailure(message, e);
        }
    }

    @Override
    public synchronized List<ExtendedField> getAll(long aExtendedFieldTypeId) {
        Connection c = HarvestDBConnection.get();
        try {
            List<Long> idList = DBUtils.selectLongList(c, "SELECT extendedfield_id FROM extendedfield "
                    + "WHERE extendedfieldtype_id = ? " + "ORDER BY sequencenr ASC", aExtendedFieldTypeId);
            List<ExtendedField> extendedFields = new LinkedList<ExtendedField>();
            for (Long extendedfieldId : idList) {
                extendedFields.add(read(c, extendedfieldId));
            }
            return extendedFields;
        } finally {
            HarvestDBConnection.release(c);
        }
    }

    @Override
    public void delete(long aExtendedfieldId) throws IOFailure {
        ArgumentNotValid.checkNotNull(aExtendedfieldId, "aExtendedfieldId");

        Connection c = HarvestDBConnection.get();
        PreparedStatement stm = null;
        try {
            c.setAutoCommit(false);

            stm = c.prepareStatement("DELETE FROM extendedfieldvalue WHERE extendedfield_id = ?");
            stm.setLong(1, aExtendedfieldId);
            stm.executeUpdate();
            stm.close();
            stm = c.prepareStatement("DELETE FROM extendedfield WHERE extendedfield_id = ?");
            stm.setLong(1, aExtendedfieldId);
            stm.executeUpdate();

            c.commit();

        } catch (SQLException e) {
            String message = "SQL error deleting extended fields for ID " + aExtendedfieldId + "\n"
                    + ExceptionUtils.getSQLExceptionCause(e);
            log.warn(message, e);
        } finally {
            DBUtils.closeStatementIfOpen(stm);
            DBUtils.rollbackIfNeeded(c, "delete extended field", aExtendedfieldId);
            HarvestDBConnection.release(c);
        }

    }
}