From f274ef333aede3a2a9e1a841eb7fd246c471ea93 Mon Sep 17 00:00:00 2001 From: Garrett Date: Wed, 25 Jan 2023 15:02:34 -0800 Subject: [PATCH 1/8] Minimal working implementation, tested for fetching a list of course announcements --- .gitignore | 3 +- .../java/edu/ksu/canvas/CanvasApiFactory.java | 8 +- .../edu/ksu/canvas/impl/AnnouncementImpl.java | 36 ++ .../ksu/canvas/impl/DiscussionTopicImpl.java | 65 ++++ .../canvas/interfaces/AnnouncementReader.java | 13 + .../canvas/interfaces/AnnouncementWriter.java | 13 + .../interfaces/DiscussionTopicReader.java | 17 + .../interfaces/DiscussionTopicWriter.java | 16 + .../model/announcement/Announcement.java | 11 + .../canvas/model/assignment/Assignment.java | 2 +- .../model/discussion/DiscussionTopic.java | 362 ++++++++++++++++++ .../discussion/DiscussionTopicPermission.java | 13 + .../GetSingleDiscussionTopicOptions.java | 38 ++ .../ListCourseAnnouncementsOptions.java | 61 +++ .../ListCourseDiscussionTopicsOptions.java | 80 ++++ .../edu/ksu/canvas/BaseCanvasModelUTest.java | 4 +- 16 files changed, 737 insertions(+), 5 deletions(-) create mode 100644 src/main/java/edu/ksu/canvas/impl/AnnouncementImpl.java create mode 100644 src/main/java/edu/ksu/canvas/impl/DiscussionTopicImpl.java create mode 100644 src/main/java/edu/ksu/canvas/interfaces/AnnouncementReader.java create mode 100644 src/main/java/edu/ksu/canvas/interfaces/AnnouncementWriter.java create mode 100644 src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicReader.java create mode 100644 src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicWriter.java create mode 100644 src/main/java/edu/ksu/canvas/model/announcement/Announcement.java create mode 100644 src/main/java/edu/ksu/canvas/model/discussion/DiscussionTopic.java create mode 100644 src/main/java/edu/ksu/canvas/model/discussion/DiscussionTopicPermission.java create mode 100644 src/main/java/edu/ksu/canvas/requestOptions/GetSingleDiscussionTopicOptions.java create mode 100644 src/main/java/edu/ksu/canvas/requestOptions/ListCourseAnnouncementsOptions.java create mode 100644 src/main/java/edu/ksu/canvas/requestOptions/ListCourseDiscussionTopicsOptions.java diff --git a/.gitignore b/.gitignore index 970d3230..ef410531 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ rebel.xml rebel-remote.xml *.iml *.idea -release.properties \ No newline at end of file +release.properties +/discussion_test/ diff --git a/src/main/java/edu/ksu/canvas/CanvasApiFactory.java b/src/main/java/edu/ksu/canvas/CanvasApiFactory.java index 1e753be0..fd16f01a 100644 --- a/src/main/java/edu/ksu/canvas/CanvasApiFactory.java +++ b/src/main/java/edu/ksu/canvas/CanvasApiFactory.java @@ -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; @@ -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); @@ -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); } } diff --git a/src/main/java/edu/ksu/canvas/impl/AnnouncementImpl.java b/src/main/java/edu/ksu/canvas/impl/AnnouncementImpl.java new file mode 100644 index 00000000..f38e3d34 --- /dev/null +++ b/src/main/java/edu/ksu/canvas/impl/AnnouncementImpl.java @@ -0,0 +1,36 @@ +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; + +public class AnnouncementImpl extends BaseImpl 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 listCourseAnnouncements(ListCourseAnnouncementsOptions options) throws IOException { + String url = buildCanvasUrl("/announcements", options.getOptionsMap()); + return getListFromCanvas(url); + } + + @Override + protected Type listType() { + return new TypeToken>(){}.getType(); + } + + @Override + protected Class objectType() { + return Announcement.class; + } +} diff --git a/src/main/java/edu/ksu/canvas/impl/DiscussionTopicImpl.java b/src/main/java/edu/ksu/canvas/impl/DiscussionTopicImpl.java new file mode 100644 index 00000000..a6b0e142 --- /dev/null +++ b/src/main/java/edu/ksu/canvas/impl/DiscussionTopicImpl.java @@ -0,0 +1,65 @@ +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.List; +import java.util.Optional; + +public class DiscussionTopicImpl extends BaseImpl 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 listCourseDiscussionTopics(ListCourseDiscussionTopicsOptions options) throws IOException { + String url = buildCanvasUrl("courses/" + options.getCourseId() + "/discussion_topics", options.getOptionsMap()); + return getListFromCanvas(url); + } + + @Override + public Optional 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 createDiscussionTopic(String courseId, DiscussionTopic discussionTopic) throws IOException { + return Optional.empty(); + } + + @Override + public Optional deleteDiscussionTopic(String courseId, Long discussionTopicId) throws IOException { + return Optional.empty(); + } + + @Override + public Optional editDiscussionTopic(String courseId, DiscussionTopic discussionTopic) throws IOException { + return Optional.empty(); + } + + @Override + protected Type listType() { + return new TypeToken>(){}.getType(); + } + + @Override + protected Class objectType() { + return DiscussionTopic.class; + } +} diff --git a/src/main/java/edu/ksu/canvas/interfaces/AnnouncementReader.java b/src/main/java/edu/ksu/canvas/interfaces/AnnouncementReader.java new file mode 100644 index 00000000..815ca47c --- /dev/null +++ b/src/main/java/edu/ksu/canvas/interfaces/AnnouncementReader.java @@ -0,0 +1,13 @@ +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; + +public interface AnnouncementReader extends CanvasReader { + + List listCourseAnnouncements(ListCourseAnnouncementsOptions options) throws IOException; + +} diff --git a/src/main/java/edu/ksu/canvas/interfaces/AnnouncementWriter.java b/src/main/java/edu/ksu/canvas/interfaces/AnnouncementWriter.java new file mode 100644 index 00000000..224e5095 --- /dev/null +++ b/src/main/java/edu/ksu/canvas/interfaces/AnnouncementWriter.java @@ -0,0 +1,13 @@ +package edu.ksu.canvas.interfaces; + +import edu.ksu.canvas.model.announcement.Announcement; + +public interface AnnouncementWriter extends CanvasWriter { + + /* + * There are no write calls for announcements. That's all handled by + * the DiscussionTopic calls. This is here to fit the structure of + * the library. + */ + +} diff --git a/src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicReader.java b/src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicReader.java new file mode 100644 index 00000000..95877569 --- /dev/null +++ b/src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicReader.java @@ -0,0 +1,17 @@ +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 { + + Optional getSingleDiscussionTopic(GetSingleDiscussionTopicOptions options) throws IOException; + + List listCourseDiscussionTopics(ListCourseDiscussionTopicsOptions options) throws IOException; + +} diff --git a/src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicWriter.java b/src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicWriter.java new file mode 100644 index 00000000..eb6429c4 --- /dev/null +++ b/src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicWriter.java @@ -0,0 +1,16 @@ +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 { + + Optional createDiscussionTopic(String courseId, DiscussionTopic discussionTopic) throws IOException; + + Optional deleteDiscussionTopic(String courseId, Long discussionTopicId) throws IOException; + + Optional editDiscussionTopic(String courseId, DiscussionTopic discussionTopic) throws IOException; + +} diff --git a/src/main/java/edu/ksu/canvas/model/announcement/Announcement.java b/src/main/java/edu/ksu/canvas/model/announcement/Announcement.java new file mode 100644 index 00000000..ebb22242 --- /dev/null +++ b/src/main/java/edu/ksu/canvas/model/announcement/Announcement.java @@ -0,0 +1,11 @@ +package edu.ksu.canvas.model.announcement; + +import edu.ksu.canvas.model.discussion.DiscussionTopic; + +import java.io.Serializable; + +public class Announcement extends DiscussionTopic implements Serializable { + + private static final long serialVersionUID = 1L; + +} diff --git a/src/main/java/edu/ksu/canvas/model/assignment/Assignment.java b/src/main/java/edu/ksu/canvas/model/assignment/Assignment.java index dbae7c4d..6699f8e8 100644 --- a/src/main/java/edu/ksu/canvas/model/assignment/Assignment.java +++ b/src/main/java/edu/ksu/canvas/model/assignment/Assignment.java @@ -10,7 +10,7 @@ import java.util.List; /** - * Class to represent Canvas assigmnents. + * Class to represent Canvas assignments. * See Canvas assignment documentation. */ @CanvasObject(postKey = "assignment") diff --git a/src/main/java/edu/ksu/canvas/model/discussion/DiscussionTopic.java b/src/main/java/edu/ksu/canvas/model/discussion/DiscussionTopic.java new file mode 100644 index 00000000..17098cf0 --- /dev/null +++ b/src/main/java/edu/ksu/canvas/model/discussion/DiscussionTopic.java @@ -0,0 +1,362 @@ +package edu.ksu.canvas.model.discussion; + +import edu.ksu.canvas.annotation.CanvasField; +import edu.ksu.canvas.annotation.CanvasObject; +import edu.ksu.canvas.model.BaseCanvasModel; +import edu.ksu.canvas.model.File; +import edu.ksu.canvas.model.assignment.LockInfo; + +import java.io.Serializable; +import java.util.Date; + +/** + * Class to represent canvas Discussion Topics. + * See Canvas DiscussionTopicdocumentation. + */ +@CanvasObject(postKey = "discussion_topic") +public class DiscussionTopic extends BaseCanvasModel implements Serializable { + + private static final long serialVersionUID = 1L; + private Long id; + private String title; + private String message; + private String htmlURL; + private Date postedAt; + private Date lastReplyAt; + private Boolean requireInitialPost; + private Boolean userCanSeePosts; + private Long discussionSubentryCount; + private String readState; + private Long unreadCount; + private Boolean subscribed; + private String subscriptionHold; + private Long assignmentId; + private Date delayedPostAt; + private Boolean published; + private Date lockAt; + private Boolean locked; + private Boolean pinned; + private Boolean lockedForUser; + private LockInfo lockInfo; + private String lockExplanation; + private String userName; + private Long[] topicChildren; + private TopicChildren[] groupTopicChildren; + private Long rootTopicId; + private String podcastURL; + private String discussionType; + private Long groupCategoryId; + private File[] attachments; + private DiscussionTopicPermission permissions; + private Boolean allowRating; + private Boolean onlyGradersCanRate; + private Boolean sortByRating; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @CanvasField(postKey = "title") + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + @CanvasField(postKey = "message") + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getHtmlURL() { + return htmlURL; + } + + public void setHtmlURL(String htmlURL) { + this.htmlURL = htmlURL; + } + + public Date getPostedAt() { + return postedAt; + } + + public void setPostedAt(Date postedAt) { + this.postedAt = postedAt; + } + + public Date getLastReplyAt() { + return lastReplyAt; + } + + public void setLastReplyAt(Date lastReplyAt) { + this.lastReplyAt = lastReplyAt; + } + + @CanvasField(postKey = "require_initial_post") + public Boolean getRequireInitialPost() { + return requireInitialPost; + } + + public void setRequireInitialPost(Boolean requireInitialPost) { + this.requireInitialPost = requireInitialPost; + } + + public Boolean getUserCanSeePosts() { + return userCanSeePosts; + } + + public void setUserCanSeePosts(Boolean userCanSeePosts) { + this.userCanSeePosts = userCanSeePosts; + } + + public Long getDiscussionSubentryCount() { + return discussionSubentryCount; + } + + public void setDiscussionSubentryCount(Long discussionSubentryCount) { + this.discussionSubentryCount = discussionSubentryCount; + } + + public String getReadState() { + return readState; + } + + public void setReadState(String readState) { + this.readState = readState; + } + + public Long getUnreadCount() { + return unreadCount; + } + + public void setUnreadCount(Long unreadCount) { + this.unreadCount = unreadCount; + } + + public Boolean getSubscribed() { + return subscribed; + } + + public void setSubscribed(Boolean subscribed) { + this.subscribed = subscribed; + } + + public String getSubscriptionHold() { + return subscriptionHold; + } + + public void setSubscriptionHold(String subscriptionHold) { + this.subscriptionHold = subscriptionHold; + } + + public Long getAssignmentId() { + return assignmentId; + } + + public void setAssignmentId(Long assignmentId) { + this.assignmentId = assignmentId; + } + + @CanvasField(postKey = "delayed_post_at") + public Date getDelayedPostAt() { + return delayedPostAt; + } + + public void setDelayedPostAt(Date delayedPostAt) { + this.delayedPostAt = delayedPostAt; + } + + public Boolean getPublished() { + return published; + } + + public void setPublished(Boolean published) { + this.published = published; + } + + @CanvasField(postKey = "lock_at") + public Date getLockAt() { + return lockAt; + } + + public void setLockAt(Date lockAt) { + this.lockAt = lockAt; + } + + @CanvasField(postKey = "locked") + public Boolean getLocked() { + return locked; + } + + public void setLocked(Boolean locked) { + this.locked = locked; + } + + public Boolean getPinned() { + return pinned; + } + + public void setPinned(Boolean pinned) { + this.pinned = pinned; + } + + public Boolean getLockedForUser() { + return lockedForUser; + } + + public void setLockedForUser(Boolean lockedForUser) { + this.lockedForUser = lockedForUser; + } + + public LockInfo getLockInfo() { + return lockInfo; + } + + public void setLockInfo(LockInfo lockInfo) { + this.lockInfo = lockInfo; + } + + public String getLockExplanation() { + return lockExplanation; + } + + public void setLockExplanation(String lockExplanation) { + this.lockExplanation = lockExplanation; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public Long[] getTopicChildren() { + return topicChildren; + } + + public void setTopicChildren(Long[] topicChildren) { + this.topicChildren = topicChildren; + } + + public TopicChildren[] getGroupTopicChildren() { + return groupTopicChildren; + } + + public void setGroupTopicChildren(TopicChildren[] groupTopicChildren) { + this.groupTopicChildren = groupTopicChildren; + } + + public Long getRootTopicId() { + return rootTopicId; + } + + public void setRootTopicId(Long rootTopicId) { + this.rootTopicId = rootTopicId; + } + + public String getPodcastURL() { + return podcastURL; + } + + public void setPodcastURL(String podcastURL) { + this.podcastURL = podcastURL; + } + + @CanvasField(postKey = "discussion_type") + public String getDiscussionType() { + return discussionType; + } + + public void setDiscussionType(String discussionType) { + this.discussionType = discussionType; + } + + public Long getGroupCategoryId() { + return groupCategoryId; + } + + public void setGroupCategoryId(Long groupCategoryId) { + this.groupCategoryId = groupCategoryId; + } + + @CanvasField(postKey = "attachments") + public File[] getAttachments() { + return attachments; + } + + public void setAttachments(File[] attachments) { + this.attachments = attachments; + } + + public DiscussionTopicPermission getPermissions() { + return permissions; + } + + public void setPermissions(DiscussionTopicPermission permissions) { + this.permissions = permissions; + } + + @CanvasField(postKey = "allow_rating") + public Boolean getAllowRating() { + return allowRating; + } + + public void setAllowRating(Boolean allowRating) { + this.allowRating = allowRating; + } + + @CanvasField(postKey = "only_graders_can_rate") + public Boolean getOnlyGradersCanRate() { + return onlyGradersCanRate; + } + + public void setOnlyGradersCanRate(Boolean onlyGradersCanRate) { + this.onlyGradersCanRate = onlyGradersCanRate; + } + + @CanvasField(postKey = "sort_by_rating") + public Boolean getSortByRating() { + return sortByRating; + } + + public void setSortByRating(Boolean sortByRating) { + this.sortByRating = sortByRating; + } + + public class TopicChildren implements Serializable { + + private static final long serialVersionUID = 1L; + + private String topicId; + private String groupId; + + public String getTopicId() { + return topicId; + } + + public void setTopicId(String topicId) { + this.topicId = topicId; + } + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + } + +} diff --git a/src/main/java/edu/ksu/canvas/model/discussion/DiscussionTopicPermission.java b/src/main/java/edu/ksu/canvas/model/discussion/DiscussionTopicPermission.java new file mode 100644 index 00000000..b120eafd --- /dev/null +++ b/src/main/java/edu/ksu/canvas/model/discussion/DiscussionTopicPermission.java @@ -0,0 +1,13 @@ +package edu.ksu.canvas.model.discussion; + +import java.io.Serializable; + +public class DiscussionTopicPermission implements Serializable { + + private static final long serialVersionUID = 1L; + + private Boolean attach; + + public boolean canAttach() { return attach; } + +} diff --git a/src/main/java/edu/ksu/canvas/requestOptions/GetSingleDiscussionTopicOptions.java b/src/main/java/edu/ksu/canvas/requestOptions/GetSingleDiscussionTopicOptions.java new file mode 100644 index 00000000..f0c39c68 --- /dev/null +++ b/src/main/java/edu/ksu/canvas/requestOptions/GetSingleDiscussionTopicOptions.java @@ -0,0 +1,38 @@ +package edu.ksu.canvas.requestOptions; + +import java.util.List; + +public class GetSingleDiscussionTopicOptions extends BaseOptions { + + private String courseId; + private Long discussionTopicId; + + public enum Include { + ALL_DATES, SECTIONS, SECTIONS_USER_COUNT, OVERRIDES; + + @Override + public String toString() { return name().toLowerCase(); } + } + + public GetSingleDiscussionTopicOptions(String courseId, Long discussionTopicId) { + if (courseId == null || discussionTopicId == null) { + throw new IllegalArgumentException("Course and discussion topic ids are required"); + } + this.courseId = courseId; + this.discussionTopicId = discussionTopicId; + } + + public String getCourseId() { + return courseId; + } + + public Long getDiscussionTopicId() { + return discussionTopicId; + } + + public GetSingleDiscussionTopicOptions includes(List includes) { + addEnumList("include[]", includes); + return this; + } + +} diff --git a/src/main/java/edu/ksu/canvas/requestOptions/ListCourseAnnouncementsOptions.java b/src/main/java/edu/ksu/canvas/requestOptions/ListCourseAnnouncementsOptions.java new file mode 100644 index 00000000..f5855d0b --- /dev/null +++ b/src/main/java/edu/ksu/canvas/requestOptions/ListCourseAnnouncementsOptions.java @@ -0,0 +1,61 @@ +package edu.ksu.canvas.requestOptions; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class ListCourseAnnouncementsOptions extends BaseOptions { + + public enum Include { + SECTIONS, SECTIONS_USER_COUNT; + + @Override + public String toString() { return name().toLowerCase(); } + } + + private String courseId; + + public ListCourseAnnouncementsOptions(String courseId) { + this.courseId = courseId; + List contextCodesList = new ArrayList<>(); + contextCodesList.add("course_" + courseId); + addStringList("context_codes[]", contextCodesList); + } + + public String getCourseId() { + return courseId; + } + + public ListCourseAnnouncementsOptions includes(List includes) { + addEnumList("include[]", includes); + return this; + } + + public ListCourseAnnouncementsOptions startDate(Date startDate) { + addSingleItem("start_date", formatDate(startDate)); + return this; + } + + public ListCourseAnnouncementsOptions endDate(Date endDate) { + addSingleItem("end_date", formatDate(endDate)); + return this; + } + + public ListCourseAnnouncementsOptions activeOnly(Boolean activeOnly) { + addSingleItem("active_only", activeOnly.toString()); + return this; + } + + public ListCourseAnnouncementsOptions latestOnly(Boolean latestOnly) { + addSingleItem("latest_only", latestOnly.toString()); + return this; + } + + private static String formatDate(Date date) { + DateFormat df = new SimpleDateFormat("yyyy-MM-ddTHH:mm:ssZ"); + return df.format(date); + } + +} diff --git a/src/main/java/edu/ksu/canvas/requestOptions/ListCourseDiscussionTopicsOptions.java b/src/main/java/edu/ksu/canvas/requestOptions/ListCourseDiscussionTopicsOptions.java new file mode 100644 index 00000000..61d537d1 --- /dev/null +++ b/src/main/java/edu/ksu/canvas/requestOptions/ListCourseDiscussionTopicsOptions.java @@ -0,0 +1,80 @@ +package edu.ksu.canvas.requestOptions; + +import java.util.List; + +public class ListCourseDiscussionTopicsOptions extends BaseOptions { + + public enum Include { + ALL_DATES, SECTIONS, SECTIONS_USER_COUNT, OVERRIDES; + + @Override + public String toString() { return name().toLowerCase(); } + } + + public enum OrderBy { + POSITION, RECENT_ACTIVITY, TITLE; + + @Override + public String toString() { return name().toLowerCase(); } + } + + public enum Scope { + LOCKED, UNLOCKED, PINNED, UNPINNED; + + @Override + public String toString() { return name().toLowerCase(); } + } + + public enum FilterBy { + ALL, UNREAD; + + @Override + public String toString() { return name().toLowerCase(); } + } + + private String courseId; + + public ListCourseDiscussionTopicsOptions(String courseId) { + this.courseId = courseId; + } + + public String getCourseId() { + return courseId; + } + + public ListCourseDiscussionTopicsOptions includes(List includes) { + addEnumList("include[]", includes); + return this; + } + + public ListCourseDiscussionTopicsOptions orderBy(OrderBy orderBy) { + addSingleItem("order_by", orderBy.toString()); + return this; + } + + public ListCourseDiscussionTopicsOptions scope(List scopes) { + addEnumList("scope", scopes); + return this; + } + + public ListCourseDiscussionTopicsOptions onlyAnnouncements(Boolean onlyAnnouncements) { + addSingleItem("only_announcements", onlyAnnouncements.toString()); + return this; + } + + public ListCourseDiscussionTopicsOptions searchTerm(String searchTerm) { + addSingleItem("search_term", searchTerm); + return this; + } + + public ListCourseDiscussionTopicsOptions filterBy(FilterBy filterBy) { + addSingleItem("filter_by", filterBy.toString()); + return this; + } + + public ListCourseDiscussionTopicsOptions excludeContextModuleLockedTopics(Boolean exclude) { + addSingleItem("exclude_context_module_locked_topics", exclude.toString()); + return this; + } + +} diff --git a/src/test/java/edu/ksu/canvas/BaseCanvasModelUTest.java b/src/test/java/edu/ksu/canvas/BaseCanvasModelUTest.java index 5c477996..b4e6bd23 100644 --- a/src/test/java/edu/ksu/canvas/BaseCanvasModelUTest.java +++ b/src/test/java/edu/ksu/canvas/BaseCanvasModelUTest.java @@ -13,7 +13,7 @@ import java.util.stream.Collectors; public class BaseCanvasModelUTest { - public static final String CLASS_POST_KEY = "test"; + public static final String CLASS_POST_KEY = "com/canvacord/test"; public static final String CLASS_POST_KEY_OVERRIDE = "override"; public static final String FIELD1_POST_KEY = "field1Key"; public static final String FIELD2_POST_KEY = "field2Key"; @@ -120,4 +120,4 @@ public void jsonField1Value() throws Exception { Assert.assertEquals("JSON object should have a 'field1' value of " + FIELD1_VALUE, FIELD1_VALUE, field1Value); } -} \ No newline at end of file +} From 4356293a7a93bcf5cae014eac200f0b83395cbaa Mon Sep 17 00:00:00 2001 From: Garrett Date: Wed, 25 Jan 2023 15:07:06 -0800 Subject: [PATCH 2/8] Add Javadoc comments for DiscussionTopicReader --- .../ksu/canvas/interfaces/DiscussionTopicReader.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicReader.java b/src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicReader.java index 95877569..ec706e3c 100644 --- a/src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicReader.java +++ b/src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicReader.java @@ -10,8 +10,20 @@ public interface DiscussionTopicReader extends CanvasReader { + /** + * 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 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 listCourseDiscussionTopics(ListCourseDiscussionTopicsOptions options) throws IOException; } From cb1432513319a22cffda754874bcd83d49c8377f Mon Sep 17 00:00:00 2001 From: Garrett Date: Wed, 25 Jan 2023 15:17:52 -0800 Subject: [PATCH 3/8] Add is_announcement parameter to discussion posting methods and add Javadoc comments for DiscussionTopicWriter --- .../ksu/canvas/impl/DiscussionTopicImpl.java | 2 +- .../interfaces/DiscussionTopicWriter.java | 24 ++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/ksu/canvas/impl/DiscussionTopicImpl.java b/src/main/java/edu/ksu/canvas/impl/DiscussionTopicImpl.java index a6b0e142..e7b18358 100644 --- a/src/main/java/edu/ksu/canvas/impl/DiscussionTopicImpl.java +++ b/src/main/java/edu/ksu/canvas/impl/DiscussionTopicImpl.java @@ -39,7 +39,7 @@ public Optional getSingleDiscussionTopic(GetSingleDiscussionTop } @Override - public Optional createDiscussionTopic(String courseId, DiscussionTopic discussionTopic) throws IOException { + public Optional createDiscussionTopic(String courseId, DiscussionTopic discussionTopic, boolean isAnnouncement) throws IOException { return Optional.empty(); } diff --git a/src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicWriter.java b/src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicWriter.java index eb6429c4..ab155c05 100644 --- a/src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicWriter.java +++ b/src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicWriter.java @@ -7,10 +7,32 @@ public interface DiscussionTopicWriter extends CanvasWriter { - Optional createDiscussionTopic(String courseId, DiscussionTopic discussionTopic) throws IOException; + /** + * 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 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 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 editDiscussionTopic(String courseId, DiscussionTopic discussionTopic) throws IOException; } From 4eab90785f0194c4702082222ec9c7f4e5f8edbc Mon Sep 17 00:00:00 2001 From: Garrett Date: Wed, 25 Jan 2023 15:23:48 -0800 Subject: [PATCH 4/8] Added Javadoc explanations for the Announcement classes --- .../java/edu/ksu/canvas/impl/AnnouncementImpl.java | 5 +++++ .../ksu/canvas/interfaces/AnnouncementReader.java | 6 ++++++ .../ksu/canvas/interfaces/AnnouncementWriter.java | 12 +++++------- .../ksu/canvas/model/announcement/Announcement.java | 4 ++++ 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/main/java/edu/ksu/canvas/impl/AnnouncementImpl.java b/src/main/java/edu/ksu/canvas/impl/AnnouncementImpl.java index f38e3d34..aceb9c8f 100644 --- a/src/main/java/edu/ksu/canvas/impl/AnnouncementImpl.java +++ b/src/main/java/edu/ksu/canvas/impl/AnnouncementImpl.java @@ -12,6 +12,11 @@ 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 implements AnnouncementReader, AnnouncementWriter { public AnnouncementImpl(String canvasBaseUrl, Integer apiVersion, OauthToken oauthToken, RestClient restClient, int connectTimeout, int readTimeout, Integer paginationPageSize, Boolean serializeNulls) { diff --git a/src/main/java/edu/ksu/canvas/interfaces/AnnouncementReader.java b/src/main/java/edu/ksu/canvas/interfaces/AnnouncementReader.java index 815ca47c..cb60aaaf 100644 --- a/src/main/java/edu/ksu/canvas/interfaces/AnnouncementReader.java +++ b/src/main/java/edu/ksu/canvas/interfaces/AnnouncementReader.java @@ -6,6 +6,12 @@ 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 { List listCourseAnnouncements(ListCourseAnnouncementsOptions options) throws IOException; diff --git a/src/main/java/edu/ksu/canvas/interfaces/AnnouncementWriter.java b/src/main/java/edu/ksu/canvas/interfaces/AnnouncementWriter.java index 224e5095..e49b5f06 100644 --- a/src/main/java/edu/ksu/canvas/interfaces/AnnouncementWriter.java +++ b/src/main/java/edu/ksu/canvas/interfaces/AnnouncementWriter.java @@ -2,12 +2,10 @@ 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 { - - /* - * There are no write calls for announcements. That's all handled by - * the DiscussionTopic calls. This is here to fit the structure of - * the library. - */ - } diff --git a/src/main/java/edu/ksu/canvas/model/announcement/Announcement.java b/src/main/java/edu/ksu/canvas/model/announcement/Announcement.java index ebb22242..35583203 100644 --- a/src/main/java/edu/ksu/canvas/model/announcement/Announcement.java +++ b/src/main/java/edu/ksu/canvas/model/announcement/Announcement.java @@ -4,6 +4,10 @@ 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; From bbad5a7f4400bc26eea723dbf3f2e3a5f67c7ff3 Mon Sep 17 00:00:00 2001 From: Garrett Date: Wed, 25 Jan 2023 15:31:35 -0800 Subject: [PATCH 5/8] [UNTESTED] Implemented methods for posting, deleting, and editing Discussion Topics --- .../ksu/canvas/impl/DiscussionTopicImpl.java | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/main/java/edu/ksu/canvas/impl/DiscussionTopicImpl.java b/src/main/java/edu/ksu/canvas/impl/DiscussionTopicImpl.java index e7b18358..001f87a2 100644 --- a/src/main/java/edu/ksu/canvas/impl/DiscussionTopicImpl.java +++ b/src/main/java/edu/ksu/canvas/impl/DiscussionTopicImpl.java @@ -14,8 +14,7 @@ import java.io.IOException; import java.lang.reflect.Type; -import java.util.List; -import java.util.Optional; +import java.util.*; public class DiscussionTopicImpl extends BaseImpl implements DiscussionTopicReader, DiscussionTopicWriter { private static final Logger LOG = LoggerFactory.getLogger(DiscussionTopicImpl.class); @@ -40,17 +39,30 @@ public Optional getSingleDiscussionTopic(GetSingleDiscussionTop @Override public Optional createDiscussionTopic(String courseId, DiscussionTopic discussionTopic, boolean isAnnouncement) throws IOException { - return Optional.empty(); + 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 deleteDiscussionTopic(String courseId, Long discussionTopicId) throws IOException { - return Optional.empty(); + Map> 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 editDiscussionTopic(String courseId, DiscussionTopic discussionTopic) throws IOException { - return Optional.empty(); + 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 From f1ad66703c395059463db653c564e2568b3feb7c Mon Sep 17 00:00:00 2001 From: Garrett Date: Wed, 25 Jan 2023 15:37:59 -0800 Subject: [PATCH 6/8] Reformatted files to match code style --- .../edu/ksu/canvas/impl/AnnouncementImpl.java | 32 +- .../ksu/canvas/impl/DiscussionTopicImpl.java | 98 +-- .../canvas/interfaces/AnnouncementReader.java | 2 +- .../interfaces/DiscussionTopicReader.java | 28 +- .../interfaces/DiscussionTopicWriter.java | 50 +- .../model/announcement/Announcement.java | 2 +- .../model/discussion/DiscussionTopic.java | 650 +++++++++--------- .../discussion/DiscussionTopicPermission.java | 6 +- 8 files changed, 434 insertions(+), 434 deletions(-) diff --git a/src/main/java/edu/ksu/canvas/impl/AnnouncementImpl.java b/src/main/java/edu/ksu/canvas/impl/AnnouncementImpl.java index aceb9c8f..8d8b6819 100644 --- a/src/main/java/edu/ksu/canvas/impl/AnnouncementImpl.java +++ b/src/main/java/edu/ksu/canvas/impl/AnnouncementImpl.java @@ -19,23 +19,23 @@ */ public class AnnouncementImpl extends BaseImpl 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); - } + 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 listCourseAnnouncements(ListCourseAnnouncementsOptions options) throws IOException { - String url = buildCanvasUrl("/announcements", options.getOptionsMap()); - return getListFromCanvas(url); - } + @Override + public List listCourseAnnouncements(ListCourseAnnouncementsOptions options) throws IOException { + String url = buildCanvasUrl("/announcements", options.getOptionsMap()); + return getListFromCanvas(url); + } - @Override - protected Type listType() { - return new TypeToken>(){}.getType(); - } + @Override + protected Type listType() { + return new TypeToken>(){}.getType(); + } - @Override - protected Class objectType() { - return Announcement.class; - } + @Override + protected Class objectType() { + return Announcement.class; + } } diff --git a/src/main/java/edu/ksu/canvas/impl/DiscussionTopicImpl.java b/src/main/java/edu/ksu/canvas/impl/DiscussionTopicImpl.java index 001f87a2..f6ea36a2 100644 --- a/src/main/java/edu/ksu/canvas/impl/DiscussionTopicImpl.java +++ b/src/main/java/edu/ksu/canvas/impl/DiscussionTopicImpl.java @@ -17,61 +17,61 @@ import java.util.*; public class DiscussionTopicImpl extends BaseImpl implements DiscussionTopicReader, DiscussionTopicWriter { - private static final Logger LOG = LoggerFactory.getLogger(DiscussionTopicImpl.class); + 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); - } + 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 listCourseDiscussionTopics(ListCourseDiscussionTopicsOptions options) throws IOException { - String url = buildCanvasUrl("courses/" + options.getCourseId() + "/discussion_topics", options.getOptionsMap()); - return getListFromCanvas(url); - } + @Override + public List listCourseDiscussionTopics(ListCourseDiscussionTopicsOptions options) throws IOException { + String url = buildCanvasUrl("courses/" + options.getCourseId() + "/discussion_topics", options.getOptionsMap()); + return getListFromCanvas(url); + } - @Override - public Optional 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 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 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 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 deleteDiscussionTopic(String courseId, Long discussionTopicId) throws IOException { - Map> 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 deleteDiscussionTopic(String courseId, Long discussionTopicId) throws IOException { + Map> 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 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 + public Optional 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>(){}.getType(); - } + @Override + protected Type listType() { + return new TypeToken>(){}.getType(); + } - @Override - protected Class objectType() { - return DiscussionTopic.class; - } + @Override + protected Class objectType() { + return DiscussionTopic.class; + } } diff --git a/src/main/java/edu/ksu/canvas/interfaces/AnnouncementReader.java b/src/main/java/edu/ksu/canvas/interfaces/AnnouncementReader.java index cb60aaaf..76ba93c9 100644 --- a/src/main/java/edu/ksu/canvas/interfaces/AnnouncementReader.java +++ b/src/main/java/edu/ksu/canvas/interfaces/AnnouncementReader.java @@ -14,6 +14,6 @@ */ public interface AnnouncementReader extends CanvasReader { - List listCourseAnnouncements(ListCourseAnnouncementsOptions options) throws IOException; + List listCourseAnnouncements(ListCourseAnnouncementsOptions options) throws IOException; } diff --git a/src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicReader.java b/src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicReader.java index ec706e3c..82377f5f 100644 --- a/src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicReader.java +++ b/src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicReader.java @@ -10,20 +10,20 @@ public interface DiscussionTopicReader extends CanvasReader { - /** - * 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 getSingleDiscussionTopic(GetSingleDiscussionTopicOptions options) throws IOException; + /** + * 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 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 listCourseDiscussionTopics(ListCourseDiscussionTopicsOptions 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 listCourseDiscussionTopics(ListCourseDiscussionTopicsOptions options) throws IOException; } diff --git a/src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicWriter.java b/src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicWriter.java index ab155c05..18256284 100644 --- a/src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicWriter.java +++ b/src/main/java/edu/ksu/canvas/interfaces/DiscussionTopicWriter.java @@ -7,32 +7,32 @@ public interface DiscussionTopicWriter extends CanvasWriter { - /** - * 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 createDiscussionTopic(String courseId, DiscussionTopic discussionTopic, boolean isAnnouncement) throws IOException; + /** + * 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 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 deleteDiscussionTopic(String courseId, Long discussionTopicId) 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 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 editDiscussionTopic(String courseId, DiscussionTopic discussionTopic) 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 editDiscussionTopic(String courseId, DiscussionTopic discussionTopic) throws IOException; } diff --git a/src/main/java/edu/ksu/canvas/model/announcement/Announcement.java b/src/main/java/edu/ksu/canvas/model/announcement/Announcement.java index 35583203..bdd0b1d2 100644 --- a/src/main/java/edu/ksu/canvas/model/announcement/Announcement.java +++ b/src/main/java/edu/ksu/canvas/model/announcement/Announcement.java @@ -10,6 +10,6 @@ */ public class Announcement extends DiscussionTopic implements Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; } diff --git a/src/main/java/edu/ksu/canvas/model/discussion/DiscussionTopic.java b/src/main/java/edu/ksu/canvas/model/discussion/DiscussionTopic.java index 17098cf0..b4c0270d 100644 --- a/src/main/java/edu/ksu/canvas/model/discussion/DiscussionTopic.java +++ b/src/main/java/edu/ksu/canvas/model/discussion/DiscussionTopic.java @@ -16,347 +16,347 @@ @CanvasObject(postKey = "discussion_topic") public class DiscussionTopic extends BaseCanvasModel implements Serializable { - private static final long serialVersionUID = 1L; - private Long id; - private String title; - private String message; - private String htmlURL; - private Date postedAt; - private Date lastReplyAt; - private Boolean requireInitialPost; - private Boolean userCanSeePosts; - private Long discussionSubentryCount; - private String readState; - private Long unreadCount; - private Boolean subscribed; - private String subscriptionHold; - private Long assignmentId; - private Date delayedPostAt; - private Boolean published; - private Date lockAt; - private Boolean locked; - private Boolean pinned; - private Boolean lockedForUser; - private LockInfo lockInfo; - private String lockExplanation; - private String userName; - private Long[] topicChildren; - private TopicChildren[] groupTopicChildren; - private Long rootTopicId; - private String podcastURL; - private String discussionType; - private Long groupCategoryId; - private File[] attachments; - private DiscussionTopicPermission permissions; - private Boolean allowRating; - private Boolean onlyGradersCanRate; - private Boolean sortByRating; - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - @CanvasField(postKey = "title") - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - @CanvasField(postKey = "message") - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public String getHtmlURL() { - return htmlURL; - } - - public void setHtmlURL(String htmlURL) { - this.htmlURL = htmlURL; - } - - public Date getPostedAt() { - return postedAt; - } - - public void setPostedAt(Date postedAt) { - this.postedAt = postedAt; - } - - public Date getLastReplyAt() { - return lastReplyAt; - } - - public void setLastReplyAt(Date lastReplyAt) { - this.lastReplyAt = lastReplyAt; - } - - @CanvasField(postKey = "require_initial_post") - public Boolean getRequireInitialPost() { - return requireInitialPost; - } - - public void setRequireInitialPost(Boolean requireInitialPost) { - this.requireInitialPost = requireInitialPost; - } - - public Boolean getUserCanSeePosts() { - return userCanSeePosts; - } - - public void setUserCanSeePosts(Boolean userCanSeePosts) { - this.userCanSeePosts = userCanSeePosts; - } - - public Long getDiscussionSubentryCount() { - return discussionSubentryCount; - } - - public void setDiscussionSubentryCount(Long discussionSubentryCount) { - this.discussionSubentryCount = discussionSubentryCount; - } - - public String getReadState() { - return readState; - } - - public void setReadState(String readState) { - this.readState = readState; - } - - public Long getUnreadCount() { - return unreadCount; - } - - public void setUnreadCount(Long unreadCount) { - this.unreadCount = unreadCount; - } - - public Boolean getSubscribed() { - return subscribed; - } - - public void setSubscribed(Boolean subscribed) { - this.subscribed = subscribed; - } - - public String getSubscriptionHold() { - return subscriptionHold; - } - - public void setSubscriptionHold(String subscriptionHold) { - this.subscriptionHold = subscriptionHold; - } - - public Long getAssignmentId() { - return assignmentId; - } - - public void setAssignmentId(Long assignmentId) { - this.assignmentId = assignmentId; - } - - @CanvasField(postKey = "delayed_post_at") - public Date getDelayedPostAt() { - return delayedPostAt; - } - - public void setDelayedPostAt(Date delayedPostAt) { - this.delayedPostAt = delayedPostAt; - } - - public Boolean getPublished() { - return published; - } - - public void setPublished(Boolean published) { - this.published = published; - } - - @CanvasField(postKey = "lock_at") - public Date getLockAt() { - return lockAt; - } - - public void setLockAt(Date lockAt) { - this.lockAt = lockAt; - } - - @CanvasField(postKey = "locked") - public Boolean getLocked() { - return locked; - } - - public void setLocked(Boolean locked) { - this.locked = locked; - } - - public Boolean getPinned() { - return pinned; - } - - public void setPinned(Boolean pinned) { - this.pinned = pinned; - } - - public Boolean getLockedForUser() { - return lockedForUser; - } - - public void setLockedForUser(Boolean lockedForUser) { - this.lockedForUser = lockedForUser; - } - - public LockInfo getLockInfo() { - return lockInfo; - } - - public void setLockInfo(LockInfo lockInfo) { - this.lockInfo = lockInfo; - } - - public String getLockExplanation() { - return lockExplanation; - } - - public void setLockExplanation(String lockExplanation) { - this.lockExplanation = lockExplanation; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } + private static final long serialVersionUID = 1L; + private Long id; + private String title; + private String message; + private String htmlURL; + private Date postedAt; + private Date lastReplyAt; + private Boolean requireInitialPost; + private Boolean userCanSeePosts; + private Long discussionSubentryCount; + private String readState; + private Long unreadCount; + private Boolean subscribed; + private String subscriptionHold; + private Long assignmentId; + private Date delayedPostAt; + private Boolean published; + private Date lockAt; + private Boolean locked; + private Boolean pinned; + private Boolean lockedForUser; + private LockInfo lockInfo; + private String lockExplanation; + private String userName; + private Long[] topicChildren; + private TopicChildren[] groupTopicChildren; + private Long rootTopicId; + private String podcastURL; + private String discussionType; + private Long groupCategoryId; + private File[] attachments; + private DiscussionTopicPermission permissions; + private Boolean allowRating; + private Boolean onlyGradersCanRate; + private Boolean sortByRating; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @CanvasField(postKey = "title") + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + @CanvasField(postKey = "message") + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getHtmlURL() { + return htmlURL; + } + + public void setHtmlURL(String htmlURL) { + this.htmlURL = htmlURL; + } + + public Date getPostedAt() { + return postedAt; + } + + public void setPostedAt(Date postedAt) { + this.postedAt = postedAt; + } + + public Date getLastReplyAt() { + return lastReplyAt; + } + + public void setLastReplyAt(Date lastReplyAt) { + this.lastReplyAt = lastReplyAt; + } + + @CanvasField(postKey = "require_initial_post") + public Boolean getRequireInitialPost() { + return requireInitialPost; + } + + public void setRequireInitialPost(Boolean requireInitialPost) { + this.requireInitialPost = requireInitialPost; + } + + public Boolean getUserCanSeePosts() { + return userCanSeePosts; + } + + public void setUserCanSeePosts(Boolean userCanSeePosts) { + this.userCanSeePosts = userCanSeePosts; + } + + public Long getDiscussionSubentryCount() { + return discussionSubentryCount; + } + + public void setDiscussionSubentryCount(Long discussionSubentryCount) { + this.discussionSubentryCount = discussionSubentryCount; + } + + public String getReadState() { + return readState; + } + + public void setReadState(String readState) { + this.readState = readState; + } + + public Long getUnreadCount() { + return unreadCount; + } + + public void setUnreadCount(Long unreadCount) { + this.unreadCount = unreadCount; + } + + public Boolean getSubscribed() { + return subscribed; + } + + public void setSubscribed(Boolean subscribed) { + this.subscribed = subscribed; + } + + public String getSubscriptionHold() { + return subscriptionHold; + } + + public void setSubscriptionHold(String subscriptionHold) { + this.subscriptionHold = subscriptionHold; + } + + public Long getAssignmentId() { + return assignmentId; + } + + public void setAssignmentId(Long assignmentId) { + this.assignmentId = assignmentId; + } + + @CanvasField(postKey = "delayed_post_at") + public Date getDelayedPostAt() { + return delayedPostAt; + } + + public void setDelayedPostAt(Date delayedPostAt) { + this.delayedPostAt = delayedPostAt; + } + + public Boolean getPublished() { + return published; + } + + public void setPublished(Boolean published) { + this.published = published; + } + + @CanvasField(postKey = "lock_at") + public Date getLockAt() { + return lockAt; + } + + public void setLockAt(Date lockAt) { + this.lockAt = lockAt; + } + + @CanvasField(postKey = "locked") + public Boolean getLocked() { + return locked; + } + + public void setLocked(Boolean locked) { + this.locked = locked; + } + + public Boolean getPinned() { + return pinned; + } + + public void setPinned(Boolean pinned) { + this.pinned = pinned; + } + + public Boolean getLockedForUser() { + return lockedForUser; + } + + public void setLockedForUser(Boolean lockedForUser) { + this.lockedForUser = lockedForUser; + } + + public LockInfo getLockInfo() { + return lockInfo; + } + + public void setLockInfo(LockInfo lockInfo) { + this.lockInfo = lockInfo; + } + + public String getLockExplanation() { + return lockExplanation; + } + + public void setLockExplanation(String lockExplanation) { + this.lockExplanation = lockExplanation; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } - public Long[] getTopicChildren() { - return topicChildren; - } + public Long[] getTopicChildren() { + return topicChildren; + } - public void setTopicChildren(Long[] topicChildren) { - this.topicChildren = topicChildren; - } + public void setTopicChildren(Long[] topicChildren) { + this.topicChildren = topicChildren; + } - public TopicChildren[] getGroupTopicChildren() { - return groupTopicChildren; - } + public TopicChildren[] getGroupTopicChildren() { + return groupTopicChildren; + } - public void setGroupTopicChildren(TopicChildren[] groupTopicChildren) { - this.groupTopicChildren = groupTopicChildren; - } - - public Long getRootTopicId() { - return rootTopicId; - } - - public void setRootTopicId(Long rootTopicId) { - this.rootTopicId = rootTopicId; - } - - public String getPodcastURL() { - return podcastURL; - } - - public void setPodcastURL(String podcastURL) { - this.podcastURL = podcastURL; - } - - @CanvasField(postKey = "discussion_type") - public String getDiscussionType() { - return discussionType; - } - - public void setDiscussionType(String discussionType) { - this.discussionType = discussionType; - } - - public Long getGroupCategoryId() { - return groupCategoryId; - } - - public void setGroupCategoryId(Long groupCategoryId) { - this.groupCategoryId = groupCategoryId; - } - - @CanvasField(postKey = "attachments") - public File[] getAttachments() { - return attachments; - } + public void setGroupTopicChildren(TopicChildren[] groupTopicChildren) { + this.groupTopicChildren = groupTopicChildren; + } + + public Long getRootTopicId() { + return rootTopicId; + } + + public void setRootTopicId(Long rootTopicId) { + this.rootTopicId = rootTopicId; + } + + public String getPodcastURL() { + return podcastURL; + } + + public void setPodcastURL(String podcastURL) { + this.podcastURL = podcastURL; + } + + @CanvasField(postKey = "discussion_type") + public String getDiscussionType() { + return discussionType; + } + + public void setDiscussionType(String discussionType) { + this.discussionType = discussionType; + } + + public Long getGroupCategoryId() { + return groupCategoryId; + } + + public void setGroupCategoryId(Long groupCategoryId) { + this.groupCategoryId = groupCategoryId; + } + + @CanvasField(postKey = "attachments") + public File[] getAttachments() { + return attachments; + } - public void setAttachments(File[] attachments) { - this.attachments = attachments; - } + public void setAttachments(File[] attachments) { + this.attachments = attachments; + } - public DiscussionTopicPermission getPermissions() { - return permissions; - } + public DiscussionTopicPermission getPermissions() { + return permissions; + } - public void setPermissions(DiscussionTopicPermission permissions) { - this.permissions = permissions; - } + public void setPermissions(DiscussionTopicPermission permissions) { + this.permissions = permissions; + } - @CanvasField(postKey = "allow_rating") - public Boolean getAllowRating() { - return allowRating; - } + @CanvasField(postKey = "allow_rating") + public Boolean getAllowRating() { + return allowRating; + } - public void setAllowRating(Boolean allowRating) { - this.allowRating = allowRating; - } + public void setAllowRating(Boolean allowRating) { + this.allowRating = allowRating; + } - @CanvasField(postKey = "only_graders_can_rate") - public Boolean getOnlyGradersCanRate() { - return onlyGradersCanRate; - } + @CanvasField(postKey = "only_graders_can_rate") + public Boolean getOnlyGradersCanRate() { + return onlyGradersCanRate; + } - public void setOnlyGradersCanRate(Boolean onlyGradersCanRate) { - this.onlyGradersCanRate = onlyGradersCanRate; - } + public void setOnlyGradersCanRate(Boolean onlyGradersCanRate) { + this.onlyGradersCanRate = onlyGradersCanRate; + } - @CanvasField(postKey = "sort_by_rating") - public Boolean getSortByRating() { - return sortByRating; - } - - public void setSortByRating(Boolean sortByRating) { - this.sortByRating = sortByRating; - } - - public class TopicChildren implements Serializable { + @CanvasField(postKey = "sort_by_rating") + public Boolean getSortByRating() { + return sortByRating; + } + + public void setSortByRating(Boolean sortByRating) { + this.sortByRating = sortByRating; + } + + public class TopicChildren implements Serializable { - private static final long serialVersionUID = 1L; - - private String topicId; - private String groupId; + private static final long serialVersionUID = 1L; + + private String topicId; + private String groupId; - public String getTopicId() { - return topicId; - } + public String getTopicId() { + return topicId; + } - public void setTopicId(String topicId) { - this.topicId = topicId; - } + public void setTopicId(String topicId) { + this.topicId = topicId; + } - public String getGroupId() { - return groupId; - } + public String getGroupId() { + return groupId; + } - public void setGroupId(String groupId) { - this.groupId = groupId; - } - } + public void setGroupId(String groupId) { + this.groupId = groupId; + } + } } diff --git a/src/main/java/edu/ksu/canvas/model/discussion/DiscussionTopicPermission.java b/src/main/java/edu/ksu/canvas/model/discussion/DiscussionTopicPermission.java index b120eafd..946bdaed 100644 --- a/src/main/java/edu/ksu/canvas/model/discussion/DiscussionTopicPermission.java +++ b/src/main/java/edu/ksu/canvas/model/discussion/DiscussionTopicPermission.java @@ -4,10 +4,10 @@ public class DiscussionTopicPermission implements Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - private Boolean attach; + private Boolean attach; - public boolean canAttach() { return attach; } + public boolean canAttach() { return attach; } } From a6bcca8eb24f8f749168788b72912da8beff1121 Mon Sep 17 00:00:00 2001 From: Garrett Date: Wed, 25 Jan 2023 15:46:00 -0800 Subject: [PATCH 7/8] Revert gitignore file --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index ef410531..42e0cfd3 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,3 @@ rebel-remote.xml *.iml *.idea release.properties -/discussion_test/ From d0892297b1793df858b27bcbe68435049ca09781 Mon Sep 17 00:00:00 2001 From: Garrett Date: Wed, 25 Jan 2023 15:48:11 -0800 Subject: [PATCH 8/8] Revert changes made by a mistaken auto-refactor --- src/test/java/edu/ksu/canvas/BaseCanvasModelUTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/edu/ksu/canvas/BaseCanvasModelUTest.java b/src/test/java/edu/ksu/canvas/BaseCanvasModelUTest.java index b4e6bd23..0e3b0c06 100644 --- a/src/test/java/edu/ksu/canvas/BaseCanvasModelUTest.java +++ b/src/test/java/edu/ksu/canvas/BaseCanvasModelUTest.java @@ -13,7 +13,7 @@ import java.util.stream.Collectors; public class BaseCanvasModelUTest { - public static final String CLASS_POST_KEY = "com/canvacord/test"; + public static final String CLASS_POST_KEY = "test"; public static final String CLASS_POST_KEY_OVERRIDE = "override"; public static final String FIELD1_POST_KEY = "field1Key"; public static final String FIELD2_POST_KEY = "field2Key";