Search in sources :

Example 36 with CourseEditorTreeNode

use of org.olat.course.tree.CourseEditorTreeNode in project openolat by klemens.

the class CourseEditorEnvImpl method checkFolderNodes.

private List<StatusDescription> checkFolderNodes(INode rootNode, ICourse course, List<StatusDescription> descriptions) {
    List<StatusDescription> descriptionsI = descriptions;
    Visitor visitor = new Visitor() {

        @Override
        public void visit(INode node) {
            CourseEditorTreeNode courseNode = (CourseEditorTreeNode) course.getEditorTreeModel().getNodeById(node.getIdent());
            if (!courseNode.isDeleted() && courseNode.getCourseNode() instanceof BCCourseNode) {
                BCCourseNode bcNode = (BCCourseNode) courseNode.getCourseNode();
                if (bcNode.isSharedFolder()) {
                    String translPackage = Util.getPackageName(BCCourseNodeEditController.class);
                    StatusDescription status = new StatusDescription(StatusDescription.ERROR, "warning.no.sharedfolder", "warning.no.sharedfolder", null, translPackage);
                    status.setDescriptionForUnit(bcNode.getIdent());
                    // set which pane is affected by error
                    status.setActivateableViewIdentifier(BCCourseNodeEditController.PANE_TAB_FOLDER);
                    descriptionsI.add(status);
                }
            }
        }
    };
    TreeVisitor v = new TreeVisitor(visitor, rootNode, false);
    v.visitAll();
    return descriptionsI;
}
Also used : TreeVisitor(org.olat.core.util.tree.TreeVisitor) INode(org.olat.core.util.nodes.INode) BCCourseNode(org.olat.course.nodes.BCCourseNode) TreeVisitor(org.olat.core.util.tree.TreeVisitor) Visitor(org.olat.core.util.tree.Visitor) CourseEditorTreeNode(org.olat.course.tree.CourseEditorTreeNode)

Example 37 with CourseEditorTreeNode

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

Example 38 with CourseEditorTreeNode

use of org.olat.course.tree.CourseEditorTreeNode in project openolat by klemens.

the class PublishProcess method assemblePublishConfirmation.

String assemblePublishConfirmation() {
    List<String> nodeIdsToPublish = originalNodeIdsToPublish;
    StringBuilder msg = new StringBuilder();
    OLATResourceable courseRunOres = OresHelper.createOLATResourceableInstance(RunMainController.ORES_TYPE_COURSE_RUN, repositoryEntry.getOlatResource().getResourceableId());
    // -1: Remove myself from list
    int cnt = CoordinatorManager.getInstance().getCoordinator().getEventBus().getListeningIdentityCntFor(courseRunOres) - 1;
    if (cnt > 0) {
        msg.append(translate("pbl.confirm.users", String.valueOf(cnt)));
    } else {
        msg.append(translator.translate("pbl.confirm"));
    }
    if (nodeIdsToPublish != null && nodeIdsToPublish.size() > 0) {
        msg.append("<ul class='list-unstyled'>");
        CourseEditorTreeModel cetm = course.getEditorTreeModel();
        for (int i = 0; i < nodeIdsToPublish.size(); i++) {
            msg.append("<li>");
            String nodeId = nodeIdsToPublish.get(i);
            CourseEditorTreeNode cetn = (CourseEditorTreeNode) cetm.getNodeById(nodeId);
            CourseNode cn = cetm.getCourseNode(nodeId);
            if (cetn.isDeleted() && !cetn.isNewnode()) {
                msg.append("<i class='o_icon o_icon_delete_item'> </i> ");
            } else {
                CourseNodeConfiguration nodeConfig = CourseNodeFactory.getInstance().getCourseNodeConfigurationEvenForDisabledBB(cn.getType());
                if (nodeConfig != null) {
                    msg.append("<i class='o_icon ").append(nodeConfig.getIconCSSClass()).append("'> </i> ");
                }
            }
            msg.append(cn.getShortTitle()).append("</li>");
        }
        msg.append("</ul>");
    }
    return msg.toString();
}
Also used : CourseEditorTreeModel(org.olat.course.tree.CourseEditorTreeModel) OLATResourceable(org.olat.core.id.OLATResourceable) CourseEditorTreeNode(org.olat.course.tree.CourseEditorTreeNode) CourseNode(org.olat.course.nodes.CourseNode) CourseNodeConfiguration(org.olat.course.nodes.CourseNodeConfiguration)

Example 39 with CourseEditorTreeNode

use of org.olat.course.tree.CourseEditorTreeNode in project openolat by klemens.

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 40 with CourseEditorTreeNode

use of org.olat.course.tree.CourseEditorTreeNode in project OpenOLAT by OpenOLAT.

the class CourseHandler method importResource.

@Override
public RepositoryEntry importResource(Identity initialAuthor, String initialAuthorAlt, String displayname, String description, boolean withReferences, Locale locale, File file, String filename) {
    OLATResource newCourseResource = OLATResourceManager.getInstance().createOLATResourceInstance(CourseModule.class);
    ICourse course = CourseFactory.importCourseFromZip(newCourseResource, file);
    // cfc.release();
    if (course == null) {
        return null;
    }
    RepositoryService repositoryService = CoreSpringFactory.getImpl(RepositoryService.class);
    RepositoryEntry re = repositoryService.create(initialAuthor, null, "", displayname, description, newCourseResource, RepositoryEntry.ACC_OWNERS);
    DBFactory.getInstance().commit();
    // create empty run structure
    course = CourseFactory.openCourseEditSession(course.getResourceableId());
    Structure runStructure = course.getRunStructure();
    runStructure.getRootNode().removeAllChildren();
    CourseFactory.saveCourse(course.getResourceableId());
    // import references
    CourseEditorTreeNode rootNode = (CourseEditorTreeNode) course.getEditorTreeModel().getRootNode();
    importReferences(rootNode, course, initialAuthor, locale, withReferences);
    if (withReferences && course.getCourseConfig().hasCustomSharedFolder()) {
        importSharedFolder(course, initialAuthor);
    }
    if (withReferences && course.getCourseConfig().hasGlossary()) {
        importGlossary(course, initialAuthor);
    }
    // create group management / import groups
    CourseGroupManager cgm = course.getCourseEnvironment().getCourseGroupManager();
    File fImportBaseDirectory = course.getCourseExportDataDir().getBasefile();
    CourseEnvironmentMapper envMapper = cgm.importCourseBusinessGroups(fImportBaseDirectory);
    envMapper.setAuthor(initialAuthor);
    // upgrade course
    course = CourseFactory.loadCourse(cgm.getCourseResource());
    course.postImport(fImportBaseDirectory, envMapper);
    // rename root nodes, but only when user modified the course title
    boolean doUpdateTitle = true;
    File repoConfigXml = new File(fImportBaseDirectory, "repo.xml");
    if (repoConfigXml.exists()) {
        RepositoryEntryImport importConfig;
        try {
            importConfig = RepositoryEntryImportExport.getConfiguration(new FileInputStream(repoConfigXml));
            if (importConfig != null) {
                if (displayname.equals(importConfig.getDisplayname())) {
                    // do not update if title was not modified during import
                    // user does not expect to have an updated title and there is a chance
                    // the root node title is not the same as the course title
                    doUpdateTitle = false;
                }
            }
        } catch (FileNotFoundException e) {
        // ignore
        }
    }
    if (doUpdateTitle) {
        // do not use truncate!
        course.getRunStructure().getRootNode().setShortTitle(Formatter.truncateOnly(displayname, 25));
        course.getRunStructure().getRootNode().setLongTitle(displayname);
    }
    // course.saveRunStructure();
    CourseEditorTreeNode editorRootNode = ((CourseEditorTreeNode) course.getEditorTreeModel().getRootNode());
    // do not use truncate!
    editorRootNode.getCourseNode().setShortTitle(Formatter.truncateOnly(displayname, 25));
    editorRootNode.getCourseNode().setLongTitle(displayname);
    // mark entire structure as dirty/new so the user can re-publish
    markDirtyNewRecursively(editorRootNode);
    // root has already been created during export. Unmark it.
    editorRootNode.setNewnode(false);
    // save and close edit session
    CourseFactory.saveCourse(course.getResourceableId());
    CourseFactory.closeCourseEditSession(course.getResourceableId(), true);
    RepositoryEntryImportExport imp = new RepositoryEntryImportExport(fImportBaseDirectory);
    if (imp.anyExportedPropertiesAvailable()) {
        re = imp.importContent(re, getMediaContainer(re));
    }
    // import reminders
    importReminders(re, fImportBaseDirectory, envMapper, initialAuthor);
    // clean up export folder
    cleanExportAfterImport(fImportBaseDirectory);
    return re;
}
Also used : CourseGroupManager(org.olat.course.groupsandrights.CourseGroupManager) PersistingCourseGroupManager(org.olat.course.groupsandrights.PersistingCourseGroupManager) RepositoryEntryImportExport(org.olat.repository.RepositoryEntryImportExport) CourseEditorTreeNode(org.olat.course.tree.CourseEditorTreeNode) FileNotFoundException(java.io.FileNotFoundException) OLATResource(org.olat.resource.OLATResource) ICourse(org.olat.course.ICourse) RepositoryEntry(org.olat.repository.RepositoryEntry) RepositoryEntryImport(org.olat.repository.RepositoryEntryImportExport.RepositoryEntryImport) FileInputStream(java.io.FileInputStream) Structure(org.olat.course.Structure) File(java.io.File) CourseEnvironmentMapper(org.olat.course.export.CourseEnvironmentMapper) RepositoryService(org.olat.repository.RepositoryService)

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