API documentation

This commit is contained in:
anhefti 2021-05-11 21:07:57 +02:00
parent 10fd2f408d
commit 70fcbead41
2 changed files with 49 additions and 44 deletions

View file

@ -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<Result<QuizData>> getQuizzesFromCache(Set<String> 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<ExamineeAccountDetails> 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<Chapters> 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<SEBRestriction> 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<SEBRestriction> 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<Exam> releaseSEBClientRestriction(Exam exam);

View file

@ -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<QuizData> 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<QuizData> reduceCoursesToQuizzes(
final String urlPrefix,
final Collection<CourseDataShort> courseQuizData) {
return courseQuizData
.stream()
.reduce(
@ -465,14 +459,12 @@ public class MoodleCourseAccess extends CourseAccess {
}
}
static Map<String, String> additionalAttrs = new HashMap<>();
private List<QuizData> quizDataOf(
final LmsSetup lmsSetup,
final CourseData courseData,
final String uriPrefix) {
additionalAttrs.clear();
final Map<String, String> 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<String, String> 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);