//\r
// Design notes are the bottom of the source.\r
//\r
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
+\r
+//\r
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)\r
+//\r
+// Permission is hereby granted, free of charge, to any person obtaining\r
+// a copy of this software and associated documentation files (the\r
+// "Software"), to deal in the Software without restriction, including\r
+// without limitation the rights to use, copy, modify, merge, publish,\r
+// distribute, sublicense, and/or sell copies of the Software, and to\r
+// permit persons to whom the Software is furnished to do so, subject to\r
+// the following conditions:\r
+// \r
+// The above copyright notice and this permission notice shall be\r
+// included in all copies or substantial portions of the Software.\r
+// \r
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+//\r
+\r
using System;\r
using System.Collections;\r
using System.Data;\r
+using System.Globalization;\r
using System.IO; // for Driver\r
using System.Text; // for Driver\r
using System.Xml;\r
public DataColumn SimpleContent;\r
public DataColumn PrimaryKey;\r
public DataColumn ReferenceKey;\r
-#if NET_2_0\r
public int lastElementIndex = -1;\r
-#endif\r
\r
// Parent TableMapping\r
public TableMapping ParentTable;\r
if (document.DocumentElement == null)\r
return;\r
\r
+ dataset.Locale = new CultureInfo ("en-US"); // default(!)\r
+\r
// If the root element is not a data table, treat \r
// this element as DataSet.\r
// Read one element. It might be DataSet element.\r
}\r
}\r
\r
+ int count = 0; \r
foreach (TableMapping map in tables) {\r
+ string baseName = map.PrimaryKey != null ? map.PrimaryKey.ColumnName : map.Table.TableName + "_Id";\r
+ \r
+ // Make sure name of RK column is unique\r
+ string rkName = baseName;\r
+ if (map.ChildTables [map.Table.TableName] != null) {\r
+ rkName = baseName + '_' + count;\r
+ while (map.GetColumn (rkName) != null) {\r
+ count++;\r
+ rkName = baseName + '_' + count;\r
+ }\r
+ }\r
+ \r
foreach (TableMapping ct in map.ChildTables) {\r
- ct.ReferenceKey = GetMappedColumn (ct, map.Table.TableName + "_Id", map.Table.Prefix, map.Table.Namespace, MappingType.Hidden);\r
+ ct.ReferenceKey = GetMappedColumn (ct, rkName, map.Table.Prefix, map.Table.Namespace, MappingType.Hidden, map.PrimaryKey != null ? map.PrimaryKey.DataType : typeof (int));\r
}\r
}\r
\r
continue;\r
if (map.PrimaryKey != null)\r
map.Table.Columns.Add (map.PrimaryKey);\r
- foreach (DataColumn col in map.Elements)\r
+\r
+ foreach (DataColumn col in map.Elements) \r
map.Table.Columns.Add (col);\r
+\r
foreach (DataColumn col in map.Attributes)\r
map.Table.Columns.Add (col);\r
- if (map.SimpleContent != null)\r
+ \r
+ if (map.SimpleContent != null) \r
map.Table.Columns.Add (map.SimpleContent);\r
- if (map.ReferenceKey != null)\r
+ \r
+ if (map.ReferenceKey != null) \r
map.Table.Columns.Add (map.ReferenceKey);\r
dataset.Tables.Add (map.Table);\r
}\r
DataTable pt = dataset.Tables [rs.ParentTableName];\r
DataTable ct = dataset.Tables [rs.ChildTableName];\r
DataColumn pc = pt.Columns [rs.ParentColumnName];\r
- DataColumn cc = ct.Columns [rs.ChildColumnName];\r
+ DataColumn cc = null;\r
+ \r
+ // If both parent and child tables have same name, it is quite\r
+ // possible to have column names suffixed with some numbers.\r
+ if (rs.ParentTableName == rs.ChildTableName) {\r
+ cc = ct.Columns [rs.ChildColumnName + "_" + count];\r
+ }\r
+ if (cc == null)\r
+ cc = ct.Columns [rs.ChildColumnName];\r
+ \r
if (pt == null)\r
throw new DataException ("Parent table was not found : " + rs.ParentTableName);\r
else if (ct == null)\r
\r
private void InferColumnElement (TableMapping table, XmlElement el)\r
{\r
- string localName = XmlHelper.Decode (el.LocalName);
+ string localName = XmlHelper.Decode (el.LocalName);\r
DataColumn col = table.GetColumn (localName);\r
if (col != null) {\r
if (col.ColumnMapping != MappingType.Element)\r
throw new DataException (String.Format ("Column {0} is already mapped to {1}.", localName, col.ColumnMapping));\r
-#if NET_2_0\r
table.lastElementIndex = table.Elements.IndexOf (col);\r
-#endif\r
return;\r
}\r
if (table.ChildTables [localName] != null)\r
col = new DataColumn (localName, typeof (string));\r
col.Namespace = el.NamespaceURI;\r
col.Prefix = el.Prefix;\r
-#if NET_2_0\r
table.Elements.Insert (++table.lastElementIndex, col);\r
-#else\r
- table.Elements.Add (col);\r
-#endif\r
}\r
\r
private void CheckExtraneousElementColumn (TableMapping parentTable, XmlElement el)\r
\r
private void PopulatePrimaryKey (TableMapping table)\r
{\r
- if (table.PrimaryKey != null) {\r
- if (table.PrimaryKey.ColumnName != table.Table.TableName + "_Id")\r
- throw new DataException ("There is already a primary key column.");\r
- return;\r
- }\r
DataColumn col = new DataColumn (table.Table.TableName + "_Id");\r
col.ColumnMapping = MappingType.Hidden;\r
col.DataType = typeof (int);\r
table.PrimaryKey = col;\r
}\r
\r
- private void PopulateRelationStructure (string parent, string child)\r
+ private void PopulateRelationStructure (string parent, string child, string pkeyColumn)\r
{\r
if (relations [parent, child] != null)\r
return;\r
-\r
RelationStructure rs = new RelationStructure ();\r
rs.ParentTableName = parent;\r
rs.ChildTableName = child;\r
- rs.ParentColumnName = parent + "_Id";\r
- rs.ChildColumnName = parent + "_Id";\r
+ rs.ParentColumnName = pkeyColumn;\r
+ rs.ChildColumnName = pkeyColumn;\r
rs.CreateConstraint = true;\r
rs.IsNested = true;\r
relations.Add (rs);\r
if (table.SimpleContent != null)\r
return;\r
\r
- GetMappedColumn (table, localName + "_Column", el.Prefix, el.NamespaceURI, MappingType.SimpleContent);\r
+ GetMappedColumn (table, localName + "_Column", el.Prefix, el.NamespaceURI, MappingType.SimpleContent, null);\r
}\r
\r
private void InferTableElement (TableMapping parentTable, XmlElement el)\r
\r
bool hasChildElements = false;\r
bool hasAttributes = false;\r
- bool hasText = false;
+ bool hasText = false;\r
bool isElementRepeated = false;\r
\r
foreach (XmlAttribute attr in el.Attributes) {\r
if (attr.NamespaceURI == XmlConstants.XmlnsNS\r
-#if NET_2_0\r
|| attr.NamespaceURI == XmlConstants.XmlNS\r
-#endif\r
)\r
continue;\r
if (ignoredNamespaces != null &&\r
continue;\r
\r
hasAttributes = true;\r
- DataColumn col = GetMappedColumn (table,\r
+ GetMappedColumn (table,\r
XmlHelper.Decode (attr.LocalName),\r
attr.Prefix,\r
- attr.NamespaceURI,\r
- MappingType.Attribute);\r
+ attr.NamespaceURI,\r
+ MappingType.Attribute,\r
+ null); \r
}\r
\r
foreach (XmlNode n in el.ChildNodes) {\r
case XmlNodeType.ProcessingInstruction: // ignore\r
continue;\r
default: // text content\r
- hasText = true;
- if (GetElementMappingType (el, ignoredNamespaces, null) == ElementMappingType.Repeated)
- isElementRepeated = true;
+ hasText = true;\r
+ if (GetElementMappingType (el, ignoredNamespaces, null) == ElementMappingType.Repeated)\r
+ isElementRepeated = true;\r
break;\r
case XmlNodeType.Element: // child\r
hasChildElements = true;\r
InferColumnElement (table, cel);\r
break;\r
case ElementMappingType.Repeated:\r
- PopulatePrimaryKey (table);\r
- PopulateRelationStructure (table.Table.TableName, childLocalName);\r
+ if (table.PrimaryKey == null)\r
+ PopulatePrimaryKey (table);\r
+ PopulateRelationStructure (table.Table.TableName, childLocalName, table.PrimaryKey.ColumnName);\r
InferRepeatedElement (table, cel);\r
break;\r
case ElementMappingType.Complex:\r
- PopulatePrimaryKey (table);\r
- PopulateRelationStructure (table.Table.TableName, childLocalName);\r
+ if (table.PrimaryKey == null)\r
+ PopulatePrimaryKey (table);\r
+ PopulateRelationStructure (table.Table.TableName, childLocalName, table.PrimaryKey.ColumnName);\r
InferTableElement (table, cel);\r
break;\r
}\r
// Attributes + !Children + Text = SimpleContent\r
if (table.SimpleContent == null // no need to create\r
&& !hasChildElements && hasText && (hasAttributes || isElementRepeated)) {\r
- GetMappedColumn (table, table.Table.TableName + "_Text", String.Empty, String.Empty, MappingType.SimpleContent);\r
+ GetMappedColumn (table, table.Table.TableName + "_Text", String.Empty, String.Empty, MappingType.SimpleContent, null);\r
}\r
}\r
\r
return map;\r
}\r
\r
- private DataColumn GetMappedColumn (TableMapping table, string name, string prefix, string ns, MappingType type)\r
+ private DataColumn GetMappedColumn (TableMapping table, string name, string prefix, string ns, MappingType type, Type optColType)\r
{\r
DataColumn col = table.GetColumn (name);\r
// Infer schema\r
break;\r
case MappingType.Hidden:\r
// To generate parent key\r
- col.DataType = typeof (int);\r
+ col.DataType = optColType;\r
table.ReferenceKey = col;\r
break;\r
}\r
\r
foreach (XmlAttribute attr in el.Attributes) {\r
if (attr.NamespaceURI == XmlConstants.XmlnsNS \r
-#if NET_2_0\r
|| attr.NamespaceURI == XmlConstants.XmlNS\r
-#endif\r
)\r
continue;\r
if (ignoredNamespaces != null && ignoredNamespaces.Contains (attr.NamespaceURI))\r
{\r
foreach (XmlAttribute attr in top.Attributes) {\r
if (attr.NamespaceURI == XmlConstants.XmlnsNS\r
-#if NET_2_0\r
|| attr.NamespaceURI == XmlConstants.XmlNS\r
-#endif\r
)\r
continue;\r
if (ignoredNamespaces != null &&\r
// Returns if it "might" be a column element (this method is\r
// called per child element, thus it might still consist of\r
// table, since it might be repeated).\r
+ /*\r
private bool IsPossibleColumnElement (XmlElement el)\r
{\r
foreach (XmlAttribute attr in el.Attributes) {\r
if (attr.NamespaceURI == XmlConstants.XmlnsNS\r
-#if NET_2_0\r
|| attr.NamespaceURI == XmlConstants.XmlNS\r
-#endif\r
)\r
continue;\r
return false;\r
return false;\r
return true;\r
}\r
+ */\r
}\r
}\r
\r