/*
* 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. 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.
*/
package org.aitools.programd.predicates;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import org.aitools.programd.Core;
import org.aitools.util.db.Entity;
import org.aitools.util.runtime.DeveloperError;
/**
* A database-oriented {@link PredicateManager} . Uses a database for storage and retrieval of predicates.
*
* @author <a href="mailto:noel@aitools.org">Noel Bush</a>
*/
public class DBPredicateManager extends PredicateManager {
private static final String LOAD_PREDICATE_SELECT =
"SELECT predicate.value FROM predicate " +
"INNER JOIN bot ON predicate.bot_id = bot.id " +
"INNER JOIN user ON predicate.user_id = user.id " +
"WHERE bot.id = ? AND user.name = ? AND predicate.name = ?";
private static final String SET_PREDICATE_INSERT =
"INSERT INTO predicate (name, value, user_id, bot_id) " +
"VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE value = VALUES(value)";
/**
* Creates a new DBMultiplexor with the given Core as owner.
*
* @param core the Core that owns this DBMultiplexor
*/
public DBPredicateManager(Core core) {
super(core);
}
/**
* @see org.aitools.programd.predicates.PredicateManager#dumpPredicates()
*
* TODO: get userid first
*/
@SuppressWarnings("boxing")
@Override
public void dumpPredicates() {
Connection connection = this._core.getDBConnection();
PreparedStatement insert;
try {
insert = connection.prepareStatement(SET_PREDICATE_INSERT);
insert.clearBatch();
for (String bot : this._bots.keySet()) {
Map<String, PredicateMap> predicateCache = this._bots.get(bot).getPredicateCache();
int bot_id = Entity.getOrCreate(connection, "bot", "label", bot);
for (String user : predicateCache.keySet()) {
PredicateMap predicateMap = predicateCache.get(user);
int user_id = Entity.getOrCreate(connection, "user", "name", user);
for (String name : predicateMap.keySet()) {
PredicateValue value = predicateMap.get(name);
insert.clearParameters();
insert.setInt(3, user_id);
insert.setInt(4, bot_id);
if (value.size() == 1) {
insert.setString(1, name);
insert.setString(2, value.getFirstValue());
insert.addBatch();
}
else {
for (int index = 1; index <= value.size(); index++) {
insert.setString(1, String.format("%s.%d", name, index));
insert.setString(2, value.get(index));
insert.addBatch();
}
}
}
predicateMap.clear();
}
}
insert.executeBatch();
connection.close();
}
catch (SQLException e) {
throw new DeveloperError("SQL error dumping predicates.", e);
}
}
/**
* Prepares the {@link PreparedStatement}s that will be pooled and used for operations.
*/
@Override
public void initialize() {
Connection connection = this._core.getDBConnection();
// These will be pooled by the connection manager.
try {
connection.prepareStatement(LOAD_PREDICATE_SELECT);
connection.prepareStatement(SET_PREDICATE_INSERT);
connection.close();
}
catch (SQLException e) {
throw new DeveloperError("SQL exception creating PreparedStatements.", e);
}
}
/**
* @see org.aitools.programd.predicates.PredicateManager#loadPredicate(java.lang.String, java.lang.String,
* java.lang.String)
*/
@Override
public String loadPredicate(String name, String user, String bot) throws NoSuchPredicateException {
String result = null;
Connection connection = this._core.getDBConnection();
try {
PreparedStatement select = connection.prepareStatement(LOAD_PREDICATE_SELECT);
select.clearParameters();
select.setString(1, bot);
select.setString(2, user);
select.setString(3, name);
ResultSet records = select.executeQuery();
while (records.next()) {
result = records.getString("value");
}
records.close();
connection.close();
}
catch (SQLException e) {
this._logger.error("Database error.", e);
throw new NoSuchPredicateException(name);
}
if (result == null) {
throw new NoSuchPredicateException(name);
}
// If found, return it.
return result;
}
}