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  }