From a279d5c18aeb224325cb438183b01a53b2e3236e Mon Sep 17 00:00:00 2001 From: srosse <none@none> Date: Thu, 23 Jul 2015 17:13:34 +0200 Subject: [PATCH] OO-1593: link qti 2.1 session to assessment entry --- .../course/assessment/AssessmentManager.java | 6 +- .../manager/CourseAssessmentManagerImpl.java | 61 +++++++------- .../course/nodes/AssessableCourseNode.java | 3 + .../olat/course/nodes/BasicLTICourseNode.java | 27 +++--- .../course/nodes/CheckListCourseNode.java | 29 +++++-- .../org/olat/course/nodes/GTACourseNode.java | 26 ++++-- .../olat/course/nodes/IQTESTCourseNode.java | 28 +++++-- .../org/olat/course/nodes/MSCourseNode.java | 38 +++++---- .../course/nodes/PortfolioCourseNode.java | 50 ++++++++--- .../course/nodes/ProjectBrokerCourseNode.java | 35 ++++---- .../org/olat/course/nodes/STCourseNode.java | 13 ++- .../olat/course/nodes/ScormCourseNode.java | 34 ++++++-- .../org/olat/course/nodes/TACourseNode.java | 31 ++++--- .../course/nodes/cp/CPEditController.java | 2 +- .../olat/course/nodes/iq/IQRunController.java | 29 +++---- .../nodes/ta/ConvertToGTACourseNode.java | 8 +- .../run/preview/PreviewAssessmentManager.java | 7 +- .../java/org/olat/ims/qti21/QTI21Service.java | 7 +- .../ims/qti21/manager/QTI21ServiceImpl.java | 11 ++- .../olat/ims/qti21/manager/SessionDAO.java | 40 +++++---- .../qti21/model/jpa/UserTestSessionImpl.java | 42 ++++++---- .../handlers/QTI21AssessmentTestHandler.java | 4 +- .../ui/AssessmentItemDisplayController.java | 6 +- .../ui/AssessmentTestDisplayController.java | 21 +++-- .../qti21/ui/InMemoryOutcomesListener.java | 12 +-- .../AssessmentItemEditorController.java | 8 +- .../modules/assessment/AssessmentService.java | 32 +++++++ .../manager/AssessmentEntryDAO.java | 60 +++++++++++-- .../manager/AssessmentServiceImpl.java | 84 +++++++++++++++++++ .../assessment/model/AssessmentEntryImpl.java | 12 ++- .../database/mysql/alter_10_x_0_to_11_0_0.sql | 49 +++++------ .../database/mysql/setupDatabase.sql | 10 ++- .../postgresql/alter_10_x_0_to_11_0_0.sql | 54 ++++++------ .../database/postgresql/setupDatabase.sql | 14 ++-- .../ims/qti21/manager/SessionDAOTest.java | 40 ++++++++- 35 files changed, 653 insertions(+), 280 deletions(-) create mode 100644 src/main/java/org/olat/modules/assessment/manager/AssessmentServiceImpl.java diff --git a/src/main/java/org/olat/course/assessment/AssessmentManager.java b/src/main/java/org/olat/course/assessment/AssessmentManager.java index 3a01ddc8098..5b90736b22a 100644 --- a/src/main/java/org/olat/course/assessment/AssessmentManager.java +++ b/src/main/java/org/olat/course/assessment/AssessmentManager.java @@ -210,6 +210,10 @@ public interface AssessmentManager { * set to not fully assessed, null if no info is available */ public Boolean getNodeFullyAssessed(CourseNode courseNode, Identity identity); + + + public AssessmentEntry getAssessmentEntry(CourseNode courseNode, Identity assessedIdentity, String referenceSoftKey); - public List<AssessmentEntry> getAssessmentData(CourseNode courseNode); + public List<AssessmentEntry> getAssessmentEntries(CourseNode courseNode); + } \ No newline at end of file diff --git a/src/main/java/org/olat/course/assessment/manager/CourseAssessmentManagerImpl.java b/src/main/java/org/olat/course/assessment/manager/CourseAssessmentManagerImpl.java index 2dc48da9ec9..e8d6d50cd47 100644 --- a/src/main/java/org/olat/course/assessment/manager/CourseAssessmentManagerImpl.java +++ b/src/main/java/org/olat/course/assessment/manager/CourseAssessmentManagerImpl.java @@ -48,7 +48,7 @@ import org.olat.course.nodes.CourseNode; import org.olat.course.run.scoring.ScoreEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; import org.olat.modules.assessment.AssessmentEntry; -import org.olat.modules.assessment.manager.AssessmentEntryDAO; +import org.olat.modules.assessment.AssessmentService; import org.olat.repository.RepositoryEntry; import org.olat.util.logging.activity.LoggingResourceable; @@ -64,31 +64,29 @@ public class CourseAssessmentManagerImpl implements AssessmentManager { private static final Integer INTEGER_ZERO = new Integer(0); private final RepositoryEntry courseEntry; + private final AssessmentService assessmentService; private final CertificatesManager certificatesManager; - private final AssessmentEntryDAO courseNodeAssessmentDao; private final EfficiencyStatementManager efficiencyStatementManager; public CourseAssessmentManagerImpl(RepositoryEntry courseEntry) { this.courseEntry = courseEntry; + assessmentService = CoreSpringFactory.getImpl(AssessmentService.class); certificatesManager = CoreSpringFactory.getImpl(CertificatesManager.class); - courseNodeAssessmentDao = CoreSpringFactory.getImpl(AssessmentEntryDAO.class); efficiencyStatementManager = CoreSpringFactory.getImpl(EfficiencyStatementManager.class); } private AssessmentEntry getOrCreate(Identity assessedIdentity, CourseNode courseNode) { - AssessmentEntry nodeAssessment = courseNodeAssessmentDao - .loadAssessmentEntry(assessedIdentity, courseEntry, courseNode.getIdent()); - if(nodeAssessment == null) { - nodeAssessment = courseNodeAssessmentDao - .createCourseNodeAssessment(assessedIdentity, courseEntry, - courseNode.getIdent(), courseNode.getReferencedRepositoryEntry()); - } - return nodeAssessment; + return assessmentService.getOrCreateAssessmentEntry(assessedIdentity, courseEntry, courseNode.getIdent(), courseNode.getReferencedRepositoryEntry()); } @Override - public List<AssessmentEntry> getAssessmentData(CourseNode courseNode) { - return courseNodeAssessmentDao.loadAssessmentEntryBySubIdent(courseEntry, courseNode.getIdent()); + public List<AssessmentEntry> getAssessmentEntries(CourseNode courseNode) { + return assessmentService.loadAssessmentEntriesBySubIdent(courseEntry, courseNode.getIdent()); + } + + @Override + public AssessmentEntry getAssessmentEntry(CourseNode courseNode, Identity assessedIdentity, String referenceSoftKey) { + return assessmentService.loadAssessmentEntry(assessedIdentity, courseEntry, courseNode.getIdent(), referenceSoftKey); } @Override @@ -97,7 +95,7 @@ public class CourseAssessmentManagerImpl implements AssessmentManager { AssessmentEntry nodeAssessment = getOrCreate(assessedIdentity, courseNode); nodeAssessment.setAttempts(attempts); - courseNodeAssessmentDao.updateCourseNodeAssessment(nodeAssessment); + assessmentService.updateAssessmentEntry(nodeAssessment); //node log UserNodeAuditManager am = course.getCourseEnvironment().getAuditManager(); @@ -120,7 +118,7 @@ public class CourseAssessmentManagerImpl implements AssessmentManager { AssessmentEntry nodeAssessment = getOrCreate(assessedIdentity, courseNode); nodeAssessment.setComment(comment); - courseNodeAssessmentDao.updateCourseNodeAssessment(nodeAssessment); + assessmentService.updateAssessmentEntry(nodeAssessment); // node log UserNodeAuditManager am = course.getCourseEnvironment().getAuditManager(); @@ -143,7 +141,7 @@ public class CourseAssessmentManagerImpl implements AssessmentManager { AssessmentEntry nodeAssessment = getOrCreate(assessedIdentity, courseNode); nodeAssessment.setCoachComment(comment); - courseNodeAssessmentDao.updateCourseNodeAssessment(nodeAssessment); + assessmentService.updateAssessmentEntry(nodeAssessment); // notify about changes AssessmentChangedEvent ace = new AssessmentChangedEvent(AssessmentChangedEvent.TYPE_COACH_COMMENT_CHANGED, assessedIdentity); @@ -163,7 +161,7 @@ public class CourseAssessmentManagerImpl implements AssessmentManager { AssessmentEntry nodeAssessment = getOrCreate(assessedIdentity, courseNode); int attempts = nodeAssessment.getAttempts() == null ? 1 :nodeAssessment.getAttempts().intValue() + 1; nodeAssessment.setAttempts(attempts); - courseNodeAssessmentDao.updateCourseNodeAssessment(nodeAssessment); + assessmentService.updateAssessmentEntry(nodeAssessment); if(courseNode instanceof AssessableCourseNode) { // Update users efficiency statement efficiencyStatementManager.updateUserEfficiencyStatement(userCourseEnv); @@ -187,7 +185,7 @@ public class CourseAssessmentManagerImpl implements AssessmentManager { AssessmentEntry nodeAssessment = getOrCreate(assessedIdentity, courseNode); int attempts = nodeAssessment.getAttempts() == null ? 1 :nodeAssessment.getAttempts().intValue() + 1; nodeAssessment.setAttempts(attempts); - courseNodeAssessmentDao.updateCourseNodeAssessment(nodeAssessment); + assessmentService.updateAssessmentEntry(nodeAssessment); if(courseNode instanceof AssessableCourseNode) { // Update users efficiency statement efficiencyStatementManager.updateUserEfficiencyStatement(userCourseEnv); @@ -221,7 +219,7 @@ public class CourseAssessmentManagerImpl implements AssessmentManager { int attempts = nodeAssessment.getAttempts() == null ? 1 :nodeAssessment.getAttempts().intValue() + 1; nodeAssessment.setAttempts(attempts); } - nodeAssessment = courseNodeAssessmentDao.updateCourseNodeAssessment(nodeAssessment); + nodeAssessment = assessmentService.updateAssessmentEntry(nodeAssessment); if(courseNode instanceof AssessableCourseNode) { @@ -249,26 +247,25 @@ public class CourseAssessmentManagerImpl implements AssessmentManager { return FLOAT_ZERO; // return default value } - AssessmentEntry nodeAssessment = courseNodeAssessmentDao - .loadAssessmentEntry(identity, courseEntry, courseNode.getIdent()); - if(nodeAssessment != null && nodeAssessment.getScore() != null) { - return nodeAssessment.getScore().floatValue(); + AssessmentEntry entry = assessmentService.loadAssessmentEntry(identity, courseEntry, courseNode.getIdent()); + if(entry != null && entry.getScore() != null) { + return entry.getScore().floatValue(); } return FLOAT_ZERO; } @Override public String getNodeComment(CourseNode courseNode, Identity identity) { - AssessmentEntry nodeAssessment = courseNodeAssessmentDao + AssessmentEntry entry = assessmentService .loadAssessmentEntry(identity, courseEntry, courseNode.getIdent()); - return nodeAssessment == null ? null : nodeAssessment.getComment(); + return entry == null ? null : entry.getComment(); } @Override public String getNodeCoachComment(CourseNode courseNode, Identity identity) { - AssessmentEntry nodeAssessment = courseNodeAssessmentDao + AssessmentEntry entry = assessmentService .loadAssessmentEntry(identity, courseEntry, courseNode.getIdent()); - return nodeAssessment == null ? null : nodeAssessment.getCoachComment(); + return entry == null ? null : entry.getCoachComment(); } @Override @@ -277,7 +274,7 @@ public class CourseAssessmentManagerImpl implements AssessmentManager { return Boolean.FALSE; // return default value } - AssessmentEntry nodeAssessment = courseNodeAssessmentDao + AssessmentEntry nodeAssessment = assessmentService .loadAssessmentEntry(identity, courseEntry, courseNode.getIdent()); return nodeAssessment == null ? null : nodeAssessment.getPassed(); } @@ -286,14 +283,14 @@ public class CourseAssessmentManagerImpl implements AssessmentManager { public Integer getNodeAttempts(CourseNode courseNode, Identity identity) { if(courseNode == null) return INTEGER_ZERO; - AssessmentEntry nodeAssessment = courseNodeAssessmentDao + AssessmentEntry nodeAssessment = assessmentService .loadAssessmentEntry(identity, courseEntry, courseNode.getIdent()); return nodeAssessment == null ? INTEGER_ZERO : nodeAssessment.getAttempts(); } @Override public Long getAssessmentID(CourseNode courseNode, Identity identity) { - AssessmentEntry nodeAssessment = courseNodeAssessmentDao + AssessmentEntry nodeAssessment = assessmentService .loadAssessmentEntry(identity, courseEntry, courseNode.getIdent()); return nodeAssessment == null ? null : nodeAssessment.getAssessmentId(); } @@ -301,14 +298,14 @@ public class CourseAssessmentManagerImpl implements AssessmentManager { @Override public Date getScoreLastModifiedDate(CourseNode courseNode, Identity identity) { if(courseNode == null) return null; - AssessmentEntry nodeAssessment = courseNodeAssessmentDao + AssessmentEntry nodeAssessment = assessmentService .loadAssessmentEntry(identity, courseEntry, courseNode.getIdent()); return nodeAssessment == null ? null : nodeAssessment.getLastModified(); } @Override public Boolean getNodeFullyAssessed(CourseNode courseNode, Identity identity) { - AssessmentEntry nodeAssessment = courseNodeAssessmentDao + AssessmentEntry nodeAssessment = assessmentService .loadAssessmentEntry(identity, courseEntry, courseNode.getIdent()); return nodeAssessment == null ? null : nodeAssessment.getFullyAssessed(); } diff --git a/src/main/java/org/olat/course/nodes/AssessableCourseNode.java b/src/main/java/org/olat/course/nodes/AssessableCourseNode.java index 9a9f8c4d317..be049f12b01 100644 --- a/src/main/java/org/olat/course/nodes/AssessableCourseNode.java +++ b/src/main/java/org/olat/course/nodes/AssessableCourseNode.java @@ -36,6 +36,7 @@ import org.olat.core.id.Identity; import org.olat.course.run.environment.CourseEnvironment; import org.olat.course.run.scoring.ScoreEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; +import org.olat.modules.assessment.AssessmentEntry; /** @@ -109,6 +110,8 @@ public interface AssessableCourseNode extends CourseNode { * @return null, if this node cannot deliver any useful scoring info (this is not the case for a test never tried or manual scoring: those have default values 0.0f / false for score/passed; currently only the STNode returns null if there are no scoring rules defined.) */ public ScoreEvaluation getUserScoreEvaluation(UserCourseEnvironment userCourseEnv); + + public AssessmentEntry getUserAssessmentEntry(UserCourseEnvironment userCourseEnv); /** * @param userCourseEnvironment diff --git a/src/main/java/org/olat/course/nodes/BasicLTICourseNode.java b/src/main/java/org/olat/course/nodes/BasicLTICourseNode.java index 127c1fba499..ba15d39c3d9 100644 --- a/src/main/java/org/olat/course/nodes/BasicLTICourseNode.java +++ b/src/main/java/org/olat/course/nodes/BasicLTICourseNode.java @@ -51,6 +51,7 @@ import org.olat.course.run.userview.NodeEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; import org.olat.ims.lti.ui.LTIResultDetailsController; import org.olat.modules.ModuleConfiguration; +import org.olat.modules.assessment.AssessmentEntry; import org.olat.repository.RepositoryEntry; import org.olat.resource.OLATResource; @@ -61,6 +62,7 @@ import org.olat.resource.OLATResource; public class BasicLTICourseNode extends AbstractAccessableCourseNode implements AssessableCourseNode { private static final long serialVersionUID = 2210572148308757127L; + private static final String translatorStr = Util.getPackageName(LTIEditController.class); private static final String TYPE = "lti"; public static final String CONFIG_KEY_AUTHORROLE = "authorRole"; @@ -144,8 +146,7 @@ public class BasicLTICourseNode extends AbstractAccessableCourseNode implements if (!isValid) { // FIXME: refine statusdescriptions String[] params = new String[] { this.getShortTitle() }; - String translPackage = Util.getPackageName(LTIConfigForm.class); - sd = new StatusDescription(StatusDescription.ERROR, NLS_ERROR_HOSTMISSING_SHORT, NLS_ERROR_HOSTMISSING_LONG, params, translPackage); + sd = new StatusDescription(StatusDescription.ERROR, NLS_ERROR_HOSTMISSING_SHORT, NLS_ERROR_HOSTMISSING_LONG, params, translatorStr); sd.setDescriptionForUnit(getIdent()); // set which pane is affected by error sd.setActivateableViewIdentifier(LTIEditController.PANE_TAB_LTCONFIG); @@ -161,7 +162,6 @@ public class BasicLTICourseNode extends AbstractAccessableCourseNode implements oneClickStatusCache = null; // only here we know which translator to take for translating condition // error messages - String translatorStr = Util.getPackageName(LTIEditController.class); List<StatusDescription> sds = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions()); oneClickStatusCache = StatusDescriptionHelper.sort(sds); return oneClickStatusCache; @@ -289,6 +289,12 @@ public class BasicLTICourseNode extends AbstractAccessableCourseNode implements Boolean score = config.getBooleanEntry(CONFIG_KEY_HAS_SCORE_FIELD); return (score == null) ? false : score.booleanValue(); } + + @Override + public AssessmentEntry getUserAssessmentEntry(UserCourseEnvironment userCourseEnv) { + AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager(); + return am.getAssessmentEntry(this, userCourseEnv.getIdentityEnvironment().getIdentity(), null); + } @Override public ScoreEvaluation getUserScoreEvaluation(UserCourseEnvironment userCourseEnv) { @@ -301,24 +307,21 @@ public class BasicLTICourseNode extends AbstractAccessableCourseNode implements if (hasPassedConfigured()) passed = am.getNodePassed(this, mySelf); if (hasScoreConfigured()) score = am.getNodeScore(this, mySelf); - ScoreEvaluation se = new ScoreEvaluation(score, passed); - return se; + return new ScoreEvaluation(score, passed); } @Override public String getUserUserComment(UserCourseEnvironment userCourseEnvironment) { AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager(); Identity mySelf = userCourseEnvironment.getIdentityEnvironment().getIdentity(); - String userCommentValue = am.getNodeComment(this, mySelf); - return userCommentValue; + return am.getNodeComment(this, mySelf); } @Override public String getUserCoachComment(UserCourseEnvironment userCourseEnvironment) { AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager(); Identity mySelf = userCourseEnvironment.getIdentityEnvironment().getIdentity(); - String coachCommentValue = am.getNodeCoachComment(this, mySelf); - return coachCommentValue; + return am.getNodeCoachComment(this, mySelf); } @Override @@ -326,16 +329,14 @@ public class BasicLTICourseNode extends AbstractAccessableCourseNode implements // having score defined means the node is assessable UserNodeAuditManager am = userCourseEnvironment.getCourseEnvironment().getAuditManager(); Identity mySelf = userCourseEnvironment.getIdentityEnvironment().getIdentity(); - String logValue = am.getUserNodeLog(this, mySelf); - return logValue; + return am.getUserNodeLog(this, mySelf); } @Override public Integer getUserAttempts(UserCourseEnvironment userCourseEnvironment) { AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager(); Identity mySelf = userCourseEnvironment.getIdentityEnvironment().getIdentity(); - Integer userAttemptsValue = am.getNodeAttempts(this, mySelf); - return userAttemptsValue; + return am.getNodeAttempts(this, mySelf); } @Override diff --git a/src/main/java/org/olat/course/nodes/CheckListCourseNode.java b/src/main/java/org/olat/course/nodes/CheckListCourseNode.java index a2818e861d3..189f23e1cb2 100644 --- a/src/main/java/org/olat/course/nodes/CheckListCourseNode.java +++ b/src/main/java/org/olat/course/nodes/CheckListCourseNode.java @@ -74,6 +74,7 @@ import org.olat.course.run.userview.NodeEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; import org.olat.course.run.userview.UserCourseEnvironmentImpl; import org.olat.modules.ModuleConfiguration; +import org.olat.modules.assessment.AssessmentEntry; import org.olat.repository.RepositoryEntry; /** @@ -170,18 +171,28 @@ public class CheckListCourseNode extends AbstractAccessableCourseNode implements * @see org.olat.course.nodes.AssessableCourseNode#getUserScoreEvaluation(org.olat.course.run.userview.UserCourseEnvironment) */ @Override - public ScoreEvaluation getUserScoreEvaluation(UserCourseEnvironment userCourseEnvironment) { - // read score from properties - AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager(); - Identity mySelf = userCourseEnvironment.getIdentityEnvironment().getIdentity(); + public ScoreEvaluation getUserScoreEvaluation(UserCourseEnvironment userCourseEnv) { Boolean passed = null; Float score = null; - // only db lookup if configured, else return null - if (hasPassedConfigured()) passed = am.getNodePassed(this, mySelf); - if (hasScoreConfigured()) score = am.getNodeScore(this, mySelf); + if(hasPassedConfigured() || hasScoreConfigured()) { + AssessmentEntry entry = getUserAssessmentEntry(userCourseEnv); + if(entry != null) { + if (hasPassedConfigured()) { + passed = entry.getPassed(); + } + if (hasScoreConfigured() && entry.getScore() != null) { + score = entry.getScore().floatValue(); + } + } + } + return new ScoreEvaluation(score, passed); + } - ScoreEvaluation se = new ScoreEvaluation(score, passed); - return se; + @Override + public AssessmentEntry getUserAssessmentEntry(UserCourseEnvironment userCourseEnv) { + AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager(); + Identity mySelf = userCourseEnv.getIdentityEnvironment().getIdentity(); + return am.getAssessmentEntry(this, mySelf, null); } /** diff --git a/src/main/java/org/olat/course/nodes/GTACourseNode.java b/src/main/java/org/olat/course/nodes/GTACourseNode.java index b656f66768c..b4f8df8f94d 100644 --- a/src/main/java/org/olat/course/nodes/GTACourseNode.java +++ b/src/main/java/org/olat/course/nodes/GTACourseNode.java @@ -86,6 +86,7 @@ import org.olat.course.run.userview.NodeEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; import org.olat.group.BusinessGroup; import org.olat.modules.ModuleConfiguration; +import org.olat.modules.assessment.AssessmentEntry; import org.olat.repository.RepositoryEntry; import org.olat.resource.OLATResource; import org.olat.user.UserManager; @@ -788,20 +789,29 @@ public class GTACourseNode extends AbstractAccessableCourseNode implements Asses @Override public ScoreEvaluation getUserScoreEvaluation(UserCourseEnvironment userCourseEnv) { - AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager(); - Identity assessedIdentity = userCourseEnv.getIdentityEnvironment().getIdentity(); Boolean passed = null; Float score = null; - // only db lookup if configured, else return null - if (hasPassedConfigured()) { - passed = am.getNodePassed(this, assessedIdentity); - } - if (hasScoreConfigured()) { - score = am.getNodeScore(this, assessedIdentity); + if(hasPassedConfigured() || hasScoreConfigured()) { + AssessmentEntry entry = getUserAssessmentEntry(userCourseEnv); + if(entry != null) { + if (hasPassedConfigured()) { + passed = entry.getPassed(); + } + if (hasScoreConfigured() && entry.getScore() != null) { + score = entry.getScore().floatValue(); + } + } } return new ScoreEvaluation(score, passed); } + @Override + public AssessmentEntry getUserAssessmentEntry(UserCourseEnvironment userCourseEnv) { + AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager(); + Identity mySelf = userCourseEnv.getIdentityEnvironment().getIdentity(); + return am.getAssessmentEntry(this, mySelf, null); + } + @Override public String getUserUserComment(UserCourseEnvironment userCourseEnv) { AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager(); diff --git a/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java b/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java index a0d0e98dc71..2caa3d0e3f0 100644 --- a/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java +++ b/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java @@ -86,6 +86,7 @@ import org.olat.ims.qti.statistics.QTIType; import org.olat.ims.qti.statistics.ui.QTI12PullTestsToolController; import org.olat.ims.qti.statistics.ui.QTI12StatisticsToolController; import org.olat.modules.ModuleConfiguration; +import org.olat.modules.assessment.AssessmentEntry; import org.olat.modules.iq.IQSecurityCallback; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryEntryImportExport; @@ -107,6 +108,7 @@ import de.bps.onyx.plugin.run.OnyxRunController; public class IQTESTCourseNode extends AbstractAccessableCourseNode implements AssessableCourseNode, QTICourseNode { private static final long serialVersionUID = 5806292895738005387L; private static final OLog log = Tracing.createLoggerFor(IQTESTCourseNode.class); + private static final String translatorStr = Util.getPackageName(IQEditController.class); private static final String TYPE = "iqtest"; private static final int CURRENT_CONFIG_VERSION = 2; @@ -269,9 +271,8 @@ public class IQTESTCourseNode extends AbstractAccessableCourseNode implements As if (!isValid) { String shortKey = "error.test.undefined.short"; String longKey = "error.test.undefined.long"; - String[] params = new String[] { this.getShortTitle() }; - String translPackage = Util.getPackageName(IQEditController.class); - sd = new StatusDescription(StatusDescription.ERROR, shortKey, longKey, params, translPackage); + String[] params = new String[] { getShortTitle() }; + sd = new StatusDescription(StatusDescription.ERROR, shortKey, longKey, params, translatorStr); sd.setDescriptionForUnit(getIdent()); // set which pane is affected by error sd.setActivateableViewIdentifier(IQEditController.PANE_TAB_IQCONFIG_TEST); @@ -287,7 +288,6 @@ public class IQTESTCourseNode extends AbstractAccessableCourseNode implements As oneClickStatusCache = null; // only here we know which translator to take for translating condition // error messages - String translatorStr = Util.getPackageName(IQEditController.class); List<StatusDescription> sds = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions()); oneClickStatusCache = StatusDescriptionHelper.sort(sds); return oneClickStatusCache; @@ -297,10 +297,10 @@ public class IQTESTCourseNode extends AbstractAccessableCourseNode implements As * @see org.olat.course.nodes.AssessableCourseNode#getUserScoreEvaluation(org.olat.course.run.userview.UserCourseEnvironment) */ @Override - public ScoreEvaluation getUserScoreEvaluation(UserCourseEnvironment userCourseEnvironment) { + public ScoreEvaluation getUserScoreEvaluation(UserCourseEnvironment userCourseEnv) { // read score from properties save score, passed and attempts information - AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager(); - Identity mySelf = userCourseEnvironment.getIdentityEnvironment().getIdentity(); + AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager(); + Identity mySelf = userCourseEnv.getIdentityEnvironment().getIdentity(); Boolean passed = am.getNodePassed(this, mySelf); Float score = am.getNodeScore(this, mySelf); Long assessmentID = am.getAssessmentID(this, mySelf); @@ -309,6 +309,16 @@ public class IQTESTCourseNode extends AbstractAccessableCourseNode implements As return se; } + @Override + public AssessmentEntry getUserAssessmentEntry(UserCourseEnvironment userCourseEnv) { + AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager(); + Identity mySelf = userCourseEnv.getIdentityEnvironment().getIdentity(); + if(getRepositoryEntrySoftKey() != null) { + return am.getAssessmentEntry(this, mySelf, getRepositoryEntrySoftKey()); + } + return null; + } + /** * @see org.olat.course.nodes.AssessableCourseNode#getCutValueConfiguration() */ @@ -464,6 +474,10 @@ public class IQTESTCourseNode extends AbstractAccessableCourseNode implements As RepositoryEntry re = IQEditController.getIQReference(getModuleConfiguration(), false); return re; } + + private String getRepositoryEntrySoftKey() { + return (String)getModuleConfiguration().get(IQEditController.CONFIG_KEY_REPOSITORY_SOFTKEY); + } /** * @see org.olat.course.nodes.CourseNode#needsReferenceToARepositoryEntry() diff --git a/src/main/java/org/olat/course/nodes/MSCourseNode.java b/src/main/java/org/olat/course/nodes/MSCourseNode.java index e106fde2c3a..529a9f20cb9 100644 --- a/src/main/java/org/olat/course/nodes/MSCourseNode.java +++ b/src/main/java/org/olat/course/nodes/MSCourseNode.java @@ -62,6 +62,7 @@ import org.olat.course.run.scoring.ScoreEvaluation; import org.olat.course.run.userview.NodeEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; import org.olat.modules.ModuleConfiguration; +import org.olat.modules.assessment.AssessmentEntry; import org.olat.properties.Property; import org.olat.repository.RepositoryEntry; import org.olat.resource.OLATResource; @@ -75,7 +76,6 @@ import org.olat.resource.OLATResource; public class MSCourseNode extends AbstractAccessableCourseNode implements AssessableCourseNode { private static final long serialVersionUID = -7741172700015384397L; private static final String PACKAGE_MS = Util.getPackageName(MSCourseNodeRunController.class); - private static final String PACKAGE = Util.getPackageName(MSCourseNode.class); private static final String TYPE = "ms"; /** configuration: score can be set */ @@ -144,7 +144,7 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Assess // Do not allow guests to have manual scoring Roles roles = ureq.getUserSession().getRoles(); if (roles.isGuestOnly()) { - Translator trans = new PackageTranslator(PACKAGE, ureq.getLocale()); + Translator trans = Util.createPackageTranslator(MSCourseNode.class, ureq.getLocale()); String title = trans.translate("guestnoaccess.title"); String message = trans.translate("guestnoaccess.message"); controller = MessageUIFactory.createInfoMessage(ureq, wControl, title, message); @@ -187,8 +187,7 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Assess String shortKey = "error.missingconfig.short"; String longKey = "error.missingconfig.long"; String[] params = new String[] { this.getShortTitle() }; - String translPackage = Util.getPackageName(MSEditFormController.class); - sd = new StatusDescription(StatusDescription.ERROR, shortKey, longKey, params, translPackage); + sd = new StatusDescription(StatusDescription.ERROR, shortKey, longKey, params, PACKAGE_MS); sd.setDescriptionForUnit(getIdent()); // set which pane is affected by error sd.setActivateableViewIdentifier(MSCourseNodeEditController.PANE_TAB_CONFIGURATION); @@ -204,8 +203,7 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Assess oneClickStatusCache = null; // only here we know which translator to take for translating condition // error messages - String translatorStr = Util.getPackageName(MSEditFormController.class); - List<StatusDescription> sds = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions()); + List<StatusDescription> sds = isConfigValidWithTranslator(cev, PACKAGE_MS, getConditionExpressions()); oneClickStatusCache = StatusDescriptionHelper.sort(sds); return oneClickStatusCache; } @@ -213,18 +211,28 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Assess /** * @see org.olat.course.nodes.AssessableCourseNode#getUserScoreEvaluation(org.olat.course.run.userview.UserCourseEnvironment) */ - public ScoreEvaluation getUserScoreEvaluation(UserCourseEnvironment userCourseEnvironment) { - // read score from properties - AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager(); - Identity mySelf = userCourseEnvironment.getIdentityEnvironment().getIdentity(); + public ScoreEvaluation getUserScoreEvaluation(UserCourseEnvironment userCourseEnv) { Boolean passed = null; Float score = null; - // only db lookup if configured, else return null - if (hasPassedConfigured()) passed = am.getNodePassed(this, mySelf); - if (hasScoreConfigured()) score = am.getNodeScore(this, mySelf); + if(hasPassedConfigured() || hasScoreConfigured()) { + AssessmentEntry entry = getUserAssessmentEntry(userCourseEnv); + if(entry != null) { + if (hasPassedConfigured()) { + passed = entry.getPassed(); + } + if (hasScoreConfigured() && entry.getScore() != null) { + score = entry.getScore().floatValue(); + } + } + } + return new ScoreEvaluation(score, passed); + } - ScoreEvaluation se = new ScoreEvaluation(score, passed); - return se; + @Override + public AssessmentEntry getUserAssessmentEntry(UserCourseEnvironment userCourseEnv) { + AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager(); + Identity mySelf = userCourseEnv.getIdentityEnvironment().getIdentity(); + return am.getAssessmentEntry(this, mySelf, null); } /** diff --git a/src/main/java/org/olat/course/nodes/PortfolioCourseNode.java b/src/main/java/org/olat/course/nodes/PortfolioCourseNode.java index 3aa6a46c30b..ab8b17ecf35 100644 --- a/src/main/java/org/olat/course/nodes/PortfolioCourseNode.java +++ b/src/main/java/org/olat/course/nodes/PortfolioCourseNode.java @@ -55,6 +55,7 @@ import org.olat.course.run.scoring.ScoreEvaluation; import org.olat.course.run.userview.NodeEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; import org.olat.modules.ModuleConfiguration; +import org.olat.modules.assessment.AssessmentEntry; import org.olat.portfolio.EPTemplateMapResource; import org.olat.portfolio.manager.EPFrontendManager; import org.olat.portfolio.manager.EPStructureManager; @@ -197,6 +198,10 @@ public class PortfolioCourseNode extends AbstractAccessableCourseNode implements return null; } + private String getReferencedRepositoryEntrySoftkey() { + return (String)getModuleConfiguration().get(PortfolioCourseNodeConfiguration.REPO_SOFT_KEY); + } + @Override public boolean needsReferenceToARepositoryEntry() { return true; @@ -305,18 +310,43 @@ public class PortfolioCourseNode extends AbstractAccessableCourseNode implements } @Override - public ScoreEvaluation getUserScoreEvaluation(UserCourseEnvironment userCourseEnvironment) { - // read score from properties - AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager(); - Identity mySelf = userCourseEnvironment.getIdentityEnvironment().getIdentity(); + public ScoreEvaluation getUserScoreEvaluation(UserCourseEnvironment userCourseEnv) { Boolean passed = null; Float score = null; - // only db lookup if configured, else return null - if (hasPassedConfigured()) passed = am.getNodePassed(this, mySelf); - if (hasScoreConfigured()) score = am.getNodeScore(this, mySelf); - - ScoreEvaluation se = new ScoreEvaluation(score, passed); - return se; + if (hasPassedConfigured() || hasScoreConfigured()) { + AssessmentEntry entry = getUserAssessmentEntry(userCourseEnv); + if(entry != null) { + if (hasPassedConfigured()) { + passed = entry.getPassed(); + } + if (hasScoreConfigured() && entry.getScore() != null) { + score = entry.getScore().floatValue(); + } + } + } + return new ScoreEvaluation(score, passed); + } + + @Override + public AssessmentEntry getUserAssessmentEntry(UserCourseEnvironment userCourseEnv) { + AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager(); + Identity mySelf = userCourseEnv.getIdentityEnvironment().getIdentity(); + String referenceSoftkey = getReferencedRepositoryEntrySoftkey(); + if(referenceSoftkey == null) { + Long mapKey = (Long)getModuleConfiguration().get(PortfolioCourseNodeConfiguration.MAP_KEY); + if(mapKey != null) { + RepositoryEntry re = CoreSpringFactory.getImpl(EPStructureManager.class) + .loadPortfolioRepositoryEntryByMapKey(mapKey); + if(re != null) { + referenceSoftkey = re.getSoftkey(); + } + } + } + + if(referenceSoftkey != null) { + return am.getAssessmentEntry(this, mySelf, referenceSoftkey); + } + return null; } @Override diff --git a/src/main/java/org/olat/course/nodes/ProjectBrokerCourseNode.java b/src/main/java/org/olat/course/nodes/ProjectBrokerCourseNode.java index 62edaaebc93..3acb044bd09 100644 --- a/src/main/java/org/olat/course/nodes/ProjectBrokerCourseNode.java +++ b/src/main/java/org/olat/course/nodes/ProjectBrokerCourseNode.java @@ -110,6 +110,7 @@ import org.olat.group.BusinessGroup; import org.olat.group.BusinessGroupService; import org.olat.group.model.BusinessGroupReference; import org.olat.modules.ModuleConfiguration; +import org.olat.modules.assessment.AssessmentEntry; import org.olat.properties.Property; import org.olat.repository.RepositoryEntry; import org.olat.resource.OLATResource; @@ -466,24 +467,30 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Assess condition.setConditionId("projectbroker"); this.conditionProjectBroker = condition; } - - // //////////// assessable interface implementation - /** - * @see org.olat.course.nodes.AssessableCourseNode#getUserScoreEvaluation(org.olat.course.run.userview.UserCourseEnvironment) - */ - public ScoreEvaluation getUserScoreEvaluation(UserCourseEnvironment userCourseEnvironment) { - // read score from properties - AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager(); - Identity mySelf = userCourseEnvironment.getIdentityEnvironment().getIdentity(); + @Override + public ScoreEvaluation getUserScoreEvaluation(UserCourseEnvironment userCourseEnv) { Boolean passed = null; Float score = null; - // only db lookup if configured, else return null - if (hasPassedConfigured()) passed = am.getNodePassed(this, mySelf); - if (hasScoreConfigured()) score = am.getNodeScore(this, mySelf); + if(hasPassedConfigured() || hasScoreConfigured()) { + AssessmentEntry entry = getUserAssessmentEntry(userCourseEnv); + if(entry != null) { + if (hasPassedConfigured()) { + passed = entry.getPassed(); + } + if (hasScoreConfigured() && entry.getScore() != null) { + score = entry.getScore().floatValue(); + } + } + } + return new ScoreEvaluation(score, passed); + } - ScoreEvaluation se = new ScoreEvaluation(score, passed); - return se; + @Override + public AssessmentEntry getUserAssessmentEntry(UserCourseEnvironment userCourseEnv) { + AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager(); + Identity mySelf = userCourseEnv.getIdentityEnvironment().getIdentity(); + return am.getAssessmentEntry(this, mySelf, null); } /** diff --git a/src/main/java/org/olat/course/nodes/STCourseNode.java b/src/main/java/org/olat/course/nodes/STCourseNode.java index af2cd168fb9..a73a5fcd01c 100644 --- a/src/main/java/org/olat/course/nodes/STCourseNode.java +++ b/src/main/java/org/olat/course/nodes/STCourseNode.java @@ -54,6 +54,7 @@ import org.olat.core.util.resource.OresHelper; import org.olat.course.CourseFactory; import org.olat.course.CourseModule; import org.olat.course.ICourse; +import org.olat.course.assessment.AssessmentManager; import org.olat.course.condition.Condition; import org.olat.course.condition.interpreter.ConditionExpression; import org.olat.course.condition.interpreter.ConditionInterpreter; @@ -75,6 +76,7 @@ import org.olat.course.run.userview.NodeEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; import org.olat.course.tree.CourseInternalLinkTreeModel; import org.olat.modules.ModuleConfiguration; +import org.olat.modules.assessment.AssessmentEntry; import org.olat.repository.RepositoryEntry; import org.olat.util.logging.activity.LoggingResourceable; @@ -265,6 +267,7 @@ public class STCourseNode extends AbstractAccessableCourseNode implements Assess * * @see org.olat.course.nodes.AssessableCourseNode#getUserScoreEvaluation(org.olat.course.run.userview.UserCourseEnvironment) */ + @Override public ScoreEvaluation getUserScoreEvaluation(UserCourseEnvironment userCourseEnv) { Float score = null; Boolean passed = null; @@ -284,8 +287,14 @@ public class STCourseNode extends AbstractAccessableCourseNode implements Assess if (passedExpressionStr != null) { passed = new Boolean(ci.evaluateCondition(passedExpressionStr)); } - ScoreEvaluation se = new ScoreEvaluation(score, passed); - return se; + return new ScoreEvaluation(score, passed); + } + + @Override + public AssessmentEntry getUserAssessmentEntry(UserCourseEnvironment userCourseEnv) { + AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager(); + Identity mySelf = userCourseEnv.getIdentityEnvironment().getIdentity(); + return am.getAssessmentEntry(this, mySelf, null); } /** diff --git a/src/main/java/org/olat/course/nodes/ScormCourseNode.java b/src/main/java/org/olat/course/nodes/ScormCourseNode.java index 48ecf1a901d..a97d751d34e 100644 --- a/src/main/java/org/olat/course/nodes/ScormCourseNode.java +++ b/src/main/java/org/olat/course/nodes/ScormCourseNode.java @@ -63,6 +63,7 @@ import org.olat.course.run.userview.NodeEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; import org.olat.fileresource.types.ScormCPFileResource; import org.olat.modules.ModuleConfiguration; +import org.olat.modules.assessment.AssessmentEntry; import org.olat.modules.scorm.ScormMainManager; import org.olat.modules.scorm.ScormPackageConfig; import org.olat.modules.scorm.archiver.ScormExportManager; @@ -188,6 +189,10 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Ass RepositoryEntry entry = CPEditController.getCPReference(getModuleConfiguration(), false); return entry; } + + public String getReferencedRepositoryEntrySoftkey() { + return (String)getModuleConfiguration().get(CPEditController.CONFIG_KEY_REPOSITORY_SOFTKEY); + } /** * @see org.olat.course.nodes.CourseNode#needsReferenceToARepositoryEntry() @@ -371,14 +376,27 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Ass } @Override - public ScoreEvaluation getUserScoreEvaluation(UserCourseEnvironment userCourseEnvironment) { - // read score from properties save score, passed and attempts information - AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager(); - Identity mySelf = userCourseEnvironment.getIdentityEnvironment().getIdentity(); - Boolean passed = am.getNodePassed(this, mySelf); - Float score = am.getNodeScore(this, mySelf); - ScoreEvaluation se = new ScoreEvaluation(score, passed); - return se; + public ScoreEvaluation getUserScoreEvaluation(UserCourseEnvironment userCourseEnv) { + AssessmentEntry entry = getUserAssessmentEntry(userCourseEnv); + Boolean passed = null; + Float score = null; + if(entry != null) { + passed = entry.getPassed(); + if(entry.getScore() != null) { + score = entry.getScore().floatValue(); + } + } + return new ScoreEvaluation(score, passed); + } + + @Override + public AssessmentEntry getUserAssessmentEntry(UserCourseEnvironment userCourseEnv) { + AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager(); + Identity mySelf = userCourseEnv.getIdentityEnvironment().getIdentity(); + if(getReferencedRepositoryEntrySoftkey() != null) { + return am.getAssessmentEntry(this, mySelf, getReferencedRepositoryEntrySoftkey()); + } + return null; } /** diff --git a/src/main/java/org/olat/course/nodes/TACourseNode.java b/src/main/java/org/olat/course/nodes/TACourseNode.java index c13971347c8..322a2dacac3 100644 --- a/src/main/java/org/olat/course/nodes/TACourseNode.java +++ b/src/main/java/org/olat/course/nodes/TACourseNode.java @@ -94,6 +94,7 @@ import org.olat.course.run.scoring.ScoreEvaluation; import org.olat.course.run.userview.NodeEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; import org.olat.modules.ModuleConfiguration; +import org.olat.modules.assessment.AssessmentEntry; import org.olat.properties.Property; import org.olat.repository.RepositoryEntry; import org.olat.resource.OLATResource; @@ -480,24 +481,32 @@ public class TACourseNode extends GenericCourseNode implements AssessableCourseN this.conditionSolution = conditionSolution; } - // //////////// assessable interface implementation - /** * @see org.olat.course.nodes.AssessableCourseNode#getUserScoreEvaluation(org.olat.course.run.userview.UserCourseEnvironment) */ @Override - public ScoreEvaluation getUserScoreEvaluation(UserCourseEnvironment userCourseEnvironment) { - // read score from properties - AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager(); - Identity mySelf = userCourseEnvironment.getIdentityEnvironment().getIdentity(); + public ScoreEvaluation getUserScoreEvaluation(UserCourseEnvironment userCourseEnv) { Boolean passed = null; Float score = null; - // only db lookup if configured, else return null - if (hasPassedConfigured()) passed = am.getNodePassed(this, mySelf); - if (hasScoreConfigured()) score = am.getNodeScore(this, mySelf); + if(hasPassedConfigured() || hasScoreConfigured()) { + AssessmentEntry entry = getUserAssessmentEntry(userCourseEnv); + if(entry != null) { + if (hasPassedConfigured()) { + passed = entry.getPassed(); + } + if (hasScoreConfigured() && entry.getScore() != null) { + score = entry.getScore().floatValue(); + } + } + } + return new ScoreEvaluation(score, passed); + } - ScoreEvaluation se = new ScoreEvaluation(score, passed); - return se; + @Override + public AssessmentEntry getUserAssessmentEntry(UserCourseEnvironment userCourseEnv) { + AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager(); + Identity mySelf = userCourseEnv.getIdentityEnvironment().getIdentity(); + return am.getAssessmentEntry(this, mySelf, null); } /** diff --git a/src/main/java/org/olat/course/nodes/cp/CPEditController.java b/src/main/java/org/olat/course/nodes/cp/CPEditController.java index 6580b4fc7c4..ee47bbe90d5 100644 --- a/src/main/java/org/olat/course/nodes/cp/CPEditController.java +++ b/src/main/java/org/olat/course/nodes/cp/CPEditController.java @@ -83,7 +83,7 @@ public class CPEditController extends ActivateableTabbableDefaultController impl public static final String PANE_TAB_CPCONFIG = "pane.tab.cpconfig"; private static final String PANE_TAB_ACCESSIBILITY = "pane.tab.accessibility"; private static final String PANE_TAB_DELIVERYOPTIONS = "pane.tab.deliveryOptions"; - private static final String CONFIG_KEY_REPOSITORY_SOFTKEY = "reporef"; + public static final String CONFIG_KEY_REPOSITORY_SOFTKEY = "reporef"; private static final String VC_CHOSENCP = "chosencp"; public static final String CONFIG_DELIVERYOPTIONS = "deliveryOptions"; diff --git a/src/main/java/org/olat/course/nodes/iq/IQRunController.java b/src/main/java/org/olat/course/nodes/iq/IQRunController.java index f9231f5baa9..755cd9ec860 100644 --- a/src/main/java/org/olat/course/nodes/iq/IQRunController.java +++ b/src/main/java/org/olat/course/nodes/iq/IQRunController.java @@ -555,7 +555,7 @@ public class IQRunController extends BasicController implements GenericEventList } private void exposeUserTestDataToVC(UserRequest ureq) { - // config : show score info + // config : show score info Object enableScoreInfoObject = modConfig.get(IQEditController.CONFIG_KEY_ENABLESCOREINFO); if (enableScoreInfoObject != null) { myContent.contextPut("enableScoreInfo", enableScoreInfoObject ); @@ -563,24 +563,25 @@ public class IQRunController extends BasicController implements GenericEventList myContent.contextPut("enableScoreInfo", Boolean.TRUE ); } - // configuration data - myContent.contextPut("attemptsConfig", modConfig.get(IQEditController.CONFIG_KEY_ATTEMPTS)); - // user data - if ( !(courseNode instanceof AssessableCourseNode)) - throw new AssertException("exposeUserTestDataToVC can only be called for test nodes, not for selftest or questionnaire"); + // configuration data + myContent.contextPut("attemptsConfig", modConfig.get(IQEditController.CONFIG_KEY_ATTEMPTS)); + // user data + if ( !(courseNode instanceof AssessableCourseNode)) { + throw new AssertException("exposeUserTestDataToVC can only be called for test nodes, not for selftest or questionnaire"); + } AssessableCourseNode acn = (AssessableCourseNode)courseNode; // assessment nodes are assesable ScoreEvaluation scoreEval = acn.getUserScoreEvaluation(userCourseEnv); //block if test passed (and config set to check it) Boolean blockAfterSuccess = (Boolean)modConfig.get(IQEditController.CONFIG_KEY_BLOCK_AFTER_SUCCESS); - Boolean blocked = Boolean.FALSE; - if(blockAfterSuccess != null && blockAfterSuccess.booleanValue()) { - Boolean passed = scoreEval.getPassed(); - if(passed != null && passed.booleanValue()) { - blocked = Boolean.TRUE; - } - } - myContent.contextPut("blockAfterSuccess", blocked ); + Boolean blocked = Boolean.FALSE; + if(blockAfterSuccess != null && blockAfterSuccess.booleanValue()) { + Boolean passed = scoreEval.getPassed(); + if(passed != null && passed.booleanValue()) { + blocked = Boolean.TRUE; + } + } + myContent.contextPut("blockAfterSuccess", blocked ); Identity identity = userCourseEnv.getIdentityEnvironment().getIdentity(); myContent.contextPut("score", AssessmentHelper.getRoundedScore(scoreEval.getScore())); diff --git a/src/main/java/org/olat/course/nodes/ta/ConvertToGTACourseNode.java b/src/main/java/org/olat/course/nodes/ta/ConvertToGTACourseNode.java index cd73d218a1b..ccae86d1729 100644 --- a/src/main/java/org/olat/course/nodes/ta/ConvertToGTACourseNode.java +++ b/src/main/java/org/olat/course/nodes/ta/ConvertToGTACourseNode.java @@ -219,7 +219,7 @@ public class ConvertToGTACourseNode { CoursePropertyManager propertyMgr = courseEnv.getCoursePropertyManager(); Map<Long,AssessmentEntry> datas = new HashMap<>(); - List<AssessmentEntry> properties = courseEnv.getAssessmentManager().getAssessmentData(sourceNode); + List<AssessmentEntry> properties = courseEnv.getAssessmentManager().getAssessmentEntries(sourceNode); for(AssessmentEntry property:properties) { Identity identity = property.getIdentity(); @@ -266,14 +266,14 @@ public class ConvertToGTACourseNode { List<Property> logEntries = propertyMgr .listCourseNodeProperties(sourceNode, null, null, UserNodeAuditManager.LOG_IDENTIFYER); for(Property logEntry:logEntries) { - String log = logEntry.getTextValue(); + String logText = logEntry.getTextValue(); Identity identity = securityManager.loadIdentityByKey(logEntry.getIdentity().getKey()); Property targetProp = propertyMgr.findCourseNodeProperty(gtaNode, identity, null, UserNodeAuditManager.LOG_IDENTIFYER); if(targetProp == null) { targetProp = propertyMgr - .createCourseNodePropertyInstance(gtaNode, identity, null, UserNodeAuditManager.LOG_IDENTIFYER, null, null, null, log); + .createCourseNodePropertyInstance(gtaNode, identity, null, UserNodeAuditManager.LOG_IDENTIFYER, null, null, null, logText); } else { - targetProp.setTextValue(log); + targetProp.setTextValue(logText); } propertyMgr.saveProperty(targetProp); } diff --git a/src/main/java/org/olat/course/run/preview/PreviewAssessmentManager.java b/src/main/java/org/olat/course/run/preview/PreviewAssessmentManager.java index 242f9ece905..dc23b65b137 100644 --- a/src/main/java/org/olat/course/run/preview/PreviewAssessmentManager.java +++ b/src/main/java/org/olat/course/run/preview/PreviewAssessmentManager.java @@ -61,10 +61,15 @@ final class PreviewAssessmentManager extends BasicManager implements AssessmentM } @Override - public List<AssessmentEntry> getAssessmentData(CourseNode courseNode) { + public List<AssessmentEntry> getAssessmentEntries(CourseNode courseNode) { return Collections.emptyList(); } + @Override + public AssessmentEntry getAssessmentEntry(CourseNode courseNode, Identity assessedIdentity, String referenceSoftKey) { + return null; + } + /** * @see org.olat.course.assessment.AssessmentManager#saveNodeAttempts(org.olat.course.nodes.CourseNode, org.olat.core.id.Identity, org.olat.core.id.Identity, java.lang.Integer) */ diff --git a/src/main/java/org/olat/ims/qti21/QTI21Service.java b/src/main/java/org/olat/ims/qti21/QTI21Service.java index 57135c1b9ca..276a673f928 100644 --- a/src/main/java/org/olat/ims/qti21/QTI21Service.java +++ b/src/main/java/org/olat/ims/qti21/QTI21Service.java @@ -30,6 +30,7 @@ import org.olat.core.id.Identity; import org.olat.ims.qti21.model.CandidateItemEventType; import org.olat.ims.qti21.model.CandidateTestEventType; import org.olat.ims.qti21.model.jpa.CandidateEvent; +import org.olat.modules.assessment.AssessmentEntry; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryEntryRef; @@ -53,9 +54,11 @@ public interface QTI21Service { public <E extends ResolvedAssessmentObject<?>> E loadAndResolveAssessmentObject(File resourceDirectory); - public UserTestSession createTestSession(RepositoryEntry testEntry, RepositoryEntry courseEntry, String subIdent, Identity identity); + public UserTestSession createTestSession(Identity identity, AssessmentEntry assessmentEntry, + RepositoryEntry entry, String subIdent, RepositoryEntry testEntry, + boolean authorMode); - public UserTestSession getResumableTestSession(RepositoryEntry testEntry, RepositoryEntry courseEntry, String subIdent, Identity identity); + public UserTestSession getResumableTestSession(Identity identity, RepositoryEntry entry, String subIdent, RepositoryEntry testEntry); public UserTestSession updateTestSession(UserTestSession session); diff --git a/src/main/java/org/olat/ims/qti21/manager/QTI21ServiceImpl.java b/src/main/java/org/olat/ims/qti21/manager/QTI21ServiceImpl.java index a8bfb7bbc94..52145ee18e7 100644 --- a/src/main/java/org/olat/ims/qti21/manager/QTI21ServiceImpl.java +++ b/src/main/java/org/olat/ims/qti21/manager/QTI21ServiceImpl.java @@ -53,6 +53,7 @@ import org.olat.ims.qti21.model.CandidateItemEventType; import org.olat.ims.qti21.model.CandidateTestEventType; import org.olat.ims.qti21.model.jpa.CandidateEvent; import org.olat.ims.qti21.ui.rendering.XmlUtilities; +import org.olat.modules.assessment.AssessmentEntry; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryEntryRef; import org.springframework.beans.factory.annotation.Autowired; @@ -171,13 +172,15 @@ public class QTI21ServiceImpl implements QTI21Service { } @Override - public UserTestSession createTestSession(RepositoryEntry testEntry, RepositoryEntry courseEntry, String courseSubIdent, Identity identity) { - return testSessionDao.createTestSession(testEntry, courseEntry, courseSubIdent, identity); + public UserTestSession createTestSession(Identity identity, AssessmentEntry assessmentEntry, + RepositoryEntry entry, String subIdent, RepositoryEntry testEntry, + boolean authorMode) { + return testSessionDao.createTestSession(testEntry, entry, subIdent, assessmentEntry, identity, authorMode); } @Override - public UserTestSession getResumableTestSession(RepositoryEntry testEntry, RepositoryEntry courseEntry, String subIdent, Identity identity) { - UserTestSession session = testSessionDao.getLastTestSession(testEntry, courseEntry, subIdent, identity); + public UserTestSession getResumableTestSession(Identity identity, RepositoryEntry entry, String subIdent, RepositoryEntry testEntry) { + UserTestSession session = testSessionDao.getLastTestSession(testEntry, entry, subIdent, identity); if(session == null || session.isExploded() || session.getTerminationTime() != null) { session = null; } else { diff --git a/src/main/java/org/olat/ims/qti21/manager/SessionDAO.java b/src/main/java/org/olat/ims/qti21/manager/SessionDAO.java index 08fbc8c41a6..60045e2337b 100644 --- a/src/main/java/org/olat/ims/qti21/manager/SessionDAO.java +++ b/src/main/java/org/olat/ims/qti21/manager/SessionDAO.java @@ -29,6 +29,7 @@ import org.olat.core.commons.persistence.DB; import org.olat.core.id.Identity; import org.olat.ims.qti21.UserTestSession; import org.olat.ims.qti21.model.jpa.UserTestSessionImpl; +import org.olat.modules.assessment.AssessmentEntry; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryEntryRef; import org.springframework.beans.factory.annotation.Autowired; @@ -50,16 +51,19 @@ public class SessionDAO { public UserTestSession createTestSession(RepositoryEntry testEntry, - RepositoryEntry courseEntry, String courseSubIdent, Identity identity) { + RepositoryEntry repositoryEntry, String subIdent, + AssessmentEntry assessmentEntry, Identity identity, + boolean authorMode) { UserTestSessionImpl testSession = new UserTestSessionImpl(); Date now = new Date(); testSession.setCreationDate(now); testSession.setLastModified(now); testSession.setTestEntry(testEntry); - testSession.setCourseEntry(courseEntry); - testSession.setCourseSubIdent(courseSubIdent); - testSession.setAuthorMode(false); + testSession.setRepositoryEntry(repositoryEntry); + testSession.setSubIdent(subIdent); + testSession.setAssessmentEntry(assessmentEntry); + testSession.setAuthorMode(authorMode); testSession.setExploded(false); testSession.setIdentity(identity); testSession.setStorage(storage.getRelativeDir()); @@ -68,21 +72,21 @@ public class SessionDAO { } public UserTestSession getLastTestSession(RepositoryEntryRef testEntry, - RepositoryEntryRef courseEntry, String courseSubIdent, IdentityRef identity) { + RepositoryEntryRef entry, String subIdent, IdentityRef identity) { StringBuilder sb = new StringBuilder(); sb.append("select session from qtiassessmentsession session ") .append("where session.testEntry.key=:testEntryKey and session.identity.key=:identityKey"); - if(courseEntry != null) { - sb.append(" and session.courseEntry.key=:courseEntryKey"); + if(entry != null) { + sb.append(" and session.repositoryEntry.key=:courseEntryKey"); } else { - sb.append(" and session.courseEntry.key is null"); + sb.append(" and session.repositoryEntry.key is null"); } - if(courseSubIdent != null) { - sb.append(" and session.courseSubIdent=:courseSubIdent"); + if(subIdent != null) { + sb.append(" and session.subIdent=:courseSubIdent"); } else { - sb.append(" and session.courseSubIdent is null"); + sb.append(" and session.subIdent is null"); } sb.append(" order by session.creationDate desc"); @@ -90,11 +94,11 @@ public class SessionDAO { .createQuery(sb.toString(), UserTestSession.class) .setParameter("testEntryKey", testEntry.getKey()) .setParameter("identityKey", identity.getKey()); - if(courseEntry != null) { - query.setParameter("courseEntryKey", courseEntry.getKey()); + if(entry != null) { + query.setParameter("courseEntryKey", entry.getKey()); } - if(courseSubIdent != null) { - query.setParameter("courseSubIdent", courseSubIdent); + if(subIdent != null) { + query.setParameter("courseSubIdent", subIdent); } List<UserTestSession> lastSessions = query.setMaxResults(1).getResultList(); @@ -108,10 +112,10 @@ public class SessionDAO { public List<UserTestSession> getUserTestSessions(RepositoryEntryRef courseEntry, String courseSubIdent, IdentityRef identity) { return dbInstance.getCurrentEntityManager() - .createNamedQuery("loadTestSessionsByUserAndCourse", UserTestSession.class) - .setParameter("courseEntryKey", courseEntry.getKey()) + .createNamedQuery("loadTestSessionsByUserAndRepositoryEntryAndSubIdent", UserTestSession.class) + .setParameter("repositoryEntryKey", courseEntry.getKey()) .setParameter("identityKey", identity.getKey()) - .setParameter("courseSubIdent", courseSubIdent) + .setParameter("subIdent", courseSubIdent) .getResultList(); } diff --git a/src/main/java/org/olat/ims/qti21/model/jpa/UserTestSessionImpl.java b/src/main/java/org/olat/ims/qti21/model/jpa/UserTestSessionImpl.java index 8f09d67ebb1..163d4011120 100644 --- a/src/main/java/org/olat/ims/qti21/model/jpa/UserTestSessionImpl.java +++ b/src/main/java/org/olat/ims/qti21/model/jpa/UserTestSessionImpl.java @@ -39,6 +39,8 @@ import org.olat.basesecurity.IdentityImpl; import org.olat.core.id.Identity; import org.olat.core.id.Persistable; import org.olat.ims.qti21.UserTestSession; +import org.olat.modules.assessment.AssessmentEntry; +import org.olat.modules.assessment.model.AssessmentEntryImpl; import org.olat.repository.RepositoryEntry; /** @@ -52,7 +54,7 @@ import org.olat.repository.RepositoryEntry; @Entity(name="qtiassessmentsession") @Table(name="o_qti_assessment_session") @NamedQueries({ - @NamedQuery(name="loadTestSessionsByUserAndCourse", query="select session from qtiassessmentsession session where session.courseEntry.key=:courseEntryKey and session.identity.key=:identityKey and session.courseSubIdent=:courseSubIdent") + @NamedQuery(name="loadTestSessionsByUserAndRepositoryEntryAndSubIdent", query="select session from qtiassessmentsession session where session.repositoryEntry.key=:repositoryEntryKey and session.identity.key=:identityKey and session.subIdent=:subIdent") }) public class UserTestSessionImpl implements UserTestSession, Persistable { @@ -70,17 +72,21 @@ public class UserTestSessionImpl implements UserTestSession, Persistable { @Temporal(TemporalType.TIMESTAMP) @Column(name="lastmodified", nullable=false, insertable=true, updatable=true) private Date lastModified; + + @ManyToOne(targetEntity=AssessmentEntryImpl.class,fetch=FetchType.LAZY,optional=false) + @JoinColumn(name="fk_assessment_entry", nullable=false, insertable=true, updatable=false) + private AssessmentEntry assessmentEntry; @ManyToOne(targetEntity=RepositoryEntry.class,fetch=FetchType.LAZY,optional=false) - @JoinColumn(name="fk_entry", nullable=false, insertable=true, updatable=false) + @JoinColumn(name="fk_reference_entry", nullable=false, insertable=true, updatable=false) private RepositoryEntry testEntry; @ManyToOne(targetEntity=RepositoryEntry.class,fetch=FetchType.LAZY,optional=true) - @JoinColumn(name="fk_course", nullable=true, insertable=true, updatable=false) - private RepositoryEntry courseEntry; + @JoinColumn(name="fk_entry", nullable=true, insertable=true, updatable=false) + private RepositoryEntry repositoryEntry; - @Column(name="q_course_subident", nullable=true, insertable=true, updatable=false) - private String courseSubIdent; + @Column(name="q_subident", nullable=true, insertable=true, updatable=false) + private String subIdent; @ManyToOne(targetEntity=IdentityImpl.class,fetch=FetchType.LAZY,optional=false) @JoinColumn(name="fk_identity", nullable=false, insertable=true, updatable=false) @@ -162,6 +168,14 @@ public class UserTestSessionImpl implements UserTestSession, Persistable { this.lastModified = lastModified; } + public AssessmentEntry getAssessmentEntry() { + return assessmentEntry; + } + + public void setAssessmentEntry(AssessmentEntry assessmentEntry) { + this.assessmentEntry = assessmentEntry; + } + public RepositoryEntry getTestEntry() { return testEntry; } @@ -170,20 +184,20 @@ public class UserTestSessionImpl implements UserTestSession, Persistable { this.testEntry = testEntry; } - public RepositoryEntry getCourseEntry() { - return courseEntry; + public RepositoryEntry getRepositoryEntry() { + return repositoryEntry; } - public void setCourseEntry(RepositoryEntry courseEntry) { - this.courseEntry = courseEntry; + public void setRepositoryEntry(RepositoryEntry repositoryEntry) { + this.repositoryEntry = repositoryEntry; } - public String getCourseSubIdent() { - return courseSubIdent; + public String getSubIdent() { + return subIdent; } - public void setCourseSubIdent(String courseSubIdent) { - this.courseSubIdent = courseSubIdent; + public void setSubIdent(String subIdent) { + this.subIdent = subIdent; } public Identity getIdentity() { diff --git a/src/main/java/org/olat/ims/qti21/repository/handlers/QTI21AssessmentTestHandler.java b/src/main/java/org/olat/ims/qti21/repository/handlers/QTI21AssessmentTestHandler.java index 0515dbbcbfc..ddab0488267 100644 --- a/src/main/java/org/olat/ims/qti21/repository/handlers/QTI21AssessmentTestHandler.java +++ b/src/main/java/org/olat/ims/qti21/repository/handlers/QTI21AssessmentTestHandler.java @@ -299,9 +299,9 @@ public class QTI21AssessmentTestHandler extends FileHandler { new RuntimeControllerCreator() { @Override public Controller create(UserRequest uureq, WindowControl wwControl, TooledStackedPanel toolbarPanel, - RepositoryEntry entry, RepositoryEntrySecurity reSecurity, AssessmentMode mode) { + RepositoryEntry entry, RepositoryEntrySecurity repoSecurity, AssessmentMode mode) { InMemoryOutcomesListener listener = new InMemoryOutcomesListener(); - return new AssessmentTestDisplayController(uureq, wwControl, listener, entry, null, null); + return new AssessmentTestDisplayController(uureq, wwControl, listener, entry, entry, null); } }); } diff --git a/src/main/java/org/olat/ims/qti21/ui/AssessmentItemDisplayController.java b/src/main/java/org/olat/ims/qti21/ui/AssessmentItemDisplayController.java index 765d743ad80..204a1fb0670 100644 --- a/src/main/java/org/olat/ims/qti21/ui/AssessmentItemDisplayController.java +++ b/src/main/java/org/olat/ims/qti21/ui/AssessmentItemDisplayController.java @@ -47,6 +47,7 @@ import org.olat.ims.qti21.UserTestSession; import org.olat.ims.qti21.model.CandidateItemEventType; import org.olat.ims.qti21.model.jpa.CandidateEvent; import org.olat.ims.qti21.ui.components.AssessmentItemFormItem; +import org.olat.modules.assessment.AssessmentEntry; import org.olat.repository.RepositoryEntry; import org.springframework.beans.factory.annotation.Autowired; @@ -96,7 +97,8 @@ public class AssessmentItemDisplayController extends BasicController implements @Autowired private JqtiExtensionManager jqtiExtensionManager; - public AssessmentItemDisplayController(UserRequest ureq, WindowControl wControl, RepositoryEntry testEntry, + public AssessmentItemDisplayController(UserRequest ureq, WindowControl wControl, + RepositoryEntry testEntry, AssessmentEntry assessmentEntry, boolean authorMode, ResolvedAssessmentItem resolvedAssessmentItem, AssessmentItemRef itemRef, File fUnzippedDirRoot) { super(ureq, wControl); @@ -104,7 +106,7 @@ public class AssessmentItemDisplayController extends BasicController implements this.fUnzippedDirRoot = fUnzippedDirRoot; this.resolvedAssessmentItem = resolvedAssessmentItem; currentRequestTimestamp = ureq.getRequestTimestamp(); - candidateSession = qtiService.createTestSession(testEntry, null, itemRef.getIdentifier().toString(), getIdentity()); + candidateSession = qtiService.createTestSession(getIdentity(), assessmentEntry, testEntry, itemRef.getIdentifier().toString(), testEntry, authorMode); mapperUri = registerCacheableMapper(null, UUID.randomUUID().toString(), new ResourcesMapper()); itemSessionController = enterSession(ureq); diff --git a/src/main/java/org/olat/ims/qti21/ui/AssessmentTestDisplayController.java b/src/main/java/org/olat/ims/qti21/ui/AssessmentTestDisplayController.java index 43ecd8e5235..f5555b67d68 100644 --- a/src/main/java/org/olat/ims/qti21/ui/AssessmentTestDisplayController.java +++ b/src/main/java/org/olat/ims/qti21/ui/AssessmentTestDisplayController.java @@ -49,6 +49,8 @@ import org.olat.ims.qti21.model.CandidateItemEventType; import org.olat.ims.qti21.model.CandidateTestEventType; import org.olat.ims.qti21.model.jpa.CandidateEvent; import org.olat.ims.qti21.ui.components.AssessmentTestFormItem; +import org.olat.modules.assessment.AssessmentEntry; +import org.olat.modules.assessment.AssessmentService; import org.olat.repository.RepositoryEntry; import org.springframework.beans.factory.annotation.Autowired; @@ -102,6 +104,7 @@ public class AssessmentTestDisplayController extends BasicController implements private CandidateEvent lastEvent; private Date currentRequestTimestamp; private UserTestSession candidateSession; + private AssessmentEntry assessmentEntry; private OutcomesListener outcomesListener; @@ -109,6 +112,8 @@ public class AssessmentTestDisplayController extends BasicController implements @Autowired private QTI21Service qtiService; @Autowired + private AssessmentService assessmentService; + @Autowired private JqtiExtensionManager jqtiExtensionManager; /** @@ -116,25 +121,27 @@ public class AssessmentTestDisplayController extends BasicController implements * @param ureq * @param wControl * @param listener - * @param entry - * @param courseRe Course repository entry (optional) + * @param testEntry + * @param entry Course repository entry (optional) * @param subIdent The course node identifier (mandatory only if in a course is used) */ public AssessmentTestDisplayController(UserRequest ureq, WindowControl wControl, OutcomesListener listener, - RepositoryEntry entry, RepositoryEntry courseRe, String courseSubIdent) { + RepositoryEntry testEntry, RepositoryEntry entry, String subIdent) { super(ureq, wControl); this.outcomesListener = listener; FileResourceManager frm = FileResourceManager.getInstance(); - fUnzippedDirRoot = frm.unzipFileResource(entry.getOlatResource()); - mapperUri = registerCacheableMapper(null, "QTI21Resources::" + entry.getKey(), new ResourcesMapper()); + fUnzippedDirRoot = frm.unzipFileResource(testEntry.getOlatResource()); + mapperUri = registerCacheableMapper(null, "QTI21Resources::" + testEntry.getKey(), new ResourcesMapper()); currentRequestTimestamp = ureq.getRequestTimestamp(); - UserTestSession lastSession = qtiService.getResumableTestSession(entry, courseRe, courseSubIdent, getIdentity()); + assessmentEntry = assessmentService.getOrCreateAssessmentEntry(getIdentity(), entry, subIdent, testEntry); + + UserTestSession lastSession = qtiService.getResumableTestSession(getIdentity(), entry, subIdent, testEntry); if(lastSession == null) { - candidateSession = qtiService.createTestSession(entry, courseRe, courseSubIdent, getIdentity()); + candidateSession = qtiService.createTestSession(getIdentity(), assessmentEntry, entry, subIdent, testEntry, false); testSessionController = enterSession(ureq); } else { candidateSession = lastSession; diff --git a/src/main/java/org/olat/ims/qti21/ui/InMemoryOutcomesListener.java b/src/main/java/org/olat/ims/qti21/ui/InMemoryOutcomesListener.java index 3534fc7310f..1d6f447e4ce 100644 --- a/src/main/java/org/olat/ims/qti21/ui/InMemoryOutcomesListener.java +++ b/src/main/java/org/olat/ims/qti21/ui/InMemoryOutcomesListener.java @@ -43,14 +43,14 @@ public class InMemoryOutcomesListener implements OutcomesListener { } @Override - public void updateOutcomes(Float score, Boolean pass) { - this.score = score; - this.pass = pass; + public void updateOutcomes(Float updatedScore, Boolean updatedPassed) { + score = updatedScore; + pass = updatedPassed; } @Override - public void submit(Float score, Boolean pass) { - this.score = score; - this.pass = pass; + public void submit(Float submittedScore, Boolean submittedPass) { + score = submittedScore; + pass = submittedPass; } } diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentItemEditorController.java b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentItemEditorController.java index aceb0dd2972..94f5da88fa1 100644 --- a/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentItemEditorController.java +++ b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentItemEditorController.java @@ -35,6 +35,8 @@ import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.controller.BasicController; import org.olat.ims.qti21.QTI21Constants; import org.olat.ims.qti21.ui.AssessmentItemDisplayController; +import org.olat.modules.assessment.AssessmentEntry; +import org.olat.modules.assessment.AssessmentService; import org.olat.repository.RepositoryEntry; import org.springframework.beans.factory.annotation.Autowired; @@ -63,6 +65,8 @@ public class AssessmentItemEditorController extends BasicController { @Autowired private QtiSerializer qtiSerializer; + @Autowired + private AssessmentService assessmentService; public AssessmentItemEditorController(UserRequest ureq, WindowControl wControl, RepositoryEntry testEntry, ResolvedAssessmentItem resolvedAssessmentItem, AssessmentItemRef itemRef, File unzippedDirectory) { @@ -76,7 +80,9 @@ public class AssessmentItemEditorController extends BasicController { initItemEditor(ureq); - displayCtrl = new AssessmentItemDisplayController(ureq, getWindowControl(), testEntry, resolvedAssessmentItem, itemRef, unzippedDirectory); + AssessmentEntry assessmentEntry = assessmentService.getOrCreateAssessmentEntry(getIdentity(), testEntry, null, testEntry); + displayCtrl = new AssessmentItemDisplayController(ureq, getWindowControl(), + testEntry, assessmentEntry, true, resolvedAssessmentItem, itemRef, unzippedDirectory); listenTo(displayCtrl); tabbedPane.addTab("Preview", displayCtrl.getInitialComponent()); diff --git a/src/main/java/org/olat/modules/assessment/AssessmentService.java b/src/main/java/org/olat/modules/assessment/AssessmentService.java index 6715ccdec59..0263d575406 100644 --- a/src/main/java/org/olat/modules/assessment/AssessmentService.java +++ b/src/main/java/org/olat/modules/assessment/AssessmentService.java @@ -19,6 +19,11 @@ */ package org.olat.modules.assessment; +import java.util.List; + +import org.olat.core.id.Identity; +import org.olat.repository.RepositoryEntry; + /** * * Initial date: 22.07.2015<br> @@ -26,5 +31,32 @@ package org.olat.modules.assessment; * */ public interface AssessmentService { + + /** + * + * @param assessedIdentity + * @param entry The repository entry, the course + * @param subIdent An additional reference for the cours element + * @param referenceEntry The test repository entry + * @return + */ + public AssessmentEntry getOrCreateAssessmentEntry(Identity assessedIdentity, + RepositoryEntry entry, String subIdent, RepositoryEntry referenceEntry); + + public AssessmentEntry loadAssessmentEntry(Identity assessedIdentity, RepositoryEntry entry, String subIdent); + + /** + * The search by the reference soft key is set not is null if the value is null. + * @param assessedIdentity + * @param entry + * @param subIdent + * @param referenceSoftKey + * @return + */ + public AssessmentEntry loadAssessmentEntry(Identity assessedIdentity, RepositoryEntry entry, String subIdent, String referenceSoftKey); + + public AssessmentEntry updateAssessmentEntry(AssessmentEntry entry); + + public List<AssessmentEntry> loadAssessmentEntriesBySubIdent(RepositoryEntry entry, String subIdent); } diff --git a/src/main/java/org/olat/modules/assessment/manager/AssessmentEntryDAO.java b/src/main/java/org/olat/modules/assessment/manager/AssessmentEntryDAO.java index 9bc23b903cf..ea26650e4e9 100644 --- a/src/main/java/org/olat/modules/assessment/manager/AssessmentEntryDAO.java +++ b/src/main/java/org/olat/modules/assessment/manager/AssessmentEntryDAO.java @@ -22,6 +22,8 @@ package org.olat.modules.assessment.manager; import java.util.Date; import java.util.List; +import javax.persistence.TypedQuery; + import org.olat.basesecurity.IdentityRef; import org.olat.core.commons.persistence.DB; import org.olat.core.id.Identity; @@ -66,19 +68,59 @@ public class AssessmentEntryDAO { return nodeAssessment.isEmpty() ? null : nodeAssessment.get(0); } - public AssessmentEntry loadAssessmentEntry(IdentityRef assessedIdentity, RepositoryEntryRef entry, - String subIdent) { + public AssessmentEntry loadAssessmentEntry(IdentityRef assessedIdentity, RepositoryEntryRef entry, String subIdent) { + TypedQuery<AssessmentEntry> query; + if(subIdent == null) { + query = dbInstance.getCurrentEntityManager() + .createNamedQuery("loadAssessmentEntryByRepositoryEntryAndUserAndNullSubIdent", AssessmentEntry.class); + } else { + query = dbInstance.getCurrentEntityManager() + .createNamedQuery("loadAssessmentEntryByRepositoryEntryAndUserAndSubIdent", AssessmentEntry.class) + .setParameter("subIdent", subIdent); + } + List<AssessmentEntry> entries = query + .setParameter("repositoryEntryKey", entry.getKey()) + .setParameter("identityKey", assessedIdentity.getKey()) + .getResultList(); + return entries.isEmpty() ? null : entries.get(0); + } + + public AssessmentEntry loadAssessmentEntry(IdentityRef assessedIdentity, RepositoryEntryRef entry, String subIdent, String referenceSoftKey) { + StringBuilder sb = new StringBuilder(); - List<AssessmentEntry> nodeAssessment = dbInstance.getCurrentEntityManager() - .createNamedQuery("loadAssessmentEntryByRepositoryEntryAndUser", AssessmentEntry.class) + sb.append("select data from assessmententry data"); + if(referenceSoftKey != null) { + sb.append(" inner join data.referenceEntry referenceEntry"); + } + + sb.append(" where data.repositoryEntry.key=:repositoryEntryKey and data.identity.key=:identityKey"); + if(subIdent != null) { + sb.append(" and data.subIdent=:subIdent"); + } else { + sb.append(" and data.subIdent is null"); + } + + if(referenceSoftKey != null) { + sb.append(" and referenceEntry.softkey=:softkey"); + } else { + sb.append(" and referenceEntry.softkey is null"); + } + + TypedQuery<AssessmentEntry> query = dbInstance.getCurrentEntityManager() + .createQuery(sb.toString(), AssessmentEntry.class) .setParameter("repositoryEntryKey", entry.getKey()) - .setParameter("identityKey", assessedIdentity.getKey()) - .setParameter("subIdent", subIdent) - .getResultList(); - return nodeAssessment.isEmpty() ? null : nodeAssessment.get(0); + .setParameter("identityKey", assessedIdentity.getKey()); + if(subIdent != null) { + query.setParameter("subIdent", subIdent); + } + if(referenceSoftKey != null) { + query.setParameter("softkey", referenceSoftKey); + } + List<AssessmentEntry> entries = query.getResultList(); + return entries.isEmpty() ? null : entries.get(0); } - public AssessmentEntry updateCourseNodeAssessment(AssessmentEntry nodeAssessment) { + public AssessmentEntry updateAssessmentEntry(AssessmentEntry nodeAssessment) { ((AssessmentEntryImpl)nodeAssessment).setLastModified(new Date()); return dbInstance.getCurrentEntityManager().merge(nodeAssessment); } diff --git a/src/main/java/org/olat/modules/assessment/manager/AssessmentServiceImpl.java b/src/main/java/org/olat/modules/assessment/manager/AssessmentServiceImpl.java new file mode 100644 index 00000000000..85103271194 --- /dev/null +++ b/src/main/java/org/olat/modules/assessment/manager/AssessmentServiceImpl.java @@ -0,0 +1,84 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.modules.assessment.manager; + +import java.util.List; + +import org.olat.core.commons.persistence.DB; +import org.olat.core.id.Identity; +import org.olat.modules.assessment.AssessmentEntry; +import org.olat.modules.assessment.AssessmentService; +import org.olat.repository.RepositoryEntry; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * + * Initial date: 23.07.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +@Service +public class AssessmentServiceImpl implements AssessmentService { + + @Autowired + private DB dbInstance; + @Autowired + private AssessmentEntryDAO assessmentEntryDao; + + @Override + public AssessmentEntry getOrCreateAssessmentEntry(Identity assessedIdentity, RepositoryEntry entry, String subIdent, + RepositoryEntry referenceEntry) { + + AssessmentEntry assessmentEntry = assessmentEntryDao.loadAssessmentEntry(assessedIdentity, entry, subIdent); + if(assessmentEntry == null) { + assessmentEntry = assessmentEntryDao.createCourseNodeAssessment(assessedIdentity, entry, subIdent, referenceEntry); + dbInstance.commit(); + } + return assessmentEntry; + } + + @Override + public AssessmentEntry loadAssessmentEntry(Identity assessedIdentity, RepositoryEntry entry, String subIdent) { + if(assessedIdentity == null || entry == null) return null; + return assessmentEntryDao.loadAssessmentEntry(assessedIdentity, entry, subIdent); + } + + @Override + public AssessmentEntry loadAssessmentEntry(Identity assessedIdentity, RepositoryEntry entry, String subIdent, String referenceSoftKey) { + if(assessedIdentity == null || entry == null) return null; + return assessmentEntryDao.loadAssessmentEntry(assessedIdentity, entry, subIdent, referenceSoftKey); + } + + @Override + public AssessmentEntry updateAssessmentEntry(AssessmentEntry entry) { + return assessmentEntryDao.updateAssessmentEntry(entry); + } + + @Override + public List<AssessmentEntry> loadAssessmentEntriesBySubIdent(RepositoryEntry entry, String subIdent) { + return assessmentEntryDao.loadAssessmentEntryBySubIdent(entry, subIdent); + } + + + + + +} diff --git a/src/main/java/org/olat/modules/assessment/model/AssessmentEntryImpl.java b/src/main/java/org/olat/modules/assessment/model/AssessmentEntryImpl.java index ca5d5c3da9d..ce35834cc4d 100644 --- a/src/main/java/org/olat/modules/assessment/model/AssessmentEntryImpl.java +++ b/src/main/java/org/olat/modules/assessment/model/AssessmentEntryImpl.java @@ -53,9 +53,15 @@ import org.olat.repository.RepositoryEntry; @Entity(name="assessmententry") @Table(name="o_as_entry") @NamedQueries({ - @NamedQuery(name="loadAssessmentEntryById", query="select data from assessmententry data where data.key=:key"), - @NamedQuery(name="loadAssessmentEntryByRepositoryEntryAndUser", query="select data from assessmententry data where data.repositoryEntry.key=:repositoryEntryKey and data.identity.key=:identityKey and data.subIdent=:subIdent"), - @NamedQuery(name="loadAssessmentEntryByRepositoryEntryAndSubIdent", query="select data from assessmententry data where data.repositoryEntry.key=:repositoryEntryKey and data.subIdent=:subIdent") + @NamedQuery(name="loadAssessmentEntryById", + query="select data from assessmententry data where data.key=:key"), + @NamedQuery(name="loadAssessmentEntryByRepositoryEntryAndUserAndSubIdent", + query="select data from assessmententry data where data.repositoryEntry.key=:repositoryEntryKey and data.identity.key=:identityKey and data.subIdent=:subIdent"), + @NamedQuery(name="loadAssessmentEntryByRepositoryEntryAndUserAndNullSubIdent", + query="select data from assessmententry data where data.repositoryEntry.key=:repositoryEntryKey and data.identity.key=:identityKey and data.subIdent is null"), + @NamedQuery(name="loadAssessmentEntryByRepositoryEntryAndSubIdent", + query="select data from assessmententry data where data.repositoryEntry.key=:repositoryEntryKey and data.subIdent=:subIdent") + }) diff --git a/src/main/resources/database/mysql/alter_10_x_0_to_11_0_0.sql b/src/main/resources/database/mysql/alter_10_x_0_to_11_0_0.sql index e4b4f1bbab4..e53734ee89a 100644 --- a/src/main/resources/database/mysql/alter_10_x_0_to_11_0_0.sql +++ b/src/main/resources/database/mysql/alter_10_x_0_to_11_0_0.sql @@ -1,26 +1,3 @@ -create table o_qti_assessment_session ( - id bigint not null auto_increment, - creationdate datetime not null, - lastmodified datetime not null, - q_exploded bit not null default 0, - q_author_mode bit not null default 0, - q_finish_time datetime, - q_termination_time datetime, - q_storage varchar(32), - fk_identity bigint not null, - fk_entry bigint not null, - fk_course bigint, - q_course_subident varchar(64), - primary key (id) -); -alter table o_qti_assessment_session ENGINE = InnoDB; - -alter table o_qti_assessment_session add constraint qti_sess_to_repo_entry_idx foreign key (fk_entry) references o_repositoryentry (repositoryentry_id); -alter table o_qti_assessment_session add constraint qti_sess_to_course_entry_idx foreign key (fk_course) references o_repositoryentry (repositoryentry_id); -alter table o_qti_assessment_session add constraint qti_sess_to_identity_idx foreign key (fk_identity) references o_bs_identity (id); - - - create table o_as_entry ( id bigint not null auto_increment, creationdate datetime not null, @@ -45,5 +22,29 @@ alter table o_as_entry ENGINE = InnoDB; alter table o_as_entry add constraint as_entry_to_identity_idx foreign key (fk_identity) references o_bs_identity (id); alter table o_as_entry add constraint as_entry_to_entry_idx foreign key (fk_entry) references o_repositoryentry (repositoryentry_id); alter table o_as_entry add constraint as_entry_to_refentry_idx foreign key (fk_reference_entry) references o_repositoryentry (repositoryentry_id); - create index idx_as_entry_to_id_idx on o_as_entry (a_assessment_id); + + + +create table o_qti_assessment_session ( + id bigint not null auto_increment, + creationdate datetime not null, + lastmodified datetime not null, + q_exploded bit not null default 0, + q_author_mode bit not null default 0, + q_finish_time datetime, + q_termination_time datetime, + q_storage varchar(32), + fk_reference_entry bigint not null, + fk_entry bigint, + q_subident varchar(64), + fk_identity bigint not null, + fk_assessment_entry bigint not null, + primary key (id) +); +alter table o_qti_assessment_session ENGINE = InnoDB; + +alter table o_qti_assessment_session add constraint qti_sess_to_repo_entry_idx foreign key (fk_entry) references o_repositoryentry (repositoryentry_id); +alter table o_qti_assessment_session add constraint qti_sess_to_course_entry_idx foreign key (fk_reference_entry) references o_repositoryentry (repositoryentry_id); +alter table o_qti_assessment_session add constraint qti_sess_to_identity_idx foreign key (fk_identity) references o_bs_identity (id); +alter table o_qti_assessment_session add constraint qti_sess_to_as_entry_idx foreign key (fk_assessment_entry) references o_as_entry (id); diff --git a/src/main/resources/database/mysql/setupDatabase.sql b/src/main/resources/database/mysql/setupDatabase.sql index 1988ee14ff9..497e85e3bcf 100644 --- a/src/main/resources/database/mysql/setupDatabase.sql +++ b/src/main/resources/database/mysql/setupDatabase.sql @@ -1221,10 +1221,11 @@ create table o_qti_assessment_session ( q_finish_time datetime, q_termination_time datetime, q_storage varchar(32), + fk_reference_entry bigint not null, + fk_entry bigint, + q_subident varchar(64), fk_identity bigint not null, - fk_entry bigint not null, - fk_course bigint, - q_course_subident varchar(64), + fk_assessment_entry bigint not null, primary key (id) ); @@ -2105,8 +2106,9 @@ create index o_mapper_uuid_idx on o_mapper (mapper_uuid); -- qti 2.1 alter table o_qti_assessment_session add constraint qti_sess_to_repo_entry_idx foreign key (fk_entry) references o_repositoryentry (repositoryentry_id); -alter table o_qti_assessment_session add constraint qti_sess_to_course_entry_idx foreign key (fk_course) references o_repositoryentry (repositoryentry_id); +alter table o_qti_assessment_session add constraint qti_sess_to_course_entry_idx foreign key (fk_reference_entry) references o_repositoryentry (repositoryentry_id); alter table o_qti_assessment_session add constraint qti_sess_to_identity_idx foreign key (fk_identity) references o_bs_identity (id); +alter table o_qti_assessment_session add constraint qti_sess_to_as_entry_idx foreign key (fk_assessment_entry) references o_as_entry (id); -- question pool alter table o_qp_pool add constraint idx_qp_pool_owner_grp_id foreign key (fk_ownergroup) references o_bs_secgroup(id); diff --git a/src/main/resources/database/postgresql/alter_10_x_0_to_11_0_0.sql b/src/main/resources/database/postgresql/alter_10_x_0_to_11_0_0.sql index ec896e6017d..6e76bea7136 100644 --- a/src/main/resources/database/postgresql/alter_10_x_0_to_11_0_0.sql +++ b/src/main/resources/database/postgresql/alter_10_x_0_to_11_0_0.sql @@ -1,28 +1,3 @@ -create table o_qti_assessment_session ( - id bigserial, - creationdate timestamp not null, - lastmodified timestamp not null, - q_exploded bool default false, - q_author_mode bool default false, - q_finish_time timestamp, - q_termination_time timestamp, - q_storage varchar(32), - fk_identity int8 not null, - fk_entry int8 not null, - fk_course int8, - q_course_subident varchar(64), - primary key (id) -); - -alter table o_qti_assessment_session add constraint qti_sess_to_repo_entry_idx foreign key (fk_entry) references o_repositoryentry (repositoryentry_id); -create index idx_testess_to_repo_entry_idx on o_qti_assessment_session (fk_entry); -alter table o_qti_assessment_session add constraint qti_sess_to_course_entry_idx foreign key (fk_course) references o_repositoryentry (repositoryentry_id); -create index idx_qti_sess_to_course_entry_idx on o_qti_assessment_session (fk_course); -alter table o_qti_assessment_session add constraint qti_sess_to_identity_idx foreign key (fk_identity) references o_bs_identity (id); -create index idx_qti_sess_to_identity_idx on o_qti_assessment_session (fk_identity); - - - create table o_as_entry ( id bigserial, creationdate timestamp not null, @@ -49,7 +24,34 @@ alter table o_as_entry add constraint as_entry_to_entry_idx foreign key (fk_entr create index idx_as_entry_to_entry_idx on o_as_entry (fk_entry); alter table o_as_entry add constraint as_entry_to_refentry_idx foreign key (fk_reference_entry) references o_repositoryentry (repositoryentry_id); create index idx_as_entry_to_refentry_idx on o_as_entry (fk_reference_entry); - create index idx_as_entry_to_id_idx on o_as_entry (a_assessment_id); + +create table o_qti_assessment_session ( + id bigserial, + creationdate timestamp not null, + lastmodified timestamp not null, + q_exploded bool default false, + q_author_mode bool default false, + q_finish_time timestamp, + q_termination_time timestamp, + q_storage varchar(32), + fk_reference_entry int8 not null, + fk_entry int8, + q_subident varchar(64), + fk_identity int8 not null, + fk_assessment_entry int8 not null, + primary key (id) +); + +alter table o_qti_assessment_session add constraint qti_sess_to_repo_entry_idx foreign key (fk_entry) references o_repositoryentry (repositoryentry_id); +create index idx_testess_to_repo_entry_idx on o_qti_assessment_session (fk_entry); +alter table o_qti_assessment_session add constraint qti_sess_to_course_entry_idx foreign key (fk_reference_entry) references o_repositoryentry (repositoryentry_id); +create index idx_qti_sess_to_course_entry_idx on o_qti_assessment_session (fk_reference_entry); +alter table o_qti_assessment_session add constraint qti_sess_to_identity_idx foreign key (fk_identity) references o_bs_identity (id); +create index idx_qti_sess_to_identity_idx on o_qti_assessment_session (fk_identity); +alter table o_qti_assessment_session add constraint qti_sess_to_as_entry_idx foreign key (fk_assessment_entry) references o_as_entry (id); +create index idx_qti_sess_to_as_entry_idx on o_qti_assessment_session (fk_assessment_entry); + + diff --git a/src/main/resources/database/postgresql/setupDatabase.sql b/src/main/resources/database/postgresql/setupDatabase.sql index 3cbe71a6ab2..edb770723b1 100644 --- a/src/main/resources/database/postgresql/setupDatabase.sql +++ b/src/main/resources/database/postgresql/setupDatabase.sql @@ -1222,10 +1222,11 @@ create table o_qti_assessment_session ( q_finish_time timestamp, q_termination_time timestamp, q_storage varchar(32), + fk_reference_entry int8 not null, + fk_entry int8, + q_subident varchar(64), fk_identity int8 not null, - fk_entry int8 not null, - fk_course int8, - q_course_subident varchar(64), + fk_assessment_entry int8 not null, primary key (id) ); @@ -2108,10 +2109,13 @@ create index o_mapper_uuid_idx on o_mapper (mapper_uuid); -- qti 2.1 alter table o_qti_assessment_session add constraint qti_sess_to_repo_entry_idx foreign key (fk_entry) references o_repositoryentry (repositoryentry_id); create index idx_testess_to_repo_entry_idx on o_qti_assessment_session (fk_entry); -alter table o_qti_assessment_session add constraint qti_sess_to_course_entry_idx foreign key (fk_course) references o_repositoryentry (repositoryentry_id); -create index idx_qti_sess_to_course_entry_idx on o_qti_assessment_session (fk_course); +alter table o_qti_assessment_session add constraint qti_sess_to_course_entry_idx foreign key (fk_reference_entry) references o_repositoryentry (repositoryentry_id); +create index idx_qti_sess_to_course_entry_idx on o_qti_assessment_session (fk_reference_entry); alter table o_qti_assessment_session add constraint qti_sess_to_identity_idx foreign key (fk_identity) references o_bs_identity (id); create index idx_qti_sess_to_identity_idx on o_qti_assessment_session (fk_identity); +alter table o_qti_assessment_session add constraint qti_sess_to_as_entry_idx foreign key (fk_assessment_entry) references o_as_entry (id); +create index idx_qti_sess_to_as_entry_idx on o_qti_assessment_session (fk_assessment_entry); + -- question pool alter table o_qp_pool add constraint idx_qp_pool_owner_grp_id foreign key (fk_ownergroup) references o_bs_secgroup(id); diff --git a/src/test/java/org/olat/ims/qti21/manager/SessionDAOTest.java b/src/test/java/org/olat/ims/qti21/manager/SessionDAOTest.java index dcb96d53c42..e6368471b17 100644 --- a/src/test/java/org/olat/ims/qti21/manager/SessionDAOTest.java +++ b/src/test/java/org/olat/ims/qti21/manager/SessionDAOTest.java @@ -27,6 +27,8 @@ import org.junit.Test; import org.olat.core.commons.persistence.DB; import org.olat.core.id.Identity; import org.olat.ims.qti21.UserTestSession; +import org.olat.modules.assessment.AssessmentEntry; +import org.olat.modules.assessment.AssessmentService; import org.olat.repository.RepositoryEntry; import org.olat.test.JunitTestHelper; import org.olat.test.OlatTestCase; @@ -44,15 +46,18 @@ public class SessionDAOTest extends OlatTestCase { private DB dbInstance; @Autowired private SessionDAO testSessionDao; + @Autowired + private AssessmentService assessmentService; @Test public void createTestSession_repo() { // prepare a test and a user RepositoryEntry testEntry = JunitTestHelper.createAndPersistRepositoryEntry(); Identity assessedIdentity = JunitTestHelper.createAndPersistIdentityAsRndUser("session-1"); + AssessmentEntry assessmentEntry = assessmentService.getOrCreateAssessmentEntry(assessedIdentity, testEntry, "-", testEntry); dbInstance.commit(); - UserTestSession testSession = testSessionDao.createTestSession(testEntry, null, null, assessedIdentity); + UserTestSession testSession = testSessionDao.createTestSession(testEntry, testEntry, "-", assessmentEntry, assessedIdentity, true); Assert.assertNotNull(testSession); dbInstance.commit(); } @@ -64,9 +69,10 @@ public class SessionDAOTest extends OlatTestCase { RepositoryEntry courseEntry = JunitTestHelper.createAndPersistRepositoryEntry(); String subIdent = UUID.randomUUID().toString(); Identity assessedIdentity = JunitTestHelper.createAndPersistIdentityAsRndUser("session-2"); + AssessmentEntry assessmentEntry = assessmentService.getOrCreateAssessmentEntry(assessedIdentity, courseEntry, subIdent, testEntry); dbInstance.commit(); - UserTestSession testSession = testSessionDao.createTestSession(testEntry, courseEntry, subIdent, assessedIdentity); + UserTestSession testSession = testSessionDao.createTestSession(testEntry, courseEntry, subIdent, assessmentEntry, assessedIdentity, false); Assert.assertNotNull(testSession); dbInstance.commit(); } @@ -78,9 +84,10 @@ public class SessionDAOTest extends OlatTestCase { RepositoryEntry courseEntry = JunitTestHelper.createAndPersistRepositoryEntry(); String subIdent = UUID.randomUUID().toString(); Identity assessedIdentity = JunitTestHelper.createAndPersistIdentityAsRndUser("session-3"); + AssessmentEntry assessmentEntry = assessmentService.getOrCreateAssessmentEntry(assessedIdentity, courseEntry, subIdent, testEntry); dbInstance.commit(); - UserTestSession testSession = testSessionDao.createTestSession(testEntry, courseEntry, subIdent, assessedIdentity); + UserTestSession testSession = testSessionDao.createTestSession(testEntry, courseEntry, subIdent, assessmentEntry, assessedIdentity, true); Assert.assertNotNull(testSession); dbInstance.commitAndCloseSession(); @@ -89,5 +96,32 @@ public class SessionDAOTest extends OlatTestCase { Assert.assertEquals(1, sessions.size()); Assert.assertEquals(testSession, sessions.get(0)); } + + @Test + public void getLastTestSession() { + // prepare a test and a user + RepositoryEntry testEntry = JunitTestHelper.createAndPersistRepositoryEntry(); + RepositoryEntry courseEntry = JunitTestHelper.createAndPersistRepositoryEntry(); + String subIdent = UUID.randomUUID().toString(); + Identity assessedIdentity = JunitTestHelper.createAndPersistIdentityAsRndUser("session-3"); + AssessmentEntry assessmentEntry = assessmentService.getOrCreateAssessmentEntry(assessedIdentity, courseEntry, subIdent, testEntry); + dbInstance.commit(); + + UserTestSession testSession1 = testSessionDao.createTestSession(testEntry, courseEntry, subIdent, assessmentEntry, assessedIdentity, false); + Assert.assertNotNull(testSession1); + dbInstance.commitAndCloseSession(); + + //to have a time difference + sleep(1500); + + UserTestSession testSession2 = testSessionDao.createTestSession(testEntry, courseEntry, subIdent, assessmentEntry, assessedIdentity, false); + Assert.assertNotNull(testSession2); + dbInstance.commitAndCloseSession(); + + //load the last session + UserTestSession lastTestSession = testSessionDao.getLastTestSession(testEntry, courseEntry, subIdent, assessedIdentity); + Assert.assertNotNull(lastTestSession); + Assert.assertEquals(testSession2, lastTestSession); + } } -- GitLab