github.com/pavlo67/common@v0.5.3/common/errors/errors.go (about) 1 package errors 2 3 import ( 4 "errors" 5 "fmt" 6 "reflect" 7 "strings" 8 9 "github.com/pavlo67/common/common" 10 ) 11 12 type Key = common.ErrorKey 13 14 type Error interface { 15 error 16 Cause() error 17 Key() Key 18 Data() common.Map 19 Append(interface{}) Error 20 } 21 22 func CommonError(any ...interface{}) Error { 23 var err *commonError 24 for _, anything := range any { 25 err = err.append(anything) 26 } 27 28 if reflect.ValueOf(err).IsNil() { 29 return nil 30 } 31 32 return err 33 } 34 35 func AddErrors(err, errToAdd error) error { 36 if err == nil { 37 return errToAdd 38 } else if v := reflect.ValueOf(err); v.Kind() == reflect.Interface && v.IsNil() { 39 return errToAdd 40 } else if e, _ := err.(Error); e != nil { 41 return e.Append(errToAdd) 42 } 43 44 return CommonError(err, errToAdd) 45 } 46 47 //func CommonError(key Key, data common.Map) Error { 48 // return &commonError{ 49 // errs: nil, 50 // key: key, 51 // data: data, 52 // } 53 //} 54 55 func Keyed(err error) Key { 56 if err == nil { 57 return "" 58 } 59 60 if errs, _ := err.(Error); errs != nil { 61 return errs.Key() 62 } 63 return "" 64 } 65 66 func Cause(err error) error { 67 if err == nil { 68 return nil 69 } 70 71 if errs, _ := err.(Error); errs != nil { 72 return errs.Cause() 73 } 74 return nil 75 } 76 77 func Data(err error) common.Map { 78 if err == nil { 79 return nil 80 } 81 82 if errs, _ := err.(Error); errs != nil { 83 return errs.Data() 84 } 85 return nil 86 } 87 88 // commonError ------------------------------------------------------------------------------------------------------- 89 90 var _ Error = &commonError{} 91 92 type commonError struct { 93 errs multipleErrors 94 key Key 95 data common.Map 96 } 97 98 func (ce *commonError) Cause() error { 99 if ce != nil { 100 if len(ce.errs) > 0 { 101 return ce.errs[0] 102 } else if ce.key != "" { 103 // ??? 104 New(string(ce.key)) 105 } 106 } 107 108 return nil 109 } 110 111 func (ce *commonError) Error() string { 112 if ce == nil { 113 return "" 114 } 115 errStr := strings.TrimSpace(string(ce.key)) 116 if errStr == "" { 117 // errStr = "<no key> " 118 } 119 120 if len(ce.data) > 0 { 121 errStr += fmt.Sprintf(" (%v) ", ce.data) 122 } 123 124 return errStr + ce.errs.String() 125 } 126 127 func (ce *commonError) Key() Key { 128 if ce == nil { 129 return "" 130 } 131 132 return ce.key 133 } 134 135 func (ce *commonError) Data() common.Map { 136 if ce == nil { 137 return nil 138 } 139 140 return ce.data 141 } 142 143 func (ce *commonError) append(anything interface{}) *commonError { 144 if anything == nil { 145 return ce 146 } 147 148 switch v := anything.(type) { 149 case Key: 150 if ce == nil { 151 return &commonError{key: v} 152 } else if ce.key == "" { 153 ce.key = v 154 return ce 155 } else { 156 anything = commonError{key: v} 157 } 158 case common.Map: 159 if ce == nil { 160 return &commonError{data: v} 161 } else if len(ce.data) < 1 { 162 ce.data = v 163 return ce 164 } else { 165 anything = commonError{data: v} 166 } 167 case string: 168 anything = errors.New(v) 169 } 170 171 if ce == nil { 172 switch v := anything.(type) { 173 case commonError: 174 v1 := v // to prevent recursion in the case: ke1 := CommonError(...); ke2 := CommonError(ke1, ke1) 175 return &v1 176 case *commonError: 177 v1 := *v // to prevent recursion in the case: ke1 := CommonError(...); ke2 := CommonError(ke1, ke1) 178 return &v1 179 case Error: 180 return &commonError{ 181 errs: multipleErrors{errors.New(v.Error())}, 182 key: v.Key(), 183 data: v.Data(), 184 } 185 case error: 186 return &commonError{errs: multipleErrors{v}} 187 case string: 188 return &commonError{errs: multipleErrors{errors.New(v)}} 189 } 190 ce = &commonError{} 191 } 192 193 var err error 194 switch v := anything.(type) { 195 case commonError: 196 err = &v 197 case *commonError: 198 err = v 199 case Error: 200 err = v 201 case error: 202 err = v 203 case string: 204 err = errors.New(v) 205 default: 206 } 207 208 ce.errs = append(ce.errs, err) 209 return ce 210 } 211 212 func (ce *commonError) Append(anything interface{}) Error { 213 return ce.append(anything) 214 215 }