/*
* ConcourseConnect
* Copyright 2009 Concursive Corporation
* http://www.concursive.com
*
* This file is part of ConcourseConnect, an open source social business
* software and community platform.
*
* Concursive ConcourseConnect is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, version 3 of the License.
*
* Under the terms of the GNU Affero General Public License you must release the
* complete source code for any application that uses any part of ConcourseConnect
* (system header files and libraries used by the operating system are excluded).
* These terms must be included in any work that has ConcourseConnect components.
* If you are developing and distributing open source applications under the
* GNU Affero General Public License, then you are free to use ConcourseConnect
* under the GNU Affero General Public License.
*
* If you are deploying a web site in which users interact with any portion of
* ConcourseConnect over a network, the complete source code changes must be made
* available. For example, include a link to the source archive directly from
* your web site.
*
* For OEMs, ISVs, SIs and VARs who distribute ConcourseConnect with their
* products, and do not license and distribute their source code under the GNU
* Affero General Public License, Concursive provides a flexible commercial
* license.
*
* To anyone in doubt, we recommend the commercial license. Our commercial license
* is competitively priced and will eliminate any confusion about how
* ConcourseConnect can be used and distributed.
*
* ConcourseConnect 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 Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with ConcourseConnect. If not, see <http://www.gnu.org/licenses/>.
*
* Attribution Notice: ConcourseConnect is an Original Work of software created
* by Concursive Corporation
*/
package com.concursive.connect.web.modules.calendar.dao;
import com.concursive.commons.db.DatabaseUtils;
import com.concursive.commons.text.StringUtils;
import com.concursive.commons.web.mvc.beans.GenericBean;
import com.concursive.connect.web.modules.calendar.utils.DimDimUtils;
import com.concursive.connect.web.modules.common.social.rating.dao.Rating;
import com.concursive.connect.web.modules.profile.dao.Project;
import java.sql.*;
import java.util.ArrayList;
/**
* Represents a Meeting page
*
* @author matt rajkowski
* @version $Id$
* @created February 7, 2006
*/
public class Meeting extends GenericBean {
public static final String TABLE = "project_calendar_meeting";
public static final String PRIMARY_KEY = "meeting_id";
private int id = -1;
private int projectId = -1;
private Timestamp entered = null;
private int enteredBy = -1;
private Timestamp modified = null;
private int modifiedBy = -1;
private int owner = -1;
private String title = null;
private String location = null;
private Timestamp startDate = null;
private Timestamp endDate = null;
private boolean isTentative = false;
private int durationDays = 0;
private int durationHours = 0;
private int durationMinutes = 0;
private boolean byInvitationOnly = true;
private String description = null;
private boolean isDimdim = false;
private String meetingInvitees = "";
private String dimdimMeetingId = null;
private String dimdimUrl = null;
private String dimdimUsername = null;
private String dimdimPassword = null;
private String dimdimMeetingKey = null;
private int ratingCount = 0;
private int ratingValue = 0;
private double ratingAvg = 0.0;
private int inappropriateCount = 0;
private boolean isWebcast = false;
// Helper objects
private MeetingAttendeeList meetingAttendeeList = null;
public Meeting() {
}
public Meeting(ResultSet rs) throws SQLException {
buildRecord(rs);
}
public Meeting(Connection db, int id, int projectId) throws SQLException {
this.projectId = projectId;
queryRecord(db, id);
}
public Meeting(Connection db, int id) throws SQLException {
queryRecord(db, id);
}
public static Meeting createMeetingFromProject(Project project) {
Meeting meeting = new Meeting();
meeting.setTitle(project.getTitle());
meeting.setStartDate(project.getRequestDate());
meeting.setEndDate(project.getEstimatedCloseDate());
meeting.setEnteredBy(project.getEnteredBy());
meeting.setModifiedBy(project.getModifiedBy());
meeting.setProjectId(project.getId());
meeting.setOwner(project.getEnteredBy());
meeting.setLocation(project.getAddressToAndLocation());
return meeting;
}
public void queryRecord(Connection db, int meetingId) throws SQLException {
StringBuffer sql = new StringBuffer();
sql.append(
"SELECT m.* " +
"FROM project_calendar_meeting m " +
"WHERE meeting_id = ? ");
if (projectId > -1) {
sql.append("AND project_id = ? ");
}
PreparedStatement pst = db.prepareStatement(sql.toString());
int i = 0;
pst.setInt(++i, meetingId);
if (projectId > -1) {
pst.setInt(++i, projectId);
}
ResultSet rs = pst.executeQuery();
if (rs.next()) {
buildRecord(rs);
}
rs.close();
pst.close();
if (id == -1) {
throw new SQLException("Meeting record not found.");
}
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public void setId(String tmp) {
this.id = Integer.parseInt(tmp);
}
public int getProjectId() {
return projectId;
}
public void setProjectId(int projectId) {
this.projectId = projectId;
}
public void setProjectId(String tmp) {
this.projectId = Integer.parseInt(tmp);
}
public int getOwner() {
return owner;
}
public void setOwner(int owner) {
this.owner = owner;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public Timestamp getStartDate() {
return startDate;
}
public void setStartDate(Timestamp startDate) {
this.startDate = startDate;
}
/**
* Sets the startDate attribute of the Project object
*
* @param startDate The new startDate value
*/
public void setStartDate(String startDate) {
this.startDate = DatabaseUtils.parseTimestamp(startDate);
}
public Timestamp getEndDate() {
return endDate;
}
public void setEndDate(Timestamp endDate) {
this.endDate = endDate;
}
/**
* sets endDate attribute of the ProjectObject
*
* @param endDate new endDate value
*/
public void setEndDate(String endDate) {
this.endDate = DatabaseUtils.parseTimestamp(endDate);
}
public boolean getIsTentative() {
return isTentative;
}
public void setIsTentative(boolean isTentative) {
this.isTentative = isTentative;
}
/**
* Sets the isTentative attribute of the Project object
*
* @param isTentative The new isTentative value
*/
public void setIsTentative(String isTentative) {
this.isTentative = DatabaseUtils.parseBoolean(isTentative);
}
/**
* @return if true meeting is a Dimdim meeting
*/
public boolean getIsDimdim() {
return isDimdim;
}
/**
* @param isDimdim Set to true if its a Dimdim meeting
*/
public void setIsDimdim(boolean isDimdim) {
this.isDimdim = isDimdim;
}
/**
* @param isDimdim Set to true if its a Dimdim meeting
*/
public void setIsDimdim(String isDimdim) {
this.isDimdim = DatabaseUtils.parseBoolean(isDimdim);
}
/**
* @param meetingInvitees Dimdim meeting invitees
*/
public void setMeetingInvitees(String meetingInvitees) {
this.meetingInvitees = meetingInvitees;
}
public String getMeetingInvitees() {
return meetingInvitees;
}
/**
* @return URL of dimdim server
*/
public String getDimdimUrl() {
return dimdimUrl;
}
/**
* @param dimdimUrl URL of dimdim server
*/
public void setDimdimUrl(String dimdimUrl) {
//add a slash if the URL does not end with it
if (StringUtils.hasText(dimdimUrl) && !dimdimUrl.endsWith("/")) {
dimdimUrl += "/";
}
this.dimdimUrl = dimdimUrl;
}
/**
* @return Dimdim web meeting id
*/
public String getDimdimMeetingId() {
return dimdimMeetingId;
}
/**
* @param dimdimMeetingId Dimdim web meeting id
*/
public void setDimdimMeetingId(String dimdimMeetingId) {
this.dimdimMeetingId = dimdimMeetingId;
}
/**
* @return Username to dimdim server
*/
public String getDimdimUsername() {
return dimdimUsername;
}
/**
* @param dimdimUsername username to dimdim server
*/
public void setDimdimUsername(String dimdimUsername) {
this.dimdimUsername = dimdimUsername;
}
/**
* @return password to dimdim server
*/
public String getDimdimPassword() {
return dimdimPassword;
}
/**
* @param dimdimPassword password to dimdim server
*/
public void setDimdimPassword(String dimdimPassword) {
this.dimdimPassword = dimdimPassword;
}
/**
* @return - Participant meeting key for private Dimdim meeting.
*/
public String getDimdimMeetingKey() {
if (!StringUtils.hasText(dimdimMeetingKey) && isDimdim && byInvitationOnly) {
dimdimMeetingKey = StringUtils.randomString(5, 6);
}
return dimdimMeetingKey;
}
/**
*
* @param dimdimMeetingKey
*/
public void setDimdimMeetingKey(String dimdimMeetingKey) {
this.dimdimMeetingKey = dimdimMeetingKey;
}
public Timestamp getEntered() {
return entered;
}
public void setEntered(Timestamp entered) {
this.entered = entered;
}
public void setEntered(String tmp) {
this.entered = DatabaseUtils.parseTimestamp(tmp);
}
public int getEnteredBy() {
return enteredBy;
}
public void setEnteredBy(int enteredBy) {
this.enteredBy = enteredBy;
}
public Timestamp getModified() {
return modified;
}
public void setModified(Timestamp modified) {
this.modified = modified;
}
public void setModified(String tmp) {
this.modified = DatabaseUtils.parseTimestamp(tmp);
}
public int getModifiedBy() {
return modifiedBy;
}
public void setModifiedBy(int modifiedBy) {
this.modifiedBy = modifiedBy;
}
/**
* @return the ratingCount
*/
public int getRatingCount() {
return ratingCount;
}
/**
* @param ratingCount the ratingCount to set
*/
public void setRatingCount(int ratingCount) {
this.ratingCount = ratingCount;
}
public void setRatingCount(String ratingCount) {
this.ratingCount = Integer.parseInt(ratingCount);
}
/**
* @return the ratingValue
*/
public int getRatingValue() {
return ratingValue;
}
/**
* @param ratingValue the ratingValue to set
*/
public void setRatingValue(int ratingValue) {
this.ratingValue = ratingValue;
}
public void setRatingValue(String ratingValue) {
this.ratingValue = Integer.parseInt(ratingValue);
}
/**
* @return the ratingAvg
*/
public double getRatingAvg() {
return ratingAvg;
}
/**
* @param ratingAvg the ratingAvg to set
*/
public void setRatingAvg(double ratingAvg) {
this.ratingAvg = ratingAvg;
}
public void setRatingAvg(String ratingAvg) {
this.ratingAvg = Double.parseDouble(ratingAvg);
}
/**
* @return the inappropriateCount
*/
public int getInappropriateCount() {
return inappropriateCount;
}
/**
* @param inappropriateCount the inappropriateCount to set
*/
public void setInappropriateCount(int inappropriateCount) {
this.inappropriateCount = inappropriateCount;
}
public void setInappropriateCount(String inappropriateCount) {
this.inappropriateCount = Integer.parseInt(inappropriateCount);
}
public MeetingAttendeeList getMeetingAttendeeList() {
return meetingAttendeeList;
}
public void setMeetingAttendeeList(MeetingAttendeeList meetingAttendeeList) {
this.meetingAttendeeList = meetingAttendeeList;
}
public boolean getIsWebcast() {
return isWebcast;
}
public void setIsWebcast(boolean isWebcast) {
this.isWebcast = isWebcast;
}
public void setIsWebcast(String tmp) {
this.isWebcast = DatabaseUtils.parseBoolean(tmp);
}
public boolean hasDuration() {
return (durationDays > 0 || durationHours > 0 || durationMinutes > 0);
}
public String getDuration() {
StringBuffer duration = new StringBuffer();
if (durationDays > 0) {
duration.append(durationDays).append(" day");
if (durationDays > 1) {
duration.append("s");
}
}
if (durationHours > 0) {
if (duration.length() > 0) {
duration.append(" ");
}
duration.append(durationHours).append(" hour");
if (durationHours > 1) {
duration.append("s");
}
}
if (durationMinutes > 0) {
if (duration.length() > 0) {
duration.append(" ");
}
duration.append(durationMinutes).append(" minute");
if (durationMinutes > 1) {
duration.append("s");
}
}
return duration.toString();
}
public boolean getByInvitationOnly() {
return byInvitationOnly;
}
public void setByInvitationOnly(boolean byInvitationOnly) {
this.byInvitationOnly = byInvitationOnly;
}
public void setByInvitationOnly(String byInvitationOnly) {
this.byInvitationOnly = DatabaseUtils.parseBoolean(byInvitationOnly);
}
public boolean getAllowUsersToJoin() {
return !byInvitationOnly;
}
public void setAllowUsersToJoin(boolean allowUsersToJoin) {
this.byInvitationOnly = !allowUsersToJoin;
}
public void setAllowUsersToJoin(String allowUsersToJoin) {
this.byInvitationOnly = !DatabaseUtils.parseBoolean(allowUsersToJoin);
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
/**
* The following fields depend on a timezone preference
*
* @return The timeZoneParams value
*/
public static ArrayList<String> getTimeZoneParams() {
ArrayList<String> thisList = new ArrayList<String>();
thisList.add("startDate");
thisList.add("endDate");
return thisList;
}
private void buildRecord(ResultSet rs) throws SQLException {
id = rs.getInt("meeting_id");
projectId = rs.getInt("project_id");
entered = rs.getTimestamp("entered");
enteredBy = rs.getInt("enteredby");
modified = rs.getTimestamp("modified");
modifiedBy = rs.getInt("modifiedby");
owner = rs.getInt("owner");
title = rs.getString("title");
location = rs.getString("location");
startDate = rs.getTimestamp("start_date");
endDate = rs.getTimestamp("end_date");
isTentative = rs.getBoolean("is_tentative");
byInvitationOnly = rs.getBoolean("by_invitation_only");
description = rs.getString("description");
if (startDate != null) {
if (endDate != null) {
float durationCheck = ((endDate.getTime() - startDate.getTime()) / 60000);
int totalMinutes = java.lang.Math.round(durationCheck);
durationDays = java.lang.Math.round(totalMinutes / 60 / 24);
durationHours = java.lang.Math.round((totalMinutes - (60 * 24 * durationDays)) / 60);
durationMinutes = java.lang.Math.round(totalMinutes - (60 * durationHours));
}
}
ratingCount = DatabaseUtils.getInt(rs, "rating_count", 0);
ratingValue = DatabaseUtils.getInt(rs, "rating_value", 0);
ratingAvg = DatabaseUtils.getDouble(rs, "rating_avg", 0.0);
inappropriateCount = DatabaseUtils.getInt(rs, "inappropriate_count", 0);
isDimdim = rs.getBoolean("is_dimdim");
dimdimUrl = rs.getString("dimdim_url");
dimdimMeetingId = rs.getString("dimdim_meetingid");
dimdimUsername = rs.getString("dimdim_username");
dimdimPassword = DimDimUtils.decryptData(rs.getString("dimdim_password"));
dimdimMeetingKey = rs.getString("dimdim_meeting_key");
isWebcast = rs.getBoolean("is_webcast");
}
public boolean isValid() {
if (projectId == -1) {
errors.put("actionError", "Project ID not specified");
}
if (!StringUtils.hasText(title)) {
errors.put("titleError", "Required field");
}
if (startDate == null) {
errors.put("startDateError", "Required field");
}
if (endDate == null) {
errors.put("endDateError", "Required field");
}
if (owner == -1 && enteredBy > -1) {
owner = enteredBy;
}
/*
if (owner == -1 || enteredBy == -1 || modifiedBy == -1) {
errors.put("contentError", "Required field");
} */
return !hasErrors();
}
public boolean insert(Connection db) throws SQLException {
if (!isValid()) {
return false;
}
boolean commit = db.getAutoCommit();
try {
if (commit) {
db.setAutoCommit(false);
}
StringBuffer sql = new StringBuffer();
sql.append(
"INSERT INTO project_calendar_meeting " +
"(project_id, title, location, start_date, end_date, is_tentative, ");
if (entered != null) {
sql.append("entered, ");
}
if (modified != null) {
sql.append("modified, ");
}
if (description != null) {
sql.append("description, ");
}
if (dimdimMeetingId != null) {
sql.append("dimdim_meetingid, ");
}
if (dimdimUrl != null) {
sql.append("dimdim_url, ");
}
if (dimdimUsername != null) {
sql.append("dimdim_username, ");
}
if (dimdimPassword != null) {
sql.append("dimdim_password, ");
}
if (getDimdimMeetingKey() != null) {
sql.append("dimdim_meeting_key, ");
}
sql.append("owner,enteredby, modifiedby, by_invitation_only, is_dimdim, is_webcast)");
sql.append("VALUES (?, ?, ?, ?, ?, ?, ");
if (entered != null) {
sql.append("?, ");
}
if (modified != null) {
sql.append("?, ");
}
if (description != null) {
sql.append("?, ");
}
if (dimdimMeetingId != null) {
sql.append("?, ");
}
if (dimdimUrl != null) {
sql.append("?, ");
}
if (dimdimUsername != null) {
sql.append("?, ");
}
if (dimdimPassword != null) {
sql.append("?, ");
}
if (dimdimMeetingKey != null) {
sql.append("?, ");
}
sql.append("?,?,?,?,?,?) ");
int i = 0;
//Insert the Meeting
PreparedStatement pst = db.prepareStatement(sql.toString());
pst.setInt(++i, projectId);
pst.setString(++i, title);
pst.setString(++i, location);
pst.setTimestamp(++i, startDate);
pst.setTimestamp(++i, endDate);
pst.setBoolean(++i, isTentative);
if (entered != null) {
pst.setTimestamp(++i, entered);
}
if (modified != null) {
pst.setTimestamp(++i, modified);
}
if (description != null) {
pst.setString(++i, description);
}
if (dimdimMeetingId != null) {
pst.setString(++i, dimdimMeetingId);
}
if (dimdimUrl != null) {
pst.setString(++i, dimdimUrl);
}
if (dimdimUsername != null) {
pst.setString(++i, dimdimUsername);
}
if (dimdimPassword != null) {
pst.setString(++i, DimDimUtils.encryptData(dimdimPassword));
}
if (dimdimMeetingKey != null) {
pst.setString(++i, dimdimMeetingKey);
}
pst.setInt(++i, owner);
pst.setInt(++i, enteredBy);
pst.setInt(++i, modifiedBy);
pst.setBoolean(++i, byInvitationOnly);
pst.setBoolean(++i, isDimdim);
pst.setBoolean(++i, isWebcast);
pst.execute();
pst.close();
id = DatabaseUtils.getCurrVal(db, "project_calendar_meeting_meeting_id_seq", -1);
if (commit) {
db.commit();
}
} catch (SQLException e) {
if (commit) {
db.rollback();
}
throw new SQLException(e.getMessage());
} finally {
if (commit) {
db.setAutoCommit(true);
}
}
return true;
}
public int update(Connection db) throws SQLException {
int resultCount = 0;
boolean commit = db.getAutoCommit();
try {
if (commit) {
db.setAutoCommit(false);
}
if (this.getId() == -1) {
throw new SQLException("ID was not specified");
}
if (!isValid()) {
return -1;
}
int i = 0;
String sql = "UPDATE project_calendar_meeting " +
"SET title = ?, " +
"location = ?, end_date = ?, start_date = ?, is_tentative = ?, " +
"modifiedby = ?, modified = CURRENT_TIMESTAMP, by_invitation_only = ?, " +
"is_dimdim = ?, is_webcast = ?, dimdim_meetingid = ? ";
if (description != null) {
sql += ", description = ? ";
}
if (dimdimUrl != null) {
sql += ", dimdim_url = ? ";
}
if (dimdimUsername != null) {
sql += ", dimdim_username = ? ";
}
if (dimdimPassword != null) {
sql += ", dimdim_password = ? ";
}
if (getDimdimMeetingKey() != null) {
sql += ", dimdim_meeting_key = ? ";
}
sql += "WHERE meeting_id = ? AND modified = ?";
PreparedStatement pst = db.prepareStatement(sql);
pst.setString(++i, title);
pst.setString(++i, location);
pst.setTimestamp(++i, endDate);
pst.setTimestamp(++i, startDate);
pst.setBoolean(++i, isTentative);
pst.setInt(++i, this.getModifiedBy());
pst.setBoolean(++i, byInvitationOnly);
pst.setBoolean(++i, isDimdim);
pst.setBoolean(++i, isWebcast);
pst.setString(++i, dimdimMeetingId);
if (description != null) {
pst.setString(++i, description);
}
if (dimdimUrl != null) {
pst.setString(++i, dimdimUrl);
}
if (dimdimUsername != null) {
pst.setString(++i, dimdimUsername);
}
if (dimdimPassword != null) {
pst.setString(++i, DimDimUtils.encryptData(dimdimPassword));
}
if (dimdimMeetingKey != null) {
pst.setString(++i, dimdimMeetingKey);
}
pst.setInt(++i, id);
pst.setTimestamp(++i, modified);
resultCount = pst.executeUpdate();
pst.close();
if (commit) {
db.commit();
}
} catch (SQLException e) {
if (commit) {
db.rollback();
}
throw new SQLException(e.getMessage());
} finally {
if (commit) {
db.setAutoCommit(true);
}
}
return resultCount;
}
public void delete(Connection db) throws SQLException {
boolean autoCommit = db.getAutoCommit();
try {
if (autoCommit) {
db.setAutoCommit(false);
}
//Delete rating
Rating.delete(db, id, TABLE, PRIMARY_KEY);
// Delete the Meeting Attendees
PreparedStatement pst = db.prepareStatement(
"DELETE FROM project_calendar_meeting_attendees " +
"WHERE meeting_id = ? ");
pst.setInt(1, id);
pst.execute();
pst.close();
// Delete the Meeting
pst = db.prepareStatement(
"DELETE FROM project_calendar_meeting " +
"WHERE meeting_id = ? ");
int i = 0;
pst.setInt(++i, id);
pst.execute();
pst.close();
if (autoCommit) {
db.commit();
}
} catch (Exception e) {
if (autoCommit) {
db.rollback();
}
throw new SQLException(e.getMessage());
} finally {
if (autoCommit) {
db.setAutoCommit(true);
}
}
}
public void buildAttendeeList(Connection db) throws SQLException {
meetingAttendeeList = new MeetingAttendeeList();
meetingAttendeeList.setMeetingId(id);
meetingAttendeeList.buildList(db);
}
}