//---------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
namespace System.Data.EntityModel.SchemaObjectModel
{
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Metadata.Edm;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Xml;
using System.Xml.Linq;
///
/// Summary description for SchemaElement.
///
[DebuggerDisplay("Name={Name}")]
internal abstract class SchemaElement
{
// see http://www.w3.org/TR/2006/REC-xml-names-20060816/
internal const string XmlNamespaceNamespace = "http://www.w3.org/2000/xmlns/";
#region Instance Fields
private SchemaElement _parentElement = null;
private Schema _schema = null;
private int _lineNumber = 0;
private int _linePosition = 0;
private string _name = null;
private DocumentationElement _documentation = null;
private List _otherContent;
#endregion
#region Static Fields
///
protected const int MaxValueVersionComponent = short.MaxValue;
#endregion
#region Public Properties
///
///
///
internal int LineNumber
{
get
{
return _lineNumber;
}
}
///
///
///
internal int LinePosition
{
get
{
return _linePosition;
}
}
///
///
///
public virtual string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
///
///
///
internal DocumentationElement Documentation
{
get
{
return _documentation;
}
set
{
_documentation = value;
}
}
///
///
///
internal SchemaElement ParentElement
{
get
{
return _parentElement;
}
private set
{
_parentElement = value;
}
}
///
///
///
internal Schema Schema
{
get
{
return _schema;
}
set
{
_schema = value;
}
}
///
///
///
public virtual string FQName
{
get
{
return Name;
}
}
///
///
///
public virtual string Identity
{
get
{
return Name;
}
}
public List OtherContent
{
get
{
if (_otherContent == null)
{
_otherContent = new List();
}
return _otherContent;
}
}
#endregion
#region Internal Methods
///
/// Validates this element and its children
///
internal virtual void Validate()
{
}
///
///
///
///
///
///
///
///
internal void AddError( ErrorCode errorCode, EdmSchemaErrorSeverity severity, int lineNumber, int linePosition, object message )
{
AddError(errorCode,severity,SchemaLocation,lineNumber,linePosition,message);
}
///
///
///
///
///
///
///
internal void AddError( ErrorCode errorCode, EdmSchemaErrorSeverity severity, XmlReader reader, object message )
{
int lineNumber;
int linePosition;
GetPositionInfo(reader, out lineNumber, out linePosition);
AddError(errorCode,severity,SchemaLocation,lineNumber,linePosition,message);
}
///
///
///
///
///
///
internal void AddError( ErrorCode errorCode, EdmSchemaErrorSeverity severity, object message )
{
AddError(errorCode,severity,SchemaLocation,LineNumber,LinePosition,message);
}
///
///
///
///
///
///
///
internal void AddError( ErrorCode errorCode, EdmSchemaErrorSeverity severity, SchemaElement element, object message )
{
AddError(errorCode,severity,element.Schema.Location,element.LineNumber,element.LinePosition,message);
}
///
///
///
///
///
internal void Parse(XmlReader reader)
{
GetPositionInfo(reader);
bool hasEndElement = !reader.IsEmptyElement;
Debug.Assert(reader.NodeType == XmlNodeType.Element);
for ( bool more = reader.MoveToFirstAttribute(); more; more = reader.MoveToNextAttribute() )
{
ParseAttribute(reader);
}
HandleAttributesComplete();
bool done = !hasEndElement;
bool skipToNextElement = false;
while ( !done )
{
if ( skipToNextElement )
{
skipToNextElement = false;
reader.Skip();
if ( reader.EOF )
break;
}
else
{
if ( !reader.Read() )
break;
}
switch ( reader.NodeType )
{
case XmlNodeType.Element:
skipToNextElement = ParseElement(reader);
break;
case XmlNodeType.EndElement:
{
done = true;
break;
}
case XmlNodeType.CDATA:
case XmlNodeType.Text:
case XmlNodeType.SignificantWhitespace:
ParseText(reader);
break;
// we ignore these childless elements
case XmlNodeType.Whitespace:
case XmlNodeType.XmlDeclaration:
case XmlNodeType.Comment:
case XmlNodeType.Notation:
case XmlNodeType.ProcessingInstruction:
{
break;
}
// we ignore these elements that can have children
case XmlNodeType.DocumentType:
case XmlNodeType.EntityReference:
{
skipToNextElement = true;
break;
}
default:
{
AddError( ErrorCode.UnexpectedXmlNodeType, EdmSchemaErrorSeverity.Error, reader,
System.Data.Entity.Strings.UnexpectedXmlNodeType(reader.NodeType));
skipToNextElement = true;
break;
}
}
}
HandleChildElementsComplete();
if ( reader.EOF && reader.Depth > 0 )
{
AddError( ErrorCode.MalformedXml, EdmSchemaErrorSeverity.Error, 0, 0,
System.Data.Entity.Strings.MalformedXml(LineNumber,LinePosition));
}
}
///
/// Set the current line number and position for an XmlReader
///
/// the reader whose position is desired
internal void GetPositionInfo(XmlReader reader)
{
GetPositionInfo(reader,out _lineNumber,out _linePosition);
}
///
/// Get the current line number and position for an XmlReader
///
/// the reader whose position is desired
/// the line number
/// the line position
internal static void GetPositionInfo(XmlReader reader, out int lineNumber, out int linePosition)
{
IXmlLineInfo xmlLineInfo = reader as IXmlLineInfo;
if ( xmlLineInfo != null && xmlLineInfo.HasLineInfo() )
{
lineNumber = xmlLineInfo.LineNumber;
linePosition = xmlLineInfo.LinePosition;
}
else
{
lineNumber = 0;
linePosition = 0;
}
}
///
///
///
internal virtual void ResolveTopLevelNames()
{
}
internal virtual void ResolveSecondLevelNames()
{
}
#endregion
#region Protected Methods
///
///
///
///
internal SchemaElement(SchemaElement parentElement)
{
if ( parentElement != null )
{
ParentElement = parentElement;
for ( SchemaElement element = parentElement; element != null; element = element.ParentElement )
{
Schema schema = element as Schema;
if ( schema != null )
{
Schema = schema;
break;
}
}
if (Schema == null)
{
throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.AllElementsMustBeInSchema);
}
}
}
internal SchemaElement(SchemaElement parentElement, string name)
: this(parentElement)
{
_name = name;
}
///
///
///
protected virtual void HandleAttributesComplete()
{
}
///
///
///
protected virtual void HandleChildElementsComplete()
{
}
///
///
///
///
///
///
protected string HandleUndottedNameAttribute(XmlReader reader, string field)
{
string name = field;
Debug.Assert(string.IsNullOrEmpty(field), string.Format(CultureInfo.CurrentCulture, "{0} is already defined", reader.Name));
bool success = Utils.GetUndottedName(Schema, reader, out name);
if ( !success )
return name;
return name;
}
///
///
///
///
///
///
///
protected ReturnValue HandleDottedNameAttribute(XmlReader reader, string field, Func