package org.freeplane.features.link;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import org.freeplane.core.extension.IExtension;
import org.freeplane.features.map.MapModel;
import org.freeplane.features.map.NodeModel;
class EvaluationDependencies implements IExtension{
private static EvaluationDependencies getEvaluationDependencies(MapModel map) {
EvaluationDependencies dependencies = (EvaluationDependencies) map.getExtension(EvaluationDependencies.class);
if (dependencies == null) {
dependencies = new EvaluationDependencies();
map.addExtension(dependencies);
}
return dependencies;
}
public static List<NodeModel> manageChangeAndReturnDependencies(boolean includeChanged, final NodeModel... nodes) {
final ArrayList<NodeModel> dependencies = new ArrayList<NodeModel>();
for (int i = 0; i < nodes.length; i++) {
final LinkedHashSet<NodeModel> nodeDependencies = new LinkedHashSet<NodeModel>(0);
getEvaluationDependencies(nodes[i].getMap()).getDependencies(nodeDependencies, nodes[i]);
if (nodeDependencies != null)
dependencies.addAll(nodeDependencies);
if (includeChanged)
dependencies.add(nodes[i]);
}
return dependencies;
}
public static void accessNode(NodeModel accessingNode, NodeModel accessedNode) {
getEvaluationDependencies(accessingNode.getMap()).accessNodeImpl(accessingNode, accessedNode);
}
private HashMap<NodeModel, HashSet<NodeModel>> onNodeDependencies = new HashMap<NodeModel, 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);
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. */
private void accessNodeImpl(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);
}
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");
}
}
return builder.toString();
}
}