| 
									
										
										
										
											2016-08-03 10:59:49 +00:00
										 |  |  | //------------------------------------------------------------------------------ | 
					
						
							|  |  |  | // <copyright file="XDRSchema.cs" company="Microsoft"> | 
					
						
							|  |  |  | //     Copyright (c) Microsoft Corporation.  All rights reserved. | 
					
						
							|  |  |  | // </copyright>                                                                 | 
					
						
							| 
									
										
										
										
											2017-08-21 15:34:15 +00:00
										 |  |  | // <owner current="true" primary="true">Microsoft</owner> | 
					
						
							|  |  |  | // <owner current="true" primary="false">Microsoft</owner> | 
					
						
							|  |  |  | // <owner current="false" primary="false">Microsoft</owner> | 
					
						
							| 
									
										
										
										
											2016-08-03 10:59:49 +00:00
										 |  |  | //------------------------------------------------------------------------------ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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(StorageType.Char, 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); | 
					
						
							|  |  |  |                 }     | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         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; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |