File: System\Xml\Xsl\XsltOld\OutputScopeManager.cs
Project: ndp\fx\src\XmlUtils\System.Data.SqlXml.csproj (System.Data.SqlXml)
//------------------------------------------------------------------------------
// <copyright file="OutputScopeManager.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>                                                                
// <owner current="true" primary="true">Microsoft</owner>
//------------------------------------------------------------------------------
 
namespace System.Xml.Xsl.XsltOld {
    using Res = System.Xml.Utils.Res;
    using System;
    using System.Globalization;
    using System.Diagnostics;
    using System.Xml;
 
    internal class OutputScopeManager {
        private const int STACK_INCREMENT = 10;
 
        private HWStack         elementScopesStack;
        private string          defaultNS;
        private OutKeywords     atoms;
        private XmlNameTable    nameTable;
        private int             prefixIndex;
 
        internal string DefaultNamespace {
            get { return this.defaultNS; }
        }
 
        internal OutputScope CurrentElementScope {
            get {
                Debug.Assert(this.elementScopesStack.Peek() != null); // We adding rootElementScope to garantee this
                return (OutputScope) this.elementScopesStack.Peek();
            }
        }
 
        internal XmlSpace XmlSpace {
            get { return CurrentElementScope.Space; }
        }
 
        internal string XmlLang {
            get { return CurrentElementScope.Lang; }
        }
 
        internal OutputScopeManager(XmlNameTable nameTable, OutKeywords atoms) {
            Debug.Assert(nameTable != null);
            Debug.Assert(atoms     != null);
 
            this.elementScopesStack = new HWStack(STACK_INCREMENT);
            this.nameTable          = nameTable;
            this.atoms              = atoms;
            this.defaultNS          = this.atoms.Empty;
 
            // We always adding rootElementScope to garantee that CurrentElementScope != null
            // This context is active between PI and first element for example
            OutputScope rootElementScope = (OutputScope) this.elementScopesStack.Push();
            if(rootElementScope == null) {
                rootElementScope = new OutputScope();
                this.elementScopesStack.AddToTop(rootElementScope);
            }
            rootElementScope.Init(string.Empty, string.Empty, string.Empty, /*space:*/XmlSpace.None, /*lang:*/string.Empty, /*mixed:*/false);
        }
 
        internal void PushNamespace(string prefix, string nspace) {
            Debug.Assert(prefix != null);
            Debug.Assert(nspace != null);
            CurrentElementScope.AddNamespace(prefix, nspace, this.defaultNS);
 
            if (prefix == null || prefix.Length == 0) {
                this.defaultNS = nspace;
            }
        }
 
        internal void PushScope(string name, string nspace, string prefix) {
            Debug.Assert(name != null);
            Debug.Assert(nspace != null);
            Debug.Assert(prefix != null);
            OutputScope parentScope  = CurrentElementScope;
            OutputScope elementScope = (OutputScope) this.elementScopesStack.Push();
 
            if (elementScope == null) {
                elementScope = new OutputScope();
                this.elementScopesStack.AddToTop(elementScope);
            }
 
            Debug.Assert(elementScope != null);
            elementScope.Init(name, nspace, prefix, parentScope.Space, parentScope.Lang, parentScope.Mixed);
        }
 
        internal void PopScope() {
            OutputScope elementScope = (OutputScope) this.elementScopesStack.Pop();
 
            Debug.Assert(elementScope != null); // We adding rootElementScope to garantee this
 
            for (NamespaceDecl scope = elementScope.Scopes; scope != null; scope = scope.Next) {
                this.defaultNS = scope.PrevDefaultNsUri;
            }
        }
 
        internal string ResolveNamespace(string prefix) {
            bool thisScope;
            return ResolveNamespace(prefix, out thisScope);
        }
 
        internal string ResolveNamespace(string prefix, out bool thisScope) {
            Debug.Assert(prefix != null);
            thisScope = true;
 
            if (prefix == null || prefix.Length == 0) {
                return this.defaultNS;
            }
            else {
                if (Ref.Equal(prefix, this.atoms.Xml)) {
                    return this.atoms.XmlNamespace;
                }
                else if (Ref.Equal(prefix, this.atoms.Xmlns)) {
                    return this.atoms.XmlnsNamespace;
                }
 
                for (int i = this.elementScopesStack.Length - 1; i >= 0; i --) {
                    Debug.Assert(this.elementScopesStack[i] is OutputScope);
                    OutputScope elementScope = (OutputScope) this.elementScopesStack[i];
 
                    string nspace = elementScope.ResolveAtom(prefix);
                    if (nspace != null) {
                        thisScope = (i == this.elementScopesStack.Length - 1);
                        return nspace;
                    }
                }
            }
 
            return null;
        }
 
        internal bool FindPrefix(string nspace, out string prefix) {
            Debug.Assert(nspace != null);
            for (int i = this.elementScopesStack.Length - 1; 0 <= i; i--) {
                Debug.Assert(this.elementScopesStack[i] is OutputScope);
 
                OutputScope elementScope = (OutputScope) this.elementScopesStack[i];
                string      pfx          = null;
                if (elementScope.FindPrefix(nspace, out pfx)) {
                    string testNspace = ResolveNamespace(pfx);
                    if(testNspace != null && Ref.Equal(testNspace, nspace)) {
                        prefix = pfx;
                        return true;
                    }
                    else {
                        break;
                    }
                }
            }
            prefix = null;
            return false;
        }
 
        internal string GeneratePrefix(string format) {
            string prefix;
 
            do {
                prefix = String.Format(CultureInfo.InvariantCulture, format, this.prefixIndex ++);
            }while(this.nameTable.Get(prefix) != null);
 
            return this.nameTable.Add(prefix);
        }
    }
}