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?).
このコミットが含まれているのは:
コミット
139dc3c5ea
|
@ -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
|
||||
}
|
||||
|
|
読み込み中…
新しいイシューから参照