use of org.olat.core.util.tree.TreeVisitor in project openolat by klemens.
the class CourseEditorEnvImpl method listCycles.
/**
* @see org.olat.course.editor.CourseEditorEnv#listCycles()
*/
@Override
public Set<String> listCycles() {
/*
* convert nodeRefs datastructure to a directed graph
*/
DirectedGraph dg = new DefaultDirectedGraph();
DirectedEdgeFactory def = new EdgeFactories.DirectedEdgeFactory();
/*
* add the course structure as directed graph, where
*/
Visitor v = new Convert2DGVisitor(dg);
(new TreeVisitor(v, cetm.getRootNode(), true)).visitAll();
/*
* iterate over nodeRefs, add each not existing node id as vertex, for each
* key - child relation add an edge to the directed graph.
*/
Map<String, Set<String>> nodeSoftRefs = new HashMap<>();
for (Iterator<String> iter = softRefs.keySet().iterator(); iter.hasNext(); ) {
String nodeId = iter.next();
List<ConditionExpression> conditionExprs = softRefs.get(nodeId);
for (int i = 0; i < conditionExprs.size(); i++) {
ConditionExpression ce = conditionExprs.get(i);
Set<String> refs = ce.getSoftReferencesForCycleDetectorOf("courseNodeId");
if (refs != null && refs.size() > 0) {
if (nodeSoftRefs.containsKey(nodeId)) {
nodeSoftRefs.get(nodeId).addAll(refs);
} else {
nodeSoftRefs.put(nodeId, refs);
}
}
}
}
for (Iterator<String> keys = nodeSoftRefs.keySet().iterator(); keys.hasNext(); ) {
// a node
String key = keys.next();
if (!dg.containsVertex(key)) {
dg.addVertex(key);
}
// and its children
Set<String> children = nodeSoftRefs.get(key);
for (Iterator<String> childrenIt = children.iterator(); childrenIt.hasNext(); ) {
String child = childrenIt.next();
if (!dg.containsVertex(child)) {
dg.addVertex(child);
}
// add edge, precondition: vertex key - child are already added to the graph
Edge de = def.createEdge(key, child);
dg.addEdge(de);
}
}
/*
* find the id's participating in the cycle, and return the intersection
* with set of id's which actually produce references.
*/
CycleDetector cd = new CycleDetector(dg);
Set<String> cycleIds = cd.findCycles();
cycleIds.retainAll(nodeSoftRefs.keySet());
return cycleIds;
}
use of org.olat.core.util.tree.TreeVisitor in project openolat by klemens.
the class EditorMainController method dropNodeAsChild.
private void dropNodeAsChild(UserRequest ureq, ICourse course, String droppedNodeId, String targetNodeId, boolean asChild, boolean atTheEnd) {
// setDirty when moving
menuTree.setDirty(true);
CourseNode droppedNode = cetm.getCourseNode(droppedNodeId);
int position;
CourseEditorTreeNode insertParent;
if (asChild) {
insertParent = cetm.getCourseEditorNodeById(targetNodeId);
position = atTheEnd ? -1 : 0;
} else {
CourseEditorTreeNode selectedNode = cetm.getCourseEditorNodeById(targetNodeId);
if (selectedNode.getParent() == null) {
// root node
insertParent = selectedNode;
position = 0;
} else {
insertParent = course.getEditorTreeModel().getCourseEditorNodeById(selectedNode.getParent().getIdent());
position = 0;
for (position = insertParent.getChildCount(); position-- > 0; ) {
if (insertParent.getChildAt(position).getIdent().equals(selectedNode.getIdent())) {
position++;
break;
}
}
}
}
CourseEditorTreeNode moveFrom = course.getEditorTreeModel().getCourseEditorNodeById(droppedNode.getIdent());
// check if an ancestor is not dropped on a child
if (course.getEditorTreeModel().checkIfIsChild(insertParent, moveFrom)) {
showError("movecopynode.error.overlap");
fireEvent(ureq, Event.CANCELLED_EVENT);
return;
}
// don't generate red screen for that. If the position is too high -> add the node at the end
if (position >= insertParent.getChildCount()) {
position = -1;
}
try {
if (position >= 0) {
insertParent.insert(moveFrom, position);
} else {
insertParent.addChild(moveFrom);
}
} catch (IndexOutOfBoundsException e) {
logError("", e);
// reattach the node as security, if not, the node is lost
insertParent.addChild(moveFrom);
}
moveFrom.setDirty(true);
// mark subtree as dirty
TreeVisitor tv = new TreeVisitor(new Visitor() {
public void visit(INode node) {
CourseEditorTreeNode cetn = (CourseEditorTreeNode) node;
cetn.setDirty(true);
}
}, moveFrom, true);
tv.visitAll();
CourseFactory.saveCourseEditorTreeModel(course.getResourceableId());
showInfo("movecopynode.info.condmoved");
ThreadLocalUserActivityLogger.log(CourseLoggingAction.COURSE_EDITOR_NODE_MOVED, getClass());
euce.getCourseEditorEnv().validateCourse();
StatusDescription[] courseStatus = euce.getCourseEditorEnv().getCourseStatus();
updateCourseStatusMessages(ureq.getLocale(), courseStatus);
}
use of org.olat.core.util.tree.TreeVisitor in project openolat by klemens.
the class PublishProcess method calculatePublishSet.
/**
* @param nodesIdsToPublish
* @param resultingCourseRun
* @param editorModelDeletedNodes
* @param editorModelInsertedNodes
* @param editorModelModifiedNodes
*/
private void calculatePublishSet(List<String> nodesIdsToPublish) {
/*
* START NEW STYLE PUBLISH ................................................. -
* visit each node (breadth first) - if node is selected to be published ->
* publish and take into account if the node exists already in the
* runstructure (keep ident or not). And also if node should get deleted add
* it to a list of nodes to be deleted. This is needed for a later clean-up
* and archive. ............................. - if node is not selected to
* be published, but exists already in the runstructure it must be added to
* the tmp-runstructure as it is in the existing runstructure.
* ..................................................
*/
// start point for node publish visitor
CourseEditorTreeNode editorRoot = (CourseEditorTreeNode) editorTreeModel.getRootNode();
// the active runstructure and the new created runstructure
Structure existingCourseRun = course.getRunStructure();
// breadth first!
boolean visitChildrenFirst = false;
/*
* the tree is visited and the book keeping lists are filled. the visitor
* itself does not delete or modify neither runstructure nor editor tree
* model. The whole complexity of published is encapsulated in the visitor.
*/
Visitor nodePublishV = new NodePublishVisitor(editorRoot, nodesIdsToPublish, existingCourseRun);
TreeVisitor tv = new TreeVisitor(nodePublishV, editorRoot, visitChildrenFirst);
tv.visitAll();
}
use of org.olat.core.util.tree.TreeVisitor in project openolat by klemens.
the class EditorMainController method doCreateAlternateBuildingBlock.
/**
* The following operation are done:
* <ul>
* <li>create a new instance of the replacement type
* <li>add the new element below the original element
* <li>copy the element title, description and the generic configuration options
* <li>copy the access, visibility and scoring rules (easy and expert)
* <li>optionally copy some other configuration if this is possible at all
* <li>move all child elements from the original to the replacement element
* <li>mark the original element as deleted
* </ul>
*
* @param chosenNode
* @param selectAlternative
*/
private void doCreateAlternateBuildingBlock(UserRequest ureq, ICourse course, CourseNode chosenNode, String selectAlternative) {
if (!StringHelper.containsNonWhitespace(selectAlternative))
return;
// create the alternative node
CourseNodeConfiguration newConfig = CourseNodeFactory.getInstance().getCourseNodeConfiguration(selectAlternative);
CourseNode newNode = newConfig.getInstance();
// copy configurations
chosenNode.copyConfigurationTo(newNode, course);
// insert the node
CourseEditorTreeNode cetn = (CourseEditorTreeNode) cetm.getNodeById(chosenNode.getIdent());
CourseEditorTreeNode parentNode = (CourseEditorTreeNode) cetn.getParent();
int position = cetn.getPosition() + 1;
CourseEditorTreeNode newCetn = course.getEditorTreeModel().insertCourseNodeAt(newNode, parentNode.getCourseNode(), position);
doInsert(ureq, newNode);
// copy the children
while (cetn.getChildCount() > 0) {
CourseEditorTreeNode childNode = (CourseEditorTreeNode) cetn.getChildAt(0);
newCetn.addChild(childNode);
}
// set all dirty
TreeVisitor tv = new TreeVisitor(new Visitor() {
public void visit(INode node) {
((CourseEditorTreeNode) node).setDirty(true);
}
}, newCetn, true);
tv.visitAll();
// mark as deleted
doDelete(course, chosenNode.getIdent());
// save
CourseFactory.saveCourseEditorTreeModel(course.getResourceableId());
}
use of org.olat.core.util.tree.TreeVisitor in project openolat by klemens.
the class MoveCopySubtreeController method doInsert.
private void doInsert(UserRequest ureq, TreePosition tp) {
ICourse course = CourseFactory.getCourseEditSession(ores.getResourceableId());
int insertPos = tp.getChildpos();
CourseNode selectedNode = getCourseNode(tp.getParentTreeNode());
CourseEditorTreeNode insertParent = course.getEditorTreeModel().getCourseEditorNodeById(selectedNode.getIdent());
// check if insert position is within the to-be-copied tree
if (course.getEditorTreeModel().checkIfIsChild(insertParent, moveCopyFrom)) {
showError("movecopynode.error.overlap");
fireEvent(ureq, Event.CANCELLED_EVENT);
} else if (copy) {
// do a copy
// copy subtree and save model
recursiveCopy(moveCopyFrom, insertParent, insertPos, true, CourseFactory.getCourseEditSession(ores.getResourceableId()));
CourseFactory.saveCourseEditorTreeModel(course.getResourceableId());
ThreadLocalUserActivityLogger.log(CourseLoggingAction.COURSE_EDITOR_NODE_COPIED, getClass());
fireEvent(ureq, Event.DONE_EVENT);
} else {
// move only
if (insertParent.getIdent().equals(moveCopyFrom.getParent().getIdent())) {
// same parent, adjust insertPos
if (insertPos > moveCopyFrom.getPosition())
insertPos--;
}
insertParent.insert(moveCopyFrom, insertPos);
moveCopyFrom.setDirty(true);
// mark subtree as dirty
TreeVisitor tv = new TreeVisitor(new Visitor() {
@Override
public void visit(INode node) {
CourseEditorTreeNode cetn = (CourseEditorTreeNode) node;
cetn.setDirty(true);
}
}, moveCopyFrom, true);
tv.visitAll();
CourseFactory.saveCourseEditorTreeModel(course.getResourceableId());
showInfo("movecopynode.info.condmoved");
ThreadLocalUserActivityLogger.log(CourseLoggingAction.COURSE_EDITOR_NODE_MOVED, getClass());
fireEvent(ureq, Event.DONE_EVENT);
}
}
Aggregations