- Fixed MR-84
[castle.git] / MonoRail / Castle.MonoRail.Views.Brail / Macros / ComponentMacro.cs
blobf16cc11098a78b5849c6415151378f8e8be0bc54
1 // Copyright 2004-2007 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.Brail
17 using System;
18 using System.Collections;
19 using System.IO;
20 using Boo.Lang.Compiler;
21 using Boo.Lang.Compiler.Ast;
22 using Boo.Lang.Compiler.TypeSystem;
23 using Castle.MonoRail.Framework;
25 public class ComponentMacro : AbstractAstMacro
27 public override Statement Expand(MacroStatement macro)
29 if (macro.Arguments.Count == 0)
30 throw new MonoRailException("Component must be called with a name");
32 Block block = new Block();
34 Method method;
35 Node parent = macro.ParentNode;
36 while((parent is Method) == false)
38 parent = parent.ParentNode;
40 method = (Method) parent;
42 StringLiteralExpression componentName = new StringLiteralExpression(macro.Arguments[0].ToString());
44 MethodInvocationExpression dictionary = CreateParametersDictionary(macro);
47 Expression macroBody = CodeBuilderHelper.CreateCallableFromMacroBody(CodeBuilder, macro);
49 MethodInvocationExpression initContext = new MethodInvocationExpression();
50 initContext.Target = AstUtil.CreateReferenceExpression("Castle.MonoRail.Views.Brail.BrailViewComponentContext");
51 initContext.Arguments.Extend(
52 new Expression[]
54 new SelfLiteralExpression(),
55 macroBody, componentName,
56 AstUtil.CreateReferenceExpression("OutputStream"),
57 dictionary
58 });
60 // compilerContext = BrailViewComponentContext(macroBodyClosure, "componentName", OutputStream, dictionary)
61 block.Add(new BinaryExpression(BinaryOperatorType.Assign,
62 new ReferenceExpression("componentContext"), initContext));
64 // AddViewComponentProperties( compilerContext.ComponentParams )
65 MethodInvocationExpression addProperties = new MethodInvocationExpression(AstUtil.CreateReferenceExpression("AddViewComponentProperties"));
66 addProperties.Arguments.Add(AstUtil.CreateReferenceExpression("componentContext.ComponentParameters"));
67 block.Add(addProperties);
69 InternalLocal viewComponentFactoryLocal = CodeBuilder.DeclareLocal(method, "viewComponentFactory",
70 TypeSystemServices.Map(
71 typeof(IViewComponentFactory)));
72 // viewComponentFactory = context.GetService(IViewComponentFactory)
73 MethodInvocationExpression callService = new MethodInvocationExpression(
74 AstUtil.CreateReferenceExpression("context.GetService"));
75 callService.Arguments.Add(CodeBuilder.CreateTypeofExpression(typeof(IViewComponentFactory)));
77 block.Add(new BinaryExpression(BinaryOperatorType.Assign,
78 CodeBuilder.CreateLocalReference("viewComponentFactory", viewComponentFactoryLocal),
79 callService));
81 // component = viewComponentFactory.Create( componentName)
82 MethodInvocationExpression createComponent = new MethodInvocationExpression(
83 new MemberReferenceExpression(CodeBuilder.CreateLocalReference("viewComponentFactory", viewComponentFactoryLocal),
84 "Create"));
85 createComponent.Arguments.Add(componentName);
86 block.Add(new BinaryExpression(BinaryOperatorType.Assign,
87 new ReferenceExpression("component"),
88 createComponent));
91 AddSections(block, macro);
94 // component.Init(context, componentContext)
95 MethodInvocationExpression initComponent = new MethodInvocationExpression(
96 AstUtil.CreateReferenceExpression("component.Init"));
97 initComponent.Arguments.Extend(
98 new Expression[] {AstUtil.CreateReferenceExpression("context"), new ReferenceExpression("componentContext")});
100 block.Add(initComponent);
102 // component.Render()
103 block.Add(new MethodInvocationExpression(
104 AstUtil.CreateReferenceExpression("component.Render")));
106 // if component.ViewToRender is not null:
107 // OutputSubView("/"+component.ViewToRender, context.CompnentParameters)
108 Block renderView = new Block();
109 MethodInvocationExpression outputSubView = new MethodInvocationExpression(
110 AstUtil.CreateReferenceExpression("OutputSubView"));
111 outputSubView.Arguments.Add(new BinaryExpression(BinaryOperatorType.Addition,
112 new StringLiteralExpression("/"),
113 AstUtil.CreateReferenceExpression("componentContext.ViewToRender")));
115 outputSubView.Arguments.Add(AstUtil.CreateReferenceExpression("componentContext.ComponentParameters"));
116 renderView.Add(outputSubView);
118 block.Add(new IfStatement(AstUtil.CreateReferenceExpression("componentContext.ViewToRender"),
119 renderView, new Block()));
121 // RemoveViewComponentProperties( compilerContext.ComponentParams )
122 MethodInvocationExpression removeProperties = new MethodInvocationExpression(AstUtil.CreateReferenceExpression("RemoveViewComponentProperties"));
123 removeProperties.Arguments.Add(AstUtil.CreateReferenceExpression("componentContext.ComponentParameters"));
124 block.Add(removeProperties);
126 return block;
129 private static void AddSections(Block block, MacroStatement macro)
131 IDictionary sections = (IDictionary)macro["sections"];
132 if (sections == null)
133 return;
134 foreach(DictionaryEntry entry in sections)
136 block.Add((Block)entry.Value);
140 private static MethodInvocationExpression CreateParametersDictionary(MacroStatement macro)
142 // Make sure that hash table is an case insensitive one.
143 MethodInvocationExpression dictionary = new MethodInvocationExpression();
144 dictionary.Target = AstUtil.CreateReferenceExpression("System.Collections.Hashtable");
146 //If component has parameters, add them
147 if (macro.Arguments.Count == 2)
148 dictionary.Arguments.Add(macro.Arguments[1]);
150 dictionary.Arguments.Add(
151 AstUtil.CreateReferenceExpression("System.Collections.CaseInsensitiveHashCodeProvider.Default"));
152 dictionary.Arguments.Add(AstUtil.CreateReferenceExpression("System.Collections.CaseInsensitiveComparer.Default"));
153 return dictionary;