1 // Copyright 2004-2007 Castle Project - http://www.castleproject.org/
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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
18 using System
.Collections
;
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();
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(
54 new SelfLiteralExpression(),
55 macroBody
, componentName
,
56 AstUtil
.CreateReferenceExpression("OutputStream"),
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
),
81 // component = viewComponentFactory.Create( componentName)
82 MethodInvocationExpression createComponent
= new MethodInvocationExpression(
83 new MemberReferenceExpression(CodeBuilder
.CreateLocalReference("viewComponentFactory", viewComponentFactoryLocal
),
85 createComponent
.Arguments
.Add(componentName
);
86 block
.Add(new BinaryExpression(BinaryOperatorType
.Assign
,
87 new ReferenceExpression("component"),
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
);
129 private static void AddSections(Block block
, MacroStatement macro
)
131 IDictionary sections
= (IDictionary
)macro
["sections"];
132 if (sections
== null)
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"));