/**
* <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.course.nodes.ta;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.olat.basesecurity.BaseSecurity;
import org.olat.core.CoreSpringFactory;
import org.olat.core.commons.modules.bc.FolderConfig;
import org.olat.core.commons.modules.bc.meta.MetaInfo;
import org.olat.core.commons.modules.bc.meta.tagged.MetaTagged;
import org.olat.core.commons.modules.bc.vfs.OlatRootFolderImpl;
import org.olat.core.commons.persistence.DBFactory;
import org.olat.core.id.Identity;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.util.StringHelper;
import org.olat.core.util.io.SystemFileFilter;
import org.olat.core.util.vfs.VFSContainer;
import org.olat.core.util.vfs.VFSItem;
import org.olat.core.util.vfs.VFSLeaf;
import org.olat.core.util.vfs.VFSManager;
import org.olat.course.ICourse;
import org.olat.course.assessment.AssessmentHelper;
import org.olat.course.assessment.AssessmentManager;
import org.olat.course.auditing.UserNodeAuditManager;
import org.olat.course.nodes.GTACourseNode;
import org.olat.course.nodes.MSCourseNode;
import org.olat.course.nodes.TACourseNode;
import org.olat.course.nodes.gta.GTAManager;
import org.olat.course.nodes.gta.GTAType;
import org.olat.course.nodes.gta.Task;
import org.olat.course.nodes.gta.TaskList;
import org.olat.course.nodes.gta.TaskProcess;
import org.olat.course.nodes.gta.model.Solution;
import org.olat.course.nodes.gta.model.SolutionList;
import org.olat.course.nodes.gta.model.TaskDefinition;
import org.olat.course.nodes.gta.model.TaskDefinitionList;
import org.olat.course.properties.CoursePropertyManager;
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.ModuleConfiguration;
import org.olat.modules.assessment.AssessmentEntry;
import org.olat.properties.Property;
/**
*
* Initial date: 30.03.2015<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class ConvertToGTACourseNode {
private static final OLog log = Tracing.createLoggerFor(ConvertToGTACourseNode.class);
private final GTAManager gtaManager;
private final BaseSecurity securityManager;
public ConvertToGTACourseNode() {
gtaManager = CoreSpringFactory.getImpl(GTAManager.class);
securityManager = CoreSpringFactory.getImpl(BaseSecurity.class);
}
public void convert(TACourseNode sourceNode, GTACourseNode gtaNode, ICourse course) {
ModuleConfiguration modConfig = sourceNode.getModuleConfiguration();
CourseEnvironment courseEnv = course.getCourseEnvironment();
gtaNode.setShortTitle("New_ " + sourceNode.getShortTitle());
gtaNode.setLongTitle("New_ " + sourceNode.getLongTitle());
gtaNode.setDisplayOption(sourceNode.getDisplayOption());
gtaNode.setLearningObjectives(sourceNode.getLearningObjectives());
TaskList taskList = gtaManager.createIfNotExists(courseEnv.getCourseGroupManager().getCourseEntry(), gtaNode);
DBFactory.getInstance().commit();
convertConfiguration(sourceNode, gtaNode);
if(modConfig.getBooleanSafe(TACourseNode.CONF_TASK_ENABLED)) {
convertTasks(taskList, sourceNode, gtaNode, course);
DBFactory.getInstance().commit();
}
if(modConfig.getBooleanSafe(TACourseNode.CONF_DROPBOX_ENABLED)) {
convertDropbox(taskList, sourceNode, gtaNode, courseEnv);
DBFactory.getInstance().commit();
}
if(modConfig.getBooleanSafe(TACourseNode.CONF_RETURNBOX_ENABLED)) {
convertReturnbox( taskList, sourceNode, gtaNode, courseEnv);
DBFactory.getInstance().commit();
}
if(modConfig.getBooleanSafe(TACourseNode.CONF_SCORING_ENABLED)) {
//copy the scores
convertAssessmentDatas(taskList, sourceNode, gtaNode, course);
DBFactory.getInstance().commit();
}
//solutions
if(modConfig.getBooleanSafe(TACourseNode.CONF_SOLUTION_ENABLED)) {
copySolutions(sourceNode, gtaNode, courseEnv);
}
}
private void convertTasks(TaskList taskList, TACourseNode sourceNode, GTACourseNode gtaNode, ICourse course) {
File taskFolder = new File(FolderConfig.getCanonicalRoot(), TACourseNode.getTaskFolderPathRelToFolderRoot(course, sourceNode));
OlatRootFolderImpl taskContainer = new OlatRootFolderImpl(TACourseNode.getTaskFolderPathRelToFolderRoot(course, sourceNode), null);
CourseEnvironment courseEnv = course.getCourseEnvironment();
File gtaskDirectory = gtaManager.getTasksDirectory(courseEnv, gtaNode);
VFSContainer gtaskContainer = gtaManager.getTasksContainer(courseEnv, gtaNode);
//make the task
TaskDefinitionList taskDefs = new TaskDefinitionList();
for(File task:taskFolder.listFiles(SystemFileFilter.FILES_ONLY)) {
TaskDefinition taskDef = new TaskDefinition();
taskDef.setDescription("");
taskDef.setFilename(task.getName());
taskDef.setTitle(task.getName());
taskDefs.getTasks().add(taskDef);
try {
File target = new File(gtaskDirectory, task.getName());
Files.copy(task.toPath(), target.toPath(), StandardCopyOption.REPLACE_EXISTING);
convertMetada(taskContainer, gtaskContainer, task.getName(), taskDef, null);
} catch(Exception ex) {
log.error("", ex);
}
List<Property> samples = courseEnv.getCoursePropertyManager().listCourseNodeProperties(sourceNode, null, null, TaskController.PROP_ASSIGNED);
for(Property sample:samples) {
File taskFile = new File(gtaskDirectory, sample.getStringValue());
Identity id = securityManager.loadIdentityByKey(sample.getIdentity().getKey());
gtaManager.selectTask(id, taskList, gtaNode, taskFile);
}
}
gtaNode.getModuleConfiguration().set(GTACourseNode.GTASK_TASKS, taskDefs);
}
private void convertDropbox(TaskList taskList, TACourseNode sourceNode, GTACourseNode gtaNode, CourseEnvironment courseEnv) {
String dropbox = DropboxController.getDropboxPathRelToFolderRoot(courseEnv, sourceNode);
OlatRootFolderImpl dropboxContainer = new OlatRootFolderImpl(dropbox, null);
for(VFSItem userDropbox:dropboxContainer.getItems()) {
if(userDropbox instanceof VFSContainer) {
VFSContainer userDropContainer = (VFSContainer)userDropbox;
String username = userDropContainer.getName();
Identity assessedIdentity = securityManager.findIdentityByName(username);
if(assessedIdentity != null) {
VFSContainer sumbitContainer = gtaManager.getSubmitContainer(courseEnv, gtaNode, assessedIdentity);
boolean dropped = false;
for(VFSItem dropppedItem:userDropContainer.getItems()) {
if(dropppedItem instanceof VFSLeaf) {
VFSLeaf submittedDocument = sumbitContainer.createChildLeaf(dropppedItem.getName());
VFSManager.copyContent((VFSLeaf)dropppedItem, submittedDocument);
convertMetada(userDropContainer, sumbitContainer, dropppedItem.getName(), null, null);
dropped = true;
}
}
if(dropped) {
setTaskStatus(taskList, assessedIdentity, TaskProcess.submit, gtaNode);
}
}
}
}
}
private void convertReturnbox(TaskList taskList, TACourseNode sourceNode, GTACourseNode gtaNode, CourseEnvironment courseEnv) {
String returnbox = ReturnboxController.getReturnboxPathRelToFolderRoot(courseEnv, sourceNode);
OlatRootFolderImpl returnContainer = new OlatRootFolderImpl(returnbox, null);
for(VFSItem item:returnContainer.getItems()) {
if(item instanceof VFSContainer) {
VFSContainer userContainer = (VFSContainer)item;
String username = userContainer.getName();
Identity assessedIdentity = securityManager.findIdentityByName(username);
if(assessedIdentity != null) {
VFSContainer correctionContainer = gtaManager.getCorrectionContainer(courseEnv, gtaNode, assessedIdentity);
boolean returned = false;
for(VFSItem returnedItem:userContainer.getItems()) {
if(returnedItem instanceof VFSLeaf) {
VFSLeaf correctionDocument = correctionContainer.createChildLeaf(returnedItem.getName());
VFSManager.copyContent((VFSLeaf)returnedItem, correctionDocument);
convertMetada(userContainer, correctionContainer, returnedItem.getName(), null, null);
returned = true;
}
}
if(returned) {
setTaskStatus(taskList, assessedIdentity, TaskProcess.grading, gtaNode);
}
}
}
}
}
private void convertAssessmentDatas(TaskList taskList, TACourseNode sourceNode, GTACourseNode gtaNode, ICourse course) {
CourseEnvironment courseEnv = course.getCourseEnvironment();
CoursePropertyManager propertyMgr = courseEnv.getCoursePropertyManager();
Map<Long,AssessmentEntry> datas = new HashMap<>();
List<AssessmentEntry> properties = courseEnv.getAssessmentManager().getAssessmentEntries(sourceNode);
for(AssessmentEntry property:properties) {
Identity identity = property.getIdentity();
datas.put(identity.getKey(), property);
}
properties = null;
DBFactory.getInstance().getCurrentEntityManager().clear();
AssessmentManager assessmentMgr = courseEnv.getAssessmentManager();
for(AssessmentEntry assessmentData:datas.values()) {
Identity assessedIdentity = securityManager.loadIdentityByKey(assessmentData.getIdentity().getKey());
if(assessmentData.getPassed() != null || assessmentData.getScore() != null) {
UserCourseEnvironment userCourseEnv = AssessmentHelper.createAndInitUserCourseEnvironment(assessedIdentity, course);
Float score = assessmentData.getScore() == null ? null : assessmentData.getScore().floatValue();
ScoreEvaluation scoreEval = new ScoreEvaluation(score, assessmentData.getPassed());
assessmentMgr.saveScoreEvaluation(gtaNode, null, assessedIdentity, scoreEval, userCourseEnv, false);
//set graded
Task task = gtaManager.getTask(assessedIdentity, taskList);
if(task == null) {
gtaManager.createTask(null, taskList, TaskProcess.graded, null, assessedIdentity, gtaNode);
} else {
gtaManager.updateTask(task, TaskProcess.graded, gtaNode);
}
}
if(assessmentData.getAttempts() != null) {
assessmentMgr.saveNodeAttempts(gtaNode, null, assessedIdentity, assessmentData.getAttempts().intValue());
}
if(StringHelper.containsNonWhitespace(assessmentData.getCoachComment())) {
assessmentMgr.saveNodeCoachComment(gtaNode, assessedIdentity, assessmentData.getCoachComment());
}
if(StringHelper.containsNonWhitespace(assessmentData.getComment())) {
assessmentMgr.saveNodeComment(gtaNode, null, assessedIdentity, assessmentData.getComment());
}
}
DBFactory.getInstance().getCurrentEntityManager().clear();
//copy log entries
List<Property> logEntries = propertyMgr
.listCourseNodeProperties(sourceNode, null, null, UserNodeAuditManager.LOG_IDENTIFYER);
for(Property logEntry:logEntries) {
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, logText);
} else {
targetProp.setTextValue(logText);
}
propertyMgr.saveProperty(targetProp);
}
}
private void copySolutions(TACourseNode sourceNode, GTACourseNode gtaNode, CourseEnvironment courseEnv) {
ModuleConfiguration gtaConfig = gtaNode.getModuleConfiguration();
String solutionPath = SolutionController.getSolutionPathRelToFolderRoot(courseEnv, sourceNode);
OlatRootFolderImpl solutionContainer = new OlatRootFolderImpl(solutionPath, null);
VFSContainer solutionDirectory = gtaManager.getSolutionsContainer(courseEnv, gtaNode);
SolutionList solutionList = new SolutionList();
for(VFSItem solution:solutionContainer.getItems()) {
if(solution instanceof VFSLeaf) {
VFSLeaf solutionDocument = solutionDirectory.createChildLeaf(solution.getName());
VFSManager.copyContent((VFSLeaf)solution, solutionDocument);
Solution solDef = new Solution();
convertMetada(solutionContainer, solutionDirectory, solution.getName(), null, solDef);
solDef.setFilename(solution.getName());
solutionList.getSolutions().add(solDef);
}
}
gtaConfig.set(GTACourseNode.GTASK_SOLUTIONS, solutionList);
}
private void convertConfiguration(TACourseNode sourceNode, GTACourseNode gtaNode) {
ModuleConfiguration gtaConfig = gtaNode.getModuleConfiguration();
ModuleConfiguration modConfig = sourceNode.getModuleConfiguration();
gtaConfig.setStringValue(GTACourseNode.GTASK_TYPE, GTAType.individual.name());
gtaConfig.setBooleanEntry(GTACourseNode.GTASK_ASSIGNMENT, modConfig.getBooleanSafe(TACourseNode.CONF_TASK_ENABLED));
if(TaskController.TYPE_AUTO.equals(modConfig.get(TACourseNode.CONF_TASK_TYPE))) {
gtaConfig.setStringValue(GTACourseNode.GTASK_ASSIGNEMENT_TYPE, GTACourseNode.GTASK_ASSIGNEMENT_TYPE_AUTO);
} else if(TaskController.TYPE_MANUAL.equals(modConfig.get(TACourseNode.CONF_TASK_TYPE))) {
gtaConfig.setStringValue(GTACourseNode.GTASK_ASSIGNEMENT_TYPE, GTACourseNode.GTASK_ASSIGNEMENT_TYPE_MANUAL);
} else {
gtaConfig.setStringValue(GTACourseNode.GTASK_ASSIGNEMENT_TYPE, GTACourseNode.GTASK_ASSIGNEMENT_TYPE_MANUAL);
}
gtaConfig.setBooleanEntry(GTACourseNode.GTASK_PREVIEW, modConfig.getBooleanSafe(TACourseNode.CONF_TASK_PREVIEW));
if(modConfig.getBooleanSafe(TACourseNode.CONF_TASK_SAMPLING_WITH_REPLACEMENT)) {
gtaConfig.setStringValue(GTACourseNode.GTASK_SAMPLING, GTACourseNode.GTASK_SAMPLING_REUSE);
} else {
gtaConfig.setStringValue(GTACourseNode.GTASK_SAMPLING, GTACourseNode.GTASK_SAMPLING_UNIQUE);
}
if(modConfig.get(TACourseNode.CONF_TASK_TEXT) != null) {
gtaConfig.setStringValue(GTACourseNode.GTASK_USERS_TEXT, modConfig.get(TACourseNode.CONF_TASK_TEXT).toString());
}
gtaConfig.setBooleanEntry(GTACourseNode.GTASK_SUBMIT, modConfig.getBooleanSafe(TACourseNode.CONF_DROPBOX_ENABLED));
//drop box options
String confirmation = modConfig.getStringValue(TACourseNode.CONF_DROPBOX_CONFIRMATION);
if(StringHelper.containsNonWhitespace(confirmation)) {
gtaConfig.setStringValue(GTACourseNode.GTASK_SUBMISSION_TEXT, confirmation);
gtaConfig.setBooleanEntry(GTACourseNode.GTASK_SUBMISSION_MAIL_CONFIRMATION, modConfig.getBooleanSafe(TACourseNode.CONF_DROPBOX_ENABLEMAIL));
}
gtaConfig.setBooleanEntry(GTACourseNode.GTASK_REVIEW_AND_CORRECTION, modConfig.getBooleanSafe(TACourseNode.CONF_RETURNBOX_ENABLED));
//passed
gtaConfig.setBooleanEntry(GTACourseNode.GTASK_GRADING, modConfig.getBooleanSafe(TACourseNode.CONF_SCORING_ENABLED));
//grading options
gtaConfig.set(MSCourseNode.CONFIG_KEY_HAS_SCORE_FIELD, modConfig.getBooleanEntry(MSCourseNode.CONFIG_KEY_HAS_SCORE_FIELD));
gtaConfig.set(MSCourseNode.CONFIG_KEY_SCORE_MIN, modConfig.get(MSCourseNode.CONFIG_KEY_SCORE_MIN));
gtaConfig.set(MSCourseNode.CONFIG_KEY_SCORE_MAX, modConfig.get(MSCourseNode.CONFIG_KEY_SCORE_MAX));
gtaConfig.set(MSCourseNode.CONFIG_KEY_HAS_PASSED_FIELD, modConfig.getBooleanEntry(MSCourseNode.CONFIG_KEY_HAS_PASSED_FIELD));
if(modConfig.get(MSCourseNode.CONFIG_KEY_PASSED_CUT_VALUE) != null) {
gtaConfig.set(MSCourseNode.CONFIG_KEY_PASSED_CUT_VALUE, modConfig.get(MSCourseNode.CONFIG_KEY_PASSED_CUT_VALUE));
}
gtaConfig.set(MSCourseNode.CONFIG_KEY_HAS_COMMENT_FIELD, modConfig.getBooleanEntry(MSCourseNode.CONFIG_KEY_HAS_COMMENT_FIELD));
gtaConfig.set(MSCourseNode.CONFIG_KEY_INFOTEXT_USER, modConfig.get(MSCourseNode.CONFIG_KEY_INFOTEXT_USER));
gtaConfig.set(MSCourseNode.CONFIG_KEY_INFOTEXT_COACH, modConfig.get(MSCourseNode.CONFIG_KEY_INFOTEXT_COACH));
gtaConfig.setBooleanEntry(GTACourseNode.GTASK_SAMPLE_SOLUTION, modConfig.getBooleanSafe(TACourseNode.CONF_SOLUTION_ENABLED));
}
private void setTaskStatus(TaskList taskList, Identity assessedIdentity, TaskProcess current, GTACourseNode gtaNode) {
TaskProcess process = gtaManager.nextStep(current, gtaNode);
Task task = gtaManager.getTask(assessedIdentity, taskList);
if(task == null) {
gtaManager.createTask(null, taskList, process, null, assessedIdentity, gtaNode);
} else {
gtaManager.updateTask(task, process, gtaNode);
}
}
private void convertMetada(VFSContainer source, VFSContainer target, String name, TaskDefinition taskDef, Solution solDef) {
VFSItem sourceItem = source.resolve(name);
VFSItem targetItem = target.resolve(name);
if(sourceItem instanceof MetaTagged && targetItem instanceof MetaTagged) {
MetaTagged taggedSource = (MetaTagged)sourceItem;
MetaInfo metaSource = taggedSource.getMetaInfo();
MetaTagged taggedTarget = (MetaTagged)targetItem;
MetaInfo metaTarget = taggedTarget.getMetaInfo();
if(metaSource != null) {
if(taskDef != null) {
if(StringHelper.containsNonWhitespace(metaSource.getTitle())) {
taskDef.setTitle(metaSource.getTitle());
}
taskDef.setDescription(metaSource.getComment());
}
if(solDef != null) {
if(StringHelper.containsNonWhitespace(metaSource.getTitle())) {
solDef.setTitle(metaSource.getTitle());
}
}
if(metaTarget != null) {
metaTarget.copyValues(metaSource);
metaTarget.write();
}
}
}
}
}