Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.Data.SqlXml / System / Xml / Xsl / XsltOld / ElementAction.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="ElementAction.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>                                                                
5 // <owner current="true" primary="true">[....]</owner>
6 //------------------------------------------------------------------------------
7
8 namespace System.Xml.Xsl.XsltOld {
9     using Res = System.Xml.Utils.Res;
10     using System;
11     using System.Diagnostics;
12     using System.Xml;
13     using System.Xml.XPath;
14
15     internal class ElementAction : ContainerAction {
16         private const int NameDone           = 2;
17
18         private Avt                nameAvt;
19         private Avt                nsAvt;
20         private bool               empty;
21         private InputScopeManager  manager;
22         // Compile time precalculated AVTs
23         private string              name;
24         private string              nsUri;
25         private PrefixQName         qname; // When we not have AVTs at all we can do this. null otherwise.
26
27         internal ElementAction() {}
28
29         private static PrefixQName CreateElementQName(string name, string nsUri, InputScopeManager manager) {
30             if (nsUri == XmlReservedNs.NsXmlNs) {
31                 throw XsltException.Create(Res.Xslt_ReservedNS, nsUri);
32             }
33
34             PrefixQName qname = new PrefixQName();
35             qname.SetQName(name);
36
37             if (nsUri == null) {
38                 qname.Namespace = manager.ResolveXmlNamespace(qname.Prefix);
39             }
40             else {
41                 qname.Namespace = nsUri;
42             }
43             return qname;
44         }
45
46         internal override void Compile(Compiler compiler) {
47             CompileAttributes(compiler);
48             CheckRequiredAttribute(compiler, this.nameAvt, "name");
49
50             this.name  = PrecalculateAvt(ref this.nameAvt);
51             this.nsUri = PrecalculateAvt(ref this.nsAvt  );
52
53             // if both name and ns are not AVT we can calculate qname at compile time and will not need namespace manager anymore
54             if (this.nameAvt == null && this.nsAvt == null) {
55                 if(this.name != "xmlns") {
56                     this.qname = CreateElementQName(this.name, this.nsUri, compiler.CloneScopeManager());                    
57                 }
58             }
59             else {
60                 this.manager = compiler.CloneScopeManager();
61             }
62
63             if (compiler.Recurse()) {
64                 Debug.Assert(this.empty == false);
65                 CompileTemplate(compiler);
66                 compiler.ToParent();
67             }
68             this.empty = (this.containedActions == null) ;
69         }
70
71         internal override bool CompileAttribute(Compiler compiler) {
72             string name   = compiler.Input.LocalName;
73             string value  = compiler.Input.Value;
74             if (Ref.Equal(name, compiler.Atoms.Name)) {
75                 this.nameAvt      = Avt.CompileAvt(compiler, value);
76             }
77             else if (Ref.Equal(name, compiler.Atoms.Namespace)) {
78                 this.nsAvt = Avt.CompileAvt(compiler, value);
79             }
80             else if (Ref.Equal(name, compiler.Atoms.UseAttributeSets)) {
81                 AddAction(compiler.CreateUseAttributeSetsAction());
82             }
83             else {
84                 return false;
85             }
86
87             return true;
88         }
89
90         internal override void Execute(Processor processor, ActionFrame frame) {
91             Debug.Assert(processor != null && frame != null);
92
93             switch (frame.State) {
94             case Initialized:
95                 if(this.qname != null) {
96                     frame.CalulatedName = this.qname;
97                 }
98                 else {
99                     frame.CalulatedName = CreateElementQName(
100                         this.nameAvt == null ? this.name  : this.nameAvt.Evaluate(processor, frame),
101                         this.nsAvt   == null ? this.nsUri : this.nsAvt  .Evaluate(processor, frame),
102                         this.manager
103                     );
104                 }
105                 goto case NameDone;
106
107             case NameDone:
108                 {
109                     PrefixQName qname = frame.CalulatedName;
110                     if (processor.BeginEvent(XPathNodeType.Element, qname.Prefix, qname.Name, qname.Namespace, this.empty) == false) {
111                         // Come back later
112                         frame.State = NameDone;
113                         break;
114                     }
115
116                     if (! this.empty) {
117                         processor.PushActionFrame(frame);
118                         frame.State = ProcessingChildren;
119                         break;                              // Allow children to run
120                     }
121                     else {
122                         goto case ProcessingChildren;
123                     }
124                 }
125             case ProcessingChildren:
126                 if (processor.EndEvent(XPathNodeType.Element) == false) {
127                     frame.State = ProcessingChildren;
128                     break;
129                 }
130                 frame.Finished();
131                 break;
132             default:
133                 Debug.Fail("Invalid ElementAction execution state");
134                     break;
135             }
136         }
137     }
138 }