package org.freeplane.plugin.script; import java.util.HashMap; import java.util.HashSet; import java.util.Map.Entry; import java.util.Set; import org.freeplane.core.extension.IExtension; import org.freeplane.features.map.NodeModel; public class EvaluationDependencies implements IExtension{ public enum Access { NODE, BRANCH, ALL } private HashMap<NodeModel, HashSet<NodeModel>> onNodeDependencies = new HashMap<NodeModel, HashSet<NodeModel>>(); // FIXME: organize node and branch dependencies in a tree? private HashMap<NodeModel, HashSet<NodeModel>> onBranchDependencies = new HashMap<NodeModel, HashSet<NodeModel>>(); private HashSet<NodeModel> onAnyNodeDependencies = new HashSet<NodeModel>(); public Set<NodeModel> getDependencies(Set<NodeModel> result, final NodeModel node) { final HashSet<NodeModel> onNode = onNodeDependencies.get(node); if (onNode != null) addRecursively(result, onNode); for (Entry<NodeModel, HashSet<NodeModel>> entry : onBranchDependencies.entrySet()) { if (node.isDescendantOf(entry.getKey())) addRecursively(result, entry.getValue()); } addRecursively(result, onAnyNodeDependencies); // System.out.println("dependencies on(" + node + "): " + result); return result; } private void addRecursively(Set<NodeModel> dependentNodes, final HashSet<NodeModel> nodesToAdd) { for (NodeModel node : nodesToAdd) { // avoid loops if (dependentNodes.add(node)) dependentNodes.addAll(getDependencies(dependentNodes, node)); } } /** accessedNode was accessed when formulaNode was evaluated. */ public void accessNode(NodeModel formulaNode, NodeModel accessedNode) { // FIXME: check if accessedNode is already covered by other accessModes getDependencySet(accessedNode, onNodeDependencies).add(formulaNode); // System.out.println(formulaNode + " accesses " + accessedNode + ". current dependencies:\n" + this); } /** accessedNode.children was accessed when formulaNode was evaluated. */ public void accessBranch(NodeModel formulaNode, NodeModel accessedNode) { // FIXME: check if accessedNode is already covered by other accessModes getDependencySet(accessedNode, onBranchDependencies).add(formulaNode); // System.out.println(formulaNode + " accesses branch of " + accessedNode + ". current dependencies:\n" + this); } /** a method was used on the formulaNode that may use any node in the map. */ public void accessAll(NodeModel formulaNode) { // FIXME: check if accessedNode is already covered by other accessModes onAnyNodeDependencies.add(formulaNode); // System.out.println(formulaNode + " accesses all nodes. current dependencies:\n" + this); } private HashSet<NodeModel> getDependencySet(final NodeModel accessedNode, final HashMap<NodeModel, HashSet<NodeModel>> dependenciesMap) { HashSet<NodeModel> set = dependenciesMap.get(accessedNode); if (set == null) { set = new HashSet<NodeModel>(); dependenciesMap.put(accessedNode, set); } return set; } @Override public String toString() { StringBuilder builder = new StringBuilder(); for (Entry<NodeModel, HashSet<NodeModel>> entry : onNodeDependencies.entrySet()) { builder.append("onNode (" + entry.getKey().getText() + "):\n"); for (NodeModel nodeModel : entry.getValue()) { builder.append(" " + nodeModel + "\n"); } } for (Entry<NodeModel, HashSet<NodeModel>> entry : onBranchDependencies.entrySet()) { builder.append("onBranch (" + entry.getKey().getText() + "):\n"); for (NodeModel nodeModel : entry.getValue()) { builder.append(" " + nodeModel + "\n"); } } if (!onAnyNodeDependencies.isEmpty()) { builder.append("onAnyNode:\n"); for (NodeModel nodeModel : onAnyNodeDependencies) { builder.append(" " + nodeModel + "\n"); } } return builder.toString(); } }