gonum.org/v1/gonum@v0.14.0/graph/formats/rdf/rdf_example_test.go (about) 1 // Copyright ©2020 The Gonum Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package rdf_test 6 7 import ( 8 "fmt" 9 "log" 10 "os" 11 "strings" 12 "text/tabwriter" 13 14 "gonum.org/v1/gonum/graph" 15 "gonum.org/v1/gonum/graph/encoding" 16 "gonum.org/v1/gonum/graph/encoding/dot" 17 "gonum.org/v1/gonum/graph/formats/rdf" 18 "gonum.org/v1/gonum/graph/multi" 19 ) 20 21 // dotNode implements graph.Node and dot.Node to allow the 22 // RDF term value to be given to the DOT encoder. 23 type dotNode struct { 24 rdf.Term 25 } 26 27 func (n dotNode) DOTID() string { return n.Term.Value } 28 29 // dotLine implements graph.Line and encoding.Attributer to 30 // allow the line's RDF term value to be given to the DOT 31 // encoder and for the nodes to be shimmed to the dotNode 32 // type. 33 // 34 // Because the graph here is directed and we are not performing 35 // any line reversals, it is safe not to implement the 36 // ReversedLine method on dotLine; it will never be called. 37 type dotLine struct { 38 *rdf.Statement 39 } 40 41 func (l dotLine) From() graph.Node { return dotNode{l.Subject} } 42 func (l dotLine) To() graph.Node { return dotNode{l.Object} } 43 44 func (l dotLine) Attributes() []encoding.Attribute { 45 return []encoding.Attribute{{Key: "label", Value: l.Predicate.Value}} 46 } 47 48 func Example_graph() { 49 const statements = ` 50 _:alice <http://xmlns.com/foaf/0.1/knows> _:bob . 51 _:alice <http://xmlns.com/foaf/0.1/givenName> "Alice" . 52 _:alice <http://xmlns.com/foaf/0.1/familyName> "Smith" . 53 _:bob <http://xmlns.com/foaf/0.1/knows> _:alice . 54 _:bob <http://xmlns.com/foaf/0.1/givenName> "Bob" . 55 _:bob <http://xmlns.com/foaf/0.1/familyName> "Smith" . 56 ` 57 58 // Decode the statement stream and insert the lines into a multigraph. 59 g := multi.NewDirectedGraph() 60 dec := rdf.NewDecoder(strings.NewReader(statements)) 61 for { 62 l, err := dec.Unmarshal() 63 if err != nil { 64 break 65 } 66 67 // Wrap the line with a shim type to allow the RDF values 68 // to be passed to the DOT marshaling routine. 69 g.SetLine(dotLine{l}) 70 } 71 72 // Marshal the graph into DOT. 73 b, err := dot.MarshalMulti(g, "smiths", "", "\t") 74 if err != nil { 75 log.Fatal(err) 76 } 77 fmt.Printf("%s\n\n", b) 78 79 // Get the ID look-up table. 80 w := tabwriter.NewWriter(os.Stdout, 0, 4, 1, ' ', 0) 81 fmt.Fprintln(w, "Term\tID") 82 for t, id := range dec.Terms() { 83 fmt.Fprintf(w, "%s\t%d\n", t, id) 84 } 85 w.Flush() 86 87 // Unordered output: 88 // 89 // digraph smiths { 90 // // Node definitions. 91 // "_:alice"; 92 // "_:bob"; 93 // "Alice"; 94 // "Smith"; 95 // "Bob"; 96 // 97 // // Edge definitions. 98 // "_:alice" -> "_:bob" [label=<http://xmlns.com/foaf/0.1/knows>]; 99 // "_:alice" -> "Alice" [label=<http://xmlns.com/foaf/0.1/givenName>]; 100 // "_:alice" -> "Smith" [label=<http://xmlns.com/foaf/0.1/familyName>]; 101 // "_:bob" -> "_:alice" [label=<http://xmlns.com/foaf/0.1/knows>]; 102 // "_:bob" -> "Smith" [label=<http://xmlns.com/foaf/0.1/familyName>]; 103 // "_:bob" -> "Bob" [label=<http://xmlns.com/foaf/0.1/givenName>]; 104 // } 105 // 106 // Term ID 107 // _:alice 1 108 // _:bob 2 109 // <http://xmlns.com/foaf/0.1/knows> 3 110 // "Alice" 4 111 // <http://xmlns.com/foaf/0.1/givenName> 5 112 // "Smith" 6 113 // <http://xmlns.com/foaf/0.1/familyName> 7 114 // "Bob" 8 115 }