Search in sources :

Example 51 with CourseEditorTreeNode

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);
    }
}
Also used : CourseEditorTreeNode(org.olat.course.tree.CourseEditorTreeNode)

Example 52 with CourseEditorTreeNode

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);
}
Also used : CourseEditorTreeNode(org.olat.course.tree.CourseEditorTreeNode) Structure(org.olat.course.Structure)

Example 53 with CourseEditorTreeNode

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
		 */
}
Also used : AssertException(org.olat.core.logging.AssertException) UserManager(org.olat.user.UserManager) CourseEditorTreeNode(org.olat.course.tree.CourseEditorTreeNode) EventBus(org.olat.core.util.event.EventBus) CourseNode(org.olat.course.nodes.CourseNode) Structure(org.olat.course.Structure) HashSet(java.util.HashSet)

Example 54 with CourseEditorTreeNode

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);
}
Also used : CourseEditorTreeModel(org.olat.course.tree.CourseEditorTreeModel) CourseEditorTreeNode(org.olat.course.tree.CourseEditorTreeNode) CourseNode(org.olat.course.nodes.CourseNode)

Example 55 with CourseEditorTreeNode

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();
    }
}
Also used : CourseEditorTreeNode(org.olat.course.tree.CourseEditorTreeNode) CourseNode(org.olat.course.nodes.CourseNode)

Aggregations

CourseEditorTreeNode (org.olat.course.tree.CourseEditorTreeNode)88 CourseNode (org.olat.course.nodes.CourseNode)54 ICourse (org.olat.course.ICourse)38 CourseEditorTreeModel (org.olat.course.tree.CourseEditorTreeModel)24 INode (org.olat.core.util.nodes.INode)22 Test (org.junit.Test)20 RepositoryEntry (org.olat.repository.RepositoryEntry)18 Identity (org.olat.core.id.Identity)14 TreeVisitor (org.olat.core.util.tree.TreeVisitor)14 Visitor (org.olat.core.util.tree.Visitor)14 CourseNodeVO (org.olat.restapi.support.vo.CourseNodeVO)12 TreeNode (org.olat.core.gui.components.tree.TreeNode)10 STCourseNode (org.olat.course.nodes.STCourseNode)10 ArrayList (java.util.ArrayList)9 File (java.io.File)8 URI (java.net.URI)8 HttpResponse (org.apache.http.HttpResponse)8 HttpPut (org.apache.http.client.methods.HttpPut)8 Structure (org.olat.course.Structure)8 BCCourseNode (org.olat.course.nodes.BCCourseNode)8