11/*
2- * Copyright 2012- 2024 the original author or authors .
2+ * Copyright 2024 The Go-Spring Authors .
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@ import (
2424 "strings"
2525
2626 "github.com/go-spring/spring-core/util"
27- "github.com/go-spring/spring-core/util/macro "
27+ "github.com/go-spring/spring-core/util/errutil "
2828)
2929
3030var (
@@ -94,22 +94,27 @@ type BindParam struct {
9494}
9595
9696func (param * BindParam ) BindTag (tag string , validate reflect.StructTag ) error {
97+ param .Validate = validate
9798 parsedTag , err := ParseTag (tag )
9899 if err != nil {
99100 return err
100101 }
102+ if parsedTag .Key == "" { // ${:=} 默认值语法
103+ if parsedTag .HasDef {
104+ param .Tag = parsedTag
105+ return nil
106+ }
107+ return fmt .Errorf ("xxxx" ) // todo
108+ }
101109 if parsedTag .Key == "ROOT" {
102110 parsedTag .Key = ""
103- } else if parsedTag .Key == "" {
104- parsedTag .Key = "ANONYMOUS"
105111 }
106- param .Tag = parsedTag
107112 if param .Key == "" {
108113 param .Key = parsedTag .Key
109114 } else if parsedTag .Key != "" {
110115 param .Key = param .Key + "." + parsedTag .Key
111116 }
112- param .Validate = validate
117+ param .Tag = parsedTag
113118 return nil
114119}
115120
@@ -118,11 +123,11 @@ type Filter interface {
118123}
119124
120125// BindValue binds properties to a value.
121- func BindValue (p readOnlyProperties , v reflect.Value , t reflect.Type , param BindParam , filter Filter ) (RetErr error ) {
126+ func BindValue (p ReadOnlyProperties , v reflect.Value , t reflect.Type , param BindParam , filter Filter ) (RetErr error ) {
122127
123- if ! util .IsValueType (t ) {
128+ if ! util .IsPropBindingTarget (t ) {
124129 err := errors .New ("target should be value type" )
125- return fmt .Errorf ("%s: bind %s error, %w" , macro . FileLine (), param . Path , err )
130+ return fmt .Errorf ("bind path=%s type= %s error: %w" , param . Path , v . Type (). String () , err )
126131 }
127132
128133 defer func () {
@@ -144,29 +149,29 @@ func BindValue(p readOnlyProperties, v reflect.Value, t reflect.Type, param Bind
144149 return bindSlice (p , v , t , param , filter )
145150 case reflect .Array :
146151 err := errors .New ("use slice instead of array" )
147- return fmt .Errorf ("%s: bind %s error, %w" , macro . FileLine (), param . Path , err )
152+ return fmt .Errorf ("bind path=%s type= %s error: %w" , param . Path , v . Type (). String () , err )
148153 default : // for linter
149154 }
150155
151156 fn := converters [t ]
152157 if fn == nil && v .Kind () == reflect .Struct {
153158 if err := bindStruct (p , v , t , param , filter ); err != nil {
154- return fmt . Errorf ( "%s: bind %s error, %w" , macro . FileLine (), param . Path , err )
159+ return err // no wrap
155160 }
156161 return nil
157162 }
158163
159164 val , err := resolve (p , param )
160165 if err != nil {
161- return fmt . Errorf ( "%s: bind %s error, %w " , macro . FileLine (), param .Path , err )
166+ return errutil . WrapError ( err , "bind path=%s type= %s error" , param .Path , v . Type (). String () )
162167 }
163168
164169 if fn != nil {
165170 fnValue := reflect .ValueOf (fn )
166171 out := fnValue .Call ([]reflect.Value {reflect .ValueOf (val )})
167172 if ! out [1 ].IsNil () {
168173 err = out [1 ].Interface ().(error )
169- return fmt . Errorf ( "%s: bind %s error, %w " , macro . FileLine (), param .Path , err )
174+ return errutil . WrapError ( err , "bind path=%s type= %s error" , param .Path , v . Type (). String () )
170175 }
171176 v .Set (out [0 ])
172177 return nil
@@ -179,45 +184,45 @@ func BindValue(p readOnlyProperties, v reflect.Value, t reflect.Type, param Bind
179184 v .SetUint (u )
180185 return nil
181186 }
182- return fmt . Errorf ( "%s: bind %s error, %w " , macro . FileLine (), param .Path , err )
187+ return errutil . WrapError ( err , "bind path=%s type= %s error" , param .Path , v . Type (). String () )
183188 case reflect .Int , reflect .Int8 , reflect .Int16 , reflect .Int32 , reflect .Int64 :
184189 var i int64
185190 if i , err = strconv .ParseInt (val , 0 , 0 ); err == nil {
186191 v .SetInt (i )
187192 return nil
188193 }
189- return fmt . Errorf ( "%s: bind %s error, %w " , macro . FileLine (), param .Path , err )
194+ return errutil . WrapError ( err , "bind path=%s type= %s error" , param .Path , v . Type (). String () )
190195 case reflect .Float32 , reflect .Float64 :
191196 var f float64
192197 if f , err = strconv .ParseFloat (val , 64 ); err == nil {
193198 v .SetFloat (f )
194199 return nil
195200 }
196- return fmt . Errorf ( "%s: bind %s error, %w " , macro . FileLine (), param .Path , err )
201+ return errutil . WrapError ( err , "bind path=%s type= %s error" , param .Path , v . Type (). String () )
197202 case reflect .Bool :
198203 var b bool
199204 if b , err = strconv .ParseBool (val ); err == nil {
200205 v .SetBool (b )
201206 return nil
202207 }
203- return fmt . Errorf ( "%s: bind %s error, %w " , macro . FileLine (), param .Path , err )
208+ return errutil . WrapError ( err , "bind path=%s type= %s error" , param .Path , v . Type (). String () )
204209 case reflect .String :
205210 v .SetString (val )
206211 return nil
207212 default : // for linter
208213 }
209214
210- err = fmt . Errorf ("unsupported bind type %q" , t . String () )
211- return fmt .Errorf ("%s: bind %s error, %w" , macro . FileLine (), param . Path , err )
215+ err = errors . New ("unsupported bind type" )
216+ return fmt .Errorf ("bind path=%s type= %s error: %w" , param . Path , v . Type (). String () , err )
212217}
213218
214219// bindSlice binds properties to a slice value.
215- func bindSlice (p readOnlyProperties , v reflect.Value , t reflect.Type , param BindParam , filter Filter ) error {
220+ func bindSlice (p ReadOnlyProperties , v reflect.Value , t reflect.Type , param BindParam , filter Filter ) error {
216221
217222 et := t .Elem ()
218223 p , err := getSlice (p , et , param )
219224 if err != nil {
220- return fmt . Errorf ( "%s: bind %s error, %w " , macro . FileLine (), param .Path , err )
225+ return errutil . WrapError ( err , "bind path=%s type= %s error" , param .Path , v . Type (). String () )
221226 }
222227
223228 slice := reflect .MakeSlice (t , 0 , 0 )
@@ -238,14 +243,14 @@ func bindSlice(p readOnlyProperties, v reflect.Value, t reflect.Type, param Bind
238243 break
239244 }
240245 if err != nil {
241- return fmt . Errorf ( "%s: bind %s error, %w " , macro . FileLine (), param .Path , err )
246+ return errutil . WrapError ( err , "bind path=%s type= %s error" , param .Path , v . Type (). String () )
242247 }
243248 slice = reflect .Append (slice , e )
244249 }
245250 return nil
246251}
247252
248- func getSlice (p readOnlyProperties , et reflect.Type , param BindParam ) (readOnlyProperties , error ) {
253+ func getSlice (p ReadOnlyProperties , et reflect.Type , param BindParam ) (ReadOnlyProperties , error ) {
249254
250255 // properties that defined as list.
251256 if p .Has (param .Key + "[0]" ) {
@@ -259,13 +264,13 @@ func getSlice(p readOnlyProperties, et reflect.Type, param BindParam) (readOnlyP
259264 strVal = p .Get (param .Key )
260265 } else {
261266 if ! param .Tag .HasDef {
262- return nil , fmt .Errorf ("%s: property %q %w" , macro . FileLine () , param .Key , ErrNotExist )
267+ return nil , fmt .Errorf ("property %q %w" , param .Key , ErrNotExist )
263268 }
264269 if param .Tag .Def == "" {
265270 return nil , nil
266271 }
267272 if ! util .IsPrimitiveValueType (et ) && converters [et ] == nil {
268- return nil , fmt .Errorf ("%s: can't find converter for %s" , macro . FileLine () , et .String ())
273+ return nil , fmt .Errorf ("can't find converter for %s" , et .String ())
269274 }
270275 strVal = param .Tag .Def
271276 }
@@ -286,35 +291,44 @@ func getSlice(p readOnlyProperties, et reflect.Type, param BindParam) (readOnlyP
286291 }
287292 } else if fn , ok := splitters [s ]; ok && fn != nil {
288293 if arrVal , err = fn (strVal ); err != nil {
289- return nil , fmt .Errorf ("%s: split error: %w, value: %q" , macro . FileLine () , err , strVal )
294+ return nil , fmt .Errorf ("split error: %w, value: %q" , err , strVal )
290295 }
291296 } else {
292- return nil , fmt .Errorf ("%s: unknown splitter %q" , macro . FileLine () , s )
297+ return nil , fmt .Errorf ("unknown splitter %q" , s )
293298 }
294299
295300 r := New ()
296301 for i , s := range arrVal {
297302 k := fmt .Sprintf ("%s[%d]" , param .Key , i )
298- _ = r .storage .Set (k , s )
303+ if err = r .storage .Set (k , s ); err != nil {
304+ return nil , err
305+ }
299306 }
300307 return r , nil
301308}
302309
303310// bindMap binds properties to a map value.
304- func bindMap (p readOnlyProperties , v reflect.Value , t reflect.Type , param BindParam , filter Filter ) error {
311+ func bindMap (p ReadOnlyProperties , v reflect.Value , t reflect.Type , param BindParam , filter Filter ) error {
305312
306313 if param .Tag .HasDef && param .Tag .Def != "" {
307314 err := errors .New ("map can't have a non-empty default value" )
308- return fmt .Errorf ("%s: bind %s error, %w" , macro . FileLine (), param . Path , err )
315+ return fmt .Errorf ("bind path=%s type= %s error: %w" , param . Path , v . Type (). String () , err )
309316 }
310317
311318 et := t .Elem ()
312319 ret := reflect .MakeMap (t )
313320 defer func () { v .Set (ret ) }()
314321
322+ // 当成默认值处理
323+ if param .Tag .Key == "" {
324+ if param .Tag .HasDef {
325+ return nil
326+ }
327+ }
328+
315329 keys , err := p .SubKeys (param .Key )
316330 if err != nil {
317- return fmt . Errorf ( "%s: bind %s error, %w " , macro . FileLine (), param .Path , err )
331+ return errutil . WrapError ( err , "bind path=%s type= %s error" , param .Path , v . Type (). String () )
318332 }
319333
320334 for _ , key := range keys {
@@ -327,21 +341,20 @@ func bindMap(p readOnlyProperties, v reflect.Value, t reflect.Type, param BindPa
327341 Key : subKey ,
328342 Path : param .Path ,
329343 }
330- err = BindValue (p , e , et , subParam , filter )
331- if err != nil {
332- return fmt .Errorf ("%s: bind %s error, %w" , macro .FileLine (), param .Path , err )
344+ if err = BindValue (p , e , et , subParam , filter ); err != nil {
345+ return err // no wrap
333346 }
334347 ret .SetMapIndex (reflect .ValueOf (key ), e )
335348 }
336349 return nil
337350}
338351
339352// bindStruct binds properties to a struct value.
340- func bindStruct (p readOnlyProperties , v reflect.Value , t reflect.Type , param BindParam , filter Filter ) error {
353+ func bindStruct (p ReadOnlyProperties , v reflect.Value , t reflect.Type , param BindParam , filter Filter ) error {
341354
342355 if param .Tag .HasDef && param .Tag .Def != "" {
343356 err := errors .New ("struct can't have a non-empty default value" )
344- return fmt .Errorf ("%s: bind %s error, %w" , macro . FileLine (), param . Path , err )
357+ return fmt .Errorf ("bind path=%s type= %s error: %w" , param . Path , v . Type (). String () , err )
345358 }
346359
347360 for i := 0 ; i < t .NumField (); i ++ {
@@ -359,7 +372,7 @@ func bindStruct(p readOnlyProperties, v reflect.Value, t reflect.Type, param Bin
359372
360373 if tag , ok := ft .Tag .Lookup ("value" ); ok {
361374 if err := subParam .BindTag (tag , ft .Tag ); err != nil {
362- return fmt . Errorf ( "%s: bind %s error, %w " , macro . FileLine (), param .Path , err )
375+ return errutil . WrapError ( err , "bind path=%s type= %s error" , param .Path , v . Type (). String () )
363376 }
364377 if filter != nil {
365378 ret , err := filter .Do (fv .Addr ().Interface (), subParam )
@@ -371,7 +384,7 @@ func bindStruct(p readOnlyProperties, v reflect.Value, t reflect.Type, param Bin
371384 }
372385 }
373386 if err := BindValue (p , fv , ft .Type , subParam , filter ); err != nil {
374- return fmt . Errorf ( "%s: bind %s error, %w" , macro . FileLine (), param . Path , err )
387+ return err // no wrap
375388 }
376389 continue
377390 }
@@ -382,12 +395,12 @@ func bindStruct(p readOnlyProperties, v reflect.Value, t reflect.Type, param Bin
382395 continue
383396 }
384397 if err := bindStruct (p , fv , ft .Type , subParam , filter ); err != nil {
385- return fmt . Errorf ( "%s: bind %s error, %w" , macro . FileLine (), param . Path , err )
398+ return err // no wrap
386399 }
387400 continue
388401 }
389402
390- if util .IsValueType (ft .Type ) {
403+ if util .IsPropBindingTarget (ft .Type ) {
391404 if subParam .Key == "" {
392405 subParam .Key = ft .Name
393406 } else {
@@ -396,33 +409,31 @@ func bindStruct(p readOnlyProperties, v reflect.Value, t reflect.Type, param Bin
396409 subParam .Key = strings .ToLower (subParam .Key )
397410 subParam .Key = strings .ReplaceAll (subParam .Key , "_" , "." )
398411 if err := BindValue (p , fv , ft .Type , subParam , filter ); err != nil {
399- return fmt . Errorf ( "%s: bind %s error, %w" , macro . FileLine (), param . Path , err )
412+ return err // no wrap
400413 }
401414 }
402415 }
403416 return nil
404417}
405418
406419// resolve returns property references processed property value.
407- func resolve (p readOnlyProperties , param BindParam ) (string , error ) {
420+ func resolve (p ReadOnlyProperties , param BindParam ) (string , error ) {
408421 const defVal = "@@def@@"
409- val := p .Get (param .Key , Def ( defVal ) )
422+ val := p .Get (param .Key , defVal )
410423 if val != defVal {
411424 return resolveString (p , val )
412425 }
413426 if p .Has (param .Key ) {
414- err := fmt .Errorf ("property %q isn't simple value" , param .Key )
415- return "" , fmt .Errorf ("%s: resolve property %q error, %w" , macro .FileLine (), param .Key , err )
427+ return "" , fmt .Errorf ("property key=%s isn't simple value" , param .Key )
416428 }
417429 if param .Tag .HasDef {
418430 return resolveString (p , param .Tag .Def )
419431 }
420- err := fmt .Errorf ("property %q %w" , param .Key , ErrNotExist )
421- return "" , fmt .Errorf ("%s: resolve property %q error, %w" , macro .FileLine (), param .Key , err )
432+ return "" , fmt .Errorf ("property key=%s %w" , param .Key , ErrNotExist )
422433}
423434
424435// resolveString returns property references processed string.
425- func resolveString (p readOnlyProperties , s string ) (string , error ) {
436+ func resolveString (p ReadOnlyProperties , s string ) (string , error ) {
426437
427438 var (
428439 length = len (s )
@@ -456,20 +467,20 @@ func resolveString(p readOnlyProperties, s string) (string, error) {
456467
457468 if end < 0 || count > 0 {
458469 err := ErrInvalidSyntax
459- return "" , fmt .Errorf ("%s: resolve string %q error, %w" , macro . FileLine () , s , err )
470+ return "" , fmt .Errorf ("resolve string %q error: %w" , s , err )
460471 }
461472
462473 var param BindParam
463474 _ = param .BindTag (s [start :end + 1 ], "" )
464475
465476 s1 , err := resolve (p , param )
466477 if err != nil {
467- return "" , fmt . Errorf ( "%s: resolve string %q error, %w " , macro . FileLine (), s , err )
478+ return "" , errutil . WrapError ( err , " resolve string %q error" , s )
468479 }
469480
470481 s2 , err := resolveString (p , s [end + 1 :])
471482 if err != nil {
472- return "" , fmt . Errorf ( "%s: resolve string %q error, %w " , macro . FileLine (), s , err )
483+ return "" , errutil . WrapError ( err , " resolve string %q error" , s )
473484 }
474485
475486 return s [:start ] + s1 + s2 , nil
0 commit comments