99 lines
1.7 KiB
Go
99 lines
1.7 KiB
Go
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
|
|
}
|