/**
 *  ---------
 * |.##> <##.|  Open Smart Card Development Platform (www.openscdp.org)
 * |#       #|
 * |#       #|  Copyright (c) 1999-2009 CardContact Software & System Consulting
 * |'##> <##'|  Andreas Schwier, 32429 Minden, Germany (www.cardcontact.de)
 *  ---------
 *
 *  This file is part of OpenSCDP.
 *
 *  OpenSCDP is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation.
 *
 *  OpenSCDP 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with OpenSCDP; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @fileoverview TokenDAO for database objects
 */

var Token			= require('scsh/pki-db/Token').Token;
var TokenAction		= require('scsh/pki-db/TokenAction').TokenAction;
var Subject			= require('scsh/pki-db/Subject').Subject;
var ServiceRequest 		= require('scsh/pki-db/ServiceRequest').ServiceRequest;


/**
 * Data access object for token
 *
 * @param {Object} the factory that created this DAO
 */
function TokenDAO(factory) {
	GPSystem.log(GPSystem.DEBUG, module.id, "new()");

	this.factory = factory;
}

exports.TokenDAO = TokenDAO;


TokenDAO.create = [
"CREATE TABLE IF NOT EXISTS Token (" +
"	id MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT," +
"	path VARCHAR(100) NOT NULL," +
"	subjectId MEDIUMINT UNSIGNED," +
"	lastSeen TIMESTAMP DEFAULT NOW()," +
"	lastSeenAt VARCHAR(100)," +
"   online MEDIUMINT UNSIGNED DEFAULT 0,"+
"	serviceRequestId MEDIUMINT UNSIGNED," +
"	type INT UNSIGNED,"+
"	managedByRoleId MEDIUMINT UNSIGNED,"+
"	hardware VARCHAR(100),"+
"	certId MEDIUMINT UNSIGNED,"+
"	PRIMARY KEY (id)," +
"	unique (path), " +
"	CONSTRAINT FK_Token_Role FOREIGN KEY (managedByRoleId) REFERENCES Role(id)," +
"	CONSTRAINT FK_Token_Certificate FOREIGN KEY (certId) REFERENCES Certificate(id) ON DELETE SET NULL," +
"	FOREIGN KEY (serviceRequestId) REFERENCES ServiceRequest(id) ON DELETE SET NULL," +
"	FOREIGN KEY (subjectId) REFERENCES Subject(id) ON DELETE SET NULL" +
")",
"CREATE TABLE IF NOT EXISTS TokenAction (" +
"	id MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT," +
"	tokenId MEDIUMINT UNSIGNED," +
"	serviceRequestId MEDIUMINT UNSIGNED," +
"	PRIMARY KEY (id)," +
"	FOREIGN KEY (tokenId) REFERENCES Token(id) ON DELETE CASCADE," +
"	FOREIGN KEY (serviceRequestId) REFERENCES ServiceRequest(id) ON DELETE CASCADE" +
")"
];


TokenDAO.drop = [
"DROP TABLE IF EXISTS TokenAction",
"DROP TABLE IF EXISTS Token"
];



TokenDAO.alter = [
	"ALTER TABLE Token " +
	"DROP COLUMN IF EXISTS keyDomain",

	"ALTER TABLE Token " +
	"ADD COLUMN IF NOT EXISTS type INT UNSIGNED",

	"ALTER TABLE Token " +
	"ADD COLUMN IF NOT EXISTS managedByRoleId MEDIUMINT UNSIGNED",

	"ALTER TABLE Token " +
	"ADD CONSTRAINT FK_Token_Role FOREIGN KEY IF NOT EXISTS (managedByRoleId) REFERENCES Role(id)",

	"ALTER TABLE Token " +
	"ADD COLUMN IF NOT EXISTS hardware VARCHAR(100)",

	"ALTER TABLE Token " +
	"ADD COLUMN IF NOT EXISTS certId MEDIUMINT UNSIGNED",

	"ALTER TABLE Token " +
	"ADD CONSTRAINT FK_Token_Certificate FOREIGN KEY IF NOT EXISTS (certId) REFERENCES Certificate(id) ON DELETE SET NULL",

	"ALTER TABLE Token " +
	"ADD COLUMN IF NOT EXISTS lastSeenAt VARCHAR(100)",

	"ALTER TABLE Token " +
	"ADD COLUMN IF NOT EXISTS online MEDIUMINT UNSIGNED DEFAULT 0"
]



TokenDAO.prototype.toString = function() {
	return "TokenDAO(db)";
}



/**
 * Create and persists a new token
 *
 * @param {String} tokenPath the path of this token
 * @param {Object} template the optional template
 * @type Token
 * @return the newly created token object
 */
TokenDAO.prototype.newToken = function(tokenPath, template) {
	GPSystem.log(GPSystem.DEBUG, module.id, "newToken(" + tokenPath + ")");

	assert(tokenPath, "Parameter tokenPath must not be empty");
	assert(typeof(tokenPath) == "string", "Parameter tokenPath must be a String");

	var token = new Token(this, tokenPath, template);

	var con = null;
	var stmt = null;
	var rs = null;

	try	{
		con = this.factory.getConnection();

		stmt = this.factory.insertStatementFromObject(con, "Token", token);

		stmt.executeUpdate();
		rs = stmt.getGeneratedKeys();
		rs.next();
		token.id = rs.getInt(1);
	}
	finally {
		if (rs != null) {
			rs.close();
		}
		if (stmt != null) {
			stmt.close();
		}
		if (con != null) {
			con.close();
		}
	}

	return token;
}



/**
 * Delete token
 *
 * @param {String} path the token path
 * @type boolean
 * @return true if deleted
 */
TokenDAO.prototype.deleteToken = function(path) {
	GPSystem.log(GPSystem.DEBUG, module.id, "deleteToken(" + path + ")");

	assert(path, "Parameter path must not be empty");
	assert(typeof(path) == "string", "Parameter path must be a String");

	var con = null;
	var stmt = null;

	try	{
		con = this.factory.getConnection();

		stmt = con.prepareStatement("delete from Token where path = ?;");

		stmt.setString(1, path);
		stmt.executeUpdate();
	}
	finally {
		if (stmt != null) {
			stmt.close();
		}
		if (con != null) {
			con.close();
		}
	}
	return true;
}



/**
 * Get token for given id
 *
 * @param {Number} id the id of the token
 * @type Token
 * @return the token for the given id or null
 */
TokenDAO.prototype.getTokenById = function(id) {
	GPSystem.log(GPSystem.DEBUG, module.id, "getTokenById(" + id + ")");

	assert(typeof(id) == "number", "Parameter id must be a Number");

	var con = null;
	var stmt = null;
	var rs = null;
	var token = null;

	try	{
		con = this.factory.getConnection();

		stmt = con.prepareStatement("select * from Token where id = ?;");
		stmt.setInt(1, id);

		rs = stmt.executeQuery();
		if (!rs.next()) {
			GPSystem.log(GPSystem.DEBUG, module.id, "id " + id + " not found");
			return null;
		}

		token = new Token(this);
		this.factory.resultSetToProperties(rs, token);
	}
	finally {
		if (rs != null) {
			rs.close();
		}
		if (stmt != null) {
			stmt.close();
		}
		if (con != null) {
			con.close();
		}
	}

	return token;
}



/**
 * Get token for given path
 *
 * @param {String} path the path of the token
 * @type Token
 * @return the token for the given path or null
 */
TokenDAO.prototype.getToken = function(path) {
	GPSystem.log(GPSystem.DEBUG, module.id, "getToken(" + path + ")");

	assert(path, "Parameter path must not be empty");
	assert(typeof(path) == "string", "Parameter path must be a String");

	var con = null;
	var stmt = null;
	var rs = null;
	var token = null;

	try	{
		con = this.factory.getConnection();

		stmt = con.prepareStatement("select * from Token where path = ?;");
		stmt.setString(1, path);

		rs = stmt.executeQuery();
		if (!rs.next()) {
			GPSystem.log(GPSystem.DEBUG, module.id, "path " + path + " not found");
			return null;
		}

		token = new Token(this);
		this.factory.resultSetToProperties(rs, token);
	}
	finally {
		if (rs != null) {
			rs.close();
		}
		if (stmt != null) {
			stmt.close();
		}
		if (con != null) {
			con.close();
		}
	}

	return token;
}



/**
 * Get all token which are registered for a given subject
 *
 * @param {Number} subjectId the subject id of the requested token
 * @type Token[]
 * @return the list of token for the given subject id
 */
TokenDAO.prototype.getTokenListBySubjectId = function(subjectId) {
	GPSystem.log(GPSystem.DEBUG, module.id, "getTokenListBySubjectId(" + subjectId + ")");

	assert(subjectId, "Parameter subjectId must not be empty");
	assert(typeof(subjectId) == "number", "Parameter subjectId must be a number");

	var con = null;
	var stmt = null;
	var rs = null;
	var token = null;
	var list = [];

	try	{
		con = this.factory.getConnection();

		stmt = con.prepareStatement("select * from Token where subjectId = ?;");
		stmt.setInt(1, subjectId);

		rs = stmt.executeQuery();

		while (rs.next()) {
			token = new Token(this);
			this.factory.resultSetToProperties(rs, token);
			list.push(token);
		}
	}
	finally {
		if (rs != null) {
			rs.close();
		}
		if (stmt != null) {
			stmt.close();
		}
		if (con != null) {
			con.close();
		}
	}

	if (list.length == 0) {
		GPSystem.log(GPSystem.DEBUG, module.id, "No token found for subject id " + subjectId);
	}

	return list;
}



/**
 * Get a list of all token
 *
 * @param {Object} filter the filter criteria object
 * @param {Number} pageOffset the offset into the result set (optional)
 * @param {Number} page the maximum number of records (optional)
 * @type Token[]
 * @return the list of token
 */
TokenDAO.prototype.getTokenList = function(filter, pageOffset, page) {
	GPSystem.log(GPSystem.DEBUG, module.id, "getTokenList()");

	assert(typeof(filter) == "object", "Parameter filter must be an object");
	assert(typeof(pageOffset) == "undefined" || typeof(pageOffset) == "number", "Parameter pageOffset must be a Number");
	assert(typeof(page) == "undefined" || typeof(page) == "number", "Parameter page must be a Number");

	var con = null;
	var stmt = null;
	var rs = null;
	var token = null;
	var list = [];

	try	{
		con = this.factory.getConnection();

		var sql = "select * from Token";

		var where = this.factory.whereClauseFromFilter(filter);
		if (where.length > 0) {
			sql += " where " + where;
		}

		if (page) {
			sql += " limit ?,?";
		}

		stmt = con.prepareStatement(sql);

		var offset = this.factory.setArgumentsFromFilter(stmt, 1, filter);

		if (page) {
			stmt.setInt(offset++, pageOffset);
			stmt.setInt(offset, page);
		}

		rs = stmt.executeQuery();

		while (rs.next()) {
			token = new Token(this);
			this.factory.resultSetToProperties(rs, token);
			list.push(token);
		}
	}
	finally {
		if (rs != null) {
			rs.close();
		}
		if (stmt != null) {
			stmt.close();
		}
		if (con != null) {
			con.close();
		}
	}

	if (list.length == 0) {
		GPSystem.log(GPSystem.DEBUG, module.id, "The token table is empty");
	}

	return list;
}



/**
 * Count token
 *
 * @param {Object} filter the filter criteria object
 * @type Token[]
 * @return the list of token
 */
TokenDAO.prototype.countTokenList = function(filter) {
	GPSystem.log(GPSystem.DEBUG, module.id, "getTokenListByManagedByRoleId()");

	assert(typeof(filter) == "object", "Parameter filter must be an object");

	var con = null;
	var stmt = null;
	var rs = null;
	var token = null;
	var list = [];

	try	{
		con = this.factory.getConnection();

		var sql = "select count(id) from Token";

		var where = this.factory.whereClauseFromFilter(filter);
		if (where.length > 0) {
			sql += " where " + where;
		}

		stmt = con.prepareStatement(sql);

		var offset = this.factory.setArgumentsFromFilter(stmt, 1, filter);

		rs = stmt.executeQuery();
		rs.next();
		var count = rs.getInt(1);
		GPSystem.log(GPSystem.DEBUG, module.id, "countTokenList() returns " + count);
		return count;
	}
	finally {
		if (rs != null) {
			rs.close();
		}
		if (stmt != null) {
			stmt.close();
		}
		if (con != null) {
			con.close();
		}
	}

	if (list.length == 0) {
		GPSystem.log(GPSystem.DEBUG, module.id, "The token table is empty");
	}

	return list;
}



/**
 * Get all token that a managed by one of the given roles
 *
 * @param {Number[]} roles the list of role ids that might be involved or undefined
 * @param {Object} filter the filter criteria object
 * @param {Number} pageOffset the offset into the result set (optional)
 * @param {Number} page the maximum number of records (optional)
 * @type Token[]
 * @return the list of token
 */
TokenDAO.prototype.getTokenListByManagedByRoleId = function(roles, filter, pageOffset, page) {
	GPSystem.log(GPSystem.DEBUG, module.id, "getTokenListByManagedByRoleId(" + roles + ")");

	assert(roles instanceof Array, "Parameter roles must be a list");
	assert(typeof(filter) == "object", "Parameter filter must be an object");
	assert(typeof(pageOffset) == "undefined" || typeof(pageOffset) == "number", "Parameter pageOffset must be a Number");
	assert(typeof(page) == "undefined" || typeof(page) == "number", "Parameter page must be a Number");

	var con = null;
	var stmt = null;
	var rs = null;
	var token = null;
	var list = [];

	if (roles.length == 0) {
		GPSystem.log(GPSystem.DEBUG, module.id, "The list of roles is empty");
		return list;
	}

	try	{
		con = this.factory.getConnection();

		var where = this.factory.whereClauseFromFilter(filter);
		if (where.length > 0) {
			where += " or ";
		}

		var sql = "select * from Token where " + where;
		sql += "managedByRoleId in (";
		for (var i = 0; i < roles.length; i++) {
			if (i < roles.length -1) {
				sql += "?,"
			} else {
				sql += "?)"
			}
		}

		if (page) {
			sql += " limit ?,?";
		}

		stmt = con.prepareStatement(sql);

		var offset = this.factory.setArgumentsFromFilter(stmt, 1, filter);

		for (var i = 0; i < roles.length; i++) {
			stmt.setInt(offset++, roles[i]);
		}

		if (page) {
			stmt.setInt(offset++, pageOffset);
			stmt.setInt(offset, page);
		}

		rs = stmt.executeQuery();

		while (rs.next()) {
			token = new Token(this);
			this.factory.resultSetToProperties(rs, token);
			list.push(token);
		}
	}
	finally {
		if (rs != null) {
			rs.close();
		}
		if (stmt != null) {
			stmt.close();
		}
		if (con != null) {
			con.close();
		}
	}

	if (list.length == 0) {
		GPSystem.log(GPSystem.DEBUG, module.id, "No token is managed by one of the roles: " + roles);
	}

	return list;
}



/**
 * Count token that a managed by one of the given roles
 *
 * @param {Number[]} roles the list of role ids that might be involved or undefined
 * @param {Object} filter the filter criteria object
 * @type Token[]
 * @return the list of token
 */
TokenDAO.prototype.countTokenByManagedByRoleId = function(roles, filter) {
	GPSystem.log(GPSystem.DEBUG, module.id, "countTokenByManagedByRoleId(" + roles + ")");

	assert(roles instanceof Array, "Parameter roles must be a list");
	assert(typeof(filter) == "object", "Parameter filter must be an object");

	var con = null;
	var stmt = null;
	var rs = null;
	var token = null;
	var list = [];

	if (roles.length == 0) {
		GPSystem.log(GPSystem.DEBUG, module.id, "The list of roles is empty");
		return list;
	}

	try	{
		con = this.factory.getConnection();

		var where = this.factory.whereClauseFromFilter(filter);
		if (where.length > 0) {
			where += " or ";
		}

		var sql = "select count(id) from Token where " + where;
		sql += "managedByRoleId in (";
		for (var i = 0; i < roles.length; i++) {
			if (i < roles.length -1) {
				sql += "?,"
			} else {
				sql += "?);"
			}
		}

		stmt = con.prepareStatement(sql);

		var offset = this.factory.setArgumentsFromFilter(stmt, 1, filter);

		for (var i = 0; i < roles.length; i++) {
			stmt.setInt(offset++, roles[i]);
		}

		rs = stmt.executeQuery();
		rs.next();
		var count = rs.getInt(1);
		GPSystem.log(GPSystem.DEBUG, module.id, "countTokenByManagedByRoleId() returns " + count);
		return count;
	}
	finally {
		if (rs != null) {
			rs.close();
		}
		if (stmt != null) {
			stmt.close();
		}
		if (con != null) {
			con.close();
		}
	}
}



/**
 * Get the encoded token type
 *
 * @param {Number} type the token type - 01 for SC-HSM
 * @param {Number} platform the platform version
 * @param {Number} major the major version
 * @param {Number} minor the minor version
 * @type Number
 * @return the encoded type
 */
TokenDAO.prototype.encodeType= function(type, platform, major, minor) {
	var tokenType = type << 24;
	tokenType += platform << 16;
	tokenType += major << 8;
	tokenType += minor;
	GPSystem.log(GPSystem.DEBUG, module.id, "DB Token Type: " + tokenType.toString(HEX));
	GPSystem.log(GPSystem.DEBUG, module.id, "DB Token Type: " + tokenType);
	return tokenType;
}



/**
 * Update the token type, platform version, major version, minor version and last seen timestamp
 *
 * @param {String} path the path of this token
 * @param {Number} type the token type - 01 for SC-HSM
 * @param {Number} platform the platform version
 * @param {Number} major the major version
 * @param {Number} minor the minor version
 */
TokenDAO.prototype.updateTypeAndLastSeen= function(path, type, platform, major, minor) {
	GPSystem.log(GPSystem.DEBUG, module.id, "updateMetaData(" + path + ", " + type + ", " + platform + ", " + major + ", " + minor + ")");

	assert(path, "Parameter path must not be empty");
	assert(typeof(path) == "string", "Parameter path must be a String");

	assert(type, "Parameter type must not be empty");
	assert(typeof(type) == "number", "Parameter type must be a number");

	assert(typeof(platform) == "number", "Parameter platform must be a number");

	assert(typeof(major) == "number", "Parameter major must be a number");

	assert(typeof(minor) == "number", "Parameter minor must be a number");

	var con = null;
	var stmt = null;

	var tokenType = this.encodeType(type, platform, major, minor);

	try	{
		con = this.factory.getConnection();

		stmt = con.prepareStatement("update Token set lastSeen = ?, type = ? where path = ?;");

		var ts = new java.sql.Timestamp(new Date());
		stmt.setTimestamp(1, ts);
		stmt.setInt(2, tokenType);
		stmt.setString(3, path);
		stmt.executeUpdate();
	}
	finally {
		if (stmt != null) {
			stmt.close();
		}
		if (con != null) {
			con.close();
		}
	}
}



/**
 * Update the token's subject
 *
 * @param {Token} token the token
 * @param {Number} subjectId the new subject
 */
TokenDAO.prototype.updateSubjectId = function(token, subjectId) {
	GPSystem.log(GPSystem.DEBUG, module.id, "updateSubjectId(" + token + "," + subjectId + ")");

	assert(token, "Parameter token must not be empty");
	assert(token instanceof Token, "Parameter must be instance of Token");
	assert(subjectId, "Parameter subjectId must not be empty");
	assert(typeof(subjectId) == "number", "Parameter subjectId must be a number");

	var con = null;
	var stmt = null;

	try	{
		con = this.factory.getConnection();

		stmt = con.prepareStatement("update Token set subjectId = ? where path = ?;");

		stmt.setInt(1, subjectId);
		stmt.setString(2, token.path);
		stmt.executeUpdate();
	}
	finally {
		if (stmt != null) {
			stmt.close();
		}
		if (con != null) {
			con.close();
		}
	}

	token.subjectId = subjectId;
}



/**
 * Update the token's service request
 *
 * @param {Token} token the token
 * @param {Number} serviceRequestId the service request id
 */
TokenDAO.prototype.updateServiceRequestId = function(token, serviceRequestId) {
	GPSystem.log(GPSystem.DEBUG, module.id, "updateServiceRequestId(" + token + "," + serviceRequestId+ ")");

	assert(token, "Parameter token must not be empty");
	assert(token instanceof Token, "Parameter must be instance of Token");
	assert(serviceRequestId, "Parameter serviceRequestId must not be empty");
	assert(typeof(serviceRequestId) == "number", "Parameter serviceRequestId must be a number");
	serviceRequestId

	var con = null;
	var stmt = null;

	try	{
		con = this.factory.getConnection();

		stmt = con.prepareStatement("update Token set serviceRequestId = ? where path = ?;");

		stmt.setInt(1, serviceRequestId);
		stmt.setString(2, token.path);
		stmt.executeUpdate();
	}
	finally {
		if (stmt != null) {
			stmt.close();
		}
		if (con != null) {
			con.close();
		}
	}

	token.serviceRequestId = serviceRequestId;
}



/**
 * Set the token's subject id to null
 *
 * @param {Token} token the token
 */
TokenDAO.prototype.deregisterToken = function(path) {
	GPSystem.log(GPSystem.DEBUG, module.id, "deregisterToken(" + path + ")");

	assert(path, "Parameter path must not be empty");
	assert(typeof(path) == "string", "Parameter path must be a String");

	var con = null;
	var stmt = null;

	try	{
		con = this.factory.getConnection();

		stmt = con.prepareStatement("update Token set subjectId = NULL, serviceRequestId = NULL where path = ?;");

		stmt.setString(1, path);
		stmt.executeUpdate();
	}
	finally {
		if (stmt != null) {
			stmt.close();
		}
		if (con != null) {
			con.close();
		}
	}
}



/**
 * Add token action
 *
 * @param {Number} tokenId the token database id
 * @param {Number} serviceRequestId the database id of the service request handling this action
 */
TokenDAO.prototype.addTokenAction = function(tokenId, serviceRequestId) {
	GPSystem.log(GPSystem.DEBUG, module.id, "addTokenAction(" + tokenId + "," + serviceRequestId + ")");

	assert(typeof(tokenId) == "number", "Parameter tokenId must be a number");
	assert(typeof(serviceRequestId) == "number", "Parameter serviceRequestId must be a number");

	var con = null;
	var stmt = null;
	var rs = null;

	var tokenAction = new TokenAction(this, tokenId, serviceRequestId);

	try	{
		con = this.factory.getConnection();

		stmt = this.factory.insertStatementFromObject(con, "TokenAction", tokenAction);

		stmt.executeUpdate();

		rs = stmt.getGeneratedKeys();
		rs.next();
		tokenAction.id = rs.getInt(1);
	}
	finally {
		if (rs != null) {
			rs.close();
		}
		if (stmt != null) {
			stmt.close();
		}
		if (con != null) {
			con.close();
		}
	}

	return tokenAction;
}



/**
 * Enumerate pending service requests for token
 *
 * @param {Token} token the token
 */
TokenDAO.prototype.enumerateTokenAction = function(tokenId) {
	GPSystem.log(GPSystem.DEBUG, module.id, "enumerateTokenAction(" + tokenId + ")");

	assert(typeof(tokenId) == "number", "Parameter tokenId must be a number");

	var con = null;
	var stmt = null;
	var rs = null;
	var result = [];

	try	{
		con = this.factory.getConnection();

		stmt = con.prepareStatement("select * from TokenAction where tokenId = ? order by id;");
		stmt.setInt(1, tokenId);
		rs = stmt.executeQuery();
		while (rs.next()) {
			var action = new TokenAction(this);
			this.factory.resultSetToProperties(rs, action);
			result.push(action);
		}
	}
	finally {
		if (rs != null) {
			rs.close();
		}
		if (stmt != null) {
			stmt.close();
		}
		if (con != null) {
			con.close();
		}
	}

	return result;
}



/**
 * Remove token action
 *
 * @param {Number} id the token action id
 */
TokenDAO.prototype.removeTokenAction = function(id) {
	GPSystem.log(GPSystem.DEBUG, module.id, "removeTokenAction(" + id + ")");

	assert(typeof(id) == "number", "Parameter id must be a number");

	var con = null;
	var stmt = null;

	try	{
		con = this.factory.getConnection();

		stmt = con.prepareStatement("delete from TokenAction where id = ?;");

		stmt.setInt(1, id);
		stmt.executeUpdate();
	}
	finally {
		if (stmt != null) {
			stmt.close();
		}
		if (con != null) {
			con.close();
		}
	}
}



/**
 * Remove token action
 *
 * @param {Number} id the service request id
 */
TokenDAO.prototype.removeTokenActionForServiceRequest = function(id) {
	GPSystem.log(GPSystem.DEBUG, module.id, "removeTokenActionForServiceRequest(" + id + ")");

	assert(typeof(id) == "number", "Parameter id must be a number");

	var con = null;
	var stmt = null;

	try	{
		con = this.factory.getConnection();

		stmt = con.prepareStatement("delete from TokenAction where serviceRequestId = ?;");

		stmt.setInt(1, id);
		stmt.executeUpdate();
	}
	finally {
		if (stmt != null) {
			stmt.close();
		}
		if (con != null) {
			con.close();
		}
	}
}
