Files
libopenapi/datamodel/low/v3/create_document.go
Dave Shanley 65b242b6c4 Building out low level docs now
a long road ahead, but we must push forward.
2022-09-20 07:55:19 -04:00

193 lines
5.2 KiB
Go

package v3
import (
"github.com/pb33f/libopenapi/datamodel"
"github.com/pb33f/libopenapi/datamodel/low"
"github.com/pb33f/libopenapi/datamodel/low/base"
"github.com/pb33f/libopenapi/index"
"github.com/pb33f/libopenapi/resolver"
"github.com/pb33f/libopenapi/utils"
"sync"
)
func CreateDocument(info *datamodel.SpecInfo) (*Document, []error) {
doc := Document{Version: low.ValueReference[string]{Value: info.Version, ValueNode: info.RootNode}}
// build an index
idx := index.NewSpecIndex(info.RootNode)
doc.Index = idx
// create resolver and check for circular references.
resolve := resolver.NewResolver(idx)
_ = resolve.CheckForCircularReferences()
var wg sync.WaitGroup
var errors []error
doc.Extensions = low.ExtractExtensions(info.RootNode.Content[0])
// if set, extract jsonSchemaDialect (3.1)
_, dialectLabel, dialectNode := utils.FindKeyNodeFull(JSONSchemaDialectLabel, info.RootNode.Content)
if dialectNode != nil {
doc.JsonSchemaDialect = low.NodeReference[string]{
Value: dialectNode.Value, KeyNode: dialectLabel, ValueNode: dialectLabel}
}
var runExtraction = func(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex,
runFunc func(i *datamodel.SpecInfo, d *Document, idx *index.SpecIndex) error,
ers *[]error,
wg *sync.WaitGroup) {
if er := runFunc(info, doc, idx); er != nil {
*ers = append(*ers, er)
}
wg.Done()
}
extractionFuncs := []func(i *datamodel.SpecInfo, d *Document, idx *index.SpecIndex) error{
extractInfo,
extractServers,
extractTags,
extractComponents,
extractSecurity,
extractExternalDocs,
extractPaths,
extractWebhooks,
}
wg.Add(len(extractionFuncs))
for _, f := range extractionFuncs {
go runExtraction(info, &doc, idx, f, &errors, &wg)
}
wg.Wait()
return &doc, errors
}
func extractInfo(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
_, ln, vn := utils.FindKeyNodeFull(base.InfoLabel, info.RootNode.Content)
if vn != nil {
ir := base.Info{}
_ = low.BuildModel(vn, &ir)
_ = ir.Build(vn, idx)
nr := low.NodeReference[*base.Info]{Value: &ir, ValueNode: vn, KeyNode: ln}
doc.Info = nr
}
return nil
}
func extractSecurity(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
sec, sErr := low.ExtractObject[*SecurityRequirement](SecurityLabel, info.RootNode, idx)
if sErr != nil {
return sErr
}
doc.Security = sec
return nil
}
func extractExternalDocs(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
extDocs, dErr := low.ExtractObject[*base.ExternalDoc](base.ExternalDocsLabel, info.RootNode, idx)
if dErr != nil {
return dErr
}
doc.ExternalDocs = extDocs
return nil
}
func extractComponents(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
_, ln, vn := utils.FindKeyNodeFull(ComponentsLabel, info.RootNode.Content)
if vn != nil {
ir := Components{}
_ = low.BuildModel(vn, &ir)
err := ir.Build(vn, idx)
if err != nil {
return err
}
nr := low.NodeReference[*Components]{Value: &ir, ValueNode: vn, KeyNode: ln}
doc.Components = nr
}
return nil
}
func extractServers(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
_, ln, vn := utils.FindKeyNodeFull(ServersLabel, info.RootNode.Content)
if vn != nil {
if utils.IsNodeArray(vn) {
var servers []low.ValueReference[*Server]
for _, srvN := range vn.Content {
if utils.IsNodeMap(srvN) {
srvr := Server{}
_ = low.BuildModel(srvN, &srvr)
_ = srvr.Build(srvN, idx)
servers = append(servers, low.ValueReference[*Server]{
Value: &srvr,
ValueNode: srvN,
})
}
}
doc.Servers = low.NodeReference[[]low.ValueReference[*Server]]{
Value: servers,
KeyNode: ln,
ValueNode: vn,
}
}
}
return nil
}
func extractTags(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
_, ln, vn := utils.FindKeyNodeFull(base.TagsLabel, info.RootNode.Content)
if vn != nil {
if utils.IsNodeArray(vn) {
var tags []low.ValueReference[*base.Tag]
for _, tagN := range vn.Content {
if utils.IsNodeMap(tagN) {
tag := base.Tag{}
_ = low.BuildModel(tagN, &tag)
if err := tag.Build(tagN, idx); err != nil {
return err
}
tags = append(tags, low.ValueReference[*base.Tag]{
Value: &tag,
ValueNode: tagN,
})
}
}
doc.Tags = low.NodeReference[[]low.ValueReference[*base.Tag]]{
Value: tags,
KeyNode: ln,
ValueNode: vn,
}
}
}
return nil
}
func extractPaths(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
_, ln, vn := utils.FindKeyNodeFull(PathsLabel, info.RootNode.Content)
if vn != nil {
ir := Paths{}
err := ir.Build(vn, idx)
if err != nil {
return err
}
nr := low.NodeReference[*Paths]{Value: &ir, ValueNode: vn, KeyNode: ln}
doc.Paths = nr
}
return nil
}
func extractWebhooks(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
hooks, hooksL, hooksN, eErr := low.ExtractMap[*PathItem](WebhooksLabel, info.RootNode, idx)
if eErr != nil {
return eErr
}
if hooks != nil {
doc.Webhooks = low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*PathItem]]{
Value: hooks,
KeyNode: hooksL,
ValueNode: hooksN,
}
}
return nil
}