package rdf import ( "bytes" "fmt" "github.com/dave/jennifer/jen" "github.com/go-fed/activity/astool/codegen" "net/url" ) // ParsedVocabulary is the internal data structure produced after parsing the // definition of an ActivityStream vocabulary. It is the intermediate // understanding of the specification in the context of certain ontologies. // // At the end of parsing, the ParsedVocabulary is not guaranteed to be // semantically valid, just that the parser resolved all important ontological // details. // // Note that the Order field contains the order in which parsed specs were // understood and resolved. Kinds added as references (such as XML, Schema.org, // or rdfs types) are not included in Order. It is expected that the last // element of Order must be the vocabulary in Vocab. type ParsedVocabulary struct { Vocab Vocabulary References map[string]*Vocabulary Order []string } // Size returns the number of types, properties, and values in the parsed // vocabulary. func (p ParsedVocabulary) Size() int { s := p.Vocab.Size() for _, v := range p.References { s += v.Size() } return s } // Clone creates a copy of this ParsedVocabulary. Note that the cloned // vocabulary does not copy References, so the original and clone both have // pointers to the same referenced vocabularies. func (p ParsedVocabulary) Clone() *ParsedVocabulary { clone := &ParsedVocabulary{ Vocab: p.Vocab, References: make(map[string]*Vocabulary, len(p.References)), Order: make([]string, len(p.Order)), } for k, v := range p.References { clone.References[k] = v } copy(clone.Order, p.Order) return clone } // GetReference looks up a reference based on its URI. func (p *ParsedVocabulary) GetReference(uri string) (*Vocabulary, error) { httpSpec, httpsSpec, err := ToHttpAndHttps(uri) if err != nil { return nil, err } if p.References == nil { p.References = make(map[string]*Vocabulary, 0) } if v, ok := p.References[httpSpec]; ok { return v, nil } else if v, ok := p.References[httpsSpec]; ok { return v, nil } else { p.References[uri] = &Vocabulary{} } return p.References[uri], nil } // String returns a printable version of this ParsedVocabulary for debugging. func (p ParsedVocabulary) String() string { var b bytes.Buffer b.WriteString(fmt.Sprintf("Vocab:\n%s", p.Vocab)) for k, v := range p.References { b.WriteString(fmt.Sprintf("Reference %s:\n\t%s\n", k, v)) } return b.String() } // Vocabulary contains the type, property, and value definitions for a single // ActivityStreams or extension vocabulary. type Vocabulary struct { Name string URI *url.URL Types map[string]VocabularyType Properties map[string]VocabularyProperty Values map[string]VocabularyValue Registry *RDFRegistry } // Size returns the number of types, properties, and values in this vocabulary. func (v Vocabulary) Size() int { return len(v.Types) + len(v.Properties) + len(v.Values) } // GetName returns the vocabulary's name. func (v Vocabulary) GetName() string { return v.Name } // SetName sets the vocabulary's name. func (v *Vocabulary) SetName(s string) { v.Name = s } // SetURI sets the value's URI. func (v *Vocabulary) SetURI(s string) error { var e error v.URI, e = url.Parse(s) return e } // String returns a printable version of this Vocabulary for debugging. func (v Vocabulary) String() string { var b bytes.Buffer b.WriteString(fmt.Sprintf("Vocabulary %q\n", v.Name)) for k, v := range v.Types { b.WriteString(fmt.Sprintf("Type %s:\n\t%s\n", k, v)) } for k, v := range v.Properties { b.WriteString(fmt.Sprintf("Property %s:\n\t%s\n", k, v)) } for k, v := range v.Values { b.WriteString(fmt.Sprintf("Value %s:\n\t%s\n", k, v)) } return b.String() } // SetType sets a type keyed by its name. Returns an error if a type is already // set for that name. func (v *Vocabulary) SetType(name string, a *VocabularyType) error { if v.Types == nil { v.Types = make(map[string]VocabularyType, 1) } if _, has := v.Types[name]; has { return fmt.Errorf("name %q already exists for vocabulary Types", name) } v.Types[name] = *a return nil } // SetProperty sets a property keyed by its name. Returns an error if a property // is already set for that name. func (v *Vocabulary) SetProperty(name string, a *VocabularyProperty) error { if v.Properties == nil { v.Properties = make(map[string]VocabularyProperty, 1) } if _, has := v.Properties[name]; has { return fmt.Errorf("name already exists for vocabulary Properties") } v.Properties[name] = *a return nil } // SetValue sets a value keyed by its name. Returns an error if the value is // already set for that name. func (v *Vocabulary) SetValue(name string, a *VocabularyValue) error { if v.Values == nil { v.Values = make(map[string]VocabularyValue, 1) } if _, has := v.Values[name]; has { return fmt.Errorf("name already exists for vocabulary Values") } v.Values[name] = *a return nil } var ( _ NameSetter = &Vocabulary{} _ NameGetter = &Vocabulary{} _ URISetter = &Vocabulary{} ) // VocabularyValue represents a value type that properties can take on. type VocabularyValue struct { Name string URI *url.URL DefinitionType *jen.Statement Zero string IsNilable bool IsURI bool SerializeFn *codegen.Function DeserializeFn *codegen.Function LessFn *codegen.Function } // String returns a printable version of this value for debugging. func (v VocabularyValue) String() string { return fmt.Sprintf("Value=%s,%s,%s,%s", v.Name, v.URI, v.DefinitionType, v.Zero) } // SetName sets the value's name. func (v *VocabularyValue) SetName(s string) { v.Name = s } // GetName returns the value's name. func (v VocabularyValue) GetName() string { return v.Name } // SetURI sets the value's URI. func (v *VocabularyValue) SetURI(s string) error { var e error v.URI, e = url.Parse(s) return e } var ( _ NameSetter = &VocabularyValue{} _ NameGetter = &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 Examples []VocabularyExample Properties []VocabularyReference WithoutProperties []VocabularyReference } // String returns a printable version of this type, for debugging. func (v VocabularyType) String() string { 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) } // SetName sets the name of this type. func (v *VocabularyType) SetName(s string) { v.Name = s } // SetName returns the name of this type. func (v VocabularyType) GetName() string { return v.Name } // TypeName returns the name of this type. // // Used to satisfy an interface. func (v VocabularyType) TypeName() string { return v.Name } // SetURI sets the URI of this type, returning an error if it cannot parse the // URI. func (v *VocabularyType) SetURI(s string) error { var e error v.URI, e = url.Parse(s) return e } // SetNotes sets the notes on this type. func (v *VocabularyType) SetNotes(s string) { v.Notes = s } // AddExample adds an example on this type. func (v *VocabularyType) AddExample(e *VocabularyExample) { v.Examples = append(v.Examples, *e) } var ( _ NameSetter = &VocabularyType{} _ NameGetter = &VocabularyType{} _ URISetter = &VocabularyType{} _ NotesSetter = &VocabularyType{} _ ExampleAdder = &VocabularyType{} ) // VocabularyProperty represents a single ActivityStream property type in a // vocabulary. type VocabularyProperty struct { 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 SubpropertyOf VocabularyReference // Must be a VocabularyProperty Functional bool NaturalLanguageMap bool } // String returns a printable version of this property for debugging. func (v VocabularyProperty) String() string { 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) } // SetName sets the name on this property. func (v *VocabularyProperty) SetName(s string) { v.Name = s } // GetName returns the name of this property. func (v VocabularyProperty) GetName() string { return v.Name } // PropertyName returns the name of this property. // // Used to satisfy an interface. func (v VocabularyProperty) PropertyName() string { return v.Name } // SetURI sets the URI for this property, returning an error if it cannot be // parsed. func (v *VocabularyProperty) SetURI(s string) error { var e error v.URI, e = url.Parse(s) return e } // SetNotes sets notes on this Property. func (v *VocabularyProperty) SetNotes(s string) { v.Notes = s } // AddExample adds an example for this property. func (v *VocabularyProperty) AddExample(e *VocabularyExample) { v.Examples = append(v.Examples, *e) } var ( _ NameSetter = &VocabularyProperty{} _ NameGetter = &VocabularyProperty{} _ URISetter = &VocabularyProperty{} _ NotesSetter = &VocabularyProperty{} _ ExampleAdder = &VocabularyProperty{} ) // VocabularyExample documents an Example for an ActivityStream type or property // in the vocabulary. type VocabularyExample struct { Name string URI *url.URL Example interface{} } // String returns a printable string used for debugging. func (v VocabularyExample) String() string { return fmt.Sprintf("VocabularyExample: %s,%s,%s", v.Name, v.URI, v.Example) } // SetName sets the name on this example. func (v *VocabularyExample) SetName(s string) { v.Name = s } // GetName returns the name of this example. func (v VocabularyExample) GetName() string { return v.Name } // SetURI sets the URI of this example, returning an error if it cannot be // parsed. func (v *VocabularyExample) SetURI(s string) error { var e error v.URI, e = url.Parse(s) return e } var ( _ NameSetter = &VocabularyExample{} _ NameGetter = &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. type VocabularyReference struct { Name string URI *url.URL Vocab string // If present, must match key in ParsedVocabulary.References } // String returns a printable string for this reference, used for debugging. func (v VocabularyReference) String() string { return fmt.Sprintf("VocabularyReference: %s,%s,%s", v.Name, v.URI, v.Vocab) } // SetName sets the name of this reference. func (v *VocabularyReference) SetName(s string) { v.Name = s } // GetName returns the name of this reference. func (v VocabularyReference) GetName() string { return v.Name } // SetURI sets the URI for this reference. Returns an error if the URI cannot // be parsed. func (v *VocabularyReference) SetURI(s string) error { var e error v.URI, e = url.Parse(s) return e } var ( _ NameSetter = &VocabularyReference{} _ NameGetter = &VocabularyReference{} _ URISetter = &VocabularyReference{} )