Merge pull request #79 from cjslep/dev

Update the experimental tool and added Code of Conduct from dev fork.
このコミットが含まれているのは:
Cory J Slep 2018-12-24 07:56:07 +01:00 committed by GitHub
コミット 3ca0b5182d
この署名に対応する既知のキーがデータベースに存在しません
GPGキーID: 4AEE18F83AFDEB23
14個のファイルの変更1976行の追加251行の削除

72
CODE_OF_CONDUCT.md ノーマルファイル
ファイルの表示

@ -0,0 +1,72 @@
# Contributor Covenant Code Of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and
expression, level of experience, education, socio-economic status, nationality,
personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, or to ban temporarily or permanently any
contributor for other behaviors that they deem inappropriate, threatening,
offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at cjslep@gmail.com. All complaints will
be reviewed and investigated and will result in a response that is deemed
necessary and appropriate to the circumstances. The project team is obligated to
maintain confidentiality with regard to the reporter of an incident. Further
details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the projects leadership.
## Attribution
This Code of Conduct is adapted from the Contributor Covenant, version 1.4,
available at
[https://www.contributor-covenant.org/version/1/4/code-of-conduct.html](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html)

562
tools/exp/convert/convert.go ノーマルファイル
ファイルの表示

@ -0,0 +1,562 @@
package convert
import (
"fmt"
"github.com/cjslep/activity/tools/exp/props"
"github.com/cjslep/activity/tools/exp/rdf"
"github.com/dave/jennifer/jen"
"strings"
)
type File struct {
F *jen.File
FileName string
Directory string
}
type vocabulary struct {
Kinds map[string]*props.Kind
FProps map[string]*props.FunctionalPropertyGenerator
NFProps map[string]*props.NonFunctionalPropertyGenerator
Types map[string]*props.TypeGenerator
}
func newVocabulary() vocabulary {
return vocabulary{
Kinds: make(map[string]*props.Kind, 0),
FProps: make(map[string]*props.FunctionalPropertyGenerator, 0),
NFProps: make(map[string]*props.NonFunctionalPropertyGenerator, 0),
Types: make(map[string]*props.TypeGenerator, 0),
}
}
type PropertyPackagePolicy int
const (
PropertyFlatUnderRoot PropertyPackagePolicy = iota
PropertyIndividualUnderRoot
PropertyFlatUnderVocabularyRoot
)
type TypePackagePolicy int
const (
TypeFlatUnderRoot TypePackagePolicy = iota
TypeIndividualUnderRoot
TypeFlatUnderVocabularyRoot
)
type Converter struct {
Registry *rdf.RDFRegistry
VocabularyRoot string
PropertyPackagePolicy PropertyPackagePolicy
PropertyPackageRoot string
TypePackagePolicy TypePackagePolicy
TypePackageRoot string
}
func (c Converter) Convert(p *rdf.ParsedVocabulary) (f []*File, e error) {
var v vocabulary
v, e = c.convertVocabulary(p)
if e != nil {
return
}
f, e = c.convertToFiles(v)
return
}
func (c Converter) convertToFiles(v vocabulary) (f []*File, e error) {
for _, _ = range v.Kinds {
// TODO: Implement
}
for _, i := range v.FProps {
var pkg string
pkg, e = c.propertyPackageFile(i)
if e != nil {
return
}
var dir string
dir, e = c.propertyPackageDirectory(i)
if e != nil {
return
}
file := jen.NewFilePath(pkg)
file.Add(i.Definition().Definition())
f = append(f, &File{
F: file,
FileName: fmt.Sprintf("gen_%s.go", i.PropertyName()),
Directory: dir,
})
}
for _, i := range v.NFProps {
var pkg string
pkg, e = c.propertyPackageFile(i)
if e != nil {
return
}
var dir string
dir, e = c.propertyPackageDirectory(i)
if e != nil {
return
}
file := jen.NewFilePath(pkg)
s, t := i.Definitions()
file.Add(s.Definition()).Line().Add(t.Definition())
f = append(f, &File{
F: file,
FileName: fmt.Sprintf("gen_%s.go", i.PropertyName()),
Directory: dir,
})
}
for _, i := range v.Types {
var pkg string
pkg, e = c.typePackageFile(i)
if e != nil {
return
}
var dir string
dir, e = c.typePackageDirectory(i)
if e != nil {
return
}
file := jen.NewFilePath(pkg)
file.Add(i.Definition().Definition())
f = append(f, &File{
F: file,
FileName: fmt.Sprintf("gen_%s.go", i.TypeName()),
Directory: dir,
})
}
return
}
// convertVocabulary works in a two-pass system: first converting all known
// properties, and then the types.
//
// Due to the fact that properties rely on the Kind abstraction, and both
// properties and types can be Kinds, this introduces tight coupling between
// the two so that callbacks can fill in missing links in data that isn't known
// beforehand (ex: how to serialize, deserialize, and compare types).
//
// This feels very hacky and could be decoupled using standard design patterns,
// but since there is no need, it isn't addressed now.
func (c Converter) convertVocabulary(p *rdf.ParsedVocabulary) (v vocabulary, e error) {
v = newVocabulary()
for k, val := range p.Vocab.Values {
v.Kinds[k] = c.convertValue(val)
}
for k, prop := range p.Vocab.Properties {
if prop.Functional {
v.FProps[k], e = c.convertFunctionalProperty(prop, v.Kinds, p.Vocab, p.References)
} else {
v.NFProps[k], e = c.convertNonFunctionalProperty(prop, v.Kinds, p.Vocab, p.References)
}
if e != nil {
return
}
}
// Instead of building a dependency tree, naively keep iterating through
// 'allTypes' until it is empty (good) or we get stuck (return error).
allTypes := make([]rdf.VocabularyType, 0, len(p.Vocab.Types))
for _, t := range p.Vocab.Types {
allTypes = append(allTypes, t)
}
for {
if len(allTypes) == 0 {
break
}
stuck := true
for i, t := range allTypes {
if allExtendsAreIn(t, v.Types) {
var tg *props.TypeGenerator
tg, e = c.convertType(t, p.Vocab, v.FProps, v.NFProps, v.Types)
if e != nil {
return
}
v.Types[t.Name] = tg
stuck = false
// Delete the one we just did.
allTypes[i] = allTypes[len(allTypes)-1]
allTypes = allTypes[:len(allTypes)-1]
break
}
}
if stuck {
e = fmt.Errorf("converting props got stuck in dependency cycle")
return
}
}
return
}
func (c Converter) convertType(t rdf.VocabularyType,
v rdf.Vocabulary,
existingFProps map[string]*props.FunctionalPropertyGenerator,
existingNFProps map[string]*props.NonFunctionalPropertyGenerator,
existingTypes map[string]*props.TypeGenerator) (tg *props.TypeGenerator, e error) {
// Determine the props package name
var pkg string
pkg, e = c.typePackageName(t)
if e != nil {
return
}
// Determine the properties for this type
var p []props.Property
for _, prop := range t.Properties {
if len(prop.Vocab) != 0 {
e = fmt.Errorf("unhandled use case: property domain outside its vocabulary")
return
} else {
var property props.Property
var ok bool
property, ok = existingFProps[prop.Name]
if !ok {
property, ok = existingNFProps[prop.Name]
if !ok {
e = fmt.Errorf("cannot find property with name: %s", prop.Name)
return
}
}
p = append(p, property)
}
}
// Determine WithoutProperties for this type
var wop []props.Property
for _, prop := range t.WithoutProperties {
if len(prop.Vocab) != 0 {
e = fmt.Errorf("unhandled use case: withoutproperty domain outside its vocabulary")
return
} else {
var property props.Property
var ok bool
property, ok = existingFProps[prop.Name]
if !ok {
property, ok = existingNFProps[prop.Name]
if !ok {
e = fmt.Errorf("cannot find property with name: %s", prop.Name)
return
}
}
wop = append(wop, property)
}
}
// Determine what this type extends
var ext []*props.TypeGenerator
for _, ex := range t.Extends {
if len(ex.Vocab) != 0 {
// TODO: This should be fixed to handle references
e = fmt.Errorf("unhandled use case: type extends another type outside its vocabulary")
return
} else {
ext = append(ext, existingTypes[ex.Name])
}
}
tg, e = props.NewTypeGenerator(
pkg,
c.convertTypeToName(t),
t.Notes,
p,
wop,
ext,
nil)
if e != nil {
return
}
// Apply disjoint if both sides are available because the TypeGenerator
// does not know the entire vocabulary, so cannot do this lookup and
// create this connection for us.
//
// TODO: Pass in the disjoint and have the TypeGenerator complete the
// doubly-linked connection for us.
for _, disj := range t.DisjointWith {
if len(disj.Vocab) != 0 {
// TODO: This should be fixed to handle references
e = fmt.Errorf("unhandled use case: type is disjoint with another type outside its vocabulary")
return
} else if disjointType, ok := existingTypes[disj.Name]; ok {
disjointType.AddDisjoint(tg)
tg.AddDisjoint(disjointType)
}
}
// Apply the type's KindSerializationFuncs to the property because there
// is no way for the TypeGenerator to know all properties who have a
// range of this type.
//
// TODO: Pass in these properties to the TypeGenerator constructor so it
// can build these double-links properly. Note this would also need to
// apply to referenced properties, possibly.
for _, prop := range existingFProps {
for _, kind := range prop.Kinds {
if kind.Name.LowerName == tg.TypeName() {
ser, deser, less := tg.KindSerializationFuncs()
if e = prop.SetKindFns(tg.TypeName(), ser, deser, less); e != nil {
return
}
}
}
}
for _, prop := range existingNFProps {
for _, kind := range prop.Kinds {
if kind.Name.LowerName == tg.TypeName() {
ser, deser, less := tg.KindSerializationFuncs()
if e = prop.SetKindFns(tg.TypeName(), ser, deser, less); e != nil {
return
}
}
}
}
return
}
func (c Converter) convertFunctionalProperty(p rdf.VocabularyProperty,
kinds map[string]*props.Kind,
v rdf.Vocabulary,
refs map[string]*rdf.Vocabulary) (fp *props.FunctionalPropertyGenerator, e error) {
var k []props.Kind
k, e = c.propertyKinds(p, kinds, v, refs)
if e != nil {
return
}
var pkg string
pkg, e = c.propertyPackageName(p)
if e != nil {
return
}
fp = props.NewFunctionalPropertyGenerator(
pkg,
c.toIdentifier(p),
k,
p.NaturalLanguageMap)
return
}
func (c Converter) convertNonFunctionalProperty(p rdf.VocabularyProperty,
kinds map[string]*props.Kind,
v rdf.Vocabulary,
refs map[string]*rdf.Vocabulary) (nfp *props.NonFunctionalPropertyGenerator, e error) {
var k []props.Kind
k, e = c.propertyKinds(p, kinds, v, refs)
if e != nil {
return
}
var pkg string
pkg, e = c.propertyPackageName(p)
if e != nil {
return
}
nfp = props.NewNonFunctionalPropertyGenerator(
pkg,
c.toIdentifier(p),
k,
p.NaturalLanguageMap)
return
}
func (c Converter) convertValue(v rdf.VocabularyValue) (k *props.Kind) {
k = &props.Kind{
Name: c.toIdentifier(v),
ConcreteKind: v.DefinitionType,
Nilable: c.isNilable(v.DefinitionType),
SerializeFn: v.SerializeFn,
DeserializeFn: v.DeserializeFn,
LessFn: v.LessFn,
}
return
}
func (c Converter) convertTypeToKind(v rdf.VocabularyType) (k *props.Kind, e error) {
k = &props.Kind{
Name: c.toIdentifier(v),
ConcreteKind: c.convertTypeToConcreteKind(v),
Nilable: true,
// Instead of populating:
// - SerializeFn
// - DeserializeFn
// - LessFn
//
// The TypeGenerator is responsible for calling setKindFns on
// the properties, to property wire a Property's Kind back to
// the Type's implementation.
}
return
}
func (c Converter) convertTypeToName(v rdf.VocabularyType) string {
return strings.Title(v.Name)
}
func (c Converter) convertTypeToConcreteKind(v rdf.VocabularyType) string {
return "*" + c.convertTypeToName(v)
}
func (c Converter) propertyKinds(v rdf.VocabularyProperty,
kinds map[string]*props.Kind,
vocab rdf.Vocabulary,
refs map[string]*rdf.Vocabulary) (k []props.Kind, e error) {
for _, r := range v.Range {
if len(r.Vocab) == 0 {
if kind, ok := kinds[r.Name]; !ok {
// It is a Type of the vocabulary
if t, ok := vocab.Types[r.Name]; !ok {
e = fmt.Errorf("cannot find own kind with name %q", r.Name)
return
} else {
var kt *props.Kind
kt, e = c.convertTypeToKind(t)
if e != nil {
return
}
k = append(k, *kt)
}
} else {
// It is a Value of the vocabulary
k = append(k, *kind)
}
} else {
var url string
url, e = c.Registry.ResolveAlias(r.Vocab)
if e != nil {
return
}
refVocab, ok := refs[url]
if !ok {
e = fmt.Errorf("references do not contain %s", url)
return
}
if val, ok := refVocab.Values[r.Name]; !ok {
// It is a Type of the vocabulary instead
if t, ok := refVocab.Types[r.Name]; !ok {
e = fmt.Errorf("cannot find kind with name %q in %s", r.Name, url)
return
} else {
var kt *props.Kind
kt, e = c.convertTypeToKind(t)
if e != nil {
return
}
k = append(k, *kt)
}
} else {
// It is a Value of the vocabulary
k = append(k, *c.convertValue(val))
}
}
}
return
}
func (c Converter) typePackageName(v rdf.VocabularyType) (pkg string, e error) {
switch c.TypePackagePolicy {
case TypeFlatUnderRoot:
pkg = c.TypePackageRoot
case TypeIndividualUnderRoot:
pkg = v.Name
case TypeFlatUnderVocabularyRoot:
pkg = c.VocabularyRoot
default:
e = fmt.Errorf("unrecognized TypePackagePolicy: %v", c.TypePackagePolicy)
}
return
}
func (c Converter) propertyPackageName(v rdf.VocabularyProperty) (pkg string, e error) {
switch c.PropertyPackagePolicy {
case PropertyFlatUnderRoot:
pkg = c.PropertyPackageRoot
case PropertyIndividualUnderRoot:
pkg = v.Name
case PropertyFlatUnderVocabularyRoot:
pkg = c.VocabularyRoot
default:
e = fmt.Errorf("unrecognized PropertyPackagePolicy: %v", c.PropertyPackagePolicy)
}
return
}
func (c Converter) typePackageDirectory(v *props.TypeGenerator) (dir string, e error) {
switch c.TypePackagePolicy {
case TypeFlatUnderRoot:
dir = fmt.Sprintf("%s/%s/", c.VocabularyRoot, c.TypePackageRoot)
case TypeIndividualUnderRoot:
dir = fmt.Sprintf("%s/%s/%s/", c.VocabularyRoot, c.TypePackageRoot, v.TypeName())
case TypeFlatUnderVocabularyRoot:
dir = c.VocabularyRoot + "/"
default:
e = fmt.Errorf("unrecognized TypePackagePolicy: %v", c.TypePackagePolicy)
}
return
}
func (c Converter) typePackageFile(v *props.TypeGenerator) (pkg string, e error) {
switch c.TypePackagePolicy {
case TypeFlatUnderRoot:
pkg = fmt.Sprintf("%s/%s", c.VocabularyRoot, c.TypePackageRoot)
case TypeIndividualUnderRoot:
pkg = fmt.Sprintf("%s/%s/%s", c.VocabularyRoot, c.TypePackageRoot, v.TypeName())
case TypeFlatUnderVocabularyRoot:
pkg = c.VocabularyRoot
default:
e = fmt.Errorf("unrecognized TypePackagePolicy: %v", c.TypePackagePolicy)
}
return
}
type propertyNamer interface {
PropertyName() string
}
var (
_ propertyNamer = &props.FunctionalPropertyGenerator{}
_ propertyNamer = &props.NonFunctionalPropertyGenerator{}
)
func (c Converter) propertyPackageDirectory(v propertyNamer) (dir string, e error) {
switch c.PropertyPackagePolicy {
case PropertyFlatUnderRoot:
dir = fmt.Sprintf("%s/%s/", c.VocabularyRoot, c.PropertyPackageRoot)
case PropertyIndividualUnderRoot:
dir = fmt.Sprintf("%s/%s/%s/", c.VocabularyRoot, c.PropertyPackageRoot, v.PropertyName())
case PropertyFlatUnderVocabularyRoot:
dir = c.VocabularyRoot + "/"
default:
e = fmt.Errorf("unrecognized PropertyPackagePolicy: %v", c.PropertyPackagePolicy)
}
return
}
func (c Converter) propertyPackageFile(v propertyNamer) (pkg string, e error) {
switch c.PropertyPackagePolicy {
case PropertyFlatUnderRoot:
pkg = fmt.Sprintf("%s/%s", c.VocabularyRoot, c.PropertyPackageRoot)
case PropertyIndividualUnderRoot:
pkg = fmt.Sprintf("%s/%s/%s", c.VocabularyRoot, c.PropertyPackageRoot, v.PropertyName())
case PropertyFlatUnderVocabularyRoot:
pkg = c.VocabularyRoot
default:
e = fmt.Errorf("unrecognized PropertyPackagePolicy: %v", c.PropertyPackagePolicy)
}
return
}
func (c Converter) toIdentifier(n rdf.NameGetter) props.Identifier {
return props.Identifier{
LowerName: n.GetName(),
CamelName: strings.Title(n.GetName()),
}
}
func (c Converter) isNilable(goType string) bool {
return goType[0] == '*'
}
func allExtendsAreIn(t rdf.VocabularyType, v map[string]*props.TypeGenerator) bool {
for _, e := range t.Extends {
if len(e.Vocab) != 0 {
// TODO: This should be fixed to handle references
return false
} else if _, ok := v[e.Name]; !ok {
return false
}
}
return true
}

ファイルの表示

@ -4,12 +4,15 @@ import (
"encoding/json"
"flag"
"fmt"
"github.com/cjslep/activity/tools/exp/convert"
"github.com/cjslep/activity/tools/exp/rdf"
"github.com/cjslep/activity/tools/exp/rdf/owl"
"github.com/cjslep/activity/tools/exp/rdf/rdfs"
"github.com/cjslep/activity/tools/exp/rdf/schema"
"github.com/cjslep/activity/tools/exp/rdf/xsd"
"io/ioutil"
"os"
"strings"
)
var registry *rdf.RDFRegistry
@ -24,19 +27,44 @@ func mustAddOntology(o rdf.Ontology) {
}
func init() {
mustAddOntology(&xsd.XMLOntology{})
mustAddOntology(&xsd.XMLOntology{Package: "xml"})
mustAddOntology(&owl.OWLOntology{})
mustAddOntology(&rdf.RDFOntology{})
mustAddOntology(&rdf.RDFOntology{Package: "rdf"})
mustAddOntology(&rdfs.RDFSchemaOntology{})
mustAddOntology(&schema.SchemaOntology{})
}
var (
input = flag.String("input", "spec.json", "Input JSON-LD specification used to generate Go code.")
// TODO: Use this flag
root = flag.String("root", "github.com/go-fed/activity/", "Go import path prefix for generated packages")
xmlpkg = flag.String("xmlpkg", "github.com/go-fed/activity/tools/exp/ref/xml", "Go package location for known XML references")
rdfpkg = flag.String("rdfpkg", "github.com/go-fed/activity/tools/exp/ref/rdf", "Go package location for known RDF references")
// TODO: Use this flag
writeWellKnown = flag.Bool("write-well-known", false, "When true, also outputs well-known specifications to './ref' subdirectories (ex: XML, RDF)")
)
type list []string
func (l *list) String() string {
return strings.Join(*l, ",")
}
func (l *list) Set(v string) error {
vals := strings.Split(v, ",")
*l = append(*l, vals...)
return nil
}
func main() {
var ref list
var refspec list
var refpkg list
flag.Var(&ref, "ref", "Input JSON-LD specification of other referenced specifications. Must be the same size and in the same order as the 'refspec' and 'refpkg' flags")
flag.Var(&refspec, "refspec", "Base URL for other referenced specifications. Must be the same size and in the same order as the 'ref' and 'refpkg' flags")
flag.Var(&refpkg, "refpkg", "Golang package location for other referenced specifications. Must be the same size and in the same order as the 'ref' and 'refspec' flags")
flag.Parse()
// TODO: Flag validation
b, err := ioutil.ReadFile(*input)
if err != nil {
@ -51,5 +79,28 @@ func main() {
if err != nil {
panic(err)
}
fmt.Printf("done\n%s\n", p)
c := &convert.Converter{
Registry: registry,
VocabularyRoot: "as",
PropertyPackagePolicy: convert.PropertyFlatUnderRoot,
PropertyPackageRoot: "props",
TypePackagePolicy: convert.TypeFlatUnderRoot,
TypePackageRoot: "types",
}
f, err := c.Convert(p)
if err != nil {
panic(err)
}
for _, file := range f {
file.F.ImportName(*xmlpkg, "xml")
file.F.ImportName(*rdfpkg, "rdf")
if e := os.MkdirAll("./"+file.Directory, 0777); e != nil {
panic(e)
}
if e := file.F.Save("./" + file.Directory + file.FileName); e != nil {
panic(e)
}
}
fmt.Printf("done")
// fmt.Printf("done\n%s\n", p)
}

ファイルの表示

@ -2,8 +2,8 @@ package props
import (
"fmt"
"github.com/cjslep/activity/tools/exp/codegen"
"github.com/dave/jennifer/jen"
"github.com/go-fed/activity/tools/exp/codegen"
"sync"
)
@ -113,7 +113,7 @@ func (p *FunctionalPropertyGenerator) funcs() []*codegen.Method {
}
methods := []*codegen.Method{
codegen.NewCommentedValueMethod(
p.packageName(),
p.PackageName(),
kindIndexMethod,
p.StructName(),
/*params=*/ nil,
@ -129,7 +129,7 @@ func (p *FunctionalPropertyGenerator) funcs() []*codegen.Method {
// IsLanguageMap Method
methods = append(methods,
codegen.NewCommentedValueMethod(
p.packageName(),
p.PackageName(),
isLanguageMapMethod,
p.StructName(),
/*params=*/ nil,
@ -154,7 +154,7 @@ func (p *FunctionalPropertyGenerator) funcs() []*codegen.Method {
// HasLanguage Method
methods = append(methods,
codegen.NewCommentedValueMethod(
p.packageName(),
p.PackageName(),
hasLanguageMethod,
p.StructName(),
[]jen.Code{jen.Id("bcp47").String()},
@ -182,7 +182,7 @@ func (p *FunctionalPropertyGenerator) funcs() []*codegen.Method {
// GetLanguage Method
methods = append(methods,
codegen.NewCommentedValueMethod(
p.packageName(),
p.PackageName(),
getLanguageMethod,
p.StructName(),
[]jen.Code{jen.Id("bcp47").String()},
@ -214,7 +214,7 @@ func (p *FunctionalPropertyGenerator) funcs() []*codegen.Method {
// SetLanguage Method
methods = append(methods,
codegen.NewCommentedPointerMethod(
p.packageName(),
p.PackageName(),
setLanguageMethod,
p.StructName(),
[]jen.Code{
@ -273,7 +273,7 @@ func (p *FunctionalPropertyGenerator) serializationFuncs() ([]*codegen.Method, [
}
serialize := []*codegen.Method{
codegen.NewCommentedValueMethod(
p.packageName(),
p.PackageName(),
p.serializeFnName(),
p.StructName(),
/*params=*/ nil,
@ -319,24 +319,24 @@ func (p *FunctionalPropertyGenerator) serializationFuncs() ([]*codegen.Method, [
if p.asIterator {
deserialize = append(deserialize,
codegen.NewCommentedFunction(
p.packageName(),
p.deserializeFnName(),
p.PackageName(),
p.DeserializeFnName(),
[]jen.Code{jen.Id("i").Interface()},
[]jen.Code{jen.Op("*").Id(p.StructName()), jen.Error()},
[]jen.Code{
deserializeFns.Add(p.unknownDeserializeCode()),
p.addUnknownDeserializeCode(deserializeFns),
jen.Return(
jen.Nil(),
jen.Nil(),
),
},
jen.Commentf("%s creates an iterator from an element that has been unmarshalled from a text or binary format.", p.deserializeFnName()),
jen.Commentf("%s creates an iterator from an element that has been unmarshalled from a text or binary format.", p.DeserializeFnName()),
))
} else {
deserialize = append(deserialize,
codegen.NewCommentedFunction(
p.packageName(),
p.deserializeFnName(),
p.PackageName(),
p.DeserializeFnName(),
[]jen.Code{jen.Id("m").Map(jen.String()).Interface()},
[]jen.Code{jen.Op("*").Id(p.StructName()), jen.Error()},
[]jen.Code{
@ -349,14 +349,14 @@ func (p *FunctionalPropertyGenerator) serializationFuncs() ([]*codegen.Method, [
),
jen.Id("ok"),
).Block(
deserializeFns.Add(p.unknownDeserializeCode()),
p.addUnknownDeserializeCode(deserializeFns),
),
jen.Return(
jen.Nil(),
jen.Nil(),
),
},
jen.Commentf("%s creates a %q property from an interface representation that has been unmarshalled from a text or binary format.", p.deserializeFnName(), p.PropertyName()),
jen.Commentf("%s creates a %q property from an interface representation that has been unmarshalled from a text or binary format.", p.DeserializeFnName(), p.PropertyName()),
))
}
return serialize, deserialize
@ -421,7 +421,7 @@ func (p *FunctionalPropertyGenerator) singleTypeFuncs() []*codegen.Method {
}
if p.Kinds[0].Nilable {
methods = append(methods, codegen.NewCommentedValueMethod(
p.packageName(),
p.PackageName(),
hasMethod,
p.StructName(),
/*params=*/ nil,
@ -431,7 +431,7 @@ func (p *FunctionalPropertyGenerator) singleTypeFuncs() []*codegen.Method {
))
} else {
methods = append(methods, codegen.NewCommentedValueMethod(
p.packageName(),
p.PackageName(),
hasMethod,
p.StructName(),
/*params=*/ nil,
@ -443,7 +443,7 @@ func (p *FunctionalPropertyGenerator) singleTypeFuncs() []*codegen.Method {
// Get Method
getComment := jen.Commentf("%s returns the value of this property. When %s returns false, %s will return any arbitrary value.", getMethod, hasMethod, getMethod)
methods = append(methods, codegen.NewCommentedValueMethod(
p.packageName(),
p.PackageName(),
p.getFnName(0),
p.StructName(),
/*params=*/ nil,
@ -465,7 +465,7 @@ func (p *FunctionalPropertyGenerator) singleTypeFuncs() []*codegen.Method {
}
if p.Kinds[0].Nilable {
methods = append(methods, codegen.NewCommentedPointerMethod(
p.packageName(),
p.PackageName(),
p.setFnName(0),
p.StructName(),
[]jen.Code{jen.Id("v").Id(p.Kinds[0].ConcreteKind)},
@ -478,7 +478,7 @@ func (p *FunctionalPropertyGenerator) singleTypeFuncs() []*codegen.Method {
))
} else {
methods = append(methods, codegen.NewCommentedPointerMethod(
p.packageName(),
p.PackageName(),
p.setFnName(0),
p.StructName(),
[]jen.Code{jen.Id("v").Id(p.Kinds[0].ConcreteKind)},
@ -507,7 +507,7 @@ func (p *FunctionalPropertyGenerator) singleTypeFuncs() []*codegen.Method {
}
if p.Kinds[0].Nilable {
methods = append(methods, codegen.NewCommentedPointerMethod(
p.packageName(),
p.PackageName(),
p.clearMethodName(),
p.StructName(),
/*params=*/ nil,
@ -517,7 +517,7 @@ func (p *FunctionalPropertyGenerator) singleTypeFuncs() []*codegen.Method {
))
} else {
methods = append(methods, codegen.NewCommentedPointerMethod(
p.packageName(),
p.PackageName(),
p.clearMethodName(),
p.StructName(),
/*params=*/ nil,
@ -602,7 +602,7 @@ func (p *FunctionalPropertyGenerator) multiTypeFuncs() []*codegen.Method {
)
}
methods = append(methods, codegen.NewCommentedPointerMethod(
p.packageName(),
p.PackageName(),
hasAnyMethodName,
p.StructName(),
/*params=*/ nil,
@ -626,7 +626,7 @@ func (p *FunctionalPropertyGenerator) multiTypeFuncs() []*codegen.Method {
clearLine = append(clearLine, jen.Id(codegen.This()).Dot(langMapMember).Op("=").Nil())
}
methods = append(methods, codegen.NewCommentedPointerMethod(
p.packageName(),
p.PackageName(),
p.clearMethodName(),
p.StructName(),
/*params=*/ nil,
@ -649,7 +649,7 @@ func (p *FunctionalPropertyGenerator) multiTypeFuncs() []*codegen.Method {
}
if kind.Nilable {
methods = append(methods, codegen.NewCommentedValueMethod(
p.packageName(),
p.PackageName(),
p.isMethodName(i),
p.StructName(),
/*params=*/ nil,
@ -659,7 +659,7 @@ func (p *FunctionalPropertyGenerator) multiTypeFuncs() []*codegen.Method {
))
} else {
methods = append(methods, codegen.NewCommentedValueMethod(
p.packageName(),
p.PackageName(),
p.isMethodName(i),
p.StructName(),
/*params=*/ nil,
@ -684,7 +684,7 @@ func (p *FunctionalPropertyGenerator) multiTypeFuncs() []*codegen.Method {
}
if kind.Nilable {
methods = append(methods, codegen.NewCommentedPointerMethod(
p.packageName(),
p.PackageName(),
p.setFnName(i),
p.StructName(),
[]jen.Code{jen.Id("v").Id(kind.ConcreteKind)},
@ -697,7 +697,7 @@ func (p *FunctionalPropertyGenerator) multiTypeFuncs() []*codegen.Method {
))
} else {
methods = append(methods, codegen.NewCommentedPointerMethod(
p.packageName(),
p.PackageName(),
p.setFnName(i),
p.StructName(),
[]jen.Code{jen.Id("v").Id(kind.ConcreteKind)},
@ -715,7 +715,7 @@ func (p *FunctionalPropertyGenerator) multiTypeFuncs() []*codegen.Method {
for i, kind := range p.Kinds {
getComment := jen.Commentf("%s returns the value of this property. When %s returns false, %s will return an arbitrary value.", p.getFnName(i), p.isMethodName(i), p.getFnName(i))
methods = append(methods, codegen.NewCommentedValueMethod(
p.packageName(),
p.PackageName(),
p.getFnName(i),
p.StructName(),
/*params=*/ nil,
@ -733,26 +733,31 @@ func (p *FunctionalPropertyGenerator) unknownMemberDef() jen.Code {
return jen.Id(unknownMemberName).Index().Byte()
}
// unknownDeserializeCode generates the "else if it's a []byte" code used for
// addUnknownDeserializeCode generates the "else if it's a []byte" code used for
// deserializing unknown values.
func (p *FunctionalPropertyGenerator) unknownDeserializeCode() jen.Code {
return jen.Else().If(
jen.List(
jen.Id("v"),
func (p *FunctionalPropertyGenerator) addUnknownDeserializeCode(existing jen.Code) jen.Code {
if len(p.Kinds) > 0 {
existing = jen.Add(existing, jen.Else())
}
return jen.Add(existing,
jen.If(
jen.List(
jen.Id("v"),
jen.Id("ok"),
).Op(":=").Id("i").Assert(
jen.Index().Byte(),
),
jen.Id("ok"),
).Op(":=").Id("i").Assert(
jen.Index().Byte(),
),
jen.Id("ok"),
).Block(
jen.Id(codegen.This()).Op(":=").Op("&").Id(p.StructName()).Values(
jen.Dict{
jen.Id(unknownMemberName): jen.Id("v"),
},
),
jen.Return(
jen.Id(codegen.This()),
jen.Err(),
).Block(
jen.Id(codegen.This()).Op(":=").Op("&").Id(p.StructName()).Values(
jen.Dict{
jen.Id(unknownMemberName): jen.Id("v"),
},
),
jen.Return(
jen.Id(codegen.This()),
jen.Err(),
),
),
)
}

ファイルの表示

@ -2,8 +2,8 @@ package props
import (
"fmt"
"github.com/cjslep/activity/tools/exp/codegen"
"github.com/dave/jennifer/jen"
"github.com/go-fed/activity/tools/exp/codegen"
"sync"
)
@ -90,7 +90,7 @@ func (p *NonFunctionalPropertyGenerator) funcs() []*codegen.Method {
prependMethodName := fmt.Sprintf("%s%s", prependMethod, p.kindCamelName(i))
methods = append(methods,
codegen.NewCommentedPointerMethod(
p.packageName(),
p.PackageName(),
prependMethodName,
p.StructName(),
[]jen.Code{jen.Id("v").Id(kind.ConcreteKind)},
@ -108,7 +108,7 @@ func (p *NonFunctionalPropertyGenerator) funcs() []*codegen.Method {
appendMethodName := fmt.Sprintf("%s%s", appendMethod, p.kindCamelName(i))
methods = append(methods,
codegen.NewCommentedPointerMethod(
p.packageName(),
p.PackageName(),
appendMethodName,
p.StructName(),
[]jen.Code{jen.Id("v").Id(kind.ConcreteKind)},
@ -140,7 +140,7 @@ func (p *NonFunctionalPropertyGenerator) funcs() []*codegen.Method {
// Remove Method
methods = append(methods,
codegen.NewCommentedPointerMethod(
p.packageName(),
p.PackageName(),
removeMethod,
p.StructName(),
[]jen.Code{jen.Id("idx").Int()},
@ -176,7 +176,7 @@ func (p *NonFunctionalPropertyGenerator) funcs() []*codegen.Method {
// Len Method
methods = append(methods,
codegen.NewCommentedValueMethod(
p.packageName(),
p.PackageName(),
lenMethod,
p.StructName(),
/*params=*/ nil,
@ -192,7 +192,7 @@ func (p *NonFunctionalPropertyGenerator) funcs() []*codegen.Method {
// Swap Method
methods = append(methods,
codegen.NewCommentedValueMethod(
p.packageName(),
p.PackageName(),
swapMethod,
p.StructName(),
[]jen.Code{
@ -213,7 +213,7 @@ func (p *NonFunctionalPropertyGenerator) funcs() []*codegen.Method {
// Less Method
methods = append(methods,
codegen.NewCommentedValueMethod(
p.packageName(),
p.PackageName(),
lessMethod,
p.StructName(),
[]jen.Code{
@ -235,7 +235,7 @@ func (p *NonFunctionalPropertyGenerator) funcs() []*codegen.Method {
// Kind Method
methods = append(methods,
codegen.NewCommentedValueMethod(
p.packageName(),
p.PackageName(),
kindIndexMethod,
p.StructName(),
[]jen.Code{jen.Id("idx").Int()},
@ -255,7 +255,7 @@ func (p *NonFunctionalPropertyGenerator) funcs() []*codegen.Method {
func (p *NonFunctionalPropertyGenerator) serializationFuncs() ([]*codegen.Method, []*codegen.Function) {
serialize := []*codegen.Method{
codegen.NewCommentedValueMethod(
p.packageName(),
p.PackageName(),
p.serializeFnName(),
p.StructName(),
/*params=*/ nil,
@ -303,7 +303,7 @@ func (p *NonFunctionalPropertyGenerator) serializationFuncs() ([]*codegen.Method
jen.List(
jen.Id("p"),
jen.Err(),
).Op(":=").Id(p.elementTypeGenerator().deserializeFnName()).Call(
).Op(":=").Id(p.elementTypeGenerator().DeserializeFnName()).Call(
jen.Id(variable),
),
jen.Err().Op("!=").Nil(),
@ -323,8 +323,8 @@ func (p *NonFunctionalPropertyGenerator) serializationFuncs() ([]*codegen.Method
}
deserialize := []*codegen.Function{
codegen.NewCommentedFunction(
p.packageName(),
p.deserializeFnName(),
p.PackageName(),
p.DeserializeFnName(),
[]jen.Code{jen.Id("m").Map(jen.String()).Interface()},
[]jen.Code{jen.Id(p.StructName()), jen.Error()},
[]jen.Code{
@ -364,7 +364,7 @@ func (p *NonFunctionalPropertyGenerator) serializationFuncs() ([]*codegen.Method
jen.Nil(),
),
},
jen.Commentf("%s creates a %q property from an interface representation that has been unmarshalled from a text or binary format.", p.deserializeFnName(), p.PropertyName()),
jen.Commentf("%s creates a %q property from an interface representation that has been unmarshalled from a text or binary format.", p.DeserializeFnName(), p.PropertyName()),
),
}
return serialize, deserialize

ファイルの表示

@ -2,8 +2,8 @@ package props
import (
"fmt"
"github.com/cjslep/activity/tools/exp/codegen"
"github.com/dave/jennifer/jen"
"github.com/go-fed/activity/tools/exp/codegen"
)
const (
@ -59,13 +59,12 @@ type Identifier struct {
// deserialize such types, compare the types, and other meta-information to use
// during Go code generation.
type Kind struct {
Name Identifier
ConcreteKind string
Nilable bool
HasNaturalLanguageMap bool
SerializeFn codegen.Function
DeserializeFn codegen.Function
LessFn codegen.Function
Name Identifier
ConcreteKind string
Nilable bool
SerializeFn *codegen.Function
DeserializeFn *codegen.Function
LessFn *codegen.Function
}
// PropertyGenerator is a common base struct used in both Functional and
@ -74,7 +73,10 @@ type Kind struct {
//
// It also properly handles the concept of generating Go code for property
// iterators, which are needed for NonFunctional properties.
//
// TODO: Make this type private
type PropertyGenerator struct {
// TODO: Make these private
Package string
Name Identifier
Kinds []Kind
@ -82,11 +84,33 @@ type PropertyGenerator struct {
asIterator bool
}
// packageName returns the name of the package for the property to be generated.
func (p *PropertyGenerator) packageName() string {
// PackageName returns the name of the package for the property to be generated.
func (p *PropertyGenerator) PackageName() string {
return p.Package
}
// SetKindFns allows TypeGenerators to later notify this Property what functions
// to use when generating the serialization code.
//
// The name parameter must match the LowerName of an Identifier.
//
// This feels very hacky.
func (p *PropertyGenerator) SetKindFns(name string, ser, deser, less *codegen.Function) error {
for i, kind := range p.Kinds {
if kind.Name.LowerName == name {
if kind.SerializeFn != nil || kind.DeserializeFn != nil || kind.LessFn != nil {
return fmt.Errorf("property kind already has serialization functions set for %q", name)
}
kind.SerializeFn = ser
kind.DeserializeFn = deser
kind.LessFn = less
p.Kinds[i] = kind
return nil
}
}
return fmt.Errorf("cannot find property kind %q", name)
}
// StructName returns the name of the type, which may or may not be a struct,
// to generate.
func (p *PropertyGenerator) StructName() string {
@ -103,9 +127,9 @@ func (p *PropertyGenerator) PropertyName() string {
return p.Name.LowerName
}
// deserializeFnName returns the identifier of the function that deserializes
// DeserializeFnName returns the identifier of the function that deserializes
// raw JSON into the generated Go type.
func (p *PropertyGenerator) deserializeFnName() string {
func (p *PropertyGenerator) DeserializeFnName() string {
if p.asIterator {
return fmt.Sprintf("%s%s", deserializeIteratorMethod, p.Name.CamelName)
}
@ -177,7 +201,7 @@ func (p *PropertyGenerator) clearMethodName() string {
func (p *PropertyGenerator) commonMethods() []*codegen.Method {
return []*codegen.Method{
codegen.NewCommentedValueMethod(
p.packageName(),
p.PackageName(),
nameMethod,
p.StructName(),
/*params=*/ nil,

ファイルの表示

@ -1,18 +1,27 @@
package types
package props
import (
"fmt"
"github.com/cjslep/activity/tools/exp/codegen"
"github.com/dave/jennifer/jen"
"github.com/go-fed/activity/tools/exp/codegen"
"sort"
"strings"
"sync"
)
// TODO: Prevent circular dependency by somehow abstracting the requisite
// functions between props and types.
const (
typeInterfaceName = "Type"
extendedByMethod = "IsExtendedBy"
extendsMethod = "Extends"
disjointWithMethod = "IsDisjointWith"
nameMethod = "Name"
typeInterfaceName = "Type"
extendedByMethod = "IsExtendedBy"
extendingMethod = "IsExtending"
extendsMethod = "Extends"
disjointWithMethod = "IsDisjointWith"
typeNameMethod = "Name"
serializeMethodName = "Serialize"
deserializeFnName = "Deserialize"
lessFnName = "Less"
)
// TypeInterface returns the Type Interface that is needed for ActivityStream
@ -22,10 +31,10 @@ func TypeInterface(pkg string) *codegen.Interface {
comment := fmt.Sprintf("%s represents an ActivityStreams type.", typeInterfaceName)
funcs := []codegen.FunctionSignature{
{
Name: nameMethod,
Name: typeNameMethod,
Params: nil,
Ret: []jen.Code{jen.String()},
Comment: fmt.Sprintf("%s returns the ActivityStreams type name.", nameMethod),
Comment: fmt.Sprintf("%s returns the ActivityStreams type name.", typeNameMethod),
},
}
return codegen.NewInterface(pkg, typeInterfaceName, funcs, comment)
@ -33,21 +42,25 @@ func TypeInterface(pkg string) *codegen.Interface {
// Property represents a property of an ActivityStreams type.
type Property interface {
PackageName() string
PropertyName() string
StructName() string
SetKindFns(name string, ser, deser, less *codegen.Function) error
DeserializeFnName() string
}
// TypeGenerator represents an ActivityStream type definition to generate in Go.
type TypeGenerator struct {
packageName string
typeName string
comment string
properties map[string]Property
extends []*TypeGenerator
disjoint []*TypeGenerator
extendedBy []*TypeGenerator
cacheOnce sync.Once
cachedStruct *codegen.Struct
packageName string
typeName string
comment string
properties map[string]Property
withoutProperties map[string]Property
extends []*TypeGenerator
disjoint []*TypeGenerator
extendedBy []*TypeGenerator
cacheOnce sync.Once
cachedStruct *codegen.Struct
}
// NewTypeGenerator creates a new generator for a specific ActivityStreams Core
@ -59,16 +72,20 @@ type TypeGenerator struct {
//
// All TypeGenerators must be created before the Definition method is called, to
// ensure that type extension, in the inheritence sense, is properly set up.
// Additionally, all properties whose range is this type should have their
// SetKindFns method called with this TypeGenerator's KindSerializationFuncs for
// all code generation to correctly reference each other.
func NewTypeGenerator(packageName, typeName, comment string,
properties []Property,
properties, withoutProperties []Property,
extends, disjoint []*TypeGenerator) (*TypeGenerator, error) {
t := &TypeGenerator{
packageName: packageName,
typeName: typeName,
comment: comment,
properties: make(map[string]Property, len(properties)),
extends: extends,
disjoint: disjoint,
packageName: packageName,
typeName: typeName,
comment: comment,
properties: make(map[string]Property, len(properties)),
withoutProperties: make(map[string]Property, len(withoutProperties)),
extends: extends,
disjoint: disjoint,
}
for _, property := range properties {
if _, has := t.properties[property.PropertyName()]; has {
@ -76,6 +93,12 @@ func NewTypeGenerator(packageName, typeName, comment string,
}
t.properties[property.PropertyName()] = property
}
for _, wop := range withoutProperties {
if _, has := t.withoutProperties[wop.PropertyName()]; has {
return nil, fmt.Errorf("type already has withoutproperty with name %q", wop.PropertyName())
}
t.withoutProperties[wop.PropertyName()] = wop
}
// Complete doubly-linked extends/extendedBy lists.
for _, ext := range extends {
ext.extendedBy = append(ext.extendedBy, t)
@ -83,6 +106,11 @@ func NewTypeGenerator(packageName, typeName, comment string,
return t, nil
}
// AddDisjoint adds another TypeGenerator that is disjoint to this one.
func (t *TypeGenerator) AddDisjoint(o *TypeGenerator) {
t.disjoint = append(t.disjoint, o)
}
// Comment returns the comment for this type.
func (t *TypeGenerator) Comment() string {
return t.comment
@ -111,6 +139,18 @@ func (t *TypeGenerator) Disjoint() []*TypeGenerator {
return t.disjoint
}
// Properties returns the Properties of this type, mapped by their property
// name.
func (t *TypeGenerator) Properties() map[string]Property {
return t.properties
}
// WithoutProperties returns the properties that do not apply to this type,
// mapped by their property name.
func (t *TypeGenerator) WithoutProperties() map[string]Property {
return t.withoutProperties
}
// extendsFnName determines the name of the Extends function, which
// determines if this ActivityStreams type extends another one.
func (t *TypeGenerator) extendsFnName() string {
@ -132,58 +172,117 @@ func (t *TypeGenerator) disjointWithFnName() string {
// Definition generates the golang code for this ActivityStreams type.
func (t *TypeGenerator) Definition() *codegen.Struct {
t.cacheOnce.Do(func() {
members := make([]jen.Code, 0, len(t.properties))
for name, property := range t.properties {
members = append(members, jen.Id(name).Id(property.StructName()))
}
members := t.members()
m := t.serializationMethod()
ser, deser, less := t.KindSerializationFuncs()
extendsFn, extendsMethod := t.extendsDefinition()
t.cachedStruct = codegen.NewStruct(
jen.Commentf(t.Comment()),
t.TypeName(),
[]*codegen.Method{
t.nameDefinition(),
t.extendsDefinition(),
extendsMethod,
m,
},
[]*codegen.Function{
t.extendedByDefinition(),
extendsFn,
t.disjointWithDefinition(),
ser,
deser,
less,
},
members)
})
return t.cachedStruct
}
func (t *TypeGenerator) allProperties() map[string]Property {
p := t.properties
// Properties of parents that are extended, minus DoesNotApplyTo
var extends []*TypeGenerator
extends = t.getAllParentExtends(extends, t)
for _, ext := range t.extends {
for k, v := range ext.Properties() {
p[k] = v
}
}
for _, ext := range t.extends {
for k, _ := range ext.WithoutProperties() {
delete(p, k)
}
}
return p
}
// sortedProperty is a slice of Properties that implements the Sort interface.
type sortedProperty []Property
func (s sortedProperty) Less(i, j int) bool {
return s[i].PropertyName() < s[j].PropertyName()
}
func (s sortedProperty) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s sortedProperty) Len() int {
return len(s)
}
func (t *TypeGenerator) members() (members []jen.Code) {
p := t.allProperties()
// Sort the properties for readability
sortedMembers := make(sortedProperty, 0, len(p))
for _, property := range p {
sortedMembers = append(sortedMembers, property)
}
sort.Sort(sortedMembers)
// Convert to jen.Code
members = make([]jen.Code, 0, len(p))
for _, property := range sortedMembers {
members = append(members, jen.Id(strings.Title(property.PropertyName())).Qual(property.PackageName(), property.StructName()))
}
return
}
// nameDefinition generates the golang method for returning the ActivityStreams
// type name.
func (t *TypeGenerator) nameDefinition() *codegen.Method {
return codegen.NewCommentedValueMethod(
t.packageName,
nameMethod,
typeNameMethod,
t.TypeName(),
/*params=*/ nil,
[]jen.Code{jen.String()},
[]jen.Code{
jen.Return(jen.Lit(t.TypeName())),
},
jen.Commentf("%s returns the name of this type.", nameMethod))
jen.Commentf("%s returns the name of this type.", typeNameMethod))
}
// getAllParentExtends recursivley determines all the parent types that this
// getAllParentExtends recursively determines all the parent types that this
// type extends from.
func (t *TypeGenerator) getAllParentExtends(s []string, tg *TypeGenerator) {
func (t *TypeGenerator) getAllParentExtends(s []*TypeGenerator, tg *TypeGenerator) []*TypeGenerator {
for _, e := range tg.Extends() {
s = append(s, e.TypeName())
t.getAllParentExtends(s, e)
s = append(s, e)
s = append(s, t.getAllParentExtends(s, e)...)
}
return s
}
// extendsDefinition generates the golang method for determining if this
// extendsDefinition generates the golang function for determining if this
// ActivityStreams type extends another type. It requires the Type interface.
func (t *TypeGenerator) extendsDefinition() *codegen.Method {
var extendNames []string
t.getAllParentExtends(extendNames, t)
func (t *TypeGenerator) extendsDefinition() (*codegen.Function, *codegen.Method) {
var extends []*TypeGenerator
extends = t.getAllParentExtends(extends, t)
extendNames := make(map[string]struct{}, len(extends))
for _, ext := range extends {
extendNames[ext.TypeName()] = struct{}{}
}
extensions := make([]jen.Code, len(extendNames))
for i, e := range extendNames {
extensions[i] = jen.Lit(e)
for e := range extendNames {
extensions = append(extensions, jen.Lit(e))
}
impl := []jen.Code{jen.Comment("Shortcut implementation: this does not extend anything."), jen.Return(jen.False())}
if len(extensions) > 0 {
@ -193,21 +292,33 @@ func (t *TypeGenerator) extendsDefinition() *codegen.Method {
jen.Id("ext"),
).Op(":=").Range().Id("extensions")).Block(
jen.If(
jen.Id("ext").Op("==").Id("other").Dot(nameMethod).Call(),
jen.Id("ext").Op("==").Id("other").Dot(typeNameMethod).Call(),
).Block(
jen.Return(jen.True()),
),
),
jen.Return(jen.False())}
}
return codegen.NewCommentedValueMethod(
f := codegen.NewCommentedFunction(
t.packageName,
t.extendsFnName(),
t.TypeName(),
[]jen.Code{jen.Id("other").Id(typeInterfaceName)},
[]jen.Code{jen.Bool()},
impl,
jen.Commentf("%s returns true if the %s type extends from the other type.", t.extendsFnName(), t.TypeName()))
m := codegen.NewCommentedValueMethod(
t.packageName,
extendingMethod,
t.TypeName(),
[]jen.Code{jen.Id("other").Id(typeInterfaceName)},
[]jen.Code{jen.Bool()},
[]jen.Code{
jen.Return(
jen.Id(t.extendsFnName()).Call(jen.Id("other")),
),
},
jen.Commentf("%s returns true if the %s type extends from the other type.", extendingMethod, t.TypeName()))
return f, m
}
// getAllChildrenExtendBy recursivley determines all the child types that this
@ -237,7 +348,7 @@ func (t *TypeGenerator) extendedByDefinition() *codegen.Function {
jen.Id("ext"),
).Op(":=").Range().Id("extensions")).Block(
jen.If(
jen.Id("ext").Op("==").Id("other").Dot(nameMethod).Call(),
jen.Id("ext").Op("==").Id("other").Dot(typeNameMethod).Call(),
).Block(
jen.Return(jen.True()),
),
@ -267,6 +378,8 @@ func (t *TypeGenerator) getAllDisjointWith(s []string) {
// another ActivityStreams type is disjoint with this type. It requires the Type
// interface.
func (t *TypeGenerator) disjointWithDefinition() *codegen.Function {
// TODO: Inherit disjoint from parent and the other extended types of
// the other.
var disjointNames []string
t.getAllDisjointWith(disjointNames)
disjointWith := make([]jen.Code, len(disjointNames))
@ -281,7 +394,7 @@ func (t *TypeGenerator) disjointWithDefinition() *codegen.Function {
jen.Id("disjoint"),
).Op(":=").Range().Id("disjointWith")).Block(
jen.If(
jen.Id("disjoint").Op("==").Id("other").Dot(nameMethod).Call(),
jen.Id("disjoint").Op("==").Id("other").Dot(typeNameMethod).Call(),
).Block(
jen.Return(jen.True()),
),
@ -296,3 +409,79 @@ func (t *TypeGenerator) disjointWithDefinition() *codegen.Function {
impl,
jen.Commentf("%s returns true if the other provided type is disjoint with the %s type.", t.disjointWithFnName(), t.TypeName()))
}
// serializationMethod returns the method needed to serialize a TypeGenerator as
// a property.
func (t *TypeGenerator) serializationMethod() (ser *codegen.Method) {
ser = codegen.NewCommentedValueMethod(
t.packageName,
serializeMethodName,
t.TypeName(),
/*params=*/ nil,
[]jen.Code{jen.Interface(), jen.Error()},
[]jen.Code{
// TODO
jen.Commentf("TODO: Serialization code for %s", t.TypeName()),
},
jen.Commentf("%s converts this into an interface representation suitable for marshalling into a text or binary format.", serializeMethodName))
return
}
// KindSerializationFuncs returns free function references that can be used to
// treat a TypeGenerator as another property's Kind.
func (t *TypeGenerator) KindSerializationFuncs() (ser, deser, less *codegen.Function) {
serName := fmt.Sprintf("%s%s", serializeMethodName, t.TypeName())
ser = codegen.NewCommentedFunction(
t.packageName,
serName,
[]jen.Code{jen.Id("s").Id(t.TypeName())},
[]jen.Code{jen.Interface(), jen.Error()},
[]jen.Code{
jen.Return(
jen.Id("s").Dot(serializeMethodName).Call(),
),
},
jen.Commentf("%s calls %s on the %s type.", serName, serializeMethodName, t.TypeName()))
deserName := fmt.Sprintf("%s%s", deserializeFnName, t.TypeName())
deserCode := jen.Empty()
for name, prop := range t.allProperties() {
deserCode = deserCode.Add(
jen.If(
jen.List(
jen.Id("p"),
jen.Err(),
).Op(":=").Qual(prop.PackageName(), prop.DeserializeFnName()).Call(jen.Id("m")),
jen.Err().Op("!=").Nil(),
).Block(
jen.Return(jen.Nil(), jen.Err()),
).Else().Block(
jen.Id(codegen.This()).Dot(strings.Title(name)).Op("=").Op("*").Id("p"),
).Line())
}
deser = codegen.NewCommentedFunction(
t.packageName,
deserName,
[]jen.Code{jen.Id("m").Map(jen.String()).Interface()},
[]jen.Code{jen.Op("*").Id(t.TypeName()), jen.Error()},
[]jen.Code{
jen.Id(codegen.This()).Op(":=").Op("&").Id(t.TypeName()).Values(),
deserCode,
jen.Return(jen.Id(codegen.This()), jen.Nil()),
},
jen.Commentf("%s creates a %s from a map representation that has been unmarshalled from a text or binary format.", deserName, t.TypeName()))
lessName := fmt.Sprintf("%s%s", lessFnName, t.TypeName())
less = codegen.NewCommentedFunction(
t.packageName,
lessName,
[]jen.Code{
jen.Id("i"),
jen.Id("j").Op("*").Id(t.TypeName()),
},
[]jen.Code{jen.Bool()},
[]jen.Code{
// TODO
jen.Commentf("TODO: Less code for %s", t.TypeName()),
},
jen.Commentf("%s computes which %s is lesser, with an arbitrary but stable determination", lessName, t.TypeName()))
return
}

ファイルの表示

@ -3,6 +3,7 @@ package rdf
import (
"bytes"
"fmt"
"github.com/cjslep/activity/tools/exp/codegen"
"net/url"
)
@ -16,7 +17,17 @@ import (
// details.
type ParsedVocabulary struct {
Vocab Vocabulary
References map[string]Vocabulary
References map[string]*Vocabulary
}
func (p *ParsedVocabulary) GetReference(uri string) *Vocabulary {
if p.References == nil {
p.References = make(map[string]*Vocabulary, 0)
}
if _, ok := p.References[uri]; !ok {
p.References[uri] = &Vocabulary{}
}
return p.References[uri]
}
func (p ParsedVocabulary) String() string {
@ -89,6 +100,9 @@ type VocabularyValue struct {
URI *url.URL
DefinitionType string
Zero string
SerializeFn *codegen.Function
DeserializeFn *codegen.Function
LessFn *codegen.Function
}
func (v VocabularyValue) String() string {
@ -99,7 +113,7 @@ func (v *VocabularyValue) SetName(s string) {
v.Name = s
}
func (v *VocabularyValue) GetName() string {
func (v VocabularyValue) GetName() string {
return v.Name
}
@ -111,7 +125,7 @@ func (v *VocabularyValue) SetURI(s string) error {
var (
_ NameSetter = &VocabularyValue{}
_ nameGetter = &VocabularyValue{}
_ NameGetter = &VocabularyValue{}
_ URISetter = &VocabularyValue{}
)
@ -121,21 +135,21 @@ type VocabularyType struct {
URI *url.URL
Notes string
DisjointWith []VocabularyReference
Extends []VocabularyReference // TODO: Object improperly extends Link
Properties []VocabularyReference // TODO: Check for duplication
WithoutProperties []VocabularyReference // TODO: Missing for IntransitiveActivity
Extends []VocabularyReference
Examples []VocabularyExample
Properties []VocabularyReference
WithoutProperties []VocabularyReference
}
func (v VocabularyType) String() string {
return fmt.Sprintf("Type=%s,%s,%s", v.Name, v.URI, v.Notes)
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)
}
func (v *VocabularyType) SetName(s string) {
v.Name = s
}
func (v *VocabularyType) GetName() string {
func (v VocabularyType) GetName() string {
return v.Name
}
@ -155,7 +169,7 @@ func (v *VocabularyType) AddExample(e *VocabularyExample) {
var (
_ NameSetter = &VocabularyType{}
_ nameGetter = &VocabularyType{}
_ NameGetter = &VocabularyType{}
_ URISetter = &VocabularyType{}
_ NotesSetter = &VocabularyType{}
_ ExampleAdder = &VocabularyType{}
@ -164,12 +178,13 @@ var (
// VocabularyProperty represents a single ActivityStream property type in a
// vocabulary.
type VocabularyProperty struct {
Name string
URI *url.URL
Notes string
Domain []VocabularyReference
Range []VocabularyReference
Examples []VocabularyExample
Name string
URI *url.URL
Notes string
Domain []VocabularyReference
Range []VocabularyReference
DoesNotApplyTo []VocabularyReference
Examples []VocabularyExample
// SubpropertyOf is ignorable as long as data is set up correctly TODO: Is this still correct?
SubpropertyOf VocabularyReference // Must be a VocabularyProperty
Functional bool
@ -177,14 +192,14 @@ type VocabularyProperty struct {
}
func (v VocabularyProperty) String() string {
return fmt.Sprintf("Property=%s,%s,%s,%s,%s", v.Name, v.URI, v.Notes, v.Functional, v.NaturalLanguageMap)
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)
}
func (v *VocabularyProperty) SetName(s string) {
v.Name = s
}
func (v *VocabularyProperty) GetName() string {
func (v VocabularyProperty) GetName() string {
return v.Name
}
@ -204,7 +219,7 @@ func (v *VocabularyProperty) AddExample(e *VocabularyExample) {
var (
_ NameSetter = &VocabularyProperty{}
_ nameGetter = &VocabularyProperty{}
_ NameGetter = &VocabularyProperty{}
_ URISetter = &VocabularyProperty{}
_ NotesSetter = &VocabularyProperty{}
_ ExampleAdder = &VocabularyProperty{}
@ -218,11 +233,15 @@ type VocabularyExample struct {
Example interface{}
}
func (v VocabularyExample) String() string {
return fmt.Sprintf("VocabularyExample: %s,%s,%s", v.Name, v.URI, v.Example)
}
func (v *VocabularyExample) SetName(s string) {
v.Name = s
}
func (v *VocabularyExample) GetName() string {
func (v VocabularyExample) GetName() string {
return v.Name
}
@ -234,7 +253,7 @@ func (v *VocabularyExample) SetURI(s string) error {
var (
_ NameSetter = &VocabularyExample{}
_ nameGetter = &VocabularyExample{}
_ NameGetter = &VocabularyExample{}
_ URISetter = &VocabularyExample{}
)
@ -247,11 +266,15 @@ type VocabularyReference struct {
Vocab string // If present, must match key in ParsedVocabulary.References
}
func (v VocabularyReference) String() string {
return fmt.Sprintf("VocabularyReference: %s,%s,%s", v.Name, v.URI, v.Vocab)
}
func (v *VocabularyReference) SetName(s string) {
v.Name = s
}
func (v *VocabularyReference) GetName() string {
func (v VocabularyReference) GetName() string {
return v.Name
}
@ -263,6 +286,6 @@ func (v *VocabularyReference) SetURI(s string) error {
var (
_ NameSetter = &VocabularyReference{}
_ nameGetter = &VocabularyReference{}
_ NameGetter = &VocabularyReference{}
_ URISetter = &VocabularyReference{}
)

ファイルの表示

@ -11,6 +11,13 @@ const (
IdActivityStreamsSpec = "id"
ContainerSpec = "@container"
IndexSpec = "@index"
// ActivityStreams specifically disallows the 'object' property on
// certain IntransitiveActivity and subtypes. There is no RDF mechanism
// to describe this. So this is a stupid hack, based on the assumption
// that no one -- W3C or otherwise -- will name a reserved word with a
// "@wtf_" prefix due to the reserved '@', the use of the unprofessional
// 'wtf', and a style-breaking underscore.
withoutPropertySpec = "@wtf_without_property"
)
// jsonLDNodes contains the well-known set of nodes as defined by the JSON-LD
@ -55,6 +62,12 @@ func jsonLDNodes(r *RDFRegistry) []RDFNode {
Name: IndexSpec,
Delegate: &IndexLD{},
},
&AliasedDelegate{
Spec: "",
Alias: "",
Name: withoutPropertySpec,
Delegate: &withoutProperty{},
},
}
}
@ -149,3 +162,32 @@ func (i *IndexLD) Exit(key string, ctx *ParsingContext) (bool, error) {
func (i *IndexLD) Apply(key string, value interface{}, ctx *ParsingContext) (bool, error) {
return true, nil
}
var _ RDFNode = &withoutProperty{}
type withoutProperty struct{}
func (w *withoutProperty) Enter(key string, ctx *ParsingContext) (bool, error) {
ctx.Push()
ctx.Current = &VocabularyReference{}
return true, nil
}
func (w *withoutProperty) Exit(key string, ctx *ParsingContext) (bool, error) {
i := ctx.Current
ctx.Pop()
vr, ok := i.(*VocabularyReference)
if !ok {
return true, fmt.Errorf("hacky withoutProperty exit did not get *rdf.VocabularyReference")
}
vp, ok := ctx.Current.(*VocabularyProperty)
if !ok {
return true, fmt.Errorf("hacky withoutProperty exit Current is not *rdf.VocabularyProperty")
}
vp.DoesNotApplyTo = append(vp.DoesNotApplyTo, *vr)
return true, nil
}
func (w *withoutProperty) Apply(key string, value interface{}, ctx *ParsingContext) (bool, error) {
return true, fmt.Errorf("hacky withoutProperty cannot be applied")
}

ファイルの表示

@ -2,17 +2,61 @@ package rdf
import (
"fmt"
"github.com/cjslep/activity/tools/exp/codegen"
"github.com/dave/jennifer/jen"
"net/url"
"strings"
)
const (
rdfSpec = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
langstringSpec = "langstring"
langstringSpec = "langString"
propertySpec = "Property"
valueSpec = "value"
)
type RDFOntology struct{}
func SerializeValueFunction(pkg, valueName string,
concreteType jen.Code,
impl []jen.Code) *codegen.Function {
name := fmt.Sprintf("Serialize%s", strings.Title(valueName))
return codegen.NewCommentedFunction(
pkg,
name,
[]jen.Code{jen.Id(codegen.This()).Add(concreteType)},
[]jen.Code{jen.Interface(), jen.Error()},
impl,
jen.Commentf("%s converts a %s value to an interface representation suitable for marshalling into a text or binary format.", name, valueName))
}
func DeserializeValueFunction(pkg, valueName string,
concreteType jen.Code,
impl []jen.Code) *codegen.Function {
name := fmt.Sprintf("Deserialize%s", strings.Title(valueName))
return codegen.NewCommentedFunction(
pkg,
name,
[]jen.Code{jen.Id(codegen.This()).Interface()},
[]jen.Code{concreteType, jen.Error()},
impl,
jen.Commentf("%s creates %s value from an interface representation that has been unmarshalled from a text or binary format.", name, valueName))
}
func LessFunction(pkg, valueName string,
concreteType jen.Code,
impl []jen.Code) *codegen.Function {
name := fmt.Sprintf("Less%s", strings.Title(valueName))
return codegen.NewCommentedFunction(
pkg,
name,
[]jen.Code{jen.List(jen.Id("lhs"), jen.Id("rhs")).Add(concreteType)},
[]jen.Code{jen.Bool()},
impl,
jen.Commentf("%s returns true if the left %s value is less than the right value.", name, valueName))
}
type RDFOntology struct {
Package string
alias string
}
func (o *RDFOntology) SpecURI() string {
return rdfSpec
@ -23,12 +67,13 @@ func (o *RDFOntology) Load() ([]RDFNode, error) {
}
func (o *RDFOntology) LoadAsAlias(s string) ([]RDFNode, error) {
o.alias = s
return []RDFNode{
&AliasedDelegate{
Spec: rdfSpec,
Alias: s,
Name: langstringSpec,
Delegate: &langstring{},
Delegate: &langstring{pkg: o.Package, alias: o.alias},
},
&AliasedDelegate{
Spec: rdfSpec,
@ -36,12 +81,6 @@ func (o *RDFOntology) LoadAsAlias(s string) ([]RDFNode, error) {
Name: propertySpec,
Delegate: &property{},
},
&AliasedDelegate{
Spec: rdfSpec,
Alias: s,
Name: valueSpec,
Delegate: &value{},
},
}, nil
}
@ -53,7 +92,7 @@ func (o *RDFOntology) LoadSpecificAsAlias(alias, name string) ([]RDFNode, error)
Spec: "",
Alias: "",
Name: alias,
Delegate: &langstring{},
Delegate: &langstring{pkg: o.Package, alias: o.alias},
},
}, nil
case propertySpec:
@ -65,15 +104,6 @@ func (o *RDFOntology) LoadSpecificAsAlias(alias, name string) ([]RDFNode, error)
Delegate: &property{},
},
}, nil
case valueSpec:
return []RDFNode{
&AliasedDelegate{
Spec: "",
Alias: "",
Name: alias,
Delegate: &value{},
},
}, nil
}
return nil, fmt.Errorf("rdf ontology cannot find %q to make alias %q", name, alias)
}
@ -86,18 +116,19 @@ func (o *RDFOntology) GetByName(name string) (RDFNode, error) {
name = strings.TrimPrefix(name, o.SpecURI())
switch name {
case langstringSpec:
return &langstring{}, nil
return &langstring{pkg: o.Package, alias: o.alias}, nil
case propertySpec:
return &property{}, nil
case valueSpec:
return &value{}, nil
}
return nil, fmt.Errorf("rdf ontology could not find node for name %s", name)
}
var _ RDFNode = &langstring{}
type langstring struct{}
type langstring struct {
alias string
pkg string
}
func (l *langstring) Enter(key string, ctx *ParsingContext) (bool, error) {
return true, fmt.Errorf("rdf langstring cannot be entered")
@ -108,8 +139,47 @@ func (l *langstring) Exit(key string, ctx *ParsingContext) (bool, error) {
}
func (l *langstring) Apply(key string, value interface{}, ctx *ParsingContext) (bool, error) {
// TODO: Act as value
return true, fmt.Errorf("rdf langstring cannot be applied")
for k, p := range ctx.Result.Vocab.Properties {
for _, ref := range p.Range {
if ref.Name == langstringSpec && ref.Vocab == l.alias {
p.NaturalLanguageMap = true
ctx.Result.Vocab.Properties[k] = p
break
}
}
}
u, e := url.Parse(rdfSpec + langstringSpec)
if e != nil {
return true, e
}
e = ctx.Result.GetReference(rdfSpec).SetValue(langstringSpec, &VocabularyValue{
Name: langstringSpec,
URI: u,
DefinitionType: "map[string]string",
Zero: "nil",
SerializeFn: SerializeValueFunction(
l.pkg,
langstringSpec,
jen.Map(jen.String()).String(),
[]jen.Code{
// TODO
}),
DeserializeFn: DeserializeValueFunction(
l.pkg,
langstringSpec,
jen.Map(jen.String()).String(),
[]jen.Code{
// TODO
}),
LessFn: LessFunction(
l.pkg,
langstringSpec,
jen.Map(jen.String()).String(),
[]jen.Code{
// TODO
}),
})
return true, e
}
var _ RDFNode = &property{}
@ -135,20 +205,3 @@ func (p *property) Apply(key string, value interface{}, ctx *ParsingContext) (bo
ctx.Current = &VocabularyProperty{}
return true, nil
}
var _ RDFNode = &value{}
type value struct{}
func (v *value) Enter(key string, ctx *ParsingContext) (bool, error) {
return true, fmt.Errorf("rdf value cannot be entered")
}
func (v *value) Exit(key string, ctx *ParsingContext) (bool, error) {
return true, fmt.Errorf("rdf value cannot be exited")
}
func (v *value) Apply(key string, value interface{}, ctx *ParsingContext) (bool, error) {
// TODO: Act as value
return true, fmt.Errorf("rdf value cannot be applied")
}

ファイルの表示

@ -73,7 +73,7 @@ func (p *ParsingContext) Push() {
func (p *ParsingContext) Pop() {
p.Current = p.Stack[0]
p.Stack = p.Stack[1:]
if ng, ok := p.Current.(nameGetter); ok {
if ng, ok := p.Current.(NameGetter); ok {
p.Name = ng.GetName()
}
}
@ -92,7 +92,7 @@ type NameSetter interface {
SetName(string)
}
type nameGetter interface {
type NameGetter interface {
GetName() string
}
@ -133,12 +133,182 @@ func ParseVocabulary(registry *RDFRegistry, input JSONLD) (vocabulary *ParsedVoc
// parser can understand things like types so that other nodes do not
// hijack processing.
nodes = append(jsonLDNodes(registry), nodes...)
// Step 1: Parse all core data, excluding:
// - Value types
// - Referenced types
// - VocabularyType's 'Properties' and 'WithoutProperties' fields
//
// This is all horrible code but it works, so....
err = apply(nodes, input, ctx)
if err != nil {
return
}
// Step 2: Populate value and referenced types.
err = resolveReferences(registry, ctx)
if err != nil {
return
}
// Step 3: Populate VocabularyType's 'Properties' and
// 'WithoutProperties' fields
err = populatePropertiesOnTypes(ctx)
return
}
// populatePropertiesOnTypes populates the 'Properties' and 'WithoutProperties'
// entries on a VocabularyType.
func populatePropertiesOnTypes(ctx *ParsingContext) error {
for _, p := range ctx.Result.Vocab.Properties {
if err := populatePropertyOnTypes(p, "", ctx); err != nil {
return err
}
}
for vName, ref := range ctx.Result.References {
for _, p := range ref.Properties {
if err := populatePropertyOnTypes(p, vName, ctx); err != nil {
return err
}
}
}
return nil
}
// populatePropertyOnTypes populates the VocabularyType's 'Properties' and
// 'WithoutProperties' fields based on the 'Domain' and 'DoesNotApplyTo'.
func populatePropertyOnTypes(p VocabularyProperty, vocabName string, ctx *ParsingContext) error {
ref := VocabularyReference{
Name: p.Name,
URI: p.URI,
Vocab: vocabName,
}
for _, d := range p.Domain {
if len(d.Vocab) == 0 {
t, ok := ctx.Result.Vocab.Types[d.Name]
if !ok {
return fmt.Errorf("cannot populate property on type %q for desired vocab", d.Name)
}
t.Properties = append(t.Properties, ref)
ctx.Result.Vocab.Types[d.Name] = t
} else {
v, ok := ctx.Result.References[d.Vocab]
if !ok {
return fmt.Errorf("cannot populate property on type for vocab %q", d.Vocab)
}
t, ok := v.Types[d.Name]
if !ok {
return fmt.Errorf("cannot populate property on type %q for vocab %q", d.Name, d.Vocab)
}
t.Properties = append(t.Properties, ref)
v.Types[d.Name] = t
}
}
for _, dna := range p.DoesNotApplyTo {
if len(dna.Vocab) == 0 {
t, ok := ctx.Result.Vocab.Types[dna.Name]
if !ok {
return fmt.Errorf("cannot populate withoutproperty on type %q for desired vocab", dna.Name)
}
t.WithoutProperties = append(t.WithoutProperties, ref)
ctx.Result.Vocab.Types[dna.Name] = t
} else {
v, ok := ctx.Result.References[dna.Vocab]
if !ok {
return fmt.Errorf("cannot populate withoutproperty on type for vocab %q", dna.Vocab)
}
t, ok := v.Types[dna.Name]
if !ok {
return fmt.Errorf("cannot populate withoutproperty on type %q for vocab %q", dna.Name, dna.Vocab)
}
t.WithoutProperties = append(t.WithoutProperties, ref)
v.Types[dna.Name] = t
}
}
return nil
}
// resolveReferences ensures that all references mentioned have been
// successfully parsed, and if not attempts to search the ontologies for any
// values, types, and properties that need to be referenced.
//
// Currently, this is the only way that values are added to the
// ParsedVocabulary.
func resolveReferences(registry *RDFRegistry, ctx *ParsingContext) error {
vocabulary := ctx.Result
for _, t := range vocabulary.Vocab.Types {
for _, ref := range t.DisjointWith {
if err := resolveReference(ref, registry, ctx); err != nil {
return err
}
}
for _, ref := range t.Extends {
if err := resolveReference(ref, registry, ctx); err != nil {
return err
}
}
}
for _, p := range vocabulary.Vocab.Properties {
for _, ref := range p.Domain {
if err := resolveReference(ref, registry, ctx); err != nil {
return err
}
}
for _, ref := range p.Range {
if err := resolveReference(ref, registry, ctx); err != nil {
return err
}
}
for _, ref := range p.DoesNotApplyTo {
if err := resolveReference(ref, registry, ctx); err != nil {
return err
}
}
if len(p.SubpropertyOf.Name) > 0 {
if err := resolveReference(p.SubpropertyOf, registry, ctx); err != nil {
return err
}
}
}
return nil
}
// resolveReference will attempt to resolve the reference by either finding it
// in the known References of the vocabulary, or load it from the registry. Will
// fail if a reference is not found.
func resolveReference(reference VocabularyReference, registry *RDFRegistry, ctx *ParsingContext) error {
name := reference.Name
vocab := &ctx.Result.Vocab
if len(reference.Vocab) > 0 {
name = joinAlias(reference.Vocab, reference.Name)
url, e := registry.ResolveAlias(reference.Vocab)
if e != nil {
return e
}
vocab = ctx.Result.GetReference(url)
}
if _, ok := vocab.Types[reference.Name]; ok {
return nil
} else if _, ok := vocab.Properties[reference.Name]; ok {
return nil
} else if _, ok := vocab.Values[reference.Name]; ok {
return nil
} else if n, e := registry.getNode(name); e != nil {
return e
} else {
applicable, e := n.Apply("", nil, ctx)
if !applicable {
return fmt.Errorf("cannot resolve reference with unapplicable node for %s", reference)
} else if e != nil {
return e
}
return nil
}
}
// apply takes a specification input to populate the ParsingContext, based on
// the capabilities of the RDFNodes created from ontologies.
//
// This function will populate all non-value data in the Vocabulary. It does not
// populate the 'Properties' nor the 'WithoutProperties' fields on any
// VocabularyType.
func apply(nodes []RDFNode, input JSONLD, ctx *ParsingContext) error {
// Hijacked processing: Process the rest of the data in this single
// node.
@ -148,7 +318,6 @@ func apply(nodes []RDFNode, input JSONLD, ctx *ParsingContext) error {
} else {
return err
}
return nil
}
// Special processing: '@type' or 'type' if they are present
if v, ok := input[JSON_LD_TYPE]; ok {

ファイルの表示

@ -41,6 +41,11 @@ func SplitAlias(s string) []string {
}
}
// joinAlias combines a string and prepends an RDF alias to it.
func joinAlias(alias, s string) string {
return fmt.Sprintf("%s%s%s", alias, ALIAS_DELIMITER, s)
}
// Ontology returns different RDF "actions" or "handlers" that are able to
// interpret the schema definitions as actions upon a set of data, specific
// for this ontology.
@ -255,3 +260,12 @@ func (r *RDFRegistry) getNode(s string) (n RDFNode, e error) {
return
}
}
// resolveAlias turns an alias into its full qualifier for the ontology.
func (r *RDFRegistry) ResolveAlias(alias string) (url string, e error) {
var ok bool
if url, ok = r.aliases[alias]; !ok {
e = fmt.Errorf("registry cannot resolve alias %q", alias)
}
return
}

ファイルの表示

@ -3,25 +3,148 @@ package xsd
import (
"fmt"
"github.com/cjslep/activity/tools/exp/rdf"
"github.com/dave/jennifer/jen"
"net/url"
"strings"
)
type XMLOntology struct{}
const (
xmlSpec = "http://www.w3.org/2001/XMLSchema#"
anyURISpec = "anyURI"
dateTimeSpec = "dateTime"
floatSpec = "float"
stringSpec = "string"
booleanSpec = "boolean"
nonNegativeIntegerSpec = "nonNegativeInteger"
durationSpec = "duration"
)
type XMLOntology struct {
Package string
}
func (o *XMLOntology) SpecURI() string {
return "http://www.w3.org/2001/XMLSchema#"
return xmlSpec
}
func (o *XMLOntology) Load() ([]rdf.RDFNode, error) {
return nil, nil
return o.LoadAsAlias("")
}
func (o *XMLOntology) LoadAsAlias(s string) ([]rdf.RDFNode, error) {
return nil, nil
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
}
func (o *XMLOntology) LoadSpecificAsAlias(alias, name string) ([]rdf.RDFNode, error) {
return nil, nil
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)
}
func (o *XMLOntology) LoadElement(name string, payload map[string]interface{}) ([]rdf.RDFNode, error) {
@ -31,7 +154,405 @@ func (o *XMLOntology) LoadElement(name string, payload map[string]interface{}) (
func (o *XMLOntology) GetByName(name string) (rdf.RDFNode, error) {
name = strings.TrimPrefix(name, o.SpecURI())
switch name {
// TODO
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{}
type anyURI struct {
pkg string
}
func (a *anyURI) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd anyURI cannot be entered")
}
func (a *anyURI) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd anyURI cannot be exited")
}
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 {
u, err := url.Parse(xmlSpec + anyURISpec)
if err != nil {
return true, err
}
val := &rdf.VocabularyValue{
Name: anyURISpec,
URI: u,
DefinitionType: "*url.URL",
Zero: "&url.URL{}",
SerializeFn: rdf.SerializeValueFunction(
a.pkg,
anyURISpec,
jen.Op("*").Qual("url", "URL"),
[]jen.Code{
// TODO
}),
DeserializeFn: rdf.DeserializeValueFunction(
a.pkg,
anyURISpec,
jen.Op("*").Qual("url", "URL"),
[]jen.Code{
// TODO
}),
LessFn: rdf.LessFunction(
a.pkg,
anyURISpec,
jen.Op("*").Qual("url", "URL"),
[]jen.Code{
// TODO
}),
}
if err = v.SetValue(anyURISpec, val); err != nil {
return true, err
}
}
return true, nil
}
var _ rdf.RDFNode = &dateTime{}
type dateTime struct {
pkg string
}
func (d *dateTime) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd dateTime cannot be entered")
}
func (d *dateTime) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd dateTime cannot be exited")
}
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 {
u, err := url.Parse(xmlSpec + dateTimeSpec)
if err != nil {
return true, err
}
val := &rdf.VocabularyValue{
Name: dateTimeSpec,
URI: u,
DefinitionType: "time.Time",
Zero: "&time.Time{}",
SerializeFn: rdf.SerializeValueFunction(
d.pkg,
dateTimeSpec,
jen.Qual("time", "Time"),
[]jen.Code{
// TODO
}),
DeserializeFn: rdf.DeserializeValueFunction(
d.pkg,
dateTimeSpec,
jen.Qual("time", "Time"),
[]jen.Code{
// TODO
}),
LessFn: rdf.LessFunction(
d.pkg,
dateTimeSpec,
jen.Qual("time", "Time"),
[]jen.Code{
// TODO
}),
}
if err = v.SetValue(dateTimeSpec, val); err != nil {
return true, err
}
}
return true, nil
}
var _ rdf.RDFNode = &float{}
type float struct {
pkg string
}
func (f *float) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd float cannot be entered")
}
func (f *float) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd float cannot be exited")
}
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 {
u, err := url.Parse(xmlSpec + floatSpec)
if err != nil {
return true, err
}
val := &rdf.VocabularyValue{
Name: floatSpec,
URI: u,
DefinitionType: "float32",
Zero: "0.0",
SerializeFn: rdf.SerializeValueFunction(
f.pkg,
floatSpec,
jen.Id("float32"),
[]jen.Code{
// TODO
}),
DeserializeFn: rdf.DeserializeValueFunction(
f.pkg,
floatSpec,
jen.Id("float32"),
[]jen.Code{
// TODO
}),
LessFn: rdf.LessFunction(
f.pkg,
floatSpec,
jen.Id("float32"),
[]jen.Code{
// TODO
}),
}
if err = v.SetValue(floatSpec, val); err != nil {
return true, err
}
}
return true, nil
}
var _ rdf.RDFNode = &xmlString{}
type xmlString struct {
pkg string
}
func (*xmlString) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd string cannot be entered")
}
func (*xmlString) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd string cannot be exited")
}
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 {
u, err := url.Parse(xmlSpec + stringSpec)
if err != nil {
return true, err
}
val := &rdf.VocabularyValue{
Name: stringSpec,
URI: u,
DefinitionType: "string",
Zero: "\"\"",
SerializeFn: rdf.SerializeValueFunction(
s.pkg,
stringSpec,
jen.Id("string"),
[]jen.Code{
// TODO
}),
DeserializeFn: rdf.DeserializeValueFunction(
s.pkg,
stringSpec,
jen.Id("string"),
[]jen.Code{
// TODO
}),
LessFn: rdf.LessFunction(
s.pkg,
stringSpec,
jen.Id("string"),
[]jen.Code{
// TODO
}),
}
if err = v.SetValue(stringSpec, val); err != nil {
return true, err
}
}
return true, nil
}
var _ rdf.RDFNode = &boolean{}
type boolean struct {
pkg string
}
func (*boolean) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd boolean cannot be entered")
}
func (*boolean) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd boolean cannot be exited")
}
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 {
u, err := url.Parse(xmlSpec + booleanSpec)
if err != nil {
return true, err
}
val := &rdf.VocabularyValue{
Name: booleanSpec,
URI: u,
DefinitionType: "bool",
Zero: "false",
SerializeFn: rdf.SerializeValueFunction(
b.pkg,
booleanSpec,
jen.Id("bool"),
[]jen.Code{
// TODO
}),
DeserializeFn: rdf.DeserializeValueFunction(
b.pkg,
booleanSpec,
jen.Id("bool"),
[]jen.Code{
// TODO
}),
LessFn: rdf.LessFunction(
b.pkg,
booleanSpec,
jen.Id("bool"),
[]jen.Code{
// TODO
}),
}
if err = v.SetValue(booleanSpec, val); err != nil {
return true, err
}
}
return true, nil
}
var _ rdf.RDFNode = &nonNegativeInteger{}
type nonNegativeInteger struct {
pkg string
}
func (*nonNegativeInteger) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd nonNegativeInteger cannot be entered")
}
func (*nonNegativeInteger) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd nonNegativeInteger cannot be exited")
}
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 {
u, err := url.Parse(xmlSpec + nonNegativeIntegerSpec)
if err != nil {
return true, err
}
val := &rdf.VocabularyValue{
Name: nonNegativeIntegerSpec,
URI: u,
DefinitionType: "int",
Zero: "0",
SerializeFn: rdf.SerializeValueFunction(
n.pkg,
nonNegativeIntegerSpec,
jen.Id("int"),
[]jen.Code{
// TODO
}),
DeserializeFn: rdf.DeserializeValueFunction(
n.pkg,
nonNegativeIntegerSpec,
jen.Id("int"),
[]jen.Code{
// TODO
}),
LessFn: rdf.LessFunction(
n.pkg,
nonNegativeIntegerSpec,
jen.Id("int"),
[]jen.Code{
// TODO
}),
}
if err = v.SetValue(nonNegativeIntegerSpec, val); err != nil {
return true, err
}
}
return true, nil
}
var _ rdf.RDFNode = &duration{}
type duration struct {
pkg string
}
func (*duration) Enter(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd duration cannot be entered")
}
func (*duration) Exit(key string, ctx *rdf.ParsingContext) (bool, error) {
return true, fmt.Errorf("xsd duration cannot be exited")
}
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 {
u, err := url.Parse(xmlSpec + durationSpec)
if err != nil {
return true, err
}
val := &rdf.VocabularyValue{
Name: durationSpec,
URI: u,
DefinitionType: "time.Duration",
Zero: "time.Duration(0)",
SerializeFn: rdf.SerializeValueFunction(
d.pkg,
durationSpec,
jen.Qual("time", "Duration"),
[]jen.Code{
// TODO
}),
DeserializeFn: rdf.DeserializeValueFunction(
d.pkg,
durationSpec,
jen.Qual("time", "Duration"),
[]jen.Code{
// TODO
}),
LessFn: rdf.LessFunction(
d.pkg,
durationSpec,
jen.Qual("time", "Duration"),
[]jen.Code{
// TODO
}),
}
if err = v.SetValue(durationSpec, val); err != nil {
return true, err
}
}
return true, nil
}

ファイルの表示

@ -20,8 +20,7 @@
"disjointWith": "owl:disjointWith",
"subPropertyOf": "rdfs:subPropertyOf",
"unionOf": "owl:unionOf",
"url": "schema:URL",
"value": "rdf:value"
"url": "schema:URL"
},
{
"sections": {
@ -1134,11 +1133,6 @@
"name": "Example 1"
},
"notes": "Describes an object of any kind. The Object type serves as the base type for most of the other kinds of objects defined in the Activity Vocabulary, including other Core types such as Activity, IntransitiveActivity, Collection and OrderedCollection.",
"subClassOf": {
"type": "owl:Class",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-link",
"name": "Link"
},
"disjointWith": {
"type": "owl:Class",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-link",
@ -1163,11 +1157,6 @@
"name": "Example 2"
},
"notes": "A Link is an indirect, qualified reference to a resource identified by a URL. The fundamental model for links is established by [ RFC5988]. Many of the properties defined by the Activity Vocabulary allow values that are either instances of Object or Link. When a Link is used, it establishes a qualified relation connecting the subject (the containing object) to the resource identified by the href. Properties of the Link are properties of the reference as opposed to properties of the resource.",
"subClassOf": {
"type": "owl:Class",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-object",
"name": "Object"
},
"disjointWith": {
"type": "owl:Class",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-object",
@ -1364,7 +1353,7 @@
"subClassOf": {
"type": "owl:Class",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-orderedcollection",
"name": "OrderedCollectionCollectionPage"
"name": "CollectionPage"
},
"disjointWith": [],
"name": "OrderedCollectionPage",
@ -1774,7 +1763,7 @@
"isDefinedBy": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-id",
"range": {
"type": "owl:Class",
"unionOf": "https://www.w3.org/TR/activitystreams-vocabulary/anyURI"
"unionOf": "xsd:anyURI"
},
"name": "id",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-id"
@ -1813,7 +1802,7 @@
"isDefinedBy": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-type",
"range": {
"type": "owl:Class",
"unionOf": "https://www.w3.org/TR/activitystreams-vocabulary/anyURI"
"unionOf": "xsd:anyURI"
},
"name": "type",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-type"
@ -2698,11 +2687,18 @@
"isDefinedBy": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-instrument",
"range": {
"type": "owl:Class",
"unionOf": {
"type": "owl:Class",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-object",
"name": "Object | Link"
}
"unionOf": [
{
"type": "owl:Class",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-object",
"name": "Object"
},
{
"type": "owl:Class",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-link",
"name": "Link"
}
]
},
"name": "instrument",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-instrument"
@ -2804,11 +2800,18 @@
"isDefinedBy": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-location",
"range": {
"type": "owl:Class",
"unionOf": {
"type": "owl:Class",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-object",
"name": "Object | Link"
}
"unionOf": [
{
"type": "owl:Class",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-object",
"name": "Object"
},
{
"type": "owl:Class",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-link",
"name": "Link"
}
]
},
"name": "location",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-location"
@ -3022,7 +3025,7 @@
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-link",
"name": "Link"
},
"xsd:datetime",
"xsd:dateTime",
"xsd:boolean"
]
},
@ -3202,16 +3205,18 @@
"unionOf": [
{
"type": "owl:Class",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-activity",
"name": "Activity"
},
{
"type": "owl:Class",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-relationship",
"name": "Relationship"
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-object",
"name": "Object"
}
]
},
"@wtf_without_property": [
{
"type": "owl:Class",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-intransitiveactivity",
"name": "IntransitiveActivity"
}
],
"isDefinedBy": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-object-term",
"range": {
"type": "owl:Class",
@ -3680,7 +3685,7 @@
"range": {
"type": "owl:Class",
"unionOf": [
"xsd:anyuri",
"xsd:anyURI",
{
"type": "owl:Class",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-link",
@ -3820,7 +3825,7 @@
"type": "owl:Class",
"unionOf": [
"xsd:string",
"rdf:langstring"
"rdf:langString"
]
},
"name": "content",
@ -3877,7 +3882,7 @@
"type": "owl:Class",
"unionOf": [
"xsd:string",
"rdf:langstring"
"rdf:langString"
]
},
"name": "name",
@ -3947,7 +3952,7 @@
"isDefinedBy": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-height",
"range": {
"type": "owl:Class",
"unionOf": "xsd:nonnegativeinteger"
"unionOf": "xsd:nonNegativeInteger"
},
"name": "height",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-height"
@ -3981,7 +3986,7 @@
"isDefinedBy": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-href",
"range": {
"type": "owl:Class",
"unionOf": "xsd:anyuri"
"unionOf": "xsd:anyURI"
},
"name": "href",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-href"
@ -4221,7 +4226,7 @@
"isDefinedBy": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-endtime",
"range": {
"type": "owl:Class",
"unionOf": "xsd:datetime"
"unionOf": "xsd:dateTime"
},
"name": "endTime",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-endtime"
@ -4256,7 +4261,7 @@
"isDefinedBy": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-published",
"range": {
"type": "owl:Class",
"unionOf": "xsd:datetime"
"unionOf": "xsd:dateTime"
},
"name": "published",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-published"
@ -4291,7 +4296,7 @@
"isDefinedBy": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-starttime",
"range": {
"type": "owl:Class",
"unionOf": "xsd:datetime"
"unionOf": "xsd:dateTime"
},
"name": "startTime",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-starttime"
@ -4406,7 +4411,7 @@
"isDefinedBy": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-startindex",
"range": {
"type": "owl:Class",
"unionOf": "xsd:nonnegativeinteger"
"unionOf": "xsd:nonNegativeInteger"
},
"name": "startIndex",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-startindex"
@ -4457,7 +4462,7 @@
"type": "owl:Class",
"unionOf": [
"xsd:string",
"rdf:langstring"
"rdf:langString"
]
},
"name": "summary",
@ -4501,7 +4506,7 @@
"isDefinedBy": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-totalitems",
"range": {
"type": "owl:Class",
"unionOf": "xsd:nonnegativeinteger"
"unionOf": "xsd:nonNegativeInteger"
},
"name": "totalItems",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-totalitems"
@ -4538,13 +4543,8 @@
"range": {
"type": "owl:Class",
"unionOf": [
"https://www.w3.org/TR/activitystreams-vocabulary/cm",
"https://www.w3.org/TR/activitystreams-vocabulary/feet",
"https://www.w3.org/TR/activitystreams-vocabulary/inches",
"https://www.w3.org/TR/activitystreams-vocabulary/km",
"https://www.w3.org/TR/activitystreams-vocabulary/m",
"https://www.w3.org/TR/activitystreams-vocabulary/miles",
"xsd:anyuri"
"xsd:string",
"xsd:anyURI"
]
},
"name": "units",
@ -4580,7 +4580,7 @@
"isDefinedBy": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-updated",
"range": {
"type": "owl:Class",
"unionOf": "xsd:datetime"
"unionOf": "xsd:dateTime"
},
"name": "updated",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-updated"
@ -4614,7 +4614,7 @@
"isDefinedBy": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-width",
"range": {
"type": "owl:Class",
"unionOf": "xsd:nonnegativeinteger"
"unionOf": "xsd:nonNegativeInteger"
},
"name": "width",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-width"
@ -4817,7 +4817,7 @@
"isDefinedBy": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-deleted",
"range": {
"type": "owl:Class",
"unionOf": "xsd:datetime"
"unionOf": "xsd:dateTime"
},
"name": "deleted",
"url": "https://www.w3.org/TR/activitystreams-vocabulary/#dfn-deleted"