Jo Shields a575963da9 Imported Upstream version 3.6.0
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
2014-08-13 10:39:27 +01:00

517 lines
12 KiB
C#

using System;
using System.Collections;
using System.Xml;
using Commons.Xml.Relaxng;
namespace Commons.Xml.Nvdl
{
public class NvdlReader
{
public static NvdlRules Read (XmlReader reader)
{
return new NvdlReader (reader).ReadRules ();
}
XmlReader reader;
IXmlLineInfo lineInfo;
XmlDocument doc = new XmlDocument ();
private NvdlReader (XmlReader reader)
{
// FIXME: use .rnc validation.
this.reader = reader;
this.lineInfo = reader as IXmlLineInfo;
reader.MoveToContent ();
}
private void FillForeignAttribute (NvdlAttributable el)
{
if (!reader.MoveToFirstAttribute ())
return;
do {
if (reader.NamespaceURI == "")
continue;
XmlAttribute a = doc.CreateAttribute (
reader.Prefix,
reader.LocalName,
reader.NamespaceURI);
a.Value = reader.Value;
el.Foreign.Add (a);
} while (reader.MoveToNextAttribute ());
reader.MoveToElement ();
}
private void FillNonXmlAttributes (NvdlMessage el)
{
if (!reader.MoveToFirstAttribute ())
return;
do {
if (reader.NamespaceURI == Nvdl.XmlNamespaceUri)
continue;
XmlAttribute a = doc.CreateAttribute (
reader.Prefix,
reader.LocalName,
reader.NamespaceURI);
a.Value = reader.Value;
el.ForeignAttributes.Add (a);
} while (reader.MoveToNextAttribute ());
reader.MoveToElement ();
}
private void FillLocation (NvdlElementBase el)
{
el.SourceUri = reader.BaseURI;
if (lineInfo != null) {
el.LineNumber = lineInfo.LineNumber;
el.LinePosition = lineInfo.LinePosition;
}
}
private NvdlRuleTarget ParseMatch (string s)
{
if (s == null)
return NvdlRuleTarget.None;
if (s.IndexOf ("elements") >= 0)
return (s.IndexOf ("attributes") >= 0) ?
NvdlRuleTarget.Both :
NvdlRuleTarget.Elements;
else
return (s.IndexOf ("attributes") >= 0) ?
NvdlRuleTarget.Attributes :
NvdlRuleTarget.None;
}
private NvdlRules ReadRules ()
{
NvdlRules el = new NvdlRules ();
FillLocation (el);
el.SchemaType = reader.GetAttribute ("schemaType");
el.StartMode = reader.GetAttribute ("startMode");
FillForeignAttribute (el);
if (reader.IsEmptyElement) {
reader.Skip ();
return el;
}
reader.Read ();
do {
reader.MoveToContent ();
if (reader.NodeType == XmlNodeType.EndElement)
break;
if (reader.NamespaceURI != Nvdl.Namespace) {
el.Foreign.Add (doc.ReadNode (reader));
continue;
}
switch (reader.LocalName) {
case "mode":
el.Modes.Add (ReadMode ());
break;
case "namespace":
el.Rules.Add (ReadNamespace ());
break;
case "anyNamespace":
el.Rules.Add (ReadAnyNamespace ());
break;
case "trigger":
el.Triggers.Add (ReadTrigger ());
break;
}
} while (!reader.EOF);
if (!reader.EOF)
reader.Read ();
return el;
}
private NvdlTrigger ReadTrigger ()
{
NvdlTrigger el = new NvdlTrigger ();
FillLocation (el);
el.NS = reader.GetAttribute ("ns");
el.NameList = reader.GetAttribute ("nameList");
FillForeignAttribute (el);
if (reader.IsEmptyElement) {
reader.Skip ();
return el;
}
reader.Read ();
do {
reader.MoveToContent ();
if (reader.NodeType == XmlNodeType.EndElement)
break;
if (reader.NamespaceURI != Nvdl.Namespace) {
el.Foreign.Add (doc.ReadNode (reader));
continue;
}
} while (!reader.EOF);
if (!reader.EOF)
reader.Read ();
return el;
}
private NvdlMode ReadMode ()
{
NvdlMode el = new NvdlMode ();
FillLocation (el);
el.Name = reader.GetAttribute ("name");
ReadModeCommon (el);
return el;
}
private NvdlIncludedMode ReadIncludedMode ()
{
NvdlIncludedMode el = new NvdlIncludedMode ();
FillLocation (el);
el.Name = reader.GetAttribute ("name");
ReadModeCommon (el);
return el;
}
private NvdlNestedMode ReadNestedMode ()
{
NvdlNestedMode el = new NvdlNestedMode ();
FillLocation (el);
ReadModeCommon (el);
return el;
}
private void ReadModeCommon (NvdlModeBase el)
{
FillForeignAttribute (el);
if (reader.IsEmptyElement) {
reader.Skip ();
return;
}
reader.Read ();
do {
reader.MoveToContent ();
if (reader.NodeType == XmlNodeType.EndElement)
break;
if (reader.NamespaceURI != Nvdl.Namespace) {
el.Foreign.Add (doc.ReadNode (reader));
continue;
}
switch (reader.LocalName) {
case "mode":
el.IncludedModes.Add (ReadIncludedMode ());
break;
case "namespace":
el.Rules.Add (ReadNamespace ());
break;
case "anyNamespace":
el.Rules.Add (ReadAnyNamespace ());
break;
}
} while (!reader.EOF);
if (!reader.EOF)
reader.Read ();
return;
}
private NvdlAnyNamespace ReadAnyNamespace ()
{
NvdlAnyNamespace el = new NvdlAnyNamespace ();
FillLocation (el);
el.Match = ParseMatch (reader.GetAttribute ("match"));
FillForeignAttribute (el);
if (reader.IsEmptyElement) {
reader.Skip ();
return el;
}
reader.Read ();
do {
reader.MoveToContent ();
if (reader.NodeType == XmlNodeType.EndElement)
break;
if (reader.NamespaceURI != Nvdl.Namespace) {
el.Foreign.Add (doc.ReadNode (reader));
continue;
}
ReadAction (el);
} while (!reader.EOF);
if (!reader.EOF)
reader.Read ();
return el;
}
private NvdlNamespace ReadNamespace ()
{
NvdlNamespace el = new NvdlNamespace ();
FillLocation (el);
el.NS = reader.GetAttribute ("ns");
el.Wildcard = reader.GetAttribute ("wildCard");
el.Match = ParseMatch (reader.GetAttribute ("match"));
FillForeignAttribute (el);
if (reader.IsEmptyElement) {
reader.Skip ();
return el;
}
reader.Read ();
do {
reader.MoveToContent ();
if (reader.NodeType == XmlNodeType.EndElement)
break;
if (reader.NamespaceURI != Nvdl.Namespace) {
el.Foreign.Add (doc.ReadNode (reader));
continue;
}
ReadAction (el);
} while (!reader.EOF);
if (!reader.EOF)
reader.Read ();
return el;
}
private void ReadAction (NvdlRule el)
{
switch (reader.LocalName) {
case "cancelNestedActions":
el.Actions.Add (ReadCancelAction ());
break;
case "validate":
el.Actions.Add (ReadValidate ());
break;
case "allow":
el.Actions.Add (ReadAllow ());
break;
case "reject":
el.Actions.Add (ReadReject ());
break;
case "attach":
el.Actions.Add (ReadAttach ());
break;
case "attachPlaceHolder":
el.Actions.Add (ReadAttachPlaceholder ());
break;
case "unwrap":
el.Actions.Add (ReadUnwrap ());
break;
default:
throw new NotSupportedException ();
}
}
private NvdlCancelAction ReadCancelAction ()
{
NvdlCancelAction el = new NvdlCancelAction ();
FillLocation (el);
FillForeignAttribute (el);
if (reader.IsEmptyElement) {
reader.Skip ();
return el;
}
reader.Read ();
do {
reader.MoveToContent ();
if (reader.NodeType == XmlNodeType.EndElement)
break;
if (reader.NamespaceURI != Nvdl.Namespace) {
el.Foreign.Add (doc.ReadNode (reader));
continue;
}
} while (!reader.EOF);
if (!reader.EOF)
reader.Read ();
return el;
}
private NvdlValidate ReadValidate ()
{
NvdlValidate el = new NvdlValidate ();
NvdlModeUsage mu = new NvdlModeUsage ();
el.ModeUsage = mu;
FillLocation (el);
el.SchemaType = reader.GetAttribute ("schemaType");
el.SimpleMessage = reader.GetAttribute ("message");
el.SchemaUri = reader.GetAttribute ("schema");
mu.UseMode = reader.GetAttribute ("useMode");
FillForeignAttribute (el);
if (reader.IsEmptyElement) {
reader.Skip ();
return el;
}
reader.Read ();
do {
reader.MoveToContent ();
if (reader.NodeType == XmlNodeType.EndElement)
break;
if (reader.NamespaceURI != Nvdl.Namespace) {
el.Foreign.Add (doc.ReadNode (reader));
continue;
}
switch (reader.LocalName) {
case "message":
el.Messages.Add (ReadMessage ());
break;
case "option":
el.Options.Add (ReadOption ());
break;
case "schema":
el.SchemaBody = (XmlElement) doc.ReadNode (reader);
break;
case "mode":
mu.NestedMode = ReadNestedMode ();
break;
case "context":
mu.Contexts.Add (ReadContext ());
break;
default:
throw new NotSupportedException ();
}
} while (!reader.EOF);
if (!reader.EOF)
reader.Read ();
return el;
}
private NvdlAllow ReadAllow ()
{
NvdlAllow el = new NvdlAllow ();
ReadCommonActionContent (el);
return el;
}
private NvdlReject ReadReject ()
{
NvdlReject el = new NvdlReject ();
ReadCommonActionContent (el);
return el;
}
private NvdlAttach ReadAttach ()
{
NvdlAttach el = new NvdlAttach ();
ReadCommonActionContent (el);
return el;
}
private NvdlAttachPlaceholder ReadAttachPlaceholder ()
{
NvdlAttachPlaceholder el = new NvdlAttachPlaceholder ();
ReadCommonActionContent (el);
return el;
}
private NvdlUnwrap ReadUnwrap ()
{
NvdlUnwrap el = new NvdlUnwrap ();
ReadCommonActionContent (el);
return el;
}
private void ReadCommonActionContent (NvdlNoCancelAction el)
{
FillLocation (el);
NvdlModeUsage mu = new NvdlModeUsage ();
el.ModeUsage = mu;
FillLocation (el);
el.SimpleMessage = reader.GetAttribute ("message");
mu.UseMode = reader.GetAttribute ("useMode");
FillForeignAttribute (el);
if (reader.IsEmptyElement) {
reader.Skip ();
return;
}
reader.Read ();
do {
reader.MoveToContent ();
if (reader.NodeType == XmlNodeType.EndElement)
break;
if (reader.NamespaceURI != Nvdl.Namespace) {
el.Foreign.Add (doc.ReadNode (reader));
continue;
}
switch (reader.LocalName) {
case "mode":
mu.NestedMode = ReadNestedMode ();
break;
case "message":
el.Messages.Add (ReadMessage ());
break;
case "context":
mu.Contexts.Add (ReadContext ());
break;
default:
throw new NotSupportedException ();
}
} while (!reader.EOF);
if (!reader.EOF)
reader.Read ();
}
private NvdlMessage ReadMessage ()
{
NvdlMessage el = new NvdlMessage ();
FillLocation (el);
el.XmlLang = reader.GetAttribute ("lang", Nvdl.XmlNamespaceUri);
FillNonXmlAttributes (el);
if (reader.IsEmptyElement) {
reader.Skip ();
el.Text = "";
}
else
el.Text = reader.ReadElementString ();
return el;
}
private NvdlOption ReadOption ()
{
NvdlOption el = new NvdlOption ();
FillLocation (el);
el.Name = reader.GetAttribute ("name");
el.Arg = reader.GetAttribute ("arg");
el.MustSupport = reader.GetAttribute ("mustSupport");
FillForeignAttribute (el);
if (reader.IsEmptyElement) {
reader.Skip ();
return el;
}
reader.Read ();
do {
reader.MoveToContent ();
if (reader.NodeType == XmlNodeType.EndElement)
break;
if (reader.NamespaceURI != Nvdl.Namespace) {
el.Foreign.Add (doc.ReadNode (reader));
continue;
}
} while (!reader.EOF);
if (!reader.EOF)
reader.Read ();
return el;
}
private NvdlContext ReadContext ()
{
NvdlContext el = new NvdlContext ();
FillLocation (el);
el.Path = reader.GetAttribute ("path");
el.UseMode = reader.GetAttribute ("useMode");
FillForeignAttribute (el);
if (reader.IsEmptyElement) {
reader.Skip ();
return el;
}
reader.Read ();
do {
reader.MoveToContent ();
if (reader.NodeType == XmlNodeType.EndElement)
break;
if (reader.NamespaceURI != Nvdl.Namespace) {
el.Foreign.Add (doc.ReadNode (reader));
continue;
}
switch (reader.LocalName) {
case "mode":
el.NestedMode = ReadNestedMode ();
break;
default:
throw new NotSupportedException ();
}
} while (!reader.EOF);
if (!reader.EOF)
reader.Read ();
return el;
}
}
}