Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
Compiler.cs
Go to the documentation of this file.
5using System.IO;
6using System.Text;
11
13
14internal class Compiler
15{
17 {
18 private readonly string _baseUri;
19
20 private readonly int _lineNumber;
21
22 private readonly int _linePosition;
23
24 public ErrorXPathExpression(string expression, string baseUri, int lineNumber, int linePosition)
26 {
27 _baseUri = baseUri;
28 _lineNumber = lineNumber;
29 _linePosition = linePosition;
30 }
31
32 public override XPathExpression Clone()
33 {
34 return this;
35 }
36
37 public override void CheckErrors()
38 {
39 throw new XsltException(System.SR.Xslt_InvalidXPath, new string[1] { Expression }, _baseUri, _linePosition, _lineNumber, null);
40 }
41 }
42
44
45 private int _stylesheetid;
46
48
50
52
54
56
58
60
62
64
66
68
70
72
74
75 private readonly QueryBuilder _queryBuilder = new QueryBuilder();
76
77 private int _rtfCount;
78
79 public bool AllowBuiltInMode;
80
81 public static XmlQualifiedName BuiltInMode = new XmlQualifiedName("*", string.Empty);
82
83 private readonly Hashtable[] _typeDeclsByLang = new Hashtable[3]
84 {
85 new Hashtable(),
86 new Hashtable(),
87 new Hashtable()
88 };
89
91
92 internal int Stylesheetid
93 {
94 get
95 {
96 return _stylesheetid;
97 }
98 set
99 {
101 }
102 }
103
105
106 internal NavigatorInput Input => _input;
107
109
111 {
112 get
113 {
114 return _rootAction;
115 }
116 set
117 {
120 }
121 }
122
124
126 {
127 get
128 {
130 }
131 set
132 {
134 }
135 }
136
138 {
139 get
140 {
142 }
143 set
144 {
146 }
147 }
148
150
152
153 internal bool Advance()
154 {
155 return Document.Advance();
156 }
157
158 internal bool Recurse()
159 {
160 return Document.Recurse();
161 }
162
163 internal bool ToParent()
164 {
165 return Document.ToParent();
166 }
167
168 internal string GetUnicRtfId()
169 {
170 _rtfCount++;
171 return _rtfCount.ToString(CultureInfo.InvariantCulture);
172 }
173
175 {
180 try
181 {
184 try
185 {
187 }
189 {
190 throw;
191 }
192 catch (Exception inner)
193 {
194 throw new XsltCompileException(inner, Input.BaseURI, Input.LineNumber, Input.LinePosition);
195 }
199 if (_globalNamespaceAliasTable != null)
200 {
203 }
204 }
205 finally
206 {
208 }
209 }
210
211 internal void InsertExtensionNamespace(string value)
212 {
213 string[] array = ResolvePrefixes(value);
214 if (array != null)
215 {
217 }
218 }
219
220 internal void InsertExcludedNamespace(string value)
221 {
222 string[] array = ResolvePrefixes(value);
223 if (array != null)
224 {
226 }
227 }
228
230 {
231 InsertExtensionNamespace(Input.Navigator.GetAttribute(Input.Atoms.ExtensionElementPrefixes, Input.Atoms.UriXsl));
232 }
233
235 {
236 InsertExcludedNamespace(Input.Navigator.GetAttribute(Input.Atoms.ExcludeResultPrefixes, Input.Atoms.UriXsl));
237 }
238
239 internal bool IsExtensionNamespace(string nspace)
240 {
242 }
243
244 internal bool IsExcludedNamespace(string nspace)
245 {
247 }
248
249 internal void PushLiteralScope()
250 {
252 string attribute = Input.Navigator.GetAttribute(Atoms.Version, Atoms.UriXsl);
253 if (attribute.Length != 0)
254 {
256 }
257 }
258
259 internal void PushNamespaceScope()
260 {
263 if (input.MoveToFirstNamespace())
264 {
265 do
266 {
267 _scopeManager.PushNamespace(input.LocalName, input.Value);
268 }
269 while (input.MoveToNextNamespace());
270 input.ToParent();
271 }
272 }
273
279
281 {
282 return _scopeManager.Clone();
283 }
284
286 {
288 VariableAction variableAction = inputScope.ResolveVariable(variable.Name);
289 if (variableAction != null)
290 {
291 if (!variableAction.IsGlobal)
292 {
294 }
295 if (variable.IsGlobal)
296 {
297 if (variable.Stylesheetid == variableAction.Stylesheetid)
298 {
300 }
301 if (variable.Stylesheetid < variableAction.Stylesheetid)
302 {
303 inputScope.InsertVariable(variable);
304 return variableAction.VarKey;
305 }
306 return -1;
307 }
308 }
309 inputScope.InsertVariable(variable);
311 }
312
324
325 internal bool IsNamespaceAlias(string StylesheetURI)
326 {
327 if (_globalNamespaceAliasTable == null)
328 {
329 return false;
330 }
332 }
333
335 {
336 if (_globalNamespaceAliasTable != null)
337 {
339 }
340 return null;
341 }
342
343 internal string ResolveXmlNamespace(string prefix)
344 {
346 }
347
348 internal string ResolveXPathNamespace(string prefix)
349 {
351 }
352
353 internal void InsertKey(XmlQualifiedName name, int MatchKey, int UseKey)
354 {
355 _rootAction.InsertKey(name, MatchKey, UseKey);
356 }
357
362
363 private string[] ResolvePrefixes(string tokens)
364 {
365 if (tokens == null || tokens.Length == 0)
366 {
367 return null;
368 }
370 try
371 {
372 for (int i = 0; i < array.Length; i++)
373 {
374 string text = array[i];
375 array[i] = _scopeManager.ResolveXmlNamespace((text == "#default") ? string.Empty : text);
376 }
377 return array;
378 }
379 catch (XsltException)
380 {
382 {
383 throw;
384 }
385 return null;
386 }
387 }
388
389 internal bool GetYesNo(string value)
390 {
391 if (value == "yes")
392 {
393 return true;
394 }
395 if (value == "no")
396 {
397 return false;
398 }
399 throw XsltException.Create(System.SR.Xslt_InvalidAttrValue, Input.LocalName, value);
400 }
401
402 internal string GetSingleAttribute(string attributeAtom)
403 {
405 string localName = input.LocalName;
406 string text = null;
407 if (input.MoveToFirstAttribute())
408 {
409 do
410 {
411 string namespaceURI = input.NamespaceURI;
412 string localName2 = input.LocalName;
413 if (namespaceURI.Length == 0)
414 {
416 {
417 text = input.Value;
418 }
419 else if (!ForwardCompatibility)
420 {
422 }
423 }
424 }
425 while (input.MoveToNextAttribute());
426 input.ToParent();
427 }
428 if (text == null)
429 {
431 }
432 return text;
433 }
434
440
446
448 {
449 reader.EntityHandling = EntityHandling.ExpandEntities;
451 try
452 {
453 return new XPathDocument(reader, XmlSpace.Preserve);
454 }
455 finally
456 {
457 reader.Close();
458 }
459 }
460
461 private void AddDocumentURI(string href)
462 {
463 _documentURIs.Add(href, null);
464 }
465
466 private void RemoveDocumentURI(string href)
467 {
469 }
470
471 internal bool IsCircularReference(string href)
472 {
474 }
475
476 internal Uri ResolveUri(string relativeUri)
477 {
478 string baseURI = Input.BaseURI;
479 Uri uri = _xmlResolver.ResolveUri((baseURI.Length != 0) ? _xmlResolver.ResolveUri(null, baseURI) : null, relativeUri);
480 if (uri == null)
481 {
483 }
484 return uri;
485 }
486
488 {
489 object entity = _xmlResolver.GetEntity(absoluteUri, null, null);
490 string text = absoluteUri.ToString();
491 if (entity is Stream)
492 {
495 return new NavigatorInput(LoadDocument(xmlTextReaderImpl).CreateNavigator(), text, _rootScope);
496 }
497 if (entity is XPathNavigator)
498 {
499 return new NavigatorInput((XPathNavigator)entity, text, _rootScope);
500 }
502 }
503
513
514 internal void PopInputDocument()
515 {
517 _input = input.Next;
518 input.Next = null;
519 if (_input != null)
520 {
523 }
524 else
525 {
526 _atoms = null;
527 _scopeManager = null;
528 }
530 input.Close();
531 }
532
534 {
535 if (_stylesheets == null)
536 {
538 }
541 }
542
544 {
545 Stylesheet result = _stylesheets.Pop();
546 stylesheet = _stylesheets.Peek();
547 return result;
548 }
549
554
555 internal void AddTemplate(TemplateAction template)
556 {
557 stylesheet.AddTemplate(template);
558 }
559
560 internal void BeginTemplate(TemplateAction template)
561 {
562 _currentTemplate = template;
563 _currentMode = template.Mode;
565 }
566
567 internal void EndTemplate()
568 {
570 }
571
572 internal int AddQuery(string xpathQuery)
573 {
574 return AddQuery(xpathQuery, allowVar: true, allowKey: true, isPattern: false);
575 }
576
577 internal int AddQuery(string xpathQuery, bool allowVar, bool allowKey, bool isPattern)
578 {
580 try
581 {
583 }
584 catch (XPathException inner)
585 {
587 {
588 throw XsltException.Create(System.SR.Xslt_InvalidXPath, new string[1] { xpathQuery }, inner);
589 }
590 compiledQuery = new ErrorXPathExpression(xpathQuery, Input.BaseURI, Input.LineNumber, Input.LinePosition);
591 }
593 return _queryStore.Count - 1;
594 }
595
596 internal int AddStringQuery(string xpathQuery)
597 {
598 string xpathQuery2 = (XmlCharType.IsOnlyWhitespace(xpathQuery) ? xpathQuery : ("string(" + xpathQuery + ")"));
599 return AddQuery(xpathQuery2);
600 }
601
602 internal int AddBooleanQuery(string xpathQuery)
603 {
604 string xpathQuery2 = (XmlCharType.IsOnlyWhitespace(xpathQuery) ? xpathQuery : ("boolean(" + xpathQuery + ")"));
605 return AddQuery(xpathQuery2);
606 }
607
608 internal void AddScript(string source, ScriptingLanguage lang, string ns, string fileName, int lineNumber)
609 {
610 ValidateExtensionNamespace(ns);
612 {
613 Hashtable hashtable = _typeDeclsByLang[(int)scriptingLanguage];
614 if (lang == scriptingLanguage)
615 {
617 }
618 if (hashtable.Contains(ns))
619 {
621 }
622 }
623 }
624
625 private static void ValidateExtensionNamespace(string nsUri)
626 {
627 if (nsUri.Length == 0 || nsUri == "http://www.w3.org/1999/XSL/Transform")
628 {
630 }
631 XmlConvert.ToUri(nsUri);
632 }
633
634 public string GetNsAlias(ref string prefix)
635 {
636 if (prefix == "#default")
637 {
638 prefix = string.Empty;
639 return DefaultNamespace;
640 }
642 {
644 }
645 return ResolveXPathNamespace(prefix);
646 }
647
648 private static void getTextLex(string avt, ref int start, StringBuilder lex)
649 {
650 int length = avt.Length;
651 int i;
652 char c;
653 for (i = start; i < length; lex.Append(c), i++)
654 {
655 c = avt[i];
656 switch (c)
657 {
658 case '{':
659 if (i + 1 < length && avt[i + 1] == '{')
660 {
661 i++;
662 continue;
663 }
664 break;
665 case '}':
666 if (i + 1 < length && avt[i + 1] == '}')
667 {
668 i++;
669 continue;
670 }
672 default:
673 continue;
674 }
675 break;
676 }
677 start = i;
678 }
679
680 private static void getXPathLex(string avt, ref int start, StringBuilder lex)
681 {
682 int length = avt.Length;
683 int num = 0;
684 for (int i = start + 1; i < length; i++)
685 {
686 char c = avt[i];
687 switch (num)
688 {
689 case 0:
690 switch (c)
691 {
692 case '{':
694 case '}':
695 i++;
696 if (i == start + 2)
697 {
699 }
700 lex.Append(avt, start + 1, i - start - 2);
701 start = i;
702 return;
703 case '\'':
704 num = 1;
705 break;
706 case '"':
707 num = 2;
708 break;
709 }
710 break;
711 case 1:
712 if (c == '\'')
713 {
714 num = 0;
715 }
716 break;
717 case 2:
718 if (c == '"')
719 {
720 num = 0;
721 }
722 break;
723 }
724 }
726 }
727
728 private static bool GetNextAvtLex(string avt, ref int start, StringBuilder lex, out bool isAvt)
729 {
730 isAvt = false;
731 if (start == avt.Length)
732 {
733 return false;
734 }
735 lex.Length = 0;
736 getTextLex(avt, ref start, lex);
737 if (lex.Length == 0)
738 {
739 isAvt = true;
740 getXPathLex(avt, ref start, lex);
741 }
742 return true;
743 }
744
745 internal ArrayList CompileAvt(string avtText, out bool constant)
746 {
748 constant = true;
749 int start = 0;
750 bool isAvt;
751 while (GetNextAvtLex(avtText, ref start, AvtStringBuilder, out isAvt))
752 {
753 string text = AvtStringBuilder.ToString();
754 if (isAvt)
755 {
756 arrayList.Add(new AvtEvent(AddStringQuery(text)));
757 constant = false;
758 }
759 else
760 {
762 }
763 }
764 return arrayList;
765 }
766
767 internal ArrayList CompileAvt(string avtText)
768 {
769 bool constant;
770 return CompileAvt(avtText, out constant);
771 }
772
779
786
788 {
790 attributeAction.Compile(this);
791 return attributeAction;
792 }
793
800
807
809 {
811 chooseAction.Compile(this);
812 return chooseAction;
813 }
814
816 {
818 commentAction.Compile(this);
819 return commentAction;
820 }
821
823 {
825 copyAction.Compile(this);
826 return copyAction;
827 }
828
830 {
832 copyOfAction.Compile(this);
833 return copyOfAction;
834 }
835
837 {
839 elementAction.Compile(this);
840 return elementAction;
841 }
842
844 {
846 forEachAction.Compile(this);
847 return forEachAction;
848 }
849
851 {
853 ifAction.Compile(this);
854 return ifAction;
855 }
856
858 {
860 messageAction.Compile(this);
861 return messageAction;
862 }
863
870
872 {
874 numberAction.Compile(this);
875 return numberAction;
876 }
877
884
885 public virtual void CreateRootAction()
886 {
887 RootAction = new RootAction();
888 RootAction.Compile(this);
889 }
890
892 {
894 sortAction.Compile(this);
895 return sortAction;
896 }
897
899 {
901 templateAction.Compile(this);
902 return templateAction;
903 }
904
906 {
908 templateAction.CompileSingle(this);
909 return templateAction;
910 }
911
913 {
915 textAction.Compile(this);
916 return textAction;
917 }
918
925
927 {
929 valueOfAction.Compile(this);
930 return valueOfAction;
931 }
932
934 {
936 variableAction.Compile(this);
937 if (variableAction.VarKey != -1)
938 {
939 return variableAction;
940 }
941 return null;
942 }
943
945 {
947 withParamAction.Compile(this);
948 return withParamAction;
949 }
950
952 {
953 return new BeginEvent(this);
954 }
955
956 public virtual TextEvent CreateTextEvent()
957 {
958 return new TextEvent(this);
959 }
960
962 {
963 XPathNavigator xPathNavigator = Input.Navigator.Clone();
964 string name = xPathNavigator.Name;
965 xPathNavigator.MoveToParent();
966 string name2 = xPathNavigator.Name;
968 }
969}
Query Build(AstNode root, string query)
Query BuildPatternQuery(string query, bool allowVar, bool allowKey)
void Add(TKey key, TValue value)
virtual bool Contains(object key)
Definition Hashtable.cs:719
static CultureInfo InvariantCulture
static string Xslt_MissingAttribute
Definition SR.cs:1882
static string Xslt_InvalidXPath
Definition SR.cs:2090
static string Xslt_OpenBracesAvt
Definition SR.cs:2082
static string Xslt_EmptyAvtExpr
Definition SR.cs:2088
static string Xslt_InvalidAttrValue
Definition SR.cs:1884
static string Xslt_OpenLiteralAvt
Definition SR.cs:2084
static string Xslt_DupVarName
Definition SR.cs:2096
static string Xslt_CantResolve
Definition SR.cs:2078
static string Xslt_UnexpectedKeyword
Definition SR.cs:2074
static string Xslt_NestedAvt
Definition SR.cs:2086
static string Xslt_SingleRightAvt
Definition SR.cs:2080
static string Xslt_ScriptMixedLanguages
Definition SR.cs:1932
static string Xslt_InvalidAttribute
Definition SR.cs:1880
static string CompilingScriptsNotSupported
Definition SR.cs:2148
static string Xslt_InvalidExtensionNamespace
Definition SR.cs:2124
Definition SR.cs:7
override string ToString()
static bool Equal(string strA, string strB)
Definition Ref.cs:5
static bool IsOnlyWhitespace(string str)
static string[] SplitString(string value)
static Uri ToUri(string s)
object? GetEntity(Uri absoluteUri, string? role, Type? ofObjectToReturn)
virtual Uri ResolveUri(Uri? baseUri, string? relativeUri)
static XsltException Create(string res, params string[] args)
ErrorXPathExpression(string expression, string baseUri, int lineNumber, int linePosition)
Definition Compiler.cs:24
XmlQualifiedName CurrentMode
Definition Compiler.cs:151
void AddDecimalFormat(XmlQualifiedName name, DecimalFormat formatinfo)
Definition Compiler.cs:358
XmlQualifiedName _currentMode
Definition Compiler.cs:53
XmlQualifiedName CreateXPathQName(string qname)
Definition Compiler.cs:435
virtual ValueOfAction CreateValueOfAction()
Definition Compiler.cs:926
void BeginTemplate(TemplateAction template)
Definition Compiler.cs:560
TemplateBaseAction _currentTemplate
Definition Compiler.cs:51
void AddScript(string source, ScriptingLanguage lang, string ns, string fileName, int lineNumber)
Definition Compiler.cs:608
InputScopeManager CloneScopeManager()
Definition Compiler.cs:280
virtual void CreateRootAction()
Definition Compiler.cs:885
void AddAttributeSet(AttributeSetAction attributeSet)
Definition Compiler.cs:550
virtual ApplyTemplatesAction CreateApplyTemplatesAction()
Definition Compiler.cs:780
void InsertExtensionNamespace(string value)
Definition Compiler.cs:211
int AddStringQuery(string xpathQuery)
Definition Compiler.cs:596
readonly Hashtable[] _typeDeclsByLang
Definition Compiler.cs:83
NavigatorInput ResolveDocument(Uri absoluteUri)
Definition Compiler.cs:487
string GetSingleAttribute(string attributeAtom)
Definition Compiler.cs:402
List< TheQuery > QueryStore
Definition Compiler.cs:123
virtual TemplateAction CreateTemplateAction()
Definition Compiler.cs:898
virtual IfAction CreateIfAction(IfAction.ConditionType type)
Definition Compiler.cs:850
int AddQuery(string xpathQuery, bool allowVar, bool allowKey, bool isPattern)
Definition Compiler.cs:577
XmlQualifiedName CreateXmlQName(string qname)
Definition Compiler.cs:441
static XmlQualifiedName BuiltInMode
Definition Compiler.cs:81
ArrayList CompileAvt(string avtText)
Definition Compiler.cs:767
static void ValidateExtensionNamespace(string nsUri)
Definition Compiler.cs:625
virtual NewInstructionAction CreateNewInstructionAction()
Definition Compiler.cs:864
int AddQuery(string xpathQuery)
Definition Compiler.cs:572
Uri ResolveUri(string relativeUri)
Definition Compiler.cs:476
NamespaceInfo FindNamespaceAlias(string StylesheetURI)
Definition Compiler.cs:334
List< TheQuery > _queryStore
Definition Compiler.cs:73
virtual AttributeSetAction CreateAttributeSetAction()
Definition Compiler.cs:794
void Compile(NavigatorInput input, XmlResolver xmlResolver)
Definition Compiler.cs:174
static XPathDocument LoadDocument(XmlTextReaderImpl reader)
Definition Compiler.cs:447
virtual ProcessingInstructionAction CreateProcessingInstructionAction()
Definition Compiler.cs:878
void InsertExcludedNamespace(string value)
Definition Compiler.cs:220
string GetNsAlias(ref string prefix)
Definition Compiler.cs:634
void PushStylesheet(Stylesheet stylesheet)
Definition Compiler.cs:533
bool IsNamespaceAlias(string StylesheetURI)
Definition Compiler.cs:325
int AddBooleanQuery(string xpathQuery)
Definition Compiler.cs:602
virtual ElementAction CreateElementAction()
Definition Compiler.cs:836
string ResolveXPathNamespace(string prefix)
Definition Compiler.cs:348
int InsertVariable(VariableAction variable)
Definition Compiler.cs:285
bool IsExcludedNamespace(string nspace)
Definition Compiler.cs:244
XsltException UnexpectedKeyword()
Definition Compiler.cs:961
Stack< Stylesheet > _stylesheets
Definition Compiler.cs:57
ArrayList CompileAvt(string avtText, out bool constant)
Definition Compiler.cs:745
bool GetYesNo(string value)
Definition Compiler.cs:389
virtual AttributeAction CreateAttributeAction()
Definition Compiler.cs:787
void AddNamespaceAlias(string StylesheetURI, NamespaceInfo AliasInfo)
Definition Compiler.cs:313
void AddTemplate(TemplateAction template)
Definition Compiler.cs:555
virtual CallTemplateAction CreateCallTemplateAction()
Definition Compiler.cs:801
virtual BeginEvent CreateBeginEvent()
Definition Compiler.cs:951
virtual TextEvent CreateTextEvent()
Definition Compiler.cs:956
virtual NumberAction CreateNumberAction()
Definition Compiler.cs:871
virtual VariableAction CreateVariableAction(VariableType type)
Definition Compiler.cs:933
readonly QueryBuilder _queryBuilder
Definition Compiler.cs:75
virtual CommentAction CreateCommentAction()
Definition Compiler.cs:815
void RemoveDocumentURI(string href)
Definition Compiler.cs:466
bool IsCircularReference(string href)
Definition Compiler.cs:471
bool IsExtensionNamespace(string nspace)
Definition Compiler.cs:239
virtual TextAction CreateTextAction()
Definition Compiler.cs:912
InputScopeManager _scopeManager
Definition Compiler.cs:65
virtual ChooseAction CreateChooseAction()
Definition Compiler.cs:808
virtual CopyOfAction CreateCopyOfAction()
Definition Compiler.cs:829
readonly HybridDictionary _documentURIs
Definition Compiler.cs:59
virtual SortAction CreateSortAction()
Definition Compiler.cs:891
virtual UseAttributeSetsAction CreateUseAttributeSetsAction()
Definition Compiler.cs:919
static void getTextLex(string avt, ref int start, StringBuilder lex)
Definition Compiler.cs:648
void AddDocumentURI(string href)
Definition Compiler.cs:461
void InsertKey(XmlQualifiedName name, int MatchKey, int UseKey)
Definition Compiler.cs:353
static void getXPathLex(string avt, ref int start, StringBuilder lex)
Definition Compiler.cs:680
virtual MessageAction CreateMessageAction()
Definition Compiler.cs:857
virtual CopyAction CreateCopyAction()
Definition Compiler.cs:822
virtual TemplateAction CreateSingleTemplateAction()
Definition Compiler.cs:905
void PushInputDocument(NavigatorInput newInput)
Definition Compiler.cs:504
virtual ApplyImportsAction CreateApplyImportsAction()
Definition Compiler.cs:773
static bool GetNextAvtLex(string avt, ref int start, StringBuilder lex, out bool isAvt)
Definition Compiler.cs:728
string ResolveXmlNamespace(string prefix)
Definition Compiler.cs:343
virtual ForEachAction CreateForEachAction()
Definition Compiler.cs:843
virtual WithParamAction CreateWithParamAction()
Definition Compiler.cs:944
string[] ResolvePrefixes(string tokens)
Definition Compiler.cs:363
override void ReplaceNamespaceAlias(Compiler compiler)
void PushNamespace(string prefix, string nspace)
static void ParseQualifiedName(string qname, out string prefix, out string local)
static bool ValidatePrefix(string prefix)
override void Compile(Compiler compiler)
Definition RootAction.cs:36
void PorcessAttributeSets(Stylesheet rootStylesheet)
Definition RootAction.cs:60
void AddDecimalFormat(XmlQualifiedName name, DecimalFormat formatinfo)
void InsertKey(XmlQualifiedName name, int MatchKey, int UseKey)
Definition RootAction.cs:41
void ReplaceNamespaceAlias(Compiler compiler)
void AddAttributeSet(AttributeSetAction attributeSet)
void AddTemplate(TemplateAction template)