Remove ValueRoot and comment all direct code.

Still need to review the comments on all code-generated code.
This commit is contained in:
Cory Slep 2019-01-12 20:53:00 +01:00
parent 1f12842eeb
commit e6160858f0
16 changed files with 514 additions and 19 deletions

View file

@ -5,20 +5,26 @@ import (
"sort"
)
// sortedFunctionSignature sorts FunctionSignatures by name.
type sortedFunctionSignature []FunctionSignature
// Less compares Names.
func (s sortedFunctionSignature) Less(i, j int) bool {
return s[i].Name < s[j].Name
}
// Swap values.
func (s sortedFunctionSignature) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
// Len is the length of this slice.
func (s sortedFunctionSignature) Len() int {
return len(s)
}
// FunctionSignature is an interface's function definition without
// an implementation.
type FunctionSignature struct {
Name string
Params []jen.Code
@ -26,6 +32,7 @@ type FunctionSignature struct {
Comment string
}
// Interface manages and generates a Golang interface definition.
type Interface struct {
qual *jen.Statement
name string
@ -33,6 +40,7 @@ type Interface struct {
comment string
}
// NewInterface creates an Interface.
func NewInterface(pkg, name string,
funcs []FunctionSignature,
comment string) *Interface {
@ -46,6 +54,7 @@ func NewInterface(pkg, name string,
return i
}
// Definition produces the Golang code.
func (i Interface) Definition() jen.Code {
stmts := jen.Empty()
if len(i.comment) > 0 {

View file

@ -4,6 +4,7 @@ import (
"github.com/dave/jennifer/jen"
)
// memberType defines the way a method belongs to its struct.
type memberType int
const (
@ -11,7 +12,9 @@ const (
)
const (
// A method is by value.
valueMember memberType = iota
// A method is by pointer.
pointerMember
)

View file

@ -9,12 +9,17 @@ import (
"strings"
)
// File is a code-generated file.
type File struct {
F *jen.File
FileName string
// F is the code-generated contents of this file.
F *jen.File
// FileName is the name of this file to write.
FileName string
// Directory specifies the location to write this file.
Directory string
}
// vocabulary is a set of code generators for the vocabulary.
type vocabulary struct {
Values map[string]*gen.Kind
FProps map[string]*gen.FunctionalPropertyGenerator
@ -24,6 +29,7 @@ type vocabulary struct {
References map[string]*vocabulary
}
// newVocabulary creates a vocabulary with maps already made.
func newVocabulary() vocabulary {
return vocabulary{
Values: make(map[string]*gen.Kind, 0),
@ -34,6 +40,7 @@ func newVocabulary() vocabulary {
}
}
// typeArray converts Types to an array.
func (v vocabulary) typeArray() []*gen.TypeGenerator {
tg := make([]*gen.TypeGenerator, 0, len(v.Types))
for _, t := range v.Types {
@ -42,6 +49,7 @@ func (v vocabulary) typeArray() []*gen.TypeGenerator {
return tg
}
// propArray converts FProps and NFProps to a generic array.
func (v vocabulary) propArray() []*gen.PropertyGenerator {
fp := make([]*gen.PropertyGenerator, 0, len(v.FProps)+len(v.NFProps))
for _, f := range v.FProps {
@ -53,6 +61,7 @@ func (v vocabulary) propArray() []*gen.PropertyGenerator {
return fp
}
// funcPropArray converts only FProps to an array.
func (v vocabulary) funcPropArray() []*gen.FunctionalPropertyGenerator {
fp := make([]*gen.FunctionalPropertyGenerator, 0, len(v.FProps))
for _, f := range v.FProps {
@ -61,6 +70,7 @@ func (v vocabulary) funcPropArray() []*gen.FunctionalPropertyGenerator {
return fp
}
// nonFuncPropArray converts NFProps to an array.
func (v vocabulary) nonFuncPropArray() []*gen.NonFunctionalPropertyGenerator {
nfp := make([]*gen.NonFunctionalPropertyGenerator, 0, len(v.NFProps))
for _, nf := range v.NFProps {
@ -69,27 +79,59 @@ func (v vocabulary) nonFuncPropArray() []*gen.NonFunctionalPropertyGenerator {
return nfp
}
// PackagePolicy governs what file directory structure to generate files in.
// Only affects types and properties in a vocabulary. Does not affect values.
type PackagePolicy int
const (
// FlatUnderRoot puts all types and properties together for each
// vocabulary.
FlatUnderRoot PackagePolicy = iota
// IndividualUnderRoot puts each type and each property into their own
// package within each vocabulary.
IndividualUnderRoot
)
// Converter is responsible for taking the intermediate RDF understanding of one
// or more ActivityStreams-based specifications and converting it into a series
// of code-generated files.
//
// It supports generating code in two different styles, which greatly affects
// the package imports that application developers will use in their
// applications. While both are available, this results in code that may not be
// able to be built on some systems due to the compilation memory requirements.
// Therefore, final tooling is ecouraged to pick one and only one to use as
// there is no need for another dimension of code fragmentation. These styles
// are dicatated by the Converter's PackagePolicy.
//
// The generated code is separated into three locations: a "values" series of
// subdirectories, the subdirectories for the ActivityStream specification, and
// the "root" generated package.
//
// The "root" package is indended to be the sole package that all application
// developers use for non-interface types. It contains free-functions that aid
// in navigating the ActivityStreams hierarchy (such as extends and disjoints).
// It also contains a Resolver for deserialization or type dispatching.
//
// The specifications' generated code contains both interfaces and
// implementations. Developers' applications should only rely on the interfaces,
// which are used internally anyway.
type Converter struct {
Registry *rdf.RDFRegistry
GenRoot *gen.PackageManager
VocabularyName string
ValueRoot *gen.PackageManager
PackagePolicy PackagePolicy
}
// Convert turns a ParsedVocabulary into a set of code-generated files.
func (c Converter) Convert(p *rdf.ParsedVocabulary) (f []*File, e error) {
var v vocabulary
v, e = c.convertVocabulary(p)
if e != nil {
return
}
// Step 1: Convert the rdf.ParsedVocabulary into the internal set of
// code generators.
for k, refVocab := range p.References {
// Create a copy, but with the Reference moved to Vocab.
refP := p
@ -103,10 +145,14 @@ func (c Converter) Convert(p *rdf.ParsedVocabulary) (f []*File, e error) {
}
v.References[k] = &refV
}
// Step 2: Use the code generators to build the resulting code-generated
// files.
f, e = c.convertToFiles(v)
return
}
// convertToFiles takes the generators for a vocabulary and maps them into a
// file structure.
func (c Converter) convertToFiles(v vocabulary) (f []*File, e error) {
// Values -- include all referenced values too.
for _, v := range v.Values {
@ -288,6 +334,10 @@ func (c Converter) convertVocabulary(p *rdf.ParsedVocabulary) (v vocabulary, e e
return
}
// convertType turns the rdf.VocabularyType into a TypeGenerator.
//
// Precondition: The types it extends from and the properties it references are
// already converted into their applicable generators.
func (c Converter) convertType(t rdf.VocabularyType,
v rdf.Vocabulary,
existingFProps map[string]*gen.FunctionalPropertyGenerator,
@ -374,6 +424,8 @@ func (c Converter) convertType(t rdf.VocabularyType,
var rangeProps []gen.Property
for _, prop := range existingFProps {
for _, kind := range prop.GetKinds() {
// TODO: Rename "LowerName" since the type's name is
// actually title case.
if kind.Name.LowerName == name {
rangeProps = append(rangeProps, prop)
}
@ -399,6 +451,8 @@ func (c Converter) convertType(t rdf.VocabularyType,
return
}
// convertFunctionalProperty converts an rdf.VocabularyProperty that is
// functional (can only have one value) into a FunctionalPropertyGenerator.
func (c Converter) convertFunctionalProperty(p rdf.VocabularyProperty,
kinds map[string]*gen.Kind,
v rdf.Vocabulary,
@ -416,13 +470,16 @@ func (c Converter) convertFunctionalProperty(p rdf.VocabularyProperty,
fp = gen.NewFunctionalPropertyGenerator(
v.GetName(),
pm,
c.toIdentifier(p),
toIdentifier(p),
p.Notes,
k,
p.NaturalLanguageMap)
return
}
// convertNonFunctionalProperty converts an rdf.VocabularyProperty that is
// non-functional (can have multiple values) into a
// NonFunctionalPropertyGenerator.
func (c Converter) convertNonFunctionalProperty(p rdf.VocabularyProperty,
kinds map[string]*gen.Kind,
v rdf.Vocabulary,
@ -440,19 +497,24 @@ func (c Converter) convertNonFunctionalProperty(p rdf.VocabularyProperty,
nfp = gen.NewNonFunctionalPropertyGenerator(
v.GetName(),
pm,
c.toIdentifier(p),
toIdentifier(p),
p.Notes,
k,
p.NaturalLanguageMap)
return
}
// convertValue turns a rdf.VocabularyValue into a Kind.
//
// TODO: Turn this into a Kind constructor in gen?
func (c Converter) convertValue(v rdf.VocabularyValue) (k *gen.Kind) {
s := v.SerializeFn.CloneToPackage(c.vocabValuePackage(v).Path())
d := v.DeserializeFn.CloneToPackage(c.vocabValuePackage(v).Path())
l := v.LessFn.CloneToPackage(c.vocabValuePackage(v).Path())
k = &gen.Kind{
Name: c.toIdentifier(v),
// Name must use toIdentifier for vocabValuePackage and
// valuePackage to be the same.
Name: toIdentifier(v),
ConcreteKind: v.DefinitionType,
Nilable: v.IsNilable,
IsURI: v.IsURI,
@ -466,9 +528,14 @@ func (c Converter) convertValue(v rdf.VocabularyValue) (k *gen.Kind) {
return
}
// convertTypeToKind turns a rdf.VocabularyType into a Kind.
//
// TODO: Turn this into a Kind constructor in gen?
func (c Converter) convertTypeToKind(v rdf.VocabularyType) (k *gen.Kind, e error) {
k = &gen.Kind{
Name: c.toIdentifier(v),
// Name must use toIdentifier for vocabValuePackage and
// valuePackage to be the same.
Name: toIdentifier(v),
Nilable: true,
IsURI: false,
// Instead of populating:
@ -484,10 +551,14 @@ func (c Converter) convertTypeToKind(v rdf.VocabularyType) (k *gen.Kind, e error
return
}
// convertTypeToName makes a Titled version of the VocabularyType's name.
func (c Converter) convertTypeToName(v rdf.VocabularyType) string {
return strings.Title(v.Name)
}
// propertyKinds determines what Kind names are referenced by the
// rdf.VocabularyProperty, which may rely on the parsing registry for these
// particular files.
func (c Converter) propertyKinds(v rdf.VocabularyProperty,
kinds map[string]*gen.Kind,
vocab rdf.Vocabulary,
@ -544,22 +615,48 @@ func (c Converter) propertyKinds(v rdf.VocabularyProperty,
return
}
// getValueRoot returns the subdirectory that contains value types.
func (c Converter) getValueRoot() *gen.PackageManager {
return c.GenRoot.Sub("values")
}
// valuePackage returns the subpackage for a value Kind.
//
// It must match the result of vocabValuePackage. Therefore, convertTypeToKind
// and convertValue must also use toIdentifier.
func (c Converter) valuePackage(v *gen.Kind) gen.Package {
return c.ValueRoot.Sub(v.Name.LowerName).PublicPackage()
return c.getValueRoot().Sub(v.Name.LowerName).PublicPackage()
}
// vocabValuePackage returns the subpackage for a value Kind.
//
// It must match the result of valuePackage. Therefore, convertTypeToKind and
// convertValue must also use toIdentifier.
func (c Converter) vocabValuePackage(v rdf.VocabularyValue) gen.Package {
return c.ValueRoot.Sub(c.toIdentifier(v).LowerName).PublicPackage()
return c.getValueRoot().Sub(toIdentifier(v).LowerName).PublicPackage()
}
// typePackageManager returns a package manager for an individual type. It may
// be the same as other types depending on the code generation policy.
func (c Converter) typePackageManager(v typeNamer) (pkg *gen.PackageManager, e error) {
return c.packageManager("type_" + v.TypeName())
}
// propertyPackageManager returns a package manager for an individual property.
// It may be the same as other types depending on the code generation policy.
func (c Converter) propertyPackageManager(v propertyNamer) (pkg *gen.PackageManager, e error) {
return c.packageManager("property_" + v.PropertyName())
}
// packageManager applies the code generation package policy and returns a
// PackageManager applicable for that policy.
//
// The FlatUnderRoot policy puts all properties and types together in a single
// public and single private package.
//
// The IndividualUnderRoot policy puts each property and each type in their own
// package, and each of those packages has their own public and private
// subpackages.
func (c Converter) packageManager(s string) (pkg *gen.PackageManager, e error) {
s = strings.ToLower(s)
switch c.PackagePolicy {
@ -573,6 +670,8 @@ func (c Converter) packageManager(s string) (pkg *gen.PackageManager, e error) {
return
}
// rootFiles creates files that are applied for all vocabularies. These files
// are the ones typically used by developers.
func (c Converter) rootFiles(pkg gen.Package, vocabName string, v vocabulary) (f []*File, e error) {
pg := gen.NewPackageGenerator()
ctors, ext, disj, extBy, globalVar, initFn := pg.RootDefinitions(vocabName, v.Manager, v.typeArray(), v.propArray())
@ -590,6 +689,16 @@ func (c Converter) rootFiles(pkg gen.Package, vocabName string, v vocabulary) (f
return
}
// packageFiles generates package-level files necessary for types and properties
// within a single vocabulary.
//
// In the FlatUnderRoot policy, only one is needed in the public and private
// directories since all types and properties are co-located within the same
// package.
//
// In the IndividualUnderRoot policy, multiple are needed. Since each type and
// property are in their own package, one package file is needed in each of
// those types' and properties' subpackage.
func (c Converter) packageFiles(v vocabulary) (f []*File, e error) {
switch c.PackagePolicy {
case FlatUnderRoot:
@ -652,6 +761,8 @@ func (c Converter) packageFiles(v vocabulary) (f []*File, e error) {
return
}
// typePackageFile creates the package-level files necessary for a type if it
// is being generated in its own package.
func (c Converter) typePackageFiles(tg *gen.TypeGenerator) (f []*File, e error) {
// Only need one for all types.
tpg := gen.NewTypePackageGenerator()
@ -684,6 +795,8 @@ func (c Converter) typePackageFiles(tg *gen.TypeGenerator) (f []*File, e error)
return
}
// propertyPackageFiles creates the package-level files necessary for a property
// if it is being generated in its own package.
func (c Converter) propertyPackageFiles(pg *gen.PropertyGenerator) (f []*File, e error) {
// Only need one for all types.
ppg := gen.NewPropertyPackageGenerator()
@ -706,6 +819,7 @@ func (c Converter) propertyPackageFiles(pg *gen.PropertyGenerator) (f []*File, e
return
}
// typeNamer bridges rdf.VocabularyType and gen.TypeGenerator.
type typeNamer interface {
TypeName() string
}
@ -715,6 +829,8 @@ var (
_ typeNamer = &rdf.VocabularyType{}
)
// propertyNamer bridges rdf.VocabularyProperty to the gen side of functional
// and non-functional property generators.
type propertyNamer interface {
PropertyName() string
}
@ -725,13 +841,17 @@ var (
_ propertyNamer = &rdf.VocabularyProperty{}
)
func (c Converter) toIdentifier(n rdf.NameGetter) gen.Identifier {
// toIdentifier converts the name in the rdf package to a gen-compatible
// Identifier.
func toIdentifier(n rdf.NameGetter) gen.Identifier {
return gen.Identifier{
LowerName: n.GetName(),
CamelName: strings.Title(n.GetName()),
}
}
// allExtendsAreIn determines if a VocabularyType's parents are all already
// converted to a TypeGenerator.
func allExtendsAreIn(t rdf.VocabularyType, v map[string]*gen.TypeGenerator) bool {
for _, e := range t.Extends {
if len(e.Vocab) != 0 {
@ -744,6 +864,7 @@ func allExtendsAreIn(t rdf.VocabularyType, v map[string]*gen.TypeGenerator) bool
return true
}
// convertValue converts a Kind value into a code-generated File.
func convertValue(pkg gen.Package, v *gen.Kind) *File {
file := jen.NewFilePath(pkg.Path())
file.Add(
@ -759,6 +880,8 @@ func convertValue(pkg gen.Package, v *gen.Kind) *File {
}
}
// funcsToFile is a helper converting an array of Functions into a single File
// in the specified Package.
func funcsToFile(pkg gen.Package, fns []*codegen.Function, filename string) *File {
file := jen.NewFilePath(pkg.Path())
for _, fn := range fns {

View file

@ -16,6 +16,8 @@ type PackageManager struct {
private string
}
// NewPackageManager creates a package manager whose private implementation is
// in an "impl" subdirectory.
func NewPackageManager(prefix, root string) *PackageManager {
return &PackageManager{
prefix: prefix,
@ -56,6 +58,8 @@ func (p *PackageManager) SubPrivate(name string) *PackageManager {
}
}
// toPackage returns the public or private Package managed by this
// PackageManager.
func (p *PackageManager) toPackage(suffix string, public bool) Package {
path := p.root
if len(suffix) > 0 {
@ -72,6 +76,7 @@ func (p *PackageManager) toPackage(suffix string, public bool) Package {
}
}
// Package represents a Golang package.
type Package struct {
prefix string
path string
@ -80,22 +85,30 @@ type Package struct {
parent *PackageManager
}
// Path is the GOPATH or module path to this package.
func (p Package) Path() string {
return p.prefix + "/" + p.path
}
// WriteDir obtains the relative directory this package should be written to,
// which may not be the same as Path. The calling code may not be running at the
// root of GOPATH.
func (p Package) WriteDir() string {
return p.path
}
// Name returns the name of this package.
func (p Package) Name() string {
return p.name
}
// IsPublic returns whether this package is intended to house public files for
// application developer use.
func (p Package) IsPublic() bool {
return p.isPublic
}
// Parent returns the PackageManager managing this Package.
func (p Package) Parent() *PackageManager {
return p.parent
}

View file

@ -90,6 +90,8 @@ type Kind struct {
LessDef *codegen.Function
}
// lessFnCode creates the correct code calling this Kind's less function
// depending on whether the Kind is a value or a type.
func (k Kind) lessFnCode(this, other *jen.Statement) *jen.Statement {
// LessFn is nil case -- call comparison Less method directly on the LHS
lessCall := this.Clone().Dot(compareLessMethod).Call(other.Clone())
@ -103,6 +105,8 @@ func (k Kind) lessFnCode(this, other *jen.Statement) *jen.Statement {
return lessCall
}
// lessFnCode creates the correct code calling this Kind's deserialize function
// depending on whether the Kind is a value or a type.
func (k Kind) deserializeFnCode(this *jen.Statement) *jen.Statement {
if k.isValue() {
return k.DeserializeFn.Clone().Call(this)
@ -113,6 +117,7 @@ func (k Kind) deserializeFnCode(this *jen.Statement) *jen.Statement {
}
}
// isValue returns true if this Kind is a value, or false if it is a type.
func (k Kind) isValue() bool {
// LessFn is not nil, this means it is a value.
// If LessFn is nil, this means it is a type. Types will have their

View file

@ -241,7 +241,7 @@ func (t *TypeGenerator) Definition() *codegen.Struct {
ser := t.serializationMethod()
less := t.lessMethod()
get := t.getUnknownMethod()
deser := t.kindDeserializationFunc()
deser := t.deserializationFn()
extendsFn, extendsMethod := t.extendsDefinition()
getters := t.allGetters()
setters := t.allSetters()
@ -275,18 +275,23 @@ func (t *TypeGenerator) Definition() *codegen.Struct {
// sortedProperty is a slice of Properties that implements the Sort interface.
type sortedProperty []Property
// Less compares the property names.
func (s sortedProperty) Less(i, j int) bool {
return s[i].PropertyName() < s[j].PropertyName()
}
// Swap reorders two elements.
func (s sortedProperty) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
// Len returns the length of this slice of properties.
func (s sortedProperty) Len() int {
return len(s)
}
// allProperties returns all properties that this type contains, accounting for
// the extended types and without properties.
func (t *TypeGenerator) allProperties() []Property {
p := t.properties
// Properties of parents that are extended, minus DoesNotApplyTo
@ -315,10 +320,12 @@ func (t *TypeGenerator) allProperties() []Property {
return sortedP
}
// memberName returns the member name for this property.
func (*TypeGenerator) memberName(p Property) string {
return strings.Title(p.PropertyName())
}
// members returns all the properties this type has as its members.
func (t *TypeGenerator) members() (members []jen.Code) {
p := t.allProperties()
// Convert to jen.Code
@ -613,9 +620,9 @@ func (t *TypeGenerator) lessMethod() (less *codegen.Method) {
return
}
// kindDeserializationFunc returns free function reference that can be used to
// deserializationFn returns free function reference that can be used to
// treat a TypeGenerator as another property's Kind.
func (t *TypeGenerator) kindDeserializationFunc() (deser *codegen.Function) {
func (t *TypeGenerator) deserializationFn() (deser *codegen.Function) {
deserCode := jen.Commentf("Begin: Known property deserialization").Line()
for _, prop := range t.allProperties() {
deserMethod := t.m.getDeserializationMethodForProperty(prop)

View file

@ -82,7 +82,6 @@ func main() {
Registry: registry,
GenRoot: gen.NewPackageManager(*prefix, "gen"),
VocabularyName: *vocabName,
ValueRoot: gen.NewPackageManager(*prefix, "gen/vals"),
PackagePolicy: policy,
}
f, err := c.Convert(p)

View file

@ -21,6 +21,7 @@ type ParsedVocabulary struct {
References map[string]*Vocabulary
}
// GetReference looks up a reference based on its URI.
func (p *ParsedVocabulary) GetReference(uri string) *Vocabulary {
if p.References == nil {
p.References = make(map[string]*Vocabulary, 0)
@ -31,6 +32,7 @@ func (p *ParsedVocabulary) GetReference(uri string) *Vocabulary {
return p.References[uri]
}
// 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))
@ -49,10 +51,12 @@ type Vocabulary struct {
Values map[string]VocabularyValue
}
// GetName returns the vocabulary's name.
func (v Vocabulary) GetName() string {
return v.Name
}
// 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))
@ -68,6 +72,8 @@ func (v Vocabulary) String() string {
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)
@ -79,6 +85,8 @@ func (v *Vocabulary) SetType(name string, a *VocabularyType) error {
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)
@ -90,6 +98,8 @@ func (v *Vocabulary) SetProperty(name string, a *VocabularyProperty) error {
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)
@ -114,18 +124,22 @@ type VocabularyValue struct {
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)
@ -150,32 +164,42 @@ type VocabularyType struct {
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)
}
@ -204,32 +228,42 @@ type VocabularyProperty struct {
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)
}
@ -250,18 +284,23 @@ type VocabularyExample struct {
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)
@ -283,18 +322,23 @@ type VocabularyReference struct {
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)

View file

@ -73,16 +73,20 @@ func jsonLDNodes(r *RDFRegistry) []RDFNode {
var _ RDFNode = &idLD{}
// idLD is an RDFNode for the 'id' property.
type idLD struct{}
// Enter returns an error.
func (i *idLD) Enter(key string, ctx *ParsingContext) (bool, error) {
return true, fmt.Errorf("id cannot be entered")
}
// Exit returns an error.
func (i *idLD) Exit(key string, ctx *ParsingContext) (bool, error) {
return true, fmt.Errorf("id cannot be exited")
}
// Apply sets the URI for the context's Current item.
func (i *idLD) Apply(key string, value interface{}, ctx *ParsingContext) (bool, error) {
if ctx.Current == nil {
return true, nil
@ -97,18 +101,22 @@ func (i *idLD) Apply(key string, value interface{}, ctx *ParsingContext) (bool,
var _ RDFNode = &typeLD{}
// typeLD is an RDFNode for the 'type' property.
type typeLD struct {
r *RDFRegistry
}
// Enter does nothing.
func (t *typeLD) Enter(key string, ctx *ParsingContext) (bool, error) {
return true, nil
}
// Exit does nothing.
func (t *typeLD) Exit(key string, ctx *ParsingContext) (bool, error) {
return true, nil
}
// Apply attempts to get the RDFNode for the type and apply it.
func (t *typeLD) Apply(key string, value interface{}, ctx *ParsingContext) (bool, error) {
vs, ok := value.(string)
if !ok {
@ -123,10 +131,15 @@ func (t *typeLD) Apply(key string, value interface{}, ctx *ParsingContext) (bool
var _ RDFNode = &ContainerLD{}
// ContainerLD is an RDFNode that delegates to an RDFNode but only at this
// next level.
type ContainerLD struct {
ContainsNode RDFNode
}
// Enter sets OnlyApplyThisNodeNextLevel on the ParsingContext.
//
// Returns an error if this is the second time Enter is called in a row.
func (c *ContainerLD) Enter(key string, ctx *ParsingContext) (bool, error) {
if ctx.OnlyApplyThisNodeNextLevel != nil {
return true, fmt.Errorf("@container parsing context exit already has non-nil node")
@ -135,6 +148,9 @@ func (c *ContainerLD) Enter(key string, ctx *ParsingContext) (bool, error) {
return true, nil
}
// Exit clears OnlyApplyThisNodeNextLevel on the ParsingContext.
//
// Returns an error if this is the second time Exit is called in a row.
func (c *ContainerLD) Exit(key string, ctx *ParsingContext) (bool, error) {
if ctx.OnlyApplyThisNodeNextLevel == nil {
return true, fmt.Errorf("@container parsing context exit already has nil node")
@ -143,36 +159,50 @@ func (c *ContainerLD) Exit(key string, ctx *ParsingContext) (bool, error) {
return true, nil
}
// Apply does nothing.
func (c *ContainerLD) Apply(key string, value interface{}, ctx *ParsingContext) (bool, error) {
return true, nil
}
var _ RDFNode = &IndexLD{}
// IndexLD does nothing.
//
// It could try to manage human-defined indices, but the machine doesn't care.
type IndexLD struct{}
// Enter does nothing.
func (i *IndexLD) Enter(key string, ctx *ParsingContext) (bool, error) {
return true, nil
}
// Exit does nothing.
func (i *IndexLD) Exit(key string, ctx *ParsingContext) (bool, error) {
return true, nil
}
// Apply does nothing.
func (i *IndexLD) Apply(key string, value interface{}, ctx *ParsingContext) (bool, error) {
return true, nil
}
var _ RDFNode = &withoutProperty{}
// withoutProperty is a hacky-as-hell way to manage ActivityStream's concept of
// "WithoutProperty". It isn't a defined RDF relationship, so this is
// non-standard but required of the ActivityStreams Core or Extended Types spec.
type withoutProperty struct{}
// Enter pushes a VocabularyReference. It is expected further nodes will
// populate it with information before dxiting this node.
func (w *withoutProperty) Enter(key string, ctx *ParsingContext) (bool, error) {
ctx.Push()
ctx.Current = &VocabularyReference{}
return true, nil
}
// Exit pops a VocabularyReferences and sets DoesNotApplyTo on the parent
// VocabularyProperty on the stack.
func (w *withoutProperty) Exit(key string, ctx *ParsingContext) (bool, error) {
i := ctx.Current
ctx.Pop()
@ -188,6 +218,7 @@ func (w *withoutProperty) Exit(key string, ctx *ParsingContext) (bool, error) {
return true, nil
}
// Apply returns an error.
func (w *withoutProperty) Apply(key string, value interface{}, ctx *ParsingContext) (bool, error) {
return true, fmt.Errorf("hacky withoutProperty cannot be applied")
}

View file

@ -14,6 +14,7 @@ const (
propertySpec = "Property"
)
// SerializeValueFunction is a helper for creating a value's Serialize function.
func SerializeValueFunction(pkg, valueName string,
concreteType jen.Code,
impl []jen.Code) *codegen.Function {
@ -27,6 +28,8 @@ func SerializeValueFunction(pkg, valueName string,
fmt.Sprintf("%s converts a %s value to an interface representation suitable for marshalling into a text or binary format.", name, valueName))
}
// DeserializeValueFunction is a helper for creating a value's Deserialize
// function.
func DeserializeValueFunction(pkg, valueName string,
concreteType jen.Code,
impl []jen.Code) *codegen.Function {
@ -40,6 +43,7 @@ func DeserializeValueFunction(pkg, valueName string,
fmt.Sprintf("%s creates %s value from an interface representation that has been unmarshalled from a text or binary format.", name, valueName))
}
// LessFunction is a helper for creating a value's Less function.
func LessFunction(pkg, valueName string,
concreteType jen.Code,
impl []jen.Code) *codegen.Function {
@ -53,19 +57,25 @@ func LessFunction(pkg, valueName string,
fmt.Sprintf("%s returns true if the left %s value is less than the right value.", name, valueName))
}
var _ Ontology = &RDFOntology{}
// RDFOntology is an Ontology for the RDF namespace.
type RDFOntology struct {
Package string
alias string
}
// SpecURI returns the RDF URI spec.
func (o *RDFOntology) SpecURI() string {
return rdfSpec
}
// Load loads the ontology with no alias set.
func (o *RDFOntology) Load() ([]RDFNode, error) {
return o.LoadAsAlias("")
}
// LoadAsAlias loads the ontology with an alias.
func (o *RDFOntology) LoadAsAlias(s string) ([]RDFNode, error) {
o.alias = s
return []RDFNode{
@ -84,6 +94,7 @@ func (o *RDFOntology) LoadAsAlias(s string) ([]RDFNode, error) {
}, nil
}
// LoadSpecificAsAlias loads a specific RDFNode with the given alias.
func (o *RDFOntology) LoadSpecificAsAlias(alias, name string) ([]RDFNode, error) {
switch name {
case langstringSpec:
@ -108,10 +119,12 @@ func (o *RDFOntology) LoadSpecificAsAlias(alias, name string) ([]RDFNode, error)
return nil, fmt.Errorf("rdf ontology cannot find %q to make alias %q", name, alias)
}
// LoadElement does nothing.
func (o *RDFOntology) LoadElement(name string, payload map[string]interface{}) ([]RDFNode, error) {
return nil, nil
}
// GetByName returns a raw, unguarded node by name.
func (o *RDFOntology) GetByName(name string) (RDFNode, error) {
name = strings.TrimPrefix(name, o.SpecURI())
switch name {
@ -125,19 +138,23 @@ func (o *RDFOntology) GetByName(name string) (RDFNode, error) {
var _ RDFNode = &langstring{}
// langstring is an RDF node representing the langstring value.
type langstring struct {
alias string
pkg string
}
// Enter returns an error.
func (l *langstring) Enter(key string, ctx *ParsingContext) (bool, error) {
return true, fmt.Errorf("rdf langstring cannot be entered")
}
// Exit returns an error.
func (l *langstring) Exit(key string, ctx *ParsingContext) (bool, error) {
return true, fmt.Errorf("rdf langstring cannot be exited")
}
// Apply sets the langstring value in the context as a referenced spec.
func (l *langstring) Apply(key string, value interface{}, ctx *ParsingContext) (bool, error) {
for k, p := range ctx.Result.Vocab.Properties {
for _, ref := range p.Range {
@ -289,16 +306,22 @@ func (l *langstring) Apply(key string, value interface{}, ctx *ParsingContext) (
var _ RDFNode = &property{}
// property is an RDFNode that sets a VocabularyProperty as the current.
type property struct{}
// Enter returns an error.
func (p *property) Enter(key string, ctx *ParsingContext) (bool, error) {
return true, fmt.Errorf("rdf property cannot be entered")
}
// Exit returns an error.
func (p *property) Exit(key string, ctx *ParsingContext) (bool, error) {
return true, fmt.Errorf("rdf property cannot be exited")
}
// Apply sets the current context to be a VocabularyProperty, if it is not
// already. If the context isn't reset, an error is returned due to another node
// not having cleaned up properly.
func (p *property) Apply(key string, value interface{}, ctx *ParsingContext) (bool, error) {
// Prepare a new VocabularyProperty in the context. If one already
// exists, skip.

View file

@ -18,18 +18,22 @@ const (
functionalPropertySpec = "FunctionalProperty"
)
// OWLOntology is an Ontology for OWL2.
type OWLOntology struct {
alias string
}
// SpecURI returns the URI of the OWL specification.
func (o *OWLOntology) SpecURI() string {
return owlSpec
}
// Load this ontology without an alias.
func (o *OWLOntology) Load() ([]rdf.RDFNode, error) {
return o.LoadAsAlias("")
}
// LoadAsAlias loads the ontology with the alias.
func (o *OWLOntology) LoadAsAlias(s string) ([]rdf.RDFNode, error) {
o.alias = s
return []rdf.RDFNode{
@ -84,6 +88,7 @@ func (o *OWLOntology) LoadAsAlias(s string) ([]rdf.RDFNode, error) {
}, nil
}
// LoadSpecificAsAlias loads a specific ontology definition as an alias.
func (o *OWLOntology) LoadSpecificAsAlias(alias, name string) ([]rdf.RDFNode, error) {
switch name {
case membersSpec:
@ -162,6 +167,8 @@ func (o *OWLOntology) LoadSpecificAsAlias(alias, name string) ([]rdf.RDFNode, er
return nil, fmt.Errorf("owl ontology cannot find %q to alias to %q", name, alias)
}
// LoadElement allows loading nodes to enable contexts containing a container
// with an index.
func (o *OWLOntology) LoadElement(name string, payload map[string]interface{}) ([]rdf.RDFNode, error) {
// First, detect if an idValue exists
var idValue interface{}
@ -213,6 +220,7 @@ func (o *OWLOntology) LoadElement(name string, payload map[string]interface{}) (
return []rdf.RDFNode{node}, nil
}
// GetByName returns a bare node.
func (o *OWLOntology) GetByName(name string) (rdf.RDFNode, error) {
name = strings.TrimPrefix(name, o.SpecURI())
switch name {
@ -238,8 +246,10 @@ func (o *OWLOntology) GetByName(name string) (rdf.RDFNode, error) {
var _ rdf.RDFNode = &members{}
// members represents owl:members.
type members struct{}
// Enter does nothing but returns an error if the context is not reset.
func (m *members) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
if !ctx.IsReset() {
return true, fmt.Errorf("owl members entered without reset context")
@ -247,6 +257,7 @@ func (m *members) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, nil
}
// Exit adds a Vocabulary Type, Property or Value to Result.
func (m *members) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
// Finish adding the Current item to the resulting vocabulary
if ctx.Current == nil {
@ -272,14 +283,17 @@ func (m *members) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, nil
}
// Apply returns an error.
func (m *members) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("owl members cannot be applied")
}
var _ rdf.RDFNode = &disjointWith{}
// disjointWith represents owl:disjointWith.
type disjointWith struct{}
// Enter ensures the Current is a Type, then pushes a Reference.
func (d *disjointWith) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
// Push the Current type aside, to build a Reference.
if ctx.Current == nil {
@ -292,6 +306,7 @@ func (d *disjointWith) Enter(key string, ctx *rdf.ParsingContext) (bool, error)
return true, nil
}
// Exit pops the Reference and adds it to the Type's DisjointWith.
func (d *disjointWith) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
// Pop the Reference, put into the type.
ref, ok := ctx.Current.(*rdf.VocabularyReference)
@ -307,16 +322,19 @@ func (d *disjointWith) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, nil
}
// Apply returns an error.
func (d *disjointWith) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("owl disjointWith cannot be applied")
}
var _ rdf.RDFNode = &unionOf{}
// unionOf represents owl:unionOf.
type unionOf struct {
entered bool
}
// Enter pushes a single Reference.
func (u *unionOf) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
u.entered = true
ctx.Push()
@ -324,6 +342,8 @@ func (u *unionOf) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, nil
}
// Exit pops a Reference and appends it to Current, which is a slice of
// References.
func (u *unionOf) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
u.entered = false
if ctx.Current == nil {
@ -343,6 +363,9 @@ func (u *unionOf) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, nil
}
// Apply will either apply a value onto a current Reference (if it was entered
// due to being a JSON array), or will append a new reference to Current (which
// is a slice of references).
func (u *unionOf) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
s, ok := value.(string)
if !ok {
@ -377,49 +400,65 @@ func (u *unionOf) Apply(key string, value interface{}, ctx *rdf.ParsingContext)
var _ rdf.RDFNode = &imports{}
// imports does nothing but returns errors. It should instead be handled by
// special cases in an Ontology's LoadElement.
//
// Overall, this is a pain to implement. If these errors are seen, then I am
// about to have a really not-fun day.
type imports struct{}
// Enter returns an error.
func (i *imports) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("owl imports cannot be entered")
}
// Exit returns an error.
func (i *imports) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("owl imports cannot be entered")
}
// Apply returns an error.
func (i *imports) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("owl imports cannot be entered")
}
var _ rdf.RDFNode = &ontology{}
// ontology does nothing.
type ontology struct{}
// Enter returns an error.
func (o *ontology) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("owl ontology cannot be entered")
}
// Exit returns an error.
func (o *ontology) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("owl ontology cannot be exited")
}
// Apply does nothing.
func (o *ontology) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
// Do nothing
return true, nil
}
var _ rdf.RDFNode = &class{}
// class prepares a new Type on Current, unless Reference has already been
// prepared.
type class struct{}
// Enter returns an error.
func (c *class) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("owl class cannot be entered")
}
// Exit returns an error.
func (c *class) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("owl class cannot be exited")
}
// Apply sets a Type on Current, unless a Reference is already set.
func (c *class) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
// Prepare a new VocabularyType in the context, unless it is a
// reference already prepared.
@ -437,16 +476,20 @@ func (c *class) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (b
var _ rdf.RDFNode = &objectProperty{}
// objectProperty is owl:objectProperty
type objectProperty struct{}
// Enter returns an error.
func (o *objectProperty) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("owl objectProperty cannot be entered")
}
// Exit returns an error.
func (o *objectProperty) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("owl objectProperty cannot be exited")
}
// Apply sets Current to be a Property, unless it is already a Property.
func (o *objectProperty) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
// Prepare a new VocabularyProperty in the context. If one already
// exists, skip.
@ -461,16 +504,22 @@ func (o *objectProperty) Apply(key string, value interface{}, ctx *rdf.ParsingCo
var _ rdf.RDFNode = &functionalProperty{}
// functionalProperty represents owl:functionalProperty
type functionalProperty struct{}
// Enter returns an error.
func (f *functionalProperty) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("owl functionalProperty cannot be entered")
}
// Exit returns an error.
func (f *functionalProperty) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("owl functionalProperty cannot be exited")
}
// Apply sets the Current Property's Functional to true.
//
// Returns an error if Current is not a Property.
func (f *functionalProperty) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
if ctx.Current == nil {
return true, fmt.Errorf("owl functionalProperty given nil Current in context")

View file

@ -17,15 +17,26 @@ 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 contains the final ParsedVocabulary from a file.
Result *ParsedVocabulary
// Current item to operate upon. A call to Push or Pop will overwrite
// this field.
Current interface{}
Name string
Stack []interface{}
// Name of the Current item. A call to Push or Pop will modify this
// field.
Name string
// The Stack of Types, Properties, References, Examples, and other
// items being analyzed. A call to Push or Pop will modify this field.
//
// Do not use directly, instead use Push and Pop.
Stack []interface{}
// Applies the node only for the next level of processing.
//
// Do not touch, instead use the accessor methods.
OnlyApplyThisNodeNextLevel RDFNode
OnlyApplied bool
// OnlyApplied keeps track if OnlyApplyThisNodeNextLevel has applied
// once.
OnlyApplied bool
// Applies the node once, for the rest of the data. This skips the
// recursive parsing, and the node's Apply is given an empty string
// for a key.
@ -34,19 +45,30 @@ type ParsingContext struct {
OnlyApplyThisNode RDFNode
}
// SetOnlyApplyThisNode sets the provided node to be the only one applied until
// ResetOnlyApplyThisNode is called.
func (p *ParsingContext) SetOnlyApplyThisNode(n RDFNode) {
p.OnlyApplyThisNode = n
}
// ResetOnlyApplyThisNode clears the only node to apply, if set.
func (p *ParsingContext) ResetOnlyApplyThisNode() {
p.OnlyApplyThisNode = nil
}
// SetOnlyApplyThisNodeNExtLevel will apply the next node only for the next
// level.
func (p *ParsingContext) SetOnlyApplyThisNodeNextLevel(n RDFNode) {
p.OnlyApplyThisNodeNextLevel = n
p.OnlyApplied = false
}
// GetNextNodes is given the list of nodes a parent process believes should be
// applied, and returns the list of nodes that actually should be used.
//
// If there is node that should only apply or should only apply at the next
// level (and hasn't yet), then the passed in list will not match the resulting
// list.
func (p *ParsingContext) GetNextNodes(n []RDFNode) (r []RDFNode, clearFn func()) {
if p.OnlyApplyThisNodeNextLevel == nil {
return n, func() {}
@ -60,16 +82,21 @@ func (p *ParsingContext) GetNextNodes(n []RDFNode) (r []RDFNode, clearFn func())
}
}
// ResetOnlyAppliedThisNodeNextLevel clears the node that should have been
// applied for the next level of depth only.
func (p *ParsingContext) ResetOnlyAppliedThisNodeNextLevel() {
p.OnlyApplyThisNodeNextLevel = nil
p.OnlyApplied = false
}
// Push puts the Current onto the Stack.
func (p *ParsingContext) Push() {
p.Stack = append([]interface{}{p.Current}, p.Stack...)
p.Current = nil
}
// Pop puts the top item on the Stack into Current, and sets Name as
// appropriate.
func (p *ParsingContext) Pop() {
p.Current = p.Stack[0]
p.Stack = p.Stack[1:]
@ -78,32 +105,39 @@ func (p *ParsingContext) Pop() {
}
}
// IsReset determines if the Context's Current is nil and Name is empty. Note
func (p *ParsingContext) IsReset() bool {
return p.Current == nil &&
p.Name == ""
}
// Reset sets Current to nil and Name to empty string.
func (p *ParsingContext) Reset() {
p.Current = nil
p.Name = ""
}
// NameSetter is a utility interface for the rdf Vocabulary types.
type NameSetter interface {
SetName(string)
}
// NameGetter is a utility interface for the rdf Vocabulary types.
type NameGetter interface {
GetName() string
}
// URISetter is a utility interface for the rdf Vocabulary types.
type URISetter interface {
SetURI(string) error
}
// NotesSetter is a utility interface for the rdf Vocabulary types.
type NotesSetter interface {
SetNotes(string)
}
// ExampleAdder is a utility interface for the rdf Vocabulary types.
type ExampleAdder interface {
AddExample(*VocabularyExample)
}
@ -112,8 +146,13 @@ type ExampleAdder interface {
// ontology (determined at creation time). It applies the value in its own
// specific implementation on the context.
type RDFNode interface {
// Enter is called when the RDFNode is a label for an array of values or
// a key within a JSON object, and the parser is about to examine its
// value(s). Exit is guaranteed to be called afterwards.
Enter(key string, ctx *ParsingContext) (bool, error)
// Exit is called after the parser examines the node's value(s).
Exit(key string, ctx *ParsingContext) (bool, error)
// Apply is called by the parser on nodes when they appear as values.
Apply(key string, value interface{}, ctx *ParsingContext) (bool, error)
}

View file

@ -16,16 +16,20 @@ const (
subPropertyOfSpec = "subPropertyOf"
)
// RDFSchemaOntology is the Ontology for rdfs.
type RDFSchemaOntology struct{}
// SpecURI returns the URI for the RDFS spec.
func (o *RDFSchemaOntology) SpecURI() string {
return rdfsSpecURI
}
// Load this Ontology without an alias.
func (o *RDFSchemaOntology) Load() ([]rdf.RDFNode, error) {
return o.LoadAsAlias("")
}
// LoadAsAlias loads this ontology with an alias.
func (o *RDFSchemaOntology) LoadAsAlias(s string) ([]rdf.RDFNode, error) {
return []rdf.RDFNode{
&rdf.AliasedDelegate{
@ -67,6 +71,7 @@ func (o *RDFSchemaOntology) LoadAsAlias(s string) ([]rdf.RDFNode, error) {
}, nil
}
// LoadSpecificAsAlias loads a specific node as an alias.
func (o *RDFSchemaOntology) LoadSpecificAsAlias(alias, name string) ([]rdf.RDFNode, error) {
switch name {
case commentSpec:
@ -127,10 +132,12 @@ func (o *RDFSchemaOntology) LoadSpecificAsAlias(alias, name string) ([]rdf.RDFNo
return nil, fmt.Errorf("rdfs ontology cannot find %q to alias to %q", name, alias)
}
// LoadElement does nothing.
func (o *RDFSchemaOntology) LoadElement(name string, payload map[string]interface{}) ([]rdf.RDFNode, error) {
return nil, nil
}
// GetByName returns a bare node by name.
func (o *RDFSchemaOntology) GetByName(name string) (rdf.RDFNode, error) {
name = strings.TrimPrefix(name, o.SpecURI())
switch name {
@ -152,16 +159,22 @@ func (o *RDFSchemaOntology) GetByName(name string) (rdf.RDFNode, error) {
var _ rdf.RDFNode = &comment{}
// comment sets Notes on vocabulary items.
type comment struct{}
// Enter returns an error.
func (n *comment) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("rdfs comment cannot be entered")
}
// Exit returns an error.
func (n *comment) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("rdfs comment cannot be exited")
}
// Apply sets the string value on Current's Notes.
//
// Returns an error if value isn't a string or Current can't set Notes.
func (n *comment) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
note, ok := value.(string)
if !ok {
@ -180,14 +193,20 @@ func (n *comment) Apply(key string, value interface{}, ctx *rdf.ParsingContext)
var _ rdf.RDFNode = &domain{}
// domain is rdfs:domain.
type domain struct{}
// Enter Pushes a Reference as Current.
func (d *domain) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
ctx.Push()
ctx.Current = make([]rdf.VocabularyReference, 0)
return true, nil
}
// Exit Pops a slice of References and sets it on the parent Property.
//
// Returns an error if the popped item is not a slice of References, or if the
// Current after Popping is not a Property.
func (d *domain) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
i := ctx.Current
ctx.Pop()
@ -203,22 +222,30 @@ func (d *domain) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, nil
}
// Apply returns an error.
func (d *domain) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("rdfs domain cannot be applied")
}
var _ rdf.RDFNode = &isDefinedBy{}
// isDefinedBy is rdfs:isDefinedBy.
type isDefinedBy struct{}
// Enter returns an error.
func (i *isDefinedBy) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("rdfs isDefinedBy cannot be entered")
}
// Exit returns an error.
func (i *isDefinedBy) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("rdfs isDefinedBy cannot be exited")
}
// Apply sets the string value as Current's URI.
//
// Returns an error if value is not a string or if Current cannot have a URI
// set.
func (i *isDefinedBy) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
s, ok := value.(string)
if !ok {
@ -233,14 +260,20 @@ func (i *isDefinedBy) Apply(key string, value interface{}, ctx *rdf.ParsingConte
var _ rdf.RDFNode = &ranges{}
// ranges is rdfs:ranges.
type ranges struct{}
// Enter Pushes as a slice of References as Current.
func (r *ranges) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
ctx.Push()
ctx.Current = make([]rdf.VocabularyReference, 0)
return true, nil
}
// Exit Pops a slice of References and sets it on the parent Property.
//
// Returns an error if the popped item is not a slice of references, or if the
// Current item after popping is not a Property.
func (r *ranges) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
i := ctx.Current
ctx.Pop()
@ -256,20 +289,27 @@ func (r *ranges) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, nil
}
// Apply returns an error.
func (r *ranges) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("rdfs ranges cannot be applied")
}
var _ rdf.RDFNode = &subClassOf{}
// subClassOf implements rdfs:subClassOf.
type subClassOf struct{}
// Enter Pushes a Reference as Current.
func (s *subClassOf) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
ctx.Push()
ctx.Current = &rdf.VocabularyReference{}
return true, nil
}
// Exit Pops a Reference and appends it to the parent Type's Extends.
//
// Returns an error if the popped item is not a reference, or if the Current
// item after popping is not a Type.
func (s *subClassOf) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
i := ctx.Current
ctx.Pop()
@ -285,20 +325,27 @@ func (s *subClassOf) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, nil
}
// Apply returns an error.
func (s *subClassOf) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("rdfs subclassof cannot be applied")
}
var _ rdf.RDFNode = &subPropertyOf{}
// subPropertyOf is rdfs:subPropertyOf
type subPropertyOf struct{}
// Enter Pushes a Reference as Current.
func (s *subPropertyOf) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
ctx.Push()
ctx.Current = &rdf.VocabularyReference{}
return true, nil
}
// Exit Pops a Reference and sets it as the parent property's SubpropertyOf.
//
// Returns an error if the popped item is not a Reference, or if after popping
// Current is not a Property.
func (s *subPropertyOf) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
i := ctx.Current
ctx.Pop()
@ -314,6 +361,7 @@ func (s *subPropertyOf) Exit(key string, ctx *rdf.ParsingContext) (bool, error)
return true, nil
}
// Apply returns an error.
func (s *subPropertyOf) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("rdfs subpropertyof cannot be applied")
}

View file

@ -18,18 +18,23 @@ const (
relSpec = "rfc5988"
)
// RFCOntology represents standards and values that originate from RFC
// specifications.
type RFCOntology struct {
Package string
}
// SpecURI returns the RFC specifications URI.
func (o *RFCOntology) SpecURI() string {
return rfcSpec
}
// Load without an alias.
func (o *RFCOntology) Load() ([]rdf.RDFNode, error) {
return o.LoadAsAlias("")
}
// LoadAsAlias loads with the given alias.
func (o *RFCOntology) LoadAsAlias(s string) ([]rdf.RDFNode, error) {
return []rdf.RDFNode{
&rdf.AliasedDelegate{
@ -53,6 +58,7 @@ func (o *RFCOntology) LoadAsAlias(s string) ([]rdf.RDFNode, error) {
}, nil
}
// LoadSpecificAsAlias loads a specific item with a given alias.
func (o *RFCOntology) LoadSpecificAsAlias(alias, name string) ([]rdf.RDFNode, error) {
switch name {
case bcp47Spec:
@ -86,10 +92,12 @@ func (o *RFCOntology) LoadSpecificAsAlias(alias, name string) ([]rdf.RDFNode, er
return nil, fmt.Errorf("rfc ontology cannot find %q to alias to %q", name, alias)
}
// LoadElement does nothing.
func (o *RFCOntology) LoadElement(name string, payload map[string]interface{}) ([]rdf.RDFNode, error) {
return nil, nil
}
// GetByName obtains a bare node by name.
func (o *RFCOntology) GetByName(name string) (rdf.RDFNode, error) {
name = strings.TrimPrefix(name, o.SpecURI())
switch name {
@ -105,18 +113,24 @@ func (o *RFCOntology) GetByName(name string) (rdf.RDFNode, error) {
var _ rdf.RDFNode = &bcp47{}
// BCP47 represents a BCP47 value.
//
// No validation is done on deserialized values.
type bcp47 struct {
pkg string
}
// Enter does nothing.
func (b *bcp47) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("bcp47 langaugetag cannot be entered")
}
// Exit does nothing.
func (b *bcp47) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("bcp47 languagetag cannot be exited")
}
// Apply adds BCP47 as a value Kind.
func (b *bcp47) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
v := ctx.Result.GetReference(rfcSpec)
if len(v.Values[bcp47Spec].Name) == 0 {
@ -185,18 +199,22 @@ func (b *bcp47) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (b
var _ rdf.RDFNode = &mime{}
// mime represents MIME values.
type mime struct {
pkg string
}
// Enter does nothing.
func (*mime) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("MIME media type cannot be entered")
}
// Exit does nothing.
func (*mime) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("MIME media type cannot be exited")
}
// Apply adds MIME as a value Kind.
func (m *mime) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
v := ctx.Result.GetReference(rfcSpec)
if len(v.Values[mimeSpec].Name) == 0 {
@ -265,18 +283,22 @@ func (m *mime) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bo
var _ rdf.RDFNode = &rel{}
// rel is a Link Relation.
type rel struct {
pkg string
}
// Enter does nothing.
func (*rel) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("rel cannot be entered")
}
// Exit does nothing.
func (*rel) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("rel cannot be exited")
}
// Apply adds rel as a supported value Kind.
func (r *rel) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
v := ctx.Result.GetReference(rfcSpec)
if len(v.Values[relSpec].Name) == 0 {

View file

@ -15,16 +15,20 @@ const (
creativeWorkSpec = "CreativeWork"
)
// SchemaOntology represents Ontologies from schema.org.
type SchemaOntology struct{}
// SpecURI returns the Schema.org URI.
func (o *SchemaOntology) SpecURI() string {
return schemaSpec
}
// Load without an alias.
func (o *SchemaOntology) Load() ([]rdf.RDFNode, error) {
return o.LoadAsAlias("")
}
// LoadAsAlias loads with an alias.
func (o *SchemaOntology) LoadAsAlias(s string) ([]rdf.RDFNode, error) {
return []rdf.RDFNode{
&rdf.AliasedDelegate{
@ -60,6 +64,7 @@ func (o *SchemaOntology) LoadAsAlias(s string) ([]rdf.RDFNode, error) {
}, nil
}
// LoadSpecificAsAlias loads a specific node and aliases it.
func (o *SchemaOntology) LoadSpecificAsAlias(alias, n string) ([]rdf.RDFNode, error) {
switch n {
case exampleSpec:
@ -111,10 +116,12 @@ func (o *SchemaOntology) LoadSpecificAsAlias(alias, n string) ([]rdf.RDFNode, er
return nil, fmt.Errorf("schema ontology cannot find %q to alias to %q", n, alias)
}
// LoadElement does nothing.
func (o *SchemaOntology) LoadElement(name string, payload map[string]interface{}) ([]rdf.RDFNode, error) {
return nil, nil
}
// GetByName returns a bare node by name.
func (o *SchemaOntology) GetByName(n string) (rdf.RDFNode, error) {
n = strings.TrimPrefix(n, o.SpecURI())
switch n {
@ -134,14 +141,20 @@ func (o *SchemaOntology) GetByName(n string) (rdf.RDFNode, error) {
var _ rdf.RDFNode = &example{}
// example is best understood by giving an example, such as this.
type example struct{}
// Enter Pushes an Example as Current.
func (e *example) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
ctx.Push()
ctx.Current = &rdf.VocabularyExample{}
return true, nil
}
// Exit Pops an Example and sets it on the parent item.
//
// Exit returns an error if the popped item is not an Example, or if after
// popping the Current item cannot have an Example added to it.
func (e *example) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
ei := ctx.Current
ctx.Pop()
@ -155,20 +168,28 @@ func (e *example) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, nil
}
// Apply returns an error.
func (e *example) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("schema example cannot be applied")
}
var _ rdf.RDFNode = &mainEntity{}
// mainEntity reapplies itself in all sublevels and simply saves the value onto
// Current. This saves the JSON example in raw form.
type mainEntity struct{}
// Enter Pushes the Current item and tells the context to only apply itself for
// all sublevels.
func (m *mainEntity) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
ctx.Push()
ctx.SetOnlyApplyThisNode(m)
return true, nil
}
// Exit saves the current raw JSON example onto a parent Example.
//
// Exit reutrns an error if Current after popping is not an Example.
func (m *mainEntity) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
// Save the example
example := ctx.Current
@ -184,6 +205,7 @@ func (m *mainEntity) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, nil
}
// Apply simply saves the value onto Current.
func (m *mainEntity) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
ctx.Current = value
return true, nil
@ -191,16 +213,23 @@ func (m *mainEntity) Apply(key string, value interface{}, ctx *rdf.ParsingContex
var _ rdf.RDFNode = &url{}
// url sets the URI on an item.
type url struct{}
// Enter does nothing.
func (u *url) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("schema url cannot be entered")
}
// Exit does nothing.
func (u *url) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("schema url cannot be exited")
}
// Apply sets the value as a URI onto an item.
//
// Returns an error if the value is not a string, or it cannot set the URI on
// the Current item.
func (u *url) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
if urlString, ok := value.(string); !ok {
return true, fmt.Errorf("schema url not given a string")
@ -213,16 +242,23 @@ func (u *url) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (boo
var _ rdf.RDFNode = &name{}
// name sets the Name on an item.
type name struct{}
// Enter does nothing.
func (n *name) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("schema name cannot be entered")
}
// Exit does nothing.
func (n *name) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("schema name cannot be exited")
}
// Apply sets the value as a name on the Current item.
//
// Returns an error if the value is not a string, or if the Current item cannot
// have its name set.
func (n *name) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
if s, ok := value.(string); !ok {
return true, fmt.Errorf("schema name not given string")
@ -237,16 +273,20 @@ func (n *name) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bo
var _ rdf.RDFNode = &creativeWork{}
// creativeWork does nothing.
type creativeWork struct{}
// Enter returns an error.
func (c *creativeWork) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("schema creative work cannot be entered")
}
// Exit does nothing.
func (c *creativeWork) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("schema creative work cannot be exited")
}
// Apply does nothing.
func (c *creativeWork) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
// Do nothing -- should already be an example.
return true, nil

View file

@ -20,18 +20,22 @@ const (
durationSpec = "duration"
)
// XMLOntology represents XML as an Ontology.
type XMLOntology struct {
Package string
}
// SpecURI returns the XML URI.
func (o *XMLOntology) SpecURI() string {
return xmlSpec
}
// Load the XML Ontology without an alias.
func (o *XMLOntology) Load() ([]rdf.RDFNode, error) {
return o.LoadAsAlias("")
}
// LoadAsAlias loads the XML Ontology with an alias.
func (o *XMLOntology) LoadAsAlias(s string) ([]rdf.RDFNode, error) {
return []rdf.RDFNode{
&rdf.AliasedDelegate{
@ -79,6 +83,7 @@ func (o *XMLOntology) LoadAsAlias(s string) ([]rdf.RDFNode, error) {
}, nil
}
// LoadSpecificAsAlias loads a specific node with an alias.
func (o *XMLOntology) LoadSpecificAsAlias(alias, name string) ([]rdf.RDFNode, error) {
switch name {
case anyURISpec:
@ -148,10 +153,12 @@ func (o *XMLOntology) LoadSpecificAsAlias(alias, name string) ([]rdf.RDFNode, er
return nil, fmt.Errorf("xml ontology cannot find %q to alias to %q", name, alias)
}
// LoadElement does nothing.
func (o *XMLOntology) LoadElement(name string, payload map[string]interface{}) ([]rdf.RDFNode, error) {
return nil, nil
}
// GetByName returns a bare node selected by name.
func (o *XMLOntology) GetByName(name string) (rdf.RDFNode, error) {
name = strings.TrimPrefix(name, o.SpecURI())
switch name {
@ -175,18 +182,22 @@ func (o *XMLOntology) GetByName(name string) (rdf.RDFNode, error) {
var _ rdf.RDFNode = &anyURI{}
// anyURI represents an xsd:anyURI value.
type anyURI struct {
pkg string
}
// Enter returns an error.
func (a *anyURI) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd anyURI cannot be entered")
}
// Exit returns an error.
func (a *anyURI) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd anyURI cannot be exited")
}
// Apply adds the anyURI value Kind to the XML namespace.
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 {
@ -268,18 +279,22 @@ func (a *anyURI) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (
var _ rdf.RDFNode = &dateTime{}
// dateTime is the xsd:dateTime value.
type dateTime struct {
pkg string
}
// Enter returns an error.
func (d *dateTime) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd dateTime cannot be entered")
}
// Exit returns an error.
func (d *dateTime) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd dateTime cannot be exited")
}
// Apply adds the xsd:dateTime value Kind to the XML namespace.
func (d *dateTime) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
v := ctx.Result.GetReference(xmlSpec)
if len(v.Values[dateTimeSpec].Name) == 0 {
@ -371,18 +386,22 @@ func (d *dateTime) Apply(key string, value interface{}, ctx *rdf.ParsingContext)
var _ rdf.RDFNode = &float{}
// float is a 32 bit floating point value.
type float struct {
pkg string
}
// Enter returns an error.
func (f *float) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd float cannot be entered")
}
// Exit returns an error.
func (f *float) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd float cannot be exited")
}
// Apply adds xsd:float value Kind to the XML namespace.
func (f *float) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
v := ctx.Result.GetReference(xmlSpec)
if len(v.Values[floatSpec].Name) == 0 {
@ -451,18 +470,22 @@ func (f *float) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (b
var _ rdf.RDFNode = &xmlString{}
// xmlString is a string.
type xmlString struct {
pkg string
}
// Enter returns an error
func (*xmlString) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd string cannot be entered")
}
// Exit returns an error.
func (*xmlString) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd string cannot be exited")
}
// Apply adds xsd:xmlString value Kind to the XML namespace.
func (s *xmlString) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
v := ctx.Result.GetReference(xmlSpec)
if len(v.Values[stringSpec].Name) == 0 {
@ -531,18 +554,22 @@ func (s *xmlString) Apply(key string, value interface{}, ctx *rdf.ParsingContext
var _ rdf.RDFNode = &boolean{}
// boolean is truly obvious.
type boolean struct {
pkg string
}
// Enter returns an error.
func (*boolean) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd boolean cannot be entered")
}
// Exit returns an error.
func (*boolean) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd boolean cannot be exited")
}
// Apply adds boolean value Kind to the XML namespace.
func (b *boolean) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
v := ctx.Result.GetReference(xmlSpec)
if len(v.Values[booleanSpec].Name) == 0 {
@ -642,18 +669,22 @@ func (b *boolean) Apply(key string, value interface{}, ctx *rdf.ParsingContext)
var _ rdf.RDFNode = &nonNegativeInteger{}
// nonNegativeInteger is a non-negative integer value.
type nonNegativeInteger struct {
pkg string
}
// Enter returns an error.
func (*nonNegativeInteger) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd nonNegativeInteger cannot be entered")
}
// Exit returns an error.
func (*nonNegativeInteger) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd nonNegativeInteger cannot be exited")
}
// Apply adds xsd:nonNegativeInteger value Kind to the XML namespace.
func (n *nonNegativeInteger) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
v := ctx.Result.GetReference(xmlSpec)
if len(v.Values[nonNegativeIntegerSpec].Name) == 0 {
@ -735,18 +766,27 @@ func (n *nonNegativeInteger) Apply(key string, value interface{}, ctx *rdf.Parsi
var _ rdf.RDFNode = &duration{}
// duration is a poorly defined value for a duration.
type duration struct {
pkg string
}
// Enter returns an error.
func (*duration) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd duration cannot be entered")
}
// Exit returns an error.
func (*duration) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd duration cannot be exited")
}
// Apply adds duration value Kind to the XML namespace.
//
// Note that duration has a really poor definition -- how long is a month or a
// year in seconds?
//
// Avoid at all costs.
func (d *duration) Apply(key string, value interface{}, ctx *rdf.ParsingContext) (bool, error) {
v := ctx.Result.GetReference(xmlSpec)
if len(v.Values[durationSpec].Name) == 0 {