|
//------------------------------------------------------------------------------
// <copyright file="UnionExpr.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">Microsoft</owner>
//------------------------------------------------------------------------------
namespace MS.Internal.Xml.XPath {
using System;
using System.Xml;
using System.Xml.XPath;
using System.Diagnostics;
using System.Xml.Xsl;
internal sealed class UnionExpr : Query {
internal Query qy1, qy2;
private bool advance1, advance2;
private XPathNavigator currentNode;
private XPathNavigator nextNode;
public UnionExpr(Query query1, Query query2) {
this.qy1 = query1;
this.qy2 = query2;
this.advance1 = true;
this.advance2 = true;
}
private UnionExpr(UnionExpr other) : base(other) {
this.qy1 = Clone(other.qy1);
this.qy2 = Clone(other.qy2);
this.advance1 = other.advance1;
this.advance2 = other.advance2;
this.currentNode = Clone(other.currentNode);
this.nextNode = Clone(other.nextNode);
}
public override void Reset() {
qy1.Reset();
qy2.Reset();
advance1 = true;
advance2 = true;
nextNode = null;
}
public override void SetXsltContext(XsltContext xsltContext) {
qy1.SetXsltContext(xsltContext);
qy2.SetXsltContext(xsltContext);
}
public override object Evaluate(XPathNodeIterator context) {
qy1.Evaluate(context);
qy2.Evaluate(context);
advance1 = true;
advance2 = true;
nextNode = null;
base.ResetCount();
return this;
}
private XPathNavigator ProcessSamePosition(XPathNavigator result){
currentNode = result;
advance1 = advance2 = true;
return result;
}
private XPathNavigator ProcessBeforePosition(XPathNavigator res1, XPathNavigator res2){
nextNode = res2;
advance2 = false;
advance1 = true;
currentNode = res1;
return res1;
}
private XPathNavigator ProcessAfterPosition(XPathNavigator res1, XPathNavigator res2){
nextNode = res1;
advance1 = false;
advance2 = true;
currentNode = res2;
return res2;
}
public override XPathNavigator Advance() {
XPathNavigator res1, res2;
XmlNodeOrder order = 0;
if (advance1) {
res1 = qy1.Advance();
} else {
res1 = nextNode;
}
if (advance2) {
res2 = qy2.Advance();
} else {
res2 = nextNode;
}
if (res1 != null && res2 != null) {
order = CompareNodes(res1, res2);
} else if (res2 == null) {
advance1 = true;
advance2 = false;
currentNode = res1;
nextNode = null;
return res1;
} else {
advance1 = false;
advance2 = true;
currentNode = res2;
nextNode = null;
return res2;
}
if (order == XmlNodeOrder.Before) {
return ProcessBeforePosition(res1, res2);
} else if (order == XmlNodeOrder.After) {
return ProcessAfterPosition(res1, res2);
} else {
// BugBug. In case of Unknown we sorting as the same.
return ProcessSamePosition(res1);
}
}
public override XPathNavigator MatchNode(XPathNavigator xsltContext) {
if (xsltContext != null) {
XPathNavigator result = qy1.MatchNode(xsltContext);
if (result != null) {
return result;
}
return qy2.MatchNode(xsltContext);
}
return null;
}
public override XPathResultType StaticType { get { return XPathResultType.NodeSet; } }
public override XPathNodeIterator Clone() { return new UnionExpr(this); }
public override XPathNavigator Current { get { return currentNode; } }
public override int CurrentPosition { get { throw new InvalidOperationException(); } }
public override void PrintQuery(XmlWriter w) {
w.WriteStartElement(this.GetType().Name);
if (qy1 != null) {
qy1.PrintQuery(w);
}
if (qy2 != null) {
qy2.PrintQuery(w);
}
w.WriteEndElement();
}
}
}
|