001/* 002 * #%L 003 * Netarchivesuite - harvester 004 * %% 005 * Copyright (C) 2005 - 2014 The Royal Danish Library, the Danish State and University Library, 006 * the National Library of France and the Austrian National Library. 007 * %% 008 * This program is free software: you can redistribute it and/or modify 009 * it under the terms of the GNU Lesser General Public License as 010 * published by the Free Software Foundation, either version 2.1 of the 011 * License, or (at your option) any later version. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Lesser Public License for more details. 017 * 018 * You should have received a copy of the GNU General Lesser Public 019 * License along with this program. If not, see 020 * <http://www.gnu.org/licenses/lgpl-2.1.html>. 021 * #L% 022 */ 023package dk.netarkivet.harvester.datamodel.extendedfield; 024 025import java.sql.Connection; 026import java.sql.PreparedStatement; 027import java.sql.ResultSet; 028import java.sql.SQLException; 029 030import org.slf4j.Logger; 031import org.slf4j.LoggerFactory; 032 033import dk.netarkivet.common.exceptions.ArgumentNotValid; 034import dk.netarkivet.common.exceptions.IOFailure; 035import dk.netarkivet.common.exceptions.UnknownID; 036import dk.netarkivet.common.utils.DBUtils; 037import dk.netarkivet.harvester.datamodel.HarvestDBConnection; 038import dk.netarkivet.harvester.datamodel.HarvesterDatabaseTables; 039 040/** 041 * Implementation class for the ExtendedFieldValueDAO interface. 042 */ 043public class ExtendedFieldValueDBDAO extends ExtendedFieldValueDAO { 044 045 /** The logger. */ 046 private static final Logger log = LoggerFactory.getLogger(ExtendedFieldValueDBDAO.class); 047 048 /** 049 * Constructor for the ExtendedFieldValueDBDAO class. 050 */ 051 public ExtendedFieldValueDBDAO() { 052 Connection connection = HarvestDBConnection.get(); 053 try { 054 HarvesterDatabaseTables.checkVersion(connection, HarvesterDatabaseTables.EXTENDEDFIELD); 055 HarvesterDatabaseTables.checkVersion(connection, HarvesterDatabaseTables.EXTENDEDFIELDTYPE); 056 HarvesterDatabaseTables.checkVersion(connection, HarvesterDatabaseTables.EXTENDEDFIELDVALUE); 057 } finally { 058 HarvestDBConnection.release(connection); 059 } 060 } 061 062 /** 063 * Create a ExtendedFieldValue in persistent storage. 064 * 065 * @param aConnection an open connection to the HarvestDatabase. 066 * @param aExtendedFieldValue The ExtendedFieldValue to create in persistent storage 067 * @param aCommit Should we commit this or not 068 * @throws SQLException In case of Database access problems. 069 */ 070 public void create(Connection aConnection, ExtendedFieldValue aExtendedFieldValue, boolean aCommit) 071 throws SQLException { 072 ArgumentNotValid.checkNotNull(aExtendedFieldValue, "aExtendedFieldValue"); 073 074 if (aExtendedFieldValue.getExtendedFieldValueID() != null) { 075 log.warn("The extendedFieldValueID for this extendedField Value is already set. " 076 + "This should probably never happen."); 077 } else { 078 aExtendedFieldValue.setExtendedFieldValueID(generateNextID(aConnection)); 079 } 080 081 log.debug("Creating {}", aExtendedFieldValue.toString()); 082 083 PreparedStatement statement = null; 084 aConnection.setAutoCommit(false); 085 statement = aConnection.prepareStatement("INSERT INTO extendedfieldvalue (" 086 + "extendedfieldvalue_id, extendedfield_id, content, instance_id) " + "VALUES (?, ?, ?, ?)"); 087 088 statement.setLong(1, aExtendedFieldValue.getExtendedFieldValueID()); 089 statement.setLong(2, aExtendedFieldValue.getExtendedFieldID()); 090 statement.setString(3, aExtendedFieldValue.getContent()); 091 statement.setLong(4, aExtendedFieldValue.getInstanceID()); 092 093 statement.executeUpdate(); 094 if (aCommit) { 095 aConnection.commit(); 096 } 097 } 098 099 @Override 100 public void create(ExtendedFieldValue aExtendedFieldValue) { 101 Connection connection = HarvestDBConnection.get(); 102 103 try { 104 create(connection, aExtendedFieldValue, true); 105 } catch (SQLException e) { 106 String message = "SQL error creating extendedfield value " + aExtendedFieldValue + " in database" + "\n"; 107 log.warn(message, e); 108 throw new IOFailure(message, e); 109 } finally { 110 DBUtils.rollbackIfNeeded(connection, "create extendedfield value", aExtendedFieldValue); 111 HarvestDBConnection.release(connection); 112 } 113 } 114 115 /** 116 * @param c an open connection to the HarvestDatabase. 117 * @return the ID for next extendedvFieldValue inserted. 118 */ 119 private Long generateNextID(Connection c) { 120 // FIXME synchronize or use identity row or generator. 121 Long maxVal = DBUtils.selectLongValue(c, "SELECT max(extendedfieldvalue_id) FROM extendedfieldvalue"); 122 123 if (maxVal == null) { 124 maxVal = 0L; 125 } 126 return maxVal + 1L; 127 } 128 129 @Override 130 public void delete(long aExtendedfieldValueID) throws IOFailure { 131 ArgumentNotValid.checkNotNull(aExtendedfieldValueID, "aExtendedfieldValueID"); 132 133 Connection c = HarvestDBConnection.get(); 134 PreparedStatement stm = null; 135 try { 136 c.setAutoCommit(false); 137 138 stm = c.prepareStatement("DELETE FROM extendedfieldvalue WHERE extendedfieldvalue_id = ?"); 139 stm.setLong(1, aExtendedfieldValueID); 140 stm.executeUpdate(); 141 142 c.commit(); 143 } catch (SQLException e) { 144 String message = "SQL error deleting extendedfieldvalue for ID " + aExtendedfieldValueID + "\n"; 145 log.warn(message, e); 146 } finally { 147 DBUtils.closeStatementIfOpen(stm); 148 DBUtils.rollbackIfNeeded(c, "delete extendedfield value", aExtendedfieldValueID); 149 HarvestDBConnection.release(c); 150 } 151 } 152 153 @Override 154 public boolean exists(Long aExtendedFieldValueID) { 155 ArgumentNotValid.checkNotNull(aExtendedFieldValueID, "Long aExtendedFieldValueID"); 156 157 Connection c = HarvestDBConnection.get(); 158 try { 159 return exists(c, aExtendedFieldValueID); 160 } finally { 161 HarvestDBConnection.release(c); 162 } 163 164 } 165 166 /** 167 * Find out if there already exists in persistent storage a ExtendedFieldValue with the given id. 168 * 169 * @param c an open connection to the HarvestDatabase. 170 * @param aExtendedFieldValueID An id associated with a ExtendedFieldValue 171 * @return true, if there already exists in persistent storage a ExtendedFieldValue with the given id. 172 */ 173 private synchronized boolean exists(Connection c, Long aExtendedFieldValueID) { 174 return 1 == DBUtils.selectLongValue(c, "SELECT COUNT(*) FROM extendedfieldvalue " 175 + "WHERE extendedfieldvalue_id = ?", aExtendedFieldValueID); 176 } 177 178 @Override 179 public synchronized ExtendedFieldValue read(Long aExtendedFieldID, Long aInstanceID) { 180 ArgumentNotValid.checkNotNull(aExtendedFieldID, "aExtendedFieldID"); 181 ArgumentNotValid.checkNotNull(aInstanceID, "aInstanceID"); 182 Connection connection = HarvestDBConnection.get(); 183 try { 184 return read(connection, aExtendedFieldID, aInstanceID); 185 } finally { 186 HarvestDBConnection.release(connection); 187 } 188 } 189 190 /** 191 * Read the ExtendedFieldValue with the given extendedFieldID. 192 * 193 * @param connection an open connection to the HarvestDatabase 194 * @param aExtendedFieldID A given ID for a ExtendedFieldValue 195 * @param aInstanceID A given instanceID 196 * @return the ExtendedFieldValue with the given extendedFieldID. 197 */ 198 private synchronized ExtendedFieldValue read(Connection connection, Long aExtendedFieldID, Long aInstanceID) { 199 ExtendedFieldValue extendedFieldValue = null; 200 PreparedStatement statement = null; 201 try { 202 statement = connection.prepareStatement("" + "SELECT extendedfieldvalue_id, " + " extendedfield_id, " 203 + " content " + "FROM extendedfieldvalue " 204 + "WHERE extendedfield_id = ? and instance_id = ?"); 205 206 statement.setLong(1, aExtendedFieldID); 207 statement.setLong(2, aInstanceID); 208 ResultSet result = statement.executeQuery(); 209 if (!result.next()) { 210 return null; 211 } 212 213 long extendedfieldvalueId = result.getLong(1); 214 long extendedfieldId = result.getLong(2); 215 long instanceId = aInstanceID; 216 String content = result.getString(3); 217 218 extendedFieldValue = new ExtendedFieldValue(extendedfieldvalueId, extendedfieldId, instanceId, content); 219 220 return extendedFieldValue; 221 } catch (SQLException e) { 222 String message = "SQL error reading extended Field " + aExtendedFieldID + " in database" + "\n"; 223 log.warn(message, e); 224 throw new IOFailure(message, e); 225 } 226 } 227 228 /** 229 * Read a ExtendedFieldValue in persistent storage. 230 * 231 * @param aConnection an open connection to the HarvestDatabase 232 * @param aExtendedFieldValue The ExtendedFieldValue to update 233 * @param aCommit Should we commit this or not 234 * @throws SQLException In case of database problems. 235 */ 236 public void update(Connection aConnection, ExtendedFieldValue aExtendedFieldValue, boolean aCommit) 237 throws SQLException { 238 PreparedStatement statement = null; 239 final Long extendedfieldvalueId = aExtendedFieldValue.getExtendedFieldID(); 240 if (!exists(aConnection, extendedfieldvalueId)) { 241 throw new UnknownID("Extended Field Value id " + extendedfieldvalueId + " is not known in " 242 + "persistent storage"); 243 } 244 245 aConnection.setAutoCommit(false); 246 247 statement = aConnection.prepareStatement("" + "UPDATE extendedfieldvalue " + "SET extendedfield_id = ?, " 248 + " instance_id = ?, " + " content = ? " 249 + "WHERE extendedfieldvalue_id = ? and instance_id = ?"); 250 251 statement.setLong(1, aExtendedFieldValue.getExtendedFieldID()); 252 statement.setLong(2, aExtendedFieldValue.getInstanceID()); 253 statement.setString(3, aExtendedFieldValue.getContent()); 254 statement.setLong(4, aExtendedFieldValue.getExtendedFieldValueID()); 255 statement.setLong(5, aExtendedFieldValue.getInstanceID()); 256 257 statement.executeUpdate(); 258 259 if (aCommit) { 260 aConnection.commit(); 261 } 262 } 263 264 @Override 265 public void update(ExtendedFieldValue aExtendedFieldValue) throws IOFailure { 266 Connection connection = HarvestDBConnection.get(); 267 268 try { 269 update(connection, aExtendedFieldValue, true); 270 } catch (SQLException e) { 271 String message = "SQL error updating extendedfield Value " + aExtendedFieldValue + " in database" + "\n"; 272 log.warn(message, e); 273 throw new IOFailure(message, e); 274 } finally { 275 DBUtils.rollbackIfNeeded(connection, "update extendedfield Value", aExtendedFieldValue); 276 HarvestDBConnection.release(connection); 277 } 278 } 279 280}