/*
* Copyright 2006-2010 Daniel Henninger. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package net.sf.kraken.pseudoroster;
import net.sf.kraken.util.StringUtils;
import org.apache.log4j.Logger;
import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.util.NotFoundException;
import java.sql.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Representation of a pseudo roster item.
*
* This is used for tracking information about a contact that we can't track on the legacy system itself.
*
* @author Daniel Henninger
*/
public class PseudoRosterItem {
static Logger Log = Logger.getLogger(PseudoRosterItem.class);
private static final String INSERT_ROSTER_ITEM =
"INSERT INTO ofGatewayPseudoRoster(registrationID, username, nickname, groups) VALUES (?,?,?,?)";
private static final String LOAD_ROSTER_ITEM =
"SELECT nickname, groups FROM ofGatewayPseudoRoster WHERE registrationID=? AND username=?";
private static final String CHANGE_USERNAME =
"UPDATE ofGatewayPseudoRoster SET username=? WHERE registrationID=? AND username=?";
private static final String SET_NICKNAME =
"UPDATE ofGatewayPseudoRoster SET nickname=? WHERE registrationID=? AND username=?";
private static final String SET_GROUPS =
"UPDATE ofGatewayPseudoRoster SET groups=? WHERE registrationID=? AND username=?";
private static final String REMOVE_ROSTER_ITEM =
"DELETE FROM ofGatewayPseudoRoster WHERE registrationID=? AND username=?";
private long registrationID;
private String username;
private String nickname;
private List<String> groups;
/**
* Do not use this constructor, it is for Externalizable use.
*/
public PseudoRosterItem() {
}
/**
* Creates a new roster item associated with a registration id.
*
* @param registrationID Id of the registration this roster item is associated with.
* @param username The username of the roster item.
* @param nickname The nickname associated with the roster item (may be null).
* @param groups The group list associated wit the roster item (may be null).
*/
public PseudoRosterItem(Long registrationID, String username, String nickname, List<String> groups) {
if (registrationID == null || username == null) {
throw new NullPointerException("Arguments cannot be null.");
}
this.registrationID = registrationID;
this.username = username;
this.nickname = nickname;
this.groups = groups;
try {
// Clean up potentially already existing item.
removeFromDb();
try {
// Insert new roster item.
insertIntoDb();
}
catch (Exception e) {
Log.error(e);
}
}
catch (Exception e) {
Log.error(e);
}
}
/**
* Creates a new pseudo roster item from an existing pseudo roster item.
*
* This is typically only used internally to import items from another cluster node.
*
* @param item PseudoRosterItem instance.
*/
public PseudoRosterItem(PseudoRosterItem item) {
this.registrationID = item.getRegistrationID();
this.username = item.getUsername();
this.nickname = item.getNickname();
this.groups = item.getGroups();
try {
// Clean up potentially already existing item.
removeFromDb();
try {
// Insert new roster item.
insertIntoDb();
}
catch (Exception e) {
Log.error(e);
}
}
catch (Exception e) {
Log.error(e);
}
}
/**
* Loads an existing roster item.
*
* @param registrationID The ID of the registration the roster item is assocaited with.
* @param username The username of the roster item.
* @throws org.jivesoftware.util.NotFoundException if the registration could not be loaded.
*/
public PseudoRosterItem(long registrationID, String username)
throws NotFoundException
{
this.registrationID = registrationID;
this.username = username;
loadFromDb();
}
/**
* Returns the unique ID of the registration associated with the roster item.
*
* @return the registration ID.
*/
public long getRegistrationID() {
return registrationID;
}
/**
* Returns the username associated with the roster item.
*
* @return the username.
*/
public String getUsername() {
return username;
}
/**
* Returns the nickname associated with the roster item.
*
* @return the nickname.
*/
public String getNickname() {
return nickname;
}
/**
* Returns the groups associated with the roster item.
*
* @return the groups.
*/
public List<String> getGroups() {
return groups;
}
/**
* Changes the username of the roster item.
* @param username New username.
*/
public void changeUsername(String username) {
if (username == null) {
throw new NullPointerException("Arguments cannot be null.");
}
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(CHANGE_USERNAME);
pstmt.setString(1, username);
pstmt.setLong(2, registrationID);
pstmt.setString(3, this.username);
pstmt.executeUpdate();
this.username = username;
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(pstmt, con);
}
}
/**
* Sets the nickname for the roster item.
* @param nickname New nickname to be associated.
*/
public void setNickname(String nickname) {
this.nickname = nickname;
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(SET_NICKNAME);
if (nickname != null) {
pstmt.setString(1, nickname);
}
else {
pstmt.setNull(1, Types.VARCHAR);
}
pstmt.setLong(2, registrationID);
pstmt.setString(3, this.username);
pstmt.executeUpdate();
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(pstmt, con);
}
}
/**
* Sets the groups for the roster item.
* @param groups New group list to be associated.
*/
public void setGroups(List<String> groups) {
this.groups = groups;
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(SET_GROUPS);
if (groups != null) {
pstmt.setString(1, StringUtils.join(groups,","));
}
else {
pstmt.setNull(1, Types.VARCHAR);
}
pstmt.setLong(2, registrationID);
pstmt.setString(3, this.username);
pstmt.executeUpdate();
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(pstmt, con);
}
}
/**
* Delete the roster item.
*/
public void delete() {
try {
removeFromDb();
}
catch (SQLException e) {
Log.error("SQL error while removing pseudo roster item "+this.getRegistrationID());
}
}
/**
* Retrieve a nice string representation of the roster item.
* @return String representation of roster item.
*/
@Override
public String toString() {
return username + ", " + nickname + ", " + groups;
}
/**
* Inserts a new roster item into the database.
*
* @throws SQLException if the SQL statement is wrong for whatever reason.
*/
private void insertIntoDb() throws SQLException {
Connection con = null;
PreparedStatement pstmt = null;
boolean abortTransaction = false;
try {
con = DbConnectionManager.getTransactionConnection();
pstmt = con.prepareStatement(INSERT_ROSTER_ITEM);
pstmt.setLong(1, registrationID);
pstmt.setString(2, username);
if (nickname != null) {
pstmt.setString(3, nickname);
}
else {
pstmt.setNull(3, Types.VARCHAR);
}
if (groups != null) {
pstmt.setString(4, StringUtils.join(groups,","));
}
else {
pstmt.setNull(4, Types.VARCHAR);
}
pstmt.executeUpdate();
}
catch (SQLException sqle) {
abortTransaction = true;
throw sqle;
}
finally {
DbConnectionManager.closeTransactionConnection(pstmt, con, abortTransaction);
}
}
/**
* Removeds a roster item from the database.
*
* @throws SQLException if the SQL statement is wrong for whatever reason.
*/
private void removeFromDb() throws SQLException {
Connection con = null;
PreparedStatement pstmt = null;
boolean abortTransaction = false;
try {
con = DbConnectionManager.getTransactionConnection();
pstmt = con.prepareStatement(REMOVE_ROSTER_ITEM);
pstmt.setLong(1, registrationID);
pstmt.setString(2, username);
pstmt.executeUpdate();
}
catch (SQLException sqle) {
abortTransaction = true;
throw sqle;
}
finally {
DbConnectionManager.closeTransactionConnection(pstmt, con, abortTransaction);
}
}
/**
* Loads the roster item from the database.
*
* @throws NotFoundException if roster item is not found in ddb for some reason.
*/
private void loadFromDb() throws NotFoundException {
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(LOAD_ROSTER_ITEM);
pstmt.setLong(1, registrationID);
pstmt.setString(2, username);
rs = pstmt.executeQuery();
if (!rs.next()) {
throw new NotFoundException("Pseudo roster item not found: " + registrationID + "/" + username);
}
this.nickname = rs.getString(1);
String groupList = rs.getString(2);
if (groupList != null) {
this.groups = Arrays.asList(groupList.split(","));
}
else {
this.groups = new ArrayList<String>();
}
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
}
}