Newer
Older
marking / src / main / java / ui / BatchMailer.java
package ui;

import dao.MarkingProperties;
import dao.ResultDAO;
import jakarta.mail.AuthenticationFailedException;
import java.net.ConnectException;
import java.util.Collection;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import javax.swing.JOptionPane;
import model.Student;
import org.slf4j.LoggerFactory;
import report.FeedbackReportGenerator;
import report.SendReport;
import static report.TimeStamp.getTimeStamp;

/**
 *
 * @author Mark George <mark.george@otago.ac.nz>
 */
public final class BatchMailer extends javax.swing.JDialog {

	private static final org.slf4j.Logger logger = LoggerFactory.getLogger(BatchMailer.class);

	private Boolean stopped = false;

	/**
	 * Creates new form BatchMailer
	 */
	public BatchMailer(java.awt.Window parent, boolean modal) {
		super(parent);
		this.setModal(modal);
		initComponents();
		addMessage("FROM: " + MarkingProperties.markerEmail());
		addMessage("CC: " + MarkingProperties.ccEmail());
		addMessage("");
	}

	/**
	 * This method is called from within the constructor to initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is always
	 * regenerated by the Form Editor.
	 */
	@SuppressWarnings("unchecked")
   // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
   private void initComponents() {

      jScrollPane1 = new javax.swing.JScrollPane();
      txtMessages = new javax.swing.JTextArea();
      btnClose = new javax.swing.JButton();
      btnStop = new javax.swing.JButton();
      btnStart = new javax.swing.JButton();
      btnReports = new javax.swing.JButton();

      setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);

      jScrollPane1.setName("jScrollPane1"); // NOI18N

      txtMessages.setColumns(20);
      txtMessages.setRows(5);
      txtMessages.setName("txtMessages"); // NOI18N
      jScrollPane1.setViewportView(txtMessages);

      btnClose.setText("Close");
      btnClose.setName("btnClose"); // NOI18N
      btnClose.addActionListener(new java.awt.event.ActionListener() {
         public void actionPerformed(java.awt.event.ActionEvent evt) {
            btnCloseActionPerformed(evt);
         }
      });

      btnStop.setText("Cancel Sending");
      btnStop.setName("btnStop"); // NOI18N
      btnStop.addActionListener(new java.awt.event.ActionListener() {
         public void actionPerformed(java.awt.event.ActionEvent evt) {
            btnStopActionPerformed(evt);
         }
      });

      btnStart.setText("Start Sending");
      btnStart.setName("btnStart"); // NOI18N
      btnStart.addActionListener(new java.awt.event.ActionListener() {
         public void actionPerformed(java.awt.event.ActionEvent evt) {
            btnStartActionPerformed(evt);
         }
      });

      btnReports.setText("Generate Reports Only ");
      btnReports.setName("btnReports"); // NOI18N
      btnReports.addActionListener(new java.awt.event.ActionListener() {
         public void actionPerformed(java.awt.event.ActionEvent evt) {
            btnReportsActionPerformed(evt);
         }
      });

      javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
      getContentPane().setLayout(layout);
      layout.setHorizontalGroup(
         layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
         .addGroup(layout.createSequentialGroup()
            .addContainerGap()
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
               .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 588, Short.MAX_VALUE)
               .addGroup(layout.createSequentialGroup()
                  .addComponent(btnStart)
                  .addGap(18, 18, 18)
                  .addComponent(btnStop)
                  .addGap(18, 18, 18)
                  .addComponent(btnReports)
                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                  .addComponent(btnClose, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE)))
            .addContainerGap())
      );
      layout.setVerticalGroup(
         layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
         .addGroup(layout.createSequentialGroup()
            .addContainerGap()
            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 545, Short.MAX_VALUE)
            .addGap(18, 18, 18)
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
               .addComponent(btnClose)
               .addComponent(btnStop)
               .addComponent(btnStart)
               .addComponent(btnReports))
            .addContainerGap())
      );

      pack();
   }// </editor-fold>//GEN-END:initComponents

   private void btnStopActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnStopActionPerformed
		int result = JOptionPane.showConfirmDialog(this, "Stop sending emails?", "Stop Sending?", JOptionPane.YES_NO_OPTION);

		// did the user click the yes button?
		if (result == JOptionPane.YES_OPTION) {
			this.stopped = true;
			addMessage("Stopped.  Messages that are in the process of being retried will continue to be retried.");
		}
   }//GEN-LAST:event_btnStopActionPerformed

	public void addMessage(String message) {
		txtMessages.append(message + "\n");
	}

   private void btnStartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnStartActionPerformed

		CompletableFuture.runAsync(() -> {

			Collection<Student> students = new ResultDAO().getStudents();

			for (Student student : students) {

				if (stopped) {
					break;
				}

				if (!student.getSendFeedback() || student.getEmailSent()) {
					continue;
				}

				String title = MarkingProperties.reportTitle();
				String footer = MarkingProperties.reportFooter();

				new FeedbackReportGenerator(new ResultDAO().getResult(student.getId()), MarkingProperties.reportPath(), MarkingProperties.attachmentFilePrefix(), title, footer).generate(student);

				String report = MarkingProperties.reportPath() + "/" + MarkingProperties.attachmentFilePrefix() + "-" + student.getId() + ".pdf";

				if (MarkingProperties.isEmailEnabled()) {

					try {
						new SendReport(BatchMailer.this).sendReport(student, report, true);
					} catch (AuthenticationFailedException ex) {
						addMessage("Authentication failed.  Click 'Start Sending' to try again.\n");
						return;
					} catch (ConnectException ex) {
						addMessage("Could not connect to SMTP server!\n");
						return;
					}

					try {
						int delay = MarkingProperties.emailDelay();
						TimeUnit.SECONDS.sleep(delay);  // delay to minimise triggering rate limiting
					} catch (InterruptedException e) {
						logger.error(e.getLocalizedMessage(), e);
					}
				}
			}

			addMessage("");
			addMessage(getTimeStamp() + " - Done\n");
		});
   }//GEN-LAST:event_btnStartActionPerformed

   private void btnCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCloseActionPerformed
		dispose();
   }//GEN-LAST:event_btnCloseActionPerformed

   private void btnReportsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnReportsActionPerformed
		CompletableFuture.runAsync(() -> {

			Collection<Student> students = new ResultDAO().getStudents();

			for (Student student : students) {

				if (stopped) {
					break;
				}

				String title = MarkingProperties.reportTitle();
				String footer = MarkingProperties.reportFooter();

				addMessage("Generating report for " + student.getSubmissionId());
				
				new FeedbackReportGenerator(new ResultDAO().getResult(student.getId()), MarkingProperties.reportPath(), MarkingProperties.attachmentFilePrefix(), title, footer).generate(student);
			}

			addMessage("");
			addMessage(getTimeStamp() + " - Done\n");

		});
   }//GEN-LAST:event_btnReportsActionPerformed

   // Variables declaration - do not modify//GEN-BEGIN:variables
   private javax.swing.JButton btnClose;
   private javax.swing.JButton btnReports;
   private javax.swing.JButton btnStart;
   private javax.swing.JButton btnStop;
   private javax.swing.JScrollPane jScrollPane1;
   private javax.swing.JTextArea txtMessages;
   // End of variables declaration//GEN-END:variables
}