From 70fcbead41432602c6bdf2d3340f7d3051279089 Mon Sep 17 00:00:00 2001 From: anhefti Date: Tue, 11 May 2021 21:07:57 +0200 Subject: [PATCH] API documentation --- .../servicelayer/lms/LmsAPITemplate.java | 63 +++++++++++-------- .../lms/impl/moodle/MoodleCourseAccess.java | 30 ++++----- 2 files changed, 49 insertions(+), 44 deletions(-) diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPITemplate.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPITemplate.java index b78c5124..2b556db4 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPITemplate.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPITemplate.java @@ -28,13 +28,23 @@ import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ResourceNotFoundException; -/** Defines the interface to an LMS within a specified LMSSetup configuration. - * There is one concrete implementations for every supported type of LMS like - * Open edX or Moodle +/** Defines an LMS API access template to build SEB Server LMS integration. * - * A LmsAPITemplate defines at least the core API access to query courses and quizzes from the LMS - * Later a concrete LmsAPITemplate may also implement some special features regarding to the type - * of the LMS */ + * A LMS integration consists of two main parts so far: + * - The course API to search and request course data from LMS as well as resolve some LMS account details for a given + * examineeId + * - The SEB restriction API to apply SEB restriction data to the LMS to restrict a certain course for SEB + * + * A LmsAPITemplate is been constructed within a LmsSetup that defines the LMS setup data that is needed to connect to + * a specific LMS instance of implemented type. + * + * The enum LmsSetup.LmsType defines the supported LMS types and for each type the supported API part(s). + * + * SEB Server uses the test functions that are defined for each LMS API part to test API access for a certain LMS + * instance respectively the underling LMSSetup. Concrete implementations can do various tests to check full + * or partial API Access and can flag missing or wrong LMSSetup attributes with the resulting LmsSetupTestResult. + * + * SEB Server than uses an instance of this template to communicate with the an LMS. */ public interface LmsAPITemplate { /** Get the underling LMSSetup configuration for this LmsAPITemplate @@ -56,7 +66,7 @@ public interface LmsAPITemplate { * @return LmsSetupTestResult instance with the test result report */ LmsSetupTestResult testCourseRestrictionAPI(); - /** Get a Result of an unsorted List of filtered QuizData from the LMS course/quiz API + /** Get an unsorted List of filtered QuizData from the LMS course/quiz API * * @param filterMap the FilterMap to get a filtered result. For possible filter attributes * see documentation on QuizData @@ -89,32 +99,35 @@ public interface LmsAPITemplate { .orElse(Result.ofError(new ResourceNotFoundException(EntityType.EXAM, id))); } - /** Get all QuizData for the set of QuizData identifiers from LMS API in a collection - * of Result. If particular Quiz cannot be loaded because of errors or deletion, - * the Result will have an error reference. + /** Get all QuizData for the set of QuizData-identifiers (ids) from the LMS defined within the + * underling LMSSetup, in a collection of Results. * - * NOTE: This method looks first in the cache if existing for all given ids. + * If there is caching involved this function shall try to get the data from the cache first. + * + * NOTE: This function depends on the specific LMS implementation and on whether caching the quiz data + * makes sense or not. Following strategy is recommended: + * Looks first in the cache if the whole set of QuizData can be get from the cache. * If all quizzes are cached, returns all from cache. - * If one quiz is not in the cache, requests all quizzes from the API and refreshes the cache + * If one or more quiz is not in the cache, requests all quizzes from the API and refreshes the cache * * @param ids the Set of Quiz identifiers to get the QuizData for * @return Collection of all QuizData from the given id set */ Collection> getQuizzesFromCache(Set ids); - /** Convert a an anonymous or temporary user session identifier from SEB Client into a user - * account details. + /** Convert an anonymous or temporary examineeUserId, sent by the SEB Client on LMS login, + * to LMS examinee account details by requesting them on the LMS API with the given examineeUserId * - * @param examineeUserId the user-account identifier derived from SEB Client + * @param examineeUserId the examinee user identifier derived from SEB Client * @return a Result refer to the ExamineeAccountDetails instance or to an error when happened or not supported */ Result getExamineeAccountDetails(String examineeUserId); - /** Used to convert an anonymous or temporary user session identifier from SEB Client into a user - * account name for displaying on monitoring page. + /** Used to convert an anonymous or temporary examineeUserId, sent by the SEB Client on LMS login, + * to a readable LMS examinee account name by requesting this on the LMS API with the given examineeUserId. * * If the underling concrete template implementation does not support this user name conversion, * the given examineeSessionId shall be returned. * - * @param examineeUserId the user-account identifier derived from SEB Client + * @param examineeUserId the examinee user identifier derived from SEB Client * @return a user account display name if supported or the given examineeSessionId if not. */ String getExamineeName(String examineeUserId); @@ -129,18 +142,18 @@ public interface LmsAPITemplate { * @return Result referencing to the Chapters model for the given course or to an error when happened. */ Result getCourseChapters(String courseId); - /** Get SEB restriction data form LMS within a SEBRestrictionData instance if available - * or a ResourceNotFoundException if not yet available or restricted + /** Get SEB restriction data form LMS within a SEBRestrictionData instance. The available restriction details + * depends on the type of LMS but shall at least contains the config-key(s) and the browser-exam-key(s). * * @param exam the exam to get the SEB restriction data for - * @return Result refer to the SEBRestrictionData instance or to an ResourceNotFoundException if restriction is + * @return Result refer to the SEBRestrictionData instance or to an ResourceNotFoundException if the restriction is * missing or to another exception on unexpected error case */ Result getSEBClientRestriction(Exam exam); - /** Applies a SEB Client restriction within the LMS with the given attributes. + /** Applies SEB Client restrictions to the LMS with the given attributes. * - * @param externalExamId The exam identifier from LMS side (Exam.externalId) - * @param sebRestrictionData containing all data for SEB Client restriction + * @param externalExamId The exam/course identifier from LMS side (Exam.externalId) + * @param sebRestrictionData containing all data for SEB Client restriction to apply to the LMS * @return Result refer to the given SEBRestrictionData if restriction was successful or to an error if not */ Result applySEBClientRestriction( String externalExamId, @@ -149,7 +162,7 @@ public interface LmsAPITemplate { /** Releases an already applied SEB Client restriction within the LMS for a given Exam. * This completely removes the SEB Client restriction on LMS side. * - * @param exam the Exam to release the restriction for + * @param exam the Exam to release the restriction for. * @return Result refer to the given Exam if successful or to an error if not */ Result releaseSEBClientRestriction(Exam exam); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleCourseAccess.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleCourseAccess.java index 375557ac..9da7f83e 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleCourseAccess.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleCourseAccess.java @@ -296,21 +296,7 @@ public class MoodleCourseAccess extends CourseAccess { return Collections.emptyList(); } - return courseQuizData - .stream() - .reduce( - new ArrayList<>(), - (list, courseData) -> { - list.addAll(quizDataOf( - this.lmsSetup, - courseData, - urlPrefix)); - return list; - }, - (list1, list2) -> { - list1.addAll(list2); - return list1; - }); + return reduceCoursesToQuizzes(urlPrefix, courseQuizData); } private List getCached() { @@ -319,6 +305,14 @@ public class MoodleCourseAccess extends CourseAccess { final String urlPrefix = (this.lmsSetup.lmsApiUrl.endsWith(Constants.URL_PATH_SEPARATOR)) ? this.lmsSetup.lmsApiUrl + MOODLE_QUIZ_START_URL_PATH : this.lmsSetup.lmsApiUrl + Constants.URL_PATH_SEPARATOR + MOODLE_QUIZ_START_URL_PATH; + + return reduceCoursesToQuizzes(urlPrefix, courseQuizData); + } + + private ArrayList reduceCoursesToQuizzes( + final String urlPrefix, + final Collection courseQuizData) { + return courseQuizData .stream() .reduce( @@ -465,14 +459,12 @@ public class MoodleCourseAccess extends CourseAccess { } } - static Map additionalAttrs = new HashMap<>(); - private List quizDataOf( final LmsSetup lmsSetup, final CourseData courseData, final String uriPrefix) { - additionalAttrs.clear(); + final Map additionalAttrs = new HashMap<>(); additionalAttrs.put(QuizData.ATTR_ADDITIONAL_CREATION_TIME, String.valueOf(courseData.time_created)); additionalAttrs.put(QuizData.ATTR_ADDITIONAL_SHORT_NAME, courseData.short_name); additionalAttrs.put(QuizData.ATTR_ADDITIONAL_ID_NUMBER, courseData.idnumber); @@ -515,7 +507,7 @@ public class MoodleCourseAccess extends CourseAccess { final CourseDataShort courseData, final String uriPrefix) { - additionalAttrs.clear(); + final Map additionalAttrs = new HashMap<>(); additionalAttrs.put(QuizData.ATTR_ADDITIONAL_CREATION_TIME, String.valueOf(courseData.time_created)); additionalAttrs.put(QuizData.ATTR_ADDITIONAL_SHORT_NAME, courseData.short_name); additionalAttrs.put(QuizData.ATTR_ADDITIONAL_ID_NUMBER, courseData.idnumber);