476 lines
11 KiB
C#
476 lines
11 KiB
C#
|
//------------------------------------------------------------
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//------------------------------------------------------------
|
||
|
namespace System.ServiceModel.Dispatcher
|
||
|
{
|
||
|
using System.Collections;
|
||
|
using System.Runtime;
|
||
|
using System.Xml.XPath;
|
||
|
using System.Xml.Xsl;
|
||
|
|
||
|
internal enum XPathExprType : byte
|
||
|
{
|
||
|
Unknown,
|
||
|
Or,
|
||
|
And,
|
||
|
Relational,
|
||
|
Union,
|
||
|
LocationPath,
|
||
|
RelativePath,
|
||
|
PathStep,
|
||
|
XsltVariable,
|
||
|
String,
|
||
|
Number,
|
||
|
Function,
|
||
|
XsltFunction,
|
||
|
Math,
|
||
|
Filter,
|
||
|
Path
|
||
|
}
|
||
|
|
||
|
internal class XPathExpr
|
||
|
{
|
||
|
ValueDataType returnType;
|
||
|
XPathExprList subExpr;
|
||
|
XPathExprType type;
|
||
|
bool negate;
|
||
|
bool castRequired;
|
||
|
|
||
|
internal XPathExpr(XPathExprType type, ValueDataType returnType, XPathExprList subExpr)
|
||
|
: this(type, returnType)
|
||
|
{
|
||
|
this.subExpr = subExpr;
|
||
|
}
|
||
|
|
||
|
internal XPathExpr(XPathExprType type, ValueDataType returnType)
|
||
|
{
|
||
|
this.type = type;
|
||
|
this.returnType = returnType;
|
||
|
}
|
||
|
|
||
|
internal virtual bool IsLiteral
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal bool Negate
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.negate;
|
||
|
}
|
||
|
set
|
||
|
{
|
||
|
this.negate = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal ValueDataType ReturnType
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.returnType;
|
||
|
}
|
||
|
set
|
||
|
{
|
||
|
this.returnType = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal int SubExprCount
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return (null == this.subExpr) ? 0 : this.subExpr.Count;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal XPathExprList SubExpr
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
if (null == this.subExpr)
|
||
|
{
|
||
|
this.subExpr = new XPathExprList();
|
||
|
}
|
||
|
return this.subExpr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal XPathExprType Type
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.type;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal bool TypecastRequired
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.castRequired;
|
||
|
}
|
||
|
set
|
||
|
{
|
||
|
this.castRequired = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void Add(XPathExpr expr)
|
||
|
{
|
||
|
Fx.Assert(null != expr, "");
|
||
|
this.SubExpr.Add(expr);
|
||
|
}
|
||
|
|
||
|
internal void AddBooleanExpression(XPathExprType boolExprType, XPathExpr expr)
|
||
|
{
|
||
|
Fx.Assert(boolExprType == this.type, "");
|
||
|
|
||
|
// An boolean sub0expression that is of the same type as its container should be merged and flattened
|
||
|
// into its parent
|
||
|
if (boolExprType == expr.Type)
|
||
|
{
|
||
|
XPathExprList subExprList = expr.SubExpr;
|
||
|
for (int i = 0; i < subExprList.Count; ++i)
|
||
|
{
|
||
|
this.AddBooleanExpression(boolExprType, subExprList[i]);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
this.Add(expr);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal class XPathExprList
|
||
|
{
|
||
|
ArrayList list;
|
||
|
|
||
|
internal XPathExprList()
|
||
|
{
|
||
|
this.list = new ArrayList(2);
|
||
|
}
|
||
|
|
||
|
internal int Count
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.list.Count;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal XPathExpr this[int index]
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return (XPathExpr)this.list[index];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void Add(XPathExpr expr)
|
||
|
{
|
||
|
Fx.Assert(null != expr, "");
|
||
|
this.list.Add(expr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal class XPathConjunctExpr : XPathExpr
|
||
|
{
|
||
|
internal XPathConjunctExpr(XPathExprType type, ValueDataType returnType, XPathExpr left, XPathExpr right)
|
||
|
: base(type, returnType)
|
||
|
{
|
||
|
if (null == left || null == right)
|
||
|
{
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryCompileException(QueryCompileError.InvalidExpression));
|
||
|
}
|
||
|
this.SubExpr.Add(left);
|
||
|
this.SubExpr.Add(right);
|
||
|
}
|
||
|
|
||
|
internal XPathExpr Left
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.SubExpr[0];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal XPathExpr Right
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.SubExpr[1];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal class XPathRelationExpr : XPathConjunctExpr
|
||
|
{
|
||
|
RelationOperator op;
|
||
|
|
||
|
internal XPathRelationExpr(RelationOperator op, XPathExpr left, XPathExpr right)
|
||
|
: base(XPathExprType.Relational, ValueDataType.Boolean, left, right)
|
||
|
{
|
||
|
this.op = op;
|
||
|
}
|
||
|
|
||
|
internal RelationOperator Op
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.op;
|
||
|
}
|
||
|
set
|
||
|
{
|
||
|
this.op = value;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal class XPathMathExpr : XPathConjunctExpr
|
||
|
{
|
||
|
MathOperator op;
|
||
|
|
||
|
internal XPathMathExpr(MathOperator op, XPathExpr left, XPathExpr right)
|
||
|
: base(XPathExprType.Math, ValueDataType.Double, left, right)
|
||
|
{
|
||
|
this.op = op;
|
||
|
}
|
||
|
|
||
|
internal MathOperator Op
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.op;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal class XPathFunctionExpr : XPathExpr
|
||
|
{
|
||
|
QueryFunction function;
|
||
|
|
||
|
internal XPathFunctionExpr(QueryFunction function, XPathExprList subExpr)
|
||
|
: base(XPathExprType.Function, function.ReturnType, subExpr)
|
||
|
{
|
||
|
Fx.Assert(null != function, "");
|
||
|
this.function = function;
|
||
|
}
|
||
|
|
||
|
internal QueryFunction Function
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.function;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal class XPathXsltFunctionExpr : XPathExpr
|
||
|
{
|
||
|
XsltContext context;
|
||
|
IXsltContextFunction function;
|
||
|
|
||
|
internal XPathXsltFunctionExpr(XsltContext context, IXsltContextFunction function, XPathExprList subExpr)
|
||
|
: base(XPathExprType.XsltFunction, ConvertTypeFromXslt(function.ReturnType), subExpr)
|
||
|
{
|
||
|
this.function = function;
|
||
|
this.context = context;
|
||
|
}
|
||
|
|
||
|
internal XsltContext Context
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.context;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal IXsltContextFunction Function
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.function;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal static XPathResultType ConvertTypeToXslt(ValueDataType type)
|
||
|
{
|
||
|
switch (type)
|
||
|
{
|
||
|
case ValueDataType.Boolean:
|
||
|
return XPathResultType.Boolean;
|
||
|
|
||
|
case ValueDataType.Double:
|
||
|
return XPathResultType.Number;
|
||
|
|
||
|
case ValueDataType.Sequence:
|
||
|
return XPathResultType.NodeSet;
|
||
|
|
||
|
case ValueDataType.String:
|
||
|
return XPathResultType.String;
|
||
|
|
||
|
default:
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryCompileException(QueryCompileError.InvalidTypeConversion));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal static ValueDataType ConvertTypeFromXslt(XPathResultType type)
|
||
|
{
|
||
|
switch (type)
|
||
|
{
|
||
|
case XPathResultType.Boolean:
|
||
|
return ValueDataType.Boolean;
|
||
|
|
||
|
case XPathResultType.Number:
|
||
|
return ValueDataType.Double;
|
||
|
|
||
|
case XPathResultType.NodeSet:
|
||
|
return ValueDataType.Sequence;
|
||
|
|
||
|
case XPathResultType.String:
|
||
|
return ValueDataType.String;
|
||
|
|
||
|
default:
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryCompileException(QueryCompileError.InvalidTypeConversion));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal class XPathXsltVariableExpr : XPathExpr
|
||
|
{
|
||
|
XsltContext context;
|
||
|
IXsltContextVariable variable;
|
||
|
|
||
|
internal XPathXsltVariableExpr(XsltContext context, IXsltContextVariable variable)
|
||
|
: base(XPathExprType.XsltVariable, XPathXsltFunctionExpr.ConvertTypeFromXslt(variable.VariableType))
|
||
|
{
|
||
|
Fx.Assert(null != variable, "");
|
||
|
this.variable = variable;
|
||
|
this.context = context;
|
||
|
}
|
||
|
|
||
|
internal XsltContext Context
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.context;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal IXsltContextVariable Variable
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.variable;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal class XPathStepExpr : XPathExpr
|
||
|
{
|
||
|
NodeSelectCriteria selectDesc;
|
||
|
|
||
|
internal XPathStepExpr(NodeSelectCriteria desc)
|
||
|
: this(desc, null)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
internal XPathStepExpr(NodeSelectCriteria desc, XPathExprList predicates)
|
||
|
: base(XPathExprType.PathStep, ValueDataType.Sequence, predicates)
|
||
|
{
|
||
|
Fx.Assert(null != desc, "");
|
||
|
this.selectDesc = desc;
|
||
|
}
|
||
|
|
||
|
internal NodeSelectCriteria SelectDesc
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.selectDesc;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal abstract class XPathLiteralExpr : XPathExpr
|
||
|
{
|
||
|
internal XPathLiteralExpr(XPathExprType type, ValueDataType returnType)
|
||
|
: base(type, returnType)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
internal override bool IsLiteral
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal abstract object Literal
|
||
|
{
|
||
|
get;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
internal class XPathStringExpr : XPathLiteralExpr
|
||
|
{
|
||
|
string literal;
|
||
|
|
||
|
internal XPathStringExpr(string literal)
|
||
|
: base(XPathExprType.String, ValueDataType.String)
|
||
|
{
|
||
|
this.literal = literal;
|
||
|
}
|
||
|
|
||
|
internal override object Literal
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.literal;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal string String
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.literal;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal class XPathNumberExpr : XPathLiteralExpr
|
||
|
{
|
||
|
double literal;
|
||
|
|
||
|
internal XPathNumberExpr(double literal)
|
||
|
: base(XPathExprType.Number, ValueDataType.Double)
|
||
|
{
|
||
|
this.literal = literal;
|
||
|
}
|
||
|
|
||
|
internal override object Literal
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.literal;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal double Number
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.literal;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|