<commit_before>package org.grouplens.lenskit.eval.graph;

import org.grouplens.grapht.graph.Edge;
import org.grouplens.grapht.graph.Graph;
import org.grouplens.grapht.graph.Node;
import org.grouplens.grapht.spi.CachedSatisfaction;
import org.grouplens.grapht.spi.Satisfaction;
import org.grouplens.grapht.spi.SatisfactionVisitor;
import org.grouplens.lenskit.core.GraphtUtils;

import javax.inject.Provider;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;

/**
 * Class to manage traversing nodes. It is not used to handle the root node, but rather handles
 * the rest of them.
*/
class GraphDumper implements SatisfactionVisitor<Void> {
    private static final String ROOT_ID = "root";

    private final GraphWriter writer;
    private final Graph graph;
    private final Map<Node, String> nodeIds;
    private final Queue<Node> queue;

    private Node currentNode;

    public GraphDumper(Graph g, GraphWriter gw) {
        writer = gw;
        graph = g;
        nodeIds = new HashMap<Node, String>();
        queue = new LinkedList<Node>();
    }

    /**
     * Set the root node for this dumper. This must be called before any other methods.
     * @param root The root node.
     * @return The ID of the root node.
     */
    public String setRoot(Node root) {
        if (!nodeIds.isEmpty()) {
            throw new IllegalStateException("root node already specificied");
        }
        nodeIds.put(root, ROOT_ID);
        writer.putNode(new NodeBuilder(ROOT_ID).setLabel("root")
                                               .setShape("diamond")
                                               .build());
        return ROOT_ID;
    }

    /**
     * Add a node to the queue.  If the node is already enqueued, the previous ID number
     * is returned.
     * @param node The node to enqueue
     * @return The node's ID.
     */
    public String enqueue(Node node) {
        if (nodeIds.isEmpty()) {
            throw new IllegalStateException("root node has not been set");
        }
        String id = nodeIds.get(node);
        if (id == null) {
            queue.add(node);
            id = "N" + nodeIds.size();
            nodeIds.put(node, id);
        }
        return id;
    }

    /**
     * Run the queue.
     */
    public void run() {
        while (!queue.isEmpty()) {
            currentNode = queue.remove();
            final CachedSatisfaction csat = currentNode.getLabel();
            assert csat != null;
            final Satisfaction sat = csat.getSatisfaction();
            sat.visit(this);
        }
        currentNode = null;
    }

    private String currentNodeId() {
        if (currentNode == null) {
            throw new IllegalStateException("dumper not running");
        }
        return nodeIds.get(currentNode);
    }

    private Satisfaction currentSatisfaction() {
        if (currentNode == null) {
            throw new IllegalStateException("dumper not running");
        }
        CachedSatisfaction csat = currentNode.getLabel();
        assert csat != null;
        return csat.getSatisfaction();
    }

    @Override
    public Void visitNull() {
        writer.putNode(new NodeBuilder(currentNodeId())
                               .setLabel("null")
                               .setShape("ellipse")
                               .build());
        return null;
    }

    @Override
    public Void visitClass(Class<?> clazz) {
        putComponentNode(clazz, null);
        return null;
    }

    @Override
    public Void visitInstance(Object instance) {
        writer.putNode(new NodeBuilder(currentNodeId())
                               .setLabel(instance.toString())
                               .setShape("ellipse")
                               .build());
        return null;
    }

    /**
     * Output the intermediate "provided" node from the current node.<commit_msg>Render DAO node (refs #264)<commit_after>package org.grouplens.lenskit.eval.graph;

import org.grouplens.grapht.graph.Edge;
import org.grouplens.grapht.graph.Graph;
import org.grouplens.grapht.graph.Node;
import org.grouplens.grapht.spi.CachedSatisfaction;
import org.grouplens.grapht.spi.Satisfaction;
import org.grouplens.grapht.spi.SatisfactionVisitor;
import org.grouplens.lenskit.core.GraphtUtils;
import org.grouplens.lenskit.data.dao.DataAccessObject;

import javax.inject.Provider;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;

/**
 * Class to manage traversing nodes. It is not used to handle the root node, but rather handles
 * the rest of them.
*/
class GraphDumper implements SatisfactionVisitor<Void> {
    private static final String ROOT_ID = "root";

    private final GraphWriter writer;
    private final Graph graph;
    private final Map<Node, String> nodeIds;
    private final Queue<Node> queue;

    private Node currentNode;

    public GraphDumper(Graph g, GraphWriter gw) {
        writer = gw;
        graph = g;
        nodeIds = new HashMap<Node, String>();
        queue = new LinkedList<Node>();
    }

    /**
     * Set the root node for this dumper. This must be called before any other methods.
     * @param root The root node.
     * @return The ID of the root node.
     */
    public String setRoot(Node root) {
        if (!nodeIds.isEmpty()) {
            throw new IllegalStateException("root node already specificied");
        }
        nodeIds.put(root, ROOT_ID);
        writer.putNode(new NodeBuilder(ROOT_ID).setLabel("root")
                                               .setShape("diamond")
                                               .build());
        return ROOT_ID;
    }

    /**
     * Add a node to the queue.  If the node is already enqueued, the previous ID number
     * is returned.
     * @param node The node to enqueue
     * @return The node's ID.
     */
    public String enqueue(Node node) {
        if (nodeIds.isEmpty()) {
            throw new IllegalStateException("root node has not been set");
        }
        String id = nodeIds.get(node);
        if (id == null) {
            queue.add(node);
            id = "N" + nodeIds.size();
            nodeIds.put(node, id);
        }
        return id;
    }

    /**
     * Run the queue.
     */
    public void run() {
        while (!queue.isEmpty()) {
            currentNode = queue.remove();
            final CachedSatisfaction csat = currentNode.getLabel();
            assert csat != null;
            final Satisfaction sat = csat.getSatisfaction();
            sat.visit(this);
        }
        currentNode = null;
    }

    private String currentNodeId() {
        if (currentNode == null) {
            throw new IllegalStateException("dumper not running");
        }
        return nodeIds.get(currentNode);
    }

    private Satisfaction currentSatisfaction() {
        if (currentNode == null) {
            throw new IllegalStateException("dumper not running");
        }
        CachedSatisfaction csat = currentNode.getLabel();
        assert csat != null;
        return csat.getSatisfaction();
    }

    @Override
    public Void visitNull() {
        NodeBuilder nb = new NodeBuilder(currentNodeId());
        nb.setShape("ellipse");
        Class<?> type = currentSatisfaction().getErasedType();
        if (DataAccessObject.class.isAssignableFrom(type)) {
            nb.setLabel("DAO");
        } else {
            nb.setLabel("null");
        }
        writer.putNode(nb.build());
        return null;
    }

    @Override
    public Void visitClass(Class<?> clazz) {
        putComponentNode(clazz, null);
        return null;
    }

    @Override
    public Void visitInstance(Object instance) {
        writer.putNode(new NodeBuilder(currentNodeId())
                               .setLabel(instance.toString())
                               .setShape("ellipse")
                               .build());
        return null;
    }

    /**
     * Output the intermediate "provided" node from the current node.
{'fraction_non_alphanumeric': 0.10129256773552076, 'fraction_numerical': 0.0003728560775540641, 'mean_word_length': 2.0071001494768312, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2279369', 'n_tokens_mistral': 2268, 'n_tokens_neox': 2208, 'n_words': 600}