The Labs \ Source Viewer \ SSCLI \ System.Xml.Xsl.XsltOld \ ActionFrame

  1. //------------------------------------------------------------------------------
  2. // <copyright file="ActionFrame.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.Xml.Xsl.XsltOld
  16. {
  17.     using Res = System.Xml.Utils.Res;
  18.     using System;
  19.     using System.Xml;
  20.     using System.Xml.XPath;
  21.     using MS.Internal.Xml.XPath;
  22.     using System.Collections;
  23.     using System.Collections.Generic;
  24.     using System.Diagnostics;
  25.     using System.Xml.Xsl.XsltOld.Debugger;
  26.    
  27.     internal class ActionFrame : IStackFrame
  28.     {
  29.         private int state;
  30.         // Action execution state
  31.         private int counter;
  32.         // Counter, for the use of particular action
  33.         private object[] variables;
  34.         // Store for template local variable values
  35.         private Hashtable withParams;
  36.         private Action action;
  37.         // Action currently being executed
  38.         private ActionFrame container;
  39.         // Frame of enclosing container action and index within it
  40.         private int currentAction;
  41.         private XPathNodeIterator nodeSet;
  42.         // Current node set
  43.         private XPathNodeIterator newNodeSet;
  44.         // Node set for processing children or other templates
  45.         // Variables to store action data between states:
  46.         private PrefixQName calulatedName;
  47.         // Used in ElementAction and AttributeAction
  48.         private string storedOutput;
  49.         // Used in NumberAction, CopyOfAction, ValueOfAction and ProcessingInstructionAction
  50.         internal PrefixQName CalulatedName {
  51.             get { return this.calulatedName; }
  52.             set { this.calulatedName = value; }
  53.         }
  54.        
  55.         internal string StoredOutput {
  56.             get { return this.storedOutput; }
  57.             set { this.storedOutput = value; }
  58.         }
  59.        
  60.         internal int State {
  61.             get { return this.state; }
  62.             set { this.state = value; }
  63.         }
  64.        
  65.         internal int Counter {
  66.             get { return this.counter; }
  67.             set { this.counter = value; }
  68.         }
  69.        
  70.         internal ActionFrame Container {
  71.             get { return this.container; }
  72.         }
  73.        
  74.         internal XPathNavigator Node {
  75.             get {
  76.                 if (this.nodeSet != null) {
  77.                     return this.nodeSet.Current;
  78.                 }
  79.                 return null;
  80.             }
  81.         }
  82.        
  83.         internal XPathNodeIterator NodeSet {
  84.             get { return this.nodeSet; }
  85.         }
  86.        
  87.         internal XPathNodeIterator NewNodeSet {
  88.             get { return this.newNodeSet; }
  89.         }
  90.        
  91.         internal int IncrementCounter()
  92.         {
  93.             return ++this.counter;
  94.         }
  95.        
  96.         internal void AllocateVariables(int count)
  97.         {
  98.             if (0 < count) {
  99.                 this.variables = new object[count];
  100.             }
  101.             else {
  102.                 this.variables = null;
  103.             }
  104.         }
  105.        
  106.         internal object GetVariable(int index)
  107.         {
  108.             Debug.Assert(this.variables != null && index < this.variables.Length);
  109.             return this.variables[index];
  110.         }
  111.        
  112.         internal void SetVariable(int index, object value)
  113.         {
  114.             Debug.Assert(this.variables != null && index < this.variables.Length);
  115.             this.variables[index] = value;
  116.         }
  117.        
  118.         internal void SetParameter(XmlQualifiedName name, object value)
  119.         {
  120.             if (this.withParams == null) {
  121.                 this.withParams = new Hashtable();
  122.             }
  123.             Debug.Assert(!this.withParams.Contains(name), "We should check duplicate params at compile time");
  124.             this.withParams[name] = value;
  125.         }
  126.        
  127.         internal void ResetParams()
  128.         {
  129.             if (this.withParams != null)
  130.                 this.withParams.Clear();
  131.         }
  132.        
  133.         internal object GetParameter(XmlQualifiedName name)
  134.         {
  135.             if (this.withParams != null) {
  136.                 return this.withParams[name];
  137.             }
  138.             return null;
  139.         }
  140.        
  141.         internal void InitNodeSet(XPathNodeIterator nodeSet)
  142.         {
  143.             Debug.Assert(nodeSet != null);
  144.             this.nodeSet = nodeSet;
  145.         }
  146.        
  147.         internal void InitNewNodeSet(XPathNodeIterator nodeSet)
  148.         {
  149.             Debug.Assert(nodeSet != null);
  150.             this.newNodeSet = nodeSet;
  151.         }
  152.        
  153.         internal void SortNewNodeSet(Processor proc, ArrayList sortarray)
  154.         {
  155.             Debug.Assert(0 < sortarray.Count);
  156.             int numSorts = sortarray.Count;
  157.             XPathSortComparer comparer = new XPathSortComparer(numSorts);
  158.             for (int i = 0; i < numSorts; i++) {
  159.                 Sort sort = (Sort)sortarray[i];
  160.                 Query expr = proc.GetCompiledQuery(sort.select);
  161.                
  162.                 comparer.AddSort(expr, new XPathComparerHelper(sort.order, sort.caseOrder, sort.lang, sort.dataType));
  163.             }
  164.             List<SortKey> results = new List<SortKey>();
  165.            
  166.             Debug.Assert(proc.ActionStack.Peek() == this, "the trick we are doing with proc.Current will work only if this is topmost frame");
  167.            
  168.             while (NewNextNode(proc)) {
  169.                 XPathNodeIterator savedNodeset = this.nodeSet;
  170.                 this.nodeSet = this.newNodeSet;
  171.                 // trick proc.Current node
  172.                     /*originalPosition:*/                SortKey key = new SortKey(numSorts, results.Count, this.newNodeSet.Current.Clone());
  173.                
  174.                 for (int j = 0; j < numSorts; j++) {
  175.                     key[j] = comparer.Expression(j).Evaluate(this.newNodeSet);
  176.                 }
  177.                 results.Add(key);
  178.                
  179.                 this.nodeSet = savedNodeset;
  180.                 // restore proc.Current node
  181.             }
  182.             results.Sort(comparer);
  183.             this.newNodeSet = new XPathSortArrayIterator(results);
  184.         }
  185.        
  186.         // Finished
  187.         internal void Finished()
  188.         {
  189.             State = Action.Finished;
  190.         }
  191.        
  192.         internal void Inherit(ActionFrame parent)
  193.         {
  194.             Debug.Assert(parent != null);
  195.             this.variables = parent.variables;
  196.         }
  197.        
  198.         private void Init(Action action, ActionFrame container, XPathNodeIterator nodeSet)
  199.         {
  200.             this.state = Action.Initialized;
  201.             this.action = action;
  202.             this.container = container;
  203.             this.currentAction = 0;
  204.             this.nodeSet = nodeSet;
  205.             this.newNodeSet = null;
  206.         }
  207.        
  208.         internal void Init(Action action, XPathNodeIterator nodeSet)
  209.         {
  210.             Init(action, null, nodeSet);
  211.         }
  212.        
  213.         internal void Init(ActionFrame containerFrame, XPathNodeIterator nodeSet)
  214.         {
  215.             Init(containerFrame.GetAction(0), containerFrame, nodeSet);
  216.         }
  217.        
  218.         internal void SetAction(Action action)
  219.         {
  220.             SetAction(action, Action.Initialized);
  221.         }
  222.        
  223.         internal void SetAction(Action action, int state)
  224.         {
  225.             this.action = action;
  226.             this.state = state;
  227.         }
  228.        
  229.         private Action GetAction(int actionIndex)
  230.         {
  231.             Debug.Assert(this.action is ContainerAction);
  232.             return ((ContainerAction)this.action).GetAction(actionIndex);
  233.         }
  234.        
  235.         internal void Exit()
  236.         {
  237.             Finished();
  238.             this.container = null;
  239.         }
  240.        
  241. /*
  242.         * Execute
  243.         *  return values: true - pop, false - nothing
  244.         */       
  245.         internal bool Execute(Processor processor)
  246.         {
  247.             if (this.action == null) {
  248.                 return true;
  249.             }
  250.            
  251.             // Execute the action
  252.             this.action.Execute(processor, this);
  253.            
  254.             // Process results
  255.             if (State == Action.Finished) {
  256.                 // Advanced to next action
  257.                 if (this.container != null) {
  258.                     this.currentAction++;
  259.                     this.action = this.container.GetAction(this.currentAction);
  260.                     State = Action.Initialized;
  261.                 }
  262.                 else {
  263.                     this.action = null;
  264.                 }
  265.                 return this.action == null;
  266.             }
  267.            
  268.             return false;
  269.             // Do not pop, unless specified otherwise
  270.         }
  271.        
  272.         internal bool NextNode(Processor proc)
  273.         {
  274.             bool next = this.nodeSet.MoveNext();
  275.             if (next && proc.Stylesheet.Whitespace) {
  276.                 XPathNodeType type = this.nodeSet.Current.NodeType;
  277.                 if (type == XPathNodeType.Whitespace) {
  278.                     XPathNavigator nav = this.nodeSet.Current.Clone();
  279.                     bool flag;
  280.                     do {
  281.                         nav.MoveTo(this.nodeSet.Current);
  282.                         nav.MoveToParent();
  283.                         flag = !proc.Stylesheet.PreserveWhiteSpace(proc, nav) && (next = this.nodeSet.MoveNext());
  284.                         type = this.nodeSet.Current.NodeType;
  285.                     }
  286.                     while (flag && (type == XPathNodeType.Whitespace));
  287.                 }
  288.             }
  289.             return next;
  290.         }
  291.        
  292.         internal bool NewNextNode(Processor proc)
  293.         {
  294.             bool next = this.newNodeSet.MoveNext();
  295.             if (next && proc.Stylesheet.Whitespace) {
  296.                 XPathNodeType type = this.newNodeSet.Current.NodeType;
  297.                 if (type == XPathNodeType.Whitespace) {
  298.                     XPathNavigator nav = this.newNodeSet.Current.Clone();
  299.                     bool flag;
  300.                     do {
  301.                         nav.MoveTo(this.newNodeSet.Current);
  302.                         nav.MoveToParent();
  303.                         flag = !proc.Stylesheet.PreserveWhiteSpace(proc, nav) && (next = this.newNodeSet.MoveNext());
  304.                         type = this.newNodeSet.Current.NodeType;
  305.                     }
  306.                     while (flag && (type == XPathNodeType.Whitespace));
  307.                 }
  308.             }
  309.             return next;
  310.         }
  311.        
  312.         // ----------------------- IStackFrame : --------------------
  313.         XPathNavigator IStackFrame.Instruction {
  314.             get {
  315.                 if (this.action == null) {
  316.                     return null;
  317.                     // for builtIn action this shoud be null;
  318.                 }
  319.                 return this.action.GetDbgData(this).StyleSheet;
  320.             }
  321.         }
  322.         XPathNodeIterator IStackFrame.NodeSet {
  323.             get { return this.nodeSet.Clone(); }
  324.         }
  325.         // Variables:
  326.         int IStackFrame.GetVariablesCount()
  327.         {
  328.             if (this.action == null) {
  329.                 return 0;
  330.             }
  331.             return this.action.GetDbgData(this).Variables.Length;
  332.         }
  333.         XPathNavigator IStackFrame.GetVariable(int varIndex)
  334.         {
  335.             return this.action.GetDbgData(this).Variables[varIndex].GetDbgData(null).StyleSheet;
  336.         }
  337.         object IStackFrame.GetVariableValue(int varIndex)
  338.         {
  339.             return GetVariable(this.action.GetDbgData(this).Variables[varIndex].VarKey);
  340.         }
  341.        
  342.         // special array iterator that iterates over ArrayList of SortKey
  343.         private class XPathSortArrayIterator : XPathArrayIterator
  344.         {
  345.             public XPathSortArrayIterator(List<SortKey> list) : base(list)
  346.             {
  347.             }
  348.             public XPathSortArrayIterator(XPathSortArrayIterator it) : base(it)
  349.             {
  350.             }
  351.            
  352.             public override XPathNodeIterator Clone()
  353.             {
  354.                 return new XPathSortArrayIterator(this);
  355.             }
  356.            
  357.             public override XPathNavigator Current {
  358.                 get {
  359.                     Debug.Assert(index > 0, "MoveNext() wasn't called");
  360.                     return ((SortKey)this.list[this.index - 1]).Node;
  361.                 }
  362.             }
  363.         }
  364.     }
  365. }

Developer Fusion