Merge remote-tracking branch 'origin/patch-1.0.2' into development
Conflicts: src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ClientEventController.java fixes in Moodle LMS binding
This commit is contained in:
commit
3fd064055a
5 changed files with 23 additions and 24 deletions
|
@ -29,6 +29,14 @@ public interface ExamDAO extends ActivatableEntityDAO<Exam, Exam>, BulkActionSup
|
||||||
* @return Result referring to the GrantEntity of the exam or to an error when happened */
|
* @return Result referring to the GrantEntity of the exam or to an error when happened */
|
||||||
Result<GrantEntity> examGrantEntityByPK(final Long id);
|
Result<GrantEntity> examGrantEntityByPK(final Long id);
|
||||||
|
|
||||||
|
/** Get an Exam GrantEntity by a given ClientConnection id.
|
||||||
|
* This is actually a Exam instance but with no course data loaded.
|
||||||
|
*
|
||||||
|
* @param connectionId the connection identifier
|
||||||
|
* @return a Result containing the Exam GrantEntity by a given ClientConnection id or refer to an error if
|
||||||
|
* happened */
|
||||||
|
Result<GrantEntity> examGrantEntityByClientConnection(Long connectionId);
|
||||||
|
|
||||||
/** Get all active Exams for a given institution.
|
/** Get all active Exams for a given institution.
|
||||||
*
|
*
|
||||||
* @param institutionId the identifier of the institution
|
* @param institutionId the identifier of the institution
|
||||||
|
@ -56,12 +64,6 @@ public interface ExamDAO extends ActivatableEntityDAO<Exam, Exam>, BulkActionSup
|
||||||
key = "#exam.id")
|
key = "#exam.id")
|
||||||
Result<Exam> save(Exam exam);
|
Result<Exam> save(Exam exam);
|
||||||
|
|
||||||
/** Get an Exam by a given ClientConnection id.
|
|
||||||
*
|
|
||||||
* @param connectionId the connection identifier
|
|
||||||
* @return a Result containing the Exam by a given ClientConnection id or refer to an error if happened */
|
|
||||||
Result<Exam> byClientConnection(Long connectionId);
|
|
||||||
|
|
||||||
/** Use this to get identifiers of all exams in a specified state for a specified institution.
|
/** Use this to get identifiers of all exams in a specified state for a specified institution.
|
||||||
*
|
*
|
||||||
* @param institutionId the institution identifier. May be null for all institutions
|
* @param institutionId the institution identifier. May be null for all institutions
|
||||||
|
|
|
@ -94,12 +94,11 @@ public class ExamDAOImpl implements ExamDAO {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public Result<Exam> byClientConnection(final Long connectionId) {
|
public Result<GrantEntity> examGrantEntityByClientConnection(final Long connectionId) {
|
||||||
return Result.tryCatch(() -> this.clientConnectionRecordMapper
|
return Result.tryCatch(() -> this.clientConnectionRecordMapper
|
||||||
.selectByPrimaryKey(connectionId))
|
.selectByPrimaryKey(connectionId))
|
||||||
.flatMap(ccRecord -> recordById(ccRecord.getExamId()))
|
.flatMap(ccRecord -> recordById(ccRecord.getExamId()))
|
||||||
.flatMap(this::toDomainModelCached)
|
.map(record -> toDomainModel(record, null).getOrThrow());
|
||||||
.onError(TransactionHandler::rollback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -708,14 +707,6 @@ public class ExamDAOImpl implements ExamDAO {
|
||||||
exam.getDescription());
|
exam.getDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Result<Exam> toDomainModelCached(final ExamRecord record) {
|
|
||||||
return Result.tryCatch(() -> this.lmsAPIService
|
|
||||||
.getLmsAPITemplate(record.getLmsSetupId())
|
|
||||||
.getOrThrow())
|
|
||||||
.flatMap(template -> template.getQuizFromCache(record.getExternalId()))
|
|
||||||
.flatMap(quizData -> this.toDomainModel(record, quizData));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Result<Exam> toDomainModel(final ExamRecord record) {
|
private Result<Exam> toDomainModel(final ExamRecord record) {
|
||||||
return toDomainModel(
|
return toDomainModel(
|
||||||
record.getLmsSetupId(),
|
record.getLmsSetupId(),
|
||||||
|
|
|
@ -18,7 +18,6 @@ import java.util.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.coyote.http11.Constants;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.util.LinkedMultiValueMap;
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
|
@ -29,6 +28,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
|
||||||
|
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
|
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
|
||||||
import ch.ethz.seb.sebserver.gbl.async.AsyncService;
|
import ch.ethz.seb.sebserver.gbl.async.AsyncService;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.Chapters;
|
import ch.ethz.seb.sebserver.gbl.model.exam.Chapters;
|
||||||
|
@ -48,7 +48,7 @@ public class MoodleCourseAccess extends CourseAccess {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(MoodleCourseAccess.class);
|
private static final Logger log = LoggerFactory.getLogger(MoodleCourseAccess.class);
|
||||||
|
|
||||||
private static final String MOODLE_QUIZ_START_URL_PATH = "mod/quiz/view.php?id=";
|
private static final String MOODLE_QUIZ_START_URL_PATH = "mod/quiz/view.php?q=";
|
||||||
private static final String MOODLE_COURSE_API_FUNCTION_NAME = "core_course_get_courses";
|
private static final String MOODLE_COURSE_API_FUNCTION_NAME = "core_course_get_courses";
|
||||||
private static final String MOODLE_USER_PROFILE_API_FUNCTION_NAME = "core_user_get_users_by_field";
|
private static final String MOODLE_USER_PROFILE_API_FUNCTION_NAME = "core_user_get_users_by_field";
|
||||||
private static final String MOODLE_QUIZ_API_FUNCTION_NAME = "mod_quiz_get_quizzes_by_courses";
|
private static final String MOODLE_QUIZ_API_FUNCTION_NAME = "mod_quiz_get_quizzes_by_courses";
|
||||||
|
@ -161,7 +161,9 @@ public class MoodleCourseAccess extends CourseAccess {
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayList<QuizData> collectAllQuizzes(final MoodleAPIRestTemplate restTemplate) {
|
private ArrayList<QuizData> collectAllQuizzes(final MoodleAPIRestTemplate restTemplate) {
|
||||||
final String urlPrefix = this.lmsSetup.lmsApiUrl + MOODLE_QUIZ_START_URL_PATH;
|
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 collectAllCourses(restTemplate)
|
return collectAllCourses(restTemplate)
|
||||||
.stream()
|
.stream()
|
||||||
.reduce(
|
.reduce(
|
||||||
|
@ -239,7 +241,7 @@ public class MoodleCourseAccess extends CourseAccess {
|
||||||
final List<QuizData> courseAndQuiz = courseData.quizzes
|
final List<QuizData> courseAndQuiz = courseData.quizzes
|
||||||
.stream()
|
.stream()
|
||||||
.map(courseQuizData -> {
|
.map(courseQuizData -> {
|
||||||
final String startURI = uriPrefix + courseQuizData.course_module;
|
final String startURI = uriPrefix + courseQuizData.id;
|
||||||
additionalAttrs.put(QuizData.ATTR_ADDITIONAL_TIME_LIMIT, String.valueOf(courseQuizData.time_limit));
|
additionalAttrs.put(QuizData.ATTR_ADDITIONAL_TIME_LIMIT, String.valueOf(courseQuizData.time_limit));
|
||||||
return new QuizData(
|
return new QuizData(
|
||||||
getInternalQuizId(courseQuizData.id, courseData.short_name, courseData.idnumber),
|
getInternalQuizId(courseQuizData.id, courseData.short_name, courseData.idnumber),
|
||||||
|
|
|
@ -244,9 +244,13 @@ public class ExamSessionServiceImpl implements ExamSessionService {
|
||||||
.putIfAbsent(Exam.FILTER_ATTR_ACTIVE, Constants.TRUE_STRING)
|
.putIfAbsent(Exam.FILTER_ATTR_ACTIVE, Constants.TRUE_STRING)
|
||||||
.putIfAbsent(Exam.FILTER_ATTR_STATUS, ExamStatus.RUNNING.name());
|
.putIfAbsent(Exam.FILTER_ATTR_STATUS, ExamStatus.RUNNING.name());
|
||||||
|
|
||||||
|
// NOTE: we evict the exam from the cache (if present) to ensure user is seeing always the current state of the Exam
|
||||||
return this.examDAO.allMatching(filterMap, predicate)
|
return this.examDAO.allMatching(filterMap, predicate)
|
||||||
.map(col -> col.stream()
|
.map(col -> col.stream()
|
||||||
.map(exam -> this.examSessionCacheService.getRunningExam(exam.id))
|
.map(exam -> {
|
||||||
|
this.examSessionCacheService.evict(exam);
|
||||||
|
return this.examSessionCacheService.getRunningExam(exam.id);
|
||||||
|
})
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.collect(Collectors.toList()));
|
.collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,7 +205,7 @@ public class ClientEventController extends ReadonlyEntityController<ClientEvent,
|
||||||
@Override
|
@Override
|
||||||
protected GrantEntity toGrantEntity(final ClientEvent entity) {
|
protected GrantEntity toGrantEntity(final ClientEvent entity) {
|
||||||
return this.examDao
|
return this.examDao
|
||||||
.byPK(entity.connectionId)
|
.examGrantEntityByClientConnection(entity.connectionId)
|
||||||
.get();
|
.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue