podman
645 строк · 18.1 Кб
1// Copyright 2015 go-swagger maintainers
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package spec
16
17import (
18"encoding/json"
19"fmt"
20"strings"
21
22"github.com/go-openapi/jsonpointer"
23"github.com/go-openapi/swag"
24)
25
26// BooleanProperty creates a boolean property
27func BooleanProperty() *Schema {
28return &Schema{SchemaProps: SchemaProps{Type: []string{"boolean"}}}
29}
30
31// BoolProperty creates a boolean property
32func BoolProperty() *Schema { return BooleanProperty() }
33
34// StringProperty creates a string property
35func StringProperty() *Schema {
36return &Schema{SchemaProps: SchemaProps{Type: []string{"string"}}}
37}
38
39// CharProperty creates a string property
40func CharProperty() *Schema {
41return &Schema{SchemaProps: SchemaProps{Type: []string{"string"}}}
42}
43
44// Float64Property creates a float64/double property
45func Float64Property() *Schema {
46return &Schema{SchemaProps: SchemaProps{Type: []string{"number"}, Format: "double"}}
47}
48
49// Float32Property creates a float32/float property
50func Float32Property() *Schema {
51return &Schema{SchemaProps: SchemaProps{Type: []string{"number"}, Format: "float"}}
52}
53
54// Int8Property creates an int8 property
55func Int8Property() *Schema {
56return &Schema{SchemaProps: SchemaProps{Type: []string{"integer"}, Format: "int8"}}
57}
58
59// Int16Property creates an int16 property
60func Int16Property() *Schema {
61return &Schema{SchemaProps: SchemaProps{Type: []string{"integer"}, Format: "int16"}}
62}
63
64// Int32Property creates an int32 property
65func Int32Property() *Schema {
66return &Schema{SchemaProps: SchemaProps{Type: []string{"integer"}, Format: "int32"}}
67}
68
69// Int64Property creates an int64 property
70func Int64Property() *Schema {
71return &Schema{SchemaProps: SchemaProps{Type: []string{"integer"}, Format: "int64"}}
72}
73
74// StrFmtProperty creates a property for the named string format
75func StrFmtProperty(format string) *Schema {
76return &Schema{SchemaProps: SchemaProps{Type: []string{"string"}, Format: format}}
77}
78
79// DateProperty creates a date property
80func DateProperty() *Schema {
81return &Schema{SchemaProps: SchemaProps{Type: []string{"string"}, Format: "date"}}
82}
83
84// DateTimeProperty creates a date time property
85func DateTimeProperty() *Schema {
86return &Schema{SchemaProps: SchemaProps{Type: []string{"string"}, Format: "date-time"}}
87}
88
89// MapProperty creates a map property
90func MapProperty(property *Schema) *Schema {
91return &Schema{SchemaProps: SchemaProps{Type: []string{"object"},
92AdditionalProperties: &SchemaOrBool{Allows: true, Schema: property}}}
93}
94
95// RefProperty creates a ref property
96func RefProperty(name string) *Schema {
97return &Schema{SchemaProps: SchemaProps{Ref: MustCreateRef(name)}}
98}
99
100// RefSchema creates a ref property
101func RefSchema(name string) *Schema {
102return &Schema{SchemaProps: SchemaProps{Ref: MustCreateRef(name)}}
103}
104
105// ArrayProperty creates an array property
106func ArrayProperty(items *Schema) *Schema {
107if items == nil {
108return &Schema{SchemaProps: SchemaProps{Type: []string{"array"}}}
109}
110return &Schema{SchemaProps: SchemaProps{Items: &SchemaOrArray{Schema: items}, Type: []string{"array"}}}
111}
112
113// ComposedSchema creates a schema with allOf
114func ComposedSchema(schemas ...Schema) *Schema {
115s := new(Schema)
116s.AllOf = schemas
117return s
118}
119
120// SchemaURL represents a schema url
121type SchemaURL string
122
123// MarshalJSON marshal this to JSON
124func (r SchemaURL) MarshalJSON() ([]byte, error) {
125if r == "" {
126return []byte("{}"), nil
127}
128v := map[string]interface{}{"$schema": string(r)}
129return json.Marshal(v)
130}
131
132// UnmarshalJSON unmarshal this from JSON
133func (r *SchemaURL) UnmarshalJSON(data []byte) error {
134var v map[string]interface{}
135if err := json.Unmarshal(data, &v); err != nil {
136return err
137}
138return r.fromMap(v)
139}
140
141func (r *SchemaURL) fromMap(v map[string]interface{}) error {
142if v == nil {
143return nil
144}
145if vv, ok := v["$schema"]; ok {
146if str, ok := vv.(string); ok {
147u, err := parseURL(str)
148if err != nil {
149return err
150}
151
152*r = SchemaURL(u.String())
153}
154}
155return nil
156}
157
158// SchemaProps describes a JSON schema (draft 4)
159type SchemaProps struct {
160ID string `json:"id,omitempty"`
161Ref Ref `json:"-"`
162Schema SchemaURL `json:"-"`
163Description string `json:"description,omitempty"`
164Type StringOrArray `json:"type,omitempty"`
165Nullable bool `json:"nullable,omitempty"`
166Format string `json:"format,omitempty"`
167Title string `json:"title,omitempty"`
168Default interface{} `json:"default,omitempty"`
169Maximum *float64 `json:"maximum,omitempty"`
170ExclusiveMaximum bool `json:"exclusiveMaximum,omitempty"`
171Minimum *float64 `json:"minimum,omitempty"`
172ExclusiveMinimum bool `json:"exclusiveMinimum,omitempty"`
173MaxLength *int64 `json:"maxLength,omitempty"`
174MinLength *int64 `json:"minLength,omitempty"`
175Pattern string `json:"pattern,omitempty"`
176MaxItems *int64 `json:"maxItems,omitempty"`
177MinItems *int64 `json:"minItems,omitempty"`
178UniqueItems bool `json:"uniqueItems,omitempty"`
179MultipleOf *float64 `json:"multipleOf,omitempty"`
180Enum []interface{} `json:"enum,omitempty"`
181MaxProperties *int64 `json:"maxProperties,omitempty"`
182MinProperties *int64 `json:"minProperties,omitempty"`
183Required []string `json:"required,omitempty"`
184Items *SchemaOrArray `json:"items,omitempty"`
185AllOf []Schema `json:"allOf,omitempty"`
186OneOf []Schema `json:"oneOf,omitempty"`
187AnyOf []Schema `json:"anyOf,omitempty"`
188Not *Schema `json:"not,omitempty"`
189Properties SchemaProperties `json:"properties,omitempty"`
190AdditionalProperties *SchemaOrBool `json:"additionalProperties,omitempty"`
191PatternProperties SchemaProperties `json:"patternProperties,omitempty"`
192Dependencies Dependencies `json:"dependencies,omitempty"`
193AdditionalItems *SchemaOrBool `json:"additionalItems,omitempty"`
194Definitions Definitions `json:"definitions,omitempty"`
195}
196
197// SwaggerSchemaProps are additional properties supported by swagger schemas, but not JSON-schema (draft 4)
198type SwaggerSchemaProps struct {
199Discriminator string `json:"discriminator,omitempty"`
200ReadOnly bool `json:"readOnly,omitempty"`
201XML *XMLObject `json:"xml,omitempty"`
202ExternalDocs *ExternalDocumentation `json:"externalDocs,omitempty"`
203Example interface{} `json:"example,omitempty"`
204}
205
206// Schema the schema object allows the definition of input and output data types.
207// These types can be objects, but also primitives and arrays.
208// This object is based on the [JSON Schema Specification Draft 4](http://json-schema.org/)
209// and uses a predefined subset of it.
210// On top of this subset, there are extensions provided by this specification to allow for more complete documentation.
211//
212// For more information: http://goo.gl/8us55a#schemaObject
213type Schema struct {
214VendorExtensible
215SchemaProps
216SwaggerSchemaProps
217ExtraProps map[string]interface{} `json:"-"`
218}
219
220// JSONLookup implements an interface to customize json pointer lookup
221func (s Schema) JSONLookup(token string) (interface{}, error) {
222if ex, ok := s.Extensions[token]; ok {
223return &ex, nil
224}
225
226if ex, ok := s.ExtraProps[token]; ok {
227return &ex, nil
228}
229
230r, _, err := jsonpointer.GetForToken(s.SchemaProps, token)
231if r != nil || (err != nil && !strings.HasPrefix(err.Error(), "object has no field")) {
232return r, err
233}
234r, _, err = jsonpointer.GetForToken(s.SwaggerSchemaProps, token)
235return r, err
236}
237
238// WithID sets the id for this schema, allows for chaining
239func (s *Schema) WithID(id string) *Schema {
240s.ID = id
241return s
242}
243
244// WithTitle sets the title for this schema, allows for chaining
245func (s *Schema) WithTitle(title string) *Schema {
246s.Title = title
247return s
248}
249
250// WithDescription sets the description for this schema, allows for chaining
251func (s *Schema) WithDescription(description string) *Schema {
252s.Description = description
253return s
254}
255
256// WithProperties sets the properties for this schema
257func (s *Schema) WithProperties(schemas map[string]Schema) *Schema {
258s.Properties = schemas
259return s
260}
261
262// SetProperty sets a property on this schema
263func (s *Schema) SetProperty(name string, schema Schema) *Schema {
264if s.Properties == nil {
265s.Properties = make(map[string]Schema)
266}
267s.Properties[name] = schema
268return s
269}
270
271// WithAllOf sets the all of property
272func (s *Schema) WithAllOf(schemas ...Schema) *Schema {
273s.AllOf = schemas
274return s
275}
276
277// WithMaxProperties sets the max number of properties an object can have
278func (s *Schema) WithMaxProperties(max int64) *Schema {
279s.MaxProperties = &max
280return s
281}
282
283// WithMinProperties sets the min number of properties an object must have
284func (s *Schema) WithMinProperties(min int64) *Schema {
285s.MinProperties = &min
286return s
287}
288
289// Typed sets the type of this schema for a single value item
290func (s *Schema) Typed(tpe, format string) *Schema {
291s.Type = []string{tpe}
292s.Format = format
293return s
294}
295
296// AddType adds a type with potential format to the types for this schema
297func (s *Schema) AddType(tpe, format string) *Schema {
298s.Type = append(s.Type, tpe)
299if format != "" {
300s.Format = format
301}
302return s
303}
304
305// AsNullable flags this schema as nullable.
306func (s *Schema) AsNullable() *Schema {
307s.Nullable = true
308return s
309}
310
311// CollectionOf a fluent builder method for an array parameter
312func (s *Schema) CollectionOf(items Schema) *Schema {
313s.Type = []string{jsonArray}
314s.Items = &SchemaOrArray{Schema: &items}
315return s
316}
317
318// WithDefault sets the default value on this parameter
319func (s *Schema) WithDefault(defaultValue interface{}) *Schema {
320s.Default = defaultValue
321return s
322}
323
324// WithRequired flags this parameter as required
325func (s *Schema) WithRequired(items ...string) *Schema {
326s.Required = items
327return s
328}
329
330// AddRequired adds field names to the required properties array
331func (s *Schema) AddRequired(items ...string) *Schema {
332s.Required = append(s.Required, items...)
333return s
334}
335
336// WithMaxLength sets a max length value
337func (s *Schema) WithMaxLength(max int64) *Schema {
338s.MaxLength = &max
339return s
340}
341
342// WithMinLength sets a min length value
343func (s *Schema) WithMinLength(min int64) *Schema {
344s.MinLength = &min
345return s
346}
347
348// WithPattern sets a pattern value
349func (s *Schema) WithPattern(pattern string) *Schema {
350s.Pattern = pattern
351return s
352}
353
354// WithMultipleOf sets a multiple of value
355func (s *Schema) WithMultipleOf(number float64) *Schema {
356s.MultipleOf = &number
357return s
358}
359
360// WithMaximum sets a maximum number value
361func (s *Schema) WithMaximum(max float64, exclusive bool) *Schema {
362s.Maximum = &max
363s.ExclusiveMaximum = exclusive
364return s
365}
366
367// WithMinimum sets a minimum number value
368func (s *Schema) WithMinimum(min float64, exclusive bool) *Schema {
369s.Minimum = &min
370s.ExclusiveMinimum = exclusive
371return s
372}
373
374// WithEnum sets a the enum values (replace)
375func (s *Schema) WithEnum(values ...interface{}) *Schema {
376s.Enum = append([]interface{}{}, values...)
377return s
378}
379
380// WithMaxItems sets the max items
381func (s *Schema) WithMaxItems(size int64) *Schema {
382s.MaxItems = &size
383return s
384}
385
386// WithMinItems sets the min items
387func (s *Schema) WithMinItems(size int64) *Schema {
388s.MinItems = &size
389return s
390}
391
392// UniqueValues dictates that this array can only have unique items
393func (s *Schema) UniqueValues() *Schema {
394s.UniqueItems = true
395return s
396}
397
398// AllowDuplicates this array can have duplicates
399func (s *Schema) AllowDuplicates() *Schema {
400s.UniqueItems = false
401return s
402}
403
404// AddToAllOf adds a schema to the allOf property
405func (s *Schema) AddToAllOf(schemas ...Schema) *Schema {
406s.AllOf = append(s.AllOf, schemas...)
407return s
408}
409
410// WithDiscriminator sets the name of the discriminator field
411func (s *Schema) WithDiscriminator(discriminator string) *Schema {
412s.Discriminator = discriminator
413return s
414}
415
416// AsReadOnly flags this schema as readonly
417func (s *Schema) AsReadOnly() *Schema {
418s.ReadOnly = true
419return s
420}
421
422// AsWritable flags this schema as writeable (not read-only)
423func (s *Schema) AsWritable() *Schema {
424s.ReadOnly = false
425return s
426}
427
428// WithExample sets the example for this schema
429func (s *Schema) WithExample(example interface{}) *Schema {
430s.Example = example
431return s
432}
433
434// WithExternalDocs sets/removes the external docs for/from this schema.
435// When you pass empty strings as params the external documents will be removed.
436// When you pass non-empty string as one value then those values will be used on the external docs object.
437// So when you pass a non-empty description, you should also pass the url and vice versa.
438func (s *Schema) WithExternalDocs(description, url string) *Schema {
439if description == "" && url == "" {
440s.ExternalDocs = nil
441return s
442}
443
444if s.ExternalDocs == nil {
445s.ExternalDocs = &ExternalDocumentation{}
446}
447s.ExternalDocs.Description = description
448s.ExternalDocs.URL = url
449return s
450}
451
452// WithXMLName sets the xml name for the object
453func (s *Schema) WithXMLName(name string) *Schema {
454if s.XML == nil {
455s.XML = new(XMLObject)
456}
457s.XML.Name = name
458return s
459}
460
461// WithXMLNamespace sets the xml namespace for the object
462func (s *Schema) WithXMLNamespace(namespace string) *Schema {
463if s.XML == nil {
464s.XML = new(XMLObject)
465}
466s.XML.Namespace = namespace
467return s
468}
469
470// WithXMLPrefix sets the xml prefix for the object
471func (s *Schema) WithXMLPrefix(prefix string) *Schema {
472if s.XML == nil {
473s.XML = new(XMLObject)
474}
475s.XML.Prefix = prefix
476return s
477}
478
479// AsXMLAttribute flags this object as xml attribute
480func (s *Schema) AsXMLAttribute() *Schema {
481if s.XML == nil {
482s.XML = new(XMLObject)
483}
484s.XML.Attribute = true
485return s
486}
487
488// AsXMLElement flags this object as an xml node
489func (s *Schema) AsXMLElement() *Schema {
490if s.XML == nil {
491s.XML = new(XMLObject)
492}
493s.XML.Attribute = false
494return s
495}
496
497// AsWrappedXML flags this object as wrapped, this is mostly useful for array types
498func (s *Schema) AsWrappedXML() *Schema {
499if s.XML == nil {
500s.XML = new(XMLObject)
501}
502s.XML.Wrapped = true
503return s
504}
505
506// AsUnwrappedXML flags this object as an xml node
507func (s *Schema) AsUnwrappedXML() *Schema {
508if s.XML == nil {
509s.XML = new(XMLObject)
510}
511s.XML.Wrapped = false
512return s
513}
514
515// SetValidations defines all schema validations.
516//
517// NOTE: Required, ReadOnly, AllOf, AnyOf, OneOf and Not are not considered.
518func (s *Schema) SetValidations(val SchemaValidations) {
519s.Maximum = val.Maximum
520s.ExclusiveMaximum = val.ExclusiveMaximum
521s.Minimum = val.Minimum
522s.ExclusiveMinimum = val.ExclusiveMinimum
523s.MaxLength = val.MaxLength
524s.MinLength = val.MinLength
525s.Pattern = val.Pattern
526s.MaxItems = val.MaxItems
527s.MinItems = val.MinItems
528s.UniqueItems = val.UniqueItems
529s.MultipleOf = val.MultipleOf
530s.Enum = val.Enum
531s.MinProperties = val.MinProperties
532s.MaxProperties = val.MaxProperties
533s.PatternProperties = val.PatternProperties
534}
535
536// WithValidations is a fluent method to set schema validations
537func (s *Schema) WithValidations(val SchemaValidations) *Schema {
538s.SetValidations(val)
539return s
540}
541
542// Validations returns a clone of the validations for this schema
543func (s Schema) Validations() SchemaValidations {
544return SchemaValidations{
545CommonValidations: CommonValidations{
546Maximum: s.Maximum,
547ExclusiveMaximum: s.ExclusiveMaximum,
548Minimum: s.Minimum,
549ExclusiveMinimum: s.ExclusiveMinimum,
550MaxLength: s.MaxLength,
551MinLength: s.MinLength,
552Pattern: s.Pattern,
553MaxItems: s.MaxItems,
554MinItems: s.MinItems,
555UniqueItems: s.UniqueItems,
556MultipleOf: s.MultipleOf,
557Enum: s.Enum,
558},
559MinProperties: s.MinProperties,
560MaxProperties: s.MaxProperties,
561PatternProperties: s.PatternProperties,
562}
563}
564
565// MarshalJSON marshal this to JSON
566func (s Schema) MarshalJSON() ([]byte, error) {
567b1, err := json.Marshal(s.SchemaProps)
568if err != nil {
569return nil, fmt.Errorf("schema props %v", err)
570}
571b2, err := json.Marshal(s.VendorExtensible)
572if err != nil {
573return nil, fmt.Errorf("vendor props %v", err)
574}
575b3, err := s.Ref.MarshalJSON()
576if err != nil {
577return nil, fmt.Errorf("ref prop %v", err)
578}
579b4, err := s.Schema.MarshalJSON()
580if err != nil {
581return nil, fmt.Errorf("schema prop %v", err)
582}
583b5, err := json.Marshal(s.SwaggerSchemaProps)
584if err != nil {
585return nil, fmt.Errorf("common validations %v", err)
586}
587var b6 []byte
588if s.ExtraProps != nil {
589jj, err := json.Marshal(s.ExtraProps)
590if err != nil {
591return nil, fmt.Errorf("extra props %v", err)
592}
593b6 = jj
594}
595return swag.ConcatJSON(b1, b2, b3, b4, b5, b6), nil
596}
597
598// UnmarshalJSON marshal this from JSON
599func (s *Schema) UnmarshalJSON(data []byte) error {
600props := struct {
601SchemaProps
602SwaggerSchemaProps
603}{}
604if err := json.Unmarshal(data, &props); err != nil {
605return err
606}
607
608sch := Schema{
609SchemaProps: props.SchemaProps,
610SwaggerSchemaProps: props.SwaggerSchemaProps,
611}
612
613var d map[string]interface{}
614if err := json.Unmarshal(data, &d); err != nil {
615return err
616}
617
618_ = sch.Ref.fromMap(d)
619_ = sch.Schema.fromMap(d)
620
621delete(d, "$ref")
622delete(d, "$schema")
623for _, pn := range swag.DefaultJSONNameProvider.GetJSONNames(s) {
624delete(d, pn)
625}
626
627for k, vv := range d {
628lk := strings.ToLower(k)
629if strings.HasPrefix(lk, "x-") {
630if sch.Extensions == nil {
631sch.Extensions = map[string]interface{}{}
632}
633sch.Extensions[k] = vv
634continue
635}
636if sch.ExtraProps == nil {
637sch.ExtraProps = map[string]interface{}{}
638}
639sch.ExtraProps[k] = vv
640}
641
642*s = sch
643
644return nil
645}
646