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	"strings"
20
21	"github.com/go-openapi/swag"
22)
23
24// Extensions vendor specific extensions
25type Extensions map[string]interface{}
26
27// Add adds a value to these extensions
28func (e Extensions) Add(key string, value interface{}) {
29	realKey := strings.ToLower(key)
30	e[realKey] = value
31}
32
33// GetString gets a string value from the extensions
34func (e Extensions) GetString(key string) (string, bool) {
35	if v, ok := e[strings.ToLower(key)]; ok {
36		str, ok := v.(string)
37		return str, ok
38	}
39	return "", false
40}
41
42// GetBool gets a string value from the extensions
43func (e Extensions) GetBool(key string) (bool, bool) {
44	if v, ok := e[strings.ToLower(key)]; ok {
45		str, ok := v.(bool)
46		return str, ok
47	}
48	return false, false
49}
50
51// GetStringSlice gets a string value from the extensions
52func (e Extensions) GetStringSlice(key string) ([]string, bool) {
53	if v, ok := e[strings.ToLower(key)]; ok {
54		arr, isSlice := v.([]interface{})
55		if !isSlice {
56			return nil, false
57		}
58		var strs []string
59		for _, iface := range arr {
60			str, isString := iface.(string)
61			if !isString {
62				return nil, false
63			}
64			strs = append(strs, str)
65		}
66		return strs, ok
67	}
68	return nil, false
69}
70
71// VendorExtensible composition block.
72type VendorExtensible struct {
73	Extensions Extensions
74}
75
76// AddExtension adds an extension to this extensible object
77func (v *VendorExtensible) AddExtension(key string, value interface{}) {
78	if value == nil {
79		return
80	}
81	if v.Extensions == nil {
82		v.Extensions = make(map[string]interface{})
83	}
84	v.Extensions.Add(key, value)
85}
86
87// MarshalJSON marshals the extensions to json
88func (v VendorExtensible) MarshalJSON() ([]byte, error) {
89	toser := make(map[string]interface{})
90	for k, v := range v.Extensions {
91		lk := strings.ToLower(k)
92		if strings.HasPrefix(lk, "x-") {
93			toser[k] = v
94		}
95	}
96	return json.Marshal(toser)
97}
98
99// UnmarshalJSON for this extensible object
100func (v *VendorExtensible) UnmarshalJSON(data []byte) error {
101	var d map[string]interface{}
102	if err := json.Unmarshal(data, &d); err != nil {
103		return err
104	}
105	for k, vv := range d {
106		lk := strings.ToLower(k)
107		if strings.HasPrefix(lk, "x-") {
108			if v.Extensions == nil {
109				v.Extensions = map[string]interface{}{}
110			}
111			v.Extensions[k] = vv
112		}
113	}
114	return nil
115}
116
117// InfoProps the properties for an info definition
118type InfoProps struct {
119	Description    string       `json:"description,omitempty"`
120	Title          string       `json:"title,omitempty"`
121	TermsOfService string       `json:"termsOfService,omitempty"`
122	Contact        *ContactInfo `json:"contact,omitempty"`
123	License        *License     `json:"license,omitempty"`
124	Version        string       `json:"version,omitempty"`
125}
126
127// Info object provides metadata about the API.
128// The metadata can be used by the clients if needed, and can be presented in the Swagger-UI for convenience.
129//
130// For more information: http://goo.gl/8us55a#infoObject
131type Info struct {
132	VendorExtensible
133	InfoProps
134}
135
136// MarshalJSON marshal this to JSON
137func (i Info) MarshalJSON() ([]byte, error) {
138	b1, err := json.Marshal(i.InfoProps)
139	if err != nil {
140		return nil, err
141	}
142	b2, err := json.Marshal(i.VendorExtensible)
143	if err != nil {
144		return nil, err
145	}
146	return swag.ConcatJSON(b1, b2), nil
147}
148
149// UnmarshalJSON marshal this from JSON
150func (i *Info) UnmarshalJSON(data []byte) error {
151	if err := json.Unmarshal(data, &i.InfoProps); err != nil {
152		return err
153	}
154	return json.Unmarshal(data, &i.VendorExtensible)
155}
156