PageRenderTime 70ms CodeModel.GetById 51ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 0ms

/framework/starter.go

http://github.com/sut-go/gon
Go | 134 lines | 105 code | 21 blank | 8 comment | 30 complexity | e17b5a22b646ab75383815781fbb48e5 MD5 | raw file
  1package starter
  2
  3import "web"
  4import "reflect"
  5import "mustache"
  6import C "app/controller"
  7import "framework/mv"
  8import "framework/gon"
  9import "strings"
 10import "app/conf/bean"
 11import "app/conf/bootstrap"
 12
 13const APP_VIEW_PATH = "app/view/"
 14
 15func Start() {
 16    bean.Initialize()
 17    bootstrap.BootStrap(bean.DefaultAppContext)
 18}
 19
 20func Get(context *web.Context, val string) {
 21    internalGet(context, val)
 22}
 23
 24func internalGet(context gon.WebContext, val string) {
 25    if( len(val) == 0) {
 26        renderRoot(context)
 27        return
 28    }
 29
 30    controllerName, actionName := splitControllerAndAction(val)
 31
 32    if controllerType, ok := C.Controllers[controllerName]; ok {
 33
 34        actionMethName := toUpperFirstLetter(actionName)
 35        if action, found := findMethod(actionMethName, controllerType); found {
 36            conValue := instantiateAndInjectController(context, controllerType);
 37            ret := action.Call([]reflect.Value{conValue})
 38            if len(ret) == 2 {
 39                // return Model and View
 40                renderWithActionName(context, ret, controllerName)
 41            } else if len(ret) == 1 {
 42                // return Model or View
 43                renderDefault(context, ret, controllerName, actionName)
 44            }
 45        }
 46
 47    }
 48    return
 49}
 50
 51func splitControllerAndAction(value string) (string,string) {
 52    controllerAndActionName := strings.Split(value,"/")
 53    controllerName := ""
 54    actionName := ""
 55
 56    if len(controllerAndActionName) == 2 {
 57        controllerName,actionName = controllerAndActionName[0],controllerAndActionName[1]
 58        if actionName == "" {
 59            actionName = "index"
 60        }
 61    } else if len(controllerAndActionName) == 1 {
 62        controllerName = controllerAndActionName[0]
 63        actionName = "index"
 64    }
 65
 66    return controllerName, actionName
 67}
 68
 69func toUpperFirstLetter(name string) string {
 70    if name == "" {
 71        return ""
 72    } else if len(name) == 1 {
 73        return strings.ToUpper(name)
 74    }
 75    return strings.ToUpper(string(name[0:1])) + name[1:]
 76}
 77
 78func findMethod(actionMethName string, controllerType reflect.Type) (reflect.Value, bool) {
 79    controllerTypePtr := reflect.PtrTo(controllerType)
 80    var actionMeth reflect.Method
 81    found := false
 82    numMethod := controllerTypePtr.NumMethod()
 83    for i := 0; i < numMethod; i++ {
 84        if controllerTypePtr.Method(i).Name == actionMethName {
 85            actionMeth = controllerTypePtr.Method(i)
 86            found = true
 87            break
 88        }
 89    }
 90    return actionMeth.Func, found
 91}
 92
 93func renderWithActionName(context gon.WebContext, ret []reflect.Value, controllerName string) {
 94    model := ret[0].Interface().(mv.Model)
 95    view  := ret[1].Interface().(mv.View )
 96    actionName := view.String()
 97    context.WriteString(mustache.RenderFile(APP_VIEW_PATH + controllerName + "/" + actionName + ".m", model))
 98}
 99
100func renderDefault(context gon.WebContext, ret []reflect.Value, controllerName string, actionName string) {
101    if model,ok := ret[0].Interface().(mv.Model); ok {
102        context.WriteString(mustache.RenderFile(APP_VIEW_PATH + controllerName + "/" + actionName + ".m", model))
103    } else if view,ok := ret[0].Interface().(mv.View); ok {
104        actionName = view.String()
105        context.WriteString(mustache.RenderFile(APP_VIEW_PATH + controllerName + "/" + actionName + ".m"))
106    }
107}
108
109func renderRoot(context gon.WebContext){
110    context.WriteString(mustache.RenderFile(APP_VIEW_PATH + "main.m"))
111}
112
113func instantiateAndInjectController(context gon.WebContext, controllerType reflect.Type) reflect.Value {
114    // Instantiate a controller
115    conValue := reflect.New(controllerType)
116    conIndirect := reflect.Indirect(conValue)
117
118    // Inject Params
119    conIndirect.FieldByName("Params").Set(reflect.ValueOf(context.GetParams()))
120
121    //
122    // Inject beans
123    // This loop tends to be slow. We should loop over field names and look-up a bean.
124    //
125    for beanName,setterFunc := range bean.Registry() {
126        if _, ok := controllerType.FieldByName(beanName); ok {
127            if field := conIndirect.FieldByName(beanName); field.IsValid() {
128                field.Set(reflect.ValueOf(setterFunc()))
129            }
130        }
131    }
132    return conValue
133}
134