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
|
||||
}
|
||||
|
||||
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.
|
||||
type VocabularyType struct {
|
||||
Name string
|
||||
URI *url.URL
|
||||
Notes string
|
||||
DisjointWith []VocabularyReference
|
||||
Extends []VocabularyReference
|
||||
Extends []VocabularyReference // TODO: Object improperly extends Link
|
||||
Properties []VocabularyReference // TODO: Check for duplication
|
||||
WithoutProperties []VocabularyReference // TODO: Missing for IntransitiveActivity
|
||||
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
|
||||
// vocabulary.
|
||||
type VocabularyProperty struct {
|
||||
|
@ -59,6 +94,26 @@ type VocabularyProperty struct {
|
|||
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
|
||||
// in the vocabulary.
|
||||
type VocabularyExample struct {
|
||||
|
@ -67,6 +122,21 @@ type VocabularyExample struct {
|
|||
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
|
||||
// VocabularyType, VocabularyValue, or a VocabularyProperty. It may refer to
|
||||
// another Vocabulary's type or property entirely.
|
||||
|
@ -75,3 +145,18 @@ type VocabularyReference struct {
|
|||
URI *url.URL
|
||||
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
|
||||
// required for RDFNodes to be able to statefully apply changes.
|
||||
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
|
||||
// ontology (determined at creation time). It applies the value in its own
|
||||
// specific implementation on the context.
|
||||
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
|
||||
// specifies a Core, Extended, or Extension vocabulary.
|
||||
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
|
||||
}
|
||||
|
||||
// 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
|
||||
// algorithm in order to build a set of nodes which will be able to parse the
|
||||
// rest of the document.
|
||||
|
|
読み込み中…
新しいイシューから参照