package nl.helixsoft.graph; import java.io.OutputStream; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import nl.helixsoft.recordstream.DefaultRecord; import nl.helixsoft.recordstream.DefaultRecordMetaData; import nl.helixsoft.recordstream.MemoryRecordStream; import nl.helixsoft.recordstream.Predicate; import nl.helixsoft.recordstream.Record; import nl.helixsoft.recordstream.RecordMetaData; import nl.helixsoft.recordstream.RecordStream; import nl.helixsoft.util.AttributesTable; import nl.helixsoft.util.StringUtils; import edu.uci.ics.jung.graph.DirectedGraph; import edu.uci.ics.jung.graph.DirectedSparseGraph; public class GraphHelper { private DirectedGraph<String, Edge> net = new DirectedSparseGraph<String, Edge>(); private AttributesTable<String> nodeAttr = new AttributesTable<String>(); private AttributesTable<Edge> edgeAttr = new AttributesTable<Edge>(); //TODO: new logic, somehow also put in Cytoscape plugin public void appendJoin(RecordStream rs, String sep) { for (Record r : rs) { String src = r.get ("src").toString(); net.addVertex(src); nodeAttr.put (src, "label", src); for (int i = 0; i < r.getMetaData().getNumCols(); ++i) { String key = r.getMetaData().getColumnName(i); if (key.equals ("src")) continue; Object val = nodeAttr.get(src, key); if (val == null) { nodeAttr.put (src, key, r.get(i)); } else { nodeAttr.put (src, key, val + sep + r.get(i)); } } } } //TODO: merge logic with MarrsProject public void appendNodeAttributes(RecordStream rs) { for (Record r : rs) { // src must be defined String src = r.get("src").toString(); net.addVertex(src); nodeAttr.put (src, "label", src); for (int i = 0; i < r.getMetaData().getNumCols(); ++i) { String key = r.getMetaData().getColumnName(i); if (key.equals ("src")) continue; nodeAttr.put (src, key, r.get(i)); } } } public void appendBackbone(RecordStream rs) { appendBackbone (rs, false); } //TODO: merge logic with MarrsProject public void appendBackbone(RecordStream rs, boolean mergeEdges) { for (Record r : rs) { // src must be defined String src = r.get("src").toString(); // dest must be defined String dest = r.get("dest").toString(); net.addVertex(src); //TODO: ID gets lost upon import from GML format... nodeAttr.put (src, "label", src); //TODO: ID gets lost upon import from GML format... net.addVertex(dest); nodeAttr.put (dest, "label", dest); Edge e = net.findEdge(src, dest); if (e == null || !mergeEdges) { e = new EdgeImpl(null); net.addEdge(e, src, dest); } for (int i = 0; i < r.getMetaData().getNumCols(); ++i) { String key = r.getMetaData().getColumnName(i); if (key.equals ("src") || key.equals ("dest")) continue; if (key.startsWith ("src_")) { nodeAttr.put (src, key.substring("src_".length()), r.get(i)); } else if (key.startsWith ("dest_")) { nodeAttr.put (dest, key.substring("dest_".length()), r.get(i)); } else { edgeAttr.put (e, key, r.get(i)); } } } } public void toGml(OutputStream os) { GmlFormat.writeGml(os, net, nodeAttr, edgeAttr); } NodeSelection selectAllNodes() { return new NodeSelection(net.getVertices()); } public class NodeSelection { private List<String> selection; @Override public String toString() { return selection.toString(); } private NodeSelection (Collection<String> value) { selection = new ArrayList<String>(value); } public List<String> attribute(String key) { List<String> result = new ArrayList<String>(); for (String node : selection) { result.add (nodeAttr.get(node, key).toString()); } return result; } public RecordStream getRecords(String[] fields) { List<Record> result = new ArrayList<Record>(); RecordMetaData rmd = new DefaultRecordMetaData(fields); for (String node : selection) { String[] values = new String[fields.length]; for (int i = 0; i < fields.length; ++i) { values[i] = StringUtils.safeToString(nodeAttr.get(node, fields[i])); } Record x = new DefaultRecord(rmd, values); result.add (x); } return new MemoryRecordStream(result); } } public class EdgeSelection { private List<Edge> selection; @Override public String toString() { return selection.toString(); } private EdgeSelection (Collection<Edge> value) { selection = new ArrayList<Edge>(value); } public List<String> attribute(String key) { List<String> result = new ArrayList<String>(); for (Edge edge : selection) { result.add (StringUtils.safeToString(edgeAttr.get(edge, key))); } return result; } public RecordStream getRecords(List<String> srcFields, List<String> edgeFields, List<String> destFields) { List<Record> result = new ArrayList<Record>(); List<String> allFields = new ArrayList<String>(); allFields.addAll (srcFields); allFields.addAll (edgeFields); allFields.addAll (destFields); RecordMetaData rmd = new DefaultRecordMetaData(allFields); for (Edge e : selection) { String[] values = new String[allFields.size()]; int col = 0; String src = net.getSource(e); String dest = net.getDest(e); for (int i = 0; i < srcFields.size(); ++i, ++col) { values[col] = StringUtils.safeToString(nodeAttr.get(src, srcFields.get(i))); } for (int i = 0; i < edgeFields.size(); ++i, ++col) { values[col] = StringUtils.safeToString(edgeAttr.get(e, edgeFields.get(i))); } for (int i = 0; i < destFields.size(); ++i, ++col) { values[col] = StringUtils.safeToString(nodeAttr.get(dest, destFields.get(i))); } Record x = new DefaultRecord(rmd, values); result.add (x); } return new MemoryRecordStream(result); } } /** * Select nodes, based on their attributes. Pass a Predicate function that examines the attributes for a given node. */ NodeSelection selectNodes(Predicate<Map<String, Object>> p) { List<String> selection = new ArrayList<String>(); for (String v : net.getVertices()) { if (p.accept(nodeAttr.getRow(v))) { selection.add (v); } } return new NodeSelection(selection); } NodeSelection allNodes() { return new NodeSelection(net.getVertices()); } EdgeSelection selectEdges(Predicate<Map<String, Object>> p) { List<Edge> selection = new ArrayList<Edge>(); for (Edge e : net.getEdges()) { if (p.accept(edgeAttr.getRow(e))) { selection.add (e); } } return new EdgeSelection(selection); } }