Fixing an issue with output parameters that are of type IntPtr
[castle.git] / Experiments / IronPythonViewEngine / Castle.MonoRail.Views.IronView / IronPythonTemplateParser.cs
blobe0751434f8a9b647e4d5a905ba75147bd3e17e4d
1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle.MonoRail.Views.IronView
17 using System;
18 using System.Collections.Generic;
19 using System.IO;
20 using System.Text;
21 using System.Xml;
23 public class IronPythonTemplateParser : ITemplateParser
25 private IElementProcessor[] processors;
26 private Stack<IElementProcessor> processorStack = new Stack<IElementProcessor>();
28 /// <summary>
29 /// Initializes a new instance of the <see cref="IronPythonTemplateParser"/> class.
30 /// </summary>
31 /// <param name="processors">The processors.</param>
32 public IronPythonTemplateParser(IElementProcessor[] processors)
34 this.processors = processors;
37 public String CreateScriptBlock(TextReader reader, String viewName,
38 IServiceProvider serviceProvider, ITemplateEngine engine)
40 XmlTextReader xmlReader = new XmlTextReader(reader);
41 xmlReader.Namespaces = false;
42 xmlReader.WhitespaceHandling = WhitespaceHandling.All;
44 DefaultContext context = new DefaultContext(viewName, xmlReader, serviceProvider, engine);
46 ProcessReader(context, 0);
48 return context.Script.ToString();
51 public string CreateFunctionScriptBlock(StreamReader reader, string partialViewName, string methodName,
52 IServiceProvider provider, ITemplateEngine engine, params String[] parameters)
54 XmlTextReader xmlReader = new XmlTextReader(reader);
55 xmlReader.Namespaces = false;
56 xmlReader.WhitespaceHandling = WhitespaceHandling.All;
58 DefaultContext context = new DefaultContext(partialViewName, xmlReader, provider, engine);
60 context.Script.Append("def ");
61 context.Script.Append(methodName);
62 context.Script.Append('(');
63 context.Script.Append("controller, context, request, response, session, output, flash, siteroot");
64 // context.Script.Append("output");
65 foreach(String param in parameters)
67 context.Script.Append(',');
68 context.Script.Append(param);
70 context.Script.Append(')');
71 context.Script.AppendLine(":");
73 context.IncreaseIndentation();
75 // context.AppendLineIndented("print 'hello'");
77 ProcessReader(context, 0);
79 context.DecreaseIndentation();
81 context.Script.AppendLine();
83 return context.Script.ToString();
86 #region ITemplateParser
88 public void ProcessReader(ITemplateContext context, int levelToStop)
90 XmlReader reader = context.Reader;
92 while(reader.Read())
94 switch(reader.NodeType)
96 case XmlNodeType.Comment:
97 break;
99 case XmlNodeType.ProcessingInstruction:
101 if (IsCustomPI(context))
103 ProcessPI(context);
105 else
107 OutputCurrentElementAsContent(context);
109 break;
111 case XmlNodeType.Element:
113 context.IncreaseDepth();
115 if (IsCustomElement(reader))
117 ProcessCustomTag(context);
119 else
121 OutputCurrentElementAsContent(context);
124 if (!reader.IsEmptyElement)
126 context.DecreaseDepth();
129 break;
131 case XmlNodeType.EndElement:
133 OutputCurrentElementAsContent(context);
135 context.DecreaseDepth();
137 if (context.CurrentElementDepth == levelToStop)
139 return;
142 break;
144 case XmlNodeType.Text:
145 case XmlNodeType.Whitespace:
146 OutputCurrentElementAsContent(context);
147 break;
149 case XmlNodeType.DocumentType:
150 OutputCurrentElementAsContent(context);
151 break;
156 public void OutputCurrentElementAsContent(ITemplateContext context)
158 OutputCurrentElementAsContent(context, null);
161 public void OutputCurrentElementAsContent(ITemplateContext context, FilterAttribute filter)
163 context.AppendIndented("output.Write('");
165 XmlReader reader = context.Reader;
166 StringBuilder script = context.Script;
168 if (reader.NodeType == XmlNodeType.Element)
170 if (reader.IsEmptyElement)
172 script.Append("<" + reader.LocalName);
173 OutputAttributes(reader, script, filter);
174 script.Append(" />");
176 else
178 script.Append("<");
179 script.Append(reader.LocalName);
180 OutputAttributes(reader, script, filter);
181 script.Append(">");
184 else if (reader.NodeType == XmlNodeType.EndElement)
186 script.Append("</");
187 script.Append(reader.LocalName);
188 script.Append(">");
190 else if (reader.NodeType == XmlNodeType.ProcessingInstruction)
192 script.Append("<?");
193 script.Append(reader.LocalName);
194 script.Append(' ');
195 script.Append(reader.Value);
196 script.Append(" ?>");
198 else if (reader.NodeType == XmlNodeType.Text ||
199 reader.NodeType == XmlNodeType.Whitespace)
201 script.Append(ConvertEscapes(reader.Value));
204 script.AppendLine("')");
207 #endregion
209 private bool IsCustomPI(ITemplateContext context)
211 foreach(IElementProcessor processor in processors)
213 if (processor.CanHandlePI(context.Reader.LocalName, context.Reader.Value))
215 processorStack.Push(processor);
217 return true;
221 return false;
224 private void ProcessPI(ITemplateContext context)
226 processorStack.Pop().ProcessPI(this, context);
229 private bool IsCustomElement(XmlReader reader)
231 foreach(IElementProcessor processor in processors)
233 if (processor.CanHandleElement(this, reader))
235 processorStack.Push(processor);
237 return true;
241 return false;
244 private void ProcessCustomTag(ITemplateContext context)
246 processorStack.Pop().ProcessElement(this, context);
249 private void OutputAttributes(XmlReader reader, StringBuilder script, FilterAttribute filter)
251 if (!reader.HasAttributes) return;
253 if (!reader.MoveToFirstAttribute()) return;
257 String name = reader.LocalName;
259 if (filter != null && !filter(name))
261 continue;
264 script.Append(' ');
265 script.Append(name);
266 script.Append('=');
267 script.Append('\"');
268 script.Append(reader.Value);
269 script.Append('\"');
271 } while(reader.MoveToNextAttribute());
274 private string ConvertEscapes(string value)
276 if (value == null || value == String.Empty) return String.Empty;
278 // TODO: This can be greatly optimized
280 return value.Replace("\t", "\\t").Replace("\n", "\\n").Replace("\r", "\\r");