96f094bd7691feb79e3b7c6da43139f2bb0c776f
[mono.git] / mcs / class / referencesource / System.Data.SqlXml / System / Xml / Xsl / Xslt / Stylesheet.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="Stylesheet.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
7
8 using System.Collections.Generic;
9 using System.Diagnostics;
10 using System.Xml.Xsl.Qil;
11
12 namespace System.Xml.Xsl.Xslt {
13
14     internal class StylesheetLevel {
15         public Stylesheet[] Imports = null;
16
17         // If (this is Stylesheet) {
18         //   ModeFlags and ApplyFunctions are abblout apply-imports
19         // } else {
20         //   ModeFlags and ApplyFunctions are abblout apply-templates
21         // }
22         // mode -> FocusFlags; Used to generate and call apply-imports/apply-template functions
23         public Dictionary<QilName, XslFlags> ModeFlags = new Dictionary<QilName, XslFlags>();
24         // mode -> xsl:apply-import functions for that mode
25         public Dictionary<QilName, List<QilFunction>> ApplyFunctions = new Dictionary<QilName, List<QilFunction>>();
26     }
27
28     internal class Stylesheet : StylesheetLevel {
29         private Compiler compiler;
30         public List<Uri> ImportHrefs = new List<Uri>();
31         public List<XslNode>        GlobalVarPars       = new List<XslNode>();
32
33         // xsl:attribute-set/@name -> AttributeSet
34         public Dictionary<QilName, AttributeSet>        AttributeSets   = new Dictionary<QilName, AttributeSet>();
35
36         private int                importPrecedence;
37         private int                orderNumber          = 0;
38
39         /*
40             WhitespaceRules[0] - rules with default priority  0
41             WhitespaceRules[1] - rules with default priority -0.25
42             WhitespaceRules[2] - rules with default priority -0.5
43         */        
44         public List<WhitespaceRule>[]   WhitespaceRules = new List<WhitespaceRule>[3];
45
46         public List<Template> Templates = new List<Template>();  // Templates defined on this level. Empty for RootLevel.
47         // xsl:template/@mode -> list of @match'es
48         public Dictionary<QilName, List<TemplateMatch>> TemplateMatches = new Dictionary<QilName, List<TemplateMatch>>();
49
50         public void AddTemplateMatch(Template template, QilLoop filter) {
51             List<TemplateMatch> matchesForMode;
52             if (!TemplateMatches.TryGetValue(template.Mode, out matchesForMode)) {
53                 matchesForMode = TemplateMatches[template.Mode] = new List<TemplateMatch>();
54             }
55             matchesForMode.Add(new TemplateMatch(template, filter));
56         }
57
58         public void SortTemplateMatches() {
59             foreach (QilName mode in TemplateMatches.Keys) {
60                 TemplateMatches[mode].Sort(TemplateMatch.Comparer);
61             }
62         }
63
64         public Stylesheet(Compiler compiler, int importPrecedence) {
65             this.compiler         = compiler;
66             this.importPrecedence = importPrecedence;
67
68             WhitespaceRules[0] = new List<WhitespaceRule>();
69             WhitespaceRules[1] = new List<WhitespaceRule>();
70             WhitespaceRules[2] = new List<WhitespaceRule>();
71         }
72
73         public int ImportPrecedence { get { return importPrecedence; } }
74
75         public void AddWhitespaceRule(int index, WhitespaceRule rule) {
76             WhitespaceRules[index].Add(rule);
77         }
78
79         public bool AddVarPar(VarPar var) {
80             Debug.Assert(var.NodeType == XslNodeType.Variable || var.NodeType == XslNodeType.Param);
81             Debug.Assert(var.Name.NamespaceUri != null, "Name must be resolved in XsltLoader");
82             foreach (XslNode prevVar in GlobalVarPars) {
83                 if (prevVar.Name.Equals(var.Name)) {
84                     // [ERR XT0630] It is a static error if a stylesheet contains more than one binding
85                     // of a global variable with the same name and same import precedence, unless it also
86                     // contains another binding with the same name and higher import precedence.
87                     return compiler.AllGlobalVarPars.ContainsKey(var.Name);
88                 }
89             }
90             GlobalVarPars.Add(var);
91             return true;
92         }
93
94         public bool AddTemplate(Template template) {
95             Debug.Assert(template.ImportPrecedence == 0);
96
97             template.ImportPrecedence = this.importPrecedence;
98             template.OrderNumber      = this.orderNumber++;
99
100             compiler.AllTemplates.Add(template);
101
102             if (template.Name != null) {
103                 Template old;
104                 if (!compiler.NamedTemplates.TryGetValue(template.Name, out old)) {
105                     compiler.NamedTemplates[template.Name] = template;
106                 } else {
107                     Debug.Assert(template.ImportPrecedence <= old.ImportPrecedence, "Global objects are processed in order of decreasing import precedence");
108                     if (old.ImportPrecedence == template.ImportPrecedence) {
109                         return false;
110                     }
111                 }
112             }
113
114             if (template.Match != null) {
115                 Templates.Add(template);
116             }
117             return true;
118         }
119     }
120 }