diff --git a/wst/trunk/tests/test_suite/test_rtti_filter.pas b/wst/trunk/tests/test_suite/test_rtti_filter.pas new file mode 100644 index 000000000..16b193bf0 --- /dev/null +++ b/wst/trunk/tests/test_suite/test_rtti_filter.pas @@ -0,0 +1,1284 @@ +{ + This file is part of the Web Service Toolkit + Copyright (c) 2006, 2007, 2008 by Inoussa OUEDRAOGO + + This file is provide under modified LGPL licence + ( the files COPYING.modifiedLGPL and COPYING.LGPL). + + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +} +{$INCLUDE wst_global.inc} +unit test_rtti_filter; + + +//{$DEFINE DBG_DISPLAY} + +interface + +uses + Classes, SysUtils, TypInfo, +{$IFDEF FPC} + fpcunit, testutils, testregistry, +{$ELSE} + TestFrameWork, +{$ENDIF} + rtti_filters; + +type + +{$IFDEF WST_DELPHI } + EAssertionFailedError = ETestFailure; +{$ENDIF} + + TSampleEnum = ( SampleEnum_A, SampleEnum_B, SampleEnum_C, SampleEnum_D, SampleEnum_E ); + + { TClass_A } + + TClass_A = class(TPersistent) + private + FBoolProp : Boolean; + FEnumProp : TSampleEnum; + FIntProp: Integer; + FStrProp: string; + FWideStrProp: widestring; + published + property IntProp : Integer read FIntProp write FIntProp; + property StrProp : string read FStrProp write FStrProp; + property WideStrProp : widestring read FWideStrProp write FWideStrProp; + property EnumProp : TSampleEnum read FEnumProp write FEnumProp; + property BoolProp : Boolean read FBoolProp write FBoolProp; + end; + TClass_AClass = class of TClass_A; + + { TRttiExpIntegerNodeItem_Test } + + TRttiExpIntegerNodeItem_Test = class(TTestCase) + published + procedure Create_Test(); + procedure Evaluate_Equal(); + procedure Evaluate_Lesser(); + procedure Evaluate_Greater(); + end; + + { TRttiExpEnumNodeItem_Test } + + TRttiExpEnumNodeItem_Test = class(TTestCase) + published + procedure Create_Test(); + procedure Evaluate_Equal(); + procedure Evaluate_Equal_bool(); + procedure Evaluate_Lesser(); + procedure Evaluate_Greater(); + end; + + { TRttiExpAnsiStringNodeItem_Test } + + TRttiExpAnsiStringNodeItem_Test = class(TTestCase) + published + procedure Create_Test(); + procedure Evaluate_EqualCaseSensitive(); + procedure Evaluate_EqualCaseInsensitive(); + end; + + { TRttiExpwWideStringNodeItem_Test } + + TRttiExpwWideStringNodeItem_Test = class(TTestCase) + published + procedure Create_Test(); + procedure Evaluate_EqualCaseSensitive(); + procedure Evaluate_EqualCaseInsensitive(); + end; + + { TRttiExpNode_Test } + + TRttiExpNode_Test = class(TTestCase) + published + procedure Left_True(); + procedure LeftTrue_Or_RightFalse(); + procedure LeftTrue_Or_RightTrue(); + procedure LeftTrue_And_RightFalse(); + procedure LeftTrue_And_RightTrue(); + + procedure Left_False(); + procedure LeftFalse_Or_RightFalse(); + procedure LeftFalse_Or_RightTrue(); + procedure LeftFalse_And_RightFalse(); + end; + + { TRttiFilterCreator_Test } + + TRttiFilterCreator_Test = class(TTestCase) + published + procedure Creation(); + procedure AddContion(); + procedure BeginEnd_Group(); + end; + + { TRttiParser_Test } + + TRttiParser_Test = class(TTestCase) + published + procedure SimpleBoolParsing(); + procedure SimpleEnumParsing(); + procedure operator_equal_string(); + procedure operator_not_equal_string(); + procedure operator_equal_int(); + procedure operator_not_equal_int(); + procedure operator_greater_or_equal_int(); + procedure operator_lesser_or_equal_int(); + procedure operator_equal_enum(); + procedure operator_not_equal_enum(); + procedure operator_greater_or_equal_enum(); + procedure operator_lesser_or_equal_enum(); + procedure BeginEnd_Group(); + end; + +implementation + +procedure TRttiExpIntegerNodeItem_Test.Create_Test(); +var + x : TRttiExpIntegerNodeItem; +begin + x := nil; + try + try + x := TRttiExpIntegerNodeItem.Create(GetPropInfo(TClass_A,'StrProp'),nfoEqual,10); + Check(False); + except + on e : EAssertionFailedError do + raise; + on e : ERttiFilterException do begin + // nothing! + end; + end; + finally + x.Free(); + end; +end; + +procedure TRttiExpIntegerNodeItem_Test.Evaluate_Equal(); +const VAL_1 : Integer = 1210; +var + x : TRttiExpIntegerNodeItem; + t : TClass_A; +begin + x := nil; + t := TClass_A.Create(); + try + x := TRttiExpIntegerNodeItem.Create(GetPropInfo(t,'IntProp'),nfoEqual,VAL_1); + + t.IntProp := 0; + Check( x.Evaluate(t) = False ,'False'); + + t.IntProp := VAL_1; + Check( x.Evaluate(t) = True, 'True' ); + finally + x.Free(); + t.Free(); + end; +end; + +procedure TRttiExpIntegerNodeItem_Test.Evaluate_Lesser(); +const VAL_1 : Integer = 1210; +var + x : TRttiExpIntegerNodeItem; + t : TClass_A; +begin + x := nil; + t := TClass_A.Create(); + try + x := TRttiExpIntegerNodeItem.Create(GetPropInfo(t,'IntProp'),nfoLesser,VAL_1); + + t.IntProp := 0; + Check( x.Evaluate(t) = True ,'True'); + + t.IntProp := VAL_1 + 1; + Check( x.Evaluate(t) = False, 'False' ); + finally + x.Free(); + t.Free(); + end; +end; + +procedure TRttiExpIntegerNodeItem_Test.Evaluate_Greater(); +const VAL_1 : Integer = 1210; +var + x : TRttiExpIntegerNodeItem; + t : TClass_A; +begin + x := nil; + t := TClass_A.Create(); + try + x := TRttiExpIntegerNodeItem.Create(GetPropInfo(t,'IntProp'),nfoGreater,VAL_1); + + t.IntProp := 0; + Check( x.Evaluate(t) = False, 'False' ); + + t.IntProp := VAL_1 + 1; + Check( x.Evaluate(t) = True ,'True'); + finally + x.Free(); + t.Free(); + end; +end; + + +{ TRttiExpNode_Test } + +procedure TRttiExpNode_Test.Left_True(); +const VAL_1 : Integer = 1210; +var + x : TRttiExpNode; + t : TClass_A; +begin + x := nil; + t := TClass_A.Create(); + try + x := TRttiExpNode.Create(); + CheckNull(x.Left); + CheckNull(x.Right); + Check(x.Connector = fcNone); + + x.Left := TRttiExpIntegerNodeItem.Create(GetPropInfo(t,'IntProp'),nfoEqual,VAL_1); + + t.IntProp := 0; + Check( x.Evaluate(t) = False, 'False' ); + + t.IntProp := VAL_1; + Check( x.Evaluate(t) = True ,'True'); + finally + x.Free(); + t.Free(); + end; +end; + +procedure TRttiExpNode_Test.LeftTrue_Or_RightFalse(); +const VAL_1 : Integer = 1210; +var + x : TRttiExpNode; + t : TClass_A; +begin + x := nil; + t := TClass_A.Create(); + try + x := TRttiExpNode.Create(); + CheckNull(x.Left); + CheckNull(x.Right); + Check(x.Connector = fcNone); + + x.Left := TRttiExpIntegerNodeItem.Create(GetPropInfo(t,'IntProp'),nfoLesser,VAL_1); + x.Connector := fcOr; + x.Right := TRttiExpIntegerNodeItem.Create(GetPropInfo(t,'IntProp'),nfoGreater,VAL_1); + + t.IntProp := 0; + Check( x.Evaluate(t) = True ,'True'); + finally + x.Free(); + t.Free(); + end; +end; + +procedure TRttiExpNode_Test.LeftTrue_Or_RightTrue(); +const VAL_1 : Integer = 1210; +var + x : TRttiExpNode; + t : TClass_A; +begin + x := nil; + t := TClass_A.Create(); + try + x := TRttiExpNode.Create(); + CheckNull(x.Left); + CheckNull(x.Right); + Check(x.Connector = fcNone); + + x.Left := TRttiExpIntegerNodeItem.Create(GetPropInfo(t,'IntProp'),nfoLesser,VAL_1); + x.Connector := fcOr; + x.Right := TRttiExpIntegerNodeItem.Create(GetPropInfo(t,'IntProp'),nfoLesser,VAL_1); + + t.IntProp := 0; + Check( x.Evaluate(t) = True ,'True'); + finally + x.Free(); + t.Free(); + end; +end; + +procedure TRttiExpNode_Test.LeftTrue_And_RightFalse(); +const VAL_1 : Integer = 1210; +var + x : TRttiExpNode; + t : TClass_A; +begin + x := nil; + t := TClass_A.Create(); + try + x := TRttiExpNode.Create(); + CheckNull(x.Left); + CheckNull(x.Right); + Check(x.Connector = fcNone); + + x.Left := TRttiExpIntegerNodeItem.Create(GetPropInfo(t,'IntProp'),nfoLesser,VAL_1); + x.Connector := fcAnd; + x.Right := TRttiExpIntegerNodeItem.Create(GetPropInfo(t,'IntProp'),nfoGreater,VAL_1); + + t.IntProp := 0; + Check( x.Evaluate(t) = False ,'False'); + finally + x.Free(); + t.Free(); + end; +end; + +procedure TRttiExpNode_Test.LeftTrue_And_RightTrue(); +const VAL_1 : Integer = 1210; +var + x : TRttiExpNode; + t : TClass_A; +begin + x := nil; + t := TClass_A.Create(); + try + x := TRttiExpNode.Create(); + CheckNull(x.Left); + CheckNull(x.Right); + Check(x.Connector = fcNone); + + x.Left := TRttiExpIntegerNodeItem.Create(GetPropInfo(t,'IntProp'),nfoLesser,VAL_1); + x.Connector := fcAnd; + x.Right := TRttiExpIntegerNodeItem.Create(GetPropInfo(t,'IntProp'),nfoLesser,VAL_1); + + t.IntProp := 0; + Check( x.Evaluate(t) = True ,'True'); + finally + x.Free(); + t.Free(); + end; +end; + +procedure TRttiExpNode_Test.Left_False(); +const VAL_1 : Integer = 1210; +var + x : TRttiExpNode; + t : TClass_A; +begin + x := nil; + t := TClass_A.Create(); + try + x := TRttiExpNode.Create(); + CheckNull(x.Left); + CheckNull(x.Right); + Check(x.Connector = fcNone); + + x.Left := TRttiExpIntegerNodeItem.Create(GetPropInfo(t,'IntProp'),nfoGreater,VAL_1); + + t.IntProp := 0; + Check( x.Evaluate(t) = False, 'False' ); + finally + x.Free(); + t.Free(); + end; +end; + +procedure TRttiExpNode_Test.LeftFalse_Or_RightFalse(); +const VAL_1 : Integer = 1210; +var + x : TRttiExpNode; + t : TClass_A; +begin + x := nil; + t := TClass_A.Create(); + try + x := TRttiExpNode.Create(); + CheckNull(x.Left); + CheckNull(x.Right); + Check(x.Connector = fcNone); + + x.Left := TRttiExpIntegerNodeItem.Create(GetPropInfo(t,'IntProp'),nfoEqual,VAL_1); + x.Connector := fcOr; + x.Right := TRttiExpIntegerNodeItem.Create(GetPropInfo(t,'IntProp'),nfoGreater,VAL_1); + + t.IntProp := 0; + Check( x.Evaluate(t) = False ,'False'); + finally + x.Free(); + t.Free(); + end; +end; + +procedure TRttiExpNode_Test.LeftFalse_Or_RightTrue(); +const VAL_1 : Integer = 1210; +var + x : TRttiExpNode; + t : TClass_A; +begin + x := nil; + t := TClass_A.Create(); + try + x := TRttiExpNode.Create(); + CheckNull(x.Left); + CheckNull(x.Right); + Check(x.Connector = fcNone); + + x.Left := TRttiExpIntegerNodeItem.Create(GetPropInfo(t,'IntProp'),nfoEqual,VAL_1); + x.Connector := fcOr; + x.Right := TRttiExpIntegerNodeItem.Create(GetPropInfo(t,'IntProp'),nfoEqual,0); + + t.IntProp := 0; + Check( x.Evaluate(t) = True ,'True'); + finally + x.Free(); + t.Free(); + end; +end; + +procedure TRttiExpNode_Test.LeftFalse_And_RightFalse(); +const VAL_1 : Integer = 1210; +var + x : TRttiExpNode; + t : TClass_A; +begin + x := nil; + t := TClass_A.Create(); + try + x := TRttiExpNode.Create(); + CheckNull(x.Left); + CheckNull(x.Right); + Check(x.Connector = fcNone); + + x.Left := TRttiExpIntegerNodeItem.Create(GetPropInfo(t,'IntProp'),nfoLesser,-VAL_1); + x.Connector := fcAnd; + x.Right := TRttiExpIntegerNodeItem.Create(GetPropInfo(t,'IntProp'),nfoGreater,VAL_1); + + t.IntProp := 0; + Check( x.Evaluate(t) = False ,'False'); + finally + x.Free(); + t.Free(); + end; +end; + +{ TRttiFilterCreator_Test } + +procedure TRttiFilterCreator_Test.Creation(); +var + x : TRttiFilterCreator; +begin + x := TRttiFilterCreator.Create(TClass_A); + try + CheckNull(x.Root,'Root <> nil'); + Check(( x.TargetClass = TClass_A ), 'TargetClass'); + finally + x.Free(); + end; +end; + +procedure Display(const AMsg : string); +begin + {$IFDEF DBG_DISPLAY} + Write(AMsg); + {$ENDIF} +end; + +type TPrintProc = procedure(const AMsg : string); +procedure PrintTree( + ATree : TRttiExpNodeItem; + APrintProc : TPrintProc; + const AIndent : Integer +); +begin + if Assigned(ATree) then begin + if ATree.InheritsFrom(TRttiExpNode) then begin + APrintProc(StringOfChar('-',AIndent)); + APrintProc(GetEnumName(TypeInfo(TFilterConnector),Ord(TRttiExpNode(ATree).Connector)) + #10#13); + PrintTree(TRttiExpNode(ATree).Left,APrintProc,AIndent+2); + PrintTree(TRttiExpNode(ATree).Right,APrintProc,AIndent+2); + end else if ATree.InheritsFrom(TRttiExpConcreteNodeItem) then begin + APrintProc(StringOfChar('-',AIndent)); + if ATree.InheritsFrom(TRttiExpNumericNodeItem) then begin + APrintProc(TRttiExpConcreteNodeItem(ATree).PropInfo^.Name + ' ' + GetEnumName(TypeInfo(TNumericFilterOperator),Ord(TRttiExpNumericNodeItem(ATree).Operation)) ); + end else if ATree.InheritsFrom(TRttiExpStringNodeItem) then begin + APrintProc(TRttiExpConcreteNodeItem(ATree).PropInfo^.Name + ' ' + GetEnumName(TypeInfo(TStringFilterOperator),Ord(TRttiExpStringNodeItem(ATree).Operation)) ) + end; + if ATree.InheritsFrom(TRttiExpIntegerNodeItem) then + APrintProc(' ' + IntToStr(TRttiExpIntegerNodeItem(ATree).ComparedValue)) + else if ATree.InheritsFrom(TRttiExpAnsiStringNodeItem) then + APrintProc(' ' + QuotedStr(TRttiExpAnsiStringNodeItem(ATree).ComparedValue)); + APrintProc(#10#13); + end; + end; +end; + +procedure CompareTree(ATreeA,ATreeB : TRttiExpNodeItem); +begin + if ( ( ATreeA = nil ) and ( ATreeB <> nil ) ) or + ( ( ATreeB = nil ) and ( ATreeA <> nil ) ) + then begin + raise Exception.Create('not equal'); + end; + if ( ATreeA <> nil ) then begin + if ATreeA.ClassType <> ATreeB.ClassType then + raise Exception.Create('Class not equal'); + if ATreeA.InheritsFrom(TRttiExpNode) then begin + if TRttiExpNode(ATreeA).Connector <> + TRttiExpNode(ATreeB).Connector + then + raise Exception.Create('TRttiExpNode not equal'); + CompareTree(TRttiExpNode(ATreeA).Left,TRttiExpNode(ATreeB).Left); + CompareTree(TRttiExpNode(ATreeA).Right,TRttiExpNode(ATreeB).Right); + end else if ATreeA.InheritsFrom(TRttiExpConcreteNodeItem) then begin + if ATreeA.InheritsFrom(TRttiExpIntegerNodeItem) then begin + if TRttiExpIntegerNodeItem(ATreeA).Operation <> + TRttiExpIntegerNodeItem(ATreeB).Operation + then + raise Exception.Create('Operation not equal'); + + if TRttiExpIntegerNodeItem(ATreeA).ComparedValue <> + TRttiExpIntegerNodeItem(ATreeB).ComparedValue + then + raise Exception.Create('Value not equal'); + end else if ATreeA.InheritsFrom(TRttiExpStringNodeItem) then begin + if TRttiExpStringNodeItem(ATreeA).Operation <> + TRttiExpStringNodeItem(ATreeB).Operation + then + raise Exception.Create('Operation not equal'); + + if ATreeA.InheritsFrom(TRttiExpAnsiStringNodeItem) then begin + if TRttiExpAnsiStringNodeItem(ATreeA).ComparedValue <> + TRttiExpAnsiStringNodeItem(ATreeB).ComparedValue + then + raise Exception.Create('Value not equal'); + end else if ATreeA.InheritsFrom(TRttiExpWideStringNodeItem) then begin + if TRttiExpWideStringNodeItem(ATreeA).ComparedValue <> + TRttiExpWideStringNodeItem(ATreeB).ComparedValue + then + raise Exception.Create('Value not equal'); + end + end; + + end; + end; +end; + +procedure TRttiFilterCreator_Test.AddContion(); +const VAL_1 : Integer = 1210; VAL_2 : Integer = 1076; VAL_3 : Integer = 176; + VAL_4 : Integer = -176; +var + x : TRttiFilterCreator; + xin : TRttiExpIntegerNodeItem; + xn : TRttiExpNode; +begin + x := TRttiFilterCreator.Create(TClass_A); + try + x.AddCondition('IntProp',nfoGreater,VAL_1,fcOr); + CheckNotNull(x.Root,'Root'); + CheckNotNull(x.Root.Left,'Root.Left'); + CheckIs(x.Root.Left,TRttiExpIntegerNodeItem,'Root.Left'); + xin := x.Root.Left as TRttiExpIntegerNodeItem; + CheckEquals(VAL_1,xin.ComparedValue); + Check( ( xin.Operation = nfoGreater ), 'Operation'); + CheckNull(x.Root.Right,'Root.Right'); + Check( ( x.Root.Connector = fcOr ), 'Root.Connector'); + + x.AddCondition('IntProp',nfoLesser,VAL_2,fcAnd); + CheckNotNull(x.Root.Left,'Root.Left'); + CheckIs(x.Root.Left,TRttiExpIntegerNodeItem,'Root.Left'); + xin := x.Root.Left as TRttiExpIntegerNodeItem; + CheckEquals(VAL_1,xin.ComparedValue); + Check( ( xin.Operation = nfoGreater ), 'Operation'); + CheckNotNull(x.Root.Right,'Root.Right'); + Check( ( x.Root.Connector = fcAnd ), 'Root.Connector'); + CheckIs(x.Root.Right,TRttiExpIntegerNodeItem,'Root.Right'); + xin := x.Root.Right as TRttiExpIntegerNodeItem; + CheckEquals(VAL_2,xin.ComparedValue); + Check( ( xin.Operation = nfoLesser ), 'Operation'); + + x.AddCondition('IntProp',nfoEqual,VAL_3,fcOr); + CheckNotNull(x.Root.Left,'Root.Left'); + CheckIs(x.Root.Left,TRttiExpIntegerNodeItem,'Root.Left'); + xin := x.Root.Left as TRttiExpIntegerNodeItem; + CheckEquals(VAL_1,xin.ComparedValue); + Check( ( xin.Operation = nfoGreater ), 'Operation'); + CheckNotNull(x.Root.Right,'Root.Right'); + Check( ( x.Root.Connector = fcAnd ), 'Root.Connector'); + CheckIs(x.Root.Right,TRttiExpNode,'Root.Right'); + xn := x.Root.Right as TRttiExpNode; + CheckNotNull(xn.Left,'Root.Right.Left'); + CheckIs(xn.Left,TRttiExpIntegerNodeItem); + xin := xn.Left as TRttiExpIntegerNodeItem; + CheckEquals(VAL_2,xin.ComparedValue); + Check( ( xin.Operation = nfoLesser ), 'Operation'); + + CheckIs(xn.Right,TRttiExpIntegerNodeItem,'xn.Right'); + xin := xn.Right as TRttiExpIntegerNodeItem; + CheckEquals(VAL_3,xin.ComparedValue); + Check( ( xin.Operation = nfoEqual ), 'Operation'); + + x.AddCondition('IntProp',nfoEqual,VAL_4,fcAnd); + PrintTree(x.Root,@Display,2); + finally + x.Free(); + end; +end; + +procedure TRttiFilterCreator_Test.BeginEnd_Group(); +const VAL_1 : Integer = 1210; VAL_2 : Integer = 1076; VAL_3 : Integer = 176; + VAL_4 : Integer = -176; +var + x : TRttiFilterCreator; + xin : TRttiExpIntegerNodeItem; + xn : TRttiExpNode; +begin + x := TRttiFilterCreator.Create(TClass_A); + try + x.AddCondition('IntProp',nfoGreater,VAL_1,fcOr); + CheckNotNull(x.Root,'Root'); + CheckNotNull(x.Root.Left,'Root.Left'); + CheckIs(x.Root.Left,TRttiExpIntegerNodeItem,'Root.Left'); + xin := x.Root.Left as TRttiExpIntegerNodeItem; + CheckEquals(VAL_1,xin.ComparedValue); + Check( ( xin.Operation = nfoGreater ), 'Operation'); + CheckNull(x.Root.Right,'Root.Right'); + Check( ( x.Root.Connector = fcOr ), 'Root.Connector'); + + x.BeginGroup(fcOr); + CheckNotNull(x.Root.Left,'Root.Left'); + CheckIs(x.Root.Left,TRttiExpIntegerNodeItem,'Root.Left'); + xin := x.Root.Left as TRttiExpIntegerNodeItem; + CheckEquals(VAL_1,xin.ComparedValue); + Check( ( xin.Operation = nfoGreater ), 'Operation'); + + CheckNotNull(x.Root.Right,'Root.Right'); + Check( ( x.Root.Connector = fcOr ), 'Root.Connector'); + CheckIs(x.Root.Right,TRttiExpNode,'Root.Right'); + xn := x.Root.Right as TRttiExpNode; + CheckNull(xn.Left); + CheckNull(xn.Right); + + x.AddCondition('IntProp',nfoLesser,VAL_2,fcAnd); + CheckNotNull(x.Root.Left,'Root.Left'); + CheckIs(x.Root.Left,TRttiExpIntegerNodeItem,'Root.Left'); + xin := x.Root.Left as TRttiExpIntegerNodeItem; + CheckEquals(VAL_1,xin.ComparedValue); + Check( ( xin.Operation = nfoGreater ), 'Operation'); + + CheckNotNull(x.Root.Right,'Root.Right'); + Check( ( x.Root.Connector = fcOr ), 'Root.Connector'); + CheckIs(x.Root.Right,TRttiExpNode,'Root.Right'); + xn := x.Root.Right as TRttiExpNode; + CheckNotNull(xn.Left,'xn.Left'); + CheckNull(xn.Right,'xn.Right'); + Check( ( xn.Connector = fcAnd ), 'xn.Connector'); + CheckIs(xn.Left,TRttiExpIntegerNodeItem,'xn.Left'); + xin := xn.Left as TRttiExpIntegerNodeItem; + CheckEquals(VAL_2,xin.ComparedValue); + Check( ( xin.Operation = nfoLesser ), 'Operation'); + + x.AddCondition('IntProp',nfoEqual,VAL_3,fcAnd); + CheckNotNull(x.Root.Left,'Root.Left'); + CheckIs(x.Root.Left,TRttiExpIntegerNodeItem,'Root.Left'); + xin := x.Root.Left as TRttiExpIntegerNodeItem; + CheckEquals(VAL_1,xin.ComparedValue); + Check( ( xin.Operation = nfoGreater ), 'Operation'); + + CheckNotNull(x.Root.Right,'Root.Right'); + Check( ( x.Root.Connector = fcOr ), 'Root.Connector'); + CheckIs(x.Root.Right,TRttiExpNode,'Root.Right'); + xn := x.Root.Right as TRttiExpNode; + CheckNotNull(xn.Left,'xn.Left'); + CheckNotNull(xn.Right,'xn.Right'); + Check( ( xn.Connector = fcAnd ), 'xn.Connector'); + CheckIs(xn.Left,TRttiExpIntegerNodeItem,'xn.Left'); + xin := xn.Left as TRttiExpIntegerNodeItem; + CheckEquals(VAL_2,xin.ComparedValue); + Check( ( xin.Operation = nfoLesser ), 'Operation'); + + CheckIs(xn.Right,TRttiExpIntegerNodeItem,'xn.Right'); + xin := xn.Right as TRttiExpIntegerNodeItem; + CheckEquals(VAL_3,xin.ComparedValue); + Check( ( xin.Operation = nfoEqual ), 'Operation'); + + x.EndGroup(); + x.AddCondition('IntProp',nfoEqual,VAL_4,fcOr); + PrintTree(x.Root,@Display,2); + + Display(#10#13); + Display(#10#13); + x.Clear(clrFreeObjects); + x.BeginGroup(fcAnd); + x.AddCondition('IntProp',nfoLesser,VAL_1,fcAnd); + x.BeginGroup(fcOr); + x.AddCondition('IntProp',nfoEqual,VAL_2,fcAnd); + x.AddCondition('IntProp',nfoEqual,VAL_3,fcAnd); + x.EndGroup(); + x.AddCondition('IntProp',nfoEqual,VAL_2,fcOr); + x.EndGroup(); + x.AddCondition('IntProp',nfoGreater,VAL_4,fcAnd); + PrintTree(x.Root,@Display,2); + finally + x.Free(); + end; +end; + + +{ TRttiExpAnsiStringNodeItem_Test } + +procedure TRttiExpAnsiStringNodeItem_Test.Create_Test(); +var + x : TRttiExpAnsiStringNodeItem; +begin + x := nil; + try + try + x := TRttiExpAnsiStringNodeItem.Create(GetPropInfo(TClass_A,'IntProp'),sfoEqualCaseInsensitive,'Azerty'); + Check(False); + except + on e : EAssertionFailedError do + raise; + on e : ERttiFilterException do begin + // nothing! + end; + end; + finally + x.Free(); + end; +end; + +procedure TRttiExpAnsiStringNodeItem_Test.Evaluate_EqualCaseSensitive(); +const VAL_1 = 'AzertY'; +var + x : TRttiExpAnsiStringNodeItem; + t : TClass_A; +begin + x := nil; + t := TClass_A.Create(); + try + x := TRttiExpAnsiStringNodeItem.Create(GetPropInfo(t,'StrProp'),sfoEqualCaseSensitive,VAL_1); + + t.StrProp := 'aaadddd'; + Check( x.Evaluate(t) = False ,'False'); + + t.StrProp := UpperCase(VAL_1); + Check( x.Evaluate(t) = False ,'False'); + + t.StrProp := LowerCase(VAL_1); + Check( x.Evaluate(t) = False ,'False'); + + t.StrProp := VAL_1; + Check( x.Evaluate(t) = True, 'True' ); + finally + x.Free(); + t.Free(); + end; +end; + +procedure TRttiExpAnsiStringNodeItem_Test.Evaluate_EqualCaseInsensitive(); +const VAL_1 = 'AzertY'; +var + x : TRttiExpAnsiStringNodeItem; + t : TClass_A; +begin + x := nil; + t := TClass_A.Create(); + try + x := TRttiExpAnsiStringNodeItem.Create(GetPropInfo(t,'StrProp'),sfoEqualCaseInsensitive,VAL_1); + + t.StrProp := 'aaadddd'; + Check( x.Evaluate(t) = False ,'False'); + + t.StrProp := UpperCase(VAL_1); + Check( x.Evaluate(t) = True ,'True'); + + t.StrProp := LowerCase(VAL_1); + Check( x.Evaluate(t) = True ,'True'); + + t.StrProp := VAL_1; + Check( x.Evaluate(t) = True, 'True' ); + finally + x.Free(); + t.Free(); + end; +end; + +{ TRttiExpwWideStringNodeItem_Test } + +procedure TRttiExpwWideStringNodeItem_Test.Create_Test(); +var + x : TRttiExpWideStringNodeItem; +begin + x := nil; + try + try + x := TRttiExpWideStringNodeItem.Create(GetPropInfo(TClass_A,'IntProp'),sfoEqualCaseInsensitive,'Azerty'); + Check(False); + except + on e : EAssertionFailedError do + raise; + on e : ERttiFilterException do begin + // nothing! + end; + end; + finally + x.Free(); + end; +end; + +procedure TRttiExpwWideStringNodeItem_Test.Evaluate_EqualCaseSensitive(); +const VAL_1 = 'AzertY'; +var + x : TRttiExpWideStringNodeItem; + t : TClass_A; +begin + x := nil; + t := TClass_A.Create(); + try + x := TRttiExpWideStringNodeItem.Create(GetPropInfo(t,'WideStrProp'),sfoEqualCaseSensitive,VAL_1); + + t.WideStrProp := 'aaadddd'; + Check( x.Evaluate(t) = False ,'False'); + + t.WideStrProp := UpperCase(VAL_1); + Check( x.Evaluate(t) = False ,'False'); + + t.WideStrProp := LowerCase(VAL_1); + Check( x.Evaluate(t) = False ,'False'); + + t.WideStrProp := VAL_1; + Check( x.Evaluate(t) = True, 'True' ); + finally + x.Free(); + t.Free(); + end; +end; + +procedure TRttiExpwWideStringNodeItem_Test.Evaluate_EqualCaseInsensitive(); +const VAL_1 = 'AzertY'; +var + x : TRttiExpWideStringNodeItem; + t : TClass_A; +begin + x := nil; + t := TClass_A.Create(); + try + x := TRttiExpWideStringNodeItem.Create(GetPropInfo(t,'WideStrProp'),sfoEqualCaseInsensitive,VAL_1); + + t.WideStrProp := 'aaadddd'; + Check( x.Evaluate(t) = False ,'False'); + + t.WideStrProp := UpperCase(VAL_1); + Check( x.Evaluate(t) = True ,'True'); + + t.WideStrProp := LowerCase(VAL_1); + Check( x.Evaluate(t) = True ,'True'); + + t.WideStrProp := VAL_1; + Check( x.Evaluate(t) = True, 'True' ); + finally + x.Free(); + t.Free(); + end; +end; + + +{ TRttiParser_Test } + +procedure TRttiParser_Test.SimpleBoolParsing(); +const VAL_1 : Boolean = False; +var + x : TRttiFilterCreator; + xN : TRttiExpEnumNodeItem; +begin + x := TRttiFilterCreator.Create(TClass_A); + try + ParseFilter(Format('EnumProp = %s',[GetEnumName(TypeInfo(TSampleEnum),Ord(VAL_1))]),x); + CheckNotNull(x.Root,'Root <> nil'); + CheckIs(x.Root.Left,TRttiExpEnumNodeItem); + xN := x.Root.Left as TRttiExpEnumNodeItem; + CheckEquals('EnumProp',xN.PropInfo^.Name); + CheckEquals(Ord(VAL_1),xN.ComparedValue); + finally + x.Free(); + end; +end; + +procedure TRttiParser_Test.SimpleEnumParsing(); +const VAL_1 : TSampleEnum = SampleEnum_C; +var + x : TRttiFilterCreator; + xN : TRttiExpEnumNodeItem; +begin + x := TRttiFilterCreator.Create(TClass_A); + try + ParseFilter(Format('EnumProp = %s',[GetEnumName(TypeInfo(TSampleEnum),Ord(VAL_1))]),x); + CheckNotNull(x.Root,'Root <> nil'); + CheckIs(x.Root.Left,TRttiExpEnumNodeItem); + xN := x.Root.Left as TRttiExpEnumNodeItem; + CheckEquals('EnumProp',xN.PropInfo^.Name); + CheckEquals(Ord(VAL_1),xN.ComparedValue); + finally + x.Free(); + end; +end; + +procedure TRttiParser_Test.operator_equal_string(); +const VAL_1 = 'inoussa'; +var + x : TRttiFilterCreator; + sN : TRttiExpAnsiStringNodeItem; +begin + x := TRttiFilterCreator.Create(TClass_A); + try + ParseFilter(Format('StrProp = %s',[QuotedStr(VAL_1)]),x); + CheckNotNull(x.Root,'Root <> nil'); + CheckIs(x.Root.Left,TRttiExpAnsiStringNodeItem); + sN := x.Root.Left as TRttiExpAnsiStringNodeItem; + CheckEquals('StrProp',sN.PropInfo^.Name); + CheckEquals(VAL_1,sN.ComparedValue); + CheckEquals(Ord(sfoEqualCaseInsensitive),Ord(sN.Operation),'Operation'); + finally + x.Free(); + end; +end; + +procedure TRttiParser_Test.operator_not_equal_string(); +const VAL_1 = 'inoussa'; +var + x : TRttiFilterCreator; + sN : TRttiExpAnsiStringNodeItem; +begin + x := TRttiFilterCreator.Create(TClass_A); + try + ParseFilter(Format('StrProp <> %s',[QuotedStr(VAL_1)]),x); + CheckNotNull(x.Root,'Root <> nil'); + CheckIs(x.Root.Left,TRttiExpAnsiStringNodeItem); + sN := x.Root.Left as TRttiExpAnsiStringNodeItem; + CheckEquals('StrProp',sN.PropInfo^.Name); + CheckEquals(VAL_1,sN.ComparedValue); + CheckEquals(Ord(sfoNotEqual),Ord(sN.Operation),'Operation'); + finally + x.Free(); + end; +end; + +procedure TRttiParser_Test.operator_equal_int(); +const VAL_1 = 1210; +var + x : TRttiFilterCreator; + sN : TRttiExpIntegerNodeItem; +begin + x := TRttiFilterCreator.Create(TClass_A); + try + ParseFilter(Format('IntProp = %d',[VAL_1]),x); + CheckNotNull(x.Root,'Root <> nil'); + CheckIs(x.Root.Left,TRttiExpIntegerNodeItem); + sN := x.Root.Left as TRttiExpIntegerNodeItem; + CheckEquals('IntProp',sN.PropInfo^.Name); + CheckEquals(VAL_1,sN.ComparedValue); + CheckEquals(Ord(nfoEqual),Ord(sN.Operation),'Operation'); + finally + x.Free(); + end; +end; + +procedure TRttiParser_Test.operator_not_equal_int(); +const VAL_1 = 1210; +var + x : TRttiFilterCreator; + sN : TRttiExpIntegerNodeItem; +begin + x := TRttiFilterCreator.Create(TClass_A); + try + ParseFilter(Format('IntProp <> %d',[VAL_1]),x); + CheckNotNull(x.Root,'Root <> nil'); + CheckIs(x.Root.Left,TRttiExpIntegerNodeItem); + sN := x.Root.Left as TRttiExpIntegerNodeItem; + CheckEquals('IntProp',sN.PropInfo^.Name); + CheckEquals(VAL_1,sN.ComparedValue); + CheckEquals(Ord(nfoNotEqual),Ord(sN.Operation),'Operation'); + finally + x.Free(); + end; +end; + +procedure TRttiParser_Test.operator_greater_or_equal_int(); +const VAL_1 = 1210; +var + x : TRttiFilterCreator; + sN : TRttiExpIntegerNodeItem; +begin + x := TRttiFilterCreator.Create(TClass_A); + try + ParseFilter(Format('IntProp >= %d',[VAL_1]),x); + CheckNotNull(x.Root,'Root <> nil'); + CheckIs(x.Root.Left,TRttiExpIntegerNodeItem); + sN := x.Root.Left as TRttiExpIntegerNodeItem; + CheckEquals('IntProp',sN.PropInfo^.Name); + CheckEquals(VAL_1,sN.ComparedValue); + CheckEquals(Ord(nfoGreaterOrEqual),Ord(sN.Operation),'Operation'); + finally + x.Free(); + end; +end; + +procedure TRttiParser_Test.operator_lesser_or_equal_int(); +const VAL_1 = 1210; +var + x : TRttiFilterCreator; + sN : TRttiExpIntegerNodeItem; +begin + x := TRttiFilterCreator.Create(TClass_A); + try + ParseFilter(Format('IntProp <= %d',[VAL_1]),x); + CheckNotNull(x.Root,'Root <> nil'); + CheckIs(x.Root.Left,TRttiExpIntegerNodeItem); + sN := x.Root.Left as TRttiExpIntegerNodeItem; + CheckEquals('IntProp',sN.PropInfo^.Name); + CheckEquals(VAL_1,sN.ComparedValue); + CheckEquals(Ord(nfoLesserOrEqual),Ord(sN.Operation),'Operation'); + finally + x.Free(); + end; +end; + +procedure TRttiParser_Test.operator_equal_enum(); +const VAL_1 = SampleEnum_B; +var + x : TRttiFilterCreator; + sN : TRttiExpEnumNodeItem; +begin + x := TRttiFilterCreator.Create(TClass_A); + try + ParseFilter(Format('EnumProp = %s',[GetEnumName(TypeInfo(TSampleEnum),Ord(VAL_1))]),x); + CheckNotNull(x.Root,'Root <> nil'); + CheckIs(x.Root.Left,TRttiExpEnumNodeItem); + sN := x.Root.Left as TRttiExpEnumNodeItem; + CheckEquals('EnumProp',sN.PropInfo^.Name); + CheckEquals(Ord(VAL_1),Ord(sN.ComparedValue)); + CheckEquals(Ord(nfoEqual),Ord(sN.Operation),'Operation'); + finally + x.Free(); + end; +end; + +procedure TRttiParser_Test.operator_not_equal_enum(); +const VAL_1 = SampleEnum_B; +var + x : TRttiFilterCreator; + sN : TRttiExpEnumNodeItem; +begin + x := TRttiFilterCreator.Create(TClass_A); + try + ParseFilter(Format('EnumProp <> %s',[GetEnumName(TypeInfo(TSampleEnum),Ord(VAL_1))]),x); + CheckNotNull(x.Root,'Root <> nil'); + CheckIs(x.Root.Left,TRttiExpEnumNodeItem); + sN := x.Root.Left as TRttiExpEnumNodeItem; + CheckEquals('EnumProp',sN.PropInfo^.Name); + CheckEquals(Ord(VAL_1),Ord(sN.ComparedValue)); + CheckEquals(Ord(nfoNotEqual),Ord(sN.Operation),'Operation'); + finally + x.Free(); + end; +end; + +procedure TRttiParser_Test.operator_greater_or_equal_enum(); +const VAL_1 = SampleEnum_B; +var + x : TRttiFilterCreator; + sN : TRttiExpEnumNodeItem; +begin + x := TRttiFilterCreator.Create(TClass_A); + try + ParseFilter(Format('EnumProp >= %s',[GetEnumName(TypeInfo(TSampleEnum),Ord(VAL_1))]),x); + CheckNotNull(x.Root,'Root <> nil'); + CheckIs(x.Root.Left,TRttiExpEnumNodeItem); + sN := x.Root.Left as TRttiExpEnumNodeItem; + CheckEquals('EnumProp',sN.PropInfo^.Name); + CheckEquals(Ord(VAL_1),Ord(sN.ComparedValue)); + CheckEquals(Ord(nfoGreaterOrEqual),Ord(sN.Operation),'Operation'); + finally + x.Free(); + end; +end; + +procedure TRttiParser_Test.operator_lesser_or_equal_enum(); +const VAL_1 = SampleEnum_B; +var + x : TRttiFilterCreator; + sN : TRttiExpEnumNodeItem; +begin + x := TRttiFilterCreator.Create(TClass_A); + try + ParseFilter(Format('EnumProp <= %s',[GetEnumName(TypeInfo(TSampleEnum),Ord(VAL_1))]),x); + CheckNotNull(x.Root,'Root <> nil'); + CheckIs(x.Root.Left,TRttiExpEnumNodeItem); + sN := x.Root.Left as TRttiExpEnumNodeItem; + CheckEquals('EnumProp',sN.PropInfo^.Name); + CheckEquals(Ord(VAL_1),Ord(sN.ComparedValue)); + CheckEquals(Ord(nfoLesserOrEqual),Ord(sN.Operation),'Operation'); + finally + x.Free(); + end; +end; + +procedure TRttiParser_Test.BeginEnd_Group(); +const VAL_1 : Integer = 1210; VAL_2 : Integer = 1076; VAL_3 : Integer = 176; + VAL_4 : Integer = -176; + VAL_S = 'inoussa'; +var + x, y : TRttiFilterCreator; + xin : TRttiExpIntegerNodeItem; + xn : TRttiExpNode; + sfltr : string; +begin + y := nil; + x := TRttiFilterCreator.Create(TClass_A); + try + sfltr := Format('IntProp > %d or ( IntProp < %d and StrProp = %s ) or IntProp = %d',[VAL_1,VAL_2,QuotedStr(VAL_S),VAL_4]); + ParseFilter(sfltr,x); + PrintTree(x.Root,@Display,2); + y := TRttiFilterCreator.Create(TClass_A); + y.AddCondition('IntProp',nfoGreater,VAL_1,fcOr); + y.BeginGroup(fcOr); + y.AddCondition('IntProp',nfoLesser,VAL_2,fcAnd); + y.AddCondition('StrProp',sfoEqualCaseInsensitive,VAL_S,fcAnd); + y.EndGroup(); + y.AddCondition('IntProp',nfoEqual,VAL_4,fcOr); + + CompareTree(x.Root,y.Root); + finally + x.Free(); + end; +end; + + +{ TRttiExpEnumNodeItem_Test } + +procedure TRttiExpEnumNodeItem_Test.Create_Test(); +var + x : TRttiExpEnumNodeItem; +begin + x := nil; + try + try + x := TRttiExpEnumNodeItem.Create(GetPropInfo(TClass_A,'StrProp'),nfoEqual,'SampleEnum_A'); + Check(False); + except + on e : EAssertionFailedError do + raise; + on e : ERttiFilterException do begin + // nothing! + end; + end; + finally + x.Free(); + end; +end; + +procedure TRttiExpEnumNodeItem_Test.Evaluate_Equal(); +const VAL_1 : TSampleEnum = SampleEnum_C; +var + x : TRttiExpEnumNodeItem; + t : TClass_A; +begin + x := nil; + t := TClass_A.Create(); + try + x := TRttiExpEnumNodeItem.Create(GetPropInfo(t,'EnumProp'),nfoEqual,GetEnumName(TypeInfo(TSampleEnum),Ord(VAL_1))); + + t.EnumProp := SampleEnum_D; + Check( x.Evaluate(t) = False ,'False'); + + t.EnumProp := VAL_1; + Check( x.Evaluate(t) = True, 'True' ); + finally + x.Free(); + t.Free(); + end; +end; + +procedure TRttiExpEnumNodeItem_Test.Evaluate_Equal_bool(); +var + x : TRttiExpEnumNodeItem; + t : TClass_A; + v : Boolean; +begin + x := nil; + t := TClass_A.Create(); + try + v := False; + x := TRttiExpEnumNodeItem.Create(GetPropInfo(t,'BoolProp'),nfoEqual,'False'); + t.BoolProp := True; + Check( x.Evaluate(t) = False ,'False'); + t.BoolProp := False; + Check( x.Evaluate(t) = True, 'True' ); + + FreeAndNil(x); + v := True; + x := TRttiExpEnumNodeItem.Create(GetPropInfo(t,'BoolProp'),nfoEqual,'True'); + t.BoolProp := True; + Check( x.Evaluate(t) = True ,'True'); + t.BoolProp := False; + Check( x.Evaluate(t) = False, 'False' ); + finally + x.Free(); + t.Free(); + end; +end; + +procedure TRttiExpEnumNodeItem_Test.Evaluate_Lesser(); +const VAL_1 : TSampleEnum = SampleEnum_C; +var + x : TRttiExpEnumNodeItem; + t : TClass_A; +begin + x := nil; + t := TClass_A.Create(); + try + x := TRttiExpEnumNodeItem.Create(GetPropInfo(t,'EnumProp'),nfoLesser,GetEnumName(TypeInfo(TSampleEnum),Ord(VAL_1))); + + t.EnumProp := SampleEnum_D; + Check( x.Evaluate(t) = False ,'False'); + + t.EnumProp := SampleEnum_B; + Check( x.Evaluate(t) = True, 'True' ); + finally + x.Free(); + t.Free(); + end; +end; + +procedure TRttiExpEnumNodeItem_Test.Evaluate_Greater(); +const VAL_1 : TSampleEnum = SampleEnum_C; +var + x : TRttiExpEnumNodeItem; + t : TClass_A; +begin + x := nil; + t := TClass_A.Create(); + try + x := TRttiExpEnumNodeItem.Create(GetPropInfo(t,'EnumProp'),nfoGreater,GetEnumName(TypeInfo(TSampleEnum),Ord(VAL_1))); + + t.EnumProp := SampleEnum_A; + Check( x.Evaluate(t) = False ,'False'); + + t.EnumProp := SampleEnum_D; + Check( x.Evaluate(t) = True, 'True' ); + finally + x.Free(); + t.Free(); + end; +end; + +Initialization + RegisterTest('Cursors',TRttiExpIntegerNodeItem_Test.Suite); + RegisterTest('Cursors',TRttiExpEnumNodeItem_Test.Suite); + RegisterTest('Cursors',TRttiExpAnsiStringNodeItem_Test.Suite); + RegisterTest('Cursors',TRttiExpwWideStringNodeItem_Test.Suite); + RegisterTest('Cursors',TRttiExpNode_Test.Suite); + RegisterTest('Cursors',TRttiFilterCreator_Test.Suite); + RegisterTest('Cursors',TRttiParser_Test.Suite); + +end. diff --git a/wst/trunk/tests/test_suite/test_std_cursors.pas b/wst/trunk/tests/test_suite/test_std_cursors.pas new file mode 100644 index 000000000..9a8cffa93 --- /dev/null +++ b/wst/trunk/tests/test_suite/test_std_cursors.pas @@ -0,0 +1,270 @@ +{$INCLUDE wst_global.inc} +unit test_std_cursors; + +interface + +uses + Classes, SysUtils, Contnrs, +{$IFDEF FPC} + fpcunit, testutils, testregistry, +{$ELSE} + TestFrameWork, +{$ENDIF} + cursor_intf, std_cursors, rtti_filters; + +{$INCLUDE wst.inc} +{$INCLUDE wst_delphi.inc} + +type + + { TClass_A } + + TClass_A = class(TPersistent) + private + FIntProp: Integer; + public + constructor Create(AIntProp : Integer); + published + property IntProp : Integer read FIntProp; + end; + + { TClass_B } + + TClass_B = class(TClass_A) + private + FIntProp_A: Integer; + FIntProp_B: Integer; + public + constructor Create(AIntProp,AIntProp_A,AIntProp_B : Integer); + published + property IntProp_A : Integer read FIntProp_A; + property IntProp_B : Integer read FIntProp_B; + end; + + { TObjectListCursor_Test } + + TObjectListCursor_Test = class(TTestCase) + published + procedure All(); + procedure GetCount(); + end; + + { TObjectListFilterableCursor_Test } + + TObjectListFilterableCursor_Test = class(TTestCase) + published + procedure All(); + end; + +implementation + +{ TClass_A } + +constructor TClass_A.Create(AIntProp: Integer); +begin + FIntProp := AIntProp; +end; + +{ TObjectListCursor_Test } + +procedure TObjectListCursor_Test.All(); +const O_COUNT = 100; +var + x : IObjectCursor; + ls : TObjectList; + c, i : Integer; +begin + ls := TObjectList.Create(True); + try + x := TObjectListCursor.Create(ls); + x.Reset(); + CheckEquals(False,x.MoveNext()); + x.Reset(); + CheckEquals(False,x.MoveNext()); + CheckEquals(False,x.MoveNext()); + try + x.GetCurrent(); + Check(False); + except + on e : ECursorException do begin + // GOOD + end; + end; + + ls.Add(TClass_A.Create(0)); + x.Reset(); + CheckEquals(True,x.MoveNext()); + CheckSame(ls[0],x.GetCurrent()); + CheckEquals(False,x.MoveNext()); + try + x.GetCurrent(); + Check(False); + except + on e : ECursorException do begin + // GOOD + end; + end; + x.Reset(); + CheckEquals(True,x.MoveNext()); + CheckSame(ls[0],x.GetCurrent()); + CheckEquals(False,x.MoveNext()); + + ls.Clear(); + for i := 0 to Pred(O_COUNT) do + ls.Add(TClass_A.Create(i)); + x.Reset(); + for i := 0 to Pred(O_COUNT) do begin + CheckEquals(True,x.MoveNext()); + CheckSame(ls[i],x.GetCurrent()); + end; + CheckEquals(False,x.MoveNext()); + x.Reset(); + for i := 0 to Pred(O_COUNT) do begin + CheckEquals(True,x.MoveNext()); + CheckSame(ls[i],x.GetCurrent()); + end; + finally + ls.Free(); + end; +end; + +procedure TObjectListCursor_Test.GetCount(); +const O_COUNT = 100; +var + x : IObjectCursor; + ls : TObjectList; + c, i : Integer; +begin + ls := TObjectList.Create(True); + try + x := TObjectListCursor.Create(ls); + CheckEquals(ls.Count,x.GetCount()); + ls.Add(TClass_A.Create(0)); + CheckEquals(ls.Count,x.GetCount()); + + ls.Clear(); + CheckEquals(ls.Count,x.GetCount()); + for i := 0 to Pred(O_COUNT) do + ls.Add(TClass_A.Create(i)); + x.Reset(); + CheckEquals(ls.Count,x.GetCount()); + for i := 0 to Pred(O_COUNT) do begin + CheckEquals(True,x.MoveNext()); + CheckEquals(ls.Count,x.GetCount()); + end; + CheckEquals(ls.Count,x.GetCount()); + finally + ls.Free(); + end; +end; + + +{ TClass_B } + +constructor TClass_B.Create(AIntProp, AIntProp_A, AIntProp_B: Integer); +begin + inherited Create(AIntProp); + FIntProp_A := AIntProp_A; + FIntProp_B := AIntProp_B; +end; + +{ TObjectListFilterableCursor_Test } + +procedure TObjectListFilterableCursor_Test.All(); +const O_COUNT = 100; +var + x : IFilterableObjectCursor; + ls : TObjectList; + c, i : Integer; + f : IObjectFilter; + fcr : TRttiFilterCreator; +begin + fcr := nil; + ls := TObjectList.Create(True); + try + x := TObjectListFilterableCursor.Create(ls); + CheckNull(x.GetFilter()); + x.Reset(); + CheckEquals(False,x.MoveNext()); + x.Reset(); + CheckEquals(False,x.MoveNext()); + CheckEquals(False,x.MoveNext()); + try + x.GetCurrent(); + Check(False); + except + on e : ECursorException do begin + // GOOD + end; + end; + + ls.Add(TClass_A.Create(0)); + x.Reset(); + CheckEquals(True,x.MoveNext()); + CheckSame(ls[0],x.GetCurrent()); + CheckEquals(False,x.MoveNext()); + try + x.GetCurrent(); + Check(False); + except + on e : ECursorException do begin + // GOOD + end; + end; + x.Reset(); + CheckEquals(True,x.MoveNext()); + CheckSame(ls[0],x.GetCurrent()); + CheckEquals(False,x.MoveNext()); + + ls.Clear(); + for i := 0 to Pred(O_COUNT) do + ls.Add(TClass_A.Create(i)); + x.Reset(); + for i := 0 to Pred(O_COUNT) do begin + CheckEquals(True,x.MoveNext()); + CheckSame(ls[i],x.GetCurrent()); + end; + CheckEquals(False,x.MoveNext()); + x.Reset(); + for i := 0 to Pred(O_COUNT) do begin + CheckEquals(True,x.MoveNext()); + CheckSame(ls[i],x.GetCurrent()); + end; + + ls.Clear(); + for i := 0 to Pred(O_COUNT) do + ls.Add(TClass_B.Create(i,( i mod 10 ), ( i mod ( ( i + 1 ) * 2 ) ) )); + + fcr := TRttiFilterCreator.Create(TClass_B); + fcr.AddCondition('IntProp',nfoEqual,-1,fcOr);// + f := TRttiObjectFilter.Create(fcr.Root,clrFreeObjects) as IObjectFilter; + x.SetFilter(f); + Check(x.GetFilter()=f); + x.SetFilter(nil); + CheckNull(x.GetFilter()); + x.SetFilter(f); + Check(x.GetFilter()=f); + x.Reset(); + CheckEquals(False,x.MoveNext()); + + fcr.AddCondition('IntProp',nfoGreater,-1,fcOr); + x.Reset(); + CheckEquals(True,x.MoveNext()); + + x.Reset(); + for i := 0 to Pred(O_COUNT) do begin + CheckEquals(True,x.MoveNext()); + CheckSame(ls[i],x.GetCurrent()); + end; + + finally + ls.Free(); + fcr.Free(); + end; +end; + +Initialization + RegisterTest('Cursors',TObjectListCursor_Test.Suite); + RegisterTest('Cursors',TObjectListFilterableCursor_Test.Suite); + +end. diff --git a/wst/trunk/tests/test_suite/test_wst_cursors.pas b/wst/trunk/tests/test_suite/test_wst_cursors.pas new file mode 100644 index 000000000..5a4ab0e15 --- /dev/null +++ b/wst/trunk/tests/test_suite/test_wst_cursors.pas @@ -0,0 +1,354 @@ +{$INCLUDE wst_global.inc} +unit test_wst_cursors; + +interface + +uses + Classes, SysUtils, Contnrs, +{$IFDEF FPC} + fpcunit, testutils, testregistry, +{$ELSE} + TestFrameWork, +{$ENDIF} + cursor_intf, wst_cursors, rtti_filters, base_service_intf; + +{$INCLUDE wst.inc} +{$INCLUDE wst_delphi.inc} + +type + + { TClass_A } + + TClass_A = class(TBaseRemotable) + private + FIntProp: Integer; + public + constructor Create(AIntProp : Integer); + published + property IntProp : Integer read FIntProp; + end; + + { TTClass_A_ArrayRemotable } + + TTClass_A_ArrayRemotable = class(TBaseObjectArrayRemotable) + public + class function GetItemClass():TBaseRemotableClass;override; + end; + + { TClass_B } + + TClass_B = class(TClass_A) + private + FIntProp_A: Integer; + FIntProp_B: Integer; + public + constructor Create(AIntProp,AIntProp_A,AIntProp_B : Integer); + published + property IntProp_A : Integer read FIntProp_A; + property IntProp_B : Integer read FIntProp_B; + end; + + { TTClass_B_ArrayRemotable } + + TTClass_B_ArrayRemotable = class(TBaseObjectArrayRemotable) + public + class function GetItemClass():TBaseRemotableClass;override; + end; + + { TBaseObjectArrayRemotableCursor_Test } + + TBaseObjectArrayRemotableCursor_Test = class(TTestCase) + published + procedure All(); + end; + + { TBaseObjectArrayRemotableFilterableCursor_Test } + + TBaseObjectArrayRemotableFilterableCursor_Test = class(TTestCase) + published + procedure All(); + end; + + { TUtilsProcs_Test } + + TUtilsProcs_Test = class(TTestCase) + published + procedure test_Find(); + procedure test_Filter(); + end; + +implementation + +{ TClass_A } + +constructor TClass_A.Create(AIntProp: Integer); +begin + FIntProp := AIntProp; +end; + +{ TBaseObjectArrayRemotableCursor_Test } + +procedure TBaseObjectArrayRemotableCursor_Test.All(); +const O_COUNT = 100; +var + x : IObjectCursor; + ls : TBaseObjectArrayRemotable; + c, i : Integer; +begin + ls := TTClass_A_ArrayRemotable.Create(); + try + x := TBaseObjectArrayRemotableCursor.Create(ls); + x.Reset(); + CheckEquals(False,x.MoveNext()); + x.Reset(); + CheckEquals(False,x.MoveNext()); + CheckEquals(False,x.MoveNext()); + try + x.GetCurrent(); + Check(False); + except + on e : ECursorException do begin + // GOOD + end; + end; + + ls.SetLength(1); + x.Reset(); + CheckEquals(True,x.MoveNext()); + CheckSame(ls[0],x.GetCurrent()); + CheckEquals(False,x.MoveNext()); + try + x.GetCurrent(); + Check(False); + except + on e : ECursorException do begin + // GOOD + end; + end; + x.Reset(); + CheckEquals(True,x.MoveNext()); + CheckSame(ls[0],x.GetCurrent()); + CheckEquals(False,x.MoveNext()); + + ls.SetLength(O_COUNT); + for i := 0 to Pred(O_COUNT) do + TClass_A(ls[i]).FIntProp := i; + x.Reset(); + for i := 0 to Pred(O_COUNT) do begin + CheckEquals(True,x.MoveNext()); + CheckSame(ls[i],x.GetCurrent()); + end; + CheckEquals(False,x.MoveNext()); + x.Reset(); + for i := 0 to Pred(O_COUNT) do begin + CheckEquals(True,x.MoveNext()); + CheckSame(ls[i],x.GetCurrent()); + end; + finally + ls.Free(); + end; +end; + + +{ TClass_B } + +constructor TClass_B.Create(AIntProp, AIntProp_A, AIntProp_B: Integer); +begin + inherited Create(AIntProp); + FIntProp_A := AIntProp_A; + FIntProp_B := AIntProp_B; +end; + +{ TBaseObjectArrayRemotableFilterableCursor_Test } + +procedure TBaseObjectArrayRemotableFilterableCursor_Test.All(); +const O_COUNT = 100; +var + x : IFilterableObjectCursor; + ls : TBaseObjectArrayRemotable; + c, i : Integer; + f : IObjectFilter; + fcr : TRttiFilterCreator; +begin + fcr := nil; + ls := TTClass_A_ArrayRemotable.Create(); + try + x := TBaseObjectArrayRemotableFilterableCursor.Create(ls); + CheckNull(x.GetFilter()); + x.Reset(); + CheckEquals(False,x.MoveNext()); + x.Reset(); + CheckEquals(False,x.MoveNext()); + CheckEquals(False,x.MoveNext()); + try + x.GetCurrent(); + Check(False); + except + on e : ECursorException do begin + // GOOD + end; + end; + + ls.SetLength(1); + x.Reset(); + CheckEquals(True,x.MoveNext()); + CheckSame(ls[0],x.GetCurrent()); + CheckEquals(False,x.MoveNext()); + try + x.GetCurrent(); + Check(False); + except + on e : ECursorException do begin + // GOOD + end; + end; + x.Reset(); + CheckEquals(True,x.MoveNext()); + CheckSame(ls[0],x.GetCurrent()); + CheckEquals(False,x.MoveNext()); + + ls.SetLength(O_COUNT); + for i := 0 to Pred(O_COUNT) do + TClass_A(ls[i]).FIntProp := i; + x.Reset(); + for i := 0 to Pred(O_COUNT) do begin + CheckEquals(True,x.MoveNext()); + CheckSame(ls[i],x.GetCurrent()); + end; + CheckEquals(False,x.MoveNext()); + x.Reset(); + for i := 0 to Pred(O_COUNT) do begin + CheckEquals(True,x.MoveNext()); + CheckSame(ls[i],x.GetCurrent()); + end; + + FreeAndNil(ls); + ls := TTClass_B_ArrayRemotable.Create(); + x := TBaseObjectArrayRemotableFilterableCursor.Create(ls); + ls.SetLength(O_COUNT); + for i := 0 to Pred(O_COUNT) do begin + TClass_B(ls[i]).FIntProp := i; + TClass_B(ls[i]).FIntProp_A := ( i mod 10 ); + TClass_B(ls[i]).FIntProp_B := ( i mod ( ( i + 1 ) * 2 ) ) ; + end; + + fcr := TRttiFilterCreator.Create(TClass_B); + fcr.AddCondition('IntProp',nfoEqual,-1,fcOr);// + f := TRttiObjectFilter.Create(fcr.Root,clrFreeObjects) as IObjectFilter; + //fcr.Clear(clrNone); + x.SetFilter(f); + Check(x.GetFilter()=f); + x.SetFilter(nil); + CheckNull(x.GetFilter()); + x.SetFilter(f); + Check(x.GetFilter()=f); + x.Reset(); + CheckEquals(False,x.MoveNext()); + + fcr.AddCondition('IntProp',nfoGreater,-1,fcOr); + x.Reset(); + CheckEquals(True,x.MoveNext()); + + x.Reset(); + for i := 0 to Pred(O_COUNT) do begin + CheckEquals(True,x.MoveNext()); + CheckSame(ls[i],x.GetCurrent()); + end; + + finally + ls.Free(); + fcr.Free(); + end; +end; + +{ TTClass_A_ArrayRemotable } + +class function TTClass_A_ArrayRemotable.GetItemClass() : TBaseRemotableClass; +begin + Result := TClass_A; +end; + +{ TTClass_B_ArrayRemotable } + +class function TTClass_B_ArrayRemotable.GetItemClass() : TBaseRemotableClass; +begin + Result := TClass_B; +end; + +{ TUtilsProcs_Test } + +procedure TUtilsProcs_Test.test_Find(); +const O_COUNT : PtrInt = 10; +var + ls : TTClass_A_ArrayRemotable; + i : PtrInt; +begin + ls := TTClass_A_ArrayRemotable.Create(); + try + CheckNull(Find(ls,'')); + CheckNull(Find(ls,'IntProp = 12')); + + ls.SetLength(1); + CheckSame(ls[0], Find(ls,'')); + CheckSame(ls[0], Find(ls,'IntProp = 0')); + CheckNull(Find(ls,'IntProp = 12')); + + ls.SetLength(O_COUNT); + for i := 0 to ( O_COUNT - 1 ) do + TClass_A(ls[i]).FIntProp := i; + CheckSame(ls[0], Find(ls,'')); + CheckSame(ls[0], Find(ls,'IntProp = 0')); + CheckNull(Find(ls,Format('IntProp = %d',[2*O_COUNT]))); + for i := 0 to ( O_COUNT - 1 ) do + CheckSame(ls[i],Find(ls,Format('IntProp = %d',[i]))); + finally + ls.Free(); + end; +end; + +procedure TUtilsProcs_Test.test_Filter(); +const O_COUNT : PtrInt = 10; +var + ls : TTClass_A_ArrayRemotable; + i : PtrInt; + crs : IObjectCursor; +begin + CheckNull(Filter(nil,''), 'filter(nil) = nil'); + ls := TTClass_A_ArrayRemotable.Create(); + try + crs := Filter(ls,''); + Check( ( crs <> nil ) ); + crs.Reset(); + Check(not crs.MoveNext()); + + ls.SetLength(O_COUNT); + for i := 0 to ( O_COUNT - 1 ) do + TClass_A(ls[i]).FIntProp := i; + crs := Filter(ls,''); + Check( ( crs <> nil ) ); + crs.Reset(); + for i := 0 to ( O_COUNT - 1 ) do begin + Check(crs.MoveNext()); + CheckSame(ls[i], crs.GetCurrent()); + end; + Check(not crs.MoveNext()); + + for i := 0 to ( O_COUNT - 1 ) do begin + crs := Filter(ls,Format('IntProp = %d',[i])); + Check( ( crs <> nil ) ); + crs.Reset(); + Check(crs.MoveNext()); + CheckSame(ls[i], crs.GetCurrent()); + Check(not crs.MoveNext()); + end; + finally + ls.Free(); + end; +end; + +initialization + RegisterTest('Cursors',TBaseObjectArrayRemotableCursor_Test.Suite); + RegisterTest('Cursors',TBaseObjectArrayRemotableFilterableCursor_Test.Suite); + RegisterTest('Cursors',TUtilsProcs_Test.Suite); + +end. diff --git a/wst/trunk/wst_rtti_filter/cursor_intf.pas b/wst/trunk/wst_rtti_filter/cursor_intf.pas index b63d340cb..0a1809f78 100644 --- a/wst/trunk/wst_rtti_filter/cursor_intf.pas +++ b/wst/trunk/wst_rtti_filter/cursor_intf.pas @@ -34,7 +34,9 @@ type ['{2B7756B1-E239-4B6F-A7A3-4B57B98FAD4F}'] procedure Reset(); function MoveNext() : Boolean; + //It is just the cursor that is cloned, the underliying datas are shared function Clone():ICursor; + function GetCount() : PtrInt; end; IObjectFilter = interface @@ -81,6 +83,7 @@ type function MoveNext() : Boolean; function Clone():ICursor; function GetCurrent() : TObject; + function GetCount() : PtrInt; function GetFilter() : IObjectFilter; function SetFilter(const AFilter : IObjectFilter) : IObjectFilter; public @@ -136,6 +139,22 @@ begin Result := FBaseCursor.GetCurrent(); end; +function TSimpleObjectFilterableCursor.GetCount() : PtrInt; +var + crs : ICursor; +begin + if ( FFilter = nil ) then begin + Result := FBaseCursor.GetCount(); + end else begin + crs := Self.Clone(); + crs.Reset(); + Result := 0; + while crs.MoveNext() do begin + Result := Result + 1; + end; + end; +end; + function TSimpleObjectFilterableCursor.GetFilter(): IObjectFilter; begin Result := FFilter; diff --git a/wst/trunk/wst_rtti_filter/dom_cursors.pas b/wst/trunk/wst_rtti_filter/dom_cursors.pas index a9f175c2e..766735cd3 100644 --- a/wst/trunk/wst_rtti_filter/dom_cursors.pas +++ b/wst/trunk/wst_rtti_filter/dom_cursors.pas @@ -53,6 +53,7 @@ type procedure Reset(); function MoveNext() : Boolean; function Clone():ICursor; + function GetCount() : PtrInt; function GetCurrent() : IDefaultItemType;virtual; public constructor Create( @@ -77,6 +78,7 @@ type procedure Reset(); function MoveNext() : Boolean; function Clone():ICursor; + function GetCount() : PtrInt; function GetCurrent() : IDefaultItemType; public constructor Create( @@ -116,6 +118,7 @@ type procedure Reset(); function MoveNext() : Boolean; function Clone():ICursor; + function GetCount() : PtrInt; function GetCurrent() : TObject;virtual; public constructor Create(ADataList : IDefaultTypedCursor); @@ -213,6 +216,11 @@ begin Result := TDOMNodeListCursor.Create(FList,faNone); end; +function TDOMNodeListCursor.GetCount() : PtrInt; +begin + Result := GetNodeListCount(FList); +end; + function TDOMNodeListCursor.GetCurrent(): IDefaultItemType; begin Result := FCurrent; @@ -287,6 +295,11 @@ begin Result := TDOMNodeRttiExposerCursor.Create(baseClone as IDefaultTypedCursor) ; end; +function TDOMNodeRttiExposerCursor.GetCount() : PtrInt; +begin + Result := FBaseCursor.GetCount(); +end; + function TDOMNodeRttiExposerCursor.GetCurrent(): TObject; begin FCurrentExposer.InnerObject := FBaseCursor.GetCurrent() as TDOMNode; @@ -328,6 +341,11 @@ begin Result := TDOMNamedNodeMapCursor.Create(FList,faNone); end; +function TDOMNamedNodeMapCursor.GetCount() : PtrInt; +begin + Result := GetNodeListCount(FList); +end; + function TDOMNamedNodeMapCursor.GetCurrent(): IDefaultItemType; begin if ( FCurrent > -1 ) and ( FCurrent < GetNodeListCount(FList) ) then diff --git a/wst/trunk/wst_rtti_filter/rtti_filters.pas b/wst/trunk/wst_rtti_filter/rtti_filters.pas index 5746cbda7..a3df11905 100644 --- a/wst/trunk/wst_rtti_filter/rtti_filters.pas +++ b/wst/trunk/wst_rtti_filter/rtti_filters.pas @@ -29,7 +29,10 @@ type TFilterConnector = ( fcNone, fcAnd, fcOr ); - TNumericFilterOperator = ( nfoEqual, nfoGreater, nfoLesser, nfoNotEqual ); + TNumericFilterOperator = ( + nfoEqual, nfoGreater, nfoLesser, nfoNotEqual, + nfoGreaterOrEqual, nfoLesserOrEqual + ); TStringFilterOperator = ( sfoEqualCaseSensitive, sfoEqualCaseInsensitive, sfoNotEqual ); TRttiFilterCreatorTarget = TPersistent; @@ -64,6 +67,13 @@ type const AValue : Integer; const AConnector : TFilterConnector ) : TRttiFilterCreator;overload; + function AddCondition( + const APropertyName : string; + const AOperator : TNumericFilterOperator; + const AEnumValue : string; + const AConnector : TFilterConnector + ) : TRttiFilterCreator;overload; + function AddCondition( const APropertyName : string; const AOperator : TStringFilterOperator; @@ -162,6 +172,17 @@ type property ComparedValue : Integer read FComparedValue; end; + { TRttiExpEnumNodeItem } + + TRttiExpEnumNodeItem = class(TRttiExpIntegerNodeItem) + public + constructor Create( + const APropInfo : PPropInfo; + const AOperation : TNumericFilterOperator; + const AComparedValue : string + ); + end; + { TRttiExpStringNodeItem } TRttiExpStringNodeItem = class(TRttiExpConcreteNodeItem) @@ -269,8 +290,15 @@ var fltrOp := sfoEqualCaseInsensitive else if ( s = tkn_NotEqual ) then fltrOp := sfoNotEqual - else + else if ( s = tkn_Inf ) then begin + MoveNext(); + if ( prsr.Token = tkn_Sup ) then + fltrOp := sfoNotEqual + else + raise ERttiFilterException.CreateFmt('Unexpected symbol : "%s".',[s]); + end else begin raise ERttiFilterException.CreateFmt('Unexpected symbol : "%s".',[s]); + end; MoveNext(); prsr.CheckToken(toString); if ( propInfo^.PropType^.Kind = tkWString ) then begin @@ -300,10 +328,62 @@ var else raise ERttiFilterException.CreateFmt('Unexpected symbol : "%s".',[s]); MoveNext(); + if ( prsr.Token = tkn_Equal ) then begin + case fltrOp of + nfoGreater : fltrOp := nfoGreaterOrEqual; + nfoLesser : fltrOp := nfoLesserOrEqual; + else + raise ERttiFilterException.CreateFmt('Unexpected symbol : "%s".',[s]); + end; + MoveNext(); + end else if ( prsr.Token = tkn_Sup ) then begin + if ( fltrOp = nfoLesser ) then + fltrOp := nfoNotEqual + else + raise ERttiFilterException.CreateFmt('Unexpected symbol : "%s".',[s]); + MoveNext(); + end; prsr.CheckToken(toInteger); AFltrCrtr.AddCondition(propName,fltrOp,prsr.TokenInt(),lastCntr); end; + procedure Handle_Enum(); + var + s : string; + fltrOp : TNumericFilterOperator; + begin + MoveNext(); + s := prsr.TokenString(); + if ( s = tkn_Equal ) then + fltrOp := nfoEqual + else if ( s = tkn_NotEqual ) then + fltrOp := nfoNotEqual + else if ( s = tkn_Inf ) then + fltrOp := nfoLesser + else if ( s = tkn_Sup ) then + fltrOp := nfoGreater + else + raise ERttiFilterException.CreateFmt('Unexpected symbol : "%s".',[s]); + MoveNext(); + if ( prsr.Token = tkn_Equal ) then begin + case fltrOp of + nfoGreater : fltrOp := nfoGreaterOrEqual; + nfoLesser : fltrOp := nfoLesserOrEqual; + else + raise ERttiFilterException.CreateFmt('Unexpected symbol : "%s".',[s]); + end; + MoveNext(); + end else if ( prsr.Token = tkn_Sup ) then begin + if ( fltrOp = nfoLesser ) then + fltrOp := nfoNotEqual + else + raise ERttiFilterException.CreateFmt('Unexpected symbol : "%s".',[s]); + MoveNext(); + end; + prsr.CheckToken(toSymbol); + AFltrCrtr.AddCondition(propName,fltrOp,prsr.TokenString(),lastCntr); + end; + var s : string; begin @@ -330,8 +410,10 @@ begin raise ERttiFilterException.CreateFmt('Invalid property : "%s"',[propName]); if ( propInfo^.PropType^.Kind in [{$IFDEF FPC}tkSString,tkAString,{$ENDIF}tkLString,tkWString] ) then Handle_String() - else if ( propInfo^.PropType^.Kind in [tkInteger,tkInt64{$IFDEF FPC},tkQWord{$ENDIF}] ) then + else if ( propInfo^.PropType^.Kind in [tkInteger,tkInt64{$IFDEF HAS_QWORD},tkQWord{$ENDIF}] ) then Handle_Integer() + else if ( propInfo^.PropType^.Kind in [tkEnumeration {$IFDEF HAS_TKBOOL},tkBool{$ENDIF}] ) then + Handle_Enum() else raise ERttiFilterException.CreateFmt('Type not handled : "%s"',[GetEnumName(TypeInfo(TTypeKind),Ord(propInfo^.PropType^.Kind))]); end; @@ -423,7 +505,7 @@ constructor TRttiExpIntegerNodeItem.Create( ); begin Assert(Assigned(APropInfo)); - if not ( APropInfo^.PropType^.Kind in [tkInteger,tkInt64{$IFDEF FPC},tkQWord{$ENDIF}] ) then + if not ( APropInfo^.PropType^.Kind in [tkInteger,tkInt64,tkEnumeration{$IFDEF HAS_QWORD},tkQWord{$ENDIF}{$IFDEF HAS_TKBOOL},tkBool{$ENDIF}] ) then raise ERttiFilterException.CreateFmt('Invalid property data type. "%s" excpeted.',['Integer']); inherited Create(APropInfo,AOperation); FComparedValue := AComparedValue; @@ -509,6 +591,7 @@ begin for i := 0 to Pred(FCurrentStack.Count) do FCurrentStack.Pop(); FRoot := nil; + FCurrent := nil; end; function TRttiFilterCreator.AddCondition( @@ -525,6 +608,20 @@ begin Result := Self; end; +function TRttiFilterCreator.AddCondition( + const APropertyName : string; + const AOperator : TNumericFilterOperator; + const AEnumValue : string; + const AConnector : TFilterConnector +) : TRttiFilterCreator; +begin + AddNode( + TRttiExpEnumNodeItem.Create(GetPropInfo(TargetClass,APropertyName),AOperator,AEnumValue), + AConnector + ); + Result := Self; +end; + function TRttiFilterCreator.AddCondition( const APropertyName : string; const AOperator : TStringFilterOperator; @@ -557,8 +654,8 @@ function TRttiFilterCreator.BeginGroup(const AConnector: TFilterConnector):TRtti var gn : TRttiExpNode; begin - if not Assigned(FCurrent) then - AddNode(TRttiExpNode.Create(),fcNone); + {if not Assigned(FCurrent) then + AddNode(TRttiExpNode.Create(),fcNone);} gn := TRttiExpNode.Create(); AddNode(gn,AConnector); PushCurrent(gn); @@ -667,4 +764,44 @@ begin end; end; +{ TRttiExpEnumNodeItem } + +constructor TRttiExpEnumNodeItem.Create( + const APropInfo : PPropInfo; + const AOperation : TNumericFilterOperator; + const AComparedValue : string +); +{$IFDEF HAS_TKBOOL} +var + locEnumOrder : Integer; + locBoolVal : Boolean; +begin + Assert(Assigned(APropInfo)); + if not ( APropInfo^.PropType^.Kind in [tkEnumeration,tkBool] ) then + raise ERttiFilterException.CreateFmt('Invalid property data type. "%s" excpeted.',['Enumeration']); + if ( APropInfo^.PropType^.Kind = tkBool ) then begin + if not TryStrToBool(AComparedValue,locBoolVal) then + raise ERttiFilterException.CreateFmt('Unknown boolean value : "%s", type : %s .',[AComparedValue,APropInfo^.PropType^.Name]); + locEnumOrder := Ord(locBoolVal); + end else begin + locEnumOrder := GetEnumValue(APropInfo^.PropType,AComparedValue); + if ( locEnumOrder < 0 ) then + raise ERttiFilterException.CreateFmt('Unknown enumeration value : "%s", type : %s .',[AComparedValue,APropInfo^.PropType^.Name]); + end; + inherited Create(APropInfo,AOperation,locEnumOrder); +end; +{$ELSE} +var + locEnumOrder : Integer; +begin + Assert(Assigned(APropInfo)); + if not ( APropInfo^.PropType^.Kind = tkEnumeration ) then + raise ERttiFilterException.CreateFmt('Invalid property data type. "%s" excpeted.',['Enumeration']); + locEnumOrder := GetEnumValue(APropInfo^.PropType^,AComparedValue); + if ( locEnumOrder < 0 ) then + raise ERttiFilterException.CreateFmt('Unknown enumeration value : "%s", type : %s .',[AComparedValue,APropInfo^.PropType^.Name]); + inherited Create(APropInfo,AOperation,locEnumOrder); +end; +{$ENDIF} + end. diff --git a/wst/trunk/wst_rtti_filter/std_cursors.pas b/wst/trunk/wst_rtti_filter/std_cursors.pas index 9b31d168a..fc7d6b1f9 100644 --- a/wst/trunk/wst_rtti_filter/std_cursors.pas +++ b/wst/trunk/wst_rtti_filter/std_cursors.pas @@ -1,3 +1,15 @@ +{ + This file is part of the Web Service Toolkit + Copyright (c) 2006, 2007, 2008 by Inoussa OUEDRAOGO + + This file is provide under modified LGPL licence + ( the files COPYING.modifiedLGPL and COPYING.LGPL). + + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +} {$INCLUDE wst_global.inc} unit std_cursors; @@ -22,6 +34,7 @@ type procedure Reset(); function MoveNext() : Boolean;virtual; function Clone():ICursor; + function GetCount() : PtrInt; function GetCurrent() : TObject; public constructor Create(ADataList : TObjectList); @@ -57,7 +70,12 @@ end; function TObjectListCursor.Clone(): ICursor; begin - Result := TObjectListCursor.Create(FList); + Result := TObjectListCursor.Create(FList) as ICursor; +end; + +function TObjectListCursor.GetCount() : PtrInt; +begin + Result := FList.Count; end; function TObjectListCursor.GetCurrent(): TObject; diff --git a/wst/trunk/wst_rtti_filter/wst_cursors.pas b/wst/trunk/wst_rtti_filter/wst_cursors.pas new file mode 100644 index 000000000..168e27935 --- /dev/null +++ b/wst/trunk/wst_rtti_filter/wst_cursors.pas @@ -0,0 +1,186 @@ +{ + This file is part of the Web Service Toolkit + Copyright (c) 2008 by Inoussa OUEDRAOGO + + This file is provide under modified LGPL licence + ( the files COPYING.modifiedLGPL and COPYING.LGPL). + + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +} +{$INCLUDE wst_global.inc} +unit wst_cursors; + +interface + +uses + Classes, SysUtils, + cursor_intf, base_service_intf; + +type + + { TBaseObjectArrayRemotableCursor } + + TBaseObjectArrayRemotableCursor = class(TInterfacedObject,ICursor,IObjectCursor) + private + FList : TBaseObjectArrayRemotable; + FCurrentIndex : PtrInt; + protected + procedure Reset(); + function MoveNext() : Boolean;virtual; + function Clone():ICursor; + function GetCount() : PtrInt; + function GetCurrent() : TObject; + public + constructor Create(ADataList : TBaseObjectArrayRemotable); + end; + + { TBaseObjectArrayRemotableFilterableCursor } + + TBaseObjectArrayRemotableFilterableCursor = class(TBaseObjectArrayRemotableCursor,IFilterableObjectCursor) + private + FFilter : IObjectFilter; + protected + function MoveNext() : Boolean;override; + function GetFilter() : IObjectFilter; + function SetFilter(const AFilter : IObjectFilter) : IObjectFilter; + public + destructor Destroy();override; + end; + + function Find( + const AList : TBaseObjectArrayRemotable; + const AFilter : string + ) : TBaseRemotable; + + function Filter( + const AList : TBaseObjectArrayRemotable; + const AFilter : string + ) : IFilterableObjectCursor; + +implementation +uses + imp_utils, rtti_filters; + +function Find( + const AList : TBaseObjectArrayRemotable; + const AFilter : string +) : TBaseRemotable ; +var + locRes : TBaseRemotable; + crs : IObjectCursor; + fltr : IObjectFilter; +begin + locRes := nil; + if ( AList <> nil ) and ( AList.Length > 0 ) then begin + if IsStrEmpty(AFilter) then begin + locRes := AList[0]; + end else begin + fltr := ParseFilter(AFilter,AList.GetItemClass()); + crs := CreateCursorOn(TBaseObjectArrayRemotableCursor.Create(AList),fltr); + crs.Reset(); + if crs.MoveNext() then + locRes := TBaseRemotable(crs.GetCurrent()); + end; + end; + Result := locRes; +end; + +function Filter( + const AList : TBaseObjectArrayRemotable; + const AFilter : string +) : IFilterableObjectCursor ; +var + crs : IFilterableObjectCursor; + fltr : IObjectFilter; +begin + crs := nil; + if ( AList <> nil ) then begin + if IsStrEmpty(AFilter) then begin + crs := CreateCursorOn(TBaseObjectArrayRemotableCursor.Create(AList),nil); + end else begin + fltr := ParseFilter(AFilter,AList.GetItemClass()); + crs := CreateCursorOn(TBaseObjectArrayRemotableCursor.Create(AList),fltr); + crs.Reset(); + end; + end; + Result := crs; +end; + +{ TBaseObjectArrayRemotableCursor } + +procedure TBaseObjectArrayRemotableCursor.Reset(); +begin + FCurrentIndex := -1; +end; + +function TBaseObjectArrayRemotableCursor.MoveNext() : Boolean; +begin + Inc(FCurrentIndex); + Result := ( FCurrentIndex < FList.Length ); +end; + +function TBaseObjectArrayRemotableCursor.Clone() : ICursor; +begin + Result := TBaseObjectArrayRemotableCursor.Create(FList) as ICursor; +end; + +function TBaseObjectArrayRemotableCursor.GetCount() : PtrInt; +begin + Result := FList.Length; +end; + +function TBaseObjectArrayRemotableCursor.GetCurrent() : TObject; +begin + if ( FCurrentIndex < 0 ) or ( FCurrentIndex >= FList.Length ) then + raise ECursorException.Create('Invalid cursor state.'); + Result := FList[FCurrentIndex]; +end; + +constructor TBaseObjectArrayRemotableCursor.Create(ADataList : TBaseObjectArrayRemotable); +begin + Assert(Assigned(ADataList)); + FList := ADataList; + Reset(); +end; + +{ TBaseObjectArrayRemotableFilterableCursor } + +function TBaseObjectArrayRemotableFilterableCursor.MoveNext() : Boolean; +begin + if ( FFilter = nil ) then begin + Result := inherited MoveNext(); + end else begin + while ( inherited MoveNext() ) do begin + if FFilter.Evaluate(GetCurrent()) then begin + Result := True; + Exit; + end; + end; + Result := False; + end; +end; + +function TBaseObjectArrayRemotableFilterableCursor.GetFilter() : IObjectFilter; +begin + Result := FFilter; +end; + +function TBaseObjectArrayRemotableFilterableCursor.SetFilter( + const AFilter : IObjectFilter +) : IObjectFilter; +begin + FFilter := AFilter; + Result := FFilter; +end; + +destructor TBaseObjectArrayRemotableFilterableCursor.Destroy(); +begin + FFilter := nil; + inherited Destroy(); +end; + +end. +