/*
* 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.communications.dao;
import com.concursive.commons.db.DatabaseUtils;
import com.concursive.connect.web.modules.login.dao.User;
import com.concursive.connect.web.modules.login.utils.UserUtils;
import com.concursive.connect.web.modules.members.dao.TeamMember;
import java.sql.*;
import java.util.Calendar;
import java.util.TimeZone;
/**
* Represents a queue to track email updates for a particular user
*
* @author Ananth
* @created Nov 30, 2009
*/
public class EmailUpdatesQueue {
//email update queue status
public final static int STATUS_UNDEFINED = -1;
public final static int STATUS_UNSCHEDULED = 0;
public final static int STATUS_SCHEDULED = 1;
public final static int STATUS_PROCESSING = 2;
private int id = -1;
private Timestamp entered = null;
private Timestamp modified = null;
private int enteredBy = -1;
private int modifiedBy = -1;
private boolean enabled = true;
//how often to send the email
private boolean scheduleOften = false;
private boolean scheduleDaily = false;
private boolean scheduleWeekly = false;
private boolean scheduleMonthly = false;
//which day of the week to send the email on
private boolean scheduleMonday = false;
private boolean scheduleTuesday = false;
private boolean scheduleWednesday = false;
private boolean scheduleThursday = false;
private boolean scheduleFriday = false;
private boolean scheduleSaturday = false;
private boolean scheduleSunday = false;
//the calculated next run time
private Timestamp scheduleTime = null;
private int status = STATUS_UNSCHEDULED;
private Timestamp processed = null;
public EmailUpdatesQueue() {
}
public EmailUpdatesQueue(Connection db, int queueId) throws SQLException {
queryRecord(db, queueId);
}
public EmailUpdatesQueue(ResultSet rs) throws SQLException {
buildRecord(rs);
}
public void queryRecord(Connection db, int queueId) throws SQLException {
PreparedStatement pst = db.prepareStatement(
"SELECT q.* " +
"FROM email_updates_queue q " +
"WHERE queue_id = ? ");
pst.setInt(1, queueId);
ResultSet rs = pst.executeQuery();
if (rs.next()) {
buildRecord(rs);
}
rs.close();
pst.close();
if (id == -1) {
throw new SQLException("Queue record not found.");
}
}
public void buildRecord(ResultSet rs) throws SQLException {
id = rs.getInt("queue_id");
entered = rs.getTimestamp("entered");
modified = rs.getTimestamp("modified");
enteredBy = rs.getInt("enteredby");
modifiedBy = rs.getInt("modifiedby");
enabled = rs.getBoolean("enabled");
scheduleOften = rs.getBoolean("schedule_often");
scheduleDaily = rs.getBoolean("schedule_daily");
scheduleWeekly = rs.getBoolean("schedule_weekly");
scheduleMonthly = rs.getBoolean("schedule_monthly");
scheduleMonday = rs.getBoolean("schedule_monday");
scheduleTuesday = rs.getBoolean("schedule_tuesday");
scheduleWednesday = rs.getBoolean("schedule_wednesday");
scheduleThursday = rs.getBoolean("schedule_thursday");
scheduleFriday = rs.getBoolean("schedule_friday");
scheduleSaturday = rs.getBoolean("schedule_saturday");
scheduleSunday = rs.getBoolean("schedule_sunday");
scheduleTime = rs.getTimestamp("schedule_time");
status = rs.getInt("status");
processed = rs.getTimestamp("processed");
}
public void insert(Connection db) throws SQLException {
boolean commit = false;
try {
commit = db.getAutoCommit();
if (commit) {
db.setAutoCommit(false);
}
//Determine the day-of-the-week preference to use
if (scheduleWeekly) {
determineDayOfTheWeek(db);
}
id = DatabaseUtils.getNextSeq(db, "email_updates_queue_queue_id_seq", id);
PreparedStatement pst = db.prepareStatement(
"INSERT INTO email_updates_queue " +
"(" + (id > -1 ? "queue_id, " : "") + "enteredby, modifiedby, enabled, " +
"schedule_often, schedule_daily, schedule_weekly, schedule_monthly, " +
"schedule_monday, schedule_tuesday, schedule_wednesday, schedule_thursday, schedule_friday, schedule_saturday, schedule_sunday, " +
"schedule_time, status, processed) " +
"VALUES (" + (id > -1 ? "?, " : "") + "?, ?, ?, " +
"?, ?, ?, ?, " +
"?, ?, ?, ?, ?, ?, ?, " +
"?, ?, ?) ");
int i = 0;
if (id > -1) {
pst.setInt(++i, id);
}
pst.setInt(++i, enteredBy);
pst.setInt(++i, modifiedBy);
pst.setBoolean(++i, enabled);
pst.setBoolean(++i, scheduleOften);
pst.setBoolean(++i, scheduleDaily);
pst.setBoolean(++i, scheduleWeekly);
pst.setBoolean(++i, scheduleMonthly);
pst.setBoolean(++i, scheduleMonday);
pst.setBoolean(++i, scheduleTuesday);
pst.setBoolean(++i, scheduleWednesday);
pst.setBoolean(++i, scheduleThursday);
pst.setBoolean(++i, scheduleFriday);
pst.setBoolean(++i, scheduleSaturday);
pst.setBoolean(++i, scheduleSunday);
pst.setTimestamp(++i, scheduleTime);
pst.setInt(++i, status);
pst.setTimestamp(++i, processed);
pst.execute();
pst.close();
id = DatabaseUtils.getCurrVal(db, "email_updates_queue_queue_id_seq", id);
//Determine the next schedule date for this queue
calculateNextRunDate(db);
if (commit) {
db.commit();
}
} catch (SQLException e) {
if (commit) {
db.rollback();
}
throw new SQLException(e.getMessage());
} finally {
db.setAutoCommit(true);
}
}
private void determineDayOfTheWeek(Connection db) throws SQLException {
//The UI currently does not allow user to specify the day-of-the-week for weekly schedule.
//Determine the day of the week based on today's date for now..
User user = UserUtils.loadUser(enteredBy);
Calendar today = Calendar.getInstance();
if (user.getTimeZone() != null) {
today = Calendar.getInstance(TimeZone.getTimeZone(user.getTimeZone()));
}
if (today.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
scheduleSunday = true;
} else if (today.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) {
scheduleMonday = true;
} else if (today.get(Calendar.DAY_OF_WEEK) == Calendar.TUESDAY) {
scheduleTuesday = true;
} else if (today.get(Calendar.DAY_OF_WEEK) == Calendar.WEDNESDAY) {
scheduleWednesday = true;
} else if (today.get(Calendar.DAY_OF_WEEK) == Calendar.THURSDAY) {
scheduleThursday = true;
} else if (today.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY) {
scheduleFriday = true;
} else if (today.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
scheduleSaturday = true;
}
}
public boolean calculateNextRunDate(Connection db) throws SQLException {
User user = UserUtils.loadUser(enteredBy);
Calendar next = Calendar.getInstance();
if (user.getTimeZone() != null) {
next = Calendar.getInstance(TimeZone.getTimeZone(user.getTimeZone()));
}
if (scheduleTime != null) {
next.setTime(scheduleTime);
}
if (scheduleOften) {
if (next.get(Calendar.HOUR_OF_DAY) < 8) {
next.set(Calendar.HOUR_OF_DAY, 8);
next.set(Calendar.MINUTE, 0);
} else if (next.get(Calendar.HOUR_OF_DAY) < 12) {
next.set(Calendar.HOUR_OF_DAY, 12);
next.set(Calendar.MINUTE, 0);
} else if (next.get(Calendar.HOUR_OF_DAY) < 16) {
next.set(Calendar.HOUR_OF_DAY, 16);
next.set(Calendar.MINUTE, 0);
} else if (next.get(Calendar.HOUR_OF_DAY) < 20) {
next.set(Calendar.HOUR_OF_DAY, 20);
next.set(Calendar.MINUTE, 0);
} else {
//next day
next.add(Calendar.DATE, 1);
next.set(Calendar.HOUR_OF_DAY, 8);
next.set(Calendar.MINUTE, 0);
}
} else if (scheduleDaily) {
next.add(Calendar.DATE, 1);
} else if (scheduleWeekly) {
next.add(Calendar.DATE, 7);
} else if (scheduleMonthly) {
next.add(Calendar.MONTH, 1);
}
// Set the next time this should run...
PreparedStatement pst = db.prepareStatement(
"UPDATE email_updates_queue " +
"SET status = ?, schedule_time = ? " +
"WHERE queue_id = ? ");
int i = 0;
pst.setInt(++i, STATUS_SCHEDULED);
pst.setTimestamp(++i, new Timestamp(next.getTimeInMillis()));
pst.setInt(++i, id);
pst.executeUpdate();
pst.close();
return true;
}
public boolean updateProcessedDate(Connection db, Timestamp processed) throws SQLException {
// Set the next time this should run...
PreparedStatement pst = db.prepareStatement(
"UPDATE email_updates_queue " +
"SET processed = ? " +
"WHERE queue_id = ? ");
int i = 0;
pst.setTimestamp(++i, processed);
pst.setInt(++i, id);
pst.executeUpdate();
pst.close();
return true;
}
public void setType(int type) {
if (type == TeamMember.EMAIL_OFTEN) {
scheduleOften = true;
} else if (type == TeamMember.EMAIL_DAILY) {
scheduleDaily = true;
} else if (type == TeamMember.EMAIL_WEEKLY) {
scheduleWeekly = true;
} else if (type == TeamMember.EMAIL_MONTHLY) {
scheduleMonthly = true;
}
if (type == TeamMember.EMAIL_OFTEN || type == TeamMember.EMAIL_DAILY) {
//Need to send on every day of the week
scheduleMonday = true;
scheduleTuesday = true;
scheduleWednesday = true;
scheduleThursday = true;
scheduleFriday = true;
scheduleSaturday = true;
scheduleSunday = true;
}
if (type == TeamMember.EMAIL_WEEKLY) {
//Need to send on today's day of week
Calendar now = Calendar.getInstance();
if (now.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) scheduleMonday = true;
if (now.get(Calendar.DAY_OF_WEEK) == Calendar.TUESDAY) scheduleTuesday = true;
if (now.get(Calendar.DAY_OF_WEEK) == Calendar.WEDNESDAY) scheduleWednesday = true;
if (now.get(Calendar.DAY_OF_WEEK) == Calendar.THURSDAY) scheduleThursday = true;
if (now.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY) scheduleFriday = true;
if (now.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) scheduleSaturday = true;
if (now.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) scheduleSunday = true;
}
if (type == TeamMember.EMAIL_MONTHLY) {
//TODO: What day of the week?
}
}
/**
* Returns whether the specified queue was just locked, false if it already
* locked
*
* @param queue
* @param db
* @return
* @throws SQLException
*/
public static boolean lockQueue(EmailUpdatesQueue queue, Connection db) throws SQLException {
PreparedStatement pst = db.prepareStatement(
"UPDATE email_updates_queue " +
"SET status = ? " +
"WHERE queue_id = ? " +
"AND status = ? ");
pst.setInt(1, EmailUpdatesQueue.STATUS_PROCESSING);
pst.setInt(2, queue.getId());
pst.setInt(3, EmailUpdatesQueue.STATUS_SCHEDULED);
int count = pst.executeUpdate();
pst.close();
return (count == 1);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Timestamp getEntered() {
return entered;
}
public void setEntered(Timestamp entered) {
this.entered = entered;
}
public Timestamp getModified() {
return modified;
}
public void setModified(Timestamp modified) {
this.modified = modified;
}
public int getEnteredBy() {
return enteredBy;
}
public void setEnteredBy(int enteredBy) {
this.enteredBy = enteredBy;
}
public int getModifiedBy() {
return modifiedBy;
}
public void setModifiedBy(int modifiedBy) {
this.modifiedBy = modifiedBy;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean getScheduleOften() {
return scheduleOften;
}
public void setScheduleOften(boolean scheduleOften) {
this.scheduleOften = scheduleOften;
}
public boolean getScheduleDaily() {
return scheduleDaily;
}
public void setScheduleDaily(boolean scheduleDaily) {
this.scheduleDaily = scheduleDaily;
}
public boolean getScheduleWeekly() {
return scheduleWeekly;
}
public void setScheduleWeekly(boolean scheduleWeekly) {
this.scheduleWeekly = scheduleWeekly;
}
public boolean getScheduleMonthly() {
return scheduleMonthly;
}
public void setScheduleMonthly(boolean scheduleMonthly) {
this.scheduleMonthly = scheduleMonthly;
}
public boolean getScheduleMonday() {
return scheduleMonday;
}
public void setScheduleMonday(boolean scheduleMonday) {
this.scheduleMonday = scheduleMonday;
}
public boolean getScheduleTuesday() {
return scheduleTuesday;
}
public void setScheduleTuesday(boolean scheduleTuesday) {
this.scheduleTuesday = scheduleTuesday;
}
public boolean getScheduleWednesday() {
return scheduleWednesday;
}
public void setScheduleWednesday(boolean scheduleWednesday) {
this.scheduleWednesday = scheduleWednesday;
}
public boolean getScheduleThursday() {
return scheduleThursday;
}
public void setScheduleThursday(boolean scheduleThursday) {
this.scheduleThursday = scheduleThursday;
}
public boolean getScheduleFriday() {
return scheduleFriday;
}
public void setScheduleFriday(boolean scheduleFriday) {
this.scheduleFriday = scheduleFriday;
}
public boolean getScheduleSaturday() {
return scheduleSaturday;
}
public void setScheduleSaturday(boolean scheduleSaturday) {
this.scheduleSaturday = scheduleSaturday;
}
public boolean getScheduleSunday() {
return scheduleSunday;
}
public void setScheduleSunday(boolean scheduleSunday) {
this.scheduleSunday = scheduleSunday;
}
public Timestamp getScheduleTime() {
return scheduleTime;
}
public void setScheduleTime(Timestamp scheduleTime) {
this.scheduleTime = scheduleTime;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public Timestamp getProcessed() {
return processed;
}
public void setProcessed(Timestamp processed) {
this.processed = processed;
}
}