use of org.olat.course.tree.CourseEditorTreeModel in project openolat by klemens.
the class PublishProcessTest method testPublishProcess.
/**
* Publish process without error
* @throws URISyntaxException
*/
@Test
public void testPublishProcess() throws URISyntaxException {
Identity author = JunitTestHelper.createAndPersistIdentityAsAdmin("publisher-" + UUID.randomUUID().toString());
RepositoryEntry re = deployTestCourse("simple_course.zip");
// change node 1
ICourse course = CourseFactory.openCourseEditSession(re.getOlatResource().getResourceableId());
CourseEditorTreeModel cetm = course.getEditorTreeModel();
CourseEditorTreeNode node1 = (CourseEditorTreeNode) cetm.getRootNode().getChildAt(0);
node1.getCourseNode().setShortTitle("Node 1 prime");
cetm.nodeConfigChanged(node1);
CourseFactory.saveCourseEditorTreeModel(course.getResourceableId());
CourseFactory.closeCourseEditSession(course.getResourceableId(), true);
// publish the course
List<String> nodeIds = Collections.singletonList(node1.getIdent());
publishCourse(nodeIds, re, author);
// check the change
ICourse reloadedCourse = CourseFactory.loadCourse(re.getOlatResource().getResourceableId());
Assert.assertEquals(3, reloadedCourse.getRunStructure().getRootNode().getChildCount());
INode runNode1 = reloadedCourse.getRunStructure().getRootNode().getChildAt(0);
Assert.assertNotNull(runNode1);
CourseNode runNode1Impl = (CourseNode) runNode1;
Assert.assertEquals("Node 1 prime", runNode1Impl.getShortTitle());
}
use of org.olat.course.tree.CourseEditorTreeModel in project openolat by klemens.
the class PublishProcessTest method testPublishNewNodeNotMarkedAsSuchAndNotPublished.
/**
* Publish a course with a node marked as not new but
* the node doesn't exist in the run structure. The node
* itself is not published.
*
* @throws URISyntaxException
*/
@Test
public void testPublishNewNodeNotMarkedAsSuchAndNotPublished() throws URISyntaxException {
Identity author = JunitTestHelper.createAndPersistIdentityAsAdmin("publisher-" + UUID.randomUUID().toString());
RepositoryEntry re = deployTestCourse("simple_course_err5_not_new_or_published.zip");
// change node 1
ICourse course = CourseFactory.loadCourse(re.getOlatResource().getResourceableId());
CourseEditorTreeModel cetm = course.getEditorTreeModel();
// publish the course and must survive this without exception
// as the course has no changes but we try to publish it
List<String> nodeIds = Collections.singletonList(cetm.getRootNode().getIdent());
publishCourse(nodeIds, re, author);
// check the change
ICourse reloadedCourse = CourseFactory.loadCourse(re.getOlatResource().getResourceableId());
Assert.assertEquals(2, reloadedCourse.getRunStructure().getRootNode().getChildCount());
INode runNode1 = reloadedCourse.getRunStructure().getRootNode().getChildAt(0);
Assert.assertNotNull(runNode1);
CourseNode runNode1Impl = (CourseNode) runNode1;
Assert.assertEquals("Node 2", runNode1Impl.getShortTitle());
}
use of org.olat.course.tree.CourseEditorTreeModel in project openolat by klemens.
the class NodeExportVisitor method exportToFilesystem.
/**
* @see org.olat.course.ICourse#exportToFilesystem(java.io.File)
* <p>
* See OLAT-5368: Course Export can take longer than say 2min.
* <p>
*/
@Override
public void exportToFilesystem(OLATResource originalCourseResource, File exportDirectory, boolean runtimeDatas, boolean backwardsCompatible) {
long s = System.currentTimeMillis();
log.info("exportToFilesystem: exporting course " + this + " to " + exportDirectory + "...");
File fCourseBase = getCourseBaseContainer().getBasefile();
// make the folder structure
File fExportedDataDir = new File(exportDirectory, EXPORTED_DATA_FOLDERNAME);
fExportedDataDir.mkdirs();
// export course config
FileUtils.copyFileToDir(new File(fCourseBase, CourseConfigManager.COURSECONFIG_XML), exportDirectory, "course export courseconfig");
// export business groups
CourseEnvironmentMapper envMapper = getCourseEnvironment().getCourseGroupManager().getBusinessGroupEnvironment();
if (backwardsCompatible) {
// prevents duplicate names
envMapper.avoidDuplicateNames();
}
getCourseEnvironment().getCourseGroupManager().exportCourseBusinessGroups(fExportedDataDir, envMapper, runtimeDatas, backwardsCompatible);
if (backwardsCompatible) {
XStream xstream = CourseXStreamAliases.getReadCourseXStream();
Structure exportedStructure = (Structure) XStreamHelper.readObject(xstream, new File(fCourseBase, RUNSTRUCTURE_XML));
visit(new NodePostExportVisitor(envMapper, backwardsCompatible), exportedStructure.getRootNode());
XStreamHelper.writeObject(xstream, new File(exportDirectory, RUNSTRUCTURE_XML), exportedStructure);
CourseEditorTreeModel exportedEditorModel = (CourseEditorTreeModel) XStreamHelper.readObject(xstream, new File(fCourseBase, EDITORTREEMODEL_XML));
visit(new NodePostExportVisitor(envMapper, backwardsCompatible), exportedEditorModel.getRootNode());
XStreamHelper.writeObject(xstream, new File(exportDirectory, EDITORTREEMODEL_XML), exportedEditorModel);
} else {
// export editor structure
FileUtils.copyFileToDir(new File(fCourseBase, EDITORTREEMODEL_XML), exportDirectory, "course export exitortreemodel");
// export run structure
FileUtils.copyFileToDir(new File(fCourseBase, RUNSTRUCTURE_XML), exportDirectory, "course export runstructure");
}
// export layout and media folder
FileUtils.copyDirToDir(new File(fCourseBase, "layout"), exportDirectory, "course export layout folder");
FileUtils.copyDirToDir(new File(fCourseBase, "media"), exportDirectory, "course export media folder");
// export course folder
FileUtils.copyDirToDir(getIsolatedCourseBaseFolder(), exportDirectory, "course export folder");
// export any node data
log.info("exportToFilesystem: exporting course " + this + ": exporting all nodes...");
Visitor visitor = new NodeExportVisitor(fExportedDataDir, this);
TreeVisitor tv = new TreeVisitor(visitor, getEditorTreeModel().getRootNode(), true);
tv.visitAll();
log.info("exportToFilesystem: exporting course " + this + ": exporting all nodes...done.");
// OLAT-5368: do intermediate commit to avoid transaction timeout
// discussion intermediatecommit vs increased transaction timeout:
// pro intermediatecommit: not much
// pro increased transaction timeout: would fix OLAT-5368 but only move the problem
// @TODO OLAT-2597: real solution is a long-running background-task concept...
DBFactory.getInstance().intermediateCommit();
// export shared folder
CourseConfig config = getCourseConfig();
if (config.hasCustomSharedFolder()) {
log.info("exportToFilesystem: exporting course " + this + ": shared folder...");
if (!SharedFolderManager.getInstance().exportSharedFolder(config.getSharedFolderSoftkey(), fExportedDataDir)) {
// export failed, delete reference to shared folder in the course config
log.info("exportToFilesystem: exporting course " + this + ": export of shared folder failed.");
config.setSharedFolderSoftkey(CourseConfig.VALUE_EMPTY_SHAREDFOLDER_SOFTKEY);
CourseConfigManagerImpl.getInstance().saveConfigTo(this, config);
}
log.info("exportToFilesystem: exporting course " + this + ": shared folder...done.");
}
// OLAT-5368: do intermediate commit to avoid transaction timeout
// discussion intermediatecommit vs increased transaction timeout:
// pro intermediatecommit: not much
// pro increased transaction timeout: would fix OLAT-5368 but only move the problem
// @TODO OLAT-2597: real solution is a long-running background-task concept...
DBFactory.getInstance().intermediateCommit();
// export glossary
if (config.hasGlossary()) {
log.info("exportToFilesystem: exporting course " + this + ": glossary...");
if (!GlossaryManager.getInstance().exportGlossary(config.getGlossarySoftKey(), fExportedDataDir)) {
// export failed, delete reference to glossary in the course config
log.info("exportToFilesystem: exporting course " + this + ": export of glossary failed.");
config.setGlossarySoftKey(null);
CourseConfigManagerImpl.getInstance().saveConfigTo(this, config);
}
log.info("exportToFilesystem: exporting course " + this + ": glossary...done.");
}
// OLAT-5368: do intermediate commit to avoid transaction timeout
// discussion intermediatecommit vs increased transaction timeout:
// pro intermediatecommit: not much
// pro increased transaction timeout: would fix OLAT-5368 but only move the problem
// @TODO OLAT-2597: real solution is a long-running background-task concept...
DBFactory.getInstance().intermediateCommit();
log.info("exportToFilesystem: exporting course " + this + ": configuration and repo data...");
// export configuration file
FileUtils.copyFileToDir(new File(fCourseBase, CourseConfigManager.COURSECONFIG_XML), exportDirectory, "course export configuration and repo info");
// export repo metadata
RepositoryManager rm = RepositoryManager.getInstance();
RepositoryEntry myRE = rm.lookupRepositoryEntry(this, true);
RepositoryEntryImportExport importExport = new RepositoryEntryImportExport(myRE, fExportedDataDir);
importExport.exportDoExportProperties();
// OLAT-5368: do intermediate commit to avoid transaction timeout
// discussion intermediatecommit vs increased transaction timeout:
// pro intermediatecommit: not much
// pro increased transaction timeout: would fix OLAT-5368 but only move the problem
// @TODO OLAT-2597: real solution is a long-running background-task concept...
DBFactory.getInstance().intermediateCommit();
// export reminders
CoreSpringFactory.getImpl(ReminderService.class).exportReminders(myRE, fExportedDataDir);
log.info("exportToFilesystem: exporting course " + this + " to " + exportDirectory + " done.");
log.info("finished export course '" + getCourseTitle() + "' in t=" + Long.toString(System.currentTimeMillis() - s));
}
use of org.olat.course.tree.CourseEditorTreeModel in project openolat by klemens.
the class NodeExportVisitor method postCopy.
@Override
public void postCopy(CourseEnvironmentMapper envMapper, ICourse sourceCourse) {
Structure importedStructure = getRunStructure();
visit(new NodePostCopyVisitor(envMapper, Processing.runstructure, this, sourceCourse), importedStructure.getRootNode());
saveRunStructure();
CourseEditorTreeModel importedEditorModel = getEditorTreeModel();
visit(new NodePostCopyVisitor(envMapper, Processing.editor, this, sourceCourse), importedEditorModel.getRootNode());
saveEditorTreeModel();
}
use of org.olat.course.tree.CourseEditorTreeModel in project openolat by klemens.
the class PublishProcess method testPublishSet.
/**
* can only be called after createPublishSetFor method. The method calculates the
* resulting runstructure, and checks them against error and warning messages.
* These are returned as a list of StatusDescriptions.<br>
* If status ok -> apply the publish set -> this changes the course effectively
*
* @param locale
* @return
*/
public PublishSetInformations testPublishSet(Locale locale) {
// check for valid references to tests, resource folder, wiki
List<StatusDescription> damagedRefsInsertedNodes = checkRefs(editorModelInsertedNodes);
if (damagedRefsInsertedNodes.size() > 0) {
// abort testing as a blocking error found!
StatusDescription[] status = new StatusDescription[damagedRefsInsertedNodes.size()];
status = damagedRefsInsertedNodes.toArray(status);
return new PublishSetInformations(status);
}
List<StatusDescription> damagedRefsModifiedNodes = checkRefs(editorModelModifiedNodes);
if (damagedRefsModifiedNodes.size() > 0) {
// abort testing as a blocking error found
StatusDescription[] status = new StatusDescription[damagedRefsModifiedNodes.size()];
status = damagedRefsModifiedNodes.toArray(status);
return new PublishSetInformations(status);
}
CourseNode clonedCourseNode = (CourseNode) ObjectCloner.deepCopy(resultingCourseRun.getRootNode());
CourseEditorTreeNode clonedRoot = new CourseEditorTreeNode(clonedCourseNode);
convertInCourseEditorTreeNode(clonedRoot, clonedCourseNode);
// Do remove all children after convertInCourseEditorTreeNode
clonedCourseNode.removeAllChildren();
CourseEditorTreeModel cloneCETM = new CourseEditorTreeModel();
cloneCETM.setRootNode(clonedRoot);
/*
* now we have the cloned editor tree synchronized with the pre-published
* runstructure. The cloned editor tree is used within a new
* CourseEditorEnvironment which is placed in a new Editor User Course
* Session for evaluation only. This is like opening the runstructure in a
* virtual course editor for using the validation facilities of the editor
* environment.
*/
CourseEditorEnv tmpCEV = new CourseEditorEnvImpl(cloneCETM, course.getCourseEnvironment().getCourseGroupManager(), locale);
// the resulting object is not needed, but constructor makes
// initializations within tmpCEV!! thus important step.
new EditorUserCourseEnvironmentImpl(tmpCEV, null);
//
tmpCEV.setCurrentCourseNodeId(cloneCETM.getRootNode().getIdent());
tmpCEV.validateCourse();
StatusDescription[] status = tmpCEV.getCourseStatus();
// check if the resulting course contains cycles.
Set<String> nodesInCycle = tmpCEV.listCycles();
if (nodesInCycle.size() > 0) {
// there are nodes generating cylces -> error! this is not a publishable
// set!
StringBuilder sb = new StringBuilder();
for (String id : nodesInCycle) {
String title = editorTreeModel.getCourseEditorNodeById(id).getTitle();
sb.append("<b>").append(title).append("</b> ").append("(id:").append(id).append(")<br>");
}
StatusDescription sd = new StatusDescription(ValidationStatus.ERROR, "pbl.error.cycles", "pbl.error.cycles", new String[] { sb.toString() }, PACKAGE);
status = new StatusDescription[] { sd };
} else {
/*
* these are now status description as they are helpful in the editor
* context. The same errors in the publish context have a kind of
* different meaning --- Let the nodes explain what it means in publish
* mode.
*/
for (int i = 0; i < status.length; i++) {
StatusDescription description = status[i];
String nodeId = description.getDescriptionForUnit();
CourseNode cn = cloneCETM.getCourseNode(nodeId);
status[i] = cn.explainThisDuringPublish(description);
}
}
List<StatusDescription> updateNotifications = testUpdateSet(tmpCEV);
return new PublishSetInformations(status, updateNotifications);
}
Aggregations