-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtranslator.go
155 lines (123 loc) · 4.39 KB
/
translator.go
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package vcomplement
import (
"github.com/kamva/gutil"
"github.com/kamva/hexa"
"github.com/kamva/tracer"
validation "github.com/go-ozzo/ozzo-validation/v4"
)
type (
// Translator is the ozzo-validation error translator.
Translator interface {
// Translate translate validation error.
Translate(err error) (*TranslateBag, error)
// Wrap translated messages in a hexa Error, if err is nil, return nil.
WrapTranslationByError(err error) hexa.Error
}
// TranslateBag is the bag contains translated validation errors or error.
TranslateBag struct {
singleMessage string
groupMessages map[string]*TranslateBag
}
)
type hexaTranslator struct {
t hexa.Translator
}
// NewHexaDriverErrorTranslator returns new instance of hexaTranslator
//that translate ozzo-validation errors.
func NewHexaDriverErrorTranslator(t hexa.Translator) Translator {
return &hexaTranslator{t: t}
}
func (t *hexaTranslator) translateErr(err validation.Error) (string, error) {
val, e := t.t.TranslateDefault(err.Code(), err.Message(), gutil.MapToKeyValue(err.Params())...)
return val, tracer.Trace(e)
}
func (t *hexaTranslator) Translate(err error) (*TranslateBag, error) {
bag := new(TranslateBag)
if e, ok := gutil.CauseErr(err).(validation.Error); ok {
msg, err := t.translateErr(e)
bag.SetSingleMsg(msg)
return bag, tracer.Trace(err)
}
if es, ok := gutil.CauseErr(err).(validation.Errors); ok {
for k, e := range es {
errBag, err := t.Translate(e)
if err != nil {
return nil, tracer.Trace(err)
}
bag.AddMsgToGroup(k, errBag)
}
return bag, nil
}
// otherwise return just empty bag and error (if error is internal
// error, so user can detect it, otherwise get empty bag that to
// detect that validation does not have any error).
return bag, err
}
// Wrap bag translated error messages to hexa Error.
// if bag be empty, returns nil.
func (t *hexaTranslator) WrapTranslationByError(err error) hexa.Error {
bag, err := t.Translate(err)
if err != nil {
return ErrInternalValidation.SetError(tracer.Trace(err))
}
// Bag can be nil (in case of valid data)
if bag.IsEmpty() {
return nil
}
return ErrValidationError.SetData(hexa.Map{"errors": bag.Map(true).(map[string]interface{})})
}
// SetSingleMsg set single error message.
func (t *TranslateBag) SetSingleMsg(msg string) {
t.singleMessage = msg
}
// AddMsgToGroup add message to the group
func (t *TranslateBag) AddMsgToGroup(key string, msg *TranslateBag) {
if t.groupMessages == nil {
t.groupMessages = map[string]*TranslateBag{}
}
t.groupMessages[key] = msg
}
// IsEmpty specify that error bag is empty or not.
func (t *TranslateBag) IsEmpty() bool {
return t.singleMessage == "" && len(t.groupMessages) == 0
}
// TOMap fucntion convert TranslateBag to a map[string]interface{}.
// but if bag just has a single message it check if forceMap is true,
// return map["error"]=<message>, otherwise returns just string message.
//
// possible values:
// - map[string]interface : when TranslateBag contains group of messages or
// contains single message with forceMap=true.
// - string: when TranslateBag contains singleMessage with forceMap=false.
// - nil : When TranslateBag does not hav single message nor group of messages.
func (t *TranslateBag) Map(forceMap bool) interface{} {
if t.singleMessage != "" {
if forceMap {
return map[string]interface{}{"error": t.singleMessage}
}
return t.singleMessage
}
messages := map[string]interface{}{}
for k, v := range t.groupMessages {
messages[k] = v.Map(false)
}
return messages
}
// TValidate get a translator and validatable interface, validate and return hexa error.
func TValidateErr(t Translator, err error) error {
return t.WrapTranslationByError(err)
}
// TValidate get a translator and validatable interface, validate and return hexa error.
func TValidate(t Translator, v validation.Validatable) error {
return TValidateErr(t, v.Validate())
}
// TValidateByHexa validate by provided translator and check to detect right driver.
func TValidateByHexa(t hexa.Translator, v validation.Validatable) error {
return TValidate(NewHexaDriverErrorTranslator(t.(hexa.Translator)), v)
}
// TranslateByHexa validate by provided translator and check to detect right driver.
func TranslateByHexa(t hexa.Translator, err error) error {
return TValidateErr(NewHexaDriverErrorTranslator(t.(hexa.Translator)), err)
}
// Assert hexaTranslator implements the Translator.
var _ Translator = &hexaTranslator{}