summaryrefslogtreecommitdiffstats
path: root/Godeps/_workspace/src/github.com/awslabs/aws-sdk-go/aws/param_validator.go
blob: e1cb5cea541d702b26dd3c03362d3cf56e105df9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package aws

import (
	"fmt"
	"reflect"
	"strings"
)

func ValidateParameters(r *Request) {
	if r.ParamsFilled() {
		v := validator{errors: []string{}}
		v.validateAny(reflect.ValueOf(r.Params), "")

		if count := len(v.errors); count > 0 {
			format := "%d validation errors:\n- %s"
			msg := fmt.Sprintf(format, count, strings.Join(v.errors, "\n- "))
			r.Error = APIError{Code: "InvalidParameter", Message: msg}
		}
	}
}

type validator struct {
	errors []string
}

func (v *validator) validateAny(value reflect.Value, path string) {
	value = reflect.Indirect(value)
	if !value.IsValid() {
		return
	}

	switch value.Kind() {
	case reflect.Struct:
		v.validateStruct(value, path)
	case reflect.Slice:
		for i := 0; i < value.Len(); i++ {
			v.validateAny(value.Index(i), path+fmt.Sprintf("[%d]", i))
		}
	case reflect.Map:
		for _, n := range value.MapKeys() {
			v.validateAny(value.MapIndex(n), path+fmt.Sprintf("[%q]", n.String()))
		}
	}
}

func (v *validator) validateStruct(value reflect.Value, path string) {
	prefix := "."
	if path == "" {
		prefix = ""
	}

	for i := 0; i < value.Type().NumField(); i++ {
		f := value.Type().Field(i)
		if strings.ToLower(f.Name[0:1]) == f.Name[0:1] {
			continue
		}
		fvalue := value.FieldByName(f.Name)

		notset := false
		if f.Tag.Get("required") != "" {
			switch fvalue.Kind() {
			case reflect.Ptr, reflect.Slice:
				if fvalue.IsNil() {
					notset = true
				}
			default:
				if !fvalue.IsValid() {
					notset = true
				}
			}
		}

		if notset {
			msg := "missing required parameter: " + path + prefix + f.Name
			v.errors = append(v.errors, msg)
		} else {
			v.validateAny(fvalue, path+prefix+f.Name)
		}
	}
}