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