/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <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>
* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <hr>
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* This file has been modified by the OpenOLAT community. Changes are licensed
* under the Apache 2.0 license as the original file.
*/
package org.olat.course.assessment.manager;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.olat.basesecurity.IdentityRef;
import org.olat.core.commons.persistence.DB;
import org.olat.core.commons.persistence.DBFactory;
import org.olat.core.id.Identity;
import org.olat.core.id.OLATResourceable;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.util.coordinate.CoordinatorManager;
import org.olat.core.util.coordinate.SyncerExecutor;
import org.olat.core.util.resource.OresHelper;
import org.olat.core.util.xml.XStreamHelper;
import org.olat.course.CourseFactory;
import org.olat.course.CourseModule;
import org.olat.course.ICourse;
import org.olat.course.assessment.AssessmentChangedEvent;
import org.olat.course.assessment.AssessmentHelper;
import org.olat.course.assessment.AssessmentManager;
import org.olat.course.assessment.EfficiencyStatement;
import org.olat.course.assessment.EfficiencyStatementArchiver;
import org.olat.course.assessment.UserEfficiencyStatement;
import org.olat.course.assessment.model.AssessmentNodeData;
import org.olat.course.assessment.model.UserEfficiencyStatementImpl;
import org.olat.course.assessment.model.UserEfficiencyStatementLight;
import org.olat.course.assessment.model.UserEfficiencyStatementStandalone;
import org.olat.course.config.CourseConfig;
import org.olat.course.run.environment.CourseEnvironment;
import org.olat.course.run.userview.UserCourseEnvironment;
import org.olat.repository.RepositoryEntry;
import org.olat.repository.RepositoryEntryRef;
import org.olat.repository.model.RepositoryEntryRefImpl;
import org.olat.resource.OLATResource;
import org.olat.user.UserDataDeletable;
import org.olat.user.UserManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.thoughtworks.xstream.XStream;
/**
* Description:<br>
* Methods to update a users efficiency statement and to retrieve such statements
* from the database.
*
* <P>
* Initial Date: 11.08.2005 <br>
* @author gnaegi
*/
@Service
public class EfficiencyStatementManager implements UserDataDeletable {
private static final OLog log = Tracing.createLoggerFor(EfficiencyStatementManager.class);
public static final String KEY_ASSESSMENT_NODES = "assessmentNodes";
public static final String KEY_COURSE_TITLE = "courseTitle";
public static final String PROPERTY_CATEGORY = "efficiencyStatement";
@Autowired
private DB dbInstance;
@Autowired
private UserManager userManager;
private final XStream xstream = XStreamHelper.createXStreamInstance();
/**
* Updates the users efficiency statement for this course. <p>
* Called in AssessmentManager in a <code>doInSync</code> block, toghether with the saveScore.
* @param userCourseEnv
*/
public void updateUserEfficiencyStatement(UserCourseEnvironment userCourseEnv) {
RepositoryEntry re = userCourseEnv.getCourseEnvironment().getCourseGroupManager().getCourseEntry();
updateUserEfficiencyStatement(userCourseEnv, re);
}
public UserEfficiencyStatement createUserEfficiencyStatement(Date creationDate, Float score, Boolean passed, Identity identity, OLATResource resource) {
UserEfficiencyStatementImpl efficiencyProperty = new UserEfficiencyStatementImpl();
efficiencyProperty.setCreationDate(creationDate);
efficiencyProperty.setLastModified(new Date());
efficiencyProperty.setScore(score);
efficiencyProperty.setPassed(passed);
efficiencyProperty.setTotalNodes(0);
efficiencyProperty.setAttemptedNodes(0);
efficiencyProperty.setPassedNodes(0);
efficiencyProperty.setIdentity(identity);
efficiencyProperty.setResource(resource);
ICourse course = CourseFactory.loadCourse(resource.getResourceableId());
efficiencyProperty.setTitle(course.getCourseEnvironment().getCourseTitle());
efficiencyProperty.setShortTitle(course.getCourseEnvironment().getRunStructure().getRootNode().getShortTitle());
efficiencyProperty.setCourseRepoKey(course.getCourseEnvironment().getCourseGroupManager().getCourseEntry().getKey());
dbInstance.getCurrentEntityManager().persist(efficiencyProperty);
return efficiencyProperty;
}
public UserEfficiencyStatement createStandAloneUserEfficiencyStatement(Date creationDate, Float score, Boolean passed,
Identity identity, Long resourceKey, String courseTitle) {
UserEfficiencyStatementStandalone efficiencyProperty = new UserEfficiencyStatementStandalone();
efficiencyProperty.setCreationDate(creationDate);
efficiencyProperty.setLastModified(new Date());
efficiencyProperty.setScore(score);
efficiencyProperty.setPassed(passed);
efficiencyProperty.setTotalNodes(0);
efficiencyProperty.setAttemptedNodes(0);
efficiencyProperty.setPassedNodes(0);
efficiencyProperty.setIdentity(identity);
efficiencyProperty.setResourceKey(resourceKey);
efficiencyProperty.setTitle(courseTitle);
efficiencyProperty.setShortTitle(courseTitle);
efficiencyProperty.setCourseRepoKey(null);
dbInstance.getCurrentEntityManager().persist(efficiencyProperty);
return efficiencyProperty;
}
/**
* Updates the users efficiency statement for this course
* @param userCourseEnv
* @param repoEntryKey
* @param courseOres
*/
private void updateUserEfficiencyStatement(final UserCourseEnvironment userCourseEnv, final RepositoryEntry repoEntry) {
// o_clusterOK: by ld
CourseConfig cc = userCourseEnv.getCourseEnvironment().getCourseConfig();
// write only when enabled for this course
if (cc.isEfficencyStatementEnabled()) {
Identity identity = userCourseEnv.getIdentityEnvironment().getIdentity();
List<AssessmentNodeData> assessmentNodeList = AssessmentHelper.getAssessmentNodeDataList(userCourseEnv, true, true, true);
updateUserEfficiencyStatement(identity, userCourseEnv.getCourseEnvironment(), assessmentNodeList, repoEntry);
}
}
public void updateUserEfficiencyStatement(Identity assessedIdentity, final CourseEnvironment courseEnv, List<AssessmentNodeData> assessmentNodeList, final RepositoryEntry repoEntry) {
List<Map<String,Object>> assessmentNodes = AssessmentHelper.assessmentNodeDataListToMap(assessmentNodeList);
EfficiencyStatement efficiencyStatement = new EfficiencyStatement();
efficiencyStatement.setAssessmentNodes(assessmentNodes);
efficiencyStatement.setCourseTitle(courseEnv.getCourseTitle());
efficiencyStatement.setCourseRepoEntryKey(repoEntry.getKey());
String userInfos = userManager.getUserDisplayName(assessedIdentity);
efficiencyStatement.setDisplayableUserInfo(userInfos);
efficiencyStatement.setLastUpdated(System.currentTimeMillis());
boolean debug = log.isDebug();
UserEfficiencyStatementImpl efficiencyProperty = getUserEfficiencyStatementFull(repoEntry, assessedIdentity);
if (assessmentNodes != null) {
if (efficiencyProperty == null) {
// create new
efficiencyProperty = new UserEfficiencyStatementImpl();
efficiencyProperty.setIdentity(assessedIdentity);
efficiencyProperty.setCourseRepoKey(repoEntry.getKey());
if(repoEntry != null) {
efficiencyProperty.setResource(repoEntry.getOlatResource());
efficiencyProperty.setCourseRepoKey(repoEntry.getKey());
}
fillEfficiencyStatement(efficiencyStatement, efficiencyProperty);
dbInstance.getCurrentEntityManager().persist(efficiencyProperty);
if (debug) {
log.debug("creating new efficiency statement property::" + efficiencyProperty.getKey() + " for id::" + assessedIdentity.getName() + " repoEntry::" + repoEntry.getKey());
}
} else {
// update existing
if (debug) {
log.debug("updating efficiency statement property::" + efficiencyProperty.getKey() + " for id::" + assessedIdentity.getName() + " repoEntry::" + repoEntry.getKey());
}
fillEfficiencyStatement(efficiencyStatement, efficiencyProperty);
dbInstance.getCurrentEntityManager().merge(efficiencyProperty);
}
} else {
if (efficiencyProperty != null) {
// remove existing since now empty efficiency statements
if (debug) {
log.debug("removing efficiency statement property::" + efficiencyProperty.getKey() + " for id::" + assessedIdentity.getName() + " repoEntry::" + repoEntry.getKey() + " since empty");
}
dbInstance.getCurrentEntityManager().remove(efficiencyProperty);
}
// else nothing to create and nothing to delete
}
// send modified event to everybody
AssessmentChangedEvent ace = new AssessmentChangedEvent(AssessmentChangedEvent.TYPE_EFFICIENCY_STATEMENT_CHANGED, assessedIdentity);
OLATResourceable courseOres = OresHelper.createOLATResourceableInstance(CourseModule.class, courseEnv.getCourseResourceableId());
CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(ace, courseOres);
}
public void fillEfficiencyStatement(EfficiencyStatement efficiencyStatement, UserEfficiencyStatementImpl efficiencyProperty) {
List<Map<String,Object>> nodeData = efficiencyStatement.getAssessmentNodes();
if(!nodeData.isEmpty()) {
Map<String,Object> rootNode = nodeData.get(0);
Object passed = rootNode.get(AssessmentHelper.KEY_PASSED);
if(passed instanceof Boolean) {
efficiencyProperty.setPassed((Boolean)passed);
} else {
efficiencyProperty.setPassed(null);
}
Object fscore = rootNode.get(AssessmentHelper.KEY_SCORE_F);
if(fscore instanceof Float) {
efficiencyProperty.setScore((Float)fscore);
} else if(fscore instanceof Number) {
efficiencyProperty.setScore(((Number)fscore).floatValue());
} else {
efficiencyProperty.setScore(null);
}
Object shortTitle = rootNode.get(AssessmentHelper.KEY_TITLE_SHORT);
if(shortTitle instanceof String) {
efficiencyProperty.setShortTitle((String)shortTitle);
}
Object longTitle = rootNode.get(AssessmentHelper.KEY_TITLE_LONG);
if(longTitle instanceof String) {
efficiencyProperty.setTitle((String)longTitle);
}
int totalNodes = getTotalNodes(nodeData);
efficiencyProperty.setTotalNodes(totalNodes);
int attemptedNodes = getAttemptedNodes(nodeData);
efficiencyProperty.setAttemptedNodes(attemptedNodes);
int passedNodes = getPassedNodes(nodeData);
efficiencyProperty.setPassedNodes(passedNodes);
}
efficiencyProperty.setLastModified(new Date());
efficiencyProperty.setStatementXml(xstream.toXML(efficiencyStatement));
}
/**
* LD: Debug method.
* @param efficiencyStatement
*/
protected void printEfficiencyStatement(EfficiencyStatement efficiencyStatement) {
List<Map<String,Object>> assessmentNodes = efficiencyStatement.getAssessmentNodes();
if (assessmentNodes != null) {
Iterator<Map<String,Object>> iter = assessmentNodes.iterator();
while (iter.hasNext()) {
Map<String,Object> nodeData = iter.next();
String title = (String)nodeData.get(AssessmentHelper.KEY_TITLE_SHORT);
String score = (String)nodeData.get(AssessmentHelper.KEY_SCORE);
Boolean passed = (Boolean)nodeData.get(AssessmentHelper.KEY_PASSED);
Integer attempts = (Integer)nodeData.get(AssessmentHelper.KEY_ATTEMPTS);
String attemptsStr = attempts==null ? null : String.valueOf(attempts.intValue());
log.info("title: " + title + " score: " + score + " passed: " + passed + " attempts: " + attemptsStr);
}
}
}
/**
* Get the user efficiency statement list for this course
* @param courseRepoEntryKey
* @param identity
* @return Map containing a list of maps that contain the nodeData for this user and course using the
* keys defined in the AssessmentHelper and the title of the course
*/
public EfficiencyStatement getUserEfficiencyStatementByCourseRepositoryEntry(RepositoryEntry courseRepoEntry, Identity identity){
UserEfficiencyStatementImpl s = getUserEfficiencyStatementFull(courseRepoEntry, identity);
if(s == null || s.getStatementXml() == null) {
return null;
}
return (EfficiencyStatement)xstream.fromXML(s.getStatementXml());
}
public EfficiencyStatement getUserEfficiencyStatementByResourceKey(Long resourceKey, Identity identity){
StringBuilder sb = new StringBuilder();
sb.append("select statement from ").append(UserEfficiencyStatementStandalone.class.getName()).append(" as statement ")
.append(" where statement.identity.key=:identityKey and statement.resourceKey=:resourceKey");
List<UserEfficiencyStatementStandalone> statement = dbInstance.getCurrentEntityManager()
.createQuery(sb.toString(), UserEfficiencyStatementStandalone.class)
.setParameter("identityKey", identity.getKey())
.setParameter("resourceKey", resourceKey)
.getResultList();
if(statement.isEmpty() || statement.get(0).getStatementXml() == null) {
return null;
}
return (EfficiencyStatement)xstream.fromXML(statement.get(0).getStatementXml());
}
public UserEfficiencyStatementImpl getUserEfficiencyStatementFull(RepositoryEntryRef courseRepoEntry, Identity identity) {
try {
StringBuilder sb = new StringBuilder();
sb.append("select statement from ").append(UserEfficiencyStatementImpl.class.getName()).append(" as statement ")
.append(" where statement.identity.key=:identityKey and statement.courseRepoKey=:repoKey");
List<UserEfficiencyStatementImpl> statement = dbInstance.getCurrentEntityManager()
.createQuery(sb.toString(), UserEfficiencyStatementImpl.class)
.setParameter("identityKey", identity.getKey())
.setParameter("repoKey", courseRepoEntry.getKey())
.getResultList();
if(statement.isEmpty()) {
return null;
}
return statement.get(0);
} catch (Exception e) {
log.error("Cannot retrieve efficiency statement: " + courseRepoEntry.getKey() + " from " + identity, e);
return null;
}
}
public UserEfficiencyStatementImpl getUserEfficiencyStatementFullByResourceKey(Long resourceKey, Identity identity) {
try {
StringBuilder sb = new StringBuilder();
sb.append("select statement from ").append(UserEfficiencyStatementImpl.class.getName()).append(" as statement ")
.append(" where statement.identity.key=:identityKey")
.append(" and statement.resource.key=:resourceKey");
List<UserEfficiencyStatementImpl> statement = dbInstance.getCurrentEntityManager()
.createQuery(sb.toString(), UserEfficiencyStatementImpl.class)
.setParameter("identityKey", identity.getKey())
.setParameter("resourceKey", resourceKey)
.getResultList();
if(statement.isEmpty()) {
return null;
}
return statement.get(0);
} catch (Exception e) {
log.error("Cannot retrieve efficiency statement: " + resourceKey + " from " + identity, e);
return null;
}
}
public boolean hasUserEfficiencyStatement(Long courseRepoEntryKey, IdentityRef identity) {
StringBuilder sb = new StringBuilder();
sb.append("select statement.key from ").append(UserEfficiencyStatementLight.class.getName()).append(" as statement ")
.append(" where statement.identity.key=:identityKey and statement.courseRepoKey=:repoKey");
List<Number> count = dbInstance.getCurrentEntityManager()
.createQuery(sb.toString(), Number.class)
.setParameter("identityKey", identity.getKey())
.setParameter("repoKey", courseRepoEntryKey)
.setFirstResult(0)
.setMaxResults(1)
.getResultList();
return count != null && count.size() > 0;
}
public UserEfficiencyStatement getUserEfficiencyStatementLightByRepositoryEntry(RepositoryEntryRef courseRepo, IdentityRef identity) {
try {
StringBuilder sb = new StringBuilder();
sb.append("select statement from ").append(UserEfficiencyStatementLight.class.getName()).append(" as statement ")
.append(" where statement.identity.key=:identityKey and statement.courseRepoKey=:repoKey");
List<UserEfficiencyStatement> statement = dbInstance.getCurrentEntityManager()
.createQuery(sb.toString(), UserEfficiencyStatement.class)
.setParameter("identityKey", identity.getKey())
.setParameter("repoKey", courseRepo.getKey())
.getResultList();
if(statement.isEmpty()) {
return null;
}
return statement.get(0);
} catch (Exception e) {
log.error("Cannot retrieve efficiency statement: " + courseRepo.getKey() + " from " + identity, e);
return null;
}
}
public UserEfficiencyStatement getUserEfficiencyStatementLightByResource(Long resourceKey, IdentityRef identity) {
try {
StringBuilder sb = new StringBuilder();
sb.append("select statement from ").append(UserEfficiencyStatementLight.class.getName()).append(" as statement ")
.append(" where statement.identity.key=:identityKey and statement.resource.key=:resourceKey");
List<UserEfficiencyStatement> statement = dbInstance.getCurrentEntityManager()
.createQuery(sb.toString(), UserEfficiencyStatement.class)
.setParameter("identityKey", identity.getKey())
.setParameter("resourceKey", resourceKey)
.getResultList();
if(statement.isEmpty()) {
return null;
}
return statement.get(0);
} catch (Exception e) {
log.error("Cannot retrieve efficiency statement: " + resourceKey + " from " + identity, e);
return null;
}
}
public EfficiencyStatement getUserEfficiencyStatementByKey(Long key) {
try {
StringBuilder sb = new StringBuilder();
sb.append("select statement from ").append(UserEfficiencyStatementImpl.class.getName()).append(" as statement ")
.append(" where statement.key=:key");
List<UserEfficiencyStatementImpl> statement = dbInstance.getCurrentEntityManager()
.createQuery(sb.toString(), UserEfficiencyStatementImpl.class)
.setParameter("key", key)
.getResultList();
if(statement.isEmpty()) {
return null;
}
return (EfficiencyStatement)xstream.fromXML(statement.get(0).getStatementXml());
} catch (Exception e) {
log.error("Cannot retrieve efficiency statement: " + key, e);
return null;
}
}
public UserEfficiencyStatementLight getUserEfficiencyStatementLightByKey(Long key) {
StringBuilder sb = new StringBuilder();
sb.append("select statement from ").append(UserEfficiencyStatementLight.class.getName()).append(" as statement ")
.append(" where statement.key=:key");
List<UserEfficiencyStatementLight> statement = dbInstance.getCurrentEntityManager()
.createQuery(sb.toString(), UserEfficiencyStatementLight.class)
.setParameter("key", key)
.getResultList();
if(statement.isEmpty()) {
return null;
}
return statement.get(0);
}
/**
* Get the passed value of a course node of a specific efficiency statment
* @param nodeIdent
* @param efficiencyStatement
* @return true if passed, false if not, null if node not found
*/
public Boolean getPassed(String nodeIdent, EfficiencyStatement efficiencyStatement) {
List<Map<String,Object>> assessmentNodes = efficiencyStatement.getAssessmentNodes();
if (assessmentNodes != null) {
Iterator<Map<String,Object>> iter = assessmentNodes.iterator();
while (iter.hasNext()) {
Map<String,Object> nodeData = iter.next();
if (nodeData.get(AssessmentHelper.KEY_IDENTIFYER).equals(nodeIdent)) {
return (Boolean) nodeData.get(AssessmentHelper.KEY_PASSED);
}
}
}
return null;
}
public int getTotalNodes(List<Map<String,Object>> assessmentNodes) {
int count = 0;
for (Iterator<Map<String,Object>> iter = assessmentNodes.iterator(); iter.hasNext(); ) {
Map<String,Object> nodeData = iter.next();
Boolean selectable = (Boolean)nodeData.get(AssessmentHelper.KEY_SELECTABLE);
if(selectable != null && selectable.booleanValue()) {
count++;
}
}
return count;
}
public int getAttemptedNodes(List<Map<String,Object>> assessmentNodes) {
int count = 0;
for (Iterator<Map<String,Object>> iter = assessmentNodes.iterator(); iter.hasNext(); ) {
Map<String,Object> nodeData = iter.next();
Boolean selectable = (Boolean)nodeData.get(AssessmentHelper.KEY_SELECTABLE);
if(selectable != null && selectable.booleanValue()) {
if(nodeData.containsKey(AssessmentHelper.KEY_SCORE)) {
count++;
} else if (nodeData.containsKey(AssessmentHelper.KEY_PASSED)) {
count++;
}
}
}
return count;
}
public int getPassedNodes(List<Map<String,Object>> assessmentNodes) {
int count = 0;
for (Iterator<Map<String,Object>> iter = assessmentNodes.iterator(); iter.hasNext(); ) {
Map<String,Object> nodeData = iter.next();
Boolean passed = (Boolean)nodeData.get(AssessmentHelper.KEY_PASSED);
Boolean selectable = (Boolean)nodeData.get(AssessmentHelper.KEY_SELECTABLE);
if(passed != null && passed.booleanValue() && selectable != null && selectable.booleanValue()) {
count++;
}
}
return count;
}
/**
* Get the score value of a course node of a specific efficiency statment
* @param nodeIdent
* @param efficiencyStatement
* @return the score, null if node not found
*/
public Double getScore(String nodeIdent, EfficiencyStatement efficiencyStatement) {
List<Map<String,Object>> assessmentNodes = efficiencyStatement.getAssessmentNodes();
if (assessmentNodes != null) {
Iterator<Map<String,Object>> iter = assessmentNodes.iterator();
while (iter.hasNext()) {
Map<String,Object> nodeData = iter.next();
if (nodeData.get(AssessmentHelper.KEY_IDENTIFYER).equals(nodeIdent)) {
String scoreString = (String) nodeData.get(AssessmentHelper.KEY_SCORE);
return Double.valueOf(scoreString);
}
}
}
return null;
}
/**
* Find all efficiency statements for a specific user
* @param identity
* @return List of efficiency statements
*/
protected List<EfficiencyStatement> findEfficiencyStatements(Identity identity) {
List<EfficiencyStatement> efficiencyStatements = new ArrayList<EfficiencyStatement>();
try {
StringBuilder sb = new StringBuilder();
sb.append("select statement from ").append(UserEfficiencyStatementImpl.class.getName()).append(" as statement ")
.append(" where statement.identity.key=:identityKey");
List<UserEfficiencyStatementImpl> statements = dbInstance.getCurrentEntityManager()
.createQuery(sb.toString(), UserEfficiencyStatementImpl.class)
.setParameter("identityKey", identity.getKey())
.getResultList();
for(UserEfficiencyStatementImpl statement:statements) {
EfficiencyStatement s = (EfficiencyStatement)xstream.fromXML(statement.getStatementXml());
efficiencyStatements.add(s);
}
} catch (Exception e) {
log.error("findEfficiencyStatements: " + identity, e);
}
return efficiencyStatements;
}
public List<UserEfficiencyStatementLight> findEfficiencyStatementsLight(Identity identity) {
try {
StringBuilder sb = new StringBuilder();
sb.append("select statement from ").append(UserEfficiencyStatementLight.class.getName()).append(" as statement ")
.append(" left join fetch statement.resource resource")
.append(" where statement.identity.key=:identityKey");
return dbInstance.getCurrentEntityManager()
.createQuery(sb.toString(), UserEfficiencyStatementLight.class)
.setParameter("identityKey", identity.getKey())
.getResultList();
} catch (Exception e) {
log.error("findEfficiencyStatements: " + identity, e);
return Collections.emptyList();
}
}
public List<UserEfficiencyStatementLight> findEfficiencyStatementsLight(List<Long> keys) {
if(keys == null || keys.isEmpty()) return Collections.emptyList();
StringBuilder sb = new StringBuilder();
sb.append("select statement from ").append(UserEfficiencyStatementLight.class.getName()).append(" as statement ")
.append(" left join fetch statement.resource resource")
.append(" where statement.key in (:keys)");
return dbInstance.getCurrentEntityManager()
.createQuery(sb.toString(), UserEfficiencyStatementLight.class)
.setParameter("keys", keys)
.getResultList();
}
/**
* Find all identities who have an efficiency statement for this course repository entry
* @param courseRepoEntryKey
* @return List of identities
*/
protected List<Identity> findIdentitiesWithEfficiencyStatements(Long courseRepoEntryKey) {
try {
StringBuilder sb = new StringBuilder();
sb.append("select distinct(statement.identity) from ").append(UserEfficiencyStatementImpl.class.getName()).append(" as statement ")
.append(" where statement.courseRepoKey=:repoKey");
return dbInstance.getCurrentEntityManager()
.createQuery(sb.toString(), Identity.class)
.setParameter("repoKey", courseRepoEntryKey)
.getResultList();
} catch (Exception e) {
log.error("findIdentitiesWithEfficiencyStatements: " + courseRepoEntryKey, e);
return Collections.emptyList();
}
}
/**
* Delete all efficiency statements from the given course for all users
* @param courseRepoEntryKey
* @return int number of deleted efficiency statements
*/
public void deleteEfficiencyStatementsFromCourse(Long courseRepoEntryKey) {
try {
StringBuilder sb = new StringBuilder();
sb.append("select statement from ").append(UserEfficiencyStatementImpl.class.getName()).append(" as statement ")
.append(" where statement.courseRepoKey=:repoKey");
List<UserEfficiencyStatementImpl> statements = dbInstance.getCurrentEntityManager()
.createQuery(sb.toString(), UserEfficiencyStatementImpl.class)
.setParameter("repoKey", courseRepoEntryKey)
.getResultList();
for(UserEfficiencyStatementImpl statement:statements) {
dbInstance.deleteObject(statement);
}
} catch (Exception e) {
log.error("deleteEfficiencyStatementsFromCourse: " + courseRepoEntryKey, e);
}
}
/**
* Delete the given efficiency statement for this person
* @param identity
* @param efficiencyStatement
*/
protected void deleteEfficiencyStatement(Identity identity, EfficiencyStatement efficiencyStatement) {
RepositoryEntryRef ref = new RepositoryEntryRefImpl(efficiencyStatement.getCourseRepoEntryKey());
UserEfficiencyStatement s = getUserEfficiencyStatementLightByRepositoryEntry(ref, identity);
if(s != null) {
dbInstance.getCurrentEntityManager().remove(s);
}
}
/**
* Delete the given efficiency statement for this person
* @param efficiencyStatement
*/
public void deleteEfficiencyStatement(UserEfficiencyStatementLight efficiencyStatement) {
dbInstance.getCurrentEntityManager().remove(efficiencyStatement);
}
/**
* Create or update all efficiency statment lists for the given list of identities and this course
* This is called from only one thread, since the course is locked at editing (either CourseEdit or CourseDetails edit).
*
* @param ores The resource to load the course
* @param identities List of identities
* false: always create new one (be careful with this one!)
*/
public void updateEfficiencyStatements(final RepositoryEntry courseEntry, List<Identity> identities) {
if (identities.size() > 0) {
final ICourse course = CourseFactory.loadCourse(courseEntry);
log.audit("Updating efficiency statements for course::" + course.getResourceableId() + ", this might produce temporary heavy load on the CPU");
// preload cache to speed up things
AssessmentManager am = course.getCourseEnvironment().getAssessmentManager();
int count = 0;
for (Identity identity : identities) {
//o_clusterOK: by ld
OLATResourceable efficiencyStatementResourceable = am.createOLATResourceableForLocking(identity);
CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync(efficiencyStatementResourceable, new SyncerExecutor() {
@Override
public void execute() {
// create temporary user course env
UserCourseEnvironment uce = AssessmentHelper.createInitAndUpdateUserCourseEnvironment(identity, course);
updateUserEfficiencyStatement(uce, courseEntry);
}
});
if (Thread.interrupted()) {
break;
}
if(++count % 10 == 0) {
DBFactory.getInstance().commitAndCloseSession();
}
}
}
}
public void archiveUserData(Identity identity, File archiveDir) {
List<EfficiencyStatement> efficiencyStatements = findEfficiencyStatements(identity);
EfficiencyStatementArchiver.getInstance().archive(efficiencyStatements, identity, archiveDir);
}
/**
* Archive efficiency statement and than delete them for the specified identity.
*
* @param identity Delete data for this identity.
*/
@Override
public void deleteUserData(Identity identity, String newDeletedUserName, File archivePath) {
archiveUserData(identity, archivePath);
deleteEfficientyStatement(identity);
}
public void deleteEfficientyStatement(Identity identity) {
try {
StringBuilder sb = new StringBuilder();
sb.append("delete from ").append(UserEfficiencyStatementImpl.class.getName()).append(" as statement ")
.append(" where statement.identity.key=:identityKey");
int numOfDeletedStatements = dbInstance.getCurrentEntityManager()
.createQuery(sb.toString())
.setParameter("identityKey", identity.getKey())
.executeUpdate();
if(log.isDebug()) log.debug(numOfDeletedStatements + " efficiency statements deleted for identity=" + identity);
} catch (Exception e) {
log.error("deleteUserData(EfficiencyStatements): " + identity, e);
}
}
}