~hduran-8/+junk/caddylegacy

« back to all changes in this revision

Viewing changes to debian/gocode/src/github.com/aws/aws-sdk-go/private/model/api/shape.go

  • Committer: Horacio Durán
  • Date: 2016-10-14 14:33:43 UTC
  • Revision ID: horacio.duran@canonical.com-20161014143343-ytyhz5sx7d1cje4q
Added new upstream version

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
package api
2
 
 
3
 
import (
4
 
        "bytes"
5
 
        "fmt"
6
 
        "path"
7
 
        "regexp"
8
 
        "sort"
9
 
        "strings"
10
 
        "text/template"
11
 
 
12
 
        "github.com/aws/aws-sdk-go/private/util"
13
 
)
14
 
 
15
 
// A ShapeRef defines the usage of a shape within the API.
16
 
type ShapeRef struct {
17
 
        API              *API   `json:"-"`
18
 
        Shape            *Shape `json:"-"`
19
 
        Documentation    string
20
 
        ShapeName        string `json:"shape"`
21
 
        Location         string
22
 
        LocationName     string
23
 
        QueryName        string
24
 
        Flattened        bool
25
 
        Streaming        bool
26
 
        XMLAttribute     bool
27
 
        XMLNamespace     XMLInfo
28
 
        Payload          string
29
 
        IdempotencyToken bool `json:"idempotencyToken"`
30
 
        Deprecated       bool `json:"deprecated"`
31
 
}
32
 
 
33
 
// A XMLInfo defines URL and prefix for Shapes when rendered as XML
34
 
type XMLInfo struct {
35
 
        Prefix string
36
 
        URI    string
37
 
}
38
 
 
39
 
// A Shape defines the definition of a shape type
40
 
type Shape struct {
41
 
        API              *API `json:"-"`
42
 
        ShapeName        string
43
 
        Documentation    string
44
 
        MemberRefs       map[string]*ShapeRef `json:"members"`
45
 
        MemberRef        ShapeRef             `json:"member"`
46
 
        KeyRef           ShapeRef             `json:"key"`
47
 
        ValueRef         ShapeRef             `json:"value"`
48
 
        Required         []string
49
 
        Payload          string
50
 
        Type             string
51
 
        Exception        bool
52
 
        Enum             []string
53
 
        EnumConsts       []string
54
 
        Flattened        bool
55
 
        Streaming        bool
56
 
        Location         string
57
 
        LocationName     string
58
 
        IdempotencyToken bool `json:"idempotencyToken"`
59
 
        XMLNamespace     XMLInfo
60
 
        Min              int // optional Minimum length (string, list) or value (number)
61
 
        Max              int // optional Minimum length (string, list) or value (number)
62
 
 
63
 
        refs       []*ShapeRef // References to this shape
64
 
        resolvePkg string      // use this package in the goType() if present
65
 
 
66
 
        // Defines if the shape is a placeholder and should not be used directly
67
 
        Placeholder bool
68
 
 
69
 
        Deprecated bool `json:"deprecated"`
70
 
}
71
 
 
72
 
// Rename changes the name of the Shape to newName. Also updates
73
 
// the associated API's reference to use newName.
74
 
func (s *Shape) Rename(newName string) {
75
 
        for _, r := range s.refs {
76
 
                r.ShapeName = newName
77
 
        }
78
 
 
79
 
        delete(s.API.Shapes, s.ShapeName)
80
 
        s.API.Shapes[newName] = s
81
 
        s.ShapeName = newName
82
 
}
83
 
 
84
 
// MemberNames returns a slice of struct member names.
85
 
func (s *Shape) MemberNames() []string {
86
 
        i, names := 0, make([]string, len(s.MemberRefs))
87
 
        for n := range s.MemberRefs {
88
 
                names[i] = n
89
 
                i++
90
 
        }
91
 
        sort.Strings(names)
92
 
        return names
93
 
}
94
 
 
95
 
// GoTypeWithPkgName returns a shape's type as a string with the package name in
96
 
// <packageName>.<type> format. Package naming only applies to structures.
97
 
func (s *Shape) GoTypeWithPkgName() string {
98
 
        return goType(s, true)
99
 
}
100
 
 
101
 
// GoType returns a shape's Go type
102
 
func (s *Shape) GoType() string {
103
 
        return goType(s, false)
104
 
}
105
 
 
106
 
// GoType returns a shape ref's Go type.
107
 
func (ref *ShapeRef) GoType() string {
108
 
        if ref.Shape == nil {
109
 
                panic(fmt.Errorf("missing shape definition on reference for %#v", ref))
110
 
        }
111
 
 
112
 
        return ref.Shape.GoType()
113
 
}
114
 
 
115
 
// GoTypeWithPkgName returns a shape's type as a string with the package name in
116
 
// <packageName>.<type> format. Package naming only applies to structures.
117
 
func (ref *ShapeRef) GoTypeWithPkgName() string {
118
 
        if ref.Shape == nil {
119
 
                panic(fmt.Errorf("missing shape definition on reference for %#v", ref))
120
 
        }
121
 
 
122
 
        return ref.Shape.GoTypeWithPkgName()
123
 
}
124
 
 
125
 
// Returns a string version of the Shape's type.
126
 
// If withPkgName is true, the package name will be added as a prefix
127
 
func goType(s *Shape, withPkgName bool) string {
128
 
        switch s.Type {
129
 
        case "structure":
130
 
                if withPkgName || s.resolvePkg != "" {
131
 
                        pkg := s.resolvePkg
132
 
                        if pkg != "" {
133
 
                                s.API.imports[pkg] = true
134
 
                                pkg = path.Base(pkg)
135
 
                        } else {
136
 
                                pkg = s.API.PackageName()
137
 
                        }
138
 
                        return fmt.Sprintf("*%s.%s", pkg, s.ShapeName)
139
 
                }
140
 
                return "*" + s.ShapeName
141
 
        case "map":
142
 
                return "map[string]" + s.ValueRef.GoType()
143
 
        case "list":
144
 
                return "[]" + s.MemberRef.GoType()
145
 
        case "boolean":
146
 
                return "*bool"
147
 
        case "string", "character":
148
 
                return "*string"
149
 
        case "blob":
150
 
                return "[]byte"
151
 
        case "integer", "long":
152
 
                return "*int64"
153
 
        case "float", "double":
154
 
                return "*float64"
155
 
        case "timestamp":
156
 
                s.API.imports["time"] = true
157
 
                return "*time.Time"
158
 
        default:
159
 
                panic("Unsupported shape type: " + s.Type)
160
 
        }
161
 
}
162
 
 
163
 
// GoTypeElem returns the Go type for the Shape. If the shape type is a pointer just
164
 
// the type will be returned minus the pointer *.
165
 
func (s *Shape) GoTypeElem() string {
166
 
        t := s.GoType()
167
 
        if strings.HasPrefix(t, "*") {
168
 
                return t[1:]
169
 
        }
170
 
        return t
171
 
}
172
 
 
173
 
// GoTypeElem returns the Go type for the Shape. If the shape type is a pointer just
174
 
// the type will be returned minus the pointer *.
175
 
func (ref *ShapeRef) GoTypeElem() string {
176
 
        if ref.Shape == nil {
177
 
                panic(fmt.Errorf("missing shape definition on reference for %#v", ref))
178
 
        }
179
 
 
180
 
        return ref.Shape.GoTypeElem()
181
 
}
182
 
 
183
 
// ShapeTag is a struct tag that will be applied to a shape's generated code
184
 
type ShapeTag struct {
185
 
        Key, Val string
186
 
}
187
 
 
188
 
// String returns the string representation of the shape tag
189
 
func (s ShapeTag) String() string {
190
 
        return fmt.Sprintf(`%s:"%s"`, s.Key, s.Val)
191
 
}
192
 
 
193
 
// ShapeTags is a collection of shape tags and provides serialization of the
194
 
// tags in an ordered list.
195
 
type ShapeTags []ShapeTag
196
 
 
197
 
// Join returns an ordered serialization of the shape tags with the provided
198
 
// seperator.
199
 
func (s ShapeTags) Join(sep string) string {
200
 
        o := &bytes.Buffer{}
201
 
        for i, t := range s {
202
 
                o.WriteString(t.String())
203
 
                if i < len(s)-1 {
204
 
                        o.WriteString(sep)
205
 
                }
206
 
        }
207
 
 
208
 
        return o.String()
209
 
}
210
 
 
211
 
// String is an alias for Join with the empty space seperator.
212
 
func (s ShapeTags) String() string {
213
 
        return s.Join(" ")
214
 
}
215
 
 
216
 
// GoTags returns the rendered tags string for the ShapeRef
217
 
func (ref *ShapeRef) GoTags(toplevel bool, isRequired bool) string {
218
 
        tags := ShapeTags{}
219
 
 
220
 
        if ref.Location != "" {
221
 
                tags = append(tags, ShapeTag{"location", ref.Location})
222
 
        } else if ref.Shape.Location != "" {
223
 
                tags = append(tags, ShapeTag{"location", ref.Shape.Location})
224
 
        }
225
 
 
226
 
        if ref.LocationName != "" {
227
 
                tags = append(tags, ShapeTag{"locationName", ref.LocationName})
228
 
        } else if ref.Shape.LocationName != "" {
229
 
                tags = append(tags, ShapeTag{"locationName", ref.Shape.LocationName})
230
 
        }
231
 
 
232
 
        if ref.QueryName != "" {
233
 
                tags = append(tags, ShapeTag{"queryName", ref.QueryName})
234
 
        }
235
 
        if ref.Shape.MemberRef.LocationName != "" {
236
 
                tags = append(tags, ShapeTag{"locationNameList", ref.Shape.MemberRef.LocationName})
237
 
        }
238
 
        if ref.Shape.KeyRef.LocationName != "" {
239
 
                tags = append(tags, ShapeTag{"locationNameKey", ref.Shape.KeyRef.LocationName})
240
 
        }
241
 
        if ref.Shape.ValueRef.LocationName != "" {
242
 
                tags = append(tags, ShapeTag{"locationNameValue", ref.Shape.ValueRef.LocationName})
243
 
        }
244
 
        if ref.Shape.Min > 0 {
245
 
                tags = append(tags, ShapeTag{"min", fmt.Sprintf("%d", ref.Shape.Min)})
246
 
        }
247
 
 
248
 
        if ref.Deprecated || ref.Shape.Deprecated {
249
 
                tags = append(tags, ShapeTag{"deprecated", "true"})
250
 
        }
251
 
        // All shapes have a type
252
 
        tags = append(tags, ShapeTag{"type", ref.Shape.Type})
253
 
 
254
 
        // embed the timestamp type for easier lookups
255
 
        if ref.Shape.Type == "timestamp" {
256
 
                t := ShapeTag{Key: "timestampFormat"}
257
 
                if ref.Location == "header" {
258
 
                        t.Val = "rfc822"
259
 
                } else {
260
 
                        switch ref.API.Metadata.Protocol {
261
 
                        case "json", "rest-json":
262
 
                                t.Val = "unix"
263
 
                        case "rest-xml", "ec2", "query":
264
 
                                t.Val = "iso8601"
265
 
                        }
266
 
                }
267
 
                tags = append(tags, t)
268
 
        }
269
 
 
270
 
        if ref.Shape.Flattened || ref.Flattened {
271
 
                tags = append(tags, ShapeTag{"flattened", "true"})
272
 
        }
273
 
        if ref.XMLAttribute {
274
 
                tags = append(tags, ShapeTag{"xmlAttribute", "true"})
275
 
        }
276
 
        if isRequired {
277
 
                tags = append(tags, ShapeTag{"required", "true"})
278
 
        }
279
 
        if ref.Shape.IsEnum() {
280
 
                tags = append(tags, ShapeTag{"enum", ref.ShapeName})
281
 
        }
282
 
 
283
 
        if toplevel {
284
 
                if ref.Shape.Payload != "" {
285
 
                        tags = append(tags, ShapeTag{"payload", ref.Shape.Payload})
286
 
                }
287
 
                if ref.XMLNamespace.Prefix != "" {
288
 
                        tags = append(tags, ShapeTag{"xmlPrefix", ref.XMLNamespace.Prefix})
289
 
                } else if ref.Shape.XMLNamespace.Prefix != "" {
290
 
                        tags = append(tags, ShapeTag{"xmlPrefix", ref.Shape.XMLNamespace.Prefix})
291
 
                }
292
 
                if ref.XMLNamespace.URI != "" {
293
 
                        tags = append(tags, ShapeTag{"xmlURI", ref.XMLNamespace.URI})
294
 
                } else if ref.Shape.XMLNamespace.URI != "" {
295
 
                        tags = append(tags, ShapeTag{"xmlURI", ref.Shape.XMLNamespace.URI})
296
 
                }
297
 
        }
298
 
 
299
 
        if ref.IdempotencyToken || ref.Shape.IdempotencyToken {
300
 
                tags = append(tags, ShapeTag{"idempotencyToken", "true"})
301
 
        }
302
 
 
303
 
        return fmt.Sprintf("`%s`", tags)
304
 
}
305
 
 
306
 
// Docstring returns the godocs formated documentation
307
 
func (ref *ShapeRef) Docstring() string {
308
 
        if ref.Documentation != "" {
309
 
                return ref.Documentation
310
 
        }
311
 
        return ref.Shape.Docstring()
312
 
}
313
 
 
314
 
// Docstring returns the godocs formated documentation
315
 
func (s *Shape) Docstring() string {
316
 
        return s.Documentation
317
 
}
318
 
 
319
 
var goCodeStringerTmpl = template.Must(template.New("goCodeStringerTmpl").Parse(`
320
 
// String returns the string representation
321
 
func (s {{ .ShapeName }}) String() string {
322
 
        return awsutil.Prettify(s)
323
 
}
324
 
// GoString returns the string representation
325
 
func (s {{ .ShapeName }}) GoString() string {
326
 
        return s.String()
327
 
}
328
 
`))
329
 
 
330
 
func (s *Shape) goCodeStringers() string {
331
 
        w := bytes.Buffer{}
332
 
        if err := goCodeStringerTmpl.Execute(&w, s); err != nil {
333
 
                panic(fmt.Sprintln("Unexpected error executing goCodeStringers template", err))
334
 
        }
335
 
 
336
 
        return w.String()
337
 
}
338
 
 
339
 
var enumStrip = regexp.MustCompile(`[^a-zA-Z0-9_:\./-]`)
340
 
var enumDelims = regexp.MustCompile(`[-_:\./]+`)
341
 
var enumCamelCase = regexp.MustCompile(`([a-z])([A-Z])`)
342
 
 
343
 
// EnumName returns the Nth enum in the shapes Enum list
344
 
func (s *Shape) EnumName(n int) string {
345
 
        enum := s.Enum[n]
346
 
        enum = enumStrip.ReplaceAllLiteralString(enum, "")
347
 
        enum = enumCamelCase.ReplaceAllString(enum, "$1-$2")
348
 
        parts := enumDelims.Split(enum, -1)
349
 
        for i, v := range parts {
350
 
                v = strings.ToLower(v)
351
 
                parts[i] = ""
352
 
                if len(v) > 0 {
353
 
                        parts[i] = strings.ToUpper(v[0:1])
354
 
                }
355
 
                if len(v) > 1 {
356
 
                        parts[i] += v[1:]
357
 
                }
358
 
        }
359
 
        enum = strings.Join(parts, "")
360
 
        enum = strings.ToUpper(enum[0:1]) + enum[1:]
361
 
        return enum
362
 
}
363
 
 
364
 
// GoCode returns the rendered Go code for the Shape.
365
 
func (s *Shape) GoCode() string {
366
 
        code := s.Docstring()
367
 
        if !s.IsEnum() {
368
 
                code += "type " + s.ShapeName + " "
369
 
        }
370
 
 
371
 
        switch {
372
 
        case s.Type == "structure":
373
 
                ref := &ShapeRef{ShapeName: s.ShapeName, API: s.API, Shape: s}
374
 
 
375
 
                code += "struct {\n"
376
 
                code += "_ struct{} " + ref.GoTags(true, false) + "\n\n"
377
 
                for _, n := range s.MemberNames() {
378
 
                        m := s.MemberRefs[n]
379
 
                        code += m.Docstring()
380
 
                        if (m.Streaming || m.Shape.Streaming) && s.Payload == n {
381
 
                                rtype := "io.ReadSeeker"
382
 
                                if len(s.refs) > 1 {
383
 
                                        rtype = "aws.ReaderSeekCloser"
384
 
                                } else if strings.HasSuffix(s.ShapeName, "Output") {
385
 
                                        rtype = "io.ReadCloser"
386
 
                                }
387
 
 
388
 
                                s.API.imports["io"] = true
389
 
                                code += n + " " + rtype + " " + m.GoTags(false, s.IsRequired(n)) + "\n\n"
390
 
                        } else {
391
 
                                code += n + " " + m.GoType() + " " + m.GoTags(false, s.IsRequired(n)) + "\n\n"
392
 
                        }
393
 
                }
394
 
                code += "}"
395
 
 
396
 
                if !s.API.NoStringerMethods {
397
 
                        code += s.goCodeStringers()
398
 
                }
399
 
        case s.IsEnum():
400
 
                code += "const (\n"
401
 
                for n, e := range s.Enum {
402
 
                        code += fmt.Sprintf("\t// @enum %s\n\t%s = %q\n",
403
 
                                s.ShapeName, s.EnumConsts[n], e)
404
 
                }
405
 
                code += ")"
406
 
        default:
407
 
                panic("Cannot generate toplevel shape for " + s.Type)
408
 
        }
409
 
 
410
 
        return util.GoFmt(code)
411
 
}
412
 
 
413
 
// IsEnum returns whether this shape is an enum list
414
 
func (s *Shape) IsEnum() bool {
415
 
        return s.Type == "string" && len(s.Enum) > 0
416
 
}
417
 
 
418
 
// IsRequired returns if member is a required field.
419
 
func (s *Shape) IsRequired(member string) bool {
420
 
        for _, n := range s.Required {
421
 
                if n == member {
422
 
                        return true
423
 
                }
424
 
        }
425
 
        return false
426
 
}
427
 
 
428
 
// IsInternal returns whether the shape was defined in this package
429
 
func (s *Shape) IsInternal() bool {
430
 
        return s.resolvePkg == ""
431
 
}
432
 
 
433
 
// removeRef removes a shape reference from the list of references this
434
 
// shape is used in.
435
 
func (s *Shape) removeRef(ref *ShapeRef) {
436
 
        r := s.refs
437
 
        for i := 0; i < len(r); i++ {
438
 
                if r[i] == ref {
439
 
                        j := i + 1
440
 
                        copy(r[i:], r[j:])
441
 
                        for k, n := len(r)-j+i, len(r); k < n; k++ {
442
 
                                r[k] = nil // free up the end of the list
443
 
                        } // for k
444
 
                        s.refs = r[:len(r)-j+i]
445
 
                        break
446
 
                }
447
 
        }
448
 
}