Setup applying RDF node understanding.
Next, the actual nodes need to be created in order to construct the proper intermediate form and translate the parsed data into a meaningful structure that can be used to generate code. Ideally, this could also potentially allow code generation in other languages too. And different ways to read in ActivityStreams specifications and extensions. But that would be way off in the future.
このコミットが含まれているのは:
コミット
94569ca549
|
@ -33,18 +33,53 @@ type VocabularyValue struct {
|
||||||
Zero string
|
Zero string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *VocabularyValue) SetName(s string) {
|
||||||
|
v.Name = s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *VocabularyValue) SetURI(s string) error {
|
||||||
|
var e error
|
||||||
|
v.URI, e = url.Parse(s)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ NameSetter = &VocabularyValue{}
|
||||||
|
_ URISetter = &VocabularyValue{}
|
||||||
|
)
|
||||||
|
|
||||||
// VocabularyType represents a single ActivityStream type in a vocabulary.
|
// VocabularyType represents a single ActivityStream type in a vocabulary.
|
||||||
type VocabularyType struct {
|
type VocabularyType struct {
|
||||||
Name string
|
Name string
|
||||||
URI *url.URL
|
URI *url.URL
|
||||||
Notes string
|
Notes string
|
||||||
DisjointWith []VocabularyReference
|
DisjointWith []VocabularyReference
|
||||||
Extends []VocabularyReference
|
Extends []VocabularyReference // TODO: Object improperly extends Link
|
||||||
Properties []VocabularyReference // TODO: Check for duplication
|
Properties []VocabularyReference // TODO: Check for duplication
|
||||||
WithoutProperties []VocabularyReference // TODO: Missing for IntransitiveActivity
|
WithoutProperties []VocabularyReference // TODO: Missing for IntransitiveActivity
|
||||||
Examples []VocabularyExample
|
Examples []VocabularyExample
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *VocabularyType) SetName(s string) {
|
||||||
|
v.Name = s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *VocabularyType) SetURI(s string) error {
|
||||||
|
var e error
|
||||||
|
v.URI, e = url.Parse(s)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *VocabularyType) SetNotes(s string) {
|
||||||
|
v.Notes = s
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ NameSetter = &VocabularyType{}
|
||||||
|
_ URISetter = &VocabularyType{}
|
||||||
|
_ NotesSetter = &VocabularyType{}
|
||||||
|
)
|
||||||
|
|
||||||
// VocabularyProperty represents a single ActivityStream property type in a
|
// VocabularyProperty represents a single ActivityStream property type in a
|
||||||
// vocabulary.
|
// vocabulary.
|
||||||
type VocabularyProperty struct {
|
type VocabularyProperty struct {
|
||||||
|
@ -59,6 +94,26 @@ type VocabularyProperty struct {
|
||||||
NaturalLanguageMap bool
|
NaturalLanguageMap bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *VocabularyProperty) SetName(s string) {
|
||||||
|
v.Name = s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *VocabularyProperty) SetURI(s string) error {
|
||||||
|
var e error
|
||||||
|
v.URI, e = url.Parse(s)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *VocabularyProperty) SetNotes(s string) {
|
||||||
|
v.Notes = s
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ NameSetter = &VocabularyProperty{}
|
||||||
|
_ URISetter = &VocabularyProperty{}
|
||||||
|
_ NotesSetter = &VocabularyProperty{}
|
||||||
|
)
|
||||||
|
|
||||||
// VocabularyExample documents an Example for an ActivityStream type or property
|
// VocabularyExample documents an Example for an ActivityStream type or property
|
||||||
// in the vocabulary.
|
// in the vocabulary.
|
||||||
type VocabularyExample struct {
|
type VocabularyExample struct {
|
||||||
|
@ -67,6 +122,21 @@ type VocabularyExample struct {
|
||||||
Example map[string]interface{}
|
Example map[string]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *VocabularyExample) SetName(s string) {
|
||||||
|
v.Name = s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *VocabularyExample) SetURI(s string) error {
|
||||||
|
var e error
|
||||||
|
v.URI, e = url.Parse(s)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ NameSetter = &VocabularyExample{}
|
||||||
|
_ URISetter = &VocabularyExample{}
|
||||||
|
)
|
||||||
|
|
||||||
// VocabularyReference refers to another Vocabulary reference, either a
|
// VocabularyReference refers to another Vocabulary reference, either a
|
||||||
// VocabularyType, VocabularyValue, or a VocabularyProperty. It may refer to
|
// VocabularyType, VocabularyValue, or a VocabularyProperty. It may refer to
|
||||||
// another Vocabulary's type or property entirely.
|
// another Vocabulary's type or property entirely.
|
||||||
|
@ -75,3 +145,18 @@ type VocabularyReference struct {
|
||||||
URI *url.URL
|
URI *url.URL
|
||||||
Vocab string // If present, must match key in ParsedVocabulary.References
|
Vocab string // If present, must match key in ParsedVocabulary.References
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *VocabularyReference) SetName(s string) {
|
||||||
|
v.Name = s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *VocabularyReference) SetURI(s string) error {
|
||||||
|
var e error
|
||||||
|
v.URI, e = url.Parse(s)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ NameSetter = &VocabularyReference{}
|
||||||
|
_ URISetter = &VocabularyReference{}
|
||||||
|
)
|
||||||
|
|
|
@ -15,23 +15,126 @@ type JSONLD map[string]interface{}
|
||||||
// ParsingContext contains the results of the parsing as well as scratch space
|
// ParsingContext contains the results of the parsing as well as scratch space
|
||||||
// required for RDFNodes to be able to statefully apply changes.
|
// required for RDFNodes to be able to statefully apply changes.
|
||||||
type ParsingContext struct {
|
type ParsingContext struct {
|
||||||
Result ParsedVocabulary
|
Result *ParsedVocabulary
|
||||||
|
Current interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type NameSetter interface {
|
||||||
|
SetName(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
type URISetter interface {
|
||||||
|
SetURI(string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type NotesSetter interface {
|
||||||
|
SetNotes(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RDFNode is able to operate on a specific key if it applies towards its
|
// RDFNode is able to operate on a specific key if it applies towards its
|
||||||
// ontology (determined at creation time). It applies the value in its own
|
// ontology (determined at creation time). It applies the value in its own
|
||||||
// specific implementation on the context.
|
// specific implementation on the context.
|
||||||
type RDFNode interface {
|
type RDFNode interface {
|
||||||
Apply(key string, value interface{}, ctx ParsedVocabulary) (bool, error)
|
Enter(key string, ctx *ParsingContext) (bool, error)
|
||||||
|
Exit(key string, ctx *ParsingContext) (bool, error)
|
||||||
|
Apply(key string, value interface{}, ctx *ParsingContext) (bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseVocabulary parses the specified input as an ActivityStreams context that
|
// ParseVocabulary parses the specified input as an ActivityStreams context that
|
||||||
// specifies a Core, Extended, or Extension vocabulary.
|
// specifies a Core, Extended, or Extension vocabulary.
|
||||||
func ParseVocabulary(registry *RDFRegistry, input JSONLD) (vocabulary *ParsedVocabulary, err error) {
|
func ParseVocabulary(registry *RDFRegistry, input JSONLD) (vocabulary *ParsedVocabulary, err error) {
|
||||||
_, err = parseJSONLDContext(registry, input)
|
var nodes []RDFNode
|
||||||
|
nodes, err = parseJSONLDContext(registry, input)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
vocabulary = &ParsedVocabulary{}
|
||||||
|
ctx := &ParsingContext{
|
||||||
|
Result: vocabulary,
|
||||||
|
}
|
||||||
|
err = apply(nodes, input, ctx)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
for k, v := range input {
|
||||||
|
// Skip the context as it has already been parsed to create the
|
||||||
|
// nodes.
|
||||||
|
if k == JSON_LD_CONTEXT {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if mapValue, ok := v.(map[string]interface{}); ok {
|
||||||
|
if err := enterFirstNode(nodes, k, ctx); err != nil {
|
||||||
|
return err
|
||||||
|
} else if err = apply(nodes, mapValue, ctx); err != nil {
|
||||||
|
return err
|
||||||
|
} else if err = exitFirstNode(nodes, k, ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if arrValue, ok := v.([]interface{}); ok {
|
||||||
|
for _, val := range arrValue {
|
||||||
|
// First, enter for this key
|
||||||
|
if err := enterFirstNode(nodes, k, ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Recur or handle the value as necessary.
|
||||||
|
if mapValue, ok := val.(map[string]interface{}); ok {
|
||||||
|
if err := apply(nodes, mapValue, ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if err := applyFirstNode(nodes, k, val, ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Finally, exit for this key
|
||||||
|
if err := exitFirstNode(nodes, k, ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if err := applyFirstNode(nodes, k, v, ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// enterFirstNode will Enter the first RDFNode that returns true or an error.
|
||||||
|
func enterFirstNode(nodes []RDFNode, key string, ctx *ParsingContext) error {
|
||||||
|
for _, node := range nodes {
|
||||||
|
if applied, err := node.Enter(key, ctx); applied {
|
||||||
|
return nil
|
||||||
|
} else if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// exitFirstNode will Exit the first RDFNode that returns true or an error.
|
||||||
|
func exitFirstNode(nodes []RDFNode, key string, ctx *ParsingContext) error {
|
||||||
|
for _, node := range nodes {
|
||||||
|
if applied, err := node.Exit(key, ctx); applied {
|
||||||
|
return nil
|
||||||
|
} else if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// applyFirstNode will Apply the first RDFNode that returns true or an error.
|
||||||
|
func applyFirstNode(nodes []RDFNode, key string, value interface{}, ctx *ParsingContext) error {
|
||||||
|
for _, node := range nodes {
|
||||||
|
if applied, err := node.Apply(key, value, ctx); applied {
|
||||||
|
return nil
|
||||||
|
} else if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// parseJSONLDContext implements a super basic JSON-LD @context parsing
|
// parseJSONLDContext implements a super basic JSON-LD @context parsing
|
||||||
// algorithm in order to build a set of nodes which will be able to parse the
|
// algorithm in order to build a set of nodes which will be able to parse the
|
||||||
// rest of the document.
|
// rest of the document.
|
||||||
|
|
読み込み中…
新しいイシューから参照