github.com/TIBCOSoftware/flogo-lib@v0.5.9/core/data/coercion.go (about) 1 package data 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "reflect" 7 "strconv" 8 "strings" 9 ) 10 11 // CoerceToValue coerce a value to the specified type 12 func CoerceToValue(value interface{}, dataType Type) (interface{}, error) { 13 14 var coerced interface{} 15 var err error 16 17 switch dataType { 18 case TypeAny: 19 coerced, err = CoerceToAny(value) 20 case TypeString: 21 coerced, err = CoerceToString(value) 22 case TypeInteger: 23 coerced, err = CoerceToInteger(value) 24 case TypeLong: 25 coerced, err = CoerceToLong(value) 26 case TypeDouble: 27 coerced, err = CoerceToDouble(value) 28 case TypeBoolean: 29 coerced, err = CoerceToBoolean(value) 30 case TypeObject: 31 coerced, err = CoerceToObject(value) 32 case TypeComplexObject: 33 coerced, err = CoerceToComplexObject(value) 34 case TypeArray: 35 coerced, err = CoerceToArrayIfNecessary(value) 36 case TypeParams: 37 coerced, err = CoerceToParams(value) 38 } 39 40 if err != nil { 41 return nil, err 42 } 43 44 return coerced, nil 45 } 46 47 // CoerceToString coerce a value to a string 48 func CoerceToString(val interface{}) (string, error) { 49 50 switch t := val.(type) { 51 case string: 52 return t, nil 53 case int: 54 return strconv.Itoa(t), nil 55 case int64: 56 return strconv.FormatInt(t, 10), nil 57 case float32: 58 return strconv.FormatFloat(float64(t), 'f', -1, 64), nil 59 case float64: 60 return strconv.FormatFloat(t, 'f', -1, 64), nil 61 case json.Number: 62 return t.String(), nil 63 case bool: 64 return strconv.FormatBool(t), nil 65 case nil: 66 return "", nil 67 default: 68 b, err := json.Marshal(t) 69 if err != nil { 70 return "", fmt.Errorf("unable to Coerce %#v to string", t) 71 } 72 return string(b), nil 73 } 74 } 75 76 // CoerceToInteger coerce a value to an integer 77 func CoerceToInteger(val interface{}) (int, error) { 78 switch t := val.(type) { 79 case int: 80 return t, nil 81 case int64: 82 return int(t), nil 83 case float64: 84 return int(t), nil 85 case json.Number: 86 i, err := t.Int64() 87 return int(i), err 88 case string: 89 return strconv.Atoi(t) 90 case bool: 91 if t { 92 return 1, nil 93 } 94 return 0, nil 95 case nil: 96 return 0, nil 97 default: 98 return 0, fmt.Errorf("Unable to coerce %#v to integer", val) 99 } 100 } 101 102 // CoerceToInteger coerce a value to an integer 103 func CoerceToLong(val interface{}) (int64, error) { 104 switch t := val.(type) { 105 case int: 106 return int64(t), nil 107 case int64: 108 return t, nil 109 case float32: 110 return int64(t), nil 111 case float64: 112 return int64(t), nil 113 case json.Number: 114 return t.Int64() 115 case string: 116 return strconv.ParseInt(t, 10, 64) 117 case bool: 118 if t { 119 return 1, nil 120 } 121 return 0, nil 122 case nil: 123 return 0, nil 124 default: 125 return 0, fmt.Errorf("Unable to coerce %#v to integer", val) 126 } 127 } 128 129 // Deprecated: Use CoerceToDouble() 130 func CoerceToNumber(val interface{}) (float64, error) { 131 return CoerceToDouble(val) 132 } 133 134 // CoerceToDouble coerce a value to a double/float64 135 func CoerceToDouble(val interface{}) (float64, error) { 136 switch t := val.(type) { 137 case int: 138 return float64(t), nil 139 case int64: 140 return float64(t), nil 141 case float64: 142 return t, nil 143 case json.Number: 144 return t.Float64() 145 case string: 146 return strconv.ParseFloat(t, 64) 147 case bool: 148 if t { 149 return 1.0, nil 150 } 151 return 0.0, nil 152 case nil: 153 return 0.0, nil 154 default: 155 return 0.0, fmt.Errorf("Unable to coerce %#v to float", val) 156 } 157 } 158 159 // CoerceToBoolean coerce a value to a boolean 160 func CoerceToBoolean(val interface{}) (bool, error) { 161 switch t := val.(type) { 162 case bool: 163 return t, nil 164 case int, int64: 165 return t != 0, nil 166 case float64: 167 return t != 0.0, nil 168 case json.Number: 169 i, err := t.Int64() 170 return i != 0, err 171 case string: 172 return strconv.ParseBool(t) 173 case nil: 174 return false, nil 175 default: 176 str, err := CoerceToString(val) 177 if err != nil { 178 return false, fmt.Errorf("unable to coerce %#v to bool", val) 179 } 180 return strconv.ParseBool(str) 181 } 182 } 183 184 // CoerceToObject coerce a value to an object 185 func CoerceToObject(val interface{}) (map[string]interface{}, error) { 186 187 switch t := val.(type) { 188 case map[string]interface{}: 189 return t, nil 190 case map[string]string: 191 ret := make(map[string]interface{}, len(t)) 192 for key, value := range t { 193 ret[key] = value 194 } 195 return ret, nil 196 case string: 197 m := make(map[string]interface{}) 198 if t != "" { 199 err := json.Unmarshal([]byte(t), &m) 200 if err != nil { 201 return nil, fmt.Errorf("unable to coerce %#v to map[string]interface{}", val) 202 } 203 } 204 return m, nil 205 case nil: 206 return nil, nil 207 default: 208 return nil, fmt.Errorf("unable to coerce %#v to map[string]interface{}", val) 209 } 210 } 211 212 // CoerceToArray coerce a value to an array of empty interface values 213 func CoerceToArray(val interface{}) ([]interface{}, error) { 214 215 switch t := val.(type) { 216 case []interface{}: 217 return t, nil 218 219 case []map[string]interface{}: 220 var a []interface{} 221 for _, v := range t { 222 a = append(a, v) 223 } 224 return a, nil 225 case string: 226 a := make([]interface{}, 0) 227 if t != "" { 228 err := json.Unmarshal([]byte(t), &a) 229 if err != nil { 230 return nil, fmt.Errorf("unable to coerce %#v to map[string]interface{}", val) 231 } 232 } 233 return a, nil 234 case nil: 235 return nil, nil 236 default: 237 s := reflect.ValueOf(val) 238 if s.Kind() == reflect.Slice { 239 a := make([]interface{}, s.Len()) 240 241 for i := 0; i < s.Len(); i++ { 242 a[i] = s.Index(i).Interface() 243 } 244 return a, nil 245 } 246 return nil, fmt.Errorf("unable to coerce %#v to []interface{}", val) 247 } 248 } 249 250 // CoerceToArrayIfNecessary coerce a value to an array if it isn't one already 251 func CoerceToArrayIfNecessary(val interface{}) (interface{}, error) { 252 253 if val == nil { 254 return nil, nil 255 } 256 257 rt := reflect.TypeOf(val).Kind() 258 259 if rt == reflect.Array || rt == reflect.Slice { 260 return val, nil 261 } 262 263 switch t := val.(type) { 264 case string: 265 a := make([]interface{}, 0) 266 if t != "" { 267 err := json.Unmarshal([]byte(t), &a) 268 if err != nil { 269 return nil, fmt.Errorf("unable to coerce %#v to map[string]interface{}", val) 270 } 271 } 272 return a, nil 273 default: 274 return nil, fmt.Errorf("unable to coerce %#v to []interface{}", val) 275 } 276 } 277 278 // CoerceToAny coerce a value to generic value 279 func CoerceToAny(val interface{}) (interface{}, error) { 280 281 switch t := val.(type) { 282 283 case json.Number: 284 if strings.Contains(t.String(), ".") { 285 return t.Float64() 286 } else { 287 return t.Int64() 288 } 289 default: 290 return val, nil 291 } 292 } 293 294 // CoerceToParams coerce a value to params 295 func CoerceToParams(val interface{}) (map[string]string, error) { 296 297 switch t := val.(type) { 298 case map[string]string: 299 return t, nil 300 case string: 301 m := make(map[string]string) 302 if t != "" { 303 err := json.Unmarshal([]byte(t), &m) 304 if err != nil { 305 return nil, fmt.Errorf("unable to coerce %#v to params", val) 306 } 307 } 308 return m, nil 309 case map[string]interface{}: 310 311 var m = make(map[string]string, len(t)) 312 for k, v := range t { 313 314 mVal, err := CoerceToString(v) 315 if err != nil { 316 return nil, err 317 } 318 m[k] = mVal 319 } 320 return m, nil 321 case map[interface{}]string: 322 323 var m = make(map[string]string, len(t)) 324 for k, v := range t { 325 326 mKey, err := CoerceToString(k) 327 if err != nil { 328 return nil, err 329 } 330 m[mKey] = v 331 } 332 return m, nil 333 case map[interface{}]interface{}: 334 335 var m = make(map[string]string, len(t)) 336 for k, v := range t { 337 338 mKey, err := CoerceToString(k) 339 if err != nil { 340 return nil, err 341 } 342 343 mVal, err := CoerceToString(v) 344 if err != nil { 345 return nil, err 346 } 347 m[mKey] = mVal 348 } 349 return m, nil 350 case nil: 351 return nil, nil 352 default: 353 return nil, fmt.Errorf("unable to coerce %#v to map[string]string", val) 354 } 355 } 356 357 // CoerceToObject coerce a value to an complex object 358 func CoerceToComplexObject(val interface{}) (*ComplexObject, error) { 359 //If the val is nil then just return empty struct 360 var emptyComplexObject = &ComplexObject{Value: "{}"} 361 if val == nil { 362 return emptyComplexObject, nil 363 } 364 switch t := val.(type) { 365 case string: 366 if val == "" { 367 return emptyComplexObject, nil 368 } else { 369 complexObject := &ComplexObject{} 370 err := json.Unmarshal([]byte(t), complexObject) 371 if err != nil { 372 return nil, err 373 } 374 return handleComplex(complexObject), nil 375 } 376 case map[string]interface{}: 377 v, err := json.Marshal(val) 378 if err != nil { 379 return nil, err 380 } 381 complexObject := &ComplexObject{} 382 err = json.Unmarshal(v, complexObject) 383 if err != nil { 384 return nil, err 385 } 386 return handleComplex(complexObject), nil 387 case *ComplexObject: 388 return handleComplex(val.(*ComplexObject)), nil 389 default: 390 return nil, fmt.Errorf("unable to coerce %#v to complex object", val) 391 } 392 } 393 394 func handleComplex(complex *ComplexObject) *ComplexObject { 395 if complex != nil { 396 if complex.Value == "" { 397 complex.Value = "{}" 398 } 399 } 400 return complex 401 } 402 403 //var mapHelper *MapHelper = &MapHelper{} 404 // 405 //func GetMapHelper() *MapHelper { 406 // return mapHelper 407 //} 408 // 409 //type MapHelper struct { 410 //} 411 // 412 //func (h *MapHelper) GetInt(data map[string]interface{}, key string) (int, bool) { 413 // mapVal, exists := data[key] 414 // if exists { 415 // value, ok := mapVal.(int) 416 // 417 // if ok { 418 // return value, true 419 // } 420 // } 421 // 422 // return 0, false 423 //} 424 // 425 //func (h *MapHelper) GetString(data map[string]interface{}, key string) (string, bool) { 426 // mapVal, exists := data[key] 427 // if exists { 428 // value, ok := mapVal.(string) 429 // 430 // if ok { 431 // return value, true 432 // } 433 // } 434 // 435 // return "", false 436 //} 437 // 438 //func (h *MapHelper) GetBool(data map[string]interface{}, key string) (bool, bool) { 439 // mapVal, exists := data[key] 440 // if exists { 441 // value, ok := mapVal.(bool) 442 // 443 // if ok { 444 // return value, true 445 // } 446 // } 447 // 448 // return false, false 449 //} 450 // 451 //func (h *MapHelper) ToAttributes(data map[string]interface{}, metadata []*Attribute, ignoreExtras bool) []*Attribute { 452 // 453 // size := len(metadata) 454 // if !ignoreExtras { 455 // size = len(data) 456 // } 457 // attrs := make([]*Attribute, 0, size) 458 // 459 // metadataMap := make(map[string]*Attribute) 460 // for _, attr := range metadata { 461 // metadataMap[attr.Name()] = attr 462 // } 463 // 464 // //todo do special handling for complex_object metadata (merge or ref it) 465 // for key, value := range data { 466 // mdAttr, exists := metadataMap[key] 467 // 468 // if !exists { 469 // if !ignoreExtras { 470 // //todo handle error 471 // attr, _ := NewAttribute(key, TypeAny, value) 472 // attrs = append(attrs, attr) 473 // } 474 // } else { 475 // attr, _ := NewAttribute(key, mdAttr.Type(), value) 476 // attrs = append(attrs, attr) 477 // } 478 // } 479 // 480 // return attrs 481 //}