use of org.olat.course.tree.CourseEditorTreeNode in project OpenOLAT by OpenOLAT.
the class PublishProcess method appendPublishableSubnodeIds.
/**
* starting from each user selected to-publish node all also affected nodes
* are added to the list of nodes to be published.
*
* @param cetn
* @param nodesToPublish
*/
private void appendPublishableSubnodeIds(CourseEditorTreeNode cetn, List<String> nodesToPublish) {
for (int i = 0; i < cetn.getChildCount(); i++) {
CourseEditorTreeNode child = (CourseEditorTreeNode) cetn.getChildAt(i);
if (child.hasPublishableChanges())
nodesToPublish.add(child.getIdent());
appendPublishableSubnodeIds(child, nodesToPublish);
}
}
use of org.olat.course.tree.CourseEditorTreeNode in project OpenOLAT by OpenOLAT.
the class PublishProcess method createPublishSetFor.
/**
* first step in publishing course editor nodes.<br>
* next step is testPublishSet, see method for more details.
* @param nodeIdsToPublish
*/
public void createPublishSetFor(List<String> nodeIdsToPublish) {
this.originalNodeIdsToPublish = nodeIdsToPublish;
// append new nodes' subnodes
int selectCount = nodeIdsToPublish.size();
for (int i = 0; i < selectCount; i++) {
// avoid using iterator here so we can modify the Collection
String nodeId = nodeIdsToPublish.get(i);
CourseEditorTreeNode cetn = editorTreeModel.getCourseEditorNodeById(nodeId);
if (cetn.isNewnode() || cetn.isDeleted() || publishTreeModel.isMoved(cetn))
appendPublishableSubnodeIds(cetn, nodeIdsToPublish);
}
/*
* generatePublishSet, testPublishSet, applyPublishSet
*/
/*
* several book keeping lists which are also used to modify the course
* editor model after the new runstructure is generated into ram.
*/
editorModelDeletedNodes = new ArrayList<CourseEditorTreeNode>();
editorModelInsertedNodes = new ArrayList<CourseEditorTreeNode>();
editorModelModifiedNodes = new ArrayList<CourseEditorTreeNode>();
resultingCourseRun = new Structure();
// has side effect on the above editorModelxxxNodes and the
// resultingCourseRun;
calculatePublishSet(nodeIdsToPublish);
}
use of org.olat.course.tree.CourseEditorTreeNode in project OpenOLAT by OpenOLAT.
the class PublishProcess method applyPublishSet.
/**
* @param identity
* @param locale
* @param newCourse Optimization for new courses, it doesn't call upddateOnPublish of inserted/updated course nodes
*/
public void applyPublishSet(Identity identity, Locale locale, boolean newCourse) {
// the active runstructure and the new created runstructure
Structure existingCourseRun = course.getRunStructure();
EventBus orec = CoordinatorManager.getInstance().getCoordinator().getEventBus();
/*
* use book keeping lists for publish event
*/
Set<String> deletedCourseNodeIds = new HashSet<String>();
if (editorModelDeletedNodes.size() > 0) {
for (Iterator<CourseEditorTreeNode> iter = editorModelDeletedNodes.iterator(); iter.hasNext(); ) {
CourseEditorTreeNode cetn = iter.next();
CourseNode cn = cetn.getCourseNode();
deletedCourseNodeIds.add(cn.getIdent());
}
}
Set<String> insertedCourseNodeIds = new HashSet<String>();
if (editorModelInsertedNodes.size() > 0) {
for (Iterator<CourseEditorTreeNode> iter = editorModelInsertedNodes.iterator(); iter.hasNext(); ) {
CourseEditorTreeNode cetn = iter.next();
CourseNode cn = cetn.getCourseNode();
insertedCourseNodeIds.add(cn.getIdent());
}
}
Set<String> modifiedCourseNodeIds = new HashSet<String>();
if (editorModelModifiedNodes.size() > 0) {
for (Iterator<CourseEditorTreeNode> iter = editorModelModifiedNodes.iterator(); iter.hasNext(); ) {
CourseEditorTreeNode cetn = iter.next();
CourseNode cn = cetn.getCourseNode();
modifiedCourseNodeIds.add(cn.getIdent());
}
}
/*
* broadcast PRE PUBLISH event that a publish will take place
*/
PublishEvent beforePublish = new PublishEvent(course, identity);
beforePublish.setDeletedCourseNodeIds(deletedCourseNodeIds);
beforePublish.setInsertedCourseNodeIds(insertedCourseNodeIds);
beforePublish.setModifiedCourseNodeIds(modifiedCourseNodeIds);
beforePublish.setState(PublishEvent.PRE_PUBLISH);
// old course structure accessible
orec.fireEventToListenersOf(beforePublish, course);
/*
* TODO:pb: discuss with fj: listeners could add information to
* beforePublish event such as a right to veto or add identities who is
* currently in the course, thus stopping the publishing author from
* publishing! i.e. if people are in a test or something like this.... we
* could the ask here beforePublish.accepted() and proceed only in this
* case.
*/
//
/*
* remove new nodes which were marked as delete and deletion is published.
*/
UserManager um = UserManager.getInstance();
String charset = um.getUserCharset(identity);
if (editorModelDeletedNodes.size() > 0) {
for (Iterator<CourseEditorTreeNode> iter = editorModelDeletedNodes.iterator(); iter.hasNext(); ) {
CourseEditorTreeNode cetn = iter.next();
CourseNode cn = cetn.getCourseNode();
CourseNode oldCn = existingCourseRun.getNode(cetn.getIdent());
// null
if (oldCn != null) {
if (!(cn.getIdent().equals(oldCn.getIdent()))) {
throw new AssertException("deleted cn.getIdent != oldCn.getIdent");
}
}
cetn.removeFromParent();
if (!cetn.isNewnode() && oldCn != null) {
// only clean up and archive of nodes which were already in run
// save data, remove references
deleteRefs(oldCn);
archiveDeletedNode(identity, cn, oldCn, locale, charset);
// 2) delete all user data
oldCn.cleanupOnDelete(course);
}
}
}
/*
* mark modified ones as no longer dirty
*/
if (editorModelModifiedNodes.size() > 0) {
for (Iterator<CourseEditorTreeNode> iter = editorModelModifiedNodes.iterator(); iter.hasNext(); ) {
CourseEditorTreeNode cetn = iter.next();
CourseNode cn = cetn.getCourseNode();
CourseNode oldCn = existingCourseRun.getNode(cetn.getIdent());
// null
if (oldCn != null) {
if (!(cn.getIdent().equals(oldCn.getIdent()))) {
throw new AssertException("deleted cn.getIdent != oldCn.getIdent");
}
}
cetn.setDirty(false);
//
updateRefs(cn, oldCn);
}
}
/*
* mark newly published ones is no longer new and dirty
*/
if (editorModelInsertedNodes.size() > 0) {
for (Iterator<CourseEditorTreeNode> iter = editorModelInsertedNodes.iterator(); iter.hasNext(); ) {
CourseEditorTreeNode cetn = iter.next();
CourseNode cn = cetn.getCourseNode();
CourseNode oldCn = existingCourseRun.getNode(cetn.getIdent());
if (oldCn != null) {
throw new AssertException("new node has an oldCN??");
}
cetn.setDirty(false);
cetn.setNewnode(false);
//
updateRefs(cn, null);
}
}
/*
* saving
*/
long pubtimestamp = System.currentTimeMillis();
editorTreeModel.setLatestPublishTimestamp(pubtimestamp);
// set the new runstructure and save it.
existingCourseRun.setRootNode(resultingCourseRun.getRootNode());
CourseFactory.saveCourse(course.getResourceableId());
// on old course, apply update to published nodes
if (!newCourse) {
for (CourseEditorTreeNode cetn : editorModelInsertedNodes) {
cetn.getCourseNode().updateOnPublish(locale, course, identity, publishEvents);
}
for (CourseEditorTreeNode cetn : editorModelModifiedNodes) {
cetn.getCourseNode().updateOnPublish(locale, course, identity, publishEvents);
}
}
// commit all changes before sending an event
DBFactory.getInstance().commitAndCloseSession();
/*
* broadcast event
*/
PublishEvent publishEvent = new PublishEvent(course, identity);
publishEvent.setDeletedCourseNodeIds(deletedCourseNodeIds);
publishEvent.setInsertedCourseNodeIds(insertedCourseNodeIds);
publishEvent.setModifiedCourseNodeIds(modifiedCourseNodeIds);
// new course structure accessible
// CourseFactory is one listener, which removes the course from the
// cache.
orec.fireEventToListenersOf(publishEvent, course);
/*
* END NEW STYLE PUBLISH
*/
}
use of org.olat.course.tree.CourseEditorTreeNode in project OpenOLAT by OpenOLAT.
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);
}
use of org.olat.course.tree.CourseEditorTreeNode in project OpenOLAT by OpenOLAT.
the class PublishProcess method convertInCourseEditorTreeNode.
/**
* Convert all CourseNodes into CourseEditorTreeNode
*
* @param courseEditorTreeNode Parent CourseEditorTreeNode
* @param node Current course node which will be converted
*/
private void convertInCourseEditorTreeNode(CourseEditorTreeNode courseEditorTreeNode, CourseNode node) {
int childCnt = node.getChildCount();
for (int i = 0; i < childCnt; i++) {
CourseNode childNode = (CourseNode) node.getChildAt(i);
CourseEditorTreeNode newEditorNode = new CourseEditorTreeNode(childNode);
courseEditorTreeNode.addChild(newEditorNode);
convertInCourseEditorTreeNode(newEditorNode, childNode);
// remove all children after calling convertInCourseEditorTreeNode
childNode.removeAllChildren();
}
}
Aggregations