|
//------------------------------------------------------------
// 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;
}
}
}
}
|