XDRSchema.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Data / System / Data / XDRSchema.cs / 1305376 / XDRSchema.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
// [....]
// [....] 
//----------------------------------------------------------------------------- 

namespace System.Data { 
    using System;
    using System.Xml;
    using System.Collections;
    using System.Globalization; 
    using System.ComponentModel;
    using System.Diagnostics; 
    using System.Data.Common; 

    internal sealed class XDRSchema : XMLSchema { 
        internal String             _schemaName;
        internal String             _schemaUri;
        internal XmlElement         _schemaRoot;
        internal DataSet            _ds; 
        private  static char[] colonArray = new char[] {':'};
 
 
        internal XDRSchema(DataSet ds, bool fInline) {
            _schemaUri = String.Empty; 
            _schemaName = String.Empty;
            _schemaRoot = null;
            _ds = ds;
        } 

        internal void LoadSchema(XmlElement schemaRoot, DataSet ds) { 
            if (schemaRoot == null) 
                return;
 
            _schemaRoot = schemaRoot;
            _ds = ds;
            _schemaName = schemaRoot.GetAttribute(Keywords.NAME);
 

            _schemaUri = ""; 
            Debug.Assert(FEqualIdentity(schemaRoot, Keywords.XDR_SCHEMA, Keywords.XDRNS), "Illegal node"); 

            // Get Locale and CaseSensitive properties 

            if (_schemaName == null || _schemaName.Length == 0)
                _schemaName = "NewDataSet";
 
            ds.Namespace = _schemaUri;
 
            // Walk all the top level Element tags. 
            for (XmlNode n = schemaRoot.FirstChild; n != null; n = n.NextSibling) {
                if (!(n is XmlElement)) 
                    continue;

                XmlElement child = (XmlElement) n;
 
                if (FEqualIdentity(child, Keywords.XDR_ELEMENTTYPE, Keywords.XDRNS)) {
                    HandleTable(child); 
                } 
            }
 
            _schemaName = XmlConvert.DecodeName(_schemaName);
            if (ds.Tables[_schemaName] == null)
                ds.DataSetName = _schemaName;
 
        }
 
        internal XmlElement FindTypeNode(XmlElement node) { 
            string      strType;
            XmlNode     vn; 
            XmlNode     vnRoof;

            Debug.Assert(FEqualIdentity(node, Keywords.XDR_ELEMENT, Keywords.XDRNS) ||
                         FEqualIdentity(node, Keywords.XDR_SCHEMA, Keywords.XDRNS) || 
                         FEqualIdentity(node, Keywords.XDR_ATTRIBUTE, Keywords.XDRNS) ||
                         FEqualIdentity(node, Keywords.XDR_ELEMENTTYPE, Keywords.XDRNS), 
                         "Invalid node type " + node.LocalName); 

            if (FEqualIdentity(node, Keywords.XDR_ELEMENTTYPE, Keywords.XDRNS)) 
                return node;

            strType = node.GetAttribute(Keywords.TYPE);
 
            if (FEqualIdentity(node, Keywords.XDR_ELEMENT, Keywords.XDRNS) ||
                FEqualIdentity(node, Keywords.XDR_ATTRIBUTE, Keywords.XDRNS)) { 
                if (strType == null || strType.Length == 0) 
                    return null;
 
                // Find an ELEMENTTYPE or ATTRIBUTETYPE with name=strType
                vn = node.OwnerDocument.FirstChild;
                vnRoof = node.OwnerDocument;
 
                while (vn != vnRoof) {
                    if ((FEqualIdentity(vn, Keywords.XDR_ELEMENTTYPE, Keywords.XDRNS) && 
                         FEqualIdentity(node, Keywords.XDR_ELEMENT, Keywords.XDRNS)) || 
                        (FEqualIdentity(vn, Keywords.XDR_ATTRIBUTETYPE, Keywords.XDRNS) &&
                         FEqualIdentity(node, Keywords.XDR_ATTRIBUTE, Keywords.XDRNS))) { 
                        if (vn is XmlElement && ((XmlElement)vn).GetAttribute(Keywords.NAME) == strType)
                            return(XmlElement)vn;
                    }
 
                    // Move vn node
                    if (vn.FirstChild != null) 
                        vn = vn.FirstChild; 
                    else if (vn.NextSibling != null)
                        vn = vn.NextSibling; 
                    else {
                        while (vn != vnRoof) {
                            vn = vn.ParentNode;
                            if (vn.NextSibling != null) { 
                                vn = vn.NextSibling;
                                break; 
                            } 
                        }
                    } 
                }

                return null;
            } 

            return null; 
        } 

        internal bool IsTextOnlyContent(XmlElement node) { 
            Debug.Assert(FEqualIdentity(node, Keywords.XDR_ELEMENTTYPE, Keywords.XDRNS),
                         "Invalid node type " + node.LocalName);

            string value = node.GetAttribute(Keywords.CONTENT); 
            if (value == null || value.Length == 0) {
                string type = node.GetAttribute(Keywords.DT_TYPE, Keywords.DTNS); 
                if (type != null && type.Length > 0) 
                    return true;
 
                return false;
            }

            if (value == Keywords.EMPTY || value == Keywords.ELTONLY || value == Keywords.ELEMENTONLY || value == Keywords.MIXED) 
                return false;
            if (value == Keywords.TEXTONLY) 
                return true; 

            throw ExceptionBuilder.InvalidAttributeValue("content", value); 
        }

        internal bool IsXDRField(XmlElement node, XmlElement typeNode) {
            int         min = 1; 
            int         max = 1;
 
            if (!IsTextOnlyContent(typeNode)) 
                return false;
 
            for (XmlNode n = typeNode.FirstChild; n != null; n = n.NextSibling) {
                if (FEqualIdentity(n, Keywords.XDR_ELEMENT, Keywords.XDRNS) ||
                    FEqualIdentity(n, Keywords.XDR_ATTRIBUTE, Keywords.XDRNS))
                    return false; 
            }
 
            if (FEqualIdentity(node, Keywords.XDR_ELEMENT, Keywords.XDRNS)) { 
                GetMinMax(node, ref min, ref max);
                if (max == -1 || max > 1) 
                    return false;
            }

            return true; 
        }
 
        internal DataTable HandleTable(XmlElement node) { 
            XmlElement     typeNode;
 
            Debug.Assert(FEqualIdentity(node, Keywords.XDR_ELEMENTTYPE, Keywords.XDRNS) ||
                         FEqualIdentity(node, Keywords.XDR_ELEMENT, Keywords.XDRNS), "Invalid node type");

 
            // Figure out if this really is a table.  If not, bail out.
            typeNode = FindTypeNode(node); 
 
            string occurs = node.GetAttribute(Keywords.MINOCCURS);
 
            if (occurs != null && occurs.Length > 0)
                if ((Convert.ToInt32(occurs, CultureInfo.InvariantCulture)>1) && (typeNode==null)){
                    return InstantiateSimpleTable(_ds, node);
                } 

            occurs = node.GetAttribute(Keywords.MAXOCCURS); 
 
            if (occurs != null && occurs.Length > 0)
                if ((string.Compare(occurs, "1" , StringComparison.Ordinal) != 0) && (typeNode==null)){ 
                    return InstantiateSimpleTable(_ds, node);
                }

 
            if (typeNode == null)
                return null; 
 
            if (IsXDRField(node, typeNode))
                    return null; 

            return InstantiateTable(_ds, node, typeNode);
        }
 
        private sealed class NameType : IComparable {
            public String   name; 
            public Type     type; 
            public NameType(String n, Type t) {
                name = n; 
                type = t;
            }
            public int CompareTo(object obj) { return String.Compare(name, (string)obj, StringComparison.Ordinal); }
        }; 
        // XDR spec: http://www.ltg.ed.ac.uk/~ht/XMLData-Reduced.htm
        //           http://webdata/newspecs/schema/xdr_dt_schema.xml 
        private static NameType[] mapNameTypeXdr = { 
            new NameType("bin.base64"          , typeof(Byte[])  ), /* XDR */
            new NameType("bin.hex"             , typeof(Byte[])  ), /* XDR */ 
            new NameType("boolean"             , typeof(bool)    ), /* XDR */
            new NameType("byte"                , typeof(SByte)   ), /* XDR */
            new NameType("char"                , typeof(Char)    ), /* XDR */
            new NameType("date"                , typeof(DateTime)), /* XDR */ 
            new NameType("dateTime"            , typeof(DateTime)), /* XDR */
            new NameType("dateTime.tz"         , typeof(DateTime)), /* XDR */ 
            new NameType("entities"            , typeof(string)  ), /* XDR */ 
            new NameType("entity"              , typeof(string)  ), /* XDR */
            new NameType("enumeration"         , typeof(string)  ), /* XDR */ 
            new NameType("fixed.14.4"          , typeof(Decimal) ), /* XDR */
            new NameType("float"               , typeof(Double)  ), /* XDR */
            new NameType("i1"                  , typeof(SByte)   ), /* XDR */
            new NameType("i2"                  , typeof(Int16)   ), /* XDR */ 
            new NameType("i4"                  , typeof(Int32)   ), /* XDR */
            new NameType("i8"                  , typeof(Int64)   ), /* XDR */ 
            new NameType("id"                  , typeof(string)  ), /* XDR */ 
            new NameType("idref"               , typeof(string)  ), /* XDR */
            new NameType("idrefs"              , typeof(string)  ), /* XDR */ 
            new NameType("int"                 , typeof(Int32)   ), /* XDR */
            new NameType("nmtoken"             , typeof(string)  ), /* XDR */
            new NameType("nmtokens"            , typeof(string)  ), /* XDR */
            new NameType("notation"            , typeof(string)  ), /* XDR */ 
            new NameType("number"              , typeof(Decimal) ), /* XDR */
            new NameType("r4"                  , typeof(Single)  ), /* XDR */ 
            new NameType("r8"                  , typeof(Double)  ), /* XDR */ 
            new NameType("string"              , typeof(string)  ), /* XDR */
            new NameType("time"                , typeof(DateTime)), /* XDR */ 
            new NameType("time.tz"             , typeof(DateTime)), /* XDR */
            new NameType("ui1"                 , typeof(Byte)    ), /* XDR */
            new NameType("ui2"                 , typeof(UInt16)  ), /* XDR */
            new NameType("ui4"                 , typeof(UInt32)  ), /* XDR */ 
            new NameType("ui8"                 , typeof(UInt64)  ), /* XDR */
            new NameType("uri"                 , typeof(string)  ), /* XDR */ 
            new NameType("uuid"                , typeof(Guid)    ), /* XDR */ 
        };
 
        private static NameType FindNameType(string name) {
#if DEBUG
            for(int i = 1; i < mapNameTypeXdr.Length; ++i) {
                Debug.Assert((mapNameTypeXdr[i-1].CompareTo(mapNameTypeXdr[i].name)) < 0, "incorrect sorting"); 
            }
#endif 
            int index = Array.BinarySearch(mapNameTypeXdr, name); 
            if (index < 0) {
#if DEBUG 
                // Let's check that we realy don't have this name:
                foreach (NameType nt in mapNameTypeXdr) {
                    Debug.Assert(nt.name != name, "FindNameType('" + name + "') -- failed. Existed name not found");
                } 
#endif
                throw ExceptionBuilder.UndefinedDatatype(name); 
            } 
            Debug.Assert(mapNameTypeXdr[index].name == name, "FindNameType('" + name + "') -- failed. Wrong name found");
            return mapNameTypeXdr[index]; 
        }

        private static NameType enumerationNameType = FindNameType("enumeration");
 
        private Type ParseDataType(string dt, string dtValues) {
            string strType = dt; 
            string[] parts = dt.Split(colonArray);  // ":" 

            if (parts.Length > 2) { 
                throw ExceptionBuilder.InvalidAttributeValue("type", dt);
            }
            else if (parts.Length == 2) {
                // 
                strType = parts[1];
            } 
 
            NameType nt = FindNameType(strType);
            if (nt == enumerationNameType && (dtValues == null || dtValues.Length == 0)) 
                throw ExceptionBuilder.MissingAttribute("type", Keywords.DT_VALUES);
            return nt.type;
        }
 
        internal string GetInstanceName(XmlElement node) {
            string  instanceName; 
 
            if (FEqualIdentity(node, Keywords.XDR_ELEMENTTYPE, Keywords.XDRNS) ||
                FEqualIdentity(node, Keywords.XDR_ATTRIBUTETYPE, Keywords.XDRNS)) { 
                instanceName = node.GetAttribute(Keywords.NAME);
                if (instanceName == null || instanceName.Length == 0) {
                    throw ExceptionBuilder.MissingAttribute("Element", Keywords.NAME);
                } 
            }
            else { 
                instanceName = node.GetAttribute(Keywords.TYPE); 
                if (instanceName == null || instanceName.Length == 0)
                    throw ExceptionBuilder.MissingAttribute("Element", Keywords.TYPE); 
            }

            return instanceName;
        } 

        internal void HandleColumn(XmlElement node, DataTable table) { 
            Debug.Assert(FEqualIdentity(node, Keywords.XDR_ELEMENT, Keywords.XDRNS) || 
                         FEqualIdentity(node, Keywords.XDR_ATTRIBUTE, Keywords.XDRNS), "Illegal node type");
 
            string          instanceName;
            string          strName;
            Type            type;
            string          strType; 
            string          strValues;
            int             minOccurs = 0; 
            int             maxOccurs = 1; 
            string          strDefault;
            DataColumn      column; 

            string strUse = node.GetAttribute(Keywords.USE);

 

            // Get the name 
            if (node.Attributes.Count > 0) { 
                string strRef = node.GetAttribute(Keywords.REF);
 
                if (strRef != null && strRef.Length>0)
                    return; //skip ref nodes. B2 item

                strName = instanceName = GetInstanceName(node); 
                column = table.Columns[instanceName, _schemaUri];
                if (column != null) { 
                    if (column.ColumnMapping == MappingType.Attribute) { 
                        if (FEqualIdentity(node, Keywords.XDR_ATTRIBUTE, Keywords.XDRNS))
                            throw ExceptionBuilder.DuplicateDeclaration(strName); 
                    }
                    else {
                        if (FEqualIdentity(node, Keywords.XDR_ELEMENT, Keywords.XDRNS)) {
                            throw ExceptionBuilder.DuplicateDeclaration(strName); 
                        }
                    } 
                    instanceName = GenUniqueColumnName(strName, table); 
                }
            } 
            else
            {
                strName = instanceName = "";
            } 

            // Now get the type 
            XmlElement typeNode = FindTypeNode(node); 

            SimpleType xsdType = null; 

            if (typeNode == null) {
                strType = node.GetAttribute(Keywords.TYPE);
                throw ExceptionBuilder.UndefinedDatatype(strType); 
            }
 
            strType = typeNode.GetAttribute(Keywords.DT_TYPE, Keywords.DTNS); 
            strValues = typeNode.GetAttribute(Keywords.DT_VALUES, Keywords.DTNS);
            if (strType == null || strType.Length == 0) { 
                strType = "";
                type = typeof(string);
            }
            else { 
                type = ParseDataType(strType, strValues);
                // HACK: temp work around special types 
                if (strType == "float") { 
                    strType = "";
                } 

                if (strType == "char") {
                    strType = "";
                    xsdType = SimpleType.CreateSimpleType(type); 
                }
 
 
                if (strType == "enumeration") {
                    strType = ""; 
                    xsdType = SimpleType.CreateEnumeratedType(strValues);
                }

                if (strType == "bin.base64") { 
                    strType = "";
                    xsdType = SimpleType.CreateByteArrayType("base64"); 
                } 

                if (strType == "bin.hex") { 
                    strType = "";
                    xsdType = SimpleType.CreateByteArrayType("hex");
                }
 
            }
 
            bool isAttribute = FEqualIdentity(node, Keywords.XDR_ATTRIBUTE, Keywords.XDRNS); 

            GetMinMax(node, isAttribute,  ref minOccurs, ref maxOccurs); 

            strDefault = null;

            // Does XDR has default? 
            strDefault = node.GetAttribute(Keywords.DEFAULT);
 
 
            bool bNullable = false;
 
            column = new DataColumn(XmlConvert.DecodeName(instanceName), type, null,
                isAttribute ? MappingType.Attribute : MappingType.Element);

            SetProperties(column, node.Attributes); // xmlschema.SetProperties will skipp setting expressions 
            column.XmlDataType = strType;
            column.SimpleType = xsdType; 
            column.AllowDBNull = (minOccurs == 0) || bNullable; 
            column.Namespace = (isAttribute) ? String.Empty : _schemaUri;
// webdata 97925 
// We will skip handling expression columns in SetProperties, so we need set the expressions here
            if (node.Attributes != null) {
                for (int i = 0; i < node.Attributes.Count; i++) {
                    if (node.Attributes[i].NamespaceURI == Keywords.MSDNS) { 
                        if (node.Attributes[i].LocalName == "Expression"){
                            column.Expression =  node.Attributes[i].Value; 
                            break; 
                        }
                    } 
                }
            }

            String targetNamespace = node.GetAttribute(Keywords.TARGETNAMESPACE); 
            if (targetNamespace != null && targetNamespace.Length > 0)
                column.Namespace = targetNamespace; 
 
            table.Columns.Add(column);
            if (strDefault != null && strDefault.Length != 0) 
                try {
                    column.DefaultValue = SqlConvert.ChangeTypeForXML(strDefault, type);
                }
                catch (System.FormatException) { 

                    throw ExceptionBuilder.CannotConvert(strDefault, type.FullName); 
                } 

            for (XmlNode n = node.FirstChild ; n != null ; n = n.NextSibling) { 
                if (FEqualIdentity(n, Keywords.XDR_DESCRIPTION, Keywords.XDRNS))
                    column.Description(((XmlElement) n).InnerText);
            }
 

        } 
 
        internal void GetMinMax(XmlElement elNode, ref int minOccurs, ref int maxOccurs) {
 
            GetMinMax(elNode, false,  ref minOccurs, ref maxOccurs);

        }
 
        internal void GetMinMax(XmlElement elNode, bool isAttribute, ref int minOccurs, ref int maxOccurs) {
 
            string occurs = elNode.GetAttribute(Keywords.MINOCCURS); 
            if (occurs != null && occurs.Length > 0) {
                try { 
                    minOccurs = Int32.Parse(occurs, CultureInfo.InvariantCulture);
                }
                catch (Exception e) {
                    // 
                    if (!ADP.IsCatchableExceptionType (e)) {
                        throw; 
                    } 
                    throw ExceptionBuilder.AttributeValues("minOccurs", "0", "1");
                } 
            }
            occurs = elNode.GetAttribute(Keywords.MAXOCCURS);

            if (occurs != null && occurs.Length > 0) { 
                int bZeroOrMore = string.Compare(occurs, Keywords.STAR , StringComparison.Ordinal);
                if (bZeroOrMore == 0) { 
                    maxOccurs = -1; 
                }
                else { 
                    try {
                        maxOccurs = Int32.Parse(occurs, CultureInfo.InvariantCulture);
                    }
                    catch (Exception e) { 
                        //
                        if (!ADP.IsCatchableExceptionType (e)) { 
                            throw; 
                        }
                        throw ExceptionBuilder.AttributeValues("maxOccurs", "1", Keywords.STAR); 
                    }
                    if (maxOccurs != 1) {
                        throw ExceptionBuilder.AttributeValues("maxOccurs", "1", Keywords.STAR);
                    } 
                }
            } 
 
        }
 

        internal void HandleTypeNode(XmlElement typeNode, DataTable table, ArrayList tableChildren)
        {
            DataTable       tableChild; 

            for (XmlNode n = typeNode.FirstChild; n != null; n = n.NextSibling) { 
 
                if (!(n is XmlElement))
                    continue; 

                if (FEqualIdentity(n, Keywords.XDR_ELEMENT, Keywords.XDRNS)) {

 
                    tableChild = HandleTable((XmlElement) n);
                    if (tableChild != null) { 
                            tableChildren.Add(tableChild); 
                        continue;
                    } 
                }

                if (FEqualIdentity(n, Keywords.XDR_ATTRIBUTE, Keywords.XDRNS) ||
                    FEqualIdentity(n, Keywords.XDR_ELEMENT, Keywords.XDRNS)) { 
                    HandleColumn((XmlElement) n, table);
                    continue; 
                } 

 

            }

 
        }
 
        internal DataTable InstantiateTable(DataSet dataSet, XmlElement node, XmlElement typeNode) { 
            string          typeName = "";
            XmlAttributeCollection      attrs = node.Attributes; 
            DataTable       table;
            int             minOccurs = 1;
            int             maxOccurs = 1;
            string          keys = null; 
            ArrayList       tableChildren = new ArrayList();
 
 

            if (attrs.Count > 0) { 
                typeName = GetInstanceName(node);
                table = dataSet.Tables.GetTable(typeName, _schemaUri);
                if (table != null) {
                      return  table; 
                }
            } 
 
            table = new DataTable(XmlConvert.DecodeName(typeName));
            // fxcop: new DataTable should inherit the CaseSensitive, Locale from DataSet and possibly updating during SetProperties 

            table.Namespace = _schemaUri;

            GetMinMax(node, ref minOccurs, ref maxOccurs); 
            table.MinOccurs = minOccurs;
            table.MaxOccurs = maxOccurs; 
 
            _ds.Tables.Add(table);
 
            HandleTypeNode(typeNode, table, tableChildren);

            SetProperties(table, attrs);
 
            // check to see if we fave unique constraint
 
            if (keys != null) { 
                string[] list = keys.TrimEnd(null).Split(null);
                int keyLength = list.Length; 

                DataColumn[] cols = new DataColumn[keyLength];

                for (int i = 0; i < keyLength; i++) { 
                    DataColumn col = table.Columns[list[i], _schemaUri];
                    if (col == null) 
                        throw ExceptionBuilder.ElementTypeNotFound(list[i]); 
                    cols[i] = col;
                } 
                table.PrimaryKey = cols;
            }

 
            foreach(DataTable _tableChild in tableChildren) {
                DataRelation relation = null; 
 
                DataRelationCollection childRelations = table.ChildRelations;
 
                for (int j = 0; j < childRelations.Count; j++) {
                    if (!childRelations[j].Nested)
                        continue;
 
                    if (_tableChild == childRelations[j].ChildTable)
                        relation = childRelations[j]; 
                } 

                if (relation!=null) 
                    continue;

                DataColumn parentKey = table.AddUniqueKey();
                // foreign key in the child table 
                DataColumn childKey = _tableChild.AddForeignKey(parentKey);
                // create relationship 
                // setup relationship between parent and this table 
                relation = new DataRelation(table.TableName + "_" + _tableChild.TableName, parentKey, childKey, true);
 
                relation.CheckMultipleNested = false; // disable the check for multiple nested parent

                relation.Nested = true;
                _tableChild.DataSet.Relations.Add(relation); 
                relation.CheckMultipleNested = true; // enable the check for multiple nested parent
            } 
 
            return table;
        } 

        internal DataTable InstantiateSimpleTable(DataSet dataSet, XmlElement node) {
            string          typeName;
            XmlAttributeCollection      attrs = node.Attributes; 
            DataTable       table;
            int             minOccurs = 1; 
            int             maxOccurs = 1; 

            typeName = GetInstanceName(node); 
            table = dataSet.Tables.GetTable(typeName, _schemaUri);
            if (table != null) {
                throw ExceptionBuilder.DuplicateDeclaration(typeName);
            } 
            String tbName = XmlConvert.DecodeName(typeName);
            table = new DataTable(tbName); 
            // fxcop: new DataTable will either inherit the CaseSensitive, Locale from DataSet or be set during SetProperties 
            table.Namespace = _schemaUri;
            GetMinMax(node, ref minOccurs, ref maxOccurs); 
            table.MinOccurs = minOccurs;
            table.MaxOccurs = maxOccurs;
            SetProperties(table, attrs);
            table.repeatableElement = true; 

            HandleColumn((XmlElement) node, table); 
 
            table.Columns[0].ColumnName = tbName + "_Column";
            _ds.Tables.Add(table); 


            return table;
        } 

 
 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
// [....]
// [....] 
//----------------------------------------------------------------------------- 

namespace System.Data { 
    using System;
    using System.Xml;
    using System.Collections;
    using System.Globalization; 
    using System.ComponentModel;
    using System.Diagnostics; 
    using System.Data.Common; 

    internal sealed class XDRSchema : XMLSchema { 
        internal String             _schemaName;
        internal String             _schemaUri;
        internal XmlElement         _schemaRoot;
        internal DataSet            _ds; 
        private  static char[] colonArray = new char[] {':'};
 
 
        internal XDRSchema(DataSet ds, bool fInline) {
            _schemaUri = String.Empty; 
            _schemaName = String.Empty;
            _schemaRoot = null;
            _ds = ds;
        } 

        internal void LoadSchema(XmlElement schemaRoot, DataSet ds) { 
            if (schemaRoot == null) 
                return;
 
            _schemaRoot = schemaRoot;
            _ds = ds;
            _schemaName = schemaRoot.GetAttribute(Keywords.NAME);
 

            _schemaUri = ""; 
            Debug.Assert(FEqualIdentity(schemaRoot, Keywords.XDR_SCHEMA, Keywords.XDRNS), "Illegal node"); 

            // Get Locale and CaseSensitive properties 

            if (_schemaName == null || _schemaName.Length == 0)
                _schemaName = "NewDataSet";
 
            ds.Namespace = _schemaUri;
 
            // Walk all the top level Element tags. 
            for (XmlNode n = schemaRoot.FirstChild; n != null; n = n.NextSibling) {
                if (!(n is XmlElement)) 
                    continue;

                XmlElement child = (XmlElement) n;
 
                if (FEqualIdentity(child, Keywords.XDR_ELEMENTTYPE, Keywords.XDRNS)) {
                    HandleTable(child); 
                } 
            }
 
            _schemaName = XmlConvert.DecodeName(_schemaName);
            if (ds.Tables[_schemaName] == null)
                ds.DataSetName = _schemaName;
 
        }
 
        internal XmlElement FindTypeNode(XmlElement node) { 
            string      strType;
            XmlNode     vn; 
            XmlNode     vnRoof;

            Debug.Assert(FEqualIdentity(node, Keywords.XDR_ELEMENT, Keywords.XDRNS) ||
                         FEqualIdentity(node, Keywords.XDR_SCHEMA, Keywords.XDRNS) || 
                         FEqualIdentity(node, Keywords.XDR_ATTRIBUTE, Keywords.XDRNS) ||
                         FEqualIdentity(node, Keywords.XDR_ELEMENTTYPE, Keywords.XDRNS), 
                         "Invalid node type " + node.LocalName); 

            if (FEqualIdentity(node, Keywords.XDR_ELEMENTTYPE, Keywords.XDRNS)) 
                return node;

            strType = node.GetAttribute(Keywords.TYPE);
 
            if (FEqualIdentity(node, Keywords.XDR_ELEMENT, Keywords.XDRNS) ||
                FEqualIdentity(node, Keywords.XDR_ATTRIBUTE, Keywords.XDRNS)) { 
                if (strType == null || strType.Length == 0) 
                    return null;
 
                // Find an ELEMENTTYPE or ATTRIBUTETYPE with name=strType
                vn = node.OwnerDocument.FirstChild;
                vnRoof = node.OwnerDocument;
 
                while (vn != vnRoof) {
                    if ((FEqualIdentity(vn, Keywords.XDR_ELEMENTTYPE, Keywords.XDRNS) && 
                         FEqualIdentity(node, Keywords.XDR_ELEMENT, Keywords.XDRNS)) || 
                        (FEqualIdentity(vn, Keywords.XDR_ATTRIBUTETYPE, Keywords.XDRNS) &&
                         FEqualIdentity(node, Keywords.XDR_ATTRIBUTE, Keywords.XDRNS))) { 
                        if (vn is XmlElement && ((XmlElement)vn).GetAttribute(Keywords.NAME) == strType)
                            return(XmlElement)vn;
                    }
 
                    // Move vn node
                    if (vn.FirstChild != null) 
                        vn = vn.FirstChild; 
                    else if (vn.NextSibling != null)
                        vn = vn.NextSibling; 
                    else {
                        while (vn != vnRoof) {
                            vn = vn.ParentNode;
                            if (vn.NextSibling != null) { 
                                vn = vn.NextSibling;
                                break; 
                            } 
                        }
                    } 
                }

                return null;
            } 

            return null; 
        } 

        internal bool IsTextOnlyContent(XmlElement node) { 
            Debug.Assert(FEqualIdentity(node, Keywords.XDR_ELEMENTTYPE, Keywords.XDRNS),
                         "Invalid node type " + node.LocalName);

            string value = node.GetAttribute(Keywords.CONTENT); 
            if (value == null || value.Length == 0) {
                string type = node.GetAttribute(Keywords.DT_TYPE, Keywords.DTNS); 
                if (type != null && type.Length > 0) 
                    return true;
 
                return false;
            }

            if (value == Keywords.EMPTY || value == Keywords.ELTONLY || value == Keywords.ELEMENTONLY || value == Keywords.MIXED) 
                return false;
            if (value == Keywords.TEXTONLY) 
                return true; 

            throw ExceptionBuilder.InvalidAttributeValue("content", value); 
        }

        internal bool IsXDRField(XmlElement node, XmlElement typeNode) {
            int         min = 1; 
            int         max = 1;
 
            if (!IsTextOnlyContent(typeNode)) 
                return false;
 
            for (XmlNode n = typeNode.FirstChild; n != null; n = n.NextSibling) {
                if (FEqualIdentity(n, Keywords.XDR_ELEMENT, Keywords.XDRNS) ||
                    FEqualIdentity(n, Keywords.XDR_ATTRIBUTE, Keywords.XDRNS))
                    return false; 
            }
 
            if (FEqualIdentity(node, Keywords.XDR_ELEMENT, Keywords.XDRNS)) { 
                GetMinMax(node, ref min, ref max);
                if (max == -1 || max > 1) 
                    return false;
            }

            return true; 
        }
 
        internal DataTable HandleTable(XmlElement node) { 
            XmlElement     typeNode;
 
            Debug.Assert(FEqualIdentity(node, Keywords.XDR_ELEMENTTYPE, Keywords.XDRNS) ||
                         FEqualIdentity(node, Keywords.XDR_ELEMENT, Keywords.XDRNS), "Invalid node type");

 
            // Figure out if this really is a table.  If not, bail out.
            typeNode = FindTypeNode(node); 
 
            string occurs = node.GetAttribute(Keywords.MINOCCURS);
 
            if (occurs != null && occurs.Length > 0)
                if ((Convert.ToInt32(occurs, CultureInfo.InvariantCulture)>1) && (typeNode==null)){
                    return InstantiateSimpleTable(_ds, node);
                } 

            occurs = node.GetAttribute(Keywords.MAXOCCURS); 
 
            if (occurs != null && occurs.Length > 0)
                if ((string.Compare(occurs, "1" , StringComparison.Ordinal) != 0) && (typeNode==null)){ 
                    return InstantiateSimpleTable(_ds, node);
                }

 
            if (typeNode == null)
                return null; 
 
            if (IsXDRField(node, typeNode))
                    return null; 

            return InstantiateTable(_ds, node, typeNode);
        }
 
        private sealed class NameType : IComparable {
            public String   name; 
            public Type     type; 
            public NameType(String n, Type t) {
                name = n; 
                type = t;
            }
            public int CompareTo(object obj) { return String.Compare(name, (string)obj, StringComparison.Ordinal); }
        }; 
        // XDR spec: http://www.ltg.ed.ac.uk/~ht/XMLData-Reduced.htm
        //           http://webdata/newspecs/schema/xdr_dt_schema.xml 
        private static NameType[] mapNameTypeXdr = { 
            new NameType("bin.base64"          , typeof(Byte[])  ), /* XDR */
            new NameType("bin.hex"             , typeof(Byte[])  ), /* XDR */ 
            new NameType("boolean"             , typeof(bool)    ), /* XDR */
            new NameType("byte"                , typeof(SByte)   ), /* XDR */
            new NameType("char"                , typeof(Char)    ), /* XDR */
            new NameType("date"                , typeof(DateTime)), /* XDR */ 
            new NameType("dateTime"            , typeof(DateTime)), /* XDR */
            new NameType("dateTime.tz"         , typeof(DateTime)), /* XDR */ 
            new NameType("entities"            , typeof(string)  ), /* XDR */ 
            new NameType("entity"              , typeof(string)  ), /* XDR */
            new NameType("enumeration"         , typeof(string)  ), /* XDR */ 
            new NameType("fixed.14.4"          , typeof(Decimal) ), /* XDR */
            new NameType("float"               , typeof(Double)  ), /* XDR */
            new NameType("i1"                  , typeof(SByte)   ), /* XDR */
            new NameType("i2"                  , typeof(Int16)   ), /* XDR */ 
            new NameType("i4"                  , typeof(Int32)   ), /* XDR */
            new NameType("i8"                  , typeof(Int64)   ), /* XDR */ 
            new NameType("id"                  , typeof(string)  ), /* XDR */ 
            new NameType("idref"               , typeof(string)  ), /* XDR */
            new NameType("idrefs"              , typeof(string)  ), /* XDR */ 
            new NameType("int"                 , typeof(Int32)   ), /* XDR */
            new NameType("nmtoken"             , typeof(string)  ), /* XDR */
            new NameType("nmtokens"            , typeof(string)  ), /* XDR */
            new NameType("notation"            , typeof(string)  ), /* XDR */ 
            new NameType("number"              , typeof(Decimal) ), /* XDR */
            new NameType("r4"                  , typeof(Single)  ), /* XDR */ 
            new NameType("r8"                  , typeof(Double)  ), /* XDR */ 
            new NameType("string"              , typeof(string)  ), /* XDR */
            new NameType("time"                , typeof(DateTime)), /* XDR */ 
            new NameType("time.tz"             , typeof(DateTime)), /* XDR */
            new NameType("ui1"                 , typeof(Byte)    ), /* XDR */
            new NameType("ui2"                 , typeof(UInt16)  ), /* XDR */
            new NameType("ui4"                 , typeof(UInt32)  ), /* XDR */ 
            new NameType("ui8"                 , typeof(UInt64)  ), /* XDR */
            new NameType("uri"                 , typeof(string)  ), /* XDR */ 
            new NameType("uuid"                , typeof(Guid)    ), /* XDR */ 
        };
 
        private static NameType FindNameType(string name) {
#if DEBUG
            for(int i = 1; i < mapNameTypeXdr.Length; ++i) {
                Debug.Assert((mapNameTypeXdr[i-1].CompareTo(mapNameTypeXdr[i].name)) < 0, "incorrect sorting"); 
            }
#endif 
            int index = Array.BinarySearch(mapNameTypeXdr, name); 
            if (index < 0) {
#if DEBUG 
                // Let's check that we realy don't have this name:
                foreach (NameType nt in mapNameTypeXdr) {
                    Debug.Assert(nt.name != name, "FindNameType('" + name + "') -- failed. Existed name not found");
                } 
#endif
                throw ExceptionBuilder.UndefinedDatatype(name); 
            } 
            Debug.Assert(mapNameTypeXdr[index].name == name, "FindNameType('" + name + "') -- failed. Wrong name found");
            return mapNameTypeXdr[index]; 
        }

        private static NameType enumerationNameType = FindNameType("enumeration");
 
        private Type ParseDataType(string dt, string dtValues) {
            string strType = dt; 
            string[] parts = dt.Split(colonArray);  // ":" 

            if (parts.Length > 2) { 
                throw ExceptionBuilder.InvalidAttributeValue("type", dt);
            }
            else if (parts.Length == 2) {
                // 
                strType = parts[1];
            } 
 
            NameType nt = FindNameType(strType);
            if (nt == enumerationNameType && (dtValues == null || dtValues.Length == 0)) 
                throw ExceptionBuilder.MissingAttribute("type", Keywords.DT_VALUES);
            return nt.type;
        }
 
        internal string GetInstanceName(XmlElement node) {
            string  instanceName; 
 
            if (FEqualIdentity(node, Keywords.XDR_ELEMENTTYPE, Keywords.XDRNS) ||
                FEqualIdentity(node, Keywords.XDR_ATTRIBUTETYPE, Keywords.XDRNS)) { 
                instanceName = node.GetAttribute(Keywords.NAME);
                if (instanceName == null || instanceName.Length == 0) {
                    throw ExceptionBuilder.MissingAttribute("Element", Keywords.NAME);
                } 
            }
            else { 
                instanceName = node.GetAttribute(Keywords.TYPE); 
                if (instanceName == null || instanceName.Length == 0)
                    throw ExceptionBuilder.MissingAttribute("Element", Keywords.TYPE); 
            }

            return instanceName;
        } 

        internal void HandleColumn(XmlElement node, DataTable table) { 
            Debug.Assert(FEqualIdentity(node, Keywords.XDR_ELEMENT, Keywords.XDRNS) || 
                         FEqualIdentity(node, Keywords.XDR_ATTRIBUTE, Keywords.XDRNS), "Illegal node type");
 
            string          instanceName;
            string          strName;
            Type            type;
            string          strType; 
            string          strValues;
            int             minOccurs = 0; 
            int             maxOccurs = 1; 
            string          strDefault;
            DataColumn      column; 

            string strUse = node.GetAttribute(Keywords.USE);

 

            // Get the name 
            if (node.Attributes.Count > 0) { 
                string strRef = node.GetAttribute(Keywords.REF);
 
                if (strRef != null && strRef.Length>0)
                    return; //skip ref nodes. B2 item

                strName = instanceName = GetInstanceName(node); 
                column = table.Columns[instanceName, _schemaUri];
                if (column != null) { 
                    if (column.ColumnMapping == MappingType.Attribute) { 
                        if (FEqualIdentity(node, Keywords.XDR_ATTRIBUTE, Keywords.XDRNS))
                            throw ExceptionBuilder.DuplicateDeclaration(strName); 
                    }
                    else {
                        if (FEqualIdentity(node, Keywords.XDR_ELEMENT, Keywords.XDRNS)) {
                            throw ExceptionBuilder.DuplicateDeclaration(strName); 
                        }
                    } 
                    instanceName = GenUniqueColumnName(strName, table); 
                }
            } 
            else
            {
                strName = instanceName = "";
            } 

            // Now get the type 
            XmlElement typeNode = FindTypeNode(node); 

            SimpleType xsdType = null; 

            if (typeNode == null) {
                strType = node.GetAttribute(Keywords.TYPE);
                throw ExceptionBuilder.UndefinedDatatype(strType); 
            }
 
            strType = typeNode.GetAttribute(Keywords.DT_TYPE, Keywords.DTNS); 
            strValues = typeNode.GetAttribute(Keywords.DT_VALUES, Keywords.DTNS);
            if (strType == null || strType.Length == 0) { 
                strType = "";
                type = typeof(string);
            }
            else { 
                type = ParseDataType(strType, strValues);
                // HACK: temp work around special types 
                if (strType == "float") { 
                    strType = "";
                } 

                if (strType == "char") {
                    strType = "";
                    xsdType = SimpleType.CreateSimpleType(type); 
                }
 
 
                if (strType == "enumeration") {
                    strType = ""; 
                    xsdType = SimpleType.CreateEnumeratedType(strValues);
                }

                if (strType == "bin.base64") { 
                    strType = "";
                    xsdType = SimpleType.CreateByteArrayType("base64"); 
                } 

                if (strType == "bin.hex") { 
                    strType = "";
                    xsdType = SimpleType.CreateByteArrayType("hex");
                }
 
            }
 
            bool isAttribute = FEqualIdentity(node, Keywords.XDR_ATTRIBUTE, Keywords.XDRNS); 

            GetMinMax(node, isAttribute,  ref minOccurs, ref maxOccurs); 

            strDefault = null;

            // Does XDR has default? 
            strDefault = node.GetAttribute(Keywords.DEFAULT);
 
 
            bool bNullable = false;
 
            column = new DataColumn(XmlConvert.DecodeName(instanceName), type, null,
                isAttribute ? MappingType.Attribute : MappingType.Element);

            SetProperties(column, node.Attributes); // xmlschema.SetProperties will skipp setting expressions 
            column.XmlDataType = strType;
            column.SimpleType = xsdType; 
            column.AllowDBNull = (minOccurs == 0) || bNullable; 
            column.Namespace = (isAttribute) ? String.Empty : _schemaUri;
// webdata 97925 
// We will skip handling expression columns in SetProperties, so we need set the expressions here
            if (node.Attributes != null) {
                for (int i = 0; i < node.Attributes.Count; i++) {
                    if (node.Attributes[i].NamespaceURI == Keywords.MSDNS) { 
                        if (node.Attributes[i].LocalName == "Expression"){
                            column.Expression =  node.Attributes[i].Value; 
                            break; 
                        }
                    } 
                }
            }

            String targetNamespace = node.GetAttribute(Keywords.TARGETNAMESPACE); 
            if (targetNamespace != null && targetNamespace.Length > 0)
                column.Namespace = targetNamespace; 
 
            table.Columns.Add(column);
            if (strDefault != null && strDefault.Length != 0) 
                try {
                    column.DefaultValue = SqlConvert.ChangeTypeForXML(strDefault, type);
                }
                catch (System.FormatException) { 

                    throw ExceptionBuilder.CannotConvert(strDefault, type.FullName); 
                } 

            for (XmlNode n = node.FirstChild ; n != null ; n = n.NextSibling) { 
                if (FEqualIdentity(n, Keywords.XDR_DESCRIPTION, Keywords.XDRNS))
                    column.Description(((XmlElement) n).InnerText);
            }
 

        } 
 
        internal void GetMinMax(XmlElement elNode, ref int minOccurs, ref int maxOccurs) {
 
            GetMinMax(elNode, false,  ref minOccurs, ref maxOccurs);

        }
 
        internal void GetMinMax(XmlElement elNode, bool isAttribute, ref int minOccurs, ref int maxOccurs) {
 
            string occurs = elNode.GetAttribute(Keywords.MINOCCURS); 
            if (occurs != null && occurs.Length > 0) {
                try { 
                    minOccurs = Int32.Parse(occurs, CultureInfo.InvariantCulture);
                }
                catch (Exception e) {
                    // 
                    if (!ADP.IsCatchableExceptionType (e)) {
                        throw; 
                    } 
                    throw ExceptionBuilder.AttributeValues("minOccurs", "0", "1");
                } 
            }
            occurs = elNode.GetAttribute(Keywords.MAXOCCURS);

            if (occurs != null && occurs.Length > 0) { 
                int bZeroOrMore = string.Compare(occurs, Keywords.STAR , StringComparison.Ordinal);
                if (bZeroOrMore == 0) { 
                    maxOccurs = -1; 
                }
                else { 
                    try {
                        maxOccurs = Int32.Parse(occurs, CultureInfo.InvariantCulture);
                    }
                    catch (Exception e) { 
                        //
                        if (!ADP.IsCatchableExceptionType (e)) { 
                            throw; 
                        }
                        throw ExceptionBuilder.AttributeValues("maxOccurs", "1", Keywords.STAR); 
                    }
                    if (maxOccurs != 1) {
                        throw ExceptionBuilder.AttributeValues("maxOccurs", "1", Keywords.STAR);
                    } 
                }
            } 
 
        }
 

        internal void HandleTypeNode(XmlElement typeNode, DataTable table, ArrayList tableChildren)
        {
            DataTable       tableChild; 

            for (XmlNode n = typeNode.FirstChild; n != null; n = n.NextSibling) { 
 
                if (!(n is XmlElement))
                    continue; 

                if (FEqualIdentity(n, Keywords.XDR_ELEMENT, Keywords.XDRNS)) {

 
                    tableChild = HandleTable((XmlElement) n);
                    if (tableChild != null) { 
                            tableChildren.Add(tableChild); 
                        continue;
                    } 
                }

                if (FEqualIdentity(n, Keywords.XDR_ATTRIBUTE, Keywords.XDRNS) ||
                    FEqualIdentity(n, Keywords.XDR_ELEMENT, Keywords.XDRNS)) { 
                    HandleColumn((XmlElement) n, table);
                    continue; 
                } 

 

            }

 
        }
 
        internal DataTable InstantiateTable(DataSet dataSet, XmlElement node, XmlElement typeNode) { 
            string          typeName = "";
            XmlAttributeCollection      attrs = node.Attributes; 
            DataTable       table;
            int             minOccurs = 1;
            int             maxOccurs = 1;
            string          keys = null; 
            ArrayList       tableChildren = new ArrayList();
 
 

            if (attrs.Count > 0) { 
                typeName = GetInstanceName(node);
                table = dataSet.Tables.GetTable(typeName, _schemaUri);
                if (table != null) {
                      return  table; 
                }
            } 
 
            table = new DataTable(XmlConvert.DecodeName(typeName));
            // fxcop: new DataTable should inherit the CaseSensitive, Locale from DataSet and possibly updating during SetProperties 

            table.Namespace = _schemaUri;

            GetMinMax(node, ref minOccurs, ref maxOccurs); 
            table.MinOccurs = minOccurs;
            table.MaxOccurs = maxOccurs; 
 
            _ds.Tables.Add(table);
 
            HandleTypeNode(typeNode, table, tableChildren);

            SetProperties(table, attrs);
 
            // check to see if we fave unique constraint
 
            if (keys != null) { 
                string[] list = keys.TrimEnd(null).Split(null);
                int keyLength = list.Length; 

                DataColumn[] cols = new DataColumn[keyLength];

                for (int i = 0; i < keyLength; i++) { 
                    DataColumn col = table.Columns[list[i], _schemaUri];
                    if (col == null) 
                        throw ExceptionBuilder.ElementTypeNotFound(list[i]); 
                    cols[i] = col;
                } 
                table.PrimaryKey = cols;
            }

 
            foreach(DataTable _tableChild in tableChildren) {
                DataRelation relation = null; 
 
                DataRelationCollection childRelations = table.ChildRelations;
 
                for (int j = 0; j < childRelations.Count; j++) {
                    if (!childRelations[j].Nested)
                        continue;
 
                    if (_tableChild == childRelations[j].ChildTable)
                        relation = childRelations[j]; 
                } 

                if (relation!=null) 
                    continue;

                DataColumn parentKey = table.AddUniqueKey();
                // foreign key in the child table 
                DataColumn childKey = _tableChild.AddForeignKey(parentKey);
                // create relationship 
                // setup relationship between parent and this table 
                relation = new DataRelation(table.TableName + "_" + _tableChild.TableName, parentKey, childKey, true);
 
                relation.CheckMultipleNested = false; // disable the check for multiple nested parent

                relation.Nested = true;
                _tableChild.DataSet.Relations.Add(relation); 
                relation.CheckMultipleNested = true; // enable the check for multiple nested parent
            } 
 
            return table;
        } 

        internal DataTable InstantiateSimpleTable(DataSet dataSet, XmlElement node) {
            string          typeName;
            XmlAttributeCollection      attrs = node.Attributes; 
            DataTable       table;
            int             minOccurs = 1; 
            int             maxOccurs = 1; 

            typeName = GetInstanceName(node); 
            table = dataSet.Tables.GetTable(typeName, _schemaUri);
            if (table != null) {
                throw ExceptionBuilder.DuplicateDeclaration(typeName);
            } 
            String tbName = XmlConvert.DecodeName(typeName);
            table = new DataTable(tbName); 
            // fxcop: new DataTable will either inherit the CaseSensitive, Locale from DataSet or be set during SetProperties 
            table.Namespace = _schemaUri;
            GetMinMax(node, ref minOccurs, ref maxOccurs); 
            table.MinOccurs = minOccurs;
            table.MaxOccurs = maxOccurs;
            SetProperties(table, attrs);
            table.repeatableElement = true; 

            HandleColumn((XmlElement) node, table); 
 
            table.Columns[0].ColumnName = tbName + "_Column";
            _ds.Tables.Add(table); 


            return table;
        } 

 
 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK