Add : GetCount() to cursor interface

rtti filter : enum properties handling, composed operators support ( <=, >=, <> ), tests cases
cursor implementation for wst array

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@514 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
inoussa
2008-07-28 18:45:16 +00:00
parent f67718e99c
commit bda5d8d5aa
8 changed files with 2293 additions and 7 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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.

View File

@ -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.

View File

@ -34,7 +34,9 @@ type
['{2B7756B1-E239-4B6F-A7A3-4B57B98FAD4F}'] ['{2B7756B1-E239-4B6F-A7A3-4B57B98FAD4F}']
procedure Reset(); procedure Reset();
function MoveNext() : Boolean; function MoveNext() : Boolean;
//It is just the cursor that is cloned, the underliying datas are shared
function Clone():ICursor; function Clone():ICursor;
function GetCount() : PtrInt;
end; end;
IObjectFilter = interface IObjectFilter = interface
@ -81,6 +83,7 @@ type
function MoveNext() : Boolean; function MoveNext() : Boolean;
function Clone():ICursor; function Clone():ICursor;
function GetCurrent() : TObject; function GetCurrent() : TObject;
function GetCount() : PtrInt;
function GetFilter() : IObjectFilter; function GetFilter() : IObjectFilter;
function SetFilter(const AFilter : IObjectFilter) : IObjectFilter; function SetFilter(const AFilter : IObjectFilter) : IObjectFilter;
public public
@ -136,6 +139,22 @@ begin
Result := FBaseCursor.GetCurrent(); Result := FBaseCursor.GetCurrent();
end; 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; function TSimpleObjectFilterableCursor.GetFilter(): IObjectFilter;
begin begin
Result := FFilter; Result := FFilter;

View File

@ -53,6 +53,7 @@ type
procedure Reset(); procedure Reset();
function MoveNext() : Boolean; function MoveNext() : Boolean;
function Clone():ICursor; function Clone():ICursor;
function GetCount() : PtrInt;
function GetCurrent() : IDefaultItemType;virtual; function GetCurrent() : IDefaultItemType;virtual;
public public
constructor Create( constructor Create(
@ -77,6 +78,7 @@ type
procedure Reset(); procedure Reset();
function MoveNext() : Boolean; function MoveNext() : Boolean;
function Clone():ICursor; function Clone():ICursor;
function GetCount() : PtrInt;
function GetCurrent() : IDefaultItemType; function GetCurrent() : IDefaultItemType;
public public
constructor Create( constructor Create(
@ -116,6 +118,7 @@ type
procedure Reset(); procedure Reset();
function MoveNext() : Boolean; function MoveNext() : Boolean;
function Clone():ICursor; function Clone():ICursor;
function GetCount() : PtrInt;
function GetCurrent() : TObject;virtual; function GetCurrent() : TObject;virtual;
public public
constructor Create(ADataList : IDefaultTypedCursor); constructor Create(ADataList : IDefaultTypedCursor);
@ -213,6 +216,11 @@ begin
Result := TDOMNodeListCursor.Create(FList,faNone); Result := TDOMNodeListCursor.Create(FList,faNone);
end; end;
function TDOMNodeListCursor.GetCount() : PtrInt;
begin
Result := GetNodeListCount(FList);
end;
function TDOMNodeListCursor.GetCurrent(): IDefaultItemType; function TDOMNodeListCursor.GetCurrent(): IDefaultItemType;
begin begin
Result := FCurrent; Result := FCurrent;
@ -287,6 +295,11 @@ begin
Result := TDOMNodeRttiExposerCursor.Create(baseClone as IDefaultTypedCursor) ; Result := TDOMNodeRttiExposerCursor.Create(baseClone as IDefaultTypedCursor) ;
end; end;
function TDOMNodeRttiExposerCursor.GetCount() : PtrInt;
begin
Result := FBaseCursor.GetCount();
end;
function TDOMNodeRttiExposerCursor.GetCurrent(): TObject; function TDOMNodeRttiExposerCursor.GetCurrent(): TObject;
begin begin
FCurrentExposer.InnerObject := FBaseCursor.GetCurrent() as TDOMNode; FCurrentExposer.InnerObject := FBaseCursor.GetCurrent() as TDOMNode;
@ -328,6 +341,11 @@ begin
Result := TDOMNamedNodeMapCursor.Create(FList,faNone); Result := TDOMNamedNodeMapCursor.Create(FList,faNone);
end; end;
function TDOMNamedNodeMapCursor.GetCount() : PtrInt;
begin
Result := GetNodeListCount(FList);
end;
function TDOMNamedNodeMapCursor.GetCurrent(): IDefaultItemType; function TDOMNamedNodeMapCursor.GetCurrent(): IDefaultItemType;
begin begin
if ( FCurrent > -1 ) and ( FCurrent < GetNodeListCount(FList) ) then if ( FCurrent > -1 ) and ( FCurrent < GetNodeListCount(FList) ) then

View File

@ -29,7 +29,10 @@ type
TFilterConnector = ( fcNone, fcAnd, fcOr ); TFilterConnector = ( fcNone, fcAnd, fcOr );
TNumericFilterOperator = ( nfoEqual, nfoGreater, nfoLesser, nfoNotEqual ); TNumericFilterOperator = (
nfoEqual, nfoGreater, nfoLesser, nfoNotEqual,
nfoGreaterOrEqual, nfoLesserOrEqual
);
TStringFilterOperator = ( sfoEqualCaseSensitive, sfoEqualCaseInsensitive, sfoNotEqual ); TStringFilterOperator = ( sfoEqualCaseSensitive, sfoEqualCaseInsensitive, sfoNotEqual );
TRttiFilterCreatorTarget = TPersistent; TRttiFilterCreatorTarget = TPersistent;
@ -64,6 +67,13 @@ type
const AValue : Integer; const AValue : Integer;
const AConnector : TFilterConnector const AConnector : TFilterConnector
) : TRttiFilterCreator;overload; ) : TRttiFilterCreator;overload;
function AddCondition(
const APropertyName : string;
const AOperator : TNumericFilterOperator;
const AEnumValue : string;
const AConnector : TFilterConnector
) : TRttiFilterCreator;overload;
function AddCondition( function AddCondition(
const APropertyName : string; const APropertyName : string;
const AOperator : TStringFilterOperator; const AOperator : TStringFilterOperator;
@ -162,6 +172,17 @@ type
property ComparedValue : Integer read FComparedValue; property ComparedValue : Integer read FComparedValue;
end; end;
{ TRttiExpEnumNodeItem }
TRttiExpEnumNodeItem = class(TRttiExpIntegerNodeItem)
public
constructor Create(
const APropInfo : PPropInfo;
const AOperation : TNumericFilterOperator;
const AComparedValue : string
);
end;
{ TRttiExpStringNodeItem } { TRttiExpStringNodeItem }
TRttiExpStringNodeItem = class(TRttiExpConcreteNodeItem) TRttiExpStringNodeItem = class(TRttiExpConcreteNodeItem)
@ -269,8 +290,15 @@ var
fltrOp := sfoEqualCaseInsensitive fltrOp := sfoEqualCaseInsensitive
else if ( s = tkn_NotEqual ) then else if ( s = tkn_NotEqual ) then
fltrOp := sfoNotEqual 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]); raise ERttiFilterException.CreateFmt('Unexpected symbol : "%s".',[s]);
end;
MoveNext(); MoveNext();
prsr.CheckToken(toString); prsr.CheckToken(toString);
if ( propInfo^.PropType^.Kind = tkWString ) then begin if ( propInfo^.PropType^.Kind = tkWString ) then begin
@ -300,10 +328,62 @@ var
else else
raise ERttiFilterException.CreateFmt('Unexpected symbol : "%s".',[s]); raise ERttiFilterException.CreateFmt('Unexpected symbol : "%s".',[s]);
MoveNext(); 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); prsr.CheckToken(toInteger);
AFltrCrtr.AddCondition(propName,fltrOp,prsr.TokenInt(),lastCntr); AFltrCrtr.AddCondition(propName,fltrOp,prsr.TokenInt(),lastCntr);
end; 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 var
s : string; s : string;
begin begin
@ -330,8 +410,10 @@ begin
raise ERttiFilterException.CreateFmt('Invalid property : "%s"',[propName]); raise ERttiFilterException.CreateFmt('Invalid property : "%s"',[propName]);
if ( propInfo^.PropType^.Kind in [{$IFDEF FPC}tkSString,tkAString,{$ENDIF}tkLString,tkWString] ) then if ( propInfo^.PropType^.Kind in [{$IFDEF FPC}tkSString,tkAString,{$ENDIF}tkLString,tkWString] ) then
Handle_String() 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() Handle_Integer()
else if ( propInfo^.PropType^.Kind in [tkEnumeration {$IFDEF HAS_TKBOOL},tkBool{$ENDIF}] ) then
Handle_Enum()
else else
raise ERttiFilterException.CreateFmt('Type not handled : "%s"',[GetEnumName(TypeInfo(TTypeKind),Ord(propInfo^.PropType^.Kind))]); raise ERttiFilterException.CreateFmt('Type not handled : "%s"',[GetEnumName(TypeInfo(TTypeKind),Ord(propInfo^.PropType^.Kind))]);
end; end;
@ -423,7 +505,7 @@ constructor TRttiExpIntegerNodeItem.Create(
); );
begin begin
Assert(Assigned(APropInfo)); 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']); raise ERttiFilterException.CreateFmt('Invalid property data type. "%s" excpeted.',['Integer']);
inherited Create(APropInfo,AOperation); inherited Create(APropInfo,AOperation);
FComparedValue := AComparedValue; FComparedValue := AComparedValue;
@ -509,6 +591,7 @@ begin
for i := 0 to Pred(FCurrentStack.Count) do for i := 0 to Pred(FCurrentStack.Count) do
FCurrentStack.Pop(); FCurrentStack.Pop();
FRoot := nil; FRoot := nil;
FCurrent := nil;
end; end;
function TRttiFilterCreator.AddCondition( function TRttiFilterCreator.AddCondition(
@ -525,6 +608,20 @@ begin
Result := Self; Result := Self;
end; 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( function TRttiFilterCreator.AddCondition(
const APropertyName : string; const APropertyName : string;
const AOperator : TStringFilterOperator; const AOperator : TStringFilterOperator;
@ -557,8 +654,8 @@ function TRttiFilterCreator.BeginGroup(const AConnector: TFilterConnector):TRtti
var var
gn : TRttiExpNode; gn : TRttiExpNode;
begin begin
if not Assigned(FCurrent) then {if not Assigned(FCurrent) then
AddNode(TRttiExpNode.Create(),fcNone); AddNode(TRttiExpNode.Create(),fcNone);}
gn := TRttiExpNode.Create(); gn := TRttiExpNode.Create();
AddNode(gn,AConnector); AddNode(gn,AConnector);
PushCurrent(gn); PushCurrent(gn);
@ -667,4 +764,44 @@ begin
end; end;
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. end.

View File

@ -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} {$INCLUDE wst_global.inc}
unit std_cursors; unit std_cursors;
@ -22,6 +34,7 @@ type
procedure Reset(); procedure Reset();
function MoveNext() : Boolean;virtual; function MoveNext() : Boolean;virtual;
function Clone():ICursor; function Clone():ICursor;
function GetCount() : PtrInt;
function GetCurrent() : TObject; function GetCurrent() : TObject;
public public
constructor Create(ADataList : TObjectList); constructor Create(ADataList : TObjectList);
@ -57,7 +70,12 @@ end;
function TObjectListCursor.Clone(): ICursor; function TObjectListCursor.Clone(): ICursor;
begin begin
Result := TObjectListCursor.Create(FList); Result := TObjectListCursor.Create(FList) as ICursor;
end;
function TObjectListCursor.GetCount() : PtrInt;
begin
Result := FList.Count;
end; end;
function TObjectListCursor.GetCurrent(): TObject; function TObjectListCursor.GetCurrent(): TObject;

View File

@ -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.