// Get the row-elem associatd w/ the region node is in. // If node is in a region not mapped (like document element node) the function returns false and sets elem to null) // This function does not work if the region is not associated w/ a DataRow (it uses DataRow association to know what is the row element associated w/ the region) internal bool GetRegion(XmlNode node, out XmlBoundElement rowElem) { while (node != null) { XmlBoundElement be = node as XmlBoundElement; // Break if found a region if (be != null && GetRowFromElement(be) != null) { rowElem = be; return(true); } if (node.NodeType == XmlNodeType.Attribute) { node = ((XmlAttribute)node).OwnerElement; } else { node = node.ParentNode; } } rowElem = null; return(false); }
internal DataColumn GetColumnSchemaForNode(XmlBoundElement rowElem, XmlNode node) { object identity = GetIdentity(rowElem.LocalName, rowElem.NamespaceURI); object obj2 = GetIdentity(node.LocalName, node.NamespaceURI); Hashtable hashtable = (Hashtable)this.columnSchemaMap[identity]; if (hashtable != null) { DataColumn column = (DataColumn)hashtable[obj2]; if (column == null) { return(null); } MappingType columnMapping = column.ColumnMapping; if ((node.NodeType == XmlNodeType.Attribute) && (columnMapping == MappingType.Attribute)) { return(column); } if ((node.NodeType == XmlNodeType.Element) && (columnMapping == MappingType.Element)) { return(column); } } return(null); }
internal DataColumn GetColumnSchemaForNode(XmlBoundElement rowElem, XmlNode node) { // Debug.Assert(rowElem != null); // The caller must make sure that node is not a row-element Debug.Assert((node is XmlBoundElement) ? ((XmlBoundElement)node).Row == null : true); object tid = GetIdentity(rowElem.LocalName, rowElem.NamespaceURI); object cid = GetIdentity(node.LocalName, node.NamespaceURI); Hashtable columns = (Hashtable)columnSchemaMap[tid]; if (columns != null) { DataColumn col = (DataColumn)(columns[cid]); if (col == null) { return(null); } MappingType mt = col.ColumnMapping; if (node.NodeType == XmlNodeType.Attribute && mt == MappingType.Attribute) { return(col); } if (node.NodeType == XmlNodeType.Element && mt == MappingType.Element) { return(col); } // node's (localName, ns) matches a column, but the MappingType is different (i.e. node is elem, MT is attr) return(null); } return(null); }
internal DataTable SearchMatchingTableSchema(XmlBoundElement rowElem, XmlBoundElement elem) { DataTable table = this.SearchMatchingTableSchema(elem.LocalName, elem.NamespaceURI); if (table != null) { if (rowElem == null) { return(table); } if (this.GetColumnSchemaForNode(rowElem, elem) == null) { return(table); } foreach (XmlAttribute attribute in elem.Attributes) { if (attribute.NamespaceURI != "http://www.w3.org/2000/xmlns/") { return(table); } } for (XmlNode node = elem.FirstChild; node != null; node = node.NextSibling) { if (node.NodeType == XmlNodeType.Element) { return(table); } } } return(null); }
private void AssertValid() { if (this.column != null) { XmlBoundElement node = this.node as XmlBoundElement; DataRow row = node.Row; ElementState elementState = node.ElementState; DataRowState rowState = row.RowState; } }
internal DataTable GetTableSchemaForElement(XmlElement elem) { XmlBoundElement be = elem as XmlBoundElement; if (be == null) { return(null); } return(this.GetTableSchemaForElement(be)); }
internal DataTable GetTableSchemaForElement(XmlBoundElement be) { DataRow row = be.Row; if (row != null) { return(row.Table); } return(null); }
internal DataRow GetRowFromElement(XmlElement e) { XmlBoundElement element = e as XmlBoundElement; if (element != null) { return(element.Row); } return(null); }
// ATTENTION: GetRowFromElement( XmlElement ) and GetRowFromElement( XmlBoundElement ) should have the same functionality and side effects. // See this code fragment for why: // XmlBoundElement be = ...; // XmlElement e = be; // GetRowFromElement( be ); // Calls GetRowFromElement( XmlBoundElement ) // GetRowFromElement( e ); // Calls GetRowFromElement( XmlElement ), in spite of e beeing an instance of XmlBoundElement internal DataRow GetRowFromElement(XmlElement e) { XmlBoundElement be = e as XmlBoundElement; if (be != null) { return(be.Row); } return(null); }
private XPathNodePointer(DataDocumentXPathNavigator owner, XmlDataDocument doc, XmlNode node, DataColumn c, bool bOnValue, XmlBoundElement parentOfNS) { this._owner = new WeakReference(owner); this._doc = doc; this._node = node; this._column = c; this._fOnValue = bOnValue; this._parentOfNS = parentOfNS; this._doc.AddPointer(this); this._bNeedFoliate = false; }
internal DataTable GetTableSchemaForElement(XmlElement elem) { //TODO: Create an overridable that takes an XmlBoundElement. XmlBoundElement be = elem as XmlBoundElement; if (be == null) { return(null); } return(GetTableSchemaForElement(be)); }
internal DataTable GetTableSchemaForElement(XmlBoundElement be) { // if bound to a row, must be a table. DataRow row = be.Row; if (row != null) { return(row.Table); } return(null); }
// SearchMatchingTableSchema function works only when the elem has not been bound to a DataRow. If you want to get the table associated w/ an element after // it has been associated w/ a DataRow use GetTableSchemaForElement function. // rowElem is the parent region rowElem or null if there is no parent region (in case elem is a row elem, then rowElem will be the parent region; if elem is not // mapped to a DataRow, then rowElem is the region elem is part of) // // Those are the rules for determing if elem is a row element: // 1. node is an element (already meet, since elem is of type XmlElement) // 2. If the node is already associated w/ a DataRow, then the node is a row element - not applicable, b/c this function is intended to be called on a // to find out if the node s/b associated w/ a DataRow (see XmlDataDocument.LoadRows) // 3. If the node localName/ns matches a DataTable then // 3.1 Take the parent region DataTable (in our case rowElem.Row.DataTable) // 3.2 If no parent region, then the node is associated w/ a DataTable // 3.3 If there is a parent region // 3.3.1 If the node has no elem children and no attr other than namespace declaration, and the node can match // a column from the parent region table, then the node is NOT associated w/ a DataTable (it is a potential DataColumn in the parent region) // 3.3.2 Else the node is a row-element (and associated w/ a DataTable / DataRow ) // internal DataTable SearchMatchingTableSchema( XmlBoundElement rowElem, XmlBoundElement elem ) { Debug.Assert( elem != null ); DataTable t = SearchMatchingTableSchema( elem.LocalName, elem.NamespaceURI ); if ( t == null ) return null; if ( rowElem == null ) return t; // Currently we expect we map things from top of the tree to the bottom Debug.Assert( rowElem.Row != null ); DataColumn col = GetColumnSchemaForNode( rowElem, elem ); if ( col == null ) return t; foreach ( XmlAttribute a in elem.Attributes ) { #if DEBUG // Some sanity check to catch errors like namespace attributes have the right localName/namespace value, but a wrong atomized namespace value if ( a.LocalName == "xmlns" ) { Debug.Assert( a.Prefix != null && a.Prefix.Length == 0 ); Debug.Assert( (object)a.NamespaceURI == (object)strReservedXmlns ); } if ( a.Prefix == "xmlns" ) { Debug.Assert( (object)a.NamespaceURI == (object)strReservedXmlns ); } if ( a.NamespaceURI == strReservedXmlns ) Debug.Assert( (object)a.NamespaceURI == (object)strReservedXmlns ); #endif // No namespace attribute found, so elem cannot be a potential DataColumn, therefore is a row-elem if ( (object)(a.NamespaceURI) != (object)strReservedXmlns ) return t; } for ( XmlNode n = elem.FirstChild; n != null; n = n.NextSibling ) { if ( n.NodeType == XmlNodeType.Element ) { // elem has an element child, so elem cannot be a potential DataColumn, therefore is a row-elem return t; } } // Node is a potential DataColumn in rowElem region return null; }
internal bool GetRegion(XmlNode node, out XmlBoundElement rowElem) { while (node != null) { XmlBoundElement be = node as XmlBoundElement; if ((be != null) && (this.GetRowFromElement(be) != null)) { rowElem = be; return true; } if (node.NodeType == XmlNodeType.Attribute) { node = ((XmlAttribute) node).OwnerElement; } else { node = node.ParentNode; } } rowElem = null; return false; }
private void AssertValid() { // This pointer must be int the document list if (_column != null) { // We must be on a de-foliated region XmlBoundElement rowElem = _node as XmlBoundElement; Debug.Assert(rowElem != null); DataRow row = rowElem.Row; Debug.Assert(row != null); ElementState state = rowElem.ElementState; Debug.Assert(state == ElementState.Defoliated, "Region is accessed using column, but it's state is FOLIATED"); // We cannot be on a column for which the value is DBNull DataRowVersion rowVersion = (row.RowState == DataRowState.Detached) ? DataRowVersion.Proposed : DataRowVersion.Current; Debug.Assert(!Convert.IsDBNull(row[_column, rowVersion])); // If we are on the Text column, we should always have fOnValue == true Debug.Assert((_column.ColumnMapping == MappingType.SimpleContent) ? (_fOnValue == true) : true); } }
internal DataColumn GetColumnSchemaForNode(XmlBoundElement rowElem, XmlNode node) { object identity = GetIdentity(rowElem.LocalName, rowElem.NamespaceURI); object obj2 = GetIdentity(node.LocalName, node.NamespaceURI); Hashtable hashtable = (Hashtable) this.columnSchemaMap[identity]; if (hashtable != null) { DataColumn column = (DataColumn) hashtable[obj2]; if (column == null) { return null; } MappingType columnMapping = column.ColumnMapping; if ((node.NodeType == XmlNodeType.Attribute) && (columnMapping == MappingType.Attribute)) { return column; } if ((node.NodeType == XmlNodeType.Element) && (columnMapping == MappingType.Element)) { return column; } } return null; }
internal DataRow?GetRowFromElement(XmlBoundElement be) => be.Row;
internal DataTable?GetTableSchemaForElement(XmlBoundElement be) => be.Row?.Table;
private bool IsFoliated(XmlBoundElement be) { return be.IsFoliated; }
internal bool OnRowElement() { XmlBoundElement currentNode = this.CurrentNode as XmlBoundElement; return((currentNode != null) && (currentNode.Row != null)); }
private void UpdateAllColumns(DataRow row, XmlBoundElement rowElement) { foreach (DataColumn c in row.Table.Columns) { OnColumnValueChanged(row, c, rowElement); } }
internal bool IsRegionRadical(XmlBoundElement rowElem) { if (rowElem.ElementState != ElementState.Defoliated) { DataColumnCollection columns = this.GetTableSchemaForElement(rowElem).Columns; int iColumn = 0; int count = rowElem.Attributes.Count; for (int i = 0; i < count; i++) { XmlAttribute node = rowElem.Attributes[i]; if (!node.Specified) { return(false); } DataColumn columnSchemaForNode = this.GetColumnSchemaForNode(rowElem, node); if (columnSchemaForNode == null) { return(false); } if (!this.IsNextColumn(columns, ref iColumn, columnSchemaForNode)) { return(false); } XmlNode node3 = node.FirstChild; if (((node3 == null) || (node3.NodeType != XmlNodeType.Text)) || (node3.NextSibling != null)) { return(false); } } iColumn = 0; XmlNode firstChild = rowElem.FirstChild; while (firstChild != null) { if (firstChild.NodeType != XmlNodeType.Element) { return(false); } XmlElement e = firstChild as XmlElement; if (this.GetRowFromElement(e) != null) { break; } DataColumn col = this.GetColumnSchemaForNode(rowElem, e); if (col == null) { return(false); } if (!this.IsNextColumn(columns, ref iColumn, col)) { return(false); } if (e.HasAttributes) { return(false); } XmlNode node2 = e.FirstChild; if (((node2 == null) || (node2.NodeType != XmlNodeType.Text)) || (node2.NextSibling != null)) { return(false); } firstChild = firstChild.NextSibling; } while (firstChild != null) { if (firstChild.NodeType != XmlNodeType.Element) { return(false); } if (this.GetRowFromElement((XmlElement)firstChild) == null) { return(false); } firstChild = firstChild.NextSibling; } } return(true); }
// Disconnect the DataRow associated w/ the rowElem region private void EnsureDisconnectedDataRow(XmlBoundElement rowElem) { Debug.Assert(rowElem.Row != null); DataRow row = rowElem.Row; DataRowState rowState = row.RowState; switch (rowState) { case DataRowState.Detached: #if DEBUG try { Debug.Assert(row.Table.DataSet.EnforceConstraints == false); #endif SetNestedParentRegion(rowElem); #if DEBUG } catch { // We should not get any exceptions here Debug.Assert(false); throw; } #endif break; case DataRowState.Deleted: // Nothing to do: moving a region associated w/ a deleted row to another disconnected tree is a NO-OP. break; case DataRowState.Unchanged: case DataRowState.Modified: EnsureFoliation(rowElem, ElementState.WeakFoliation); row.Delete(); break; case DataRowState.Added: EnsureFoliation(rowElem, ElementState.WeakFoliation); row.Delete(); SetNestedParentRegion(rowElem); break; default: // Handle your case above Debug.Assert(false); break; } Debug.Assert(!IsRowLive(rowElem.Row)); }
internal bool MoveToNamespace(string name) { //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToNamespace(name)"); _parentOfNS = this._node as XmlBoundElement; //only need to check with _node, even if _column is not null and its mapping type is element, it can't have attributes if ( _parentOfNS == null ) return false; string attrName = name; if ( attrName == "xmlns" ) attrName = "xmlns:xmlns"; if ( attrName != null && attrName.Length == 0 ) attrName = "xmlns"; RealFoliate(); XmlNode node = this._node; XmlNodeType nt = node.NodeType; XmlAttribute attr = null; XmlBoundElement be = null; while ( node != null ) { //check current element node be = node as XmlBoundElement; if ( be != null ) { if ( be.IsFoliated ) { attr = be.GetAttributeNode ( name, s_strReservedXmlns ); if ( attr != null ) { MoveTo( attr ); return true; } } else {//defoliated so that we need to search through its column DataRow curRow = be.Row; if ( curRow == null ) return false; //going through its attribute columns DataColumn curCol = PreviousColumn( curRow, null, true ); while ( curCol != null ) { if ( curCol.Namespace == s_strReservedXmlns && curCol.ColumnName == name ) { MoveTo( be, curCol, false ); return true; } curCol = PreviousColumn( curRow, curCol, true ); } } } //didn't find it, try the next element anccester. do { node = node.ParentNode; } while ( node != null && node.NodeType != XmlNodeType.Element ); } //nothing happens, the name doesn't exist as a namespace node. _parentOfNS = null; return false; }
// SearchMatchingTableSchema function works only when the elem has not been bound to a DataRow. If you want to get the table associated w/ an element after // it has been associated w/ a DataRow use GetTableSchemaForElement function. // rowElem is the parent region rowElem or null if there is no parent region (in case elem is a row elem, then rowElem will be the parent region; if elem is not // mapped to a DataRow, then rowElem is the region elem is part of) // // Those are the rules for determing if elem is a row element: // 1. node is an element (already meet, since elem is of type XmlElement) // 2. If the node is already associated w/ a DataRow, then the node is a row element - not applicable, b/c this function is intended to be called on a // to find out if the node s/b associated w/ a DataRow (see XmlDataDocument.LoadRows) // 3. If the node localName/ns matches a DataTable then // 3.1 Take the parent region DataTable (in our case rowElem.Row.DataTable) // 3.2 If no parent region, then the node is associated w/ a DataTable // 3.3 If there is a parent region // 3.3.1 If the node has no elem children and no attr other than namespace declaration, and the node can match // a column from the parent region table, then the node is NOT associated w/ a DataTable (it is a potential DataColumn in the parent region) // 3.3.2 Else the node is a row-element (and associated w/ a DataTable / DataRow ) // internal DataTable SearchMatchingTableSchema(XmlBoundElement rowElem, XmlBoundElement elem) { Debug.Assert(elem != null); DataTable t = SearchMatchingTableSchema(elem.LocalName, elem.NamespaceURI); if (t == null) { return(null); } if (rowElem == null) { return(t); } // Currently we expect we map things from top of the tree to the bottom Debug.Assert(rowElem.Row != null); DataColumn col = GetColumnSchemaForNode(rowElem, elem); if (col == null) { return(t); } foreach (XmlAttribute a in elem.Attributes) { #if DEBUG // Some sanity check to catch errors like namespace attributes have the right localName/namespace value, but a wrong atomized namespace value if (a.LocalName == "xmlns") { Debug.Assert(a.Prefix != null && a.Prefix.Length == 0); Debug.Assert((object)a.NamespaceURI == (object)strReservedXmlns); } if (a.Prefix == "xmlns") { Debug.Assert((object)a.NamespaceURI == (object)strReservedXmlns); } if (a.NamespaceURI == strReservedXmlns) { Debug.Assert((object)a.NamespaceURI == (object)strReservedXmlns); } #endif // No namespace attribute found, so elem cannot be a potential DataColumn, therefore is a row-elem if ((object)(a.NamespaceURI) != (object)strReservedXmlns) { return(t); } } for (XmlNode n = elem.FirstChild; n != null; n = n.NextSibling) { if (n.NodeType == XmlNodeType.Element) { // elem has an element child, so elem cannot be a potential DataColumn, therefore is a row-elem return(t); } } // Node is a potential DataColumn in rowElem region return(null); }
internal RegionIterator(XmlBoundElement rowElement) : base(((XmlDataDocument)rowElement.OwnerDocument).Mapper) { this.rowElement = rowElement; this.currentNode = rowElement; }
// A non-row-elem was inserted into disconnected tree (fragment) from oldParent==null state (i.e. was disconnected) private void OnNonRowElementInsertedInFragment(XmlNode node, XmlBoundElement rowElement, ArrayList rowElemList) { // non-row-elem is beeing inserted DataRow row = rowElement.Row; // Region should already have an associated data row (otherwise how was the original row-elem inserted ?) Debug.Assert(row != null); // Since oldParent == null, the only 2 row states should have been Detached or Deleted Debug.Assert(row.RowState == DataRowState.Detached || row.RowState == DataRowState.Deleted); if (row.RowState == DataRowState.Detached) SynchronizeRowFromRowElementEx(rowElement, rowElemList); // Nothing to do if the row is deleted (there is no sync-ing from XML to ROM for deleted rows) }
// A non-row-elem was inserted into the connected tree (connected) from oldParent==null state private void OnNonRowElementInsertedInTree(XmlNode node, XmlBoundElement rowElement, ArrayList rowElemList) { // non-row-elem is beeing inserted DataRow row = rowElement.Row; // Region should already have an associated data row (otherwise how was the original row-elem inserted ?) Debug.Assert(row != null); SynchronizeRowFromRowElement(rowElement); if (rowElemList != null) { TreeIterator iter = new TreeIterator(node); for (bool fMore = iter.NextRowElement(); fMore; fMore = iter.NextRightRowElement()) rowElemList.Add(iter.CurrentNode); } }
private XPathNodePointer( DataDocumentXPathNavigator owner, XmlDataDocument doc, XmlNode node, DataColumn c, bool bOnValue, XmlBoundElement parentOfNS ) { Debug.Assert( owner != null ); this._owner = new WeakReference( owner ); this._doc = doc; this._node = node; this._column = c; this._fOnValue = bOnValue; this._parentOfNS = parentOfNS; // Add this pointer to the document so it will be updated each time region changes it's foliation state. this._doc.AddPointer( (IXmlDataVirtualNode)this ); _bNeedFoliate = false; AssertValid(); }
//Caller( DataDocumentXPathNavigator will make sure that the node is at the right position for this call ) internal bool MoveToFirstNamespace(XPathNamespaceScope namespaceScope) { //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToFirstNamespace(namespaceScope)"); RealFoliate(); _parentOfNS = this._node as XmlBoundElement; //only need to check with _node, even if _column is not null and its mapping type is element, it can't have attributes if ( _parentOfNS == null ) return false; XmlNode node = this._node; XmlBoundElement be = null; while ( node != null ) { be = node as XmlBoundElement; if ( MoveToNextNamespace( be, null, null ) ) return true; //didn't find it if ( namespaceScope == XPathNamespaceScope.Local ) goto labelNoNS; //try the next element anccestor. do { node = node.ParentNode; } while ( node != null && node.NodeType != XmlNodeType.Element ); } if ( namespaceScope == XPathNamespaceScope.All ) { MoveTo( this._doc.attrXml, null, false ); return true; } labelNoNS: //didn't find one namespace node _parentOfNS = null; return false; }
//The function only helps to find out if there is a namespace declaration of given name is defined on the given node //It will not check the accestors of the given node. private string GetNamespace( XmlBoundElement be, string name ) { //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:GetNamespace(be,name)"); if ( be == null ) return null; XmlAttribute attr = null; if ( be.IsFoliated ) { attr = be.GetAttributeNode ( name, s_strReservedXmlns ); if ( attr != null ) return attr.Value; else return null; } else { //defoliated so that we need to search through its column DataRow curRow = be.Row; if ( curRow == null ) return null; //going through its attribute columns DataColumn curCol = PreviousColumn( curRow, null, true ); while ( curCol != null ) { if ( curCol.Namespace == s_strReservedXmlns ) { // DataRowVersion rowVersion = ( curRow.RowState == DataRowState.Detached ) ? DataRowVersion.Proposed : DataRowVersion.Current; return curCol.ConvertObjectToXml( curRow[curCol,rowVersion] ); } curCol = PreviousColumn( curRow, curCol, true ); } return null; } }
// A row-elem was inserted into the connected tree (connected) from oldParent==null state private void OnRowElementInsertedInTree(XmlBoundElement rowElem, ArrayList rowElemList) { Debug.Assert(rowElem.Row != null); DataRow row = rowElem.Row; DataRowState rowState = row.RowState; switch (rowState) { case DataRowState.Detached: #if DEBUG try { Debug.Assert(row.Table.DataSet.EnforceConstraints == false); #endif row.Table.Rows.Add(row); SetNestedParentRegion(rowElem); #if DEBUG } catch { // We should not get any exceptions here Debug.Assert(false); throw; } #endif // Add all sub-regions to the list if the caller needs this if (rowElemList != null) { RegionIterator iter = new RegionIterator(rowElem); for (bool fMore = iter.NextRowElement(); fMore; fMore = iter.NextRightRowElement()) rowElemList.Add(iter.CurrentNode); } break; case DataRowState.Deleted: #if DEBUG try { Debug.Assert(row.Table.DataSet.EnforceConstraints == false); #endif // Change the row status to be alive (unchanged) row.RejectChanges(); // Set ROM from XML SynchronizeRowFromRowElement(rowElem, rowElemList); // Set nested parent data row according to where is the row positioned in the tree SetNestedParentRegion(rowElem); #if DEBUG } catch { // We should not get any exceptions here Debug.Assert(false); throw; } #endif break; default: // Handle your case above Debug.Assert(false); break; } Debug.Assert(IsRowLive(rowElem.Row)); }
//the function will find the next namespace node on the given bound element starting with the given column or attribte // wether to use column or attribute depends on if the bound element is folicated or not. private bool MoveToNextNamespace( XmlBoundElement be, DataColumn col, XmlAttribute curAttr ) { //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:MoveToNextNamespace(be,col,curAttr)"); if ( be != null ) { if ( be.IsFoliated ) { XmlAttributeCollection attrs = be.Attributes; XmlAttribute attr = null; bool bFound = false; if ( curAttr == null ) bFound = true; //the first namespace will be the one #if DEBUG if ( curAttr != null ) Debug.Assert( curAttr.NamespaceURI == s_strReservedXmlns ); #endif Debug.Assert( attrs!=null ); int attrInd = attrs.Count; while ( attrInd > 0 ) { attrInd--; attr = attrs[attrInd]; if ( bFound && attr.NamespaceURI == s_strReservedXmlns && !DuplicateNS( be, attr.LocalName ) ) { MoveTo(attr); return true; } if ( attr == curAttr ) bFound = true; } } else {//defoliated so that we need to search through its column DataRow curRow = be.Row; if ( curRow == null ) return false; //going through its attribute columns DataColumn curCol = PreviousColumn( curRow, col, true ); while ( curCol != null ) { if ( curCol.Namespace == s_strReservedXmlns && !DuplicateNS( be, curCol.ColumnName ) ) { MoveTo( be, curCol, false ); return true; } curCol = PreviousColumn( curRow, curCol, true ); } } } return false; }
internal DataColumn GetColumnSchemaForNode( XmlBoundElement rowElem, XmlNode node ) { // Debug.Assert( rowElem != null ); // The caller must make sure that node is not a row-element Debug.Assert( (node is XmlBoundElement) ? ((XmlBoundElement)node).Row == null : true ); object tid = GetIdentity( rowElem.LocalName, rowElem.NamespaceURI ); object cid = GetIdentity( node.LocalName, node.NamespaceURI ); Hashtable columns = (Hashtable) columnSchemaMap[ tid ]; if ( columns != null ) { DataColumn col = (DataColumn)(columns[ cid ]); if ( col == null ) return null; MappingType mt = col.ColumnMapping; if ( node.NodeType == XmlNodeType.Attribute && mt == MappingType.Attribute ) return col; if ( node.NodeType == XmlNodeType.Element && mt == MappingType.Element ) return col; // node's (localName, ns) matches a column, but the MappingType is different (i.e. node is elem, MT is attr) return null; } return null; }
//endElem is on the path from startElem to root is enforced by the caller private bool DuplicateNS( XmlBoundElement endElem, string lname) { //Debug.WriteLineIf( XmlTrace.traceXPathNodePointerFunctions.Enabled, "XPathNodePointer:DuplicateNS(endElem, lname)"); if ( this._parentOfNS == null || endElem == null ) return false; XmlBoundElement be = this._parentOfNS; XmlNode node = null; while ( be != null && be != endElem ) { if ( GetNamespace( be, lname ) != null ) return true; node = (XmlNode)be; do { node = node.ParentNode; } while ( node != null && node.NodeType != XmlNodeType.Element ); be = node as XmlBoundElement; } return false; }
internal DataRow GetRowFromElement( XmlBoundElement be ) { return be.Row; }
private void SetNestedParentRegion(XmlBoundElement childRowElem) { Debug.Assert(childRowElem.Row != null); XmlBoundElement parentRowElem; _mapper.GetRegion(childRowElem.ParentNode, out parentRowElem); SetNestedParentRegion(childRowElem, parentRowElem); }
internal bool IsRegionRadical( XmlBoundElement rowElem ) { // You must pass a row element (which s/b associated w/ a DataRow) Debug.Assert( rowElem.Row != null ); if ( rowElem.ElementState == ElementState.Defoliated ) return true; DataTable table = GetTableSchemaForElement( rowElem ); DataColumnCollection columns = table.Columns; int iColumn = 0; // check column attributes... int cAttrs = rowElem.Attributes.Count; for ( int iAttr = 0; iAttr < cAttrs; iAttr++ ) { XmlAttribute attr = rowElem.Attributes[iAttr]; // only specified attributes are radical if ( !attr.Specified ) return false; // only mapped attrs are valid DataColumn schema = GetColumnSchemaForNode( rowElem, attr ); if ( schema == null ) { //Console.WriteLine("Region has unmapped attribute"); return false; } // check to see if column is in order if ( !IsNextColumn( columns, ref iColumn, schema ) ) { //Console.WriteLine("Region has attribute columns out of order or duplicate"); return false; } // must have exactly one text node (XmlNodeType.Text) child // XmlNode fc = attr.FirstChild; if ( fc == null || fc.NodeType != XmlNodeType.Text || fc.NextSibling != null ) { //Console.WriteLine("column element has other than a single child text node"); return false; } } // check column elements iColumn = 0; XmlNode n = rowElem.FirstChild; for ( ; n != null; n = n.NextSibling ) { // only elements can exist in radically structured data if ( n.NodeType != XmlNodeType.Element ) { //Console.WriteLine("Region has non-element child"); return false; } XmlElement e = n as XmlElement; // only checking for column mappings in this loop if ( GetRowFromElement( e ) != null ) break; // element's must have schema to be radically structured DataColumn schema = GetColumnSchemaForNode( rowElem, e ); if ( schema == null ) { //Console.WriteLine("Region has unmapped child element"); return false; } // check to see if column is in order if ( !IsNextColumn( columns, ref iColumn, schema ) ) { //Console.WriteLine("Region has element columns out of order or duplicate"); return false; } // must have no attributes if ( e.HasAttributes ) return false; // must have exactly one text node child XmlNode fc = e.FirstChild; if ( fc == null || fc.NodeType != XmlNodeType.Text || fc.NextSibling != null ) { //Console.WriteLine("column element has other than a single child text node"); return false; } } // check for remaining sub-regions for (; n != null; n = n.NextSibling ) { // only elements can exist in radically structured data if ( n.NodeType != XmlNodeType.Element ) { //Console.WriteLine("Region has non-element child"); return false; } // element's must be regions in order to be radially structured DataRow row = GetRowFromElement( (XmlElement)n ); if ( row == null ) { //Console.WriteLine("Region has unmapped element"); return false; } } return true; }
internal DataRow GetRowFromElement(XmlBoundElement be) { return(be.Row); }
private void SetNestedParentRegion(XmlBoundElement childRowElem, XmlBoundElement parentRowElem) { DataRow childRow = childRowElem.Row; if (parentRowElem == null) { SetNestedParentRow(childRow, null); return; } DataRow parentRow = parentRowElem.Row; Debug.Assert(parentRow != null); // We should set it only if there is a nested relationship between this child and parent regions DataRelation[] relations = childRow.Table.NestedParentRelations; if (relations.Length != 0 && relations[0].ParentTable == parentRow.Table) // just backward compatable { SetNestedParentRow(childRow, parentRow); } else { SetNestedParentRow(childRow, null); } }
internal bool IsRegionRadical(XmlBoundElement rowElem) { // You must pass a row element (which s/b associated w/ a DataRow) Debug.Assert(rowElem.Row != null); if (rowElem.ElementState == ElementState.Defoliated) { return(true); } DataTable table = GetTableSchemaForElement(rowElem); DataColumnCollection columns = table.Columns; int iColumn = 0; // check column attributes... int cAttrs = rowElem.Attributes.Count; for (int iAttr = 0; iAttr < cAttrs; iAttr++) { XmlAttribute attr = rowElem.Attributes[iAttr]; // only specified attributes are radical if (!attr.Specified) { return(false); } // only mapped attrs are valid DataColumn schema = GetColumnSchemaForNode(rowElem, attr); if (schema == null) { //Console.WriteLine("Region has unmapped attribute"); return(false); } // check to see if column is in order if (!IsNextColumn(columns, ref iColumn, schema)) { //Console.WriteLine("Region has attribute columns out of order or duplicate"); return(false); } // must have exactly one text node (XmlNodeType.Text) child // XmlNode fc = attr.FirstChild; if (fc == null || fc.NodeType != XmlNodeType.Text || fc.NextSibling != null) { //Console.WriteLine("column element has other than a single child text node"); return(false); } } // check column elements iColumn = 0; XmlNode n = rowElem.FirstChild; for ( ; n != null; n = n.NextSibling) { // only elements can exist in radically structured data if (n.NodeType != XmlNodeType.Element) { //Console.WriteLine("Region has non-element child"); return(false); } XmlElement e = n as XmlElement; // only checking for column mappings in this loop if (GetRowFromElement(e) != null) { break; } // element's must have schema to be radically structured DataColumn schema = GetColumnSchemaForNode(rowElem, e); if (schema == null) { //Console.WriteLine("Region has unmapped child element"); return(false); } // check to see if column is in order if (!IsNextColumn(columns, ref iColumn, schema)) { //Console.WriteLine("Region has element columns out of order or duplicate"); return(false); } // must have no attributes if (e.HasAttributes) { return(false); } // must have exactly one text node child XmlNode fc = e.FirstChild; if (fc == null || fc.NodeType != XmlNodeType.Text || fc.NextSibling != null) { //Console.WriteLine("column element has other than a single child text node"); return(false); } } // check for remaining sub-regions for (; n != null; n = n.NextSibling) { // only elements can exist in radically structured data if (n.NodeType != XmlNodeType.Element) { //Console.WriteLine("Region has non-element child"); return(false); } // element's must be regions in order to be radially structured DataRow row = GetRowFromElement((XmlElement)n); if (row == null) { //Console.WriteLine("Region has unmapped element"); return(false); } } return(true); }
private void DefoliateRegion(XmlBoundElement rowElem) { // You must pass a row element (which s/b associated w/ a DataRow) Debug.Assert(rowElem.Row != null); if (!_optimizeStorage) return; if (rowElem.ElementState != ElementState.WeakFoliation) return; if (!_mapper.IsRegionRadical(rowElem)) { return; } bool saveIgnore = IgnoreXmlEvents; IgnoreXmlEvents = true; rowElem.ElementState = ElementState.Defoliating; try { // drop all attributes rowElem.RemoveAllAttributes(); XmlNode node = rowElem.FirstChild; while (node != null) { XmlNode next = node.NextSibling; XmlBoundElement be = node as XmlBoundElement; if (be != null && be.Row != null) break; // The node must be mapped to a column (since the region is radically structured) Debug.Assert(_mapper.GetColumnSchemaForNode(rowElem, node) != null); rowElem.RemoveChild(node); node = next; } #if DEBUG // All subsequent siblings must be sub-regions for (; node != null; node = node.NextSibling) { Debug.Assert((node is XmlBoundElement) && (((XmlBoundElement)node).Row != null)); } #endif rowElem.ElementState = ElementState.Defoliated; } finally { IgnoreXmlEvents = saveIgnore; } }
internal RegionIterator(XmlBoundElement rowElement) : base(((XmlDataDocument)(rowElement.OwnerDocument)).Mapper) { Debug.Assert(rowElement != null && rowElement.Row != null); _rowElement = rowElement; _currentNode = rowElement; }
private XmlElement EnsureDocumentElement() { XmlElement docelem = DocumentElement; if (docelem == null) { string docElemName = XmlConvert.EncodeLocalName(DataSet.DataSetName); if (docElemName == null || docElemName.Length == 0) docElemName = "Xml"; string ns = DataSet.Namespace; if (ns == null) ns = string.Empty; docelem = new XmlBoundElement(string.Empty, docElemName, ns, this); AppendChild(docelem); } return docelem; }
// This function accepts node params that are not row-elements. In this case, calling this function is a no-op internal void Foliate(XmlBoundElement node, ElementState newState) { Debug.Assert(newState == ElementState.WeakFoliation || newState == ElementState.StrongFoliation); #if DEBUG // If we want to strong foliate one of the non-row-elem in a region, then the region MUST be strong-foliated (or there must be no region) // Do this only when we are not loading if (IsFoliationEnabled) { if (newState == ElementState.StrongFoliation && node.Row == null) { XmlBoundElement rowElem; ElementState rowElemState = ElementState.None; if (_mapper.GetRegion(node, out rowElem)) { rowElemState = rowElem.ElementState; Debug.Assert(rowElemState == ElementState.StrongFoliation || rowElemState == ElementState.WeakFoliation); } // Add a no-op, so we can still debug in the assert fails #pragma warning disable 1717 // assignment to self rowElemState = rowElemState; #pragma warning restore 1717 } } #endif if (IsFoliationEnabled) { if (node.ElementState == ElementState.Defoliated) { ForceFoliation(node, newState); } else if (node.ElementState == ElementState.WeakFoliation && newState == ElementState.StrongFoliation) { // Node must be a row-elem Debug.Assert(node.Row != null); node.ElementState = newState; } } }
internal DataTable GetTableSchemaForElement( XmlBoundElement be ) { // if bound to a row, must be a table. DataRow row = be.Row; if ( row != null ) return row.Table; return null; }
private void EnsureFoliation(XmlBoundElement rowElem, ElementState foliation) { if (rowElem.IsFoliated) //perf reason, avoid unecessary lock. return; ForceFoliation(rowElem, foliation); }
// Get the row-elem associatd w/ the region node is in. // If node is in a region not mapped (like document element node) the function returns false and sets elem to null) // This function does not work if the region is not associated w/ a DataRow (it uses DataRow association to know what is the row element associated w/ the region) internal bool GetRegion( XmlNode node, out XmlBoundElement rowElem ) { while ( node != null ) { XmlBoundElement be = node as XmlBoundElement; // Break if found a region if ( be != null && GetRowFromElement( be ) != null ) { rowElem = be; return true; } if ( node.NodeType == XmlNodeType.Attribute ) node = ((XmlAttribute)node).OwnerElement; else node = node.ParentNode; } rowElem = null; return false; }
private void ForceFoliation(XmlBoundElement node, ElementState newState) { lock (_foliationLock) { if (node.ElementState != ElementState.Defoliated) // The region was foliated by an other thread while this thread was locked return; // Node must be a row-elem associated w/ a non-deleted row Debug.Assert(node.Row != null); Debug.Assert(node.Row.RowState != DataRowState.Deleted); node.ElementState = ElementState.Foliating; bool saveIgnore = IgnoreXmlEvents; IgnoreXmlEvents = true; try { XmlNode priorNode = null; DataRow row = node.Row; // create new attrs & elements for row // For detached rows: we are in sync w/ temp values // For non-detached rows: we are in sync w/ the current values // For deleted rows: we never sync DataRowVersion rowVersion = (row.RowState == DataRowState.Detached) ? DataRowVersion.Proposed : DataRowVersion.Current; foreach (DataColumn col in row.Table.Columns) { if (!IsNotMapped(col)) { object value = row[col, rowVersion]; if (!Convert.IsDBNull(value)) { if (col.ColumnMapping == MappingType.Attribute) { node.SetAttribute(col.EncodedColumnName, col.Namespace, col.ConvertObjectToXml(value)); } else { XmlNode newNode = null; if (col.ColumnMapping == MappingType.Element) { newNode = new XmlBoundElement(string.Empty, col.EncodedColumnName, col.Namespace, this); newNode.AppendChild(CreateTextNode(col.ConvertObjectToXml(value))); if (priorNode != null) { node.InsertAfter(newNode, priorNode); } else if (node.FirstChild != null) { node.InsertBefore(newNode, node.FirstChild); } else { node.AppendChild(newNode); } priorNode = newNode; } else { Debug.Assert(col.ColumnMapping == MappingType.SimpleContent); newNode = CreateTextNode(col.ConvertObjectToXml(value)); if (node.FirstChild != null) node.InsertBefore(newNode, node.FirstChild); else node.AppendChild(newNode); if (priorNode == null) priorNode = newNode; } } } else { if (col.ColumnMapping == MappingType.SimpleContent) { XmlAttribute attr = CreateAttribute(XSI, Keywords.XSI_NIL, Keywords.XSINS); attr.Value = Keywords.TRUE; node.SetAttributeNode(attr); _bHasXSINIL = true; } } } } } finally { IgnoreXmlEvents = saveIgnore; node.ElementState = newState; } // update all live pointers OnFoliated(node); } }
//Determine best radical insert position for inserting column elements private XmlNode GetColumnInsertAfterLocation(DataRow row, DataColumn col, XmlBoundElement rowElement) { XmlNode prev = null; XmlNode node = null; // text only columns appear first if (IsTextOnly(col)) return null; // insert location must be after free text for (node = rowElement.FirstChild; node != null; prev = node, node = node.NextSibling) { if (!IsTextLikeNode(node)) break; } for (; node != null; prev = node, node = node.NextSibling) { // insert location must be before any non-element nodes if (node.NodeType != XmlNodeType.Element) break; XmlElement e = node as XmlElement; // insert location must be before any non-mapped elements or separate regions if (_mapper.GetRowFromElement(e) != null) break; object schema = _mapper.GetColumnSchemaForNode(rowElement, node); if (schema == null || !(schema is DataColumn)) break; // insert location must be before any columns logically after this column if (((DataColumn)schema).Ordinal > col.Ordinal) break; } return prev; }
// Returns true if the current node is on a row element (head of a region) internal bool OnRowElement() { XmlBoundElement be = CurrentNode as XmlBoundElement; return((be != null) && (be.Row != null)); }