Skip to content

Commit

Permalink
Merge pull request #45 from Elonso95/retrieve_multiple_assignment_sub…
Browse files Browse the repository at this point in the history
…missions

Added new function to call canvas service 'List submissions for multiple assignments' from the Submission API
  • Loading branch information
buckett committed Apr 22, 2022
2 parents dc43c54 + 703e166 commit dc13e5e
Show file tree
Hide file tree
Showing 6 changed files with 333 additions and 16 deletions.
29 changes: 21 additions & 8 deletions src/main/java/edu/ksu/canvas/impl/SubmissionImpl.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
package edu.ksu.canvas.impl;


import java.io.IOException;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Optional;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;

import edu.ksu.canvas.interfaces.SubmissionReader;
import edu.ksu.canvas.interfaces.SubmissionWriter;
import edu.ksu.canvas.model.Progress;
import edu.ksu.canvas.model.assignment.Submission;
import edu.ksu.canvas.net.Response;
import edu.ksu.canvas.net.RestClient;
import edu.ksu.canvas.oauth.OauthToken;
import edu.ksu.canvas.requestOptions.GetMultipleSubmissionsOptions;
import edu.ksu.canvas.requestOptions.GetSubmissionsOptions;
import edu.ksu.canvas.requestOptions.MultipleSubmissionsOptions;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Optional;

public class SubmissionImpl extends BaseImpl<Submission, SubmissionReader, SubmissionWriter> implements SubmissionReader, SubmissionWriter{
private static final Logger LOG = LoggerFactory.getLogger(SubmissionImpl.class);
Expand Down Expand Up @@ -62,6 +65,16 @@ public List<Submission> getSectionSubmissions(final GetSubmissionsOptions option
final String url = buildCanvasUrl(String.format("sections/%s/assignments/%d/submissions", options.getCanvasId(), options.getAssignmentId()), options.getOptionsMap());
return getListFromCanvas(url);
}

@Override
public List<Submission> getCourseSubmissionMultipleAssignments(final GetMultipleSubmissionsOptions options) throws IOException {
if(StringUtils.isBlank(options.getCanvasId())) {
throw new IllegalArgumentException("Course ID is required for this API call");
}
LOG.debug(String.format("Listing multiple assignment submissions for course %s", options.getCanvasId()));
final String url = buildCanvasUrl(String.format("courses/%s/students/submissions", options.getCanvasId()), options.getOptionsMap());
return getListFromCanvas(url);
}

@Override
public Optional<Submission> getSingleCourseSubmission(final GetSubmissionsOptions options) throws IOException {
Expand Down
16 changes: 13 additions & 3 deletions src/main/java/edu/ksu/canvas/interfaces/SubmissionReader.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package edu.ksu.canvas.interfaces;

import edu.ksu.canvas.model.assignment.Submission;
import edu.ksu.canvas.requestOptions.GetSubmissionsOptions;

import java.io.IOException;
import java.util.List;
import java.util.Optional;

import edu.ksu.canvas.model.assignment.Submission;
import edu.ksu.canvas.requestOptions.GetMultipleSubmissionsOptions;
import edu.ksu.canvas.requestOptions.GetSubmissionsOptions;

public interface SubmissionReader extends CanvasReader<Submission, SubmissionReader> {
/**
* Retrieve a list of assignment submissions from a course
Expand All @@ -25,6 +26,15 @@ public interface SubmissionReader extends CanvasReader<Submission, SubmissionRe
* @throws IOException When there is an error communicating with Canvas
*/
List<Submission> getSectionSubmissions(GetSubmissionsOptions options) throws IOException;

/**
* Retrieve a list of multiple assignment submissions from a course
*
* @param options Options class containing required and optional parameters for this API call
* @return List of assignment submissions in the course with the course ID
* @throws IOException When there is an error communicating with Canvas
*/
List<Submission> getCourseSubmissionMultipleAssignments(GetMultipleSubmissionsOptions options) throws IOException;

/**
* Retrieve a single assignment submission from a course
Expand Down
18 changes: 13 additions & 5 deletions src/main/java/edu/ksu/canvas/model/assignment/Submission.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,15 @@ public class Submission extends BaseCanvasModel implements Serializable {
private Instant postedAt;
private String url;
private Integer userId;
private Integer gradeId;
private Integer graderId;
private User user;
private Boolean late;
private Boolean assigmentVisible;
private Boolean excused;
private Boolean missing;
private String workflowState;
private List<Submission> submissionHistory;
private Instant gradedAt;

public Integer getId() {
return id;
Expand Down Expand Up @@ -179,12 +180,12 @@ public void setUserId(Integer userId) {
this.userId = userId;
}

public Integer getGradeId() {
return gradeId;
public Integer getGraderId() {
return graderId;
}

public void setGradeId(Integer gradeId) {
this.gradeId = gradeId;
public void setGraderId(Integer graderId) {
this.graderId = graderId;
}

public User getUser() {
Expand Down Expand Up @@ -243,4 +244,11 @@ public void setSubmissionHistory(List<Submission> submissionHistory) {
this.submissionHistory = submissionHistory;
}

public Instant getGradedAt() {
return gradedAt;
}

public void setGradedAt(Instant gradedAt) {
this.gradedAt = gradedAt;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
package edu.ksu.canvas.requestOptions;

import java.util.Date;
import java.util.List;

import edu.ksu.canvas.requestOptions.BaseOptions;
import edu.ksu.canvas.requestOptions.GetSubmissionsOptions.Include;

public class GetMultipleSubmissionsOptions extends BaseOptions {

private String canvasId;

/**
* Construct options class with required parameters to retrieve a list of multiple Submissions from courses or sections
* @param canvasId The Course or Section ID, depending on which API is being targeted.
*/
public GetMultipleSubmissionsOptions(final String canvasId) {
this.canvasId = canvasId;
}


/**
* Filter the list of submissions by the given student ids..
* @param ids List of ids to filter submissions by
* @return This object to allow adding more options
*/
public GetMultipleSubmissionsOptions studentIds(final List<String> ids) {
optionsMap.put("student_ids[]", ids);
return this;
}

/**
* Optionally include more information with the returned assignment Submission objects.
* @param includes List of optional includes
* @return This object to allow adding more options
*/
public GetMultipleSubmissionsOptions includes(final List<Include> includes) {
addEnumList("include[]", includes);
return this;
}

/**
* List of assignments to return submissions for.
* If none are given, submissions for all assignments are returned.
* @param ids List of ids to filter submissions by
* @return This object to allow adding more options
*/
public GetMultipleSubmissionsOptions assignmentIds(final List<String> ids) {
optionsMap.put("assignment_ids[]", ids);
return this;
}

/**
* When set to true, response will be grouped by student groups.
* Only valid for Submission lists, not individual submission queries.
* @param grouped Whether to group submissions by student group
* @return This object to allow adding more options
*/
public GetMultipleSubmissionsOptions grouped(Boolean grouped) {
addSingleItem("grouped", Boolean.toString(grouped));
return this;
}

/**
* If this argument is set to true, the response will only include submissions for assignments
* that have the post_to_sis flag set to true and user enrollments that were added through sis.
* @param postToSis Whether to include submissions that have the flag active
* @return This object to allow adding more options
*/
public GetMultipleSubmissionsOptions postToSis(Boolean postToSis) {
addSingleItem("post_to_sis", Boolean.toString(postToSis));
return this;
}

/**
* If this argument is set, the response will only include submissions that were submitted
* after the specified date_time.
* This will exclude submissions that do not have a submitted_at which will exclude unsubmitted submissions
* @param submittedSince date to get submissions after
* @return This object to allow adding more options
*/
public GetMultipleSubmissionsOptions submittedSince(Date submittedSince) {
addSingleItem("submitted_since", submittedSince.toString());
return this;
}

/**
* If this argument is set, the response will only include submissions that were graded
* after the specified date_time.
* This will exclude submissions that have not been graded.
* @param gradedSince date to get submissions graded after
* @return This object to allow adding more options
*/
public GetMultipleSubmissionsOptions gradedSince(Date gradedSince) {
addSingleItem("graded_since", gradedSince.toString());
return this;
}

/**
* The id of the grading period in which submissions are being requested
* (Requires grading periods to exist on the account)
* @param gradingPeriodId the grading period for the submissions
* @return This object to allow adding more options
*/
public GetMultipleSubmissionsOptions gradingPeriodId(Integer gradingPeriodId) {
addSingleItem("grading_period_id", gradingPeriodId.toString());
return this;
}

/**
*
* The current status of the submission
* @param workflowState the status to get the submissions
* @return This object to allow adding more options
*/
public GetMultipleSubmissionsOptions workflowState(String workflowState) {
addSingleItem("workflow_state", workflowState);
return this;
}

/**
*
* The current state of the enrollments.
* If omitted will include all enrollments that are not deleted.
* @param enrollmentState the state of the enrollment to get submissions
* @return This object to allow adding more options
*/
public GetMultipleSubmissionsOptions enrollmentState(String enrollmentState) {
addSingleItem("enrollment_state", enrollmentState);
return this;
}

/**
* If omitted it is set to true. When set to false it will ignore the effective state of the student enrollments
* and use the workflow_state for the enrollments.
* The argument is ignored unless enrollment_state argument is also passed.
* @param stateBasedOnDate the state of the enrollment to get submissions
* @return This object to allow adding more options
*/
public GetMultipleSubmissionsOptions stateBasedOnDate(Boolean stateBasedOnDate) {
addSingleItem("state_based_on_date", stateBasedOnDate.toString());
return this;
}

/**
* The order submissions will be returned in.
* Defaults to “id”. Doesn't affect results for “grouped” mode.
* @param order the order indicated
* @return This object to allow adding more options
*/
public GetMultipleSubmissionsOptions order(String order) {
addSingleItem("order", order);
return this;
}

/**
* Determines whether ordered results are returned in ascending or descending order.
* Defaults to “ascending”.
* Doesn't affect results for “grouped” mode.
* @param orderDirection "ascending" or "descending"
* @return This object to allow adding more options
*/
public GetMultipleSubmissionsOptions orderDirection(String orderDirection) {
addSingleItem("order_direction", orderDirection);
return this;
}


public String getCanvasId() {
return canvasId;
}


public void setCanvasId(String canvasId) {
this.canvasId = canvasId;
}
}
43 changes: 43 additions & 0 deletions src/test/java/edu/ksu/canvas/tests/submission/SubmissionUTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package edu.ksu.canvas.tests.submission;

import java.util.List;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

import edu.ksu.canvas.CanvasTestBase;
import edu.ksu.canvas.impl.SubmissionImpl;
import edu.ksu.canvas.interfaces.SubmissionReader;
import edu.ksu.canvas.model.assignment.Submission;
import edu.ksu.canvas.net.FakeRestClient;
import edu.ksu.canvas.net.Response;
import edu.ksu.canvas.requestOptions.GetMultipleSubmissionsOptions;

public class SubmissionUTest extends CanvasTestBase {
@Autowired
private FakeRestClient fakeRestClient;
private SubmissionReader submissionReader;

@Before
public void setupData() {
submissionReader = new SubmissionImpl(baseUrl, apiVersion, SOME_OAUTH_TOKEN, fakeRestClient, SOME_CONNECT_TIMEOUT,
SOME_READ_TIMEOUT, DEFAULT_PAGINATION_PAGE_SIZE, false);
}

@Test
public void testGetCourseSubmissionMultipleAssignments() throws Exception {
String someCourseId = "123456";
Response notErroredResponse = new Response();
notErroredResponse.setErrorHappened(false);
notErroredResponse.setResponseCode(200);
String url = baseUrl + "/api/v1/courses/" + someCourseId + "/students/submissions";
fakeRestClient.addSuccessResponse(url, "SampleJson/submission/SubmissionList.json");

List<Submission> submissions = submissionReader.getCourseSubmissionMultipleAssignments(new GetMultipleSubmissionsOptions(someCourseId));
Assert.assertEquals(2, submissions.size());
Assert.assertTrue(submissions.stream().map(Submission::getGrade).filter("A-"::equals).findFirst().isPresent());
Assert.assertTrue(submissions.stream().map(Submission::getGrade).filter("B-"::equals).findFirst().isPresent());
}
}
Loading

0 comments on commit dc13e5e

Please sign in to comment.