improved LMS Setup API

This commit is contained in:
anhefti 2021-03-15 13:34:22 +01:00
parent bbcbc318a9
commit 7f2b662244
6 changed files with 120 additions and 34 deletions

View file

@ -152,7 +152,7 @@ public interface LmsAPITemplate {
* @return Result refer to the given Exam if successful or to an error if not */
Result<Exam> releaseSEBClientRestriction(Exam exam);
/** This is used th verify if a given LMS Setup URL is available (valid)
/** This is used to verify if a given LMS Setup URL is available (valid)
*
* @param urlString the URL string given by the LMS Setup attribute
* @return true if SEB Server was able to ping the address. */

View file

@ -0,0 +1,26 @@
/*
* Copyright (c) 2021 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.lms;
import ch.ethz.seb.sebserver.gbl.client.ClientCredentials;
import ch.ethz.seb.sebserver.gbl.client.ProxyData;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
import ch.ethz.seb.sebserver.gbl.util.Result;
public interface LmsAPITemplateFactory {
LmsType lmsType();
Result<LmsAPITemplate> create(
final LmsSetup lmsSetup,
final ClientCredentials credentials,
final ProxyData proxyData);
}

View file

@ -9,10 +9,13 @@
package ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
@ -29,16 +32,15 @@ import ch.ethz.seb.sebserver.gbl.client.ProxyData;
import ch.ethz.seb.sebserver.gbl.model.Page;
import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.WebserviceInfo;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.LmsSetupDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.edx.OpenEdxLmsAPITemplateFactory;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleLmsAPITemplateFactory;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplateFactory;
@Lazy
@Service
@ -49,24 +51,23 @@ public class LmsAPIServiceImpl implements LmsAPIService {
private final LmsSetupDAO lmsSetupDAO;
private final ClientCredentialService clientCredentialService;
private final WebserviceInfo webserviceInfo;
private final OpenEdxLmsAPITemplateFactory openEdxLmsAPITemplateFactory;
private final MoodleLmsAPITemplateFactory moodleLmsAPITemplateFactory;
private final EnumMap<LmsType, LmsAPITemplateFactory> templateFactories;
private final Map<CacheKey, LmsAPITemplate> cache = new ConcurrentHashMap<>();
public LmsAPIServiceImpl(
final OpenEdxLmsAPITemplateFactory openEdxLmsAPITemplateFactory,
final MoodleLmsAPITemplateFactory moodleLmsAPITemplateFactory,
final LmsSetupDAO lmsSetupDAO,
final ClientCredentialService clientCredentialService,
final WebserviceInfo webserviceInfo) {
final Collection<LmsAPITemplateFactory> lmsAPITemplateFactories) {
this.openEdxLmsAPITemplateFactory = openEdxLmsAPITemplateFactory;
this.moodleLmsAPITemplateFactory = moodleLmsAPITemplateFactory;
this.lmsSetupDAO = lmsSetupDAO;
this.clientCredentialService = clientCredentialService;
this.webserviceInfo = webserviceInfo;
this.templateFactories = new EnumMap<>(lmsAPITemplateFactories
.stream()
.collect(Collectors.toMap(
t -> t.lmsType(),
Function.identity())));
}
/** Listen to LmsSetupChangeEvent to release an affected LmsAPITemplate from cache
@ -237,24 +238,13 @@ public class LmsAPIServiceImpl implements LmsAPIService {
final ClientCredentials credentials,
final ProxyData proxyData) {
switch (lmsSetup.lmsType) {
case MOCKUP:
return new MockupLmsAPITemplate(
lmsSetup,
credentials,
this.webserviceInfo);
case OPEN_EDX:
return this.openEdxLmsAPITemplateFactory
.create(lmsSetup, credentials, proxyData)
.getOrThrow();
case MOODLE:
return this.moodleLmsAPITemplateFactory
.create(lmsSetup, credentials, proxyData)
.getOrThrow();
default:
throw new UnsupportedOperationException("No support for LMS Type: " + lmsSetup.lmsType);
if (!this.templateFactories.containsKey(lmsSetup.lmsType)) {
throw new UnsupportedOperationException("No support for LMS Type: " + lmsSetup.lmsType);
}
final LmsAPITemplateFactory lmsAPITemplateFactory = this.templateFactories.get(lmsSetup.lmsType);
return lmsAPITemplateFactory.create(lmsSetup, credentials, proxyData)
.getOrThrow();
}
private static final class CacheKey {

View file

@ -0,0 +1,52 @@
/*
* Copyright (c) 2021 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import ch.ethz.seb.sebserver.gbl.client.ClientCredentials;
import ch.ethz.seb.sebserver.gbl.client.ProxyData;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.WebserviceInfo;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplateFactory;
@Lazy
@Service
@WebServiceProfile
public class MockLmsAPITemplateFactory implements LmsAPITemplateFactory {
private final WebserviceInfo webserviceInfo;
public MockLmsAPITemplateFactory(final WebserviceInfo webserviceInfo) {
this.webserviceInfo = webserviceInfo;
}
@Override
public LmsType lmsType() {
return LmsType.MOCKUP;
}
@Override
public Result<LmsAPITemplate> create(
final LmsSetup lmsSetup,
final ClientCredentials credentials,
final ProxyData proxyData) {
return Result.tryCatch(() -> new MockupLmsAPITemplate(
lmsSetup,
credentials,
this.webserviceInfo));
}
}

View file

@ -22,14 +22,17 @@ import ch.ethz.seb.sebserver.gbl.client.ClientCredentialService;
import ch.ethz.seb.sebserver.gbl.client.ClientCredentials;
import ch.ethz.seb.sebserver.gbl.client.ProxyData;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.WebserviceInfo;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplateFactory;
@Lazy
@Service
@WebServiceProfile
public class OpenEdxLmsAPITemplateFactory {
public class OpenEdxLmsAPITemplateFactory implements LmsAPITemplateFactory {
private final JSONMapper jsonMapper;
private final WebserviceInfo webserviceInfo;
@ -62,7 +65,13 @@ public class OpenEdxLmsAPITemplateFactory {
this.restrictionAPIPushCount = restrictionAPIPushCount;
}
public Result<OpenEdxLmsAPITemplate> create(
@Override
public LmsType lmsType() {
return LmsType.OPEN_EDX;
}
@Override
public Result<LmsAPITemplate> create(
final LmsSetup lmsSetup,
final ClientCredentials credentials,
final ProxyData proxyData) {

View file

@ -23,13 +23,16 @@ import ch.ethz.seb.sebserver.gbl.client.ClientCredentialService;
import ch.ethz.seb.sebserver.gbl.client.ClientCredentials;
import ch.ethz.seb.sebserver.gbl.client.ProxyData;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplateFactory;
@Lazy
@Service
@WebServiceProfile
public class MoodleLmsAPITemplateFactory {
public class MoodleLmsAPITemplateFactory implements LmsAPITemplateFactory {
private final JSONMapper jsonMapper;
private final AsyncService asyncService;
@ -59,7 +62,13 @@ public class MoodleLmsAPITemplateFactory {
: null;
}
public Result<MoodleLmsAPITemplate> create(
@Override
public LmsType lmsType() {
return LmsType.MOODLE;
}
@Override
public Result<LmsAPITemplate> create(
final LmsSetup lmsSetup,
final ClientCredentials credentials,
final ProxyData proxyData) {