Hack for "without property", begin resolving references.

Also begin populating values in the intermediate definition.

TODO: Replace the hack in the spec definition with something applicable
RDF-wise (is there anything that permits this RDF wise?).
このコミットが含まれているのは:
Cory Slep 2018-12-08 17:50:26 +01:00
コミット 139dc3c5ea
5個のファイルの変更237行の追加23行の削除

ファイルの表示

@ -16,7 +16,17 @@ import (
// details.
type ParsedVocabulary struct {
Vocab Vocabulary
References map[string]Vocabulary
References map[string]*Vocabulary
}
func (p *ParsedVocabulary) GetReference(uri string) *Vocabulary {
if p.References == nil {
p.References = make(map[string]*Vocabulary, 0)
}
if _, ok := p.References[uri]; !ok {
p.References[uri] = &Vocabulary{}
}
return p.References[uri]
}
func (p ParsedVocabulary) String() string {
@ -117,18 +127,16 @@ var (
// VocabularyType represents a single ActivityStream type in a vocabulary.
type VocabularyType struct {
Name string
URI *url.URL
Notes string
DisjointWith []VocabularyReference
Extends []VocabularyReference // TODO: Object improperly extends Link
Properties []VocabularyReference // TODO: Check for duplication
WithoutProperties []VocabularyReference // TODO: Missing for IntransitiveActivity
Examples []VocabularyExample
Name string
URI *url.URL
Notes string
DisjointWith []VocabularyReference
Extends []VocabularyReference
Examples []VocabularyExample
}
func (v VocabularyType) String() string {
return fmt.Sprintf("Type=%s,%s,%s", v.Name, v.URI, v.Notes)
return fmt.Sprintf("Type=%s,%s,%s\n\tDJW=%s\n\tExt=%s\n\tEx=%s", v.Name, v.URI, v.Notes, v.DisjointWith, v.Extends, v.Examples)
}
func (v *VocabularyType) SetName(s string) {
@ -164,12 +172,13 @@ var (
// VocabularyProperty represents a single ActivityStream property type in a
// vocabulary.
type VocabularyProperty struct {
Name string
URI *url.URL
Notes string
Domain []VocabularyReference
Range []VocabularyReference
Examples []VocabularyExample
Name string
URI *url.URL
Notes string
Domain []VocabularyReference
Range []VocabularyReference
DoesNotApplyTo []VocabularyReference
Examples []VocabularyExample
// SubpropertyOf is ignorable as long as data is set up correctly TODO: Is this still correct?
SubpropertyOf VocabularyReference // Must be a VocabularyProperty
Functional bool
@ -177,7 +186,7 @@ type VocabularyProperty struct {
}
func (v VocabularyProperty) String() string {
return fmt.Sprintf("Property=%s,%s,%s,%s,%s", v.Name, v.URI, v.Notes, v.Functional, v.NaturalLanguageMap)
return fmt.Sprintf("Property=%s,%s,%s\n\tD=%s\n\tR=%s\n\tEx=%s\n\tSub=%s\n\tDNApply=%s\n\tfunc=%t,natLangMap=%t", v.Name, v.URI, v.Notes, v.Domain, v.Range, v.Examples, v.SubpropertyOf, v.DoesNotApplyTo, v.Functional, v.NaturalLanguageMap)
}
func (v *VocabularyProperty) SetName(s string) {
@ -218,6 +227,10 @@ type VocabularyExample struct {
Example interface{}
}
func (v VocabularyExample) String() string {
return fmt.Sprintf("VocabularyExample: %s,%s,%s", v.Name, v.URI, v.Example)
}
func (v *VocabularyExample) SetName(s string) {
v.Name = s
}
@ -247,6 +260,10 @@ type VocabularyReference struct {
Vocab string // If present, must match key in ParsedVocabulary.References
}
func (v VocabularyReference) String() string {
return fmt.Sprintf("VocabularyReference: %s,%s,%s", v.Name, v.URI, v.Vocab)
}
func (v *VocabularyReference) SetName(s string) {
v.Name = s
}

ファイルの表示

@ -11,6 +11,13 @@ const (
IdActivityStreamsSpec = "id"
ContainerSpec = "@container"
IndexSpec = "@index"
// ActivityStreams specifically disallows the 'object' property on
// certain IntransitiveActivity and subtypes. There is no RDF mechanism
// to describe this. So this is a stupid hack, based on the assumption
// that no one -- W3C or otherwise -- will name a reserved word with a
// "@wtf_" prefix due to the reserved '@', the use of the unprofessional
// 'wtf', and a style-breaking underscore.
withoutPropertySpec = "@wtf_without_property"
)
// jsonLDNodes contains the well-known set of nodes as defined by the JSON-LD
@ -55,6 +62,12 @@ func jsonLDNodes(r *RDFRegistry) []RDFNode {
Name: IndexSpec,
Delegate: &IndexLD{},
},
&AliasedDelegate{
Spec: "",
Alias: "",
Name: withoutPropertySpec,
Delegate: &withoutProperty{},
},
}
}
@ -149,3 +162,32 @@ func (i *IndexLD) Exit(key string, ctx *ParsingContext) (bool, error) {
func (i *IndexLD) Apply(key string, value interface{}, ctx *ParsingContext) (bool, error) {
return true, nil
}
var _ RDFNode = &withoutProperty{}
type withoutProperty struct{}
func (w *withoutProperty) Enter(key string, ctx *ParsingContext) (bool, error) {
ctx.Push()
ctx.Current = &VocabularyReference{}
return true, nil
}
func (w *withoutProperty) Exit(key string, ctx *ParsingContext) (bool, error) {
i := ctx.Current
ctx.Pop()
vr, ok := i.(*VocabularyReference)
if !ok {
return true, fmt.Errorf("hacky withoutProperty exit did not get *rdf.VocabularyReference")
}
vp, ok := ctx.Current.(*VocabularyProperty)
if !ok {
return true, fmt.Errorf("hacky withoutProperty exit Current is not *rdf.VocabularyProperty")
}
vp.DoesNotApplyTo = append(vp.DoesNotApplyTo, *vr)
return true, nil
}
func (w *withoutProperty) Apply(key string, value interface{}, ctx *ParsingContext) (bool, error) {
return true, fmt.Errorf("hacky withoutProperty cannot be applied")
}

ファイルの表示

@ -134,9 +134,92 @@ func ParseVocabulary(registry *RDFRegistry, input JSONLD) (vocabulary *ParsedVoc
// hijack processing.
nodes = append(jsonLDNodes(registry), nodes...)
err = apply(nodes, input, ctx)
if err != nil {
return
}
err = resolveReferences(registry, ctx)
return
}
// resolveReferences ensures that all references mentioned have been
// successfully parsed, and if not attempts to search the ontologies for any
// values, types, and properties that need to be referenced.
//
// Currently, this is the only way that values are added to the
// ParsedVocabulary.
func resolveReferences(registry *RDFRegistry, ctx *ParsingContext) error {
vocabulary := ctx.Result
for _, t := range vocabulary.Vocab.Types {
for _, ref := range t.DisjointWith {
if err := resolveReference(ref, registry, ctx); err != nil {
return err
}
}
for _, ref := range t.Extends {
if err := resolveReference(ref, registry, ctx); err != nil {
return err
}
}
}
for _, p := range vocabulary.Vocab.Properties {
for _, ref := range p.Domain {
if err := resolveReference(ref, registry, ctx); err != nil {
return err
}
}
for _, ref := range p.Range {
if err := resolveReference(ref, registry, ctx); err != nil {
return err
}
}
for _, ref := range p.DoesNotApplyTo {
if err := resolveReference(ref, registry, ctx); err != nil {
return err
}
}
if len(p.SubpropertyOf.Name) > 0 {
if err := resolveReference(p.SubpropertyOf, registry, ctx); err != nil {
return err
}
}
}
return nil
}
// resolveReference will attempt to resolve the reference by either finding it
// in the known References of the vocabulary, or load it from the registry. Will
// fail if a reference is not found.
func resolveReference(reference VocabularyReference, registry *RDFRegistry, ctx *ParsingContext) error {
fmt.Println(reference)
name := reference.Name
vocab := &ctx.Result.Vocab
if len(reference.Vocab) > 0 {
name = joinAlias(reference.Vocab, reference.Name)
url, e := registry.resolveAlias(reference.Vocab)
if e != nil {
return e
}
vocab = ctx.Result.GetReference(url)
}
if _, ok := vocab.Types[reference.Name]; ok {
return nil
} else if _, ok := vocab.Properties[reference.Name]; ok {
return nil
} else if _, ok := vocab.Values[reference.Name]; ok {
return nil
} else if n, e := registry.getNode(name); e != nil {
return e
} else {
applicable, e := n.Apply("", nil, ctx)
if !applicable {
return fmt.Errorf("cannot resolve reference with unapplicable node for %s", reference)
} else if e != nil {
return e
}
return nil
}
}
// apply takes a specification input to populate the ParsingContext, based on
// the capabilities of the RDFNodes created from ontologies.
func apply(nodes []RDFNode, input JSONLD, ctx *ParsingContext) error {
@ -148,7 +231,6 @@ func apply(nodes []RDFNode, input JSONLD, ctx *ParsingContext) error {
} else {
return err
}
return nil
}
// Special processing: '@type' or 'type' if they are present
if v, ok := input[JSON_LD_TYPE]; ok {

ファイルの表示

@ -41,6 +41,11 @@ func SplitAlias(s string) []string {
}
}
// joinAlias combines a string and prepends an RDF alias to it.
func joinAlias(alias, s string) string {
return fmt.Sprintf("%s%s%s", alias, ALIAS_DELIMITER, s)
}
// Ontology returns different RDF "actions" or "handlers" that are able to
// interpret the schema definitions as actions upon a set of data, specific
// for this ontology.
@ -255,3 +260,14 @@ func (r *RDFRegistry) getNode(s string) (n RDFNode, e error) {
return
}
}
// resolveAlias turns an alias into its full qualifier for the ontology.
//
// Package public.
func (r *RDFRegistry) resolveAlias(alias string) (url string, e error) {
var ok bool
if url, ok = r.aliases[alias]; !ok {
e = fmt.Errorf("registry cannot resolve alias %q", alias)
}
return
}

ファイルの表示

@ -3,25 +3,49 @@ package xsd
import (
"fmt"
"github.com/cjslep/activity/tools/exp/rdf"
"net/url"
"strings"
)
const (
xmlSpec = "http://www.w3.org/2001/XMLSchema#"
anyURISpec = "anyURI"
)
type XMLOntology struct{}
func (o *XMLOntology) SpecURI() string {
return "http://www.w3.org/2001/XMLSchema#"
return xmlSpec
}
func (o *XMLOntology) Load() ([]rdf.RDFNode, error) {
return nil, nil
return o.LoadAsAlias("")
}
func (o *XMLOntology) LoadAsAlias(s string) ([]rdf.RDFNode, error) {
return nil, nil
return []rdf.RDFNode{
&rdf.AliasedDelegate{
Spec: xmlSpec,
Alias: s,
Name: anyURISpec,
Delegate: &anyURI{},
},
}, nil
}
func (o *XMLOntology) LoadSpecificAsAlias(alias, name string) ([]rdf.RDFNode, error) {
return nil, nil
switch name {
case anyURISpec:
return []rdf.RDFNode{
&rdf.AliasedDelegate{
Spec: "",
Alias: "",
Name: alias,
Delegate: &anyURI{},
},
}, nil
}
return nil, fmt.Errorf("xml ontology cannot find %q to alias to %q", name, alias)
}
func (o *XMLOntology) LoadElement(name string, payload map[string]interface{}) ([]rdf.RDFNode, error) {
@ -31,7 +55,40 @@ func (o *XMLOntology) LoadElement(name string, payload map[string]interface{}) (
func (o *XMLOntology) GetByName(name string) (rdf.RDFNode, error) {
name = strings.TrimPrefix(name, o.SpecURI())
switch name {
// TODO
case anyURISpec:
return &anyURI{}, nil
}
return nil, fmt.Errorf("xsd ontology could not find node for name %s", name)
}
var _ rdf.RDFNode = &anyURI{}
type anyURI struct{}
func (a *anyURI) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd anyURI cannot be entered")
}
func (a *anyURI) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd anyURI cannot be exited")
}
func (a *anyURI) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
v := ctx.Result.GetReference(xmlSpec)
if len(v.Values[anyURISpec].Name) == 0 {
u, err := url.Parse(xmlSpec + anyURISpec)
if err != nil {
return true, err
}
val := &rdf.VocabularyValue{
Name: "anyURI",
URI: u,
DefinitionType: "*url.URL",
Zero: "&url.URL{}",
}
if err = v.SetValue(anyURISpec, val); err != nil {
return true, err
}
}
return true, nil
}