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  //}