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 20 "github.com/go-openapi/jsonpointer" 21 "github.com/go-openapi/swag" 22) 23 24type OperationProps struct { 25 Description string `json:"description,omitempty"` 26 Consumes []string `json:"consumes,omitempty"` 27 Produces []string `json:"produces,omitempty"` 28 Schemes []string `json:"schemes,omitempty"` // the scheme, when present must be from [http, https, ws, wss] 29 Tags []string `json:"tags,omitempty"` 30 Summary string `json:"summary,omitempty"` 31 ExternalDocs *ExternalDocumentation `json:"externalDocs,omitempty"` 32 ID string `json:"operationId,omitempty"` 33 Deprecated bool `json:"deprecated,omitempty"` 34 Security []map[string][]string `json:"security,omitempty"` 35 Parameters []Parameter `json:"parameters,omitempty"` 36 Responses *Responses `json:"responses,omitempty"` 37} 38 39// Operation describes a single API operation on a path. 40// 41// For more information: http://goo.gl/8us55a#operationObject 42type Operation struct { 43 VendorExtensible 44 OperationProps 45} 46 47// SuccessResponse gets a success response model 48func (o *Operation) SuccessResponse() (*Response, int, bool) { 49 if o.Responses == nil { 50 return nil, 0, false 51 } 52 53 for k, v := range o.Responses.StatusCodeResponses { 54 if k/100 == 2 { 55 return &v, k, true 56 } 57 } 58 59 return o.Responses.Default, 0, false 60} 61 62// JSONLookup look up a value by the json property name 63func (o Operation) JSONLookup(token string) (interface{}, error) { 64 if ex, ok := o.Extensions[token]; ok { 65 return &ex, nil 66 } 67 r, _, err := jsonpointer.GetForToken(o.OperationProps, token) 68 return r, err 69} 70 71// UnmarshalJSON hydrates this items instance with the data from JSON 72func (o *Operation) UnmarshalJSON(data []byte) error { 73 if err := json.Unmarshal(data, &o.OperationProps); err != nil { 74 return err 75 } 76 if err := json.Unmarshal(data, &o.VendorExtensible); err != nil { 77 return err 78 } 79 return nil 80} 81 82// MarshalJSON converts this items object to JSON 83func (o Operation) MarshalJSON() ([]byte, error) { 84 b1, err := json.Marshal(o.OperationProps) 85 if err != nil { 86 return nil, err 87 } 88 b2, err := json.Marshal(o.VendorExtensible) 89 if err != nil { 90 return nil, err 91 } 92 concated := swag.ConcatJSON(b1, b2) 93 return concated, nil 94} 95 96// NewOperation creates a new operation instance. 97// It expects an ID as parameter but not passing an ID is also valid. 98func NewOperation(id string) *Operation { 99 op := new(Operation) 100 op.ID = id 101 return op 102} 103 104// WithID sets the ID property on this operation, allows for chaining. 105func (o *Operation) WithID(id string) *Operation { 106 o.ID = id 107 return o 108} 109 110// WithDescription sets the description on this operation, allows for chaining 111func (o *Operation) WithDescription(description string) *Operation { 112 o.Description = description 113 return o 114} 115 116// WithSummary sets the summary on this operation, allows for chaining 117func (o *Operation) WithSummary(summary string) *Operation { 118 o.Summary = summary 119 return o 120} 121 122// WithExternalDocs sets/removes the external docs for/from this operation. 123// When you pass empty strings as params the external documents will be removed. 124// When you pass non-empty string as one value then those values will be used on the external docs object. 125// So when you pass a non-empty description, you should also pass the url and vice versa. 126func (o *Operation) WithExternalDocs(description, url string) *Operation { 127 if description == "" && url == "" { 128 o.ExternalDocs = nil 129 return o 130 } 131 132 if o.ExternalDocs == nil { 133 o.ExternalDocs = &ExternalDocumentation{} 134 } 135 o.ExternalDocs.Description = description 136 o.ExternalDocs.URL = url 137 return o 138} 139 140// Deprecate marks the operation as deprecated 141func (o *Operation) Deprecate() *Operation { 142 o.Deprecated = true 143 return o 144} 145 146// Undeprecate marks the operation as not deprected 147func (o *Operation) Undeprecate() *Operation { 148 o.Deprecated = false 149 return o 150} 151 152// WithConsumes adds media types for incoming body values 153func (o *Operation) WithConsumes(mediaTypes ...string) *Operation { 154 o.Consumes = append(o.Consumes, mediaTypes...) 155 return o 156} 157 158// WithProduces adds media types for outgoing body values 159func (o *Operation) WithProduces(mediaTypes ...string) *Operation { 160 o.Produces = append(o.Produces, mediaTypes...) 161 return o 162} 163 164// WithTags adds tags for this operation 165func (o *Operation) WithTags(tags ...string) *Operation { 166 o.Tags = append(o.Tags, tags...) 167 return o 168} 169 170// AddParam adds a parameter to this operation, when a parameter for that location 171// and with that name already exists it will be replaced 172func (o *Operation) AddParam(param *Parameter) *Operation { 173 if param == nil { 174 return o 175 } 176 177 for i, p := range o.Parameters { 178 if p.Name == param.Name && p.In == param.In { 179 params := append(o.Parameters[:i], *param) 180 params = append(params, o.Parameters[i+1:]...) 181 o.Parameters = params 182 return o 183 } 184 } 185 186 o.Parameters = append(o.Parameters, *param) 187 return o 188} 189 190// RemoveParam removes a parameter from the operation 191func (o *Operation) RemoveParam(name, in string) *Operation { 192 for i, p := range o.Parameters { 193 if p.Name == name && p.In == name { 194 o.Parameters = append(o.Parameters[:i], o.Parameters[i+1:]...) 195 return o 196 } 197 } 198 return o 199} 200 201// SecuredWith adds a security scope to this operation. 202func (o *Operation) SecuredWith(name string, scopes ...string) *Operation { 203 o.Security = append(o.Security, map[string][]string{name: scopes}) 204 return o 205} 206 207// WithDefaultResponse adds a default response to the operation. 208// Passing a nil value will remove the response 209func (o *Operation) WithDefaultResponse(response *Response) *Operation { 210 return o.RespondsWith(0, response) 211} 212 213// RespondsWith adds a status code response to the operation. 214// When the code is 0 the value of the response will be used as default response value. 215// When the value of the response is nil it will be removed from the operation 216func (o *Operation) RespondsWith(code int, response *Response) *Operation { 217 if o.Responses == nil { 218 o.Responses = new(Responses) 219 } 220 if code == 0 { 221 o.Responses.Default = response 222 return o 223 } 224 if response == nil { 225 delete(o.Responses.StatusCodeResponses, code) 226 return o 227 } 228 if o.Responses.StatusCodeResponses == nil { 229 o.Responses.StatusCodeResponses = make(map[int]Response) 230 } 231 o.Responses.StatusCodeResponses[code] = *response 232 return o 233} 234