/framework/starter.go

http://github.com/sut-go/gon · Go · 134 lines · 105 code · 21 blank · 8 comment · 30 complexity · e17b5a22b646ab75383815781fbb48e5 MD5 · raw file

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