Add API Framework Revel Source Files
[iec.git] / src / foundation / api / revel / template_adapter_go.go
1 package revel
2
3 import (
4         "html/template"
5         "io"
6         "log"
7         "strings"
8 )
9
10 const GO_TEMPLATE = "go"
11
12 // Called on startup, initialized when the REVEL_BEFORE_MODULES_LOADED is called
13 func init() {
14         AddInitEventHandler(func(typeOf Event, value interface{}) (responseOf EventResponse) {
15                 if typeOf == REVEL_BEFORE_MODULES_LOADED {
16                         RegisterTemplateLoader(GO_TEMPLATE, func(loader *TemplateLoader) (TemplateEngine, error) {
17                                 // Set the template delimiters for the project if present, then split into left
18                                 // and right delimiters around a space character
19
20                                 TemplateDelims := Config.StringDefault("template.go.delimiters", "")
21                                 var splitDelims []string
22                                 if TemplateDelims != "" {
23                                         splitDelims = strings.Split(TemplateDelims, " ")
24                                         if len(splitDelims) != 2 {
25                                                 log.Fatalln("app.conf: Incorrect format for template.delimiters")
26                                         }
27                                 }
28
29                                 return &GoEngine{
30                                         loader:          loader,
31                                         templateSet:     template.New("__root__").Funcs(TemplateFuncs),
32                                         templatesByName: map[string]*GoTemplate{},
33                                         splitDelims:     splitDelims,
34                                 }, nil
35                         })
36                 }
37                 return
38         })
39 }
40
41 // Adapter for Go Templates.
42 type GoTemplate struct {
43         *template.Template
44         engine *GoEngine
45         *TemplateView
46 }
47
48 // return a 'revel.Template' from Go's template.
49 func (gotmpl GoTemplate) Render(wr io.Writer, arg interface{}) error {
50         return gotmpl.Execute(wr, arg)
51 }
52
53 // The main template engine for Go
54 type GoEngine struct {
55         // The template loader
56         loader *TemplateLoader
57         // THe current template set
58         templateSet *template.Template
59         // A map of templates by name
60         templatesByName map[string]*GoTemplate
61         // The delimiter that is used to indicate template code, defaults to {{
62         splitDelims []string
63         // True if map is case insensitive
64         CaseInsensitive bool
65 }
66
67 // Convert the path to lower case if needed
68 func (i *GoEngine) ConvertPath(path string) string {
69         if i.CaseInsensitive {
70                 return strings.ToLower(path)
71         }
72         return path
73 }
74
75 // Returns true if this engine can handle the response
76 func (i *GoEngine) Handles(templateView *TemplateView) bool {
77         return EngineHandles(i, templateView)
78 }
79
80 // Parses the template vide and adds it to the template set
81 func (engine *GoEngine) ParseAndAdd(baseTemplate *TemplateView) error {
82         // If alternate delimiters set for the project, change them for this set
83         if engine.splitDelims != nil && strings.Index(baseTemplate.Location(), ViewsPath) > -1 {
84                 engine.templateSet.Delims(engine.splitDelims[0], engine.splitDelims[1])
85         } else {
86                 // Reset to default otherwise
87                 engine.templateSet.Delims("", "")
88         }
89         templateSource := string(baseTemplate.FileBytes)
90         templateName := engine.ConvertPath(baseTemplate.TemplateName)
91         tpl, err := engine.templateSet.New(baseTemplate.TemplateName).Parse(templateSource)
92         if nil != err {
93                 _, line, description := ParseTemplateError(err)
94                 return &Error{
95                         Title:       "Template Compilation Error",
96                         Path:        baseTemplate.TemplateName,
97                         Description: description,
98                         Line:        line,
99                         SourceLines: strings.Split(templateSource, "\n"),
100                 }
101         }
102         engine.templatesByName[templateName] = &GoTemplate{Template: tpl, engine: engine, TemplateView: baseTemplate}
103         return nil
104 }
105
106 // Lookups the template name, to see if it is contained in this engine
107 func (engine *GoEngine) Lookup(templateName string) Template {
108         // Case-insensitive matching of template file name
109         if tpl, found := engine.templatesByName[engine.ConvertPath(templateName)]; found {
110                 return tpl
111         }
112         return nil
113 }
114
115 // Return the engine name
116 func (engine *GoEngine) Name() string {
117         return GO_TEMPLATE
118 }
119
120 // An event listener to listen for Revel INIT events
121 func (engine *GoEngine) Event(action Event, i interface{}) {
122         if action == TEMPLATE_REFRESH_REQUESTED {
123                 // At this point all the templates have been passed into the
124                 engine.templatesByName = map[string]*GoTemplate{}
125                 engine.templateSet = template.New("__root__").Funcs(TemplateFuncs)
126                 // Check to see what should be used for case sensitivity
127                 engine.CaseInsensitive = Config.BoolDefault("go.template.caseinsensitive", true)
128         }
129 }