github.com/keysonzzz/kmg@v0.0.0-20151121023212-05317bfd7d39/webTypeAdmin/fkRefType.go (about) 1 package webTypeAdmin 2 3 import ( 4 "fmt" 5 "html/template" 6 "reflect" 7 8 "github.com/bronze1man/kmg/kmgType" 9 ) 10 11 var fkRefReflectType = reflect.TypeOf((*FkRef)(nil)).Elem() 12 13 type FkRef interface { 14 GetReferenceType() reflect.Type 15 } 16 17 //xxId refer to another object 18 //path -> pass to RefType 19 type fkRefType struct { 20 kmgType.KmgType 21 referenceType adminType 22 referenceContainer reflect.Value 23 keyStringConverter kmgType.StringConverterInterface 24 ctx *context 25 } 26 27 func (t *fkRefType) init() (err error) { 28 if t.referenceType != nil { 29 return 30 } 31 var ok bool 32 rrt := reflect.Zero(t.GetReflectType()).Interface().(FkRef).GetReferenceType() 33 if t.referenceType, err = t.ctx.typeOfFromReflect(rrt); err != nil { 34 return 35 } 36 rc, ok := getFkRefContainerValue(t.ctx.RootValue, rrt) 37 if !ok { 38 return fmt.Errorf("[fkRefType.init] not found referenceContainer name:%s", t.GetReflectType().Name()) 39 } 40 t.referenceContainer = rc 41 if rc.Type().Key() != t.GetReflectType() { 42 return fmt.Errorf("[fkRefType.init] Container key type is not same with self type") 43 } 44 return nil 45 } 46 47 func getFkRefContainerValue(v reflect.Value, rrt reflect.Type) (reflect.Value, bool) { 48 switch v.Kind() { 49 case reflect.Map: 50 if v.Type().Elem() == rrt { 51 return v, true 52 } 53 if v.Type().Elem().Kind() == reflect.Ptr && v.Type().Elem().Elem() == rrt { 54 return v, true 55 } 56 return reflect.Value{}, false 57 case reflect.Ptr: 58 if v.IsNil() { 59 return reflect.Value{}, false 60 } 61 return getFkRefContainerValue(v.Elem(), rrt) 62 case reflect.Struct: 63 //TODO check mutli container 64 len := v.NumField() 65 for i := 0; i < len; i++ { 66 rv, ok := getFkRefContainerValue(v.Field(i), rrt) 67 if ok { 68 return rv, true 69 } 70 } 71 return reflect.Value{}, false 72 //not enter slice 73 //no need to check array 74 default: 75 return reflect.Value{}, false 76 } 77 return reflect.Value{}, false 78 } 79 func (t *fkRefType) HtmlView(v reflect.Value) (html template.HTML, err error) { 80 if err = t.init(); err != nil { 81 return 82 } 83 var templateData selectTemplateData 84 templateData.Value = t.keyStringConverter.ToString(v) 85 for _, vk := range t.referenceContainer.MapKeys() { 86 sk := t.keyStringConverter.ToString(vk) 87 templateData.List = append(templateData.List, sk) 88 } 89 return theTemplate.ExecuteNameToHtml("Select", templateData) 90 } 91 92 func (t *fkRefType) SaveByPath(v *reflect.Value, path kmgType.Path, value string) (err error) { 93 err = t.init() 94 if err != nil { 95 return 96 } 97 vk, err := t.keyStringConverter.FromString(value) 98 if err != nil { 99 return err 100 } 101 vv := t.referenceContainer.MapIndex(vk) 102 if !vv.IsValid() { 103 return fmt.Errorf("[fkRefType.save] save value not in container map:%s", value) 104 } 105 return t.KmgType.SaveByPath(v, path, value) 106 }