bookdata/graph/
gml.rs

1use std::fs::File;
2use std::io::prelude::*;
3use std::io::BufWriter;
4use std::path::Path;
5
6use anyhow::Result;
7use log::*;
8use petgraph::visit::*;
9
10use crate::ids::codes::ns_of_book_code;
11
12use super::{IdGraph, IdNode};
13
14fn gml_begin<W: Write>(w: &mut W) -> Result<()> {
15    writeln!(w, "graph [")?;
16    Ok(())
17}
18
19fn gml_end<W: Write>(w: &mut W) -> Result<()> {
20    writeln!(w, "]")?;
21    Ok(())
22}
23
24fn gml_node<W: Write>(w: &mut W, graph: &IdGraph, v: IdNode) -> Result<()> {
25    let node = graph.node_weight(v).unwrap();
26    writeln!(w, "  node [")?;
27    writeln!(w, "    id {}", node.code)?;
28    let ns = ns_of_book_code(node.code).unwrap();
29    writeln!(w, "    namespace \"{}\"", ns.name())?;
30    if let Some(ref l) = node.label {
31        writeln!(w, "    label \"{}\"", l)?;
32    }
33    writeln!(w, "  ]")?;
34    Ok(())
35}
36
37fn gml_edge<W: Write>(w: &mut W, graph: &IdGraph, sv: IdNode, dv: IdNode) -> Result<()> {
38    let src = graph.node_weight(sv).unwrap();
39    let dst = graph.node_weight(dv).unwrap();
40    writeln!(w, "  edge [")?;
41    writeln!(w, "    source {}", src.code)?;
42    writeln!(w, "    target {}", dst.code)?;
43    writeln!(w, "  ]")?;
44    Ok(())
45}
46
47/// Save a graph to a GML file.
48pub fn save_gml<P: AsRef<Path>>(graph: &IdGraph, path: P) -> Result<()> {
49    info!("saving graph to {}", path.as_ref().to_string_lossy());
50    let out = File::create(path)?;
51    let mut out = BufWriter::new(out);
52    gml_begin(&mut out)?;
53    for n in graph.node_indices() {
54        gml_node(&mut out, graph, n)?;
55    }
56    for e in graph.edge_references() {
57        gml_edge(&mut out, graph, e.source(), e.target())?;
58    }
59    gml_end(&mut out)?;
60    Ok(())
61}