2018-11-29 05:40:11 +09:00
|
|
|
package rdfs
|
|
|
|
|
|
|
|
import (
|
2018-12-03 07:48:54 +09:00
|
|
|
"fmt"
|
2019-01-29 05:51:12 +09:00
|
|
|
"github.com/go-fed/activity/astool/rdf"
|
2018-12-03 07:48:54 +09:00
|
|
|
"strings"
|
2018-11-29 05:40:11 +09:00
|
|
|
)
|
|
|
|
|
2018-12-06 06:53:26 +09:00
|
|
|
const (
|
|
|
|
rdfsSpecURI = "http://www.w3.org/2000/01/rdf-schema#"
|
|
|
|
commentSpec = "comment"
|
|
|
|
domainSpec = "domain"
|
|
|
|
isDefinedBySpec = "isDefinedBy"
|
|
|
|
rangeSpec = "range"
|
|
|
|
subClassOfSpec = "subClassOf"
|
|
|
|
subPropertyOfSpec = "subPropertyOf"
|
|
|
|
)
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// RDFSchemaOntology is the Ontology for rdfs.
|
2018-11-29 05:40:11 +09:00
|
|
|
type RDFSchemaOntology struct{}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// SpecURI returns the URI for the RDFS spec.
|
2018-11-29 05:40:11 +09:00
|
|
|
func (o *RDFSchemaOntology) SpecURI() string {
|
2018-12-06 06:53:26 +09:00
|
|
|
return rdfsSpecURI
|
2018-11-29 05:40:11 +09:00
|
|
|
}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// Load this Ontology without an alias.
|
2018-11-29 05:40:11 +09:00
|
|
|
func (o *RDFSchemaOntology) Load() ([]rdf.RDFNode, error) {
|
2018-12-06 06:53:26 +09:00
|
|
|
return o.LoadAsAlias("")
|
2018-11-29 05:40:11 +09:00
|
|
|
}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// LoadAsAlias loads this ontology with an alias.
|
2018-11-29 05:40:11 +09:00
|
|
|
func (o *RDFSchemaOntology) LoadAsAlias(s string) ([]rdf.RDFNode, error) {
|
2018-12-06 06:53:26 +09:00
|
|
|
return []rdf.RDFNode{
|
|
|
|
&rdf.AliasedDelegate{
|
|
|
|
Spec: rdfsSpecURI,
|
|
|
|
Alias: s,
|
|
|
|
Name: commentSpec,
|
|
|
|
Delegate: &comment{},
|
|
|
|
},
|
2018-12-06 07:36:27 +09:00
|
|
|
&rdf.AliasedDelegate{
|
|
|
|
Spec: rdfsSpecURI,
|
|
|
|
Alias: s,
|
|
|
|
Name: domainSpec,
|
|
|
|
Delegate: &domain{},
|
|
|
|
},
|
|
|
|
&rdf.AliasedDelegate{
|
|
|
|
Spec: rdfsSpecURI,
|
|
|
|
Alias: s,
|
|
|
|
Name: isDefinedBySpec,
|
|
|
|
Delegate: &isDefinedBy{},
|
|
|
|
},
|
|
|
|
&rdf.AliasedDelegate{
|
|
|
|
Spec: rdfsSpecURI,
|
|
|
|
Alias: s,
|
|
|
|
Name: rangeSpec,
|
|
|
|
Delegate: &ranges{},
|
|
|
|
},
|
|
|
|
&rdf.AliasedDelegate{
|
|
|
|
Spec: rdfsSpecURI,
|
|
|
|
Alias: s,
|
|
|
|
Name: subClassOfSpec,
|
|
|
|
Delegate: &subClassOf{},
|
|
|
|
},
|
|
|
|
&rdf.AliasedDelegate{
|
|
|
|
Spec: rdfsSpecURI,
|
|
|
|
Alias: s,
|
|
|
|
Name: subPropertyOfSpec,
|
|
|
|
Delegate: &subPropertyOf{},
|
|
|
|
},
|
2018-12-06 06:53:26 +09:00
|
|
|
}, nil
|
2018-11-29 05:40:11 +09:00
|
|
|
}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// LoadSpecificAsAlias loads a specific node as an alias.
|
2018-12-03 04:04:56 +09:00
|
|
|
func (o *RDFSchemaOntology) LoadSpecificAsAlias(alias, name string) ([]rdf.RDFNode, error) {
|
2018-12-06 06:53:26 +09:00
|
|
|
switch name {
|
|
|
|
case commentSpec:
|
|
|
|
return []rdf.RDFNode{
|
|
|
|
&rdf.AliasedDelegate{
|
|
|
|
Spec: "",
|
|
|
|
Alias: "",
|
|
|
|
Name: alias,
|
|
|
|
Delegate: &comment{},
|
|
|
|
},
|
|
|
|
}, nil
|
|
|
|
case domainSpec:
|
|
|
|
return []rdf.RDFNode{
|
|
|
|
&rdf.AliasedDelegate{
|
|
|
|
Spec: "",
|
|
|
|
Alias: "",
|
|
|
|
Name: alias,
|
|
|
|
Delegate: &domain{},
|
|
|
|
},
|
|
|
|
}, nil
|
|
|
|
case isDefinedBySpec:
|
|
|
|
return []rdf.RDFNode{
|
|
|
|
&rdf.AliasedDelegate{
|
|
|
|
Spec: "",
|
|
|
|
Alias: "",
|
|
|
|
Name: alias,
|
|
|
|
Delegate: &isDefinedBy{},
|
|
|
|
},
|
|
|
|
}, nil
|
|
|
|
case rangeSpec:
|
|
|
|
return []rdf.RDFNode{
|
|
|
|
&rdf.AliasedDelegate{
|
|
|
|
Spec: "",
|
|
|
|
Alias: "",
|
|
|
|
Name: alias,
|
|
|
|
Delegate: &ranges{},
|
|
|
|
},
|
|
|
|
}, nil
|
|
|
|
case subClassOfSpec:
|
|
|
|
return []rdf.RDFNode{
|
|
|
|
&rdf.AliasedDelegate{
|
|
|
|
Spec: "",
|
|
|
|
Alias: "",
|
|
|
|
Name: alias,
|
|
|
|
Delegate: &subClassOf{},
|
|
|
|
},
|
|
|
|
}, nil
|
|
|
|
case subPropertyOfSpec:
|
|
|
|
return []rdf.RDFNode{
|
|
|
|
&rdf.AliasedDelegate{
|
|
|
|
Spec: "",
|
|
|
|
Alias: "",
|
|
|
|
Name: alias,
|
2018-12-06 07:36:27 +09:00
|
|
|
Delegate: &subPropertyOf{},
|
2018-12-06 06:53:26 +09:00
|
|
|
},
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
return nil, fmt.Errorf("rdfs ontology cannot find %q to alias to %q", name, alias)
|
2018-12-03 04:04:56 +09:00
|
|
|
}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// LoadElement does nothing.
|
2018-11-29 05:40:11 +09:00
|
|
|
func (o *RDFSchemaOntology) LoadElement(name string, payload map[string]interface{}) ([]rdf.RDFNode, error) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
2018-12-03 07:48:54 +09:00
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// GetByName returns a bare node by name.
|
2018-12-03 07:48:54 +09:00
|
|
|
func (o *RDFSchemaOntology) GetByName(name string) (rdf.RDFNode, error) {
|
|
|
|
name = strings.TrimPrefix(name, o.SpecURI())
|
|
|
|
switch name {
|
2018-12-06 06:53:26 +09:00
|
|
|
case commentSpec:
|
|
|
|
return &comment{}, nil
|
|
|
|
case domainSpec:
|
|
|
|
return &domain{}, nil
|
|
|
|
case isDefinedBySpec:
|
|
|
|
return &isDefinedBy{}, nil
|
|
|
|
case rangeSpec:
|
|
|
|
return &ranges{}, nil
|
|
|
|
case subClassOfSpec:
|
|
|
|
return &subClassOf{}, nil
|
|
|
|
case subPropertyOfSpec:
|
|
|
|
return &subPropertyOf{}, nil
|
2018-12-03 07:48:54 +09:00
|
|
|
}
|
|
|
|
return nil, fmt.Errorf("rdfs ontology could not find node for name %s", name)
|
|
|
|
}
|
2018-12-06 06:53:26 +09:00
|
|
|
|
|
|
|
var _ rdf.RDFNode = &comment{}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// comment sets Notes on vocabulary items.
|
2018-12-06 06:53:26 +09:00
|
|
|
type comment struct{}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// Enter returns an error.
|
2018-12-06 06:53:26 +09:00
|
|
|
func (n *comment) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
|
|
|
|
return true, fmt.Errorf("rdfs comment cannot be entered")
|
|
|
|
}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// Exit returns an error.
|
2018-12-06 06:53:26 +09:00
|
|
|
func (n *comment) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
|
|
|
|
return true, fmt.Errorf("rdfs comment cannot be exited")
|
|
|
|
}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// Apply sets the string value on Current's Notes.
|
|
|
|
//
|
|
|
|
// Returns an error if value isn't a string or Current can't set Notes.
|
2018-12-06 06:53:26 +09:00
|
|
|
func (n *comment) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
|
|
|
|
note, ok := value.(string)
|
|
|
|
if !ok {
|
|
|
|
return true, fmt.Errorf("rdf comment not given string value")
|
|
|
|
}
|
|
|
|
if ctx.Current == nil {
|
|
|
|
return true, fmt.Errorf("rdf comment given nil Current")
|
|
|
|
}
|
|
|
|
noteSetter, ok := ctx.Current.(rdf.NotesSetter)
|
|
|
|
if !ok {
|
|
|
|
return true, fmt.Errorf("rdf comment not given NotesSetter")
|
|
|
|
}
|
|
|
|
noteSetter.SetNotes(note)
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ rdf.RDFNode = &domain{}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// domain is rdfs:domain.
|
2018-12-06 06:53:26 +09:00
|
|
|
type domain struct{}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// Enter Pushes a Reference as Current.
|
2018-12-06 06:53:26 +09:00
|
|
|
func (d *domain) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
|
2018-12-06 07:36:27 +09:00
|
|
|
ctx.Push()
|
|
|
|
ctx.Current = make([]rdf.VocabularyReference, 0)
|
2018-12-06 06:53:26 +09:00
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// Exit Pops a slice of References and sets it on the parent Property.
|
|
|
|
//
|
|
|
|
// Returns an error if the popped item is not a slice of References, or if the
|
|
|
|
// Current after Popping is not a Property.
|
2018-12-06 06:53:26 +09:00
|
|
|
func (d *domain) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
|
2018-12-06 07:36:27 +09:00
|
|
|
i := ctx.Current
|
|
|
|
ctx.Pop()
|
|
|
|
vr, ok := i.([]rdf.VocabularyReference)
|
|
|
|
if !ok {
|
|
|
|
return true, fmt.Errorf("rdfs domain exit did not get []rdf.VocabularyReference")
|
|
|
|
}
|
|
|
|
vp, ok := ctx.Current.(*rdf.VocabularyProperty)
|
|
|
|
if !ok {
|
|
|
|
return true, fmt.Errorf("rdf domain exit Current is not *rdf.VocabularyProperty")
|
|
|
|
}
|
|
|
|
vp.Domain = append(vp.Domain, vr...)
|
2018-12-06 06:53:26 +09:00
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// Apply returns an error.
|
2018-12-06 06:53:26 +09:00
|
|
|
func (d *domain) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
|
2018-12-06 07:36:27 +09:00
|
|
|
return true, fmt.Errorf("rdfs domain cannot be applied")
|
2018-12-06 06:53:26 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
var _ rdf.RDFNode = &isDefinedBy{}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// isDefinedBy is rdfs:isDefinedBy.
|
2018-12-06 06:53:26 +09:00
|
|
|
type isDefinedBy struct{}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// Enter returns an error.
|
2018-12-06 06:53:26 +09:00
|
|
|
func (i *isDefinedBy) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
|
2018-12-06 07:36:27 +09:00
|
|
|
return true, fmt.Errorf("rdfs isDefinedBy cannot be entered")
|
2018-12-06 06:53:26 +09:00
|
|
|
}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// Exit returns an error.
|
2018-12-06 06:53:26 +09:00
|
|
|
func (i *isDefinedBy) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
|
2018-12-06 07:36:27 +09:00
|
|
|
return true, fmt.Errorf("rdfs isDefinedBy cannot be exited")
|
2018-12-06 06:53:26 +09:00
|
|
|
}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// Apply sets the string value as Current's URI.
|
|
|
|
//
|
|
|
|
// Returns an error if value is not a string or if Current cannot have a URI
|
|
|
|
// set.
|
2018-12-06 06:53:26 +09:00
|
|
|
func (i *isDefinedBy) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
|
2018-12-06 07:36:27 +09:00
|
|
|
s, ok := value.(string)
|
|
|
|
if !ok {
|
|
|
|
return true, fmt.Errorf("rdfs isDefinedBy given non-string: %T", value)
|
|
|
|
}
|
|
|
|
u, ok := ctx.Current.(rdf.URISetter)
|
|
|
|
if !ok {
|
|
|
|
return true, fmt.Errorf("rdfs isDefinedBy Current is not rdf.URISetter: %T", ctx.Current)
|
|
|
|
}
|
|
|
|
return true, u.SetURI(s)
|
2018-12-06 06:53:26 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
var _ rdf.RDFNode = &ranges{}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// ranges is rdfs:ranges.
|
2018-12-06 06:53:26 +09:00
|
|
|
type ranges struct{}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// Enter Pushes as a slice of References as Current.
|
2018-12-06 06:53:26 +09:00
|
|
|
func (r *ranges) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
|
2018-12-06 07:36:27 +09:00
|
|
|
ctx.Push()
|
|
|
|
ctx.Current = make([]rdf.VocabularyReference, 0)
|
2018-12-06 06:53:26 +09:00
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// Exit Pops a slice of References and sets it on the parent Property.
|
|
|
|
//
|
|
|
|
// Returns an error if the popped item is not a slice of references, or if the
|
|
|
|
// Current item after popping is not a Property.
|
2018-12-06 06:53:26 +09:00
|
|
|
func (r *ranges) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
|
2018-12-06 07:36:27 +09:00
|
|
|
i := ctx.Current
|
|
|
|
ctx.Pop()
|
|
|
|
vr, ok := i.([]rdf.VocabularyReference)
|
|
|
|
if !ok {
|
|
|
|
return true, fmt.Errorf("rdfs ranges exit did not get []rdf.VocabularyReference")
|
|
|
|
}
|
|
|
|
vp, ok := ctx.Current.(*rdf.VocabularyProperty)
|
|
|
|
if !ok {
|
|
|
|
return true, fmt.Errorf("rdf ranges exit Current is not *rdf.VocabularyProperty")
|
|
|
|
}
|
|
|
|
vp.Range = append(vp.Range, vr...)
|
2018-12-06 06:53:26 +09:00
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// Apply returns an error.
|
2018-12-06 06:53:26 +09:00
|
|
|
func (r *ranges) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
|
2018-12-06 07:36:27 +09:00
|
|
|
return true, fmt.Errorf("rdfs ranges cannot be applied")
|
2018-12-06 06:53:26 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
var _ rdf.RDFNode = &subClassOf{}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// subClassOf implements rdfs:subClassOf.
|
2018-12-06 06:53:26 +09:00
|
|
|
type subClassOf struct{}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// Enter Pushes a Reference as Current.
|
2018-12-06 06:53:26 +09:00
|
|
|
func (s *subClassOf) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
|
|
|
|
ctx.Push()
|
|
|
|
ctx.Current = &rdf.VocabularyReference{}
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// Exit Pops a Reference and appends it to the parent Type's Extends.
|
|
|
|
//
|
|
|
|
// Returns an error if the popped item is not a reference, or if the Current
|
|
|
|
// item after popping is not a Type.
|
2018-12-06 06:53:26 +09:00
|
|
|
func (s *subClassOf) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
|
|
|
|
i := ctx.Current
|
|
|
|
ctx.Pop()
|
|
|
|
vr, ok := i.(*rdf.VocabularyReference)
|
|
|
|
if !ok {
|
|
|
|
return true, fmt.Errorf("rdfs subclassof exit did not get *rdf.VocabularyReference")
|
|
|
|
}
|
|
|
|
vt, ok := ctx.Current.(*rdf.VocabularyType)
|
|
|
|
if !ok {
|
|
|
|
return true, fmt.Errorf("rdf subclassof exit Current is not *rdf.VocabularyType")
|
|
|
|
}
|
|
|
|
vt.Extends = append(vt.Extends, *vr)
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// Apply returns an error.
|
2018-12-06 06:53:26 +09:00
|
|
|
func (s *subClassOf) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
|
|
|
|
return true, fmt.Errorf("rdfs subclassof cannot be applied")
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ rdf.RDFNode = &subPropertyOf{}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// subPropertyOf is rdfs:subPropertyOf
|
2018-12-06 06:53:26 +09:00
|
|
|
type subPropertyOf struct{}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// Enter Pushes a Reference as Current.
|
2018-12-06 06:53:26 +09:00
|
|
|
func (s *subPropertyOf) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
|
2018-12-06 07:36:27 +09:00
|
|
|
ctx.Push()
|
|
|
|
ctx.Current = &rdf.VocabularyReference{}
|
2018-12-06 06:53:26 +09:00
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// Exit Pops a Reference and sets it as the parent property's SubpropertyOf.
|
|
|
|
//
|
|
|
|
// Returns an error if the popped item is not a Reference, or if after popping
|
|
|
|
// Current is not a Property.
|
2018-12-06 06:53:26 +09:00
|
|
|
func (s *subPropertyOf) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
|
2018-12-06 07:36:27 +09:00
|
|
|
i := ctx.Current
|
|
|
|
ctx.Pop()
|
|
|
|
vr, ok := i.(*rdf.VocabularyReference)
|
|
|
|
if !ok {
|
|
|
|
return true, fmt.Errorf("rdfs subpropertyof exit did not get *rdf.VocabularyReference")
|
|
|
|
}
|
|
|
|
vp, ok := ctx.Current.(*rdf.VocabularyProperty)
|
|
|
|
if !ok {
|
|
|
|
return true, fmt.Errorf("rdf subpropertyof exit Current is not *rdf.VocabularyProperty")
|
|
|
|
}
|
|
|
|
vp.SubpropertyOf = *vr
|
2018-12-06 06:53:26 +09:00
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
2019-01-13 04:53:00 +09:00
|
|
|
// Apply returns an error.
|
2018-12-06 06:53:26 +09:00
|
|
|
func (s *subPropertyOf) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
|
2018-12-06 07:36:27 +09:00
|
|
|
return true, fmt.Errorf("rdfs subpropertyof cannot be applied")
|
2018-12-06 06:53:26 +09:00
|
|
|
}
|