package com.transmem.action;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.ServletContext;
import java.io.IOException;
import java.sql.SQLException;
import java.sql.Connection;
import java.util.ArrayList;
import com.transmem.data.db.Databases;
import com.transmem.data.db.Users;
import com.transmem.data.db.Groups;
import com.transmem.data.db.GroupRec;
import com.transmem.data.db.Roles;
/**
* Action class for Group-related operations.
*
* @version 0.1
* @author Ted Wen
* @date May. 2007
*/
public class GroupAction extends BaseAction
{
private Logger log_ = Logger.getLogger(GroupAction.class.getName());
private int pagelimit_ = 25;
public GroupAction()
{
super();
}
/**
* Execute GroupAction operations.
*
* Request parameters:
* operation:
* creategroup
* updategroup
* deletegroup
* invite
* kick
* changeleader
* points2group
* points2member
* joingroup
* quitgroup
* variables:
* userid
* points
* group
* grpage
*/
public void execute(ServletParams param) throws ServletException, IOException
{
log_.entering("GroupAction","execute");
Session session = param.getSession();
Users user = session.getUser();
if (user == null) {
log_.severe("session.getAttribute('user') returned null");
param.sendError(MessageCode.ERR_NOT_LOGIN);
return;
}
String op = param.getParameter("operation");
Connection conn = null;
try
{
conn = getConnection(param,Databases.CATEGORY_MAIN, true);
conn.setAutoCommit(false);
if (op == null)
{
//no operation, just show page
}
else if (op.equals("creategroup"))
{
//create a new group
createGroup(conn, user, param);
}
else if (op.equals("updategroup"))
{
//update group info
updateGroup(conn, user, param);
}
else if (op.equals("deletegroup"))
{
//dismiss a group
deleteGroup(conn, user);
//TODO: notify all members
}
else if (op.equals("invite"))
{
//invite sb into the group
invite2group(conn, user, param);
//TODO: notify user
}
else if (op.equals("kick"))
{
//kick member out of group
kickmember(conn, user, param);
//TODO: notify user
}
else if (op.equals("changeleader"))
{
changeLeader(conn, user, param);
//TODO: notify all members
}
else if (op.equals("points2group"))
{
//transfer leaders points to group account
transferPointsToGroup(conn, user, param);
//TODO: notify all members
}
else if (op.equals("points2member"))
{
//transfer some points from group account to a member
transferPointsToMember(conn, user, param);
//TODO: notify member
}
else if (op.equals("joingroup"))
{
//common user joins a group, check group publicity
joinGroup(conn, user, param);
//TODO: notify all members
}
else if (op.equals("quitgroup"))
{
//member quit a group
quitGroup(conn, user);
//TODO: notify all members
}
//next, send back proper page to show my group or a list of other groups
if (user.getRole().equals("G"))
{
String grpage = param.getParameter("grpage");
if (grpage == null || grpage.equals("mygroup"))
{
if (user.getGroup() > 0)
{
//User is a group leader and has a group
Groups g = new Groups(conn, user.getGroup());
session.setMyGroup(g);
Users usrs = new Users(conn);
ArrayList<Users> members = usrs.queryByGroup(user.getGroup());
session.setMemberList(members);
}
else
{
//User can be a group leader, but has no group
session.removeMyGroup();
}
setNextPage(PageLinks.MYGROUP_PAGE);
}
else
{
//grpage == 'list', display others
loadGroups(conn, session, param);
setNextPage(PageLinks.GROUPLIST_PAGE);
}
}
else
{
//user is not group leader
if (user.getGroup() > 0)
{
//user is in a group
Groups grp = new Groups(conn, user.getGroup());
session.setMyGroup(grp);
loadGroups(conn, session, param);
}
else
{
//user has no group
session.removeMyGroup();
loadGroups(conn, session, param);
}
setNextPage(PageLinks.GROUP_PAGE);
}
conn.commit();
}
catch (SQLException e)
{
try { conn.rollback(); } catch (Exception x) {}
log_.severe(e.getMessage());
param.sendError(900,e.toString());
}
finally
{
if (conn != null)
try { conn.close(); } catch (SQLException x) {}
}
}
/**
* Load a page of public groups required as ArrayList<GroupRec>, and store in session.
* @param conn - Connection reference
* @param session - Session to hold attributes
* @param param - ServletParams containing request parameters
*/
protected void loadGroups(Connection conn, Session session, ServletParams param) throws SQLException
{
String orderby = param.getParameter("order");
if (orderby == null)
orderby = session.getGroupOrder();
else
session.setGroupOrder(orderby);
//determine which page to load
String offsets = param.getParameter("offset");
if (offsets == null)
offsets = session.getGroupOffset();
else
session.setGroupOffset(offsets);
int offset = 0;
if (offsets != null)
{
try
{
offset = Integer.parseInt(offsets);
}
catch (Exception x)
{
}
}
Groups g = new Groups(conn);
ArrayList<GroupRec> grs = null;
if (orderby == null)
grs = g.queryPublicGroups(offset, this.pagelimit_);
else if (orderby.equals("date"))
grs = g.queryLatestPublicGroups(offset, this.pagelimit_);
else if (orderby.equals("members"))
grs = g.queryLargestPublicGroups(offset, this.pagelimit_);
else
grs = g.queryPublicGroups(offset, this.pagelimit_);
session.setGroupList(grs);
}
/**
* Get user id string from request paraemter 'userid' and create Users object from DB.
*/
private Users getUser(Connection conn, ServletParams param) throws SQLException
{
String uids = param.getParameter("userid");
if (uids == null)
{
throw new SQLException("userid not specified");
}
try
{
int uid = Integer.parseInt(uids);
if (uid <= 0)
{
throw new SQLException("userid zero or negative");
}
return new Users(conn, uid);
}
catch (NumberFormatException nfe)
{
throw new SQLException("userid '"+uids+"' invalid");
}
}
/**
* Find out the points from request parameter 'points'.
*/
private int getPoints(ServletParams param) throws SQLException
{
String pts = param.getParameter("points");
if (pts == null)
{
throw new SQLException("No points to transfer");
}
int points = 0;
try
{
points = Integer.parseInt(pts);
}
catch (NumberFormatException ne)
{
throw new SQLException("Points invalid");
}
if (points <= 0)
{
throw new SQLException("Points zero or negative");
}
return points;
}
/**
* Transfer some points from group leader account to the group account.
* @param conn - Connection to use
* @param user - Users of the group leader
* @param param - request paraemters
*/
protected void transferPointsToGroup(Connection conn, Users user, ServletParams param) throws SQLException
{
log_.info("enter transferPointsToGroup");
int points = getPoints(param);
Groups grp = new Groups(conn, user.getGroup());
if (grp.getLeader() != user.getUserID())
{
throw new SQLException("User not group leader");
}
if (user.getPoints()<points)
{
throw new SQLException("User does not have enough points");
}
grp.clearUpdates();
grp.setPoints(grp.getPoints()+points);
log_.info("about to add "+points+" points to group");
grp.update();
user.clearUpdates();
user.setPoints(user.getPoints()-points);
log_.info("about decrease points from group leader");
user.update(conn);
log_.info("transaction complete");
}
/**
* Transfer some group points to the specified member.
* @param conn - Connection to use
* @param user - Users of the group leader
* @param param - request paraemters
*/
protected void transferPointsToMember(Connection conn, Users user, ServletParams param) throws SQLException
{
log_.info("enter transferPointsToMember");
//get points
int points = getPoints(param);
//group to get points from
Groups grp = new Groups(conn, user.getGroup());
if (grp.getLeader() != user.getUserID())
{
throw new SQLException("User not group leader");
}
if (grp.getPoints()<points)
{
throw new SQLException("Group does not have enough points");
}
//find user to transfer points to
Users member = getUser(conn, param);
if (member.getGroup()!=grp.getGroupID())
{
throw new SQLException("User not a group member");
}
member.clearUpdates();
member.setPoints(member.getPoints()+points);
log_.info("about to add "+points+" points to member "+member.getUsername());
member.update();
grp.clearUpdates();
grp.setPoints(grp.getPoints()-points);
log_.info("about to delete points from group");
grp.update();
log_.info("transaction complete");
}
/**
* A common user joins a selected group.
*/
protected void joinGroup(Connection conn, Users user, ServletParams param) throws SQLException
{
String grps = param.getParameter("group");
if (grps == null)
{
throw new SQLException("Parameter group not specified");
}
int grpid = 0;
try
{
grpid = Integer.parseInt(grps);
}
catch (NumberFormatException nfe)
{
throw new SQLException("Parameter group '"+grps+"' invalid group ID");
}
Groups grp = new Groups(conn, grpid);
if (grp.getPublicity()==3)
{
user.clearUpdates();
user.setGroup(grpid);
user.update(conn);
grp.clearUpdates();
grp.setMembers(grp.getMembers()+1);
grp.update();
}
else if (grp.getPublicity()==2)
{
//TODO: send a message to group leader
log_.info("User '"+user.getRealname()+"' applies to join group "+grpid);
}
else
{
log_.warning("User '"+user.getRealname()+"' wants to join a closed group: "+grpid);
}
}
/**
* A group member quits the group.
*/
protected void quitGroup(Connection conn, Users user) throws SQLException
{
if (user.getGroup() <= 0)
throw new SQLException("User has not joined a group");
Groups grp = new Groups(conn, user.getGroup());
if (grp != null && grp.getLeader()==user.getUserID())
throw new SQLException("Group leader cannot quit");
//if (grp == null)
// throw new Exception("Group "+user.getGroup()+" no longer exists");
user.clearUpdates();
user.setGroup(0);
user.update(conn);
grp.clearUpdates();
grp.setMembers(grp.getMembers()-1);
grp.update();
}
/**
* Change group leader to a member.
* @param conn - Connection to use
* @param user - Users of the group leader
* @param param - request paraemters
*/
protected void changeLeader(Connection conn, Users user, ServletParams param) throws SQLException
{
log_.info("enter changeLeader");
String member = param.getParameter("userid");
if (member == null)
{
throw new SQLException("User not specified to change leader");
}
int uid = 0;
try
{
uid = Integer.parseInt(member);
}
catch (NumberFormatException ne)
{
throw new SQLException("User ID invalid for changing leader");
}
Groups grp = new Groups(conn, user.getGroup());
if (grp.getLeader() != user.getUserID())
{
throw new SQLException("User not group leader");
}
Users usr = new Users(conn, uid);
if (usr.getGroup()!=grp.getGroupID())
{
throw new SQLException("User not a group member");
}
Roles r = new Roles(conn, usr.getRole());
if (r.getLevel() < 1000)
{
throw new SQLException("Member '"+usr.getRealname()+"' not super user");
}
log_.info("about to set leader to "+uid);
grp.setLeader(uid);
log_.info("group leader changed");
}
/**
* Invite somebody to join the group. It's automatically joined.
* @param conn - Connection to use
* @param user - Users of the group leader
* @param param - request paraemters
*/
protected void invite2group(Connection conn, Users user, ServletParams param) throws SQLException
{
log_.info("enter invite2group");
String suser = param.getParameter("userid");
if (suser != null)
{
int uid = 0;
try
{
uid = Integer.parseInt(suser);
}
catch (Exception x)
{
throw new SQLException("User ID invalid");
}
int grpid = user.getGroup();
if (grpid > 0)
{
Groups grp = new Groups(conn, grpid);
if (user.getUserID() == grp.getLeader())
{
Users member = new Users(conn, uid);
if (member.getGroup()==0)
{
member.clearUpdates();
member.setGroup(grpid);
log_.info("about to update member, set group to "+grpid);
member.update(conn);
grp.clearUpdates();
grp.setMembers(grp.getMembers()+1);
log_.info("about to update group, add member");
grp.update();
}
else
{
log_.info("User has joined another group");
throw new SQLException("User has joined another group");
}
}
else
{
log_.warning("Not group leader, can't invite member");
throw new SQLException("You are not group leader");
}
}
else
{
log_.warning("User "+user.getUsername()+" has no group, but wants to add sb");
}
}
else
{
log_.warning("Invite nobody to group");
throw new SQLException("Invite nobody to group");
}
}
/**
* The leader kick a group member out of the group.
* @param conn - Connection
* @param user - Users object for the leader
* @param param - request containing parameters
*/
protected void kickmember(Connection conn, Users user, ServletParams param) throws SQLException
{
log_.info("enter kickmember");
int uid = 0;
String su = param.getParameter("uid");
if (su == null)
{
throw new SQLException("Member uid not given");
}
if (user.getGroup()==0)
{
throw new SQLException("User has no group");
}
Groups grp = new Groups(conn, user.getGroup());
if (user.getUserID()!=grp.getLeader())
{
throw new SQLException("User is not group leader");
}
try
{
uid = Integer.parseInt(su);
}
catch (Exception x)
{
throw new SQLException("Member uid invalid");
}
Users usr = new Users(conn, uid);
usr.clearUpdates();
usr.setGroup(0);
log_.info("about to update user, clear group");
usr.update();
grp.clearUpdates();
grp.setMembers(grp.getMembers()-1);
log_.info("about to update group, decrease member");
grp.update();
log_.info("group updated");
}
/**
* Create a Group account and insert into T_Groups table
* @param conn - Connection to use
* @param user - Users object containing user ID for the group leader/creator
* @param param - parameter containing request parameters
*/
protected void createGroup(Connection conn, Users user, ServletParams param) throws SQLException
{
log_.info("enter createGroup");
String groupName = param.getParameter("GroupName");
String publicity = param.getParameter("Publicity");
String description = param.getParameter("Description");
short pub = 3;
try
{
pub = (short)Integer.parseInt(publicity);
}
catch (NumberFormatException fe)
{
}
int gid = getSequenceInt(conn, "S_Groups");
Groups grp = new Groups(conn);
grp.setGroupID(gid);
grp.setGroupName(groupName);
grp.setLeader(user.getUserID());
grp.setPublicity(pub);
grp.setDesc(description);
log_.info("about to insert group");
grp.insert();
log_.info("group "+gid+" inserted");
}
/**
* Update a group info
* @param conn
* @param user - group leader
* @param param - request containing parameters
*/
protected void updateGroup(Connection conn, Users user, ServletParams param) throws SQLException
{
log_.info("enter updateGroup");
String groupName = param.getParameter("GroupName");
String publicity = param.getParameter("Publicity");
String description = param.getParameter("Description");
short pub = 3;
if (publicity != null)
try
{
pub = (short)Integer.parseInt(publicity);
}
catch (NumberFormatException fe)
{
}
int gid = user.getGroup();
if (gid < 1)
{
throw new SQLException("User has not group to update");
}
Groups grp = new Groups(conn, gid);
grp.clearUpdates();
grp.setGroupName(groupName);
grp.setLeader(user.getUserID());
grp.setPublicity(pub);
grp.setDesc(description);
log_.info("about to update group, gid="+gid);
grp.update();
log_.info("update done");
}
/**
* Delete a group by the creator/leader
* @param conn - Connection to use
* @param user - Users object as the group owner
*/
protected void deleteGroup(Connection conn, Users user) throws SQLException
{
log_.info("enter deleteGroup");
int grpid = user.getGroup();
if (grpid > 0)
{
Groups grp = new Groups(conn, grpid);
if (grpid == grp.getLeader())
{
//reset all user group for this group
user.setConnection(conn);
log_.info("about to clear members");
user.resetGroup(grpid);
//then delete the group
log_.info("about to delete the group");
grp.delete(conn);
log_.info("group "+grpid+" deleted");
}
else
{
log_.warning("User '"+user.getUsername()+"' not group leader to delete group "+grp.getGroupID());
throw new SQLException("No right to delete other's group");
}
}
else
{
log_.warning("User '"+user.getUsername()+"' has no group to delete");
throw new SQLException("User no group to delete");
}
}
}