package mj.ocraptor.database.dao;
import java.io.File;
import java.io.FileNotFoundException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.apache.commons.io.FileUtils;
import mj.ocraptor.database.DBManager;
import mj.ocraptor.database.H2Database;
import mj.ocraptor.file_handler.utils.FileTools;
import mj.ocraptor.tools.St;
public class FileEntryDao {
public static final String TABLE_NAME = "FILES";
public static final String COLUMN_FILE_HASH = "HASH";
public static final String COLUMN_FILE_EXTENSION = "EXT";
public static final String COLUMN_FILE_PATH = "PATH";
private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory
.getLogger(FileEntryDao.class);
/**
*
*
* @param entry
* @param connection
* @return
*
* @throws SQLException
* @throws FileNotFoundException
*/
public boolean insert(FileEntry entry, Connection connection) throws SQLException,
FileNotFoundException {
if (entry.getId() != null)
throw new IllegalArgumentException("FileEntry instance already inserted!");
PreparedStatement statement = null;
try {
String path = FileTools.multiplatformPath(entry.getPath());
File file = new File(path);
if (!file.exists()) {
throw new FileNotFoundException("File to insert not found: \"" + file.getPath() + "\"");
}
updateHash(entry);
String hash = entry.getHash();
// *INDENT-OFF*
String query =
"INSERT INTO " +
TABLE_NAME +
" ( " +
COLUMN_FILE_PATH +
", " +
COLUMN_FILE_EXTENSION +
", " +
COLUMN_FILE_HASH +
" ) " +
"VALUES ( ?, ?, ? )";
// *INDENT-ON*
statement = connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
statement.setString(1, path);
statement.setString(2, FileTools.getFileExtension(path));
statement.setString(3, hash);
statement.executeUpdate();
// set generated id to FileEntry instance
Integer id = DaoTools.getGeneratedId(statement.getGeneratedKeys());
if (id != null) {
entry.setId(id);
connection.commit();
FullText fullText = entry.getFullText();
if (fullText != null && !fullText.isEmpty() && fullText.getId() == null) {
fullText.setFileId(id);
FullTextDao fulltextDao = new FullTextDao();
fulltextDao.insert(fullText, connection);
}
return true;
}
} finally {
if (statement != null) {
statement.close();
}
}
return false;
}
/**
*
*
* @param entry
* @param connection
* @return
* @throws Exception
*/
public boolean updateDirty(FileEntry entry, Connection connection) throws Exception {
if (entry.getId() == null)
throw new IllegalArgumentException("Entry ID is null");
this.removeById(entry.getId(), connection);
this.removeGeneratedIds(entry);
return this.insert(entry, connection);
}
/**
*
*
* @param entry
* @param connection
* @return
*
* @throws SQLException
*/
public boolean update(final FileEntry entry, final Connection connection) throws SQLException {
if (entry.getId() == null) {
throw new IllegalArgumentException("Entry ID is null");
}
PreparedStatement statement = null;
try {
this.updateHash(entry); // update md5 hash in case the file changed
// TODO: implement proper update:
return updateDirty(entry, connection);
// ------------------------------------------------ //
// updateHash(entry);
// String path = entry.getPath(), hash = entry.getHash();
// Integer id = entry.getId();
// String query = "UPDATE " + TABLE_NAME //
// + " SET " + COLUMN_FILE_PATH + "=?, " //
// + COLUMN_FILE_HASH + "=? " //
// + " WHERE ID=?";
// statement = connection.prepareStatement(query);
// statement.setString(1, path);
// statement.setString(2, hash);
// statement.setInt(3, id);
// statement.executeUpdate();
// connection.commit();
// ------------------------------------------------ //
} catch (Exception e) {
e.printStackTrace();
} finally {
if (statement != null) {
statement.close();
}
}
return false;
}
/**
*
*
* @param query
*
* @throws Exception
*/
public void removeByPath(String path, Connection connection) throws Exception {
PreparedStatement statement = null;
try {
statement = connection.prepareStatement("DELETE FROM " + TABLE_NAME + " WHERE "
+ COLUMN_FILE_PATH + " = ?;");
statement.setString(1, path);
statement.executeUpdate();
connection.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (statement != null)
statement.close();
}
}
/**
*
*
* @param query
*
* @throws Exception
*/
public void removeById(Integer id, Connection connection) throws Exception {
PreparedStatement statement = null;
try {
statement = connection.prepareStatement("DELETE FROM " + TABLE_NAME + " WHERE ID=?;");
statement.setInt(1, id);
statement.executeUpdate();
connection.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (statement != null)
statement.close();
}
}
/**
*
*
* @param id
* @return
* @throws SQLException
*/
public FileEntry findById(int id, Connection connection) throws SQLException {
FileEntry entry = new FileEntry();
entry.setId(id);
List<FileEntry> entries = findByExample(entry, 1, connection);
return entries.size() == 1 ? entries.get(0) : null;
}
/**
*
*
* @return
* @throws SQLException
*/
public FileEntry findByPageId(int id, Connection connection) throws SQLException {
FullTextDao fullTextDao = new FullTextDao();
FullText fullText = fullTextDao.findById(id, connection);
if (fullText != null) {
return findById(fullText.getFileId(), connection);
}
return null;
}
/**
*
*
* @param path
* @param connection
* @return
*
* @throws SQLException
*/
public FileEntry findByPath(String path, Connection connection) throws SQLException {
FileEntry entry = new FileEntry();
entry.setPath(path);
List<FileEntry> entries = findByExample(entry, 1, connection);
return entries.size() == 1 ? entries.get(0) : null;
}
/**
*
*
* @param example
* @param connection
* @return
*
* @throws SQLException
*/
public List<FileEntry> findByExample(FileEntry example, Connection connection)
throws SQLException {
return findByExample(example, 1, connection);
}
/**
*
*
* @param example
* @param connection
* @return
* @throws SQLException
*/
public List<FileEntry> findByExample(FileEntry example, int limit, Connection connection)
throws SQLException {
List<FileEntry> entries = new ArrayList<FileEntry>();
String selectStatement = "SELECT * FROM " + FileEntryDao.TABLE_NAME;
HashMap<String, String> atts = new HashMap<String, String>();
atts.put("ID", example.getId() != null ? String.valueOf(example.getId()) : null);
atts.put(COLUMN_FILE_PATH, example.getPath());
atts.put(COLUMN_FILE_HASH, example.getHash());
selectStatement += DaoTools.getWhereStatement(atts, limit);
ResultSet rs = null;
Statement statement = null;
try {
statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
rs = statement.executeQuery(selectStatement);
List<String[]> resultRows = DBManager.convertToList(rs);
for (String[] r : resultRows) {
Integer fileId = r[0] == null ? null : Integer.parseInt(r[0]);
String filePath = r[1];
String fileHash = r[3];
if (fileEntryExists(filePath, connection, true)) {
FileEntry entry = new FileEntry(filePath, fileHash);
entry.setId(fileId);
entries.add(entry);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (rs != null)
rs.close();
if (statement != null) {
statement.close();
}
}
return entries;
}
/**
*
*
* @param example
* @param limit
* @param connection
* @return
*
* @throws SQLException
*/
public List<String> getAllFilePaths(Connection connection) throws SQLException {
if (connection == null) {
LOGGER.error("Connection to the database could not be established");
return null;
}
List<String> entries = new ArrayList<String>();
String selectStatement = "SELECT " + COLUMN_FILE_PATH + " FROM " + FileEntryDao.TABLE_NAME
+ ";";
ResultSet rs = null;
Statement statement = null;
try {
statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
rs = statement.executeQuery(selectStatement);
List<String[]> resultRows = DBManager.convertToList(rs);
for (String[] r : resultRows) {
entries.add(r[0]);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (rs != null)
rs.close();
if (statement != null) {
statement.close();
}
}
return entries;
}
/**
*
*
* @param entry
* @param connection
* @param limit
*
* @throws SQLException
*/
public void pullFullTextObjects(final FileEntry entry, final Connection connection,
final int limitFullTextObjects, final int limitElements) throws SQLException {
if (entry != null) {
FullTextDao dao = new FullTextDao();
List<FullText> fullTextObjects = dao.findByExample(new FullText().setFileId(entry.getId()),
limitFullTextObjects, connection);
//
if (!fullTextObjects.isEmpty()) {
entry.setFullText(fullTextObjects.get(0));
}
}
}
/**
*
*
* @param filePath
* @param connection
* @param removeNotExisting
* @return
* @throws Exception
*/
private boolean fileEntryExists(String filePath, Connection connection, boolean removeNotExisting)
throws Exception {
if (filePath != null && !filePath.trim().isEmpty()) {
if (!(new File(filePath).exists())) {
if (removeNotExisting) {
removeByPath(filePath, connection);
}
return false;
}
}
return true;
}
/**
*
*
* @param entry
*/
private void updateHash(final FileEntry entry) {
final String path = entry.getPath();
final File file = new File(path);
final String hash = FileTools.calculateMD5FromFile(file);
entry.setHash(hash);
}
/**
*
*
* @param entry
*/
private void removeGeneratedIds(FileEntry entry) {
entry.setId(null);
final FullText fullText = entry.getFullText();
if (fullText != null) {
fullText.setId(null);
}
}
}