1250 行
32 KiB
Go
1250 行
32 KiB
Go
package xsd
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/dave/jennifer/jen"
|
|
"github.com/go-fed/activity/astool/codegen"
|
|
"github.com/go-fed/activity/astool/rdf"
|
|
"net/url"
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
xmlName = "XMLSchema"
|
|
xmlSpec = "http://www.w3.org/2001/XMLSchema#"
|
|
anyURISpec = "anyURI"
|
|
dateTimeSpec = "dateTime"
|
|
floatSpec = "float"
|
|
stringSpec = "string"
|
|
booleanSpec = "boolean"
|
|
nonNegativeIntegerSpec = "nonNegativeInteger"
|
|
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{
|
|
Spec: xmlSpec,
|
|
Alias: s,
|
|
Name: anyURISpec,
|
|
Delegate: &anyURI{pkg: o.Package},
|
|
},
|
|
&rdf.AliasedDelegate{
|
|
Spec: xmlSpec,
|
|
Alias: s,
|
|
Name: dateTimeSpec,
|
|
Delegate: &dateTime{pkg: o.Package},
|
|
},
|
|
&rdf.AliasedDelegate{
|
|
Spec: xmlSpec,
|
|
Alias: s,
|
|
Name: floatSpec,
|
|
Delegate: &float{pkg: o.Package},
|
|
},
|
|
&rdf.AliasedDelegate{
|
|
Spec: xmlSpec,
|
|
Alias: s,
|
|
Name: stringSpec,
|
|
Delegate: &xmlString{pkg: o.Package},
|
|
},
|
|
&rdf.AliasedDelegate{
|
|
Spec: xmlSpec,
|
|
Alias: s,
|
|
Name: booleanSpec,
|
|
Delegate: &boolean{pkg: o.Package},
|
|
},
|
|
&rdf.AliasedDelegate{
|
|
Spec: xmlSpec,
|
|
Alias: s,
|
|
Name: nonNegativeIntegerSpec,
|
|
Delegate: &nonNegativeInteger{pkg: o.Package},
|
|
},
|
|
&rdf.AliasedDelegate{
|
|
Spec: xmlSpec,
|
|
Alias: s,
|
|
Name: durationSpec,
|
|
Delegate: &duration{pkg: o.Package},
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
// LoadSpecificAsAlias loads a specific node with an alias.
|
|
func (o *XMLOntology) LoadSpecificAsAlias(alias, name string) ([]rdf.RDFNode, error) {
|
|
switch name {
|
|
case anyURISpec:
|
|
return []rdf.RDFNode{
|
|
&rdf.AliasedDelegate{
|
|
Spec: "",
|
|
Alias: "",
|
|
Name: alias,
|
|
Delegate: &anyURI{pkg: o.Package},
|
|
},
|
|
}, nil
|
|
case dateTimeSpec:
|
|
return []rdf.RDFNode{
|
|
&rdf.AliasedDelegate{
|
|
Spec: "",
|
|
Alias: "",
|
|
Name: alias,
|
|
Delegate: &dateTime{pkg: o.Package},
|
|
},
|
|
}, nil
|
|
case floatSpec:
|
|
return []rdf.RDFNode{
|
|
&rdf.AliasedDelegate{
|
|
Spec: "",
|
|
Alias: "",
|
|
Name: alias,
|
|
Delegate: &float{pkg: o.Package},
|
|
},
|
|
}, nil
|
|
case stringSpec:
|
|
return []rdf.RDFNode{
|
|
&rdf.AliasedDelegate{
|
|
Spec: "",
|
|
Alias: "",
|
|
Name: alias,
|
|
Delegate: &xmlString{pkg: o.Package},
|
|
},
|
|
}, nil
|
|
case booleanSpec:
|
|
return []rdf.RDFNode{
|
|
&rdf.AliasedDelegate{
|
|
Spec: "",
|
|
Alias: "",
|
|
Name: alias,
|
|
Delegate: &boolean{pkg: o.Package},
|
|
},
|
|
}, nil
|
|
case nonNegativeIntegerSpec:
|
|
return []rdf.RDFNode{
|
|
&rdf.AliasedDelegate{
|
|
Spec: "",
|
|
Alias: "",
|
|
Name: alias,
|
|
Delegate: &nonNegativeInteger{pkg: o.Package},
|
|
},
|
|
}, nil
|
|
case durationSpec:
|
|
return []rdf.RDFNode{
|
|
&rdf.AliasedDelegate{
|
|
Spec: "",
|
|
Alias: "",
|
|
Name: alias,
|
|
Delegate: &duration{pkg: o.Package},
|
|
},
|
|
}, nil
|
|
}
|
|
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 {
|
|
case anyURISpec:
|
|
return &anyURI{pkg: o.Package}, nil
|
|
case dateTimeSpec:
|
|
return &dateTime{pkg: o.Package}, nil
|
|
case floatSpec:
|
|
return &float{pkg: o.Package}, nil
|
|
case stringSpec:
|
|
return &xmlString{pkg: o.Package}, nil
|
|
case booleanSpec:
|
|
return &boolean{pkg: o.Package}, nil
|
|
case nonNegativeIntegerSpec:
|
|
return &nonNegativeInteger{pkg: o.Package}, nil
|
|
case durationSpec:
|
|
return &duration{pkg: o.Package}, nil
|
|
}
|
|
return nil, fmt.Errorf("xsd ontology could not find node for name %s", name)
|
|
}
|
|
|
|
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, err := ctx.GetResultReferenceWithDefaults(xmlSpec, xmlName)
|
|
if err != nil {
|
|
return true, err
|
|
}
|
|
if len(v.Values[anyURISpec].Name) == 0 {
|
|
u, err := url.Parse(xmlSpec + anyURISpec)
|
|
if err != nil {
|
|
return true, err
|
|
}
|
|
val := &rdf.VocabularyValue{
|
|
Name: anyURISpec,
|
|
URI: u,
|
|
DefinitionType: jen.Op("*").Qual("net/url", "URL"),
|
|
Zero: "&url.URL{}",
|
|
IsNilable: true,
|
|
IsURI: true,
|
|
SerializeFn: rdf.SerializeValueFunction(
|
|
a.pkg,
|
|
anyURISpec,
|
|
jen.Op("*").Qual("net/url", "URL"),
|
|
[]jen.Code{
|
|
jen.Return(
|
|
jen.Id(codegen.This()).Dot("String").Call(),
|
|
jen.Nil(),
|
|
),
|
|
}),
|
|
DeserializeFn: rdf.DeserializeValueFunction(
|
|
a.pkg,
|
|
anyURISpec,
|
|
jen.Op("*").Qual("net/url", "URL"),
|
|
[]jen.Code{
|
|
jen.Var().Id("u").Op("*").Qual("net/url", "URL"),
|
|
jen.Var().Err().Error(),
|
|
jen.If(
|
|
jen.List(
|
|
jen.Id("s"),
|
|
jen.Id("ok"),
|
|
).Op(":=").Id(codegen.This()).Assert(jen.String()),
|
|
jen.Id("ok"),
|
|
).Block(
|
|
jen.List(
|
|
jen.Id("u"),
|
|
jen.Err(),
|
|
).Op("=").Qual("net/url", "Parse").Call(jen.Id("s")),
|
|
jen.If(
|
|
jen.Err().Op("!=").Nil(),
|
|
).Block(
|
|
jen.Err().Op("=").Qual("fmt", "Errorf").Call(
|
|
jen.Lit("%v cannot be interpreted as a xsd:anyURI: %s"),
|
|
jen.Id(codegen.This()),
|
|
jen.Err(),
|
|
),
|
|
).Else().If(
|
|
jen.Len(jen.Id("u").Dot("Scheme")).Op("==").Lit(0),
|
|
).Block(
|
|
jen.Err().Op("=").Qual("fmt", "Errorf").Call(
|
|
jen.Lit("%v cannot be interpreted as a xsd:anyURI: no scheme"),
|
|
jen.Id(codegen.This()),
|
|
),
|
|
),
|
|
).Else().Block(
|
|
jen.Err().Op("=").Qual("fmt", "Errorf").Call(
|
|
jen.Lit("%v cannot be interpreted as a string for xsd:anyURI"),
|
|
jen.Id(codegen.This()),
|
|
),
|
|
),
|
|
jen.Return(jen.List(
|
|
jen.Id("u"),
|
|
jen.Err(),
|
|
)),
|
|
}),
|
|
LessFn: rdf.LessFunction(
|
|
a.pkg,
|
|
anyURISpec,
|
|
jen.Op("*").Qual("net/url", "URL"),
|
|
[]jen.Code{
|
|
jen.Return(
|
|
jen.Id("lhs").Dot("String").Call().Op("<").Id("rhs").Dot("String").Call(),
|
|
),
|
|
}),
|
|
}
|
|
if err = v.SetValue(anyURISpec, val); err != nil {
|
|
return true, err
|
|
}
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
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, err := ctx.GetResultReferenceWithDefaults(xmlSpec, xmlName)
|
|
if err != nil {
|
|
return true, err
|
|
}
|
|
if len(v.Values[dateTimeSpec].Name) == 0 {
|
|
u, err := url.Parse(xmlSpec + dateTimeSpec)
|
|
if err != nil {
|
|
return true, err
|
|
}
|
|
val := &rdf.VocabularyValue{
|
|
Name: dateTimeSpec,
|
|
URI: u,
|
|
DefinitionType: jen.Qual("time", "Time"),
|
|
Zero: "&time.Time{}",
|
|
IsNilable: false,
|
|
SerializeFn: rdf.SerializeValueFunction(
|
|
d.pkg,
|
|
dateTimeSpec,
|
|
jen.Qual("time", "Time"),
|
|
[]jen.Code{
|
|
jen.Return(
|
|
jen.Id(codegen.This()).Dot("Format").Call(jen.Qual("time", "RFC3339")),
|
|
jen.Nil(),
|
|
),
|
|
}),
|
|
DeserializeFn: rdf.DeserializeValueFunction(
|
|
d.pkg,
|
|
dateTimeSpec,
|
|
jen.Qual("time", "Time"),
|
|
[]jen.Code{
|
|
jen.Var().Id("tmp").Qual("time", "Time"),
|
|
jen.Var().Err().Error(),
|
|
jen.If(
|
|
jen.List(
|
|
jen.Id("s"),
|
|
jen.Id("ok"),
|
|
).Op(":=").Id(codegen.This()).Assert(jen.String()),
|
|
jen.Id("ok"),
|
|
).Block(
|
|
jen.List(
|
|
jen.Id("tmp"),
|
|
jen.Err(),
|
|
).Op("=").Qual("time", "Parse").Call(
|
|
jen.Qual("time", "RFC3339"),
|
|
jen.Id("s"),
|
|
),
|
|
jen.If(
|
|
jen.Err().Op("!=").Nil(),
|
|
).Block(
|
|
jen.List(
|
|
jen.Id("tmp"),
|
|
jen.Err(),
|
|
).Op("=").Qual("time", "Parse").Call(
|
|
jen.Lit("2006-01-02T15:04Z07:00"),
|
|
jen.Id("s"),
|
|
),
|
|
jen.If(
|
|
jen.Err().Op("!=").Nil(),
|
|
).Block(
|
|
jen.Err().Op("=").Qual("fmt", "Errorf").Call(
|
|
jen.Lit("%v cannot be interpreted as xsd:datetime"),
|
|
jen.Id(codegen.This()),
|
|
),
|
|
),
|
|
),
|
|
).Else().Block(
|
|
jen.Err().Op("=").Qual("fmt", "Errorf").Call(
|
|
jen.Lit("%v cannot be interpreted as a string for xsd:datetime"),
|
|
jen.Id(codegen.This()),
|
|
),
|
|
),
|
|
jen.Return(jen.List(
|
|
jen.Id("tmp"),
|
|
jen.Err(),
|
|
)),
|
|
}),
|
|
LessFn: rdf.LessFunction(
|
|
d.pkg,
|
|
dateTimeSpec,
|
|
jen.Qual("time", "Time"),
|
|
[]jen.Code{
|
|
jen.Return(jen.Id("lhs").Dot("Before").Call(jen.Id("rhs"))),
|
|
}),
|
|
}
|
|
if err = v.SetValue(dateTimeSpec, val); err != nil {
|
|
return true, err
|
|
}
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
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, err := ctx.GetResultReferenceWithDefaults(xmlSpec, xmlName)
|
|
if err != nil {
|
|
return true, err
|
|
}
|
|
if len(v.Values[floatSpec].Name) == 0 {
|
|
u, err := url.Parse(xmlSpec + floatSpec)
|
|
if err != nil {
|
|
return true, err
|
|
}
|
|
val := &rdf.VocabularyValue{
|
|
Name: floatSpec,
|
|
URI: u,
|
|
DefinitionType: jen.Float64(),
|
|
Zero: "0.0",
|
|
IsNilable: false,
|
|
SerializeFn: rdf.SerializeValueFunction(
|
|
f.pkg,
|
|
floatSpec,
|
|
jen.Id("float64"),
|
|
[]jen.Code{
|
|
jen.Return(
|
|
jen.Id(codegen.This()),
|
|
jen.Nil(),
|
|
),
|
|
}),
|
|
DeserializeFn: rdf.DeserializeValueFunction(
|
|
f.pkg,
|
|
floatSpec,
|
|
jen.Id("float64"),
|
|
[]jen.Code{
|
|
jen.If(
|
|
jen.List(
|
|
jen.Id("f"),
|
|
jen.Id("ok"),
|
|
).Op(":=").Id(codegen.This()).Assert(jen.Float64()),
|
|
jen.Id("ok"),
|
|
).Block(
|
|
jen.Return(
|
|
jen.Id("f"),
|
|
jen.Nil(),
|
|
),
|
|
).Else().Block(
|
|
jen.Return(
|
|
jen.Lit(0),
|
|
jen.Qual("fmt", "Errorf").Call(
|
|
jen.Lit("%v cannot be interpreted as a float64 for xsd:float"),
|
|
jen.Id(codegen.This()),
|
|
),
|
|
),
|
|
),
|
|
}),
|
|
LessFn: rdf.LessFunction(
|
|
f.pkg,
|
|
floatSpec,
|
|
jen.Id("float64"),
|
|
[]jen.Code{
|
|
jen.Return(
|
|
jen.Id("lhs").Op("<").Id("rhs"),
|
|
),
|
|
}),
|
|
}
|
|
if err = v.SetValue(floatSpec, val); err != nil {
|
|
return true, err
|
|
}
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
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, err := ctx.GetResultReferenceWithDefaults(xmlSpec, xmlName)
|
|
if err != nil {
|
|
return true, err
|
|
}
|
|
if len(v.Values[stringSpec].Name) == 0 {
|
|
u, err := url.Parse(xmlSpec + stringSpec)
|
|
if err != nil {
|
|
return true, err
|
|
}
|
|
val := &rdf.VocabularyValue{
|
|
Name: stringSpec,
|
|
URI: u,
|
|
DefinitionType: jen.String(),
|
|
Zero: "\"\"",
|
|
IsNilable: false,
|
|
SerializeFn: rdf.SerializeValueFunction(
|
|
s.pkg,
|
|
stringSpec,
|
|
jen.Id("string"),
|
|
[]jen.Code{
|
|
jen.Return(
|
|
jen.Id(codegen.This()),
|
|
jen.Nil(),
|
|
),
|
|
}),
|
|
DeserializeFn: rdf.DeserializeValueFunction(
|
|
s.pkg,
|
|
stringSpec,
|
|
jen.Id("string"),
|
|
[]jen.Code{
|
|
jen.If(
|
|
jen.List(
|
|
jen.Id("s"),
|
|
jen.Id("ok"),
|
|
).Op(":=").Id(codegen.This()).Assert(jen.String()),
|
|
jen.Id("ok"),
|
|
).Block(
|
|
jen.Return(
|
|
jen.Id("s"),
|
|
jen.Nil(),
|
|
),
|
|
).Else().Block(
|
|
jen.Return(
|
|
jen.Lit(""),
|
|
jen.Qual("fmt", "Errorf").Call(
|
|
jen.Lit("%v cannot be interpreted as a string for xsd:string"),
|
|
jen.Id(codegen.This()),
|
|
),
|
|
),
|
|
),
|
|
}),
|
|
LessFn: rdf.LessFunction(
|
|
s.pkg,
|
|
stringSpec,
|
|
jen.Id("string"),
|
|
[]jen.Code{
|
|
jen.Return(
|
|
jen.Id("lhs").Op("<").Id("rhs"),
|
|
),
|
|
}),
|
|
}
|
|
if err = v.SetValue(stringSpec, val); err != nil {
|
|
return true, err
|
|
}
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
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, err := ctx.GetResultReferenceWithDefaults(xmlSpec, xmlName)
|
|
if err != nil {
|
|
return true, err
|
|
}
|
|
if len(v.Values[booleanSpec].Name) == 0 {
|
|
u, err := url.Parse(xmlSpec + booleanSpec)
|
|
if err != nil {
|
|
return true, err
|
|
}
|
|
val := &rdf.VocabularyValue{
|
|
Name: booleanSpec,
|
|
URI: u,
|
|
DefinitionType: jen.Bool(),
|
|
Zero: "false",
|
|
IsNilable: false,
|
|
SerializeFn: rdf.SerializeValueFunction(
|
|
b.pkg,
|
|
booleanSpec,
|
|
jen.Id("bool"),
|
|
[]jen.Code{
|
|
jen.Return(
|
|
jen.Id(codegen.This()),
|
|
jen.Nil(),
|
|
),
|
|
}),
|
|
DeserializeFn: rdf.DeserializeValueFunction(
|
|
b.pkg,
|
|
booleanSpec,
|
|
jen.Id("bool"),
|
|
[]jen.Code{
|
|
jen.If(
|
|
jen.List(
|
|
jen.Id("b"),
|
|
jen.Id("ok"),
|
|
).Op(":=").Id(codegen.This()).Assert(jen.Bool()),
|
|
jen.Id("ok"),
|
|
).Block(
|
|
jen.Return(
|
|
jen.Id("b"),
|
|
jen.Nil(),
|
|
),
|
|
).Else().If(
|
|
jen.List(
|
|
jen.Id("f"),
|
|
jen.Id("ok"),
|
|
).Op(":=").Id(codegen.This()).Assert(jen.Float64()),
|
|
jen.Id("ok"),
|
|
).Block(
|
|
jen.If(
|
|
jen.Id("f").Op("==").Lit(0),
|
|
).Block(
|
|
jen.Return(
|
|
jen.False(),
|
|
jen.Nil(),
|
|
),
|
|
).Else().If(
|
|
jen.Id("f").Op("==").Lit(1),
|
|
).Block(
|
|
jen.Return(
|
|
jen.True(),
|
|
jen.Nil(),
|
|
),
|
|
).Else().Block(
|
|
jen.Return(
|
|
jen.False(),
|
|
jen.Qual("fmt", "Errorf").Call(
|
|
jen.Lit("%v cannot be interpreted as a bool float64 for xsd:boolean"),
|
|
jen.Id(codegen.This()),
|
|
),
|
|
),
|
|
),
|
|
).Else().Block(
|
|
jen.Return(
|
|
jen.False(),
|
|
jen.Qual("fmt", "Errorf").Call(
|
|
jen.Lit("%v cannot be interpreted as a bool for xsd:boolean"),
|
|
jen.Id(codegen.This()),
|
|
),
|
|
),
|
|
),
|
|
}),
|
|
LessFn: rdf.LessFunction(
|
|
b.pkg,
|
|
booleanSpec,
|
|
jen.Id("bool"),
|
|
[]jen.Code{
|
|
jen.Commentf("Booleans don't have a natural ordering, so we pick that truth is greater than falsehood."),
|
|
jen.Return(
|
|
jen.Op("!").Id("lhs").Op("&&").Id("rhs"),
|
|
),
|
|
}),
|
|
}
|
|
if err = v.SetValue(booleanSpec, val); err != nil {
|
|
return true, err
|
|
}
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
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, err := ctx.GetResultReferenceWithDefaults(xmlSpec, xmlName)
|
|
if err != nil {
|
|
return true, err
|
|
}
|
|
if len(v.Values[nonNegativeIntegerSpec].Name) == 0 {
|
|
u, err := url.Parse(xmlSpec + nonNegativeIntegerSpec)
|
|
if err != nil {
|
|
return true, err
|
|
}
|
|
val := &rdf.VocabularyValue{
|
|
Name: nonNegativeIntegerSpec,
|
|
URI: u,
|
|
DefinitionType: jen.Int(),
|
|
Zero: "0",
|
|
IsNilable: false,
|
|
SerializeFn: rdf.SerializeValueFunction(
|
|
n.pkg,
|
|
nonNegativeIntegerSpec,
|
|
jen.Id("int"),
|
|
[]jen.Code{
|
|
jen.Return(
|
|
jen.Id(codegen.This()),
|
|
jen.Nil(),
|
|
),
|
|
}),
|
|
DeserializeFn: rdf.DeserializeValueFunction(
|
|
n.pkg,
|
|
nonNegativeIntegerSpec,
|
|
jen.Id("int"),
|
|
[]jen.Code{
|
|
jen.If(
|
|
jen.List(
|
|
jen.Id("i"),
|
|
jen.Id("ok"),
|
|
).Op(":=").Id(codegen.This()).Assert(jen.Float64()),
|
|
jen.Id("ok"),
|
|
).Block(
|
|
jen.Id("n").Op(":=").Int().Call(jen.Id("i")),
|
|
jen.If(
|
|
jen.Id("n").Op(">=").Lit(0),
|
|
).Block(
|
|
jen.Return(
|
|
jen.Id("n"),
|
|
jen.Nil(),
|
|
),
|
|
).Else().Block(
|
|
jen.Return(
|
|
jen.Lit(0),
|
|
jen.Qual("fmt", "Errorf").Call(
|
|
jen.Lit("%v is a negative integer for xsd:nonNegativeInteger"),
|
|
jen.Id(codegen.This()),
|
|
),
|
|
),
|
|
),
|
|
).Else().Block(
|
|
jen.Return(
|
|
jen.Lit(0),
|
|
jen.Qual("fmt", "Errorf").Call(
|
|
jen.Lit("%v cannot be interpreted as a float for xsd:nonNegativeInteger"),
|
|
jen.Id(codegen.This()),
|
|
),
|
|
),
|
|
),
|
|
}),
|
|
LessFn: rdf.LessFunction(
|
|
n.pkg,
|
|
nonNegativeIntegerSpec,
|
|
jen.Id("int"),
|
|
[]jen.Code{
|
|
jen.Return(
|
|
jen.Id("lhs").Op("<").Id("rhs"),
|
|
),
|
|
}),
|
|
}
|
|
if err = v.SetValue(nonNegativeIntegerSpec, val); err != nil {
|
|
return true, err
|
|
}
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
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, err := ctx.GetResultReferenceWithDefaults(xmlSpec, xmlName)
|
|
if err != nil {
|
|
return true, err
|
|
}
|
|
if len(v.Values[durationSpec].Name) == 0 {
|
|
u, err := url.Parse(xmlSpec + durationSpec)
|
|
if err != nil {
|
|
return true, err
|
|
}
|
|
val := &rdf.VocabularyValue{
|
|
Name: durationSpec,
|
|
URI: u,
|
|
DefinitionType: jen.Qual("time", "Duration"),
|
|
Zero: "time.Duration(0)",
|
|
IsNilable: false,
|
|
SerializeFn: rdf.SerializeValueFunction(
|
|
d.pkg,
|
|
durationSpec,
|
|
jen.Qual("time", "Duration"),
|
|
[]jen.Code{
|
|
jen.Commentf("Seriously questioning my life choices."),
|
|
jen.Id("s").Op(":=").Lit("P"),
|
|
jen.If(
|
|
jen.Id(codegen.This()).Op("<").Lit(0),
|
|
).Block(
|
|
jen.Id("s").Op("=").Lit("-P"),
|
|
jen.Id(codegen.This()).Op("=").Lit(-1).Op("*").Id(codegen.This()),
|
|
),
|
|
jen.Var().Id("tally").Qual("time", "Duration"),
|
|
// Years
|
|
jen.Commentf("Assume 8760 Hours per 365 days, cannot account for leap years in xsd:duration. :("),
|
|
jen.If(
|
|
jen.Id("years").Op(":=").Id(codegen.This()).Dot("Hours").Call().Op("/").Lit(8760.0),
|
|
jen.Id("years").Op(">=").Lit(1),
|
|
).Block(
|
|
jen.Id("nYears").Op(":=").Int64().Call(
|
|
jen.Qual("math", "Floor").Call(
|
|
jen.Id("years"),
|
|
),
|
|
),
|
|
jen.Id("tally").Op("+=").Qual("time", "Duration").Call(
|
|
jen.Id("nYears"),
|
|
).Op("*").Lit(8760).Op("*").Qual("time", "Hour"),
|
|
jen.Id("s").Op("=").Qual("fmt", "Sprintf").Call(
|
|
jen.Lit("%s%dY"),
|
|
jen.Id("s"),
|
|
jen.Id("nYears"),
|
|
),
|
|
),
|
|
// Months
|
|
jen.Commentf("Assume 30 days per month, cannot account for months lasting 31, 30, 29, or 28 days in xsd:duration. :("),
|
|
jen.If(
|
|
jen.Id("months").Op(":=").Parens(
|
|
jen.Id(codegen.This()).Dot("Hours").Call().Op("-").Id("tally").Dot("Hours").Call(),
|
|
).Op("/").Lit(720.0),
|
|
jen.Id("months").Op(">=").Lit(1),
|
|
).Block(
|
|
jen.Id("nMonths").Op(":=").Int64().Call(
|
|
jen.Qual("math", "Floor").Call(
|
|
jen.Id("months"),
|
|
),
|
|
),
|
|
jen.Id("tally").Op("+=").Qual("time", "Duration").Call(
|
|
jen.Id("nMonths"),
|
|
).Op("*").Lit(720).Op("*").Qual("time", "Hour"),
|
|
jen.Id("s").Op("=").Qual("fmt", "Sprintf").Call(
|
|
jen.Lit("%s%dM"),
|
|
jen.Id("s"),
|
|
jen.Id("nMonths"),
|
|
),
|
|
),
|
|
// Days
|
|
jen.If(
|
|
jen.Id("days").Op(":=").Parens(
|
|
jen.Id(codegen.This()).Dot("Hours").Call().Op("-").Id("tally").Dot("Hours").Call(),
|
|
).Op("/").Lit(24.0),
|
|
jen.Id("days").Op(">=").Lit(1),
|
|
).Block(
|
|
jen.Id("nDays").Op(":=").Int64().Call(
|
|
jen.Qual("math", "Floor").Call(
|
|
jen.Id("days"),
|
|
),
|
|
),
|
|
jen.Id("tally").Op("+=").Qual("time", "Duration").Call(
|
|
jen.Id("nDays"),
|
|
).Op("*").Lit(24).Op("*").Qual("time", "Hour"),
|
|
jen.Id("s").Op("=").Qual("fmt", "Sprintf").Call(
|
|
jen.Lit("%s%dD"),
|
|
jen.Id("s"),
|
|
jen.Id("nDays"),
|
|
),
|
|
),
|
|
jen.If(
|
|
jen.Id("tally").Op("<").Id(codegen.This()),
|
|
).Block(
|
|
jen.Id("s").Op("=").Qual("fmt", "Sprintf").Call(
|
|
jen.Lit("%sT"),
|
|
jen.Id("s"),
|
|
),
|
|
// Hours
|
|
jen.If(
|
|
jen.Id("hours").Op(":=").Id(codegen.This()).Dot("Hours").Call().Op("-").Id("tally").Dot("Hours").Call(),
|
|
jen.Id("hours").Op(">=").Lit(1),
|
|
).Block(
|
|
jen.Id("nHours").Op(":=").Int64().Call(
|
|
jen.Qual("math", "Floor").Call(
|
|
jen.Id("hours"),
|
|
),
|
|
),
|
|
jen.Id("tally").Op("+=").Qual("time", "Duration").Call(
|
|
jen.Id("nHours"),
|
|
).Op("*").Qual("time", "Hour"),
|
|
jen.Id("s").Op("=").Qual("fmt", "Sprintf").Call(
|
|
jen.Lit("%s%dH"),
|
|
jen.Id("s"),
|
|
jen.Id("nHours"),
|
|
),
|
|
),
|
|
// Minutes
|
|
jen.If(
|
|
jen.Id("minutes").Op(":=").Id(codegen.This()).Dot("Minutes").Call().Op("-").Id("tally").Dot("Minutes").Call(),
|
|
jen.Id("minutes").Op(">=").Lit(1),
|
|
).Block(
|
|
jen.Id("nMinutes").Op(":=").Int64().Call(
|
|
jen.Qual("math", "Floor").Call(
|
|
jen.Id("minutes"),
|
|
),
|
|
),
|
|
jen.Id("tally").Op("+=").Qual("time", "Duration").Call(
|
|
jen.Id("nMinutes"),
|
|
).Op("*").Qual("time", "Minute"),
|
|
jen.Id("s").Op("=").Qual("fmt", "Sprintf").Call(
|
|
jen.Lit("%s%dM"),
|
|
jen.Id("s"),
|
|
jen.Id("nMinutes"),
|
|
),
|
|
),
|
|
// Seconds
|
|
jen.If(
|
|
jen.Id("seconds").Op(":=").Id(codegen.This()).Dot("Seconds").Call().Op("-").Id("tally").Dot("Seconds").Call(),
|
|
jen.Id("seconds").Op(">=").Lit(1),
|
|
).Block(
|
|
jen.Id("nSeconds").Op(":=").Int64().Call(
|
|
jen.Qual("math", "Floor").Call(
|
|
jen.Id("seconds"),
|
|
),
|
|
),
|
|
jen.Id("tally").Op("+=").Qual("time", "Duration").Call(
|
|
jen.Id("nSeconds"),
|
|
).Op("*").Qual("time", "Second"),
|
|
jen.Id("s").Op("=").Qual("fmt", "Sprintf").Call(
|
|
jen.Lit("%s%dS"),
|
|
jen.Id("s"),
|
|
jen.Id("nSeconds"),
|
|
),
|
|
),
|
|
),
|
|
jen.Return(
|
|
jen.Id("s"),
|
|
jen.Nil(),
|
|
),
|
|
}),
|
|
DeserializeFn: rdf.DeserializeValueFunction(
|
|
d.pkg,
|
|
durationSpec,
|
|
jen.Qual("time", "Duration"),
|
|
[]jen.Code{
|
|
jen.Commentf("Maybe this time it will be easier."),
|
|
jen.If(
|
|
jen.List(
|
|
jen.Id("s"),
|
|
jen.Id("ok"),
|
|
).Op(":=").Id(codegen.This()).Assert(jen.String()),
|
|
jen.Id("ok"),
|
|
).Block(
|
|
jen.Id("isNeg").Op(":=").False(),
|
|
jen.If(
|
|
jen.Id("s").Index(jen.Lit(0)).Op("==").LitRune('-'),
|
|
).Block(
|
|
jen.Id("isNeg").Op("=").True(),
|
|
jen.Id("s").Op("=").Id("s").Index(jen.Lit(1), jen.Empty()),
|
|
),
|
|
jen.If(
|
|
jen.Id("s").Index(jen.Lit(0)).Op("!=").LitRune('P'),
|
|
).Block(
|
|
jen.Return(
|
|
jen.Lit(0),
|
|
jen.Qual("fmt", "Errorf").Call(
|
|
jen.Lit("%s malformed: missing 'P' for xsd:duration"),
|
|
jen.Id("s"),
|
|
),
|
|
),
|
|
),
|
|
jen.Id("re").Op(":=").Qual("regexp", "MustCompile").Call(
|
|
jen.Lit("P(\\d*Y)?(\\d*M)?(\\d*D)?(T(\\d*H)?(\\d*M)?(\\d*S)?)?"),
|
|
),
|
|
jen.Id("res").Op(":=").Id("re").Dot("FindStringSubmatch").Call(jen.Id("s")),
|
|
jen.Var().Id("dur").Qual("time", "Duration"),
|
|
// Years
|
|
jen.Id("nYear").Op(":=").Id("res").Index(jen.Lit(1)),
|
|
jen.If(
|
|
jen.Len(
|
|
jen.Id("nYear"),
|
|
).Op(">").Lit(0),
|
|
).Block(
|
|
jen.Id("nYear").Op("=").Id("nYear").Index(
|
|
jen.Empty(),
|
|
jen.Len(
|
|
jen.Id("nYear"),
|
|
).Op("-").Lit(1),
|
|
),
|
|
jen.List(
|
|
jen.Id("vYear"),
|
|
jen.Err(),
|
|
).Op(":=").Qual("strconv", "ParseInt").Call(
|
|
jen.Id("nYear"),
|
|
jen.Lit(10),
|
|
jen.Lit(64),
|
|
),
|
|
jen.If(
|
|
jen.Err().Op("!=").Nil(),
|
|
).Block(
|
|
jen.Return(
|
|
jen.Lit(0),
|
|
jen.Err(),
|
|
),
|
|
),
|
|
jen.Commentf("Assume 8760 Hours per 365 days, cannot account for leap years in xsd:duration. :("),
|
|
jen.Id("dur").Op("+=").Qual("time", "Duration").Call(
|
|
jen.Id("vYear"),
|
|
).Op("*").Qual("time", "Hour").Op("*").Lit(8760),
|
|
),
|
|
// Months
|
|
jen.Id("nMonth").Op(":=").Id("res").Index(jen.Lit(2)),
|
|
jen.If(
|
|
jen.Len(
|
|
jen.Id("nMonth"),
|
|
).Op(">").Lit(0),
|
|
).Block(
|
|
jen.Id("nMonth").Op("=").Id("nMonth").Index(
|
|
jen.Empty(),
|
|
jen.Len(
|
|
jen.Id("nMonth"),
|
|
).Op("-").Lit(1),
|
|
),
|
|
jen.List(
|
|
jen.Id("vMonth"),
|
|
jen.Err(),
|
|
).Op(":=").Qual("strconv", "ParseInt").Call(
|
|
jen.Id("nMonth"),
|
|
jen.Lit(10),
|
|
jen.Lit(64),
|
|
),
|
|
jen.If(
|
|
jen.Err().Op("!=").Nil(),
|
|
).Block(
|
|
jen.Return(
|
|
jen.Lit(0),
|
|
jen.Err(),
|
|
),
|
|
),
|
|
jen.Commentf("Assume 30 days per month, cannot account for months lasting 31, 30, 29, or 28 days in xsd:duration. :("),
|
|
jen.Id("dur").Op("+=").Qual("time", "Duration").Call(
|
|
jen.Id("vMonth"),
|
|
).Op("*").Qual("time", "Hour").Op("*").Lit(720),
|
|
),
|
|
// Days
|
|
jen.Id("nDay").Op(":=").Id("res").Index(jen.Lit(3)),
|
|
jen.If(
|
|
jen.Len(
|
|
jen.Id("nDay"),
|
|
).Op(">").Lit(0),
|
|
).Block(
|
|
jen.Id("nDay").Op("=").Id("nDay").Index(
|
|
jen.Empty(),
|
|
jen.Len(
|
|
jen.Id("nDay"),
|
|
).Op("-").Lit(1),
|
|
),
|
|
jen.List(
|
|
jen.Id("vDay"),
|
|
jen.Err(),
|
|
).Op(":=").Qual("strconv", "ParseInt").Call(
|
|
jen.Id("nDay"),
|
|
jen.Lit(10),
|
|
jen.Lit(64),
|
|
),
|
|
jen.If(
|
|
jen.Err().Op("!=").Nil(),
|
|
).Block(
|
|
jen.Return(
|
|
jen.Lit(0),
|
|
jen.Err(),
|
|
),
|
|
),
|
|
jen.Id("dur").Op("+=").Qual("time", "Duration").Call(
|
|
jen.Id("vDay"),
|
|
).Op("*").Qual("time", "Hour").Op("*").Lit(24),
|
|
),
|
|
// Hours
|
|
jen.Id("nHour").Op(":=").Id("res").Index(jen.Lit(5)),
|
|
jen.If(
|
|
jen.Len(
|
|
jen.Id("nHour"),
|
|
).Op(">").Lit(0),
|
|
).Block(
|
|
jen.Id("nHour").Op("=").Id("nHour").Index(
|
|
jen.Empty(),
|
|
jen.Len(
|
|
jen.Id("nHour"),
|
|
).Op("-").Lit(1),
|
|
),
|
|
jen.List(
|
|
jen.Id("vHour"),
|
|
jen.Err(),
|
|
).Op(":=").Qual("strconv", "ParseInt").Call(
|
|
jen.Id("nHour"),
|
|
jen.Lit(10),
|
|
jen.Lit(64),
|
|
),
|
|
jen.If(
|
|
jen.Err().Op("!=").Nil(),
|
|
).Block(
|
|
jen.Return(
|
|
jen.Lit(0),
|
|
jen.Err(),
|
|
),
|
|
),
|
|
jen.Id("dur").Op("+=").Qual("time", "Duration").Call(
|
|
jen.Id("vHour"),
|
|
).Op("*").Qual("time", "Hour"),
|
|
),
|
|
// Minutes
|
|
jen.Id("nMinute").Op(":=").Id("res").Index(jen.Lit(6)),
|
|
jen.If(
|
|
jen.Len(
|
|
jen.Id("nMinute"),
|
|
).Op(">").Lit(0),
|
|
).Block(
|
|
jen.Id("nMinute").Op("=").Id("nMinute").Index(
|
|
jen.Empty(),
|
|
jen.Len(
|
|
jen.Id("nMinute"),
|
|
).Op("-").Lit(1),
|
|
),
|
|
jen.List(
|
|
jen.Id("vMinute"),
|
|
jen.Err(),
|
|
).Op(":=").Qual("strconv", "ParseInt").Call(
|
|
jen.Id("nMinute"),
|
|
jen.Lit(10),
|
|
jen.Lit(64),
|
|
),
|
|
jen.If(
|
|
jen.Err().Op("!=").Nil(),
|
|
).Block(
|
|
jen.Return(
|
|
jen.Lit(0),
|
|
jen.Err(),
|
|
),
|
|
),
|
|
jen.Id("dur").Op("+=").Qual("time", "Duration").Call(
|
|
jen.Id("vMinute"),
|
|
).Op("*").Qual("time", "Minute"),
|
|
),
|
|
// Seconds
|
|
jen.Id("nSecond").Op(":=").Id("res").Index(jen.Lit(7)),
|
|
jen.If(
|
|
jen.Len(
|
|
jen.Id("nSecond"),
|
|
).Op(">").Lit(0),
|
|
).Block(
|
|
jen.Id("nSecond").Op("=").Id("nSecond").Index(
|
|
jen.Empty(),
|
|
jen.Len(
|
|
jen.Id("nSecond"),
|
|
).Op("-").Lit(1),
|
|
),
|
|
jen.List(
|
|
jen.Id("vSecond"),
|
|
jen.Err(),
|
|
).Op(":=").Qual("strconv", "ParseInt").Call(
|
|
jen.Id("nSecond"),
|
|
jen.Lit(10),
|
|
jen.Lit(64),
|
|
),
|
|
jen.If(
|
|
jen.Err().Op("!=").Nil(),
|
|
).Block(
|
|
jen.Return(
|
|
jen.Lit(0),
|
|
jen.Err(),
|
|
),
|
|
),
|
|
jen.Id("dur").Op("+=").Qual("time", "Duration").Call(
|
|
jen.Id("vSecond"),
|
|
).Op("*").Qual("time", "Second"),
|
|
),
|
|
jen.If(
|
|
jen.Id("isNeg"),
|
|
).Block(
|
|
jen.Id("dur").Op("*=").Lit(-1),
|
|
),
|
|
jen.Return(
|
|
jen.Id("dur"),
|
|
jen.Nil(),
|
|
),
|
|
).Else().Block(
|
|
jen.Return(
|
|
jen.Lit(0),
|
|
jen.Qual("fmt", "Errorf").Call(
|
|
jen.Lit("%v cannot be interpreted as a string for xsd:duration"),
|
|
jen.Id(codegen.This()),
|
|
),
|
|
),
|
|
),
|
|
}),
|
|
LessFn: rdf.LessFunction(
|
|
d.pkg,
|
|
durationSpec,
|
|
jen.Qual("time", "Duration"),
|
|
[]jen.Code{
|
|
jen.Return(
|
|
jen.Id("lhs").Op("<").Id("rhs"),
|
|
),
|
|
}),
|
|
}
|
|
if err = v.SetValue(durationSpec, val); err != nil {
|
|
return true, err
|
|
}
|
|
}
|
|
return true, nil
|
|
}
|