The Labs \ Source Viewer \ SSCLI \ System.Xml.Xsl.Runtime \ DocumentOrderComparer

  1. //------------------------------------------------------------------------------
  2. // <copyright file="DocumentOrderComparer.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. using System;
  16. using System.Collections;
  17. using System.Collections.Generic;
  18. using System.Xml;
  19. using System.Xml.XPath;
  20. using System.Diagnostics;
  21. namespace System.Xml.Xsl.Runtime
  22. {
  23.    
  24.     /// <summary>
  25.     /// IComparer implementation that orders navigators based on ComparePosition. When ComparePosition returns
  26.     /// XmlNodeOrder.Unknown, a stable order between documents is maintained by an ordered list mapping each root node
  27.     /// to an ordering index.
  28.     /// </summary>
  29.     internal class DocumentOrderComparer : IComparer<XPathNavigator>
  30.     {
  31.         private List<XPathNavigator> roots;
  32.        
  33.         /// <summary>
  34.         /// Return:
  35.         /// -1 if navThis is positioned before navThat
  36.         /// 0 if navThis has the same position as navThat
  37.         /// 1 if navThis is positioned after navThat
  38.         /// </summary>
  39.         public int Compare(XPathNavigator navThis, XPathNavigator navThat)
  40.         {
  41.             switch (navThis.ComparePosition(navThat)) {
  42.                 case XmlNodeOrder.Before:
  43.                     return -1;
  44.                 case XmlNodeOrder.Same:
  45.                     return 0;
  46.                 case XmlNodeOrder.After:
  47.                     return 1;
  48.             }
  49.            
  50.             // Use this.roots to impose stable ordering
  51.             if (this.roots == null)
  52.                 this.roots = new List<XPathNavigator>();
  53.            
  54.             Debug.Assert(GetDocumentIndex(navThis) != GetDocumentIndex(navThat));
  55.             return GetDocumentIndex(navThis) < GetDocumentIndex(navThat) ? -1 : 1;
  56.         }
  57.        
  58.         /// <summary>
  59.         /// Map navigator's document to a unique index.
  60.         /// When consecutive calls are made to GetIndexOfNavigator for navThis and navThat, it is not possible
  61.         /// for them to return the same index. navThis compared to navThat is always XmlNodeOrder.Unknown.
  62.         /// Therefore, no matter where navThis is inserted in the list, navThat will never be inserted just
  63.         /// before navThis, and therefore will never have the same index.
  64.         /// </summary>
  65.         public int GetDocumentIndex(XPathNavigator nav)
  66.         {
  67.             XPathNavigator navRoot;
  68.            
  69.             // Use this.roots to impose stable ordering
  70.             if (this.roots == null)
  71.                 this.roots = new List<XPathNavigator>();
  72.            
  73.             // Position navigator to root
  74.             navRoot = nav.Clone();
  75.             navRoot.MoveToRoot();
  76.            
  77.             for (int idx = 0; idx < this.roots.Count; idx++) {
  78.                 if (navRoot.IsSamePosition(this.roots[idx])) {
  79.                     // navigator's document was previously mapped to a unique index
  80.                     return idx;
  81.                 }
  82.             }
  83.            
  84.             // Add navigator to this.roots mapping
  85.             this.roots.Add(navRoot);
  86.            
  87.             return this.roots.Count - 1;
  88.         }
  89.     }
  90. }

Developer Fusion