Skip to content
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ rebel.xml
rebel-remote.xml
*.iml
*.idea
release.properties
release.properties
8 changes: 7 additions & 1 deletion src/main/java/edu/ksu/canvas/CanvasApiFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import edu.ksu.canvas.impl.*;
import edu.ksu.canvas.interfaces.*;
import edu.ksu.canvas.net.RestClient;
import edu.ksu.canvas.net.RefreshingRestClient;
import edu.ksu.canvas.net.RestClient;
import edu.ksu.canvas.oauth.OauthToken;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -188,6 +188,9 @@ private void setupClassMap() {
readerMap.put(FeatureFlagReader.class, FeatureFlagImpl.class);
readerMap.put(RubricReader.class, RubricImpl.class);

readerMap.put(DiscussionTopicReader.class, DiscussionTopicImpl.class);
readerMap.put(AnnouncementReader.class, AnnouncementImpl.class);

writerMap.put(AccountWriter.class, AccountImpl.class);
writerMap.put(AssignmentOverrideWriter.class, AssignmentOverrideImpl.class);
writerMap.put(AdminWriter.class, AdminImpl.class);
Expand Down Expand Up @@ -220,5 +223,8 @@ private void setupClassMap() {
writerMap.put(CommunicationChannelWriter.class, CommunicationChannelImpl.class);
writerMap.put(FeatureFlagWriter.class, FeatureFlagImpl.class);
writerMap.put(RubricWriter.class, RubricImpl.class);

writerMap.put(DiscussionTopicWriter.class, DiscussionTopicImpl.class);
writerMap.put(AnnouncementWriter.class, AnnouncementImpl.class);
}
}
41 changes: 41 additions & 0 deletions src/main/java/edu/ksu/canvas/impl/AnnouncementImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package edu.ksu.canvas.impl;

import com.google.common.reflect.TypeToken;
import edu.ksu.canvas.interfaces.AnnouncementReader;
import edu.ksu.canvas.interfaces.AnnouncementWriter;
import edu.ksu.canvas.model.announcement.Announcement;
import edu.ksu.canvas.net.RestClient;
import edu.ksu.canvas.oauth.OauthToken;
import edu.ksu.canvas.requestOptions.ListCourseAnnouncementsOptions;

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

/**
* An Announcement is really just a DiscussionTopic, but Canvas has
* a separate API call for fetching the ones posted under the
* Announcements tab rather than the Discussions tab. That's handled here.
*/
public class AnnouncementImpl extends BaseImpl<Announcement, AnnouncementReader, AnnouncementWriter> implements AnnouncementReader, AnnouncementWriter {

public AnnouncementImpl(String canvasBaseUrl, Integer apiVersion, OauthToken oauthToken, RestClient restClient, int connectTimeout, int readTimeout, Integer paginationPageSize, Boolean serializeNulls) {
super(canvasBaseUrl, apiVersion, oauthToken, restClient, connectTimeout, readTimeout, paginationPageSize, serializeNulls);
}

@Override
public List<Announcement> listCourseAnnouncements(ListCourseAnnouncementsOptions options) throws IOException {
String url = buildCanvasUrl("/announcements", options.getOptionsMap());
return getListFromCanvas(url);
}

@Override
protected Type listType() {
return new TypeToken<List<Announcement>>(){}.getType();
}

@Override
protected Class<Announcement> objectType() {
return Announcement.class;
}
}
77 changes: 77 additions & 0 deletions src/main/java/edu/ksu/canvas/impl/DiscussionTopicImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package edu.ksu.canvas.impl;

import com.google.common.reflect.TypeToken;
import edu.ksu.canvas.interfaces.DiscussionTopicReader;
import edu.ksu.canvas.interfaces.DiscussionTopicWriter;
import edu.ksu.canvas.model.discussion.DiscussionTopic;
import edu.ksu.canvas.net.Response;
import edu.ksu.canvas.net.RestClient;
import edu.ksu.canvas.oauth.OauthToken;
import edu.ksu.canvas.requestOptions.GetSingleDiscussionTopicOptions;
import edu.ksu.canvas.requestOptions.ListCourseDiscussionTopicsOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.*;

public class DiscussionTopicImpl extends BaseImpl<DiscussionTopic, DiscussionTopicReader, DiscussionTopicWriter> implements DiscussionTopicReader, DiscussionTopicWriter {
private static final Logger LOG = LoggerFactory.getLogger(DiscussionTopicImpl.class);

public DiscussionTopicImpl(String canvasBaseURL, Integer apiVersion, OauthToken oauthToken, RestClient restClient,
int connectTimeout, int readTimeout, Integer paginationPageSize, Boolean serializeNulls) {
super(canvasBaseURL, apiVersion, oauthToken, restClient, connectTimeout, readTimeout, paginationPageSize, serializeNulls);
}

@Override
public List<DiscussionTopic> listCourseDiscussionTopics(ListCourseDiscussionTopicsOptions options) throws IOException {
String url = buildCanvasUrl("courses/" + options.getCourseId() + "/discussion_topics", options.getOptionsMap());
return getListFromCanvas(url);
}

@Override
public Optional<DiscussionTopic> getSingleDiscussionTopic(GetSingleDiscussionTopicOptions options) throws IOException {
String url = buildCanvasUrl("courses/" + options.getCourseId() + "/discussion_topics/" + options.getDiscussionTopicId(), options.getOptionsMap());
Response response = canvasMessenger.getSingleResponseFromCanvas(oauthToken, url);
return responseParser.parseToObject(DiscussionTopic.class, response);
}

@Override
public Optional<DiscussionTopic> createDiscussionTopic(String courseId, DiscussionTopic discussionTopic, boolean isAnnouncement) throws IOException {
String url = buildCanvasUrl("courses/" + courseId + "/discussion_topics", Collections.emptyMap());
Response response = canvasMessenger.sendJsonPostToCanvas(oauthToken, url, discussionTopic.toJsonObject(serializeNulls));
return responseParser.parseToObject(DiscussionTopic.class, response);
}

@Override
public Optional<DiscussionTopic> deleteDiscussionTopic(String courseId, Long discussionTopicId) throws IOException {
Map<String, List<String>> postParams = new HashMap<>();
postParams.put("event", Collections.singletonList("delete"));
String createdURL = buildCanvasUrl("courses/" + courseId + "/discussion_topics/" + discussionTopicId, Collections.emptyMap());
Response response = canvasMessenger.deleteFromCanvas(oauthToken, createdURL, postParams);
LOG.debug("response {}", response.toString());
if (response.getErrorHappened() || response.getResponseCode() != 200) {
LOG.debug("Failed to delete discussion topic, error message: " + response);
return Optional.empty();
}
return responseParser.parseToObject(DiscussionTopic.class, response);
}

@Override
public Optional<DiscussionTopic> editDiscussionTopic(String courseId, DiscussionTopic discussionTopic) throws IOException {
String url = buildCanvasUrl("courses/" + courseId + "/discussion_topics", Collections.emptyMap());
Response response = canvasMessenger.sendJsonPutToCanvas(oauthToken, url, discussionTopic.toJsonObject(serializeNulls));
return responseParser.parseToObject(DiscussionTopic.class, response);
}

@Override
protected Type listType() {
return new TypeToken<List<DiscussionTopic>>(){}.getType();
}

@Override
protected Class<DiscussionTopic> objectType() {
return DiscussionTopic.class;
}
}
19 changes: 19 additions & 0 deletions src/main/java/edu/ksu/canvas/interfaces/AnnouncementReader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package edu.ksu.canvas.interfaces;

import edu.ksu.canvas.model.announcement.Announcement;
import edu.ksu.canvas.requestOptions.ListCourseAnnouncementsOptions;

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

/**
* Handles calls to the Announcement API endpoint. Functions
* almost identically to fetching lists of DiscussionTopics, since
* Announcements ARE DiscussionTopics, just hidden behind a different
* API call.
*/
public interface AnnouncementReader extends CanvasReader<Announcement, AnnouncementReader> {

List<Announcement> listCourseAnnouncements(ListCourseAnnouncementsOptions options) throws IOException;

}
11 changes: 11 additions & 0 deletions src/main/java/edu/ksu/canvas/interfaces/AnnouncementWriter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package edu.ksu.canvas.interfaces;

import edu.ksu.canvas.model.announcement.Announcement;

/**
* There are no write calls for announcements. That's all handled by
* the DiscussionTopic API calls. This is only here to fit the structure of
* the library.
*/
public interface AnnouncementWriter extends CanvasWriter<Announcement, AnnouncementWriter> {
}
29 changes: 29 additions & 0 deletions src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicReader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package edu.ksu.canvas.interfaces;

import edu.ksu.canvas.model.discussion.DiscussionTopic;
import edu.ksu.canvas.requestOptions.GetSingleDiscussionTopicOptions;
import edu.ksu.canvas.requestOptions.ListCourseDiscussionTopicsOptions;

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

public interface DiscussionTopicReader extends CanvasReader<DiscussionTopic, DiscussionTopicReader> {

/**
* Retireve a specific Discussion Topic from Canvas by its Canvas ID number
* @param options Options class containing required and optional parameters for this API call
* @return The DiscussionTopic returned by Canvas or an empty Optional
* @throws IOException When there is an error communicating with Canvas
*/
Optional<DiscussionTopic> getSingleDiscussionTopic(GetSingleDiscussionTopicOptions options) throws IOException;

/**
* Retrieve a list of Discussion Topics associated with a course
* @param options Options class containing required and optional parameters for this API call
* @return List of DiscussionTopics in the requested course
* @throws IOException When there is an error communicating with Canvas
*/
List<DiscussionTopic> listCourseDiscussionTopics(ListCourseDiscussionTopicsOptions options) throws IOException;

}
38 changes: 38 additions & 0 deletions src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicWriter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package edu.ksu.canvas.interfaces;

import edu.ksu.canvas.model.discussion.DiscussionTopic;

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

public interface DiscussionTopicWriter extends CanvasWriter<DiscussionTopic, DiscussionTopicWriter> {

/**
* Create a Discussion Topic in Canvas. The API docs interestingly do not list any fields as required.
* @param courseId the ID of the course to create the discussion topic in
* @param discussionTopic DiscussionTopic object to create
* @param isAnnouncement Whether the topic is an Announcement
* @return The created DiscussionTopic object
* @throws IOException When there is an error communicating with Canvas
*/
Optional<DiscussionTopic> createDiscussionTopic(String courseId, DiscussionTopic discussionTopic, boolean isAnnouncement) throws IOException;

/**
* Delete a specified Discussion Topic from Canvas
* @param courseId Course ID of the course to delete the Discussion Topic from
* @param discussionTopicId Canvas ID of the Discussion Topic to delete
* @return The deleted DiscussionTopic object as returned by the Canvas API
* @throws IOException When there is an error communicating with Canvas
*/
Optional<DiscussionTopic> deleteDiscussionTopic(String courseId, Long discussionTopicId) throws IOException;

/**
* Modify a Discussion Topic object on Canvas
* @param courseId Course ID of the course to modify the Discussion Topic within
* @param discussionTopic The DiscussionTopic object whose parameters should be written to Canvas
* @return The modified DiscussionTopic returned by the Canvas API
* @throws IOException When there is an error communicating with Canvas
*/
Optional<DiscussionTopic> editDiscussionTopic(String courseId, DiscussionTopic discussionTopic) throws IOException;

}
15 changes: 15 additions & 0 deletions src/main/java/edu/ksu/canvas/model/announcement/Announcement.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package edu.ksu.canvas.model.announcement;

import edu.ksu.canvas.model.discussion.DiscussionTopic;

import java.io.Serializable;

/**
* The Announcement object type is just a DiscussionTopic object
* that gets returned from a different API call.
*/
public class Announcement extends DiscussionTopic implements Serializable {

private static final long serialVersionUID = 1L;

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import java.util.List;

/**
* Class to represent Canvas assigmnents.
* Class to represent Canvas assignments.
* See <a href="https://canvas.instructure.com/doc/api/assignments.html#Assignment">Canvas assignment</a> documentation.
*/
@CanvasObject(postKey = "assignment")
Expand Down
Loading