package netflix.adminresources.resources; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.google.common.collect.Maps; import com.google.inject.Inject; import com.google.inject.Key; import com.google.inject.grapher.BindingEdge; import com.google.inject.grapher.DependencyEdge; import com.google.inject.grapher.ImplementationNode; import com.google.inject.grapher.InstanceNode; import com.google.inject.grapher.InterfaceNode; import com.google.inject.grapher.KaryonAbstractInjectorGrapher; import com.google.inject.grapher.NameFactory; import com.google.inject.grapher.Node; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.Map; final class JsonGrapher extends KaryonAbstractInjectorGrapher { private final Map<Key<?>, GraphNode> nodes = Maps.newHashMap(); private final NameFactory nameFactory; private PrintWriter out; private enum Type { Instance, Implementation, Interface } @SuppressWarnings("unused") private class GraphNode { private final List<GraphNode> boundTo = new ArrayList<>(); private final Node node; private final Type type; private final List<GraphNode> dependencies = new ArrayList<>(); private long duration; private long order = -1; public GraphNode(Node node, Type type) { this.node = node; this.type = type; } public void boundTo(GraphNode id) { if (!getName().equals(id.getName())) { this.boundTo.add(id); } } public void dependsOn(GraphNode id) { this.dependencies.add(id); } public String getAnnotation() { return nameFactory.getAnnotationName(node.getId().getKey()); } public Type getType() { return type; } public String getSource() { return nameFactory.getSourceName(node.getSource()); } public String getName() { String annot = nameFactory.getAnnotationName(node.getId().getKey()); return annot.isEmpty() ? nameFactory.getClassName(node.getId().getKey()) : nameFactory.getClassName(node.getId().getKey()) + ":" + annot; } public List<String> getDependencies() { List<String> dep = new ArrayList<>(); for (GraphNode node : dependencies) { if (node != null) { dep.add(node.getName()); } } return dep; } public List<String> getBoundTo() { List<String> dep = new ArrayList<>(); for (GraphNode node : boundTo) { dep.add(node.getName()); } return dep; } public void setDuration(long duration) { this.duration = duration; } public long getDuration() { return duration; } public void setOrder(int order) { this.order = order; } public long getOrder() { return this.order; } } @Inject JsonGrapher(NameFactory nameFactory) { this.nameFactory = nameFactory; } @Override protected void reset() { nodes.clear(); } @Override protected void postProcess() throws IOException { ObjectMapper m = new ObjectMapper(); m.writer() .with(SerializationFeature.INDENT_OUTPUT) .writeValue(out, nodes.values()); } public String quotes(String str) { return "\"" + str + "\""; } @Override protected void newInterfaceNode(InterfaceNode node) { nodes.put(node.getId().getKey(), new GraphNode(node, Type.Interface)); } @Override protected void newImplementationNode(ImplementationNode node) { nodes.put(node.getId().getKey(), new GraphNode(node, Type.Implementation)); } @Override protected void newInstanceNode(InstanceNode node) { nodes.put(node.getId().getKey(), new GraphNode(node, Type.Instance)); } @Override protected void newDependencyEdge(DependencyEdge edge) { nodes.get(edge.getFromId().getKey()) .dependsOn(nodes.get(edge.getToId().getKey())); } @Override protected void newBindingEdge(BindingEdge edge) { nodes.get(edge.getFromId().getKey()) .boundTo(nodes.get(edge.getToId().getKey())); } public void setOut(PrintWriter out) { this.out = out; } }