package org.cytoscape.d3.internal.serializer; import java.io.IOException; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import org.cytoscape.model.CyIdentifiable; import org.cytoscape.model.CyNetwork; import org.cytoscape.model.CyNode; import org.cytoscape.model.CyRow; import org.cytoscape.view.model.CyNetworkView; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; /** * Use selected node as the root. * * */ public class D3CyNetworkViewTreeSerializer extends JsonSerializer<CyNetworkView> { private Set<CyNode> expanded; @Override public void serialize(final CyNetworkView networkView, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { final CyNetwork network = networkView.getModel(); Collection<CyRow> root = network.getDefaultNodeTable().getMatchingRows(CyNetwork.SELECTED, true); if (root.size() != 1) { throw new IllegalStateException("You need to select one node as the root for this tree."); } CyRow rootNodeRow = root.iterator().next(); final CyNode rootNode = network.getNode(rootNodeRow.get(CyIdentifiable.SUID, Long.class)); if (rootNode == null) { throw new IllegalStateException("Could not find the root for this tree."); } jgen.useDefaultPrettyPrinter(); expanded = new HashSet<CyNode>(); getChildren(network, rootNode, jgen); } private final void getChildren(CyNetwork network, CyNode node, JsonGenerator jgen) throws IOException { if(network == null || node == null || jgen == null) throw new NullPointerException(); expanded.add(node); final List<CyNode> children = network.getNeighborList(node, org.cytoscape.model.CyEdge.Type.ANY); jgen.writeStartObject(); // Write labels CyRow row = network.getRow(node); jgen.writeObject(row); if(children.isEmpty()) { // Leaf jgen.writeEndObject(); return; } else { // Remove if already visited. Set<CyNode> notVisited = new HashSet<CyNode>(); for(CyNode child: children) { if(expanded.contains(child) == false) notVisited.add(child); } if(notVisited.isEmpty()) { jgen.writeEndObject(); return; } // Need to add children section jgen.writeArrayFieldStart("children"); for(CyNode child: notVisited) { getChildren(network, child, jgen); } jgen.writeEndArray(); jgen.writeEndObject(); } } @Override public Class<CyNetworkView> handledType() { return CyNetworkView.class; } }