Added more base components to mutable state.

Chopping through the list.
This commit is contained in:
Dave Shanley
2023-03-02 14:19:21 -05:00
parent fc9a230847
commit 15e458fb5d
7 changed files with 129 additions and 31 deletions

View File

@@ -4,7 +4,9 @@
package base
import (
"github.com/pb33f/libopenapi/datamodel/high"
"github.com/pb33f/libopenapi/datamodel/low/base"
"gopkg.in/yaml.v3"
)
// SecurityRequirement is a high-level representation of a Swagger / OpenAPI 2 SecurityRequirement object.
@@ -40,3 +42,17 @@ func NewSecurityRequirement(req *base.SecurityRequirement) *SecurityRequirement
func (s *SecurityRequirement) GoLow() *base.SecurityRequirement {
return s.low
}
// Render will return a YAML representation of the SecurityRequirement object as a byte slice.
func (s *SecurityRequirement) Render() ([]byte, error) {
return yaml.Marshal(s)
}
// MarshalYAML will create a ready to render YAML representation of the SecurityRequirement object.
func (s *SecurityRequirement) MarshalYAML() (interface{}, error) {
if s == nil {
return nil, nil
}
nb := high.NewNodeBuilder(s, s.low)
return nb.Render(), nil
}

View File

@@ -8,6 +8,7 @@ import (
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v3"
"strings"
"testing"
)
@@ -16,8 +17,8 @@ func TestNewSecurityRequirement(t *testing.T) {
var cNode yaml.Node
yml := `pizza:
- cheese
- tomato`
- cheese
- tomato`
_ = yaml.Unmarshal([]byte(yml), &cNode)
@@ -32,4 +33,8 @@ func TestNewSecurityRequirement(t *testing.T) {
wentLow := highExt.GoLow()
assert.Len(t, wentLow.Requirements.Value, 1)
// render the high-level object as YAML
highBytes, _ := highExt.Render()
assert.Equal(t, strings.TrimSpace(string(highBytes)), yml)
}

View File

@@ -6,6 +6,7 @@ package base
import (
"github.com/pb33f/libopenapi/datamodel/high"
low "github.com/pb33f/libopenapi/datamodel/low/base"
"gopkg.in/yaml.v3"
)
// Tag represents a high-level Tag instance that is backed by a low-level one.
@@ -15,9 +16,9 @@ import (
// - v2: https://swagger.io/specification/v2/#tagObject
// - v3: https://swagger.io/specification/#tag-object
type Tag struct {
Name string
Description string
ExternalDocs *ExternalDoc
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Description string `json:"description,omitempty" yaml:"description,omitempty"`
ExternalDocs *ExternalDoc `json:"externalDocs,omitempty" yaml:"externalDocs,omitempty"`
Extensions map[string]any
low *low.Tag
}
@@ -44,6 +45,20 @@ func (t *Tag) GoLow() *low.Tag {
return t.low
}
// Render will return a YAML representation of the Info object as a byte slice.
func (t *Tag) Render() ([]byte, error) {
return yaml.Marshal(t)
}
// MarshalYAML will create a ready to render YAML representation of the Info object.
func (t *Tag) MarshalYAML() (interface{}, error) {
if t == nil {
return nil, nil
}
nb := high.NewNodeBuilder(t, t.low)
return nb.Render(), nil
}
// Experimental mutation API.
//func (t *Tag) SetName(value string) {
// t.GoLow().Name.ValueNode.Value = value

View File

@@ -9,6 +9,7 @@ import (
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v3"
"strings"
"testing"
)
@@ -19,7 +20,7 @@ func TestNewTag(t *testing.T) {
yml := `name: chicken
description: nuggets
externalDocs:
url: https://pb33f.io
url: https://pb33f.io
x-hack: code`
_ = yaml.Unmarshal([]byte(yml), &cNode)
@@ -38,6 +39,10 @@ x-hack: code`
wentLow := highTag.GoLow()
assert.Equal(t, 5, wentLow.FindExtension("x-hack").ValueNode.Line)
// render the tag as YAML
highTagBytes, _ := highTag.Render()
assert.Equal(t, strings.TrimSpace(string(highTagBytes)), yml)
}
func ExampleNewTag() {

View File

@@ -6,6 +6,7 @@ package base
import (
"github.com/pb33f/libopenapi/datamodel/high"
low "github.com/pb33f/libopenapi/datamodel/low/base"
"gopkg.in/yaml.v3"
)
// XML represents a high-level representation of an XML object defined by all versions of OpenAPI and backed by
@@ -18,11 +19,11 @@ import (
// v2 - https://swagger.io/specification/v2/#xmlObject
// v3 - https://swagger.io/specification/#xml-object
type XML struct {
Name string
Namespace string
Prefix string
Attribute bool
Wrapped bool
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
Prefix string `json:"prefix,omitempty" yaml:"prefix,omitempty"`
Attribute bool `json:"attribute,omitempty" yaml:"attribute,omitempty"`
Wrapped bool `json:"wrapped,omitempty" yaml:"wrapped,omitempty"`
Extensions map[string]any
low *low.XML
}
@@ -33,7 +34,7 @@ func NewXML(xml *low.XML) *XML {
x.low = xml
x.Name = xml.Name.Value
x.Namespace = xml.Namespace.Value
x.Prefix = xml.Namespace.Value
x.Prefix = xml.Prefix.Value
x.Attribute = xml.Attribute.Value
x.Wrapped = xml.Wrapped.Value
x.Extensions = high.ExtractExtensions(xml.Extensions)
@@ -44,3 +45,18 @@ func NewXML(xml *low.XML) *XML {
func (x *XML) GoLow() *low.XML {
return x.low
}
// Render will return a YAML representation of the XML object as a byte slice.
func (x *XML) Render() ([]byte, error) {
return yaml.Marshal(x)
}
// MarshalYAML will create a ready to render YAML representation of the XML object.
func (x *XML) MarshalYAML() (interface{}, error) {
if x == nil {
return nil, nil
}
nb := high.NewNodeBuilder(x, x.low)
return nb.Render(), nil
}

View File

@@ -7,7 +7,10 @@ import (
"fmt"
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v3"
"strings"
"testing"
)
func ExampleNewXML() {
@@ -16,7 +19,10 @@ func ExampleNewXML() {
// this can be either JSON or YAML.
yml := `
namespace: https://pb33f.io/schema
prefix: sample`
name: something
attribute: true
prefix: sample
wrapped: true`
// unmarshal raw bytes
var node yaml.Node
@@ -34,3 +40,35 @@ prefix: sample`
fmt.Print(highXML.Namespace)
// Output: https://pb33f.io/schema
}
func TestContact_Render(t *testing.T) {
// create an example schema object
// this can be either JSON or YAML.
yml := `namespace: https://pb33f.io/schema
name: something
attribute: true
prefix: sample
wrapped: true`
// unmarshal raw bytes
var node yaml.Node
_ = yaml.Unmarshal([]byte(yml), &node)
// build out the low-level model
var lowXML lowbase.XML
_ = lowmodel.BuildModel(node.Content[0], &lowXML)
_ = lowXML.Build(node.Content[0], nil)
// build the high level tag
highXML := NewXML(&lowXML)
// print out the XML doc
highXMLBytes, _ := highXML.Render()
assert.Equal(t, yml, strings.TrimSpace(string(highXMLBytes)))
highXML.Attribute = false
highXMLBytes, _ = highXML.Render()
assert.NotEqual(t, yml, strings.TrimSpace(string(highXMLBytes)))
}

View File

@@ -167,10 +167,14 @@ func (n *NodeBuilder) add(key string) {
nodeEntry.Value = strconv.FormatInt(value.Int(), 10)
case reflect.String:
nodeEntry.Value = value.String()
case reflect.Bool:
nodeEntry.Value = value.Bool()
case reflect.Ptr:
nodeEntry.Value = f
case reflect.Map:
nodeEntry.Value = f
default:
panic("not supported yet")
}
// if there is no low level object, then we cannot extract line numbers,
@@ -216,26 +220,14 @@ func AddYAMLNode(parent *yaml.Node, key string, value any) *yaml.Node {
// check the type
t := reflect.TypeOf(value)
l := CreateStringNode(key)
var l *yaml.Node
if key != "" {
l = CreateStringNode(key)
}
var valueNode *yaml.Node
switch t.Kind() {
case reflect.String:
if value.(string) == "" {
return parent
}
valueNode = CreateStringNode(value.(string))
case reflect.Int:
valueNode = CreateIntNode(value.(int))
case reflect.Struct:
panic("no way dude, why?")
case reflect.Map:
var rawNode yaml.Node
err := rawNode.Encode(value)
if err != nil {
return parent
} else {
valueNode = &rawNode
}
case reflect.Ptr:
rawRender, _ := value.(Renderable).MarshalYAML()
if rawRender != nil {
@@ -244,9 +236,20 @@ func AddYAMLNode(parent *yaml.Node, key string, value any) *yaml.Node {
return parent
}
default:
panic("not supported yet")
var rawNode yaml.Node
err := rawNode.Encode(value)
if err != nil {
return parent
} else {
valueNode = &rawNode
}
}
parent.Content = append(parent.Content, l, valueNode)
if l != nil {
parent.Content = append(parent.Content, l, valueNode)
} else {
parent.Content = valueNode.Content
}
return parent
}