All Downloads are FREE. Search and download functionalities are using the official Maven repository.

edu.pdx.cs.joy.grader.ZipFileSubmissionsProcessor Maven / Gradle / Ivy

There is a newer version: 1.2.0
Show newest version
package edu.pdx.cs.joy.grader;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.io.ByteStreams;
import edu.pdx.cs.joy.grader.gradebook.Assignment;
import edu.pdx.cs.joy.grader.gradebook.Grade;
import edu.pdx.cs.joy.grader.gradebook.GradeBook;
import edu.pdx.cs.joy.grader.gradebook.Student;
import jakarta.mail.Address;
import jakarta.mail.Message;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.InternetAddress;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Stream;

public abstract class ZipFileSubmissionsProcessor extends StudentEmailAttachmentProcessor {
  public ZipFileSubmissionsProcessor(File directory, GradeBook gradeBook) {
    super(directory, gradeBook);
  }

  @Override
  public Iterable getSupportedContentTypes() {
    return List.of("application/zip", "application/x-zip-compressed", "application/x-gzip");
  }

  @Override
  public void processAttachment(Message message, String fileName, InputStream inputStream, String contentType) {
    String studentId;
    try {
      studentId = getIdOfStudentInGradeBookWhoSent(message);

    } catch (SubmissionException ex) {
      logException("While getting student id", ex);
      return;
    }

    try {
      File file = getLocationToWriteFile(fileName, studentId);
      info("Writing \"" + fileName + "\" to " + file);

      ByteStreams.copy(inputStream, new FileOutputStream(file));
    } catch (IOException ex) {
      logException("While writing \"" + fileName + "\" to \"" + directory + "\"", ex);
    }

    try {
      noteSubmissionInGradeBook(message);

    } catch (SubmissionException ex) {
      logException("While noting submission from \"" + fileName + "\"", ex);
    }
  }

  private String getIdOfStudentInGradeBookWhoSent(Message message) throws SubmissionException {
    Student student = getStudentFromGradeBook(message);
    return student.getId();
  }

  private void noteSubmissionInGradeBook(Message message) throws SubmissionException {
    Student student = getStudentFromGradeBook(message);
    Assignment project = getKoansProjectFromGradeBook();
    String note = getSubmissionNote(message);

    Grade grade = student.getGrade(project);
    if (grade == null) {
      grade = new Grade(project, Grade.NO_GRADE);
      student.setGrade(project.getName(), grade);
    }
    grade.addNote(note);
    grade.noteSubmission(getSentDate(message));
  }

  private String getSubmissionNote(Message message) throws SubmissionException {
    String senderName = getSenderName(message);
    LocalDateTime sentDate = getSentDate(message);

    return getSubmissionNote(senderName, sentDate);
  }

  private LocalDateTime getSentDate(Message message) throws SubmissionException {
    Date sentDate;
    try {
      sentDate = message.getSentDate();
    } catch (MessagingException e) {
      throw new SubmissionException("While getting the sent date", e);
    }
    return LocalDateTime.ofInstant(sentDate.toInstant(), ZoneId.systemDefault());
  }

  @VisibleForTesting
  static String getSubmissionNote(String senderName, LocalDateTime submissionTime) {
    return "Submitted by " + senderName + " on " + Submit.ManifestAttributes.formatSubmissionTime(submissionTime);
  }

  private Assignment getKoansProjectFromGradeBook() throws SubmissionException {
    Assignment assignment = gradeBook.getAssignment(getAssignmentName());
    if (assignment == null) {
      throw new SubmissionException("Could not find \"koans\" assignment in grade book");
    }
    return assignment;
  }

  protected abstract String getAssignmentName();

  private Student getStudentFromGradeBook(Message message) throws SubmissionException {
    String senderName = getSenderName(message);
    Optional student = getStudentWithName(senderName);
    if (student.isPresent()) {
      return student.get();
    }

    String senderAddress = getSenderEmailAddress(message);
    student = getStudentWithEmailAddress(senderAddress);
    return student.orElseThrow(() -> {
      String m = "Couldn't find student named \"" + senderName + "\" with email address \"" +
        senderAddress + "\" in gradebook";
      return new SubmissionException(m);
    });
  }

  private Optional getStudentWithEmailAddress(String senderAddress) {
    return getStudentsInGradeBook().filter(doesStudentHaveEmailAddress(senderAddress)).findAny();
  }

  private Predicate doesStudentHaveEmailAddress(String address) {
    return student -> student.getEmail().equals(address);
  }

  private String getSenderEmailAddress(Message message) throws SubmissionException {
    Address from = getSender(message);

    if (from instanceof InternetAddress) {
      return getEmailAddress((InternetAddress) from);
    } else {
      return from.toString();
    }
  }

  private Optional getStudentWithName(String studentName) {
    return getStudentsInGradeBook().filter(doesStudentHaveName(studentName)).findAny();
  }

  private Stream getStudentsInGradeBook() {
    return gradeBook.studentsStream();
  }

  private Predicate doesStudentHaveName(String studentName) {
    return student -> getFullName(student).equals(studentName) || getNickName(student).equals(studentName);
  }

  private String getNickName(Student student) {
    return student.getNickName() + " " + student.getLastName();
  }

  private String getFullName(Student student) {
    return student.getFirstName() + " " + student.getLastName();
  }

  private File getLocationToWriteFile(String fileName, String studentId) throws IOException {
    File dir = new File(directory, getAssignmentName());
    if (!dir.exists() && !dir.mkdirs()) {
      throw new IOException("Could not create directory \"" + dir + "\"");
    }
    return new File(dir, appendFileSuffixToStudentId(fileName, studentId));
  }

  private String appendFileSuffixToStudentId(String fileName, String studentId) {
    return studentId + fileName.substring(fileName.lastIndexOf('.'));
  }

  private String getSenderName(Message message) throws SubmissionException {
    Address from = getSender(message);

    if (from instanceof InternetAddress) {
      return getStudentName((InternetAddress) from);
    } else {
      return from.toString();
    }
  }

  private Address getSender(Message message) throws SubmissionException {
    Address from;
    try {
      from = message.getFrom()[0];

    } catch (MessagingException ex) {
      throw new SubmissionException("Could not get from address from " + message, ex);
    }
    return from;
  }

  private String getStudentName(InternetAddress from) {
    if (from.getPersonal() != null) {
      return from.getPersonal();

    } else {
      return getEmailAddress(from);
    }
  }

  private String getEmailAddress(InternetAddress from) {
    return from.getAddress();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy