From 4f47e7fdfa646dd29634ce3680045bd025fcfa33 Mon Sep 17 00:00:00 2001 From: Cory Slep Date: Sat, 5 Jan 2019 16:22:37 +0100 Subject: [PATCH] Clean up Manager generation. - Organize manager function generation into one helper method - Vocabulary name is passed into the type & property generators - Use interface only in the manager - Remove unused flags in the main program --- tools/exp/convert/convert.go | 15 ++- tools/exp/main.go | 21 +--- tools/exp/props/funcprop.go | 4 +- tools/exp/props/manager.go | 216 ++++++++++++--------------------- tools/exp/props/nonfuncprop.go | 4 +- tools/exp/props/property.go | 6 + tools/exp/props/type.go | 19 +-- tools/exp/rdf/data.go | 6 + tools/exp/rdf/parse.go | 4 +- 9 files changed, 123 insertions(+), 172 deletions(-) diff --git a/tools/exp/convert/convert.go b/tools/exp/convert/convert.go index 9087de9..5cf4e14 100644 --- a/tools/exp/convert/convert.go +++ b/tools/exp/convert/convert.go @@ -199,14 +199,14 @@ func (c Converter) convertToFiles(v vocabulary) (f []*File, e error) { Directory: pub.WriteDir(), }) } - // TODO: For Manager - priv := c.VocabularyRoot.PrivatePackage() - file := jen.NewFilePath(priv.Path()) - file.Add(v.Manager.PrivateManager().Definition()) + // Manager + pub := c.VocabularyRoot.PublicPackage() + file := jen.NewFilePath(pub.Path()) + file.Add(v.Manager.Definition().Definition()) f = append(f, &File{ F: file, FileName: "gen_manager.go", - Directory: priv.WriteDir(), + Directory: pub.WriteDir(), }) return } @@ -268,7 +268,7 @@ func (c Converter) convertVocabulary(p *rdf.ParsedVocabulary) (v vocabulary, e e } } v.Manager, e = props.NewManagerGenerator( - *c.VocabularyRoot, + c.VocabularyRoot.PublicPackage(), v.typeArray(), v.funcPropArray(), v.nonFuncPropArray()) @@ -374,6 +374,7 @@ func (c Converter) convertType(t rdf.VocabularyType, } } tg, e = props.NewTypeGenerator( + v.GetName(), pm, name, t.Notes, @@ -400,6 +401,7 @@ func (c Converter) convertFunctionalProperty(p rdf.VocabularyProperty, return } fp = props.NewFunctionalPropertyGenerator( + v.GetName(), pm, c.toIdentifier(p), p.Notes, @@ -423,6 +425,7 @@ func (c Converter) convertNonFunctionalProperty(p rdf.VocabularyProperty, return } nfp = props.NewNonFunctionalPropertyGenerator( + v.GetName(), pm, c.toIdentifier(p), k, diff --git a/tools/exp/main.go b/tools/exp/main.go index 203275b..8a65c84 100644 --- a/tools/exp/main.go +++ b/tools/exp/main.go @@ -36,15 +36,10 @@ func init() { } var ( - input = flag.String("input", "spec.json", "Input JSON-LD specification used to generate Go code.") + input = flag.String("input", "spec.json", "Input JSON-LD specification used to generate Go code.") + vocabName = flag.String("vocab", "ActivityStreams", "The vocabulary name being generated by 'input'.") // TODO: Be more rigorous when applying this. Also, clear the default value I am using for convenience. prefix = flag.String("prefix", "github.com/cjslep/activity/tools/exp/tmp", "Package prefix to use for all generated package paths. This should be the prefix in the GOPATH directory if generating in a subdirectory.") - // 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 @@ -60,13 +55,6 @@ func (l *list) Set(v string) error { } func main() { - // TODO: Use only one kind of flag style. - 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 @@ -79,7 +67,7 @@ func main() { if err != nil { panic(err) } - p, err := rdf.ParseVocabulary(registry, inputJSON) + p, err := rdf.ParseVocabulary(*vocabName, registry, inputJSON) if err != nil { panic(err) } @@ -97,8 +85,6 @@ func main() { 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) } @@ -107,5 +93,4 @@ func main() { } } fmt.Printf("done") - // fmt.Printf("done\n%s\n", p) } diff --git a/tools/exp/props/funcprop.go b/tools/exp/props/funcprop.go index aa6fc36..e619c47 100644 --- a/tools/exp/props/funcprop.go +++ b/tools/exp/props/funcprop.go @@ -22,13 +22,15 @@ type FunctionalPropertyGenerator struct { // // PropertyGenerators shoulf be in the first pass to construct, before types and // other generators are constructed. -func NewFunctionalPropertyGenerator(pm *PackageManager, +func NewFunctionalPropertyGenerator(vocabName string, + pm *PackageManager, name Identifier, comment string, kinds []Kind, hasNaturalLanguageMap bool) *FunctionalPropertyGenerator { return &FunctionalPropertyGenerator{ PropertyGenerator: PropertyGenerator{ + vocabName: vocabName, PackageManager: pm, HasNaturalLanguageMap: hasNaturalLanguageMap, Name: name, diff --git a/tools/exp/props/manager.go b/tools/exp/props/manager.go index eeda4fa..99f0a3f 100644 --- a/tools/exp/props/manager.go +++ b/tools/exp/props/manager.go @@ -4,7 +4,6 @@ import ( "fmt" "github.com/cjslep/activity/tools/exp/codegen" "github.com/dave/jennifer/jen" - "strings" "sync" ) @@ -13,12 +12,16 @@ const ( managerInitVarName = "mgr" ) +// managerInitName returns the package variable name for the manager. func managerInitName() string { return managerInitVarName } -// Generates the ActivityStreamManager that handles the static and/or dynamic -// loading of ActivityStream Core, Extended, and any extension types. +// Generates the ActivityStreamManager that handles the creation of +// ActivityStream Core, Extended, and any extension types. +// +// This is implicitly used by Application code, but Application code usually +// won't need to manually use this Manager. // // This also provides interfaces to break the recursive/cyclic dependencies // between properties and types. The previous version of this tool did not @@ -39,7 +42,7 @@ func managerInitName() string { // determine which types to actually generate, and prune the unneeded types. // This would cut down on the bloat on a per-program basis. type ManagerGenerator struct { - pm PackageManager + pkg Package tg []*TypeGenerator fp []*FunctionalPropertyGenerator nfp []*NonFunctionalPropertyGenerator @@ -58,24 +61,18 @@ type ManagerGenerator struct { // properties and types. type managedMethods struct { deserializor *codegen.Method - // TODO: Delete these? - publicDeserializor *codegen.Method - // Interface for a manager - mIface *codegen.Interface - // Interface(s) for the property/type - ifaces []*codegen.Interface } // NewManagerGenerator creates a new manager system. // // This generator should be constructed in the third pass, after types and // property generators are all constructed. -func NewManagerGenerator(pm PackageManager, +func NewManagerGenerator(pkg Package, tg []*TypeGenerator, fp []*FunctionalPropertyGenerator, nfp []*NonFunctionalPropertyGenerator) (*ManagerGenerator, error) { mg := &ManagerGenerator{ - pm: pm, + pkg: pkg, tg: tg, fp: fp, nfp: nfp, @@ -87,24 +84,17 @@ func NewManagerGenerator(pm PackageManager, // rely on already having this data available in the manager. for _, t := range tg { mg.tgManagedMethods[t] = &managedMethods{ - // TODO: Figure out how to use this instead of the Kind abstraction - deserializor: mg.createPrivateDeserializationMethodForType(t), - publicDeserializor: nil, - mIface: nil, + deserializor: mg.createDeserializationMethodForType(t), } } for _, p := range fp { mg.fpManagedMethods[p] = &managedMethods{ - deserializor: mg.createPrivateDeserializationMethodForFuncProperty(p), - publicDeserializor: nil, - mIface: nil, + deserializor: mg.createDeserializationMethodForFuncProperty(p), } } for _, p := range nfp { mg.nfpManagedMethods[p] = &managedMethods{ - deserializor: mg.createPrivateDeserializationMethodForNonFuncProperty(p), - publicDeserializor: nil, - mIface: nil, + deserializor: mg.createDeserializationMethodForNonFuncProperty(p), } } // Pass 2: Inform the type of this ManagerGenerator so that it can keep @@ -114,37 +104,18 @@ func NewManagerGenerator(pm PackageManager, return nil, e } } - // Pass 3: Populate interfaces of the types and properties, which relies - // on the first pass's data population. - for _, t := range tg { - publicPkg := t.PublicPackage() - mg.tgManagedMethods[t].ifaces = []*codegen.Interface{t.InterfaceDefinition(publicPkg)} - } - for _, p := range fp { - publicPkg := p.GetPublicPackage() - mg.fpManagedMethods[p].ifaces = []*codegen.Interface{p.InterfaceDefinition(publicPkg)} - } - for _, p := range nfp { - publicPkg := p.GetPublicPackage() - mg.nfpManagedMethods[p].ifaces = p.InterfaceDefinitions(publicPkg) - } return mg, nil } -func (m *ManagerGenerator) publicManager() *codegen.Struct { - // TODO - return nil -} - -func (m *ManagerGenerator) privatePackage() Package { - return m.pm.PrivatePackage() -} - -func (m *ManagerGenerator) getPrivateDeserializationMethodForType(t *TypeGenerator) *codegen.Method { +// getDeserializationMethodForType obtains the deserialization method for a +// type. +func (m *ManagerGenerator) getDeserializationMethodForType(t *TypeGenerator) *codegen.Method { return m.tgManagedMethods[t].deserializor } -func (m *ManagerGenerator) getPrivateDeserializationMethodForProperty(p Property) *codegen.Method { +// getDeserializationMethodForProperty obtains the deserialization method for a +// property regardless whether it is functional or non-functional. +func (m *ManagerGenerator) getDeserializationMethodForProperty(p Property) *codegen.Method { switch v := p.(type) { case *FunctionalPropertyGenerator: return m.fpManagedMethods[v].deserializor @@ -155,29 +126,20 @@ func (m *ManagerGenerator) getPrivateDeserializationMethodForProperty(p Property } } -// PrivateManager creates a manager implementation that works with the concrete +// Definition creates a manager implementation that works with the interface // types required by the other PropertyGenerators and TypeGenerators for // serializing and deserializing. // -// Applications should NOT use this private manager as it will force them to -// rely on the concrete type implementations. The public version uses interfaces -// which isolates Application code from this specific go-fed implementation. If -// another alternative to go-fed were to be created, it could target those -// interfaces and be a drop-in replacement for everyone's applications. +// Applications will implicitly use this manager and be isolated from the +// underlying specific go-fed implementation. If another alternative to go-fed +// were to be created, it could target those interfaces and be a drop-in +// replacement for an application. // -// It is necessary to acheive isolation without cyclic dependencies: types and -// properties can each belong in their own package (if desired) to minimize -// binary bloat. This is theoretical until the below TODO is tackled because -// this concrete implementation relies on linking against all of the types and -// properties to behave correctly. There is no simple way around this. But I am -// preparing for the better solution here. -// -// TODO: Analyze a given program, and only generate the types and properties in -// use by the go program. -func (m *ManagerGenerator) PrivateManager() *codegen.Struct { +// It is necessary to have this to acheive isolation without cyclic +// dependencies: types and properties can each belong in their own package (if +// desired) to minimize binary bloat. +func (m *ManagerGenerator) Definition() *codegen.Struct { var methods []*codegen.Method - // TODO: Interface versions of these methods should also be present for - // these specific types. for _, tg := range m.tgManagedMethods { methods = append(methods, tg.deserializor) } @@ -188,7 +150,7 @@ func (m *ManagerGenerator) PrivateManager() *codegen.Struct { methods = append(methods, nfp.deserializor) } s := codegen.NewStruct( - jen.Commentf(fmt.Sprintf("%s privately manages concrete types and deserializations for internal use by generated code. Application code should use the public version instead, which uses interfaces to abstract away the generated code and allow apps to not entirely rely on go-fed should they choose not to.", managerName)), + jen.Commentf(fmt.Sprintf("%s manages interface types and deserializations for use by generated code. Application code implicitly uses this manager at run-time to create concrete implementations of the interfaces.", managerName)), managerName, methods, /*functions=*/ nil, @@ -196,79 +158,44 @@ func (m *ManagerGenerator) PrivateManager() *codegen.Struct { return s } -// createPrivateDeserializationMethodForType creates a new method for the -// private manager. -// -// TODO: Unify these three methods behind some kind of interface. -func (m *ManagerGenerator) createPrivateDeserializationMethodForType(tg *TypeGenerator) *codegen.Method { - dn := tg.deserializationFnName() - pkg := m.pm.PrivatePackage() - // TODO: Better naming scheme from package name - name := fmt.Sprintf("%s%s%s", dn, tg.PrivatePackage().Name(), strings.Title(pkg.Name())) - return codegen.NewCommentedValueMethod( - pkg.Path(), - name, - managerName, - /*param=*/ nil, - []jen.Code{ - jen.Func().Params( - jen.Map(jen.String()).Interface(), - ).Params( - // TODO: Qualify this. - jen.Op("*").Id(tg.TypeName()), - jen.Error(), - ), - }, - []jen.Code{ - jen.Return( - jen.Qual(tg.PrivatePackage().Path(), dn), - ), - }, - jen.Commentf("%s returns the deserialization method for the %q type in package %q", name, tg.TypeName(), tg.PrivatePackage().Name())) +// createDeserializationMethodForType creates a new deserialization method for +// a type. +func (m *ManagerGenerator) createDeserializationMethodForType(tg *TypeGenerator) *codegen.Method { + return m.createDeserializationMethod( + tg.deserializationFnName(), + tg.PublicPackage(), + tg.PrivatePackage(), + tg.InterfaceName(), + tg.VocabName()) } -// createPrivateDeserializationMethodForFuncProperty creates a new method for the -// private manager. -// -// TODO: Unify these three methods behind some kind of interface. -func (m *ManagerGenerator) createPrivateDeserializationMethodForFuncProperty(fp *FunctionalPropertyGenerator) *codegen.Method { - dn := fp.DeserializeFnName() - pkg := m.pm.PrivatePackage() - // TODO: Better naming scheme from package name - name := fmt.Sprintf("%s%s%s", dn, fp.GetPrivatePackage().Name(), strings.Title(pkg.Name())) - return codegen.NewCommentedValueMethod( - pkg.Path(), - name, - managerName, - /*param=*/ nil, - []jen.Code{ - jen.Func().Params( - jen.Map(jen.String()).Interface(), - ).Params( - // TODO: Qualify this. - jen.Op("*").Id(fp.StructName()), - jen.Error(), - ), - }, - []jen.Code{ - jen.Return( - jen.Qual(fp.GetPrivatePackage().Path(), dn), - ), - }, - jen.Commentf("%s returns the deserialization method for the %q functional property in package %q", name, fp.StructName(), fp.GetPrivatePackage().Name())) +// createDeserializationMethodForFuncProperty creates a new deserialization +// method for a functional property. +func (m *ManagerGenerator) createDeserializationMethodForFuncProperty(fp *FunctionalPropertyGenerator) *codegen.Method { + return m.createDeserializationMethod( + fp.DeserializeFnName(), + fp.GetPublicPackage(), + fp.GetPrivatePackage(), + fp.InterfaceName(), + fp.VocabName()) } -// createPrivateDeserializationMethodForNonFuncProperty creates a new method for the -// private manager. -// -// TODO: Unify these three methods behind some kind of interface. -func (m *ManagerGenerator) createPrivateDeserializationMethodForNonFuncProperty(nfp *NonFunctionalPropertyGenerator) *codegen.Method { - dn := nfp.DeserializeFnName() - pkg := m.pm.PrivatePackage() - // TODO: Better naming scheme from package name - name := fmt.Sprintf("%s%s%s", dn, nfp.GetPrivatePackage().Name(), strings.Title(pkg.Name())) +// createDeserializationMethodForNonFuncProperty creates a new deserialization +// method for a non-functional property. +func (m *ManagerGenerator) createDeserializationMethodForNonFuncProperty(nfp *NonFunctionalPropertyGenerator) *codegen.Method { + return m.createDeserializationMethod( + nfp.DeserializeFnName(), + nfp.GetPublicPackage(), + nfp.GetPrivatePackage(), + nfp.InterfaceName(), + nfp.VocabName()) +} + +// createDeserializationMethod returns a function +func (m *ManagerGenerator) createDeserializationMethod(deserName string, pubPkg, privPkg Package, interfaceName, vocabName string) *codegen.Method { + name := fmt.Sprintf("%s%s", deserName, vocabName) return codegen.NewCommentedValueMethod( - pkg.Path(), + m.pkg.Path(), name, managerName, /*param=*/ nil, @@ -276,15 +203,28 @@ func (m *ManagerGenerator) createPrivateDeserializationMethodForNonFuncProperty( jen.Func().Params( jen.Map(jen.String()).Interface(), ).Params( - // TODO: Qualify this. - jen.Op("*").Id(nfp.StructName()), + jen.Qual(pubPkg.Path(), interfaceName), jen.Error(), ), }, []jen.Code{ jen.Return( - jen.Qual(nfp.GetPrivatePackage().Path(), dn), + jen.Func().Params( + jen.Id("m").Map(jen.String()).Interface(), + ).Params( + jen.Qual(pubPkg.Path(), interfaceName), + jen.Error(), + ).Block( + jen.List( + jen.Id("i"), + jen.Err(), + ).Op(":=").Qual(privPkg.Path(), deserName).Call(jen.Id("m")), + jen.Return(jen.List( + jen.Id("i"), + jen.Err(), + )), + ), ), }, - jen.Commentf("%s returns the deserialization method for the %q non-functional property in package %q", name, nfp.StructName(), nfp.GetPrivatePackage().Name())) + jen.Commentf("%s returns the deserialization method for the %q non-functional property in the vocabulary %q", name, interfaceName, vocabName)) } diff --git a/tools/exp/props/nonfuncprop.go b/tools/exp/props/nonfuncprop.go index 6d8e675..324685e 100644 --- a/tools/exp/props/nonfuncprop.go +++ b/tools/exp/props/nonfuncprop.go @@ -23,12 +23,14 @@ type NonFunctionalPropertyGenerator struct { // // PropertyGenerators shoulf be in the first pass to construct, before types and // other generators are constructed. -func NewNonFunctionalPropertyGenerator(pm *PackageManager, +func NewNonFunctionalPropertyGenerator(vocabName string, + pm *PackageManager, name Identifier, kinds []Kind, hasNaturalLanguageMap bool) *NonFunctionalPropertyGenerator { return &NonFunctionalPropertyGenerator{ PropertyGenerator: PropertyGenerator{ + vocabName: vocabName, PackageManager: pm, HasNaturalLanguageMap: hasNaturalLanguageMap, Name: name, diff --git a/tools/exp/props/property.go b/tools/exp/props/property.go index ef250cb..0310b8c 100644 --- a/tools/exp/props/property.go +++ b/tools/exp/props/property.go @@ -105,6 +105,7 @@ func (k Kind) lessFnCode(this, other *jen.Statement) *jen.Statement { // // TODO: Make this type private type PropertyGenerator struct { + vocabName string // TODO: Make these private PackageManager *PackageManager Name Identifier @@ -114,6 +115,11 @@ type PropertyGenerator struct { asIterator bool } +// VocabName returns this property's vocabulary name. +func (p *PropertyGenerator) VocabName() string { + return p.vocabName +} + // GetPrivatePackage gets this property's private Package. func (p *PropertyGenerator) GetPrivatePackage() Package { return p.PackageManager.PrivatePackage() diff --git a/tools/exp/props/type.go b/tools/exp/props/type.go index 0b0a543..ff9110d 100644 --- a/tools/exp/props/type.go +++ b/tools/exp/props/type.go @@ -50,6 +50,7 @@ type Property interface { // TypeGenerator represents an ActivityStream type definition to generate in Go. type TypeGenerator struct { + vocabName string pm *PackageManager typeName string comment string @@ -84,10 +85,11 @@ type TypeGenerator struct { // // A ManagerGenerator must be created with this type before Definition is // called, to ensure that the serialization functions are properly set up. -func NewTypeGenerator(pm *PackageManager, typeName, comment string, +func NewTypeGenerator(vocabName string, pm *PackageManager, typeName, comment string, properties, withoutProperties, rangeProperties []Property, extends, disjoint []*TypeGenerator) (*TypeGenerator, error) { t := &TypeGenerator{ + vocabName: vocabName, pm: pm, typeName: typeName, comment: comment, @@ -129,7 +131,7 @@ func (t *TypeGenerator) apply(m *ManagerGenerator) error { // Set up Kind functions // Note: this "i" must be the same as the "i" in the deserialization definition. // TODO: Remove this kluge. - deser := m.getPrivateDeserializationMethodForType(t).On(managerInitName()) + deser := m.getDeserializationMethodForType(t).On(managerInitName()) kind := jen.Qual(t.PublicPackage().Path(), t.InterfaceName()) for _, p := range t.rangeProperties { if e := p.SetKindFns(t.TypeName(), kind, deser); e != nil { @@ -139,6 +141,11 @@ func (t *TypeGenerator) apply(m *ManagerGenerator) error { return nil } +// VocabName returns this TypeGenerator's vocabulary name. +func (t *TypeGenerator) VocabName() string { + return t.vocabName +} + // Package gets this TypeGenerator's Private Package. func (t *TypeGenerator) PrivatePackage() Package { return t.pm.PrivatePackage() @@ -230,7 +237,6 @@ func (t *TypeGenerator) InterfaceDefinition(pkg Package) *codegen.Interface { // Definition generates the golang code for this ActivityStreams type. func (t *TypeGenerator) Definition() *codegen.Struct { t.cacheOnce.Do(func() { - // TODO: Constructor function (not here, maybe in manager?) members := t.members() ser := t.serializationMethod() less := t.lessMethod() @@ -600,19 +606,18 @@ func (t *TypeGenerator) lessMethod() (less *codegen.Method) { func (t *TypeGenerator) kindDeserializationFunc() (deser *codegen.Function) { deserCode := jen.Commentf("Begin: Known property deserialization").Line() for _, prop := range t.allProperties() { - deserMethod := t.m.getPrivateDeserializationMethodForProperty(prop) + deserMethod := t.m.getDeserializationMethodForProperty(prop) deserCode = deserCode.Add( jen.If( jen.List( jen.Id("p"), jen.Err(), - // TODO: Ensure this variable is called correctly - ).Op(":=").Add(deserMethod.Call(managerInitName(), jen.Id("m"))), + ).Op(":=").Add(deserMethod.On(managerInitName()).Call().Call(jen.Id("m"))), jen.Err().Op("!=").Nil(), ).Block( jen.Return(jen.Nil(), jen.Err()), ).Else().Block( - jen.Id(codegen.This()).Dot(t.memberName(prop)).Op("=").Op("*").Id("p"), + jen.Id(codegen.This()).Dot(t.memberName(prop)).Op("=").Id("p"), ).Line()) } deserCode = deserCode.Commentf("End: Known property deserialization").Line() diff --git a/tools/exp/rdf/data.go b/tools/exp/rdf/data.go index 23f1776..ae7961e 100644 --- a/tools/exp/rdf/data.go +++ b/tools/exp/rdf/data.go @@ -42,13 +42,19 @@ func (p ParsedVocabulary) String() string { // Vocabulary contains the type, property, and value definitions for a single // ActivityStreams or extension vocabulary. type Vocabulary struct { + Name string Types map[string]VocabularyType Properties map[string]VocabularyProperty Values map[string]VocabularyValue } +func (v Vocabulary) GetName() string { + return v.Name +} + func (v Vocabulary) String() string { var b bytes.Buffer + b.WriteString(fmt.Sprintf("Vocabulary %q\n", v.Name)) for k, v := range v.Types { b.WriteString(fmt.Sprintf("Type %s:\n\t%s\n", k, v)) } diff --git a/tools/exp/rdf/parse.go b/tools/exp/rdf/parse.go index dd9d30a..4f2c493 100644 --- a/tools/exp/rdf/parse.go +++ b/tools/exp/rdf/parse.go @@ -119,7 +119,7 @@ type RDFNode interface { // ParseVocabulary parses the specified input as an ActivityStreams context that // specifies a Core, Extended, or Extension vocabulary. -func ParseVocabulary(registry *RDFRegistry, input JSONLD) (vocabulary *ParsedVocabulary, err error) { +func ParseVocabulary(name string, registry *RDFRegistry, input JSONLD) (vocabulary *ParsedVocabulary, err error) { var nodes []RDFNode nodes, err = parseJSONLDContext(registry, input) if err != nil { @@ -151,6 +151,8 @@ func ParseVocabulary(registry *RDFRegistry, input JSONLD) (vocabulary *ParsedVoc // Step 3: Populate VocabularyType's 'Properties' and // 'WithoutProperties' fields err = populatePropertiesOnTypes(ctx) + // Populate this parsed vocabulary's name + vocabulary.Vocab.Name = name return }