Imports IdeaBlade.Persistence
Imports DevExpress.Data.Filtering
Namespace Filtering
'''
''' Convert a filter created by DevExpress FilterControl into a DevForce EntityQuery.
'''
'''
''' Dim visitor As New CriteriaVisitor(Of Employee)
''' mFilterControl.FilterCriteria.Accept(visitor)
''' Debug.WriteLine(visitor.Query.ToString)
'''
'''
''' Entity type for wich we want to generate EntityQuery
''' RF 2009-06-16
Public Class CriteriaVisitor(Of T As Entity)
Implements DevExpress.Data.Filtering.ICriteriaVisitor
'''
''' Generated EntityQuery object.
'''
'''
Private mQuery As New EntityQuery(GetType(T))
'''
''' Generated EntityQuery object
'''
'''
''' Generated EntityQuery object
'''
Public ReadOnly Property Query() As EntityQuery
Get
Return mQuery
End Get
End Property
Private Sub VisitRight(ByVal theOperator As CriteriaOperator)
If TypeOf theOperator Is GroupOperator Then
Visit(CType(theOperator, GroupOperator))
ElseIf TypeOf theOperator Is BinaryOperator Then
Visit(CType(theOperator, BinaryOperator))
ElseIf TypeOf theOperator Is InOperator Then
Visit(CType(theOperator, InOperator))
ElseIf TypeOf theOperator Is OperandValue Then
Visit(CType(theOperator, OperandValue))
ElseIf TypeOf theOperator Is BetweenOperator Then
Visit(CType(theOperator, BetweenOperator))
ElseIf TypeOf theOperator Is UnaryOperator Then
Visit(CType(theOperator, UnaryOperator))
'ElseIf TypeOf theOperator Is FunctionOperator Then
' Visit(CType(theOperator, FunctionOperator))
Else
ThrowEx(String.Format("CriteriaOperator type '{0}' not implemented", theOperator.GetType.ToString))
End If
End Sub
Public Function Visit(ByVal theOperator As BetweenOperator) As Object Implements ICriteriaVisitor.Visit
If TypeOf theOperator.BeginExpression Is DevExpress.Data.Filtering.OperandValue _
AndAlso TypeOf theOperator.EndExpression Is DevExpress.Data.Filtering.OperandValue Then
Dim oLeft As OperandValue = CType(theOperator.BeginExpression, OperandValue)
Dim oRight As OperandValue = CType(theOperator.EndExpression, OperandValue)
Dim sPropertyName As String = CType(theOperator.TestExpression, OperandProperty).PropertyName
Dim oColumn As EntityColumn = GetEntityColumn(sPropertyName)
If oColumn Is Nothing Then
ThrowEx(String.Format("No EntityColumn correspond to property '{0}' in System.Type '{1}'", sPropertyName, GetType(T).Name))
Else
mQuery.AddClause(New EntityQueryClause(oColumn, EntityQueryOp.Between, oLeft.Value, oRight.Value))
End If
End If
Return Nothing
End Function
Public Function Visit(ByVal theOperator As BinaryOperator) As Object Implements ICriteriaVisitor.Visit
Dim oOperator As EntityQueryOp = Nothing
Select Case theOperator.OperatorType
Case BinaryOperatorType.Equal
oOperator = EntityQueryOp.EQ
Case BinaryOperatorType.NotEqual
oOperator = EntityQueryOp.NE
Case BinaryOperatorType.Greater
oOperator = EntityQueryOp.GT
Case BinaryOperatorType.GreaterOrEqual
oOperator = EntityQueryOp.GE
Case BinaryOperatorType.Less
oOperator = EntityQueryOp.LT
Case BinaryOperatorType.LessOrEqual
oOperator = EntityQueryOp.LE
Case BinaryOperatorType.Like
oOperator = EntityQueryOp.Like
Case Else
ThrowEx(String.Format("BinaryOperator '{0}' not implemented", theOperator.OperatorType.ToString))
End Select
If TypeOf theOperator.LeftOperand Is OperandProperty Then
If oOperator IsNot Nothing Then
Dim sPropertyName As String = CType(theOperator.LeftOperand, OperandProperty).PropertyName
mQuery.AddClause(New EntityQueryClause(sPropertyName, oOperator, theOperator.RightOperand.ToString.Trim("'"c)))
Else
ThrowEx(String.Format("OperatorType '{0}' not implemented", theOperator.OperatorType.ToString))
End If
Else
ThrowEx("LeftOperand type different of OperandProperty is not implemented")
End If
Return Nothing
End Function
Public Function Visit(ByVal theOperator As GroupOperator) As Object Implements ICriteriaVisitor.Visit
For Each bin As CriteriaOperator In theOperator.Operands
VisitRight(bin)
Next
For i As Integer = 1 To theOperator.Operands.Count - 1
If theOperator.OperatorType = GroupOperatorType.And Then
mQuery.AddOperator(EntityBooleanOp.And)
ElseIf theOperator.OperatorType = GroupOperatorType.Or Then
mQuery.AddOperator(EntityBooleanOp.Or)
End If
Next
Return Nothing
End Function
Public Function Visit(ByVal theOperator As InOperator) As Object Implements ICriteriaVisitor.Visit
Dim oList As New List(Of Object)
For Each bin As CriteriaOperator In theOperator.Operands
If TypeOf bin Is DevExpress.Data.Filtering.OperandValue Then
oList.Add(CType(bin, OperandValue).Value)
End If
Next
If oList.Count > 0 Then
Dim sPropertyName As String = CType(theOperator.LeftOperand, OperandProperty).PropertyName
mQuery.AddClause(New EntityQueryClause(sPropertyName, EntityQueryOp.In, oList.ToArray))
End If
Return Nothing
End Function
Public Function Visit(ByVal theOperator As UnaryOperator) As Object Implements ICriteriaVisitor.Visit
If theOperator.OperatorType = UnaryOperatorType.Not Then
VisitRight(theOperator.Operand)
mQuery.AddOperator(EntityBooleanOp.Not)
Else
If theOperator.OperatorType = UnaryOperatorType.IsNull Then
If TypeOf theOperator.Operand Is OperandProperty Then
mQuery.AddClause(New EntityQueryClause(CType(theOperator.Operand, OperandProperty).PropertyName, EntityQueryOp.IsNull, Nothing))
Else
ThrowEx(String.Format("Operator.Operand type different of OperandProperty ({0}) is not implemented", theOperator.Operand.GetType.ToString))
End If
Else
ThrowEx(String.Format("OperatorType '{0}' not implemented", theOperator.OperatorType.ToString))
End If
End If
Return Nothing
End Function
#Region " To be completed "
Public Function Visit(ByVal theOperator As FunctionOperator) As Object Implements ICriteriaVisitor.Visit
ThrowEx("CriteriaVisitor.Visit(ByVal theOperator As FunctionOperator) not implemented")
Return Nothing
End Function
Public Function Visit(ByVal theOperand As OperandValue) As Object Implements ICriteriaVisitor.Visit
ThrowEx("CriteriaVisitor.Visit(ByVal theOperand As OperandValue) not implemented")
Return Nothing
End Function
Private Sub ThrowEx(Optional ByVal msg As String = "")
If msg = "" Then
Throw New NotImplementedException("QueryCriteria specific method not implemented.")
Else
Throw New NotImplementedException(msg)
End If
End Sub
#End Region
'''
''' Return the Entitycolumn based on the provided property name.
'''
''' Property name for wich we want the EntityColumn
'''
'''
Private Function GetEntityColumn(ByVal PropertyName As String) As EntityColumn
If Not PropertyName.EndsWith("EntityColumn") Then
PropertyName &= "EntityColumn"
End If
Dim oType As System.Type = GetType(T).BaseType
If oType.GetField(PropertyName) IsNot Nothing Then
Dim oValue As Object = oType.GetField(PropertyName).GetValue(Nothing)
If TypeOf oValue Is EntityColumn Then
Return CType(oValue, EntityColumn)
Else
Return Nothing
End If
Else
Return Nothing
End If
End Function
End Class
End Namespace