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