package main type termKey struct { termType string key string } type termMeta struct { termType string iri string } func graphFromSparqlBindings( bindings []map[string]sparqlTerm, nodeLimit int, includeBNodes bool, ) (nodes []Node, edges []Edge) { nodeIDByKey := map[termKey]int{} nodeMeta := make([]termMeta, 0, min(nodeLimit, 4096)) getOrAdd := func(term sparqlTerm) (int, bool) { if term.Type == "" || term.Value == "" { return 0, false } if term.Type == "literal" { return 0, false } var key termKey var meta termMeta if term.Type == "bnode" { if !includeBNodes { return 0, false } key = termKey{termType: "bnode", key: term.Value} meta = termMeta{termType: "bnode", iri: "_:" + term.Value} } else { key = termKey{termType: "uri", key: term.Value} meta = termMeta{termType: "uri", iri: term.Value} } if existing, ok := nodeIDByKey[key]; ok { return existing, true } if len(nodeMeta) >= nodeLimit { return 0, false } nid := len(nodeMeta) nodeIDByKey[key] = nid nodeMeta = append(nodeMeta, meta) return nid, true } for _, b := range bindings { sTerm := b["s"] oTerm := b["o"] pTerm := b["p"] sid, okS := getOrAdd(sTerm) oid, okO := getOrAdd(oTerm) if !okS || !okO { continue } pred := pTerm.Value if pred == "" { continue } edges = append(edges, Edge{ Source: sid, Target: oid, Predicate: pred, }) } nodes = make([]Node, len(nodeMeta)) for i, m := range nodeMeta { nodes[i] = Node{ ID: i, TermType: m.termType, IRI: m.iri, Label: nil, X: 0, Y: 0, } } return nodes, edges } func min(a, b int) int { if a < b { return a } return b }