feat: initial commit
This commit is contained in:
commit
a161b86c9a
705 changed files with 288162 additions and 0 deletions
368
vendor/sourcery.dny.nu/longdistance/node.go
vendored
Normal file
368
vendor/sourcery.dny.nu/longdistance/node.go
vendored
Normal file
|
|
@ -0,0 +1,368 @@
|
|||
package longdistance
|
||||
|
||||
import (
|
||||
"sourcery.dny.nu/longdistance/internal/json"
|
||||
)
|
||||
|
||||
// Properties is a key-to-array-of-[Node] map.
|
||||
//
|
||||
// It's used to hold any property that's not a JSON-LD keyword.
|
||||
type Properties map[string][]Node
|
||||
|
||||
// Node represents a node in a JSON-LD graph.
|
||||
//
|
||||
// Every supported JSON-LD keyword has a field of its own. All remaining
|
||||
// properties are tracked on the Properties field.
|
||||
type Node struct {
|
||||
Direction string // @direction / KeywordDirection
|
||||
Graph []Node // @graph / KeywordGraph
|
||||
ID string // @id / KeywordID
|
||||
Included []Node // @included / KeywordIncluded
|
||||
Index string // @index / KeywordIndex
|
||||
Language string // @language / KeywordLanguage
|
||||
List []Node // @list / KeywordList
|
||||
Reverse Properties // @reverse / KeywordReverse
|
||||
Set []Node // @set / KeywordSet
|
||||
Type []string // @type / KeywordType
|
||||
Value json.RawMessage // @value / KeywordValue
|
||||
|
||||
Properties Properties // everything else
|
||||
}
|
||||
|
||||
// Internal is a generic type that matches the internals of [Node].
|
||||
//
|
||||
// This can be used to convert to a [Node] from any type outside this package
|
||||
// that happens to be a [Node] underneath.
|
||||
type Internal interface {
|
||||
~struct {
|
||||
Direction string
|
||||
Graph []Node
|
||||
ID string
|
||||
Included []Node
|
||||
Index string
|
||||
Language string
|
||||
List []Node
|
||||
Reverse Properties
|
||||
Set []Node
|
||||
Type []string
|
||||
Value json.RawMessage
|
||||
Properties Properties
|
||||
}
|
||||
}
|
||||
|
||||
// PropertySet returns a [Set] with an entry for each property that is set on
|
||||
// the [Node].
|
||||
func (n *Node) PropertySet() map[string]struct{} {
|
||||
if n == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
res := make(map[string]struct{}, len(n.Properties)+2)
|
||||
if n.Has(KeywordDirection) {
|
||||
res[KeywordDirection] = struct{}{}
|
||||
}
|
||||
if n.Has(KeywordGraph) {
|
||||
res[KeywordGraph] = struct{}{}
|
||||
}
|
||||
if n.Has(KeywordID) {
|
||||
res[KeywordID] = struct{}{}
|
||||
}
|
||||
if n.Has(KeywordIncluded) {
|
||||
res[KeywordIncluded] = struct{}{}
|
||||
}
|
||||
if n.Has(KeywordIndex) {
|
||||
res[KeywordIndex] = struct{}{}
|
||||
}
|
||||
if n.Has(KeywordLanguage) {
|
||||
res[KeywordLanguage] = struct{}{}
|
||||
}
|
||||
if n.Has(KeywordList) {
|
||||
res[KeywordList] = struct{}{}
|
||||
}
|
||||
if n.Has(KeywordReverse) {
|
||||
res[KeywordReverse] = struct{}{}
|
||||
}
|
||||
if n.Has(KeywordSet) {
|
||||
res[KeywordSet] = struct{}{}
|
||||
}
|
||||
if n.Has(KeywordType) {
|
||||
res[KeywordType] = struct{}{}
|
||||
}
|
||||
if n.Has(KeywordValue) {
|
||||
res[KeywordValue] = struct{}{}
|
||||
}
|
||||
|
||||
for p := range n.Properties {
|
||||
res[p] = struct{}{}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func (n *Node) propsWithout(props ...string) map[string]struct{} {
|
||||
nprops := n.PropertySet()
|
||||
for _, prop := range props {
|
||||
delete(nprops, prop)
|
||||
}
|
||||
return nprops
|
||||
}
|
||||
|
||||
func (n *Node) isNode() bool {
|
||||
if n == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return !n.Has(KeywordList) && !n.Has(KeywordValue) && !n.Has(KeywordSet)
|
||||
}
|
||||
|
||||
// Has returns if a node has the requested property.
|
||||
//
|
||||
// Properties must either be a JSON-LD keyword, or an expanded IRI.
|
||||
func (n *Node) Has(prop string) bool {
|
||||
if n == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
switch prop {
|
||||
case KeywordID:
|
||||
return n.ID != ""
|
||||
case KeywordValue:
|
||||
return n.Value != nil
|
||||
case KeywordLanguage:
|
||||
return n.Language != ""
|
||||
case KeywordDirection:
|
||||
return n.Direction != ""
|
||||
case KeywordType:
|
||||
return n.Type != nil
|
||||
case KeywordList:
|
||||
return n.List != nil
|
||||
case KeywordSet:
|
||||
return n.Set != nil
|
||||
case KeywordGraph:
|
||||
return n.Graph != nil
|
||||
case KeywordIncluded:
|
||||
return n.Included != nil
|
||||
case KeywordIndex:
|
||||
return n.Index != ""
|
||||
case KeywordReverse:
|
||||
return n.Reverse != nil
|
||||
default:
|
||||
for key := range n.Properties {
|
||||
if prop == key {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// IsZero returns if this is the zero value of a [Node].
|
||||
func (n *Node) IsZero() bool {
|
||||
if n == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
return len(n.PropertySet()) == 0
|
||||
}
|
||||
|
||||
// IsSubject checks if this node is a subject.
|
||||
//
|
||||
// This means:
|
||||
// - It has an @id.
|
||||
// - It may have an @type.
|
||||
// - It has at least one other property.
|
||||
func (n *Node) IsSubject() bool {
|
||||
if n == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if !n.Has(KeywordID) {
|
||||
return false
|
||||
}
|
||||
|
||||
return len(n.propsWithout(KeywordID, KeywordIndex)) != 0
|
||||
}
|
||||
|
||||
// IsSubjectReference checks if this node is a subject reference.
|
||||
//
|
||||
// This means:
|
||||
// - It has an @id.
|
||||
// - It may have an @type.
|
||||
// - It has no other properties.
|
||||
func (n *Node) IsSubjectReference() bool {
|
||||
if n == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if !n.Has(KeywordID) {
|
||||
return false
|
||||
}
|
||||
|
||||
return len(n.propsWithout(KeywordID, KeywordType)) == 0
|
||||
}
|
||||
|
||||
// IsList checks if this node is a list.
|
||||
//
|
||||
// This means:
|
||||
// - It has an @list.
|
||||
// - It has no other properties.
|
||||
func (n *Node) IsList() bool {
|
||||
if n == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if !n.Has(KeywordList) {
|
||||
return false
|
||||
}
|
||||
|
||||
return len(n.propsWithout(KeywordList, KeywordIndex)) == 0
|
||||
}
|
||||
|
||||
// IsValue checks if this is a value node.
|
||||
//
|
||||
// This means:
|
||||
// - It has an @value.
|
||||
// - It may have an @direction, @index, @langauge and @type.
|
||||
// - It has no other properties.
|
||||
//
|
||||
// Additionally, it's invalid to have @type together with @language or
|
||||
// @direction.
|
||||
func (n *Node) IsValue() bool {
|
||||
if n == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if !n.Has(KeywordValue) {
|
||||
return false
|
||||
}
|
||||
|
||||
return len(n.propsWithout(
|
||||
KeywordValue,
|
||||
KeywordDirection,
|
||||
KeywordIndex,
|
||||
KeywordLanguage,
|
||||
KeywordType,
|
||||
)) == 0
|
||||
}
|
||||
|
||||
// IsGraph returns if the object is a graph.
|
||||
//
|
||||
// This requires:
|
||||
// - It must have an @graph.
|
||||
// - It may have @id and @index.
|
||||
// - It has no other properties.
|
||||
func (n *Node) IsGraph() bool {
|
||||
if n == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if !n.Has(KeywordGraph) {
|
||||
return false
|
||||
}
|
||||
|
||||
return len(n.propsWithout(KeywordID, KeywordIndex, KeywordGraph)) == 0
|
||||
}
|
||||
|
||||
// IsSimpleGraph returns if the object is a simple graph.
|
||||
//
|
||||
// This requires:
|
||||
// - It must have an @graph.
|
||||
// - It may have @index.
|
||||
// - It has no other properties.
|
||||
func (n *Node) IsSimpleGraph() bool {
|
||||
if n == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if !n.Has(KeywordGraph) {
|
||||
return false
|
||||
}
|
||||
|
||||
return len(n.propsWithout(KeywordIndex, KeywordGraph)) == 0
|
||||
}
|
||||
|
||||
// MarshalJSON encodes to Expanded Document Form.
|
||||
func (n *Node) MarshalJSON() ([]byte, error) {
|
||||
result := map[string]any{}
|
||||
|
||||
if n.Has(KeywordID) {
|
||||
result[KeywordID] = n.ID
|
||||
}
|
||||
|
||||
if n.Has(KeywordIndex) {
|
||||
result[KeywordIndex] = n.Index
|
||||
}
|
||||
|
||||
if n.Has(KeywordType) {
|
||||
var data any
|
||||
if n.Value != nil && len(n.Type) == 1 {
|
||||
data = n.Type[0]
|
||||
} else {
|
||||
data = n.Type
|
||||
}
|
||||
result[KeywordType] = data
|
||||
}
|
||||
|
||||
if n.Has(KeywordValue) {
|
||||
result[KeywordValue] = n.Value
|
||||
}
|
||||
|
||||
if n.Has(KeywordLanguage) {
|
||||
result[KeywordLanguage] = n.Language
|
||||
}
|
||||
|
||||
if n.Has(KeywordDirection) {
|
||||
result[KeywordDirection] = n.Direction
|
||||
}
|
||||
|
||||
if n.Has(KeywordList) {
|
||||
result[KeywordList] = n.List
|
||||
}
|
||||
|
||||
if n.Has(KeywordGraph) {
|
||||
result[KeywordGraph] = n.Graph
|
||||
}
|
||||
|
||||
if n.Has(KeywordIncluded) {
|
||||
result[KeywordIncluded] = n.Included
|
||||
}
|
||||
|
||||
if n.Has(KeywordReverse) {
|
||||
result[KeywordReverse] = n.Reverse
|
||||
}
|
||||
|
||||
for k, v := range n.Properties {
|
||||
result[k] = v
|
||||
}
|
||||
|
||||
return json.Marshal(result)
|
||||
}
|
||||
|
||||
// GetNodes returns the nodes stored in property.
|
||||
func (n *Node) GetNodes(property string) []Node {
|
||||
switch property {
|
||||
case KeywordGraph:
|
||||
return n.Graph
|
||||
case KeywordIncluded:
|
||||
return n.Included
|
||||
case KeywordList:
|
||||
return n.List
|
||||
case KeywordSet:
|
||||
return n.Set
|
||||
default:
|
||||
if !n.Has(property) {
|
||||
return nil
|
||||
}
|
||||
return n.Properties[property]
|
||||
}
|
||||
}
|
||||
|
||||
// AddNodes appends the nodes stored in property.
|
||||
func (n *Node) AddNodes(property string, nodes ...Node) {
|
||||
n.Properties[property] = append(n.Properties[property], nodes...)
|
||||
}
|
||||
|
||||
// SetNodes overrides the nodes stored in property.
|
||||
func (n *Node) SetNodes(property string, nodes ...Node) {
|
||||
n.Properties[property] = nodes
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue