github.com/keysonzzz/kmg@v0.0.0-20151121023212-05317bfd7d39/kmgType/MapType.go (about)

     1  package kmgType
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  )
     7  
     8  //path -> key(Key type)
     9  //key can be bool,string,stringEnum,int,float,
    10  //map elem CanSet() will be false
    11  //even if map CanSet false , SetMapIndex will success
    12  //if elem change(can not set),map must use SetMapIndex to set it..
    13  type MapType struct {
    14  	reflectTypeGetterImp
    15  	KeyStringConverter StringConverterInterface
    16  	KeyType            KmgType
    17  	ElemType           KmgType
    18  }
    19  
    20  func (t *MapType) Init() (err error) {
    21  	if t.KeyStringConverter != nil {
    22  		return
    23  	}
    24  	t.KeyType, err = TypeOf(t.GetReflectType().Key())
    25  	if err != nil {
    26  		return err
    27  	}
    28  	var ok bool
    29  	t.KeyStringConverter, ok = t.KeyType.(StringConverterInterface)
    30  	if !ok {
    31  		return fmt.Errorf(
    32  			"mapType key type not implement stringConverterType,key: %s",
    33  			t.KeyType.GetReflectType().Kind().String(),
    34  		)
    35  	}
    36  	t.ElemType, err = TypeOf(t.GetReflectType().Elem())
    37  	if err != nil {
    38  		return err
    39  	}
    40  	return nil
    41  }
    42  
    43  func (t *MapType) GetElemByString(v reflect.Value, k string) (ev reflect.Value, et KmgType, err error) {
    44  	err = t.Init()
    45  	if err != nil {
    46  		return
    47  	}
    48  	vk, err := t.KeyStringConverter.FromString(k)
    49  	if err != nil {
    50  		return
    51  	}
    52  	if err != nil {
    53  		return
    54  	}
    55  	ev = v.MapIndex(vk)
    56  	if !ev.IsValid() {
    57  		err = fmt.Errorf("[mapType.getSubValueByString] map key not found k:%s", k)
    58  		return
    59  	}
    60  	et = t.ElemType
    61  	return
    62  }
    63  
    64  func (t *MapType) SaveByPath(v *reflect.Value, path Path, value string) (err error) {
    65  	err = t.Init()
    66  	if err != nil {
    67  		return
    68  	}
    69  	if len(path) == 0 {
    70  		return fmt.Errorf("[mapType.save] get map with no path, value:%s", value)
    71  	}
    72  	//OriginCanSet := v.CanSet()
    73  	if v.IsNil() {
    74  		if v.CanSet() {
    75  			v.Set(reflect.MakeMap(t.GetReflectType()))
    76  		} else {
    77  			*v = reflect.MakeMap(t.GetReflectType())
    78  		}
    79  	}
    80  	vk, err := t.KeyStringConverter.FromString(path[0])
    81  	if err != nil {
    82  		return err
    83  	}
    84  	saveElemV := v.MapIndex(vk)
    85  	KeyNotExist := false
    86  	if !saveElemV.IsValid() {
    87  		saveElemV = reflect.New(t.ElemType.GetReflectType()).Elem()
    88  		KeyNotExist = true
    89  	}
    90  	oElemV := saveElemV
    91  	err = t.ElemType.SaveByPath(&saveElemV, path[1:], value)
    92  	if err != nil {
    93  		return err
    94  	}
    95  	if KeyNotExist {
    96  		v.SetMapIndex(vk, saveElemV)
    97  	}
    98  	if oElemV != saveElemV {
    99  		v.SetMapIndex(vk, saveElemV)
   100  	}
   101  	return nil
   102  }
   103  
   104  func (t *MapType) DeleteByPath(v *reflect.Value, path Path) (err error) {
   105  	err = t.Init()
   106  	if err != nil {
   107  		return
   108  	}
   109  	if len(path) > 1 {
   110  		vk, err := t.KeyStringConverter.FromString(path[0])
   111  		if err != nil {
   112  			return err
   113  		}
   114  		ev := v.MapIndex(vk)
   115  		et := t.ElemType
   116  		oEv := ev
   117  		err = et.DeleteByPath(&ev, path[1:])
   118  		if err != nil {
   119  			return err
   120  		}
   121  		if oEv == ev {
   122  			return nil
   123  		}
   124  		v.SetMapIndex(vk, ev)
   125  		return nil
   126  	} else if len(path) == 0 {
   127  		return fmt.Errorf("[MapType.DeleteByPath] delete map with no path.")
   128  	}
   129  	//Addressable?
   130  	vk, err := t.KeyStringConverter.FromString(path[0])
   131  	if err != nil {
   132  		return err
   133  	}
   134  	v.SetMapIndex(vk, reflect.Value{})
   135  	return nil
   136  }