summaryrefslogtreecommitdiff
path: root/docview/src/docdump/iterator_intf.pas
blob: e82b59a14e1020b1bdf58646b01152583f570a2a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
unit iterator_intf;

{$mode objfpc}{$H+}

interface

uses
  Classes
  ,SysUtils
  ;

type
  { A custom exception class }
  ENoIteratorImpl = class(Exception);
  EUniDirectionalIterator = class(Exception);


  { Standard iterators }

  ITBIterator = interface(IInterface)
  ['{9C2BC10D-54C8-4B59-88B5-A564921CF0E3}']
    function    HasNext: Boolean;
    function    Next: TObject;
    function    HasPrevious: Boolean;
    function    Previous: TObject;
  end;


  ITBStringIterator = interface(IInterface)
  ['{B2A449B4-5D0A-4F14-AC11-CA055EDA3ED7}']
    function    HasNext: Boolean;
    function    Next: string;
    function    HasPrevious: Boolean;
    function    Previous: string;
  end;


  ITBStringAndObjectIterator = interface(ITBStringIterator)
  ['{287373DC-A90D-400E-BAEE-C85474C317A8}']
    function    HasNextObject: Boolean;
    function    NextObject: TObject;
    function    HasPreviousObject: Boolean;
    function    PreviousObject: TObject;
  end;


  ITBInterfaceIterator = interface
  ['{9B599C5B-4BBB-43F6-AF8E-09FEE9AE0E20}']
    function    HasNext: Boolean;
    function    Next: IInterface;
    function    HasPrevious: Boolean;
    function    Previous: IInterface;
  end;

  { TODO:
    More interfaces could be added for collections like:
    TTreeView, TStringGrid etc... }


  { Filtered iterators }

  ITBFilteredStringIterator = interface(ITBStringIterator)
  ['{CF1B9E2D-DD05-4D15-95C6-686EAFA4ED82}']
    function    GetFilter: string;
    procedure   SetFilter(const AValue: string);
    property    Filter: string read GetFilter write SetFilter;
  end;


  { TODO:
    More filtered versions of the standard iterators could
    be added here... }



  { Iterator Factory }

  TTBIteratorFactory = class(TObject)
    function    Iterator(const ASource: TObject): ITBIterator;
    function    StringIterator(const ASource: TObject): ITBStringIterator;
    function    StringAndObjectIterator(const ASource: TObject): ITBStringAndObjectIterator;
    function    InterfaceIterator(const ASource: TObject): ITBInterfaceIterator;
    function    FilteredStringIterator(const ASource: TObject; const AFilter: string): ITBFilteredStringIterator;
  end;


{ Global iterator factory singleton }
function gIteratorFactory: TTBIteratorFactory;


implementation

uses
  iterator_impl;

var
  uIteratorFactory: TTBIteratorFactory;

const
  cNoIteratorImpl = 'No Iterator implementation found for <%s>';


{ The lazy mans singleton implementation, but it does the job just fine. }
function gIteratorFactory: TTBIteratorFactory;
begin
  if not Assigned(uIteratorFactory) then
    uIteratorFactory := TTBIteratorFactory.Create;
  Result := uIteratorFactory;
end;


{ TTBIteratorFactory }

function TTBIteratorFactory.Iterator(const ASource: TObject): ITBIterator;
begin
  if ASource is TList then
    Result := TTBListIterator.CreateCustom(TList(ASource))
  else if ASource is TCollection then
    Result := TTBCollectionIterator.CreateCustom(TCollection(ASource))
  //else if ASource is TTreeNodes then
    //Result := TTBTreeNodesIterator.CreateCustom(TTreeNodes(ASource))
  else
    raise ENoIteratorImpl.CreateFmt(cNoIteratorImpl, [ASource.ClassName]);
end;

function TTBIteratorFactory.StringIterator(const ASource: TObject): ITBStringIterator;
begin
  if ASource is TStrings then
    Result := TTBStringsIterator.CreateCustom(TStrings(ASource))
  else
    raise ENoIteratorImpl.CreateFmt(cNoIteratorImpl, [ASource.ClassName]);
end;

function TTBIteratorFactory.StringAndObjectIterator(const ASource: TObject): ITBStringAndObjectIterator;
begin
  if ASource is TStrings then
    Result := TTBStringsIterator.CreateCustom(TStrings(ASource))
  else
    raise ENoIteratorImpl.CreateFmt(cNoIteratorImpl, [ASource.ClassName]);
end;

function TTBIteratorFactory.InterfaceIterator(const ASource: TObject): ITBInterfaceIterator;
begin
  if ASource is TInterfaceList then
    Result := TTBInterfaceListIterator.CreateCustom(TInterfaceList(ASource))
  else
    raise ENoIteratorImpl.CreateFmt(cNoIteratorImpl, [ASource.ClassName]);
end;

function TTBIteratorFactory.FilteredStringIterator(const ASource: TObject; const AFilter: string): ITBFilteredStringIterator;
begin
  if ASource is TStrings then
  begin
    Result := TTBFilteredStringsIterator.CreateCustom(TStrings(ASource));
    Result.Filter := AFilter;
  end
  else
    raise ENoIteratorImpl.CreateFmt(cNoIteratorImpl, [ASource.ClassName]);
end;


initialization
  uIteratorFactory := nil;

finalization
  uIteratorFactory.Free;

end.